diff --git a/src/libtomahawk/contextmenu.cpp b/src/libtomahawk/contextmenu.cpp index 75acadf55..46764d04d 100644 --- a/src/libtomahawk/contextmenu.cpp +++ b/src/libtomahawk/contextmenu.cpp @@ -36,7 +36,7 @@ ContextMenu::ContextMenu( QWidget* parent ) m_sigmap = new QSignalMapper( this ); connect( m_sigmap, SIGNAL( mapped( int ) ), SLOT( onTriggered( int ) ) ); - m_supportedActions = ActionPlay | ActionQueue | ActionCopyLink; + m_supportedActions = ActionPlay | ActionQueue | ActionCopyLink | ActionAddToPlaylist | ActionAddTrackToPl; } ContextMenu::~ContextMenu() @@ -50,6 +50,7 @@ ContextMenu::clear() m_queries.clear(); m_albums.clear(); m_artists.clear(); + } unsigned int @@ -61,9 +62,11 @@ ContextMenu::itemCount() const void ContextMenu::setQueries( const QList& queries ) { + if ( queries.isEmpty() ) return; + QMenu::clear(); m_queries.clear(); m_queries << queries; @@ -74,7 +77,24 @@ ContextMenu::setQueries( const QList& queries ) if ( m_supportedActions & ActionQueue ) m_sigmap->setMapping( addAction( tr( "Add to &Queue" ) ), ActionQueue ); - //m_sigmap->setMapping( addAction( tr( "&Add to Playlist" ) ), ActionAddToPlaylist ); + + + if ( m_supportedActions & ActionAddToPlaylist ){ + + QList 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(); @@ -86,8 +106,11 @@ ContextMenu::setQueries( const QList& queries ) if ( m_supportedActions & ActionDelete ) m_sigmap->setMapping( addAction( queries.count() > 1 ? tr( "&Delete Items" ) : tr( "&Delete Item" ) ), ActionDelete ); + + foreach ( QAction* action, actions() ) { + connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) ); } } @@ -96,12 +119,14 @@ ContextMenu::setQueries( const QList& queries ) void ContextMenu::setQuery( const Tomahawk::query_ptr& query ) { + QList queries; queries << query; setQueries( queries ); } + void ContextMenu::setAlbums( const QList& 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 ContextMenu::onTriggered( int action ) { @@ -199,6 +239,7 @@ ContextMenu::onTriggered( int action ) } + void ContextMenu::addToQueue() { foreach ( const query_ptr& query, m_queries ) @@ -221,6 +262,7 @@ void ContextMenu::addToQueue() void ContextMenu::copyLink() { + qDebug() << Q_FUNC_INFO; if ( m_queries.count() ) { GlobalActionManager::instance()->copyToClipboard( m_queries.first() ); diff --git a/src/libtomahawk/contextmenu.h b/src/libtomahawk/contextmenu.h index 3c1842948..a653c65fb 100644 --- a/src/libtomahawk/contextmenu.h +++ b/src/libtomahawk/contextmenu.h @@ -34,7 +34,14 @@ Q_OBJECT public: 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 ); virtual ~ContextMenu(); @@ -57,19 +64,21 @@ public: signals: void triggered( int action ); + void clicked( int action ); private slots: void onTriggered( int action ); - + void onClicked( int action ); void copyLink(); void addToQueue(); - + void onAction(const QString& what); private: QSignalMapper* m_sigmap; int m_supportedActions; QList m_queries; QList m_artists; + playlist_ptr m_playlist; QList m_albums; }; diff --git a/src/libtomahawk/dropjob.cpp b/src/libtomahawk/dropjob.cpp index f284cefdd..649bff453 100644 --- a/src/libtomahawk/dropjob.cpp +++ b/src/libtomahawk/dropjob.cpp @@ -29,7 +29,7 @@ #include "utils/logger.h" #include "globalactionmanager.h" #include "infosystem/infosystem.h" - +#include "utils/xspfloader.h" using namespace Tomahawk; DropJob::DropJob( QObject *parent ) @@ -60,10 +60,40 @@ DropJob::mimeTypes() return mimeTypes; } +bool +DropJob::DropAction() +{ + + if ( dropAction() == DropJob::Create ) + return true; + return false; + +} + 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" ) || data->hasFormat( "application/tomahawk.plentry.list" ) || data->hasFormat( "application/tomahawk.result.list" ) @@ -75,22 +105,42 @@ DropJob::acceptsMimeData( const QMimeData* data, bool tracksOnly ) 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 - if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" ) && - ( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) ) + if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" ) + && 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; // crude check for rdio tracks - if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rdio.com" ) && - ( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) ) + if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rdio.com" ) + && data->data( "text/plain" ).contains( "track" ) + && ( acceptedType.testFlag(DropJob::Track) || acceptedType.testFlag(DropJob::All) ) + ) 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, // so we do an extra level of lookup 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( "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 false; @@ -134,6 +184,26 @@ DropJob::tracksFromMimeData( const QMimeData* data, bool allowDuplicates, bool o void 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; if ( data->hasFormat( "application/tomahawk.query.list" ) ) results = tracksFromQueryList( data ); @@ -148,8 +218,14 @@ DropJob::parseMimeData( const QMimeData *data ) else if ( data->hasFormat( "text/plain" ) ) { QString plainData = QString::fromUtf8( data->data( "text/plain" ).constData() ); - tDebug() << "Got text/plain mime data:" << data->data( "text/plain" ) << "decoded to:" << plainData; - handleTrackUrls ( 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 ); } m_resultList.append( results ); @@ -331,13 +407,72 @@ DropJob::tracksFromMixedData( const QMimeData *data ) 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 ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) ); + } + + m_queryCount++; + } + +} + void 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" ) ) { - QStringList tracks = urls.split( "\n" ); + QStringList tracks = urls.split(QRegExp("\\s+"), QString::SkipEmptyParts); tDebug() << "Got a list of spotify urls!" << tracks; SpotifyParser* spot = new SpotifyParser( tracks, this ); @@ -367,7 +502,6 @@ DropJob::handleTrackUrls( const QString& urls ) } } - void DropJob::expandedUrls( QStringList urls ) { diff --git a/src/libtomahawk/dropjob.h b/src/libtomahawk/dropjob.h index 3e84d6510..24506ac4a 100644 --- a/src/libtomahawk/dropjob.h +++ b/src/libtomahawk/dropjob.h @@ -43,12 +43,41 @@ public: * * 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(); + 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 setGetWholeAlbums( bool getWholeAlbums ); 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: /// QMimeData parsing results @@ -63,7 +92,7 @@ private slots: private: /// handle parsing mime data - void parseMimeData( const QMimeData* data ); + void handleTrackUrls( const QString& urls ); QList< Tomahawk::query_ptr > tracksFromQueryList( const QMimeData* d ); @@ -86,8 +115,11 @@ private: bool m_getWholeArtists; bool m_getWholeAlbums; bool m_top10; + DropTypes m_dropTypes; + DropAction m_dropAction; + bool DropAction(); QList< Tomahawk::query_ptr > m_resultList; }; - +Q_DECLARE_OPERATORS_FOR_FLAGS(DropJob::DropTypes) #endif // DROPJOB_H diff --git a/src/libtomahawk/utils/spotifyparser.cpp b/src/libtomahawk/utils/spotifyparser.cpp index fb2e7993c..0051a0035 100644 --- a/src/libtomahawk/utils/spotifyparser.cpp +++ b/src/libtomahawk/utils/spotifyparser.cpp @@ -21,7 +21,7 @@ #include "utils/logger.h" #include "utils/tomahawkutils.h" #include "query.h" - +#include "sourcelist.h" #include #include @@ -29,19 +29,22 @@ using namespace Tomahawk; -SpotifyParser::SpotifyParser( const QStringList& trackUrls, QObject* parent ) +SpotifyParser::SpotifyParser( const QStringList& Urls, QObject* parent, bool createNewPlaylist) : QObject ( parent ) , m_single( false ) + { - foreach ( const QString& url, trackUrls ) - lookupTrack( url ); + m_createNewPlaylist = createNewPlaylist; + 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 ) , m_single( true ) { - lookupTrack( trackUrl ); + m_createNewPlaylist = createNewPlaylist; + lookupUrl( Url ); } SpotifyParser::~SpotifyParser() @@ -49,10 +52,43 @@ 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 SpotifyParser::lookupTrack( const QString& link ) { - if ( !link.contains( "track" ) ) // we only support track links atm + + tDebug() << "Got a QString " << link; + if ( !link.contains( "track" )) // we only support track links atm return; // we need Spotify URIs such as spotify:track:XXXXXX, so if we by chance get a http://open.spotify.com url, convert it @@ -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 SpotifyParser::spotifyTrackLookupFinished() { @@ -93,12 +183,12 @@ SpotifyParser::spotifyTrackLookupFinished() if ( !ok ) { tLog() << "Failed to parse json from Spotify track lookup:" << p.errorString() << "On line" << p.errorLine(); - checkFinished(); + checkTrackFinished(); return; } else if ( !res.contains( "track" ) ) { tLog() << "No 'track' item in the spotify track lookup result... not doing anything"; - checkFinished(); + checkTrackFinished(); return; } @@ -128,11 +218,33 @@ SpotifyParser::spotifyTrackLookupFinished() tLog() << "Error in network request to Spotify for track decoding:" << r->errorString(); } - checkFinished(); + checkTrackFinished(); } 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 { diff --git a/src/libtomahawk/utils/spotifyparser.h b/src/libtomahawk/utils/spotifyparser.h index 24bba4fbf..b7381fe4f 100644 --- a/src/libtomahawk/utils/spotifyparser.h +++ b/src/libtomahawk/utils/spotifyparser.h @@ -40,24 +40,31 @@ class DLLEXPORT SpotifyParser : public QObject { Q_OBJECT public: - explicit SpotifyParser( const QString& trackUrl, QObject* parent = 0 ); - explicit SpotifyParser( const QStringList& trackUrls, QObject* parent = 0 ); + explicit SpotifyParser( const QString& trackUrl, QObject* parent = 0, bool createNewPl = false ); + explicit SpotifyParser( const QStringList& trackUrls, QObject* parent = 0, bool createNewPl = false); virtual ~SpotifyParser(); signals: void track( const Tomahawk::query_ptr& track ); void tracks( const QList< Tomahawk::query_ptr > tracks ); + void playlist( const Tomahawk::query_ptr& playlist ); private slots: void spotifyTrackLookupFinished(); + void spotifyPlaylistLookupFinished(); private: + void lookupUrl( const QString& url ); void lookupTrack( const QString& track ); - void checkFinished(); - + void lookupPlaylist( const QString& playlist ); + void checkTrackFinished(); + void checkPlaylistFinished(); bool m_single; + bool m_createNewPlaylist; QList< query_ptr > m_tracks; QSet< QNetworkReply* > m_queries; + QString m_title, m_info, m_creator; + Tomahawk::playlist_ptr m_playlist; }; } diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp index 54d0bfec5..55f2a16ea 100644 --- a/src/sourcetree/sourcetreeview.cpp +++ b/src/sourcetree/sourcetreeview.cpp @@ -426,16 +426,16 @@ SourceTreeView::dragEnterEvent( QDragEnterEvent* event ) qDebug() << Q_FUNC_INFO; QTreeView::dragEnterEvent( event ); - if ( DropJob::acceptsMimeData( event->mimeData() ) ) + if ( DropJob::acceptsMimeData( event->mimeData(), DropJob::Track | DropJob::Playlist, DropJob::Create ) ) { - m_dragging = true; - m_dropRect = QRect(); - m_dropIndex = QPersistentModelIndex(); + m_dragging = true; + m_dropRect = QRect(); + m_dropIndex = QPersistentModelIndex(); - qDebug() << "Accepting Drag Event"; - event->setDropAction( Qt::CopyAction ); - event->accept(); - } + qDebug() << Q_FUNC_INFO << "Accepting Drag Event"; + event->setDropAction( Qt::CopyAction ); + event->acceptProposedAction(); + } } @@ -459,7 +459,7 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event ) bool accept = false; QTreeView::dragMoveEvent( event ); - if ( DropJob::acceptsMimeData( event->mimeData() ) ) + if ( DropJob::acceptsMimeData( event->mimeData(), DropJob::Track, DropJob::Append ) ) { setDirtyRegion( m_dropRect ); const QPoint pos = event->pos(); @@ -475,6 +475,7 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event ) SourceTreeItem* item = itemFromIndex< SourceTreeItem >( index ); if( item->willAcceptDrag( event->mimeData() ) ) { + accept = true; m_delegate->hovered( index, event->mimeData() ); dataChanged(index, index); @@ -489,14 +490,24 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event ) if ( accept ) { + //qDebug() << Q_FUNC_INFO << "Accepting"; event->setDropAction( Qt::CopyAction ); event->accept(); } - else - event->ignore(); + else{ - 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 ); 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) 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() ); QTreeView::dropEvent( newEvent ); delete newEvent; } 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 ); } diff --git a/src/sourcetree/sourcetreeview.h b/src/sourcetree/sourcetreeview.h index a2612337b..ac1c1355f 100644 --- a/src/sourcetree/sourcetreeview.h +++ b/src/sourcetree/sourcetreeview.h @@ -34,7 +34,7 @@ Q_OBJECT public: explicit SourceTreeView( QWidget* parent = 0 ); - + //static bool acceptsMimeData( const QMimeData* data, bool playlistOnly = true ); public slots: void showOfflineSources( bool offlineSourcesShown ); @@ -79,7 +79,7 @@ private: template< typename T > T* itemFromIndex( const QModelIndex& index ) const; - + //void parseMimeData( const QMimeData* data ); SourcesModel* m_model; SourcesProxyModel* m_proxyModel; QModelIndex m_contextMenuIndex;