From a227ae4bcb717b44a9154904361ebdbc3bb94a17 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 21 Aug 2011 04:09:19 +0200 Subject: [PATCH] more work on the drag and drop menu --- src/libtomahawk/dropjob.cpp | 95 ++++++++++++++++++++------ src/libtomahawk/dropjob.h | 8 +++ src/libtomahawk/playlist/treemodel.cpp | 90 ++++++++++++++++++++++++ src/sourcetree/items/categoryitems.cpp | 6 ++ src/sourcetree/items/categoryitems.h | 1 + src/sourcetree/items/playlistitems.cpp | 33 ++++++++- src/sourcetree/items/playlistitems.h | 2 +- src/sourcetree/items/sourcetreeitem.h | 14 ++-- src/sourcetree/sourcedelegate.cpp | 74 ++++++++++++++------ src/sourcetree/sourcedelegate.h | 3 +- src/sourcetree/sourcetreeview.cpp | 8 +-- 11 files changed, 279 insertions(+), 55 deletions(-) diff --git a/src/libtomahawk/dropjob.cpp b/src/libtomahawk/dropjob.cpp index 313940ab7..95af9f038 100644 --- a/src/libtomahawk/dropjob.cpp +++ b/src/libtomahawk/dropjob.cpp @@ -95,6 +95,18 @@ DropJob::acceptsMimeData( const QMimeData* data, bool tracksOnly ) return false; } +void +DropJob::setGetWholeArtists( bool getWholeArtists ) +{ + m_getWholeArtists = getWholeArtists; +} + +void +DropJob::setGetWholeAlbums( bool getWholeAlbums ) +{ + m_getWholeAlbums = getWholeAlbums; +} + void DropJob::tracksFromMimeData( const QMimeData* data, bool allowDuplicates, bool onlyLocal, bool top10 ) @@ -158,7 +170,19 @@ DropJob::tracksFromQueryList( const QMimeData* data ) if ( query && !query->isNull() ) { tDebug() << "Dropped query item:" << query->data()->artist() << "-" << query->data()->track(); - queries << *query; + + if ( m_getWholeArtists ) + { + queries << getArtist( query->data()->artist() ); + } + else if ( m_getWholeAlbums ) + { + queries << getAlbum( query->data()->artist(), query->data()->album() ); + } + else + { + queries << *query; + } } } @@ -182,8 +206,20 @@ DropJob::tracksFromResultList( const QMimeData* data ) { tDebug() << "Dropped result item:" << result->data()->artist()->name() << "-" << result->data()->track(); query_ptr q = result->data()->toQuery(); - q->addResults( QList< result_ptr >() << *result ); - queries << q; + + if ( m_getWholeArtists ) + { + queries << getArtist( q->artist() ); + } + else if ( m_getWholeAlbums ) + { + queries << getAlbum( q->artist(), q->album() ); + } + else + { + q->addResults( QList< result_ptr >() << *result ); + queries << q; + } } } @@ -204,16 +240,10 @@ DropJob::tracksFromAlbumMetaData( const QMimeData *data ) QString album; stream >> album; - artist_ptr artistPtr = Artist::get( artist ); - album_ptr albumPtr = Album::get( artistPtr, album ); - if ( albumPtr->tracks().isEmpty() ) - { - connect( albumPtr.data(), SIGNAL( tracksAdded( QList ) ), - SLOT( onTracksAdded( QList ) ) ); - m_queryCount++; - } + if ( m_getWholeArtists ) + queries << getArtist( artist ); else - queries << albumPtr->tracks(); + queries << getAlbum( artist, album ); } return queries; } @@ -232,15 +262,7 @@ DropJob::tracksFromArtistMetaData( const QMimeData *data ) if ( !m_top10 ) { - artist_ptr artistPtr = Artist::get( artist ); - if ( artistPtr->tracks().isEmpty() ) - { - connect( artistPtr.data(), SIGNAL( tracksAdded( QList ) ), - SLOT( onTracksAdded( QList ) ) ); - m_queryCount++; - } - else - queries << artistPtr->tracks(); + queries << getArtist( artist ); } else { @@ -435,3 +457,34 @@ DropJob::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVar onTracksAdded( results ); } } + +QList< query_ptr > +DropJob::getArtist( const QString &artist ) +{ + artist_ptr artistPtr = Artist::get( artist ); + if ( artistPtr->tracks().isEmpty() ) + { + connect( artistPtr.data(), SIGNAL( tracksAdded( QList ) ), + SLOT( onTracksAdded( QList ) ) ); + m_queryCount++; + return QList< query_ptr >(); + } + else + return artistPtr->tracks(); +} + +QList< query_ptr > +DropJob::getAlbum(const QString &artist, const QString &album) +{ + artist_ptr artistPtr = Artist::get( artist ); + album_ptr albumPtr = Album::get( artistPtr, album ); + if ( albumPtr->tracks().isEmpty() ) + { + connect( albumPtr.data(), SIGNAL( tracksAdded( QList ) ), + SLOT( onTracksAdded( QList ) ) ); + m_queryCount++; + return QList< query_ptr >(); + } + else + return albumPtr->tracks(); +} diff --git a/src/libtomahawk/dropjob.h b/src/libtomahawk/dropjob.h index ca542ee7b..eecc4e9e1 100644 --- a/src/libtomahawk/dropjob.h +++ b/src/libtomahawk/dropjob.h @@ -45,6 +45,9 @@ public: */ static bool acceptsMimeData( const QMimeData* data, bool tracksOnly = true ); static QStringList mimeTypes(); + + void setGetWholeArtists( bool getWholeArtists ); + void setGetWholeAlbums( bool getWholeAlbums ); void tracksFromMimeData( const QMimeData* data, bool allowDuplicates = false, bool onlyLocal = false, bool top10 = false ); signals: @@ -69,12 +72,17 @@ private: QList< Tomahawk::query_ptr > tracksFromAlbumMetaData( const QMimeData* d ); QList< Tomahawk::query_ptr > tracksFromMixedData( const QMimeData* d ); + QList< Tomahawk::query_ptr > getArtist( const QString& artist ); + QList< Tomahawk::query_ptr > getAlbum( const QString& artist, const QString& album ); + void removeDuplicates(); void removeRemoteSources(); int m_queryCount; bool m_allowDuplicates; bool m_onlyLocal; + bool m_getWholeArtists; + bool m_getWholeAlbums; bool m_top10; QList< Tomahawk::query_ptr > m_resultList; diff --git a/src/libtomahawk/playlist/treemodel.cpp b/src/libtomahawk/playlist/treemodel.cpp index eb1d1c63e..6e0e2552b 100644 --- a/src/libtomahawk/playlist/treemodel.cpp +++ b/src/libtomahawk/playlist/treemodel.cpp @@ -318,6 +318,96 @@ TreeModel::mimeData( const QModelIndexList &indexes ) const QByteArray resultData; QDataStream resultStream( &resultData, QIODevice::WriteOnly ); + // lets try with artist only + bool fail = false; + foreach ( const QModelIndex& i, indexes) + { + if ( i.column() > 0 || indexes.contains( i.parent() ) ) + continue; + + TreeModelItem* item = itemFromIndex( i ); + if ( !item ) + continue; + + if ( !item->artist().isNull() ) + { + const artist_ptr& artist = item->artist(); + resultStream << artist->name(); + } + else + { + fail = true; + break; + } + } + if ( !fail ) + { + QMimeData* mimeData = new QMimeData(); + mimeData->setData( "application/tomahawk.metadata.artist", resultData ); + return mimeData; + } + + // lets try with album only + fail = false; + foreach ( const QModelIndex& i, indexes) + { + if ( i.column() > 0 || indexes.contains( i.parent() ) ) + continue; + + TreeModelItem* item = itemFromIndex( i ); + if ( !item ) + continue; + + if ( !item->album().isNull() ) + { + const album_ptr& album = item->album(); + resultStream << album->artist()->name(); + resultStream << album->name(); + } + else + { + fail = true; + break; + } + } + if ( !fail ) + { + QMimeData* mimeData = new QMimeData(); + mimeData->setData( "application/tomahawk.metadata.album", resultData ); + return mimeData; + } + + + // lets try with tracks only + fail = false; + foreach ( const QModelIndex& i, indexes) + { + if ( i.column() > 0 || indexes.contains( i.parent() ) ) + continue; + + TreeModelItem* item = itemFromIndex( i ); + if ( !item ) + continue; + + if ( !item->result().isNull() ) + { + const result_ptr& result = item->result(); + resultStream << qlonglong( &result ); + } + else + { + fail = true; + break; + } + } + if ( !fail ) + { + QMimeData* mimeData = new QMimeData(); + mimeData->setData( "application/tomahawk.result.list", resultData ); + return mimeData; + } + + // Ok... we have to use mixed foreach ( const QModelIndex& i, indexes ) { if ( i.column() > 0 || indexes.contains( i.parent() ) ) diff --git a/src/sourcetree/items/categoryitems.cpp b/src/sourcetree/items/categoryitems.cpp index 86bc03134..dc05d2cff 100644 --- a/src/sourcetree/items/categoryitems.cpp +++ b/src/sourcetree/items/categoryitems.cpp @@ -139,6 +139,12 @@ CategoryAddItem::willAcceptDrag( const QMimeData* data ) const return false; } +SourceTreeItem::DropTypes +CategoryAddItem::supportedDropTypes( const QMimeData* data ) const +{ + return DropTypesNone; +} + bool CategoryAddItem::dropMimeData( const QMimeData* data, Qt::DropAction ) diff --git a/src/sourcetree/items/categoryitems.h b/src/sourcetree/items/categoryitems.h index a7de58b0f..18cb21d77 100644 --- a/src/sourcetree/items/categoryitems.h +++ b/src/sourcetree/items/categoryitems.h @@ -33,6 +33,7 @@ public: virtual int peerSortValue() const; virtual bool willAcceptDrag(const QMimeData* data) const; + virtual DropTypes supportedDropTypes(const QMimeData* data) const; virtual bool dropMimeData(const QMimeData* data, Qt::DropAction action); private slots: diff --git a/src/sourcetree/items/playlistitems.cpp b/src/sourcetree/items/playlistitems.cpp index 5899405f9..58570168c 100644 --- a/src/sourcetree/items/playlistitems.cpp +++ b/src/sourcetree/items/playlistitems.cpp @@ -139,9 +139,25 @@ PlaylistItem::willAcceptDrag( const QMimeData* data ) const } PlaylistItem::DropTypes -PlaylistItem::supportedDropTypes() const +PlaylistItem::supportedDropTypes( const QMimeData* data ) const { - return DropTypeAllItems | DropTypeLocalItems | DropTypeTop10; + if ( data->hasFormat( "application/tomahawk.query.list" ) ) + return DropTypeThisTrack | DropTypeThisAlbum | DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50; + else if ( data->hasFormat( "application/tomahawk.result.list" ) ) + return DropTypeThisTrack | DropTypeThisAlbum | DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50; + else if ( data->hasFormat( "application/tomahawk.metadata.album" ) ) + return DropTypeThisAlbum | DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50; + else if ( data->hasFormat( "application/tomahawk.metadata.artist" ) ) + return DropTypeAllFromArtist | DropTypeLocalItems | DropTypeTop50; + else if ( data->hasFormat( "application/tomahawk.mixed" ) ) + { + return DropTypesNone; + } + else if ( data->hasFormat( "text/plain" ) ) + { + return DropTypesNone; + } + return DropTypesNone; } @@ -159,10 +175,21 @@ PlaylistItem::dropMimeData( const QMimeData* data, Qt::DropAction action ) DropJob *dj = new DropJob(); connect( dj, SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) ); + if ( dropType() == DropTypeAllFromArtist ) + dj->setGetWholeArtists( true ); + if ( dropType() == DropTypeThisAlbum ) + dj->setGetWholeAlbums( true ); + if ( dropType() == DropTypeLocalItems ) + { + dj->setGetWholeArtists( true ); dj->tracksFromMimeData( data, false, true ); - else if ( dropType() == DropTypeTop10 ) + } + else if ( dropType() == DropTypeTop50 ) + { + dj->setGetWholeArtists( true ); dj->tracksFromMimeData( data, false, false, true ); + } else dj->tracksFromMimeData( data, false, false ); diff --git a/src/sourcetree/items/playlistitems.h b/src/sourcetree/items/playlistitems.h index 62ddefc2d..cc02e7bfb 100644 --- a/src/sourcetree/items/playlistitems.h +++ b/src/sourcetree/items/playlistitems.h @@ -34,7 +34,7 @@ public: virtual Qt::ItemFlags flags() const; virtual void activate(); virtual bool willAcceptDrag( const QMimeData* data ) const; - virtual DropTypes supportedDropTypes() const; + virtual DropTypes supportedDropTypes( const QMimeData* data ) const; virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action ); virtual QIcon icon() const; virtual bool setData(const QVariant& v, bool role); diff --git a/src/sourcetree/items/sourcetreeitem.h b/src/sourcetree/items/sourcetreeitem.h index 2c174f220..a3bdaec1a 100644 --- a/src/sourcetree/items/sourcetreeitem.h +++ b/src/sourcetree/items/sourcetreeitem.h @@ -34,11 +34,13 @@ class SourceTreeItem : public QObject public: enum DropType { - DropTypesNone = 0x00, - DropTypeAllItems = 0x01, - DropTypeLocalItems = 0x02, - DropTypeTop10 = 0x04, - DropTypesAllTypes = 0xff + DropTypesNone = 0x00, + DropTypeThisTrack = 0x01, + DropTypeThisAlbum = 0x02, + DropTypeAllFromArtist = 0x04, + DropTypeLocalItems = 0x08, + DropTypeTop50 = 0x10, + DropTypesAllTypes = 0xff }; Q_DECLARE_FLAGS( DropTypes, DropType ) @@ -66,7 +68,7 @@ public: virtual bool setData( const QVariant&, bool ) { return false; } virtual int peerSortValue() const { return 0; } // How to sort relative to peers in the tree. virtual int IDValue() const { return 0; } - virtual DropTypes supportedDropTypes() const { return DropTypesNone; } + virtual DropTypes supportedDropTypes( const QMimeData* mimeData ) const { Q_UNUSED( mimeData ); return DropTypesNone; } virtual void setDropType( DropType type ) { m_dropType = type; } virtual DropType dropType() const { return m_dropType; } diff --git a/src/sourcetree/sourcedelegate.cpp b/src/sourcetree/sourcedelegate.cpp index b128b5f38..17cbef2d3 100644 --- a/src/sourcetree/sourcedelegate.cpp +++ b/src/sourcetree/sourcedelegate.cpp @@ -3,6 +3,7 @@ #include "items/sourcetreeitem.h" #include "items/collectionitem.h" #include "items/playlistitems.h" +#include "items/categoryitems.h" #include "utils/tomahawkutils.h" #include "items/temporarypageitem.h" @@ -23,6 +24,7 @@ SourceDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& else if ( index == m_dropHoverIndex ) { QSize originalSize = QStyledItemDelegate::sizeHint( option, index ); + qDebug() << "droptypecount is" << dropTypeCount( item ); return originalSize + QSize( 0, originalSize.height() * dropTypeCount( item ) ); } else @@ -137,22 +139,31 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co painter->restore(); } - else if ( type == SourcesModel::StaticPlaylist ) + else if ( type == SourcesModel::StaticPlaylist || type == SourcesModel::CategoryAdd ) { painter->save(); - QFont normal = painter->font(); QFont bold = painter->font(); bold.setBold( true ); - PlaylistItem* plItem = qobject_cast< PlaylistItem* >( item ); - Q_ASSERT( plItem ); - QString name = index.data().toString(); - - if ( plItem && !plItem->playlist().isNull() ) + if ( type == SourcesModel::StaticPlaylist ) { - name = plItem->playlist()->title(); + PlaylistItem* plItem = qobject_cast< PlaylistItem* >( item ); + Q_ASSERT( plItem ); + + + if ( plItem && !plItem->playlist().isNull() ) + { + name = plItem->playlist()->title(); + } + } + else if ( type == SourcesModel::CategoryAdd ) + { + CategoryAddItem* cItem = qobject_cast< CategoryAddItem* >( item ); + Q_ASSERT( cItem ); + + name = cItem->text(); } int height = option.rect.height(); @@ -182,31 +193,50 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co painter->drawRoundedRect( selectionRect, 5, 5 ); int count = 1; - if ( item->supportedDropTypes().testFlag( SourceTreeItem::DropTypeAllItems ) ) + SourceTreeItem::DropTypes dropTypes = item->supportedDropTypes( m_dropMimeData ); + if ( dropTypes.testFlag( SourceTreeItem::DropTypeThisTrack ) ) { - text = tr( "All items" ); + text = tr( "This track" ); textRect = option.rect.adjusted( iconRect.width() + 8, 2 + ( count * height ), 0, 0 ); painter->drawText( textRect, text ); if ( count == hoveredDropTypeIndex ) - m_hoveredDropType = SourceTreeItem::DropTypeAllItems; + m_hoveredDropType = SourceTreeItem::DropTypeThisTrack; count++; } - if ( item->supportedDropTypes().testFlag( SourceTreeItem::DropTypeLocalItems ) ) + if ( dropTypes.testFlag( SourceTreeItem::DropTypeThisAlbum ) ) { - text = tr( "Local items" ); + text = tr( "This album" ); + textRect = option.rect.adjusted( iconRect.width() + 8, 2 + ( count * height ), 0, 0 ); + painter->drawText( textRect, text ); + if ( count == hoveredDropTypeIndex ) + m_hoveredDropType = SourceTreeItem::DropTypeThisAlbum; + count++; + } + if ( dropTypes.testFlag( SourceTreeItem::DropTypeAllFromArtist ) ) + { + text = tr( "All from artist" ); + textRect = option.rect.adjusted( iconRect.width() + 8, 2 + ( count * height ), 0, 0 ); + painter->drawText( textRect, text ); + if ( count == hoveredDropTypeIndex ) + m_hoveredDropType = SourceTreeItem::DropTypeAllFromArtist; + count++; + } + if ( dropTypes.testFlag( SourceTreeItem::DropTypeLocalItems ) ) + { + text = tr( "All local from Artist" ); textRect = option.rect.adjusted( iconRect.width() + 8, 2 + ( count * height ), 0, 0 ); painter->drawText( textRect, text ); if ( count == hoveredDropTypeIndex ) m_hoveredDropType = SourceTreeItem::DropTypeLocalItems; count++; } - if ( item->supportedDropTypes().testFlag( SourceTreeItem::DropTypeTop10 ) ) + if ( dropTypes.testFlag( SourceTreeItem::DropTypeTop50 ) ) { - text = tr( "Top 10" ); + text = tr( "Top 50" ); textRect = option.rect.adjusted( iconRect.width() + 8, 2 + ( count * height ), 0, 0 ); painter->drawText( textRect, text ); if ( count == hoveredDropTypeIndex ) - m_hoveredDropType = SourceTreeItem::DropTypeTop10; + m_hoveredDropType = SourceTreeItem::DropTypeTop50; count++; } } @@ -282,13 +312,19 @@ int SourceDelegate::dropTypeCount( SourceTreeItem* item ) const { int menuCount = 0; - if ( item->supportedDropTypes().testFlag( SourceTreeItem::DropTypeAllItems ) ) + if ( item->supportedDropTypes( m_dropMimeData ).testFlag( SourceTreeItem::DropTypeThisTrack ) ) menuCount++; - if ( item->supportedDropTypes().testFlag( SourceTreeItem::DropTypeLocalItems ) ) + if ( item->supportedDropTypes( m_dropMimeData ).testFlag( SourceTreeItem::DropTypeThisAlbum ) ) menuCount++; - if ( item->supportedDropTypes().testFlag( SourceTreeItem::DropTypeTop10 ) ) + if ( item->supportedDropTypes( m_dropMimeData ).testFlag( SourceTreeItem::DropTypeAllFromArtist ) ) + menuCount++; + + if ( item->supportedDropTypes( m_dropMimeData ).testFlag( SourceTreeItem::DropTypeLocalItems ) ) + menuCount++; + + if ( item->supportedDropTypes( m_dropMimeData ).testFlag( SourceTreeItem::DropTypeTop50 ) ) menuCount++; return menuCount; diff --git a/src/sourcetree/sourcedelegate.h b/src/sourcetree/sourcedelegate.h index f0e7ad18a..124b8c3c7 100644 --- a/src/sourcetree/sourcedelegate.h +++ b/src/sourcetree/sourcedelegate.h @@ -11,7 +11,7 @@ class SourceDelegate : public QStyledItemDelegate public: SourceDelegate( QAbstractItemView* parent = 0 ) : QStyledItemDelegate( parent ), m_parent( parent ) {} - void setDropHoverIndex( const QModelIndex &index ) { m_dropHoverIndex = index; } + void setDropHoverIndex( const QModelIndex &index, const QMimeData *mimeData ) { m_dropHoverIndex = index; m_dropMimeData = const_cast< QMimeData* >( mimeData ); } SourceTreeItem::DropType hoveredDropType() const; @@ -26,6 +26,7 @@ private: QAbstractItemView* m_parent; mutable int m_iconHeight; QModelIndex m_dropHoverIndex; + QMimeData *m_dropMimeData; mutable SourceTreeItem::DropType m_hoveredDropType; // Hack to keep easily track of the current highlighted DropType in paint() }; diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp index fd71166c8..1354d1e46 100644 --- a/src/sourcetree/sourcetreeview.cpp +++ b/src/sourcetree/sourcetreeview.cpp @@ -439,7 +439,7 @@ SourceTreeView::dragLeaveEvent( QDragLeaveEvent* event ) m_dragging = false; setDirtyRegion( m_dropRect ); - m_delegate->setDropHoverIndex( QModelIndex() ); + m_delegate->setDropHoverIndex( QModelIndex(), 0 ); dataChanged(m_dropIndex, m_dropIndex); m_dropIndex = QPersistentModelIndex(); } @@ -456,7 +456,7 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event ) setDirtyRegion( m_dropRect ); const QPoint pos = event->pos(); const QModelIndex index = indexAt( pos ); - m_delegate->setDropHoverIndex( QModelIndex() ); + m_delegate->setDropHoverIndex( QModelIndex(), event->mimeData() ); dataChanged(m_dropIndex, m_dropIndex); m_dropIndex = QPersistentModelIndex( index ); @@ -469,7 +469,7 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event ) if( item->willAcceptDrag( event->mimeData() ) ) { accept = true; - m_delegate->setDropHoverIndex( index ); + m_delegate->setDropHoverIndex( index, event->mimeData() ); dataChanged(index, index); } } @@ -504,7 +504,7 @@ SourceTreeView::dropEvent( QDropEvent* event ) QTreeView::dropEvent( event ); m_dragging = false; m_dropIndex = QPersistentModelIndex(); - m_delegate->setDropHoverIndex( QModelIndex() ); + m_delegate->setDropHoverIndex( QModelIndex(), 0 ); dataChanged( index, index ); }