mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-09 07:36:48 +02:00
Updated checkFinished
This commit is contained in:
@@ -36,7 +36,7 @@ ContextMenu::ContextMenu( QWidget* parent )
|
|||||||
m_sigmap = new QSignalMapper( this );
|
m_sigmap = new QSignalMapper( this );
|
||||||
connect( m_sigmap, SIGNAL( mapped( int ) ), SLOT( onTriggered( int ) ) );
|
connect( m_sigmap, SIGNAL( mapped( int ) ), SLOT( onTriggered( int ) ) );
|
||||||
|
|
||||||
m_supportedActions = ActionPlay | ActionQueue | ActionCopyLink;
|
m_supportedActions = ActionPlay | ActionQueue | ActionCopyLink | ActionAddToPlaylist | ActionAddTrackToPl;
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextMenu::~ContextMenu()
|
ContextMenu::~ContextMenu()
|
||||||
@@ -50,6 +50,7 @@ ContextMenu::clear()
|
|||||||
m_queries.clear();
|
m_queries.clear();
|
||||||
m_albums.clear();
|
m_albums.clear();
|
||||||
m_artists.clear();
|
m_artists.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
@@ -61,9 +62,11 @@ ContextMenu::itemCount() const
|
|||||||
void
|
void
|
||||||
ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( queries.isEmpty() )
|
if ( queries.isEmpty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
QMenu::clear();
|
QMenu::clear();
|
||||||
m_queries.clear();
|
m_queries.clear();
|
||||||
m_queries << queries;
|
m_queries << queries;
|
||||||
@@ -74,7 +77,24 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
|||||||
if ( m_supportedActions & ActionQueue )
|
if ( m_supportedActions & ActionQueue )
|
||||||
m_sigmap->setMapping( addAction( tr( "Add to &Queue" ) ), ActionQueue );
|
m_sigmap->setMapping( addAction( tr( "Add to &Queue" ) ), ActionQueue );
|
||||||
|
|
||||||
//m_sigmap->setMapping( addAction( tr( "&Add to Playlist" ) ), ActionAddToPlaylist );
|
|
||||||
|
|
||||||
|
if ( m_supportedActions & ActionAddToPlaylist ){
|
||||||
|
|
||||||
|
QList<playlist_ptr> p = SourceList::instance()->getLocal()->collection()->playlists();
|
||||||
|
QMenu *addTo = new QMenu("Add to");
|
||||||
|
for(int i = 0; i< p.count(); i++){
|
||||||
|
m_sigmap->setMapping( addTo->addAction( p[i]->title() ), p[i]->guid() );
|
||||||
|
m_sigmap->setMapping( addMenu( addTo ), ActionAddToPlaylist );
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( QAction* action, addTo->actions() )
|
||||||
|
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
|
||||||
|
|
||||||
|
connect(m_sigmap, SIGNAL(mapped(QString)),
|
||||||
|
this, SLOT(onAction(QString)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
addSeparator();
|
addSeparator();
|
||||||
|
|
||||||
@@ -86,8 +106,11 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
|||||||
if ( m_supportedActions & ActionDelete )
|
if ( m_supportedActions & ActionDelete )
|
||||||
m_sigmap->setMapping( addAction( queries.count() > 1 ? tr( "&Delete Items" ) : tr( "&Delete Item" ) ), ActionDelete );
|
m_sigmap->setMapping( addAction( queries.count() > 1 ? tr( "&Delete Items" ) : tr( "&Delete Item" ) ), ActionDelete );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
foreach ( QAction* action, actions() )
|
foreach ( QAction* action, actions() )
|
||||||
{
|
{
|
||||||
|
|
||||||
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
|
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,12 +119,14 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
|||||||
void
|
void
|
||||||
ContextMenu::setQuery( const Tomahawk::query_ptr& query )
|
ContextMenu::setQuery( const Tomahawk::query_ptr& query )
|
||||||
{
|
{
|
||||||
|
|
||||||
QList<query_ptr> queries;
|
QList<query_ptr> queries;
|
||||||
queries << query;
|
queries << query;
|
||||||
setQueries( queries );
|
setQueries( queries );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ContextMenu::setAlbums( const QList<Tomahawk::album_ptr>& albums )
|
ContextMenu::setAlbums( const QList<Tomahawk::album_ptr>& albums )
|
||||||
{
|
{
|
||||||
@@ -180,6 +205,21 @@ ContextMenu::setArtist( const Tomahawk::artist_ptr& artist )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ContextMenu::onClicked( int action )
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << "Action:" << action;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ContextMenu::onAction( const QString& what )
|
||||||
|
{
|
||||||
|
playlist_ptr p = SourceList::instance()->getLocal()->collection()->playlist( what );
|
||||||
|
p->addEntries( m_queries, p->currentrevision());
|
||||||
|
qDebug() << Q_FUNC_INFO << "Adding track to guid" << what << "With title" << p->title();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ContextMenu::onTriggered( int action )
|
ContextMenu::onTriggered( int action )
|
||||||
{
|
{
|
||||||
@@ -199,6 +239,7 @@ ContextMenu::onTriggered( int action )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ContextMenu::addToQueue()
|
void ContextMenu::addToQueue()
|
||||||
{
|
{
|
||||||
foreach ( const query_ptr& query, m_queries )
|
foreach ( const query_ptr& query, m_queries )
|
||||||
@@ -221,6 +262,7 @@ void ContextMenu::addToQueue()
|
|||||||
void
|
void
|
||||||
ContextMenu::copyLink()
|
ContextMenu::copyLink()
|
||||||
{
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
if ( m_queries.count() )
|
if ( m_queries.count() )
|
||||||
{
|
{
|
||||||
GlobalActionManager::instance()->copyToClipboard( m_queries.first() );
|
GlobalActionManager::instance()->copyToClipboard( m_queries.first() );
|
||||||
|
@@ -34,7 +34,14 @@ Q_OBJECT
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
enum MenuActions
|
enum MenuActions
|
||||||
{ ActionPlay = 1, ActionQueue = 2, ActionDelete = 4, ActionCopyLink = 8 };
|
{
|
||||||
|
ActionPlay = 1,
|
||||||
|
ActionQueue = 2,
|
||||||
|
ActionDelete = 4,
|
||||||
|
ActionCopyLink = 8,
|
||||||
|
ActionAddToPlaylist = 9,
|
||||||
|
ActionAddTrackToPl = 5
|
||||||
|
};
|
||||||
|
|
||||||
explicit ContextMenu( QWidget* parent = 0 );
|
explicit ContextMenu( QWidget* parent = 0 );
|
||||||
virtual ~ContextMenu();
|
virtual ~ContextMenu();
|
||||||
@@ -57,19 +64,21 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void triggered( int action );
|
void triggered( int action );
|
||||||
|
void clicked( int action );
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onTriggered( int action );
|
void onTriggered( int action );
|
||||||
|
void onClicked( int action );
|
||||||
void copyLink();
|
void copyLink();
|
||||||
void addToQueue();
|
void addToQueue();
|
||||||
|
void onAction(const QString& what);
|
||||||
private:
|
private:
|
||||||
QSignalMapper* m_sigmap;
|
QSignalMapper* m_sigmap;
|
||||||
int m_supportedActions;
|
int m_supportedActions;
|
||||||
|
|
||||||
QList<Tomahawk::query_ptr> m_queries;
|
QList<Tomahawk::query_ptr> m_queries;
|
||||||
QList<Tomahawk::artist_ptr> m_artists;
|
QList<Tomahawk::artist_ptr> m_artists;
|
||||||
|
playlist_ptr m_playlist;
|
||||||
QList<Tomahawk::album_ptr> m_albums;
|
QList<Tomahawk::album_ptr> m_albums;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "globalactionmanager.h"
|
#include "globalactionmanager.h"
|
||||||
#include "infosystem/infosystem.h"
|
#include "infosystem/infosystem.h"
|
||||||
|
#include "utils/xspfloader.h"
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
DropJob::DropJob( QObject *parent )
|
DropJob::DropJob( QObject *parent )
|
||||||
@@ -60,10 +60,40 @@ DropJob::mimeTypes()
|
|||||||
return mimeTypes;
|
return mimeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DropJob::DropAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( dropAction() == DropJob::Create )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DropJob::acceptsMimeData( const QMimeData* data, bool tracksOnly )
|
DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType, DropJob::DropActions acceptedAction)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if (acceptedType.testFlag(DropJob::None))
|
||||||
|
qDebug() << Q_FUNC_INFO << "AcceptedType is None";
|
||||||
|
|
||||||
|
if (acceptedType.testFlag(DropJob::All))
|
||||||
|
qDebug() << Q_FUNC_INFO << "AcceptedType is All";
|
||||||
|
|
||||||
|
if (acceptedType.testFlag(DropJob::Playlist))
|
||||||
|
qDebug() << Q_FUNC_INFO << "AcceptedType is Playlist";
|
||||||
|
|
||||||
|
if (acceptedType.testFlag(DropJob::Track))
|
||||||
|
qDebug() << Q_FUNC_INFO << "AcceptedType is Track";
|
||||||
|
|
||||||
|
if (acceptedAction.testFlag(DropJob::Append))
|
||||||
|
qDebug() << Q_FUNC_INFO << "AcceptedAction is Append";
|
||||||
|
|
||||||
|
if (acceptedAction.testFlag(DropJob::Create))
|
||||||
|
qDebug() << Q_FUNC_INFO << "AcceptedAction is Create";
|
||||||
|
|
||||||
if ( data->hasFormat( "application/tomahawk.query.list" )
|
if ( data->hasFormat( "application/tomahawk.query.list" )
|
||||||
|| data->hasFormat( "application/tomahawk.plentry.list" )
|
|| data->hasFormat( "application/tomahawk.plentry.list" )
|
||||||
|| data->hasFormat( "application/tomahawk.result.list" )
|
|| data->hasFormat( "application/tomahawk.result.list" )
|
||||||
@@ -75,22 +105,42 @@ DropJob::acceptsMimeData( const QMimeData* data, bool tracksOnly )
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( data->hasFormat( "text/plain" )
|
||||||
|
&& data->data( "text/plain" ).contains( "xspf" )
|
||||||
|
&& ( acceptedType.testFlag(DropJob::Playlist) || acceptedType.testFlag(DropJob::All) )
|
||||||
|
&& acceptedAction.testFlag(DropJob::Create)
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
|
||||||
// crude check for spotify tracks
|
// crude check for spotify tracks
|
||||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" ) &&
|
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" )
|
||||||
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
|
&& data->data( "text/plain" ).contains( "playlist" )
|
||||||
|
&& ( acceptedType.testFlag(DropJob::Playlist) || acceptedType.testFlag(DropJob::All) )
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// crude check for spotify tracks
|
||||||
|
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" )
|
||||||
|
&& data->data( "text/plain" ).contains( "track" )
|
||||||
|
&& ( acceptedType.testFlag(DropJob::Track) || acceptedType.testFlag(DropJob::All) )
|
||||||
|
)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// crude check for rdio tracks
|
// crude check for rdio tracks
|
||||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rdio.com" ) &&
|
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rdio.com" )
|
||||||
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
|
&& data->data( "text/plain" ).contains( "track" )
|
||||||
|
&& ( acceptedType.testFlag(DropJob::Track) || acceptedType.testFlag(DropJob::All) )
|
||||||
|
)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
||||||
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them,
|
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them,
|
||||||
// so we do an extra level of lookup
|
// so we do an extra level of lookup
|
||||||
if ( ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "bit.ly" ) ) ||
|
if ( ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "bit.ly" ) ) ||
|
||||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "j.mp" ) ) ||
|
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "j.mp" ) ) ||
|
||||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "t.co" ) ) ||
|
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "t.co" ) ) ||
|
||||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rd.io" ) ) )
|
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rd.io" ) )
|
||||||
|
&& ( acceptedType.testFlag(DropJob::Track) || acceptedType.testFlag(DropJob::All) ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -134,6 +184,26 @@ DropJob::tracksFromMimeData( const QMimeData* data, bool allowDuplicates, bool o
|
|||||||
void
|
void
|
||||||
DropJob::parseMimeData( const QMimeData *data )
|
DropJob::parseMimeData( const QMimeData *data )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if(dropTypes() & DropJob::Playlist)
|
||||||
|
qDebug() << Q_FUNC_INFO << "DropType is Playlist";
|
||||||
|
if(dropTypes() & DropJob::All)
|
||||||
|
qDebug() << Q_FUNC_INFO << "DropType is All";
|
||||||
|
if(dropTypes() & DropJob::Track)
|
||||||
|
qDebug() << Q_FUNC_INFO << "DropType is Track";
|
||||||
|
if(dropTypes() & DropJob::Artist)
|
||||||
|
qDebug() << Q_FUNC_INFO << "DropType is Artist";
|
||||||
|
if(DropTypes() & DropJob::None)
|
||||||
|
qDebug() << Q_FUNC_INFO << "DropType is None";
|
||||||
|
else qDebug() << "DropType is I DONT KNOW!";
|
||||||
|
|
||||||
|
if(dropAction() == DropJob::Append)
|
||||||
|
qDebug() << Q_FUNC_INFO << "DropAction is Append";
|
||||||
|
if(dropAction() == DropJob::Create)
|
||||||
|
qDebug() << Q_FUNC_INFO << "DropAction is Create";
|
||||||
|
|
||||||
|
|
||||||
QList< query_ptr > results;
|
QList< query_ptr > results;
|
||||||
if ( data->hasFormat( "application/tomahawk.query.list" ) )
|
if ( data->hasFormat( "application/tomahawk.query.list" ) )
|
||||||
results = tracksFromQueryList( data );
|
results = tracksFromQueryList( data );
|
||||||
@@ -148,7 +218,13 @@ DropJob::parseMimeData( const QMimeData *data )
|
|||||||
else if ( data->hasFormat( "text/plain" ) )
|
else if ( data->hasFormat( "text/plain" ) )
|
||||||
{
|
{
|
||||||
QString plainData = QString::fromUtf8( data->data( "text/plain" ).constData() );
|
QString plainData = QString::fromUtf8( data->data( "text/plain" ).constData() );
|
||||||
tDebug() << "Got text/plain mime data:" << data->data( "text/plain" ) << "decoded to:" << plainData;
|
qDebug() << Q_FUNC_INFO << "Got text/plain mime data:" << data->data( "text/plain" ) << "decoded to:" << plainData.trimmed();
|
||||||
|
|
||||||
|
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "xspf" ) )
|
||||||
|
handleXspf( data->data( "text/plain" ).trimmed(), DropAction() );
|
||||||
|
else if ( plainData.contains( "spotify" ) && plainData.contains( "playlist" ) )
|
||||||
|
handleSpPlaylist( plainData, DropAction() );
|
||||||
|
else
|
||||||
handleTrackUrls ( plainData );
|
handleTrackUrls ( plainData );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,13 +407,72 @@ DropJob::tracksFromMixedData( const QMimeData *data )
|
|||||||
return queries;
|
return queries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DropJob::handleXspf( const QString& fileUrl, bool createNewPlaylist )
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << "Got xspf playlist!!" << fileUrl;
|
||||||
|
|
||||||
|
// Doing like so on *nix, dont know really how files are
|
||||||
|
// passed on others.
|
||||||
|
qDebug() << "Got xspf playlist!!";
|
||||||
|
QString newFile = fileUrl;
|
||||||
|
newFile.replace("file://", "");
|
||||||
|
QFile xspfFile(newFile);
|
||||||
|
XSPFLoader* l = new XSPFLoader( createNewPlaylist, this );
|
||||||
|
tDebug( LOGINFO ) << "Loading local xspf:" << newFile;
|
||||||
|
l->load( xspfFile );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DropJob::handleSpPlaylist( const QString& url, bool createNewPlaylist)
|
||||||
|
{
|
||||||
|
|
||||||
|
qDebug() << "Got spotify playlist!!" << url;
|
||||||
|
|
||||||
|
if ( url.contains( "open.spotify.com/user") ||
|
||||||
|
url.contains( "spotify:user" ) )
|
||||||
|
{
|
||||||
|
// Lets create a valid playlist uri
|
||||||
|
QString playlistUri = url;
|
||||||
|
QString validUri;
|
||||||
|
|
||||||
|
if(url.contains( "open.spotify.com/user")){
|
||||||
|
playlistUri.replace("http://open.spotify.com/", "");
|
||||||
|
QStringList playlist = playlistUri.split( "/" );
|
||||||
|
validUri = "spotify:" + playlist.join(":");
|
||||||
|
}else validUri = playlistUri;
|
||||||
|
|
||||||
|
tDebug() << "Got a spotify playlist in dropjob!" << validUri;
|
||||||
|
SpotifyParser* spot = new SpotifyParser( validUri, this, createNewPlaylist);
|
||||||
|
|
||||||
|
//This currently supports draging and dropping a spotify playlist
|
||||||
|
if(createNewPlaylist){
|
||||||
|
qDebug() << Q_FUNC_INFO << "Got spotify playlist!! Create new" << url;
|
||||||
|
}else{
|
||||||
|
qDebug() << Q_FUNC_INFO << "Got spotify playlist!!" << url;
|
||||||
|
connect( spot, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_queryCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DropJob::handleTrackUrls( const QString& urls )
|
DropJob::handleTrackUrls( const QString& urls )
|
||||||
{
|
{
|
||||||
if ( urls.contains( "open.spotify.com/track") ||
|
qDebug() << Q_FUNC_INFO << urls;
|
||||||
|
|
||||||
|
|
||||||
|
if ( urls.contains( "open.spotify.com/user") ||
|
||||||
|
urls.contains( "spotify:user" ) )
|
||||||
|
handleSpPlaylist( urls, dropAction() );
|
||||||
|
|
||||||
|
else if ( urls.contains( "open.spotify.com/track") ||
|
||||||
urls.contains( "spotify:track" ) )
|
urls.contains( "spotify:track" ) )
|
||||||
{
|
{
|
||||||
QStringList tracks = urls.split( "\n" );
|
QStringList tracks = urls.split(QRegExp("\\s+"), QString::SkipEmptyParts);
|
||||||
|
|
||||||
tDebug() << "Got a list of spotify urls!" << tracks;
|
tDebug() << "Got a list of spotify urls!" << tracks;
|
||||||
SpotifyParser* spot = new SpotifyParser( tracks, this );
|
SpotifyParser* spot = new SpotifyParser( tracks, this );
|
||||||
@@ -367,7 +502,6 @@ DropJob::handleTrackUrls( const QString& urls )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DropJob::expandedUrls( QStringList urls )
|
DropJob::expandedUrls( QStringList urls )
|
||||||
{
|
{
|
||||||
|
@@ -43,12 +43,41 @@ public:
|
|||||||
*
|
*
|
||||||
* Connect to tracks( QList< query_ptr> ); for the extracted tracks.
|
* Connect to tracks( QList< query_ptr> ); for the extracted tracks.
|
||||||
*/
|
*/
|
||||||
static bool acceptsMimeData( const QMimeData* data, bool tracksOnly = true );
|
|
||||||
|
enum DropType {
|
||||||
|
|
||||||
|
None = 0x00,
|
||||||
|
Playlist = 0x01,
|
||||||
|
Track = 0x02,
|
||||||
|
Album = 0x04,
|
||||||
|
Artist = 0x08,
|
||||||
|
All = 0x10
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_FLAGS(DropTypes, DropType)
|
||||||
|
|
||||||
|
enum DropAction {
|
||||||
|
|
||||||
|
Append = 0x0,
|
||||||
|
Create = 0x1
|
||||||
|
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(DropActions, DropAction)
|
||||||
|
|
||||||
|
|
||||||
|
static bool acceptsMimeData( const QMimeData* data, DropJob::DropTypes type = All, DropJob::DropActions action = Append );
|
||||||
static QStringList mimeTypes();
|
static QStringList mimeTypes();
|
||||||
|
|
||||||
|
virtual void setDropTypes( DropTypes types ) { m_dropTypes = types; }
|
||||||
|
virtual void setDropAction( DropAction action ) { m_dropAction = action; }
|
||||||
|
virtual DropTypes dropTypes() const { return m_dropTypes; }
|
||||||
|
virtual DropAction dropAction() const { return m_dropAction; }
|
||||||
|
void parseMimeData( const QMimeData* data );
|
||||||
void setGetWholeArtists( bool getWholeArtists );
|
void setGetWholeArtists( bool getWholeArtists );
|
||||||
void setGetWholeAlbums( bool getWholeAlbums );
|
void setGetWholeAlbums( bool getWholeAlbums );
|
||||||
void tracksFromMimeData( const QMimeData* data, bool allowDuplicates = false, bool onlyLocal = false, bool top10 = false );
|
void tracksFromMimeData( const QMimeData* data, bool allowDuplicates = false, bool onlyLocal = false, bool top10 = false );
|
||||||
|
void handleXspf( const QString& file, bool createNewPlaylist = false );
|
||||||
|
void handleSpPlaylist( const QString& url, bool createNewPlaylist = false );
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/// QMimeData parsing results
|
/// QMimeData parsing results
|
||||||
@@ -63,7 +92,7 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
/// handle parsing mime data
|
/// handle parsing mime data
|
||||||
void parseMimeData( const QMimeData* data );
|
|
||||||
|
|
||||||
void handleTrackUrls( const QString& urls );
|
void handleTrackUrls( const QString& urls );
|
||||||
QList< Tomahawk::query_ptr > tracksFromQueryList( const QMimeData* d );
|
QList< Tomahawk::query_ptr > tracksFromQueryList( const QMimeData* d );
|
||||||
@@ -86,8 +115,11 @@ private:
|
|||||||
bool m_getWholeArtists;
|
bool m_getWholeArtists;
|
||||||
bool m_getWholeAlbums;
|
bool m_getWholeAlbums;
|
||||||
bool m_top10;
|
bool m_top10;
|
||||||
|
DropTypes m_dropTypes;
|
||||||
|
DropAction m_dropAction;
|
||||||
|
bool DropAction();
|
||||||
|
|
||||||
QList< Tomahawk::query_ptr > m_resultList;
|
QList< Tomahawk::query_ptr > m_resultList;
|
||||||
};
|
};
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(DropJob::DropTypes)
|
||||||
#endif // DROPJOB_H
|
#endif // DROPJOB_H
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "utils/tomahawkutils.h"
|
#include "utils/tomahawkutils.h"
|
||||||
#include "query.h"
|
#include "query.h"
|
||||||
|
#include "sourcelist.h"
|
||||||
#include <qjson/parser.h>
|
#include <qjson/parser.h>
|
||||||
|
|
||||||
#include <QtNetwork/QNetworkAccessManager>
|
#include <QtNetwork/QNetworkAccessManager>
|
||||||
@@ -29,19 +29,22 @@
|
|||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
SpotifyParser::SpotifyParser( const QStringList& trackUrls, QObject* parent )
|
SpotifyParser::SpotifyParser( const QStringList& Urls, QObject* parent, bool createNewPlaylist)
|
||||||
: QObject ( parent )
|
: QObject ( parent )
|
||||||
, m_single( false )
|
, m_single( false )
|
||||||
|
|
||||||
{
|
{
|
||||||
foreach ( const QString& url, trackUrls )
|
m_createNewPlaylist = createNewPlaylist;
|
||||||
lookupTrack( url );
|
foreach ( const QString& url, Urls )
|
||||||
|
lookupUrl( url );
|
||||||
}
|
}
|
||||||
|
|
||||||
SpotifyParser::SpotifyParser( const QString& trackUrl, QObject* parent )
|
SpotifyParser::SpotifyParser( const QString& Url, QObject* parent, bool createNewPlaylist )
|
||||||
: QObject ( parent )
|
: QObject ( parent )
|
||||||
, m_single( true )
|
, m_single( true )
|
||||||
{
|
{
|
||||||
lookupTrack( trackUrl );
|
m_createNewPlaylist = createNewPlaylist;
|
||||||
|
lookupUrl( Url );
|
||||||
}
|
}
|
||||||
|
|
||||||
SpotifyParser::~SpotifyParser()
|
SpotifyParser::~SpotifyParser()
|
||||||
@@ -49,9 +52,42 @@ SpotifyParser::~SpotifyParser()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SpotifyParser::lookupUrl( const QString& link )
|
||||||
|
{
|
||||||
|
|
||||||
|
if( link.contains( "track" ) )
|
||||||
|
lookupTrack(link);
|
||||||
|
else if( link.contains( "playlist" ) )
|
||||||
|
lookupPlaylist( link );
|
||||||
|
else return; // We only support tracks and playlists
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SpotifyParser::lookupPlaylist( const QString& link )
|
||||||
|
{
|
||||||
|
if ( !link.contains( "spotify:user:" ) ) // we only support playlist here
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString uri = link;
|
||||||
|
tLog() << "Parsing Spotify Playlist URI:" << uri;
|
||||||
|
QUrl url = QUrl( QString( "http://www.trushuffle.com:5512/playlist/%1" ).arg( uri ) );
|
||||||
|
tDebug() << "Looking up URL..." << url.toString();
|
||||||
|
|
||||||
|
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
|
||||||
|
connect( reply, SIGNAL( finished() ), this, SLOT( spotifyPlaylistLookupFinished() ) );
|
||||||
|
|
||||||
|
m_queries.insert( reply );
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SpotifyParser::lookupTrack( const QString& link )
|
SpotifyParser::lookupTrack( const QString& link )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
tDebug() << "Got a QString " << link;
|
||||||
if ( !link.contains( "track" )) // we only support track links atm
|
if ( !link.contains( "track" )) // we only support track links atm
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -76,6 +112,60 @@ SpotifyParser::lookupTrack( const QString& link )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SpotifyParser::spotifyPlaylistLookupFinished()
|
||||||
|
{
|
||||||
|
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
|
||||||
|
Q_ASSERT( r );
|
||||||
|
m_queries.remove( r );
|
||||||
|
r->deleteLater();
|
||||||
|
|
||||||
|
if ( r->error() == QNetworkReply::NoError )
|
||||||
|
{
|
||||||
|
QJson::Parser p;
|
||||||
|
bool ok;
|
||||||
|
QVariantMap res = p.parse( r, &ok ).toMap();
|
||||||
|
|
||||||
|
if ( !ok )
|
||||||
|
{
|
||||||
|
tLog() << "Failed to parse json from Spotify playlist lookup:" << p.errorString() << "On line" << p.errorLine();
|
||||||
|
checkTrackFinished();
|
||||||
|
return;
|
||||||
|
} else if ( !res.contains( "tracks" ) )
|
||||||
|
{
|
||||||
|
tLog() << "No 'tracks' item in the spotify playlist lookup result... not doing anything";
|
||||||
|
checkTrackFinished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList trackResponse = res.value( "tracks" ).toList();
|
||||||
|
if(!trackResponse.isEmpty()){
|
||||||
|
m_title = res.value( "title" ).toString();
|
||||||
|
m_creator = res.value( "creator" ).toString();
|
||||||
|
qDebug() << "playlist owner: " << m_creator;
|
||||||
|
}
|
||||||
|
foreach(QVariant track, trackResponse){
|
||||||
|
|
||||||
|
QString title, artist, album;
|
||||||
|
title = track.toMap().value( "title" ).toString();
|
||||||
|
artist = track.toMap().value( "artists" ).toList().first().toString();
|
||||||
|
album = track.toMap().value( "album" ).toString();
|
||||||
|
Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album, uuid(), true );
|
||||||
|
m_tracks << q;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
tLog() << "Error in network request to Spotify for track decoding:" << r->errorString();
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPlaylistFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SpotifyParser::spotifyTrackLookupFinished()
|
SpotifyParser::spotifyTrackLookupFinished()
|
||||||
{
|
{
|
||||||
@@ -93,12 +183,12 @@ SpotifyParser::spotifyTrackLookupFinished()
|
|||||||
if ( !ok )
|
if ( !ok )
|
||||||
{
|
{
|
||||||
tLog() << "Failed to parse json from Spotify track lookup:" << p.errorString() << "On line" << p.errorLine();
|
tLog() << "Failed to parse json from Spotify track lookup:" << p.errorString() << "On line" << p.errorLine();
|
||||||
checkFinished();
|
checkTrackFinished();
|
||||||
return;
|
return;
|
||||||
} else if ( !res.contains( "track" ) )
|
} else if ( !res.contains( "track" ) )
|
||||||
{
|
{
|
||||||
tLog() << "No 'track' item in the spotify track lookup result... not doing anything";
|
tLog() << "No 'track' item in the spotify track lookup result... not doing anything";
|
||||||
checkFinished();
|
checkTrackFinished();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,11 +218,33 @@ SpotifyParser::spotifyTrackLookupFinished()
|
|||||||
tLog() << "Error in network request to Spotify for track decoding:" << r->errorString();
|
tLog() << "Error in network request to Spotify for track decoding:" << r->errorString();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFinished();
|
checkTrackFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SpotifyParser::checkFinished()
|
SpotifyParser::checkPlaylistFinished()
|
||||||
|
{
|
||||||
|
if ( m_queries.isEmpty() ) // we're done
|
||||||
|
{
|
||||||
|
if(m_createNewPlaylist)
|
||||||
|
m_playlist = Playlist::create( SourceList::instance()->getLocal(),
|
||||||
|
uuid(),
|
||||||
|
m_title,
|
||||||
|
m_info,
|
||||||
|
m_creator,
|
||||||
|
false,
|
||||||
|
m_tracks );
|
||||||
|
|
||||||
|
else if ( !m_tracks.isEmpty() && !m_createNewPlaylist)
|
||||||
|
emit tracks( m_tracks );
|
||||||
|
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SpotifyParser::checkTrackFinished()
|
||||||
{
|
{
|
||||||
if ( m_queries.isEmpty() ) // we're done
|
if ( m_queries.isEmpty() ) // we're done
|
||||||
{
|
{
|
||||||
|
@@ -40,24 +40,31 @@ class DLLEXPORT SpotifyParser : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit SpotifyParser( const QString& trackUrl, QObject* parent = 0 );
|
explicit SpotifyParser( const QString& trackUrl, QObject* parent = 0, bool createNewPl = false );
|
||||||
explicit SpotifyParser( const QStringList& trackUrls, QObject* parent = 0 );
|
explicit SpotifyParser( const QStringList& trackUrls, QObject* parent = 0, bool createNewPl = false);
|
||||||
virtual ~SpotifyParser();
|
virtual ~SpotifyParser();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void track( const Tomahawk::query_ptr& track );
|
void track( const Tomahawk::query_ptr& track );
|
||||||
void tracks( const QList< Tomahawk::query_ptr > tracks );
|
void tracks( const QList< Tomahawk::query_ptr > tracks );
|
||||||
|
void playlist( const Tomahawk::query_ptr& playlist );
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void spotifyTrackLookupFinished();
|
void spotifyTrackLookupFinished();
|
||||||
|
void spotifyPlaylistLookupFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void lookupUrl( const QString& url );
|
||||||
void lookupTrack( const QString& track );
|
void lookupTrack( const QString& track );
|
||||||
void checkFinished();
|
void lookupPlaylist( const QString& playlist );
|
||||||
|
void checkTrackFinished();
|
||||||
|
void checkPlaylistFinished();
|
||||||
bool m_single;
|
bool m_single;
|
||||||
|
bool m_createNewPlaylist;
|
||||||
QList< query_ptr > m_tracks;
|
QList< query_ptr > m_tracks;
|
||||||
QSet< QNetworkReply* > m_queries;
|
QSet< QNetworkReply* > m_queries;
|
||||||
|
QString m_title, m_info, m_creator;
|
||||||
|
Tomahawk::playlist_ptr m_playlist;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -426,15 +426,15 @@ SourceTreeView::dragEnterEvent( QDragEnterEvent* event )
|
|||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
QTreeView::dragEnterEvent( event );
|
QTreeView::dragEnterEvent( event );
|
||||||
|
|
||||||
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
if ( DropJob::acceptsMimeData( event->mimeData(), DropJob::Track | DropJob::Playlist, DropJob::Create ) )
|
||||||
{
|
{
|
||||||
m_dragging = true;
|
m_dragging = true;
|
||||||
m_dropRect = QRect();
|
m_dropRect = QRect();
|
||||||
m_dropIndex = QPersistentModelIndex();
|
m_dropIndex = QPersistentModelIndex();
|
||||||
|
|
||||||
qDebug() << "Accepting Drag Event";
|
qDebug() << Q_FUNC_INFO << "Accepting Drag Event";
|
||||||
event->setDropAction( Qt::CopyAction );
|
event->setDropAction( Qt::CopyAction );
|
||||||
event->accept();
|
event->acceptProposedAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,7 +459,7 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event )
|
|||||||
bool accept = false;
|
bool accept = false;
|
||||||
QTreeView::dragMoveEvent( event );
|
QTreeView::dragMoveEvent( event );
|
||||||
|
|
||||||
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
if ( DropJob::acceptsMimeData( event->mimeData(), DropJob::Track, DropJob::Append ) )
|
||||||
{
|
{
|
||||||
setDirtyRegion( m_dropRect );
|
setDirtyRegion( m_dropRect );
|
||||||
const QPoint pos = event->pos();
|
const QPoint pos = event->pos();
|
||||||
@@ -475,6 +475,7 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event )
|
|||||||
SourceTreeItem* item = itemFromIndex< SourceTreeItem >( index );
|
SourceTreeItem* item = itemFromIndex< SourceTreeItem >( index );
|
||||||
if( item->willAcceptDrag( event->mimeData() ) )
|
if( item->willAcceptDrag( event->mimeData() ) )
|
||||||
{
|
{
|
||||||
|
|
||||||
accept = true;
|
accept = true;
|
||||||
m_delegate->hovered( index, event->mimeData() );
|
m_delegate->hovered( index, event->mimeData() );
|
||||||
dataChanged(index, index);
|
dataChanged(index, index);
|
||||||
@@ -489,14 +490,24 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event )
|
|||||||
|
|
||||||
if ( accept )
|
if ( accept )
|
||||||
{
|
{
|
||||||
|
//qDebug() << Q_FUNC_INFO << "Accepting";
|
||||||
event->setDropAction( Qt::CopyAction );
|
event->setDropAction( Qt::CopyAction );
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
else
|
else{
|
||||||
event->ignore();
|
|
||||||
|
|
||||||
setDirtyRegion( m_dropRect );
|
qDebug() << Q_FUNC_INFO << "Ignoring";
|
||||||
|
event->ignore();
|
||||||
}
|
}
|
||||||
|
}else if ( DropJob::acceptsMimeData( event->mimeData(), DropJob::Playlist, DropJob::Create ) )
|
||||||
|
|
||||||
|
{
|
||||||
|
// Should maybe ignore, but we are just dropping
|
||||||
|
// a playlist in the container, not on a specific playlist
|
||||||
|
event->setDropAction( Qt::CopyAction );
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
setDirtyRegion( m_dropRect );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -513,18 +524,25 @@ SourceTreeView::dropEvent( QDropEvent* event )
|
|||||||
Q_ASSERT( item );
|
Q_ASSERT( item );
|
||||||
|
|
||||||
item->setDropType( m_delegate->hoveredDropType() );
|
item->setDropType( m_delegate->hoveredDropType() );
|
||||||
qDebug() << "dropType is " << m_delegate->hoveredDropType();
|
qDebug() << Q_FUNC_INFO << "dropType is " << m_delegate->hoveredDropType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to fake the dropevent because the treeview would reject it if it is outside the item (on the tree)
|
// Need to fake the dropevent because the treeview would reject it if it is outside the item (on the tree)
|
||||||
if ( pos.x() < 100 )
|
if ( pos.x() < 100 )
|
||||||
{
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << "New Event";
|
||||||
QDropEvent* newEvent = new QDropEvent( pos + QPoint( 100, 0 ), event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers(), event->type() );
|
QDropEvent* newEvent = new QDropEvent( pos + QPoint( 100, 0 ), event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers(), event->type() );
|
||||||
QTreeView::dropEvent( newEvent );
|
QTreeView::dropEvent( newEvent );
|
||||||
delete newEvent;
|
delete newEvent;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// In current event, parse sourceTreeView mime instead of playlistitems
|
||||||
|
qDebug() << Q_FUNC_INFO << "Current Event";
|
||||||
|
DropJob *dropThis = new DropJob;
|
||||||
|
dropThis->setDropTypes( DropJob::Playlist );
|
||||||
|
dropThis->setDropAction( DropJob::Create );
|
||||||
|
dropThis->parseMimeData( event->mimeData() );
|
||||||
QTreeView::dropEvent( event );
|
QTreeView::dropEvent( event );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,7 +34,7 @@ Q_OBJECT
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SourceTreeView( QWidget* parent = 0 );
|
explicit SourceTreeView( QWidget* parent = 0 );
|
||||||
|
//static bool acceptsMimeData( const QMimeData* data, bool playlistOnly = true );
|
||||||
public slots:
|
public slots:
|
||||||
void showOfflineSources( bool offlineSourcesShown );
|
void showOfflineSources( bool offlineSourcesShown );
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ private:
|
|||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
T* itemFromIndex( const QModelIndex& index ) const;
|
T* itemFromIndex( const QModelIndex& index ) const;
|
||||||
|
//void parseMimeData( const QMimeData* data );
|
||||||
SourcesModel* m_model;
|
SourcesModel* m_model;
|
||||||
SourcesProxyModel* m_proxyModel;
|
SourcesProxyModel* m_proxyModel;
|
||||||
QModelIndex m_contextMenuIndex;
|
QModelIndex m_contextMenuIndex;
|
||||||
|
Reference in New Issue
Block a user