From ed27dcdeeca2e3e59fa4770d3e198677bcf27f9f Mon Sep 17 00:00:00 2001 From: Leo Franchi Date: Tue, 29 Mar 2011 23:51:48 -0400 Subject: [PATCH] Move drop handling into source model Add a Add Station item (needs flag change) Cleanup restore dynamic playlists to wo rking though hidden so we don't crash fix lots of minor things in the sourcelist --- src/libtomahawk/collection.cpp | 4 +- src/libtomahawk/collection.h | 8 +- .../database/databasecollection.cpp | 4 +- src/libtomahawk/database/databasecollection.h | 2 +- ...atabasecommand_loadalldynamicplaylists.cpp | 4 +- .../databasecommand_loadalldynamicplaylists.h | 3 +- src/libtomahawk/playlist/playlistmanager.cpp | 18 +- src/libtomahawk/playlist/playlistmanager.h | 3 + src/sourcetree/sourcesmodel.cpp | 44 ++++- src/sourcetree/sourcesmodel.h | 16 +- src/sourcetree/sourcetreeitem.cpp | 166 ++++++++++++++++-- src/sourcetree/sourcetreeitem.h | 43 ++++- src/sourcetree/sourcetreeview.cpp | 139 ++++++--------- src/sourcetree/sourcetreeview.h | 13 +- 14 files changed, 330 insertions(+), 137 deletions(-) diff --git a/src/libtomahawk/collection.cpp b/src/libtomahawk/collection.cpp index 3310ee8ed..ed186be37 100644 --- a/src/libtomahawk/collection.cpp +++ b/src/libtomahawk/collection.cpp @@ -84,7 +84,7 @@ Collection::addDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p ) qDebug() << Q_FUNC_INFO << "Collection name" << name() << "from source id" << source()->id() << "numplaylists:" << m_playlists.length(); -// emit dynamicPlaylistsAdded( toadd ); + emit dynamicPlaylistsAdded( toadd ); } @@ -114,7 +114,7 @@ Collection::deleteDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p ) qDebug() << Q_FUNC_INFO << "Collection name" << name() << "from source id" << source()->id() << "numplaylists:" << m_playlists.length(); -// emit dynamicPlaylistsDeleted( todelete ); + emit dynamicPlaylistsDeleted( todelete ); } diff --git a/src/libtomahawk/collection.h b/src/libtomahawk/collection.h index d212639e4..33441b2e0 100644 --- a/src/libtomahawk/collection.h +++ b/src/libtomahawk/collection.h @@ -82,10 +82,10 @@ signals: void playlistsAdded( const QList& ); void playlistsDeleted( const QList& ); - void automaticPlaylistsAdded( const QList& ); - void automaticPlaylistsDeleted( const QList& ); - void stationsAdded( const QList& ); - void stationsDeleted( const QList& ); + void dynamicPlaylistsAdded( const QList& ); + void dynamicPlaylistsDeleted( const QList& ); +// void stationsAdded( const QList& ); +// void stationsDeleted( const QList& ); public slots: virtual void addTracks( const QList& newitems ) = 0; diff --git a/src/libtomahawk/database/databasecollection.cpp b/src/libtomahawk/database/databasecollection.cpp index 59dcf4be0..0348cd5e6 100644 --- a/src/libtomahawk/database/databasecollection.cpp +++ b/src/libtomahawk/database/databasecollection.cpp @@ -53,10 +53,12 @@ DatabaseCollection::loadDynamicPlaylists() qDebug() << Q_FUNC_INFO; DatabaseCommand_LoadAllDynamicPlaylists* cmd = new DatabaseCommand_LoadAllDynamicPlaylists( source() ); + connect( cmd, SIGNAL( dynamicPlaylistLoaded( Tomahawk::source_ptr, QVariantList ) ), + SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) );/* connect( cmd, SIGNAL( autoPlaylistLoaded( Tomahawk::source_ptr, QVariantList ) ), SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) ); connect( cmd, SIGNAL( stationLoaded( Tomahawk::source_ptr, QVariantList ) ), - SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) ); + SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) );*/ Database::instance()->enqueue( QSharedPointer( cmd ) ); } diff --git a/src/libtomahawk/database/databasecollection.h b/src/libtomahawk/database/databasecollection.h index e45e9f870..5b15913c0 100644 --- a/src/libtomahawk/database/databasecollection.h +++ b/src/libtomahawk/database/databasecollection.h @@ -51,7 +51,7 @@ public slots: virtual void removeTracks( const QDir& dir ); private slots: -// void dynamicPlaylistCreated( const Tomahawk::source_ptr& source, const QVariantList& data ); + void dynamicPlaylistCreated( const Tomahawk::source_ptr& source, const QVariantList& data ); }; #endif // DATABASECOLLECTION_H diff --git a/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.cpp b/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.cpp index a93116b91..b85c19dba 100644 --- a/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.cpp +++ b/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.cpp @@ -49,10 +49,12 @@ void DatabaseCommand_LoadAllDynamicPlaylists::exec( DatabaseImpl* dbi ) << query.value(6).toBool() //shared << query.value(5).toInt() //lastmod << query.value(0).toString(); //GUID + emit dynamicPlaylistLoaded( source(), data ); + /* if( static_cast( query.value(8).toInt() ) == Static ) emit autoPlaylistLoaded( source(), data ); else - emit stationLoaded( source(), data ); + emit stationLoaded( source(), data );*/ } emit done(); diff --git a/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.h b/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.h index e845008ed..eb56239a9 100644 --- a/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.h +++ b/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.h @@ -39,8 +39,7 @@ public: virtual QString commandname() const { return "loadalldynamicplaylists"; } signals: - void autoPlaylistLoaded( const Tomahawk::source_ptr& source, const QVariantList& data ); - void stationLoaded( const Tomahawk::source_ptr& source, const QVariantList& data ); + void dynamicPlaylistLoaded( const Tomahawk::source_ptr& source, const QVariantList& data ); void done(); }; diff --git a/src/libtomahawk/playlist/playlistmanager.cpp b/src/libtomahawk/playlist/playlistmanager.cpp index cbf1337cf..da1dbeaed 100644 --- a/src/libtomahawk/playlist/playlistmanager.cpp +++ b/src/libtomahawk/playlist/playlistmanager.cpp @@ -47,6 +47,7 @@ #include "widgets/welcomewidget.h" #include "widgets/infowidgets/sourceinfowidget.h" +#include #define FILTER_TIMEOUT 280 @@ -567,13 +568,16 @@ PlaylistManager::setPage( ViewPage* page, bool trackHistory ) if ( !playlistForInterface( currentPlaylistInterface() ).isNull() ) emit playlistActivated( playlistForInterface( currentPlaylistInterface() ) ); - if ( !dynamicPlaylistForInterface( currentPlaylistInterface() ).isNull() ) + + else if ( dynamicPlaylistForInterface( currentPlaylistInterface() ) ) emit dynamicPlaylistActivated( dynamicPlaylistForInterface( currentPlaylistInterface() ) ); - if ( !collectionForInterface( currentPlaylistInterface() ).isNull() ) + else if ( collectionForInterface( currentPlaylistInterface() ) ) emit collectionActivated( collectionForInterface( currentPlaylistInterface() ) ); - if ( isSuperCollectionVisible() ) + else if ( isSuperCollectionVisible() ) emit superCollectionActivated(); - if ( !currentPlaylistInterface() ) + else if( isNewPlaylistPageVisible() ) + emit newPlaylistActivated(); + else if ( !currentPlaylistInterface() ) emit tempPageActivated(); if ( !AudioEngine::instance()->isPlaying() ) @@ -597,6 +601,12 @@ PlaylistManager::setPage( ViewPage* page, bool trackHistory ) updateView(); } +bool +PlaylistManager::isNewPlaylistPageVisible() const +{ + return dynamic_cast< NewPlaylistWidget* >( currentPage() ) != 0; +} + void PlaylistManager::unlinkPlaylist() diff --git a/src/libtomahawk/playlist/playlistmanager.h b/src/libtomahawk/playlist/playlistmanager.h index 8ccf91f9d..ffea8d76f 100644 --- a/src/libtomahawk/playlist/playlistmanager.h +++ b/src/libtomahawk/playlist/playlistmanager.h @@ -68,6 +68,7 @@ public: PlaylistView* queue() const; bool isSuperCollectionVisible() const; + bool isNewPlaylistPageVisible() const; PlaylistInterface* currentPlaylistInterface() const; Tomahawk::ViewPage* currentPage() const; @@ -108,6 +109,8 @@ signals: void playlistActivated( const Tomahawk::playlist_ptr& playlist ); void dynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist ); + void newPlaylistActivated(); + public slots: bool showSuperCollection(); void showWelcomePage(); diff --git a/src/sourcetree/sourcesmodel.cpp b/src/sourcetree/sourcesmodel.cpp index 8ebcba337..5e19e7b62 100644 --- a/src/sourcetree/sourcesmodel.cpp +++ b/src/sourcetree/sourcesmodel.cpp @@ -67,6 +67,8 @@ SourcesModel::data( const QModelIndex& index, int role ) const return itemFromIndex( index )->type(); case Qt::DisplayRole: return itemFromIndex( index )->text(); + case Qt::DecorationRole: + return itemFromIndex( index )->icon(); } return QVariant(); } @@ -162,8 +164,15 @@ SourcesModel::mimeData( const QModelIndexList& indexes ) const bool SourcesModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent ) { - // TODO - return false; + SourceTreeItem* item; + if( row == -1 && column == -1 ) + item = itemFromIndex( parent ); + else + item = itemFromIndex( index( row, column, parent ) ); + + Q_ASSERT( item ); + + return item->dropMimeData( data, action ); } Qt::DropActions @@ -241,6 +250,37 @@ SourcesModel::removeItem( const Tomahawk::source_ptr& source ) return false; } +QModelIndex +SourcesModel::indexFromPlaylist( const playlist_ptr& playlist ) +{ + QModelIndex idx; + // No option but to iterate through everything... lame + for( int i = 0; i < rowCount(); i++ ) { + QModelIndex source = index( i, 0, QModelIndex() ); + CollectionItem* col = qobject_cast< CollectionItem* >( m_rootItem->children().at( i ) ); + if( col->source().isNull() ) + continue; // skip super collection + + // get the playlist item and look through its children + for( int k = 0; k < col->children().count(); k++ ) { + CategoryItem* cat = qobject_cast< CategoryItem* >( col->children().at( k ) ); + if( cat && cat->categoryType() == SourcesModel::PlaylistsCategory ) { // this is it + // now find the playlist itself + foreach( SourceTreeItem* plItem, cat->children() ) { + PlaylistItem* plI = qobject_cast< PlaylistItem* >( plItem ); + if( plI && plI->playlist() == playlist ) { + return indexFromItem( plI ); + } + } + break; // only one playlist category per source anyway, stop looking here + } + } + } + qDebug() << "FAILED to find playlist in source tree:" << playlist->title(); + return idx; +} + + void SourcesModel::onSourceChanged() { diff --git a/src/sourcetree/sourcesmodel.h b/src/sourcetree/sourcesmodel.h index 1f744ee57..9759ef9ba 100644 --- a/src/sourcetree/sourcesmodel.h +++ b/src/sourcetree/sourcesmodel.h @@ -44,14 +44,13 @@ public: Category = 1, - StaticPlaylist = 2, - NewStaticPlaylist = 3, + CategoryAdd = 2, + + StaticPlaylist = 3, AutomaticPlaylist = 4, Stations = 5, - NewStation = 6 - }; enum CategoryType { @@ -81,9 +80,14 @@ public: virtual Qt::DropActions supportedDropActions() const; virtual Qt::ItemFlags flags(const QModelIndex& index) const; - void appendItem( const Tomahawk::source_ptr& source ); + void appendItem( const Tomahawk::source_ptr& source ); bool removeItem( const Tomahawk::source_ptr& source ); + // HACK i don't like this + // SLOW DON'T USE IF YOU CAN AVOID IT + QModelIndex indexFromPlaylist( const Tomahawk::playlist_ptr& playlist ); + QModelIndex indexFromItem( SourceTreeItem* item ) const; + signals: void clicked( const QModelIndex& ); @@ -104,8 +108,6 @@ public slots: void onItemRowsRemovedDone(); private: SourceTreeItem* itemFromIndex( const QModelIndex& idx ) const; - QModelIndex indexFromItem( SourceTreeItem* item ) const; - Tomahawk::playlist_ptr playlistFromItem( SourceTreeItem* item ) const; int rowForItem( SourceTreeItem* item ) const; // QModelIndex indexForSource( Tomahawk::Source* source ) const; diff --git a/src/sourcetree/sourcetreeitem.cpp b/src/sourcetree/sourcetreeitem.cpp index 8f31325f7..da907bcc8 100644 --- a/src/sourcetree/sourcetreeitem.cpp +++ b/src/sourcetree/sourcetreeitem.cpp @@ -19,8 +19,11 @@ #include "playlist.h" #include "playlist/dynamic/DynamicPlaylist.h" -#include +#include "source.h" #include +#include "tomahawk/tomahawkapp.h" +#include +#include using namespace Tomahawk; @@ -30,6 +33,8 @@ SourceTreeItem::SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, Sou , m_parent( parent ) , m_model( model ) { +// connect( this, SIGNAL( selectRequest() ), m_model, SLOT( onItemSelectRequest() ) ); + connect( this, SIGNAL( beginChildRowsAdded( int,int ) ), m_model, SLOT( onItemRowsAddedBegin( int,int ) ) ); connect( this, SIGNAL( beginChildRowsRemoved( int,int ) ), m_model, SLOT( onItemRowsRemovedBegin( int,int ) ) ); connect( this, SIGNAL( childRowsAdded() ), m_model, SLOT( onItemRowsAddedDone() ) ); @@ -92,9 +97,8 @@ PlaylistItem::onPlaylistChanged() emit updated(); } - Qt::ItemFlags -PlaylistItem::flags() +PlaylistItem::flags() const { Qt::ItemFlags flags = SourceTreeItem::flags(); @@ -120,6 +124,49 @@ PlaylistItem::setLoaded( bool loaded ) m_loaded = loaded; } +bool +PlaylistItem::willAcceptDrag( const QMimeData* data ) const +{ + return !m_playlist.isNull() && m_playlist->author()->isLocal(); +} + + +bool +PlaylistItem::dropMimeData( const QMimeData* data, Qt::DropAction action ) +{ + if( data->hasFormat( "application/tomahawk.query.list" ) ) { + if ( !m_playlist.isNull() && m_playlist->author()->isLocal() ) { + + QByteArray itemData = data->data( "application/tomahawk.query.list" ); + QDataStream stream( &itemData, QIODevice::ReadOnly ); + QList< Tomahawk::query_ptr > queries; + + while ( !stream.atEnd() ) + { + qlonglong qptr; + stream >> qptr; + + Tomahawk::query_ptr* query = reinterpret_cast(qptr); + if ( query && !query->isNull() ) + { + qDebug() << "Dropped query item:" << query->data()->artist() << "-" << query->data()->track(); + queries << *query; + } + } + + qDebug() << "on playlist:" << m_playlist->title() << m_playlist->guid(); + + // TODO do we need to use this in the refactor? + // QString rev = item->currentlyLoadedPlaylistRevision( playlist->guid() ); + m_playlist->addEntries( queries, m_playlist->currentrevision() ); + + return true; + } + } + + return false; +} + /// Dynamic Playlist Item /* @@ -165,6 +212,98 @@ DynPlaylistItem::onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision revi setLoaded( true ); }*/ +/// CategoryAddItem + +CategoryAddItem::CategoryAddItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType type ) + : SourceTreeItem( model, parent, SourcesModel::CategoryAdd ) + , m_categoryType( type ) +{ + +} + +CategoryAddItem::~CategoryAddItem() +{ + +} + +QString +CategoryAddItem::text() const +{ + switch( m_categoryType ) { + case SourcesModel::PlaylistsCategory: + return tr( "New Playlist" ); + case SourcesModel::StationsCategory: + return tr( "New Station" ); + } + + return QString(); +} + +void +CategoryAddItem::activate() +{ + switch( m_categoryType ) { + case SourcesModel::PlaylistsCategory: + // only show if none is shown yet + if( !PlaylistManager::instance()->isNewPlaylistPageVisible() ) + PlaylistManager::instance()->show( new NewPlaylistWidget() ); + break; + case SourcesModel::StationsCategory: + // TODO + break; + } +} + +Qt::ItemFlags +CategoryAddItem::flags() const +{ + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QIcon +CategoryAddItem::icon() const +{ + return QIcon( RESPATH "images/list-add.png" ); +} + +// CategoryItem + +CategoryItem::CategoryItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType category, bool showAddItem ) + : SourceTreeItem( model, parent, SourcesModel::Category ) + , m_category( category ) + , m_addItem( 0 ) + , m_showAdd( showAddItem ) +{ + // in the constructor we're still being added to the parent, so we don't exist to have rows addded yet. so this is safe. +// beginRowsAdded( 0, 0 ); + if( m_showAdd ) { + m_addItem = new CategoryAddItem( model, this, m_category ); + appendChild( m_addItem ); + } +// endRowsAdded(); +} + +void +CategoryItem::insertItem( SourceTreeItem* item ) +{ + insertItems( QList< SourceTreeItem* >() << item ); +} + +void +CategoryItem::insertItems( QList< SourceTreeItem* > items ) +{ + // add the items to the category, and connect to the signals + int curCount = children().size(); + if( m_showAdd ) // if there's an add item, add it before that + curCount--; + beginRowsAdded( curCount, curCount + items.size() - 1 ); + foreach( SourceTreeItem* item, items ) { + int index = m_showAdd ? children().count() - 1 : children().count(); + insertChild( children().count() - 1, item ); + } + endRowsAdded(); +} + /// CollectionItem @@ -176,10 +315,10 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons return; } // create category item - m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory ); + m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source->isLocal() ); appendChild( m_playlists ); - m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory ); + m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source->isLocal() ); appendChild( m_stations ); // ugh :( we're being added by the model, no need to notify for added rows now @@ -187,6 +326,9 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons onPlaylistsAdded( source->collection()->playlists() ); m_playlists->blockSignals( false ); + // HACK to load only for now + source->collection()->dynamicPlaylists(); + connect( source->collection().data(), SIGNAL( playlistsAdded( QList ) ), SLOT( onPlaylistsAdded( QList ) ) ); connect( source->collection().data(), SIGNAL( playlistsDeleted( QList ) ), @@ -202,7 +344,7 @@ CollectionItem::source() const QString CollectionItem::text() const { - return m_source.isNull() ? "Super Collection" : m_source->friendlyName(); + return m_source.isNull() ? tr( "Super Collection" ) : m_source->friendlyName(); } void @@ -222,24 +364,21 @@ CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists ) if( playlists.isEmpty() ) return; - // add the items to the category, and connect to the signals - int curCount = m_playlists->children().size(); - // TODO add items to one-minus the end of the category. this leaves room for the [ + New Playlist ] item - m_playlists->beginRowsAdded( curCount, curCount + playlists.size() - 1 ); - + QList< SourceTreeItem* > items; foreach( const playlist_ptr& p, playlists ) { PlaylistItem* plItem = new PlaylistItem( model(), m_playlists, p ); - m_playlists->appendChild( plItem ); qDebug() << "Playlist added:" << p->title() << p->creator() << p->info(); p->loadRevision(); + items << plItem; } - m_playlists->endRowsAdded(); + m_playlists->insertItems( items ); } void CollectionItem::onPlaylistsDeleted( const QList< playlist_ptr >& playlists ) { + QList< SourceTreeItem* > items; foreach( const playlist_ptr& playlist, playlists ) { int curCount = m_playlists->children().count(); for( int i = 0; i < curCount; i++ ) { @@ -253,4 +392,3 @@ CollectionItem::onPlaylistsDeleted( const QList< playlist_ptr >& playlists ) } } } - diff --git a/src/sourcetree/sourcetreeitem.h b/src/sourcetree/sourcetreeitem.h index 90068a518..43cf5c81b 100644 --- a/src/sourcetree/sourcetreeitem.h +++ b/src/sourcetree/sourcetreeitem.h @@ -23,7 +23,9 @@ #include "playlist.h" #include "playlist/dynamic/DynamicPlaylist.h" #include "source.h" +#include +class QMimeData; class SourceTreeItem : public QObject { Q_OBJECT @@ -39,12 +41,16 @@ public: QList< SourceTreeItem* > children() const { return m_children; } void appendChild( SourceTreeItem* item ) { m_children.append( item ); } + void insertChild( int index, SourceTreeItem* item ) { m_children.insert( index, item ); } void removeChild( SourceTreeItem* item ) { m_children.removeAll( item ); } // varies depending on the type of the item virtual QString text() const { return QString(); } - virtual Qt::ItemFlags flags() { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; } + virtual Qt::ItemFlags flags() const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; } virtual void activate() {} + virtual QIcon icon() const { return QIcon(); } + virtual bool willAcceptDrag( const QMimeData* data ) const { return false; } + virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action ) { return false; } /// don't call me unless you are a sourcetreeitem. i prefer this to making everyone a friend void beginRowsAdded( int from, int num ) { emit beginChildRowsAdded( from, num ); } @@ -53,6 +59,7 @@ public: void endRowsRemoved() { emit childRowsRemoved(); } signals: void updated(); + void selectRequest(); void beginChildRowsAdded( int fromRow, int num ); void childRowsAdded(); @@ -67,12 +74,27 @@ private: SourcesModel* m_model; }; +class CategoryAddItem : public SourceTreeItem +{ + Q_OBJECT +public: + CategoryAddItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType type ); + ~CategoryAddItem(); + + virtual Qt::ItemFlags flags() const; + virtual QString text() const; + virtual void activate(); + virtual QIcon icon() const; + +private: + SourcesModel::CategoryType m_categoryType; +}; class CategoryItem : public SourceTreeItem { Q_OBJECT public: - CategoryItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType category ) : SourceTreeItem( model, parent, SourcesModel::Category ), m_category( category ) {} + CategoryItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::CategoryType category, bool showAddItem ); virtual QString text() const { switch( m_category ) @@ -85,15 +107,20 @@ public: return QString(); } virtual void activate(); - virtual Qt::ItemFlags flags() { return Qt::ItemIsEnabled; } + virtual Qt::ItemFlags flags() const { return Qt::ItemIsEnabled; } + + // inserts an item at the end, but before the category add item + void insertItem( SourceTreeItem* item ); + void insertItems( QList< SourceTreeItem* > item ); SourcesModel::CategoryType categoryType() { return m_category; } private: SourcesModel::CategoryType m_category; + CategoryAddItem* m_addItem; + bool m_showAdd; }; - class CollectionItem : public SourceTreeItem { Q_OBJECT @@ -101,9 +128,10 @@ public: CollectionItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::source_ptr& source ); virtual QString text() const; - Tomahawk::source_ptr source() const; virtual void activate(); + Tomahawk::source_ptr source() const; + private slots: void onPlaylistsAdded( const QList& playlists ); void onPlaylistsDeleted( const QList& playlists ); @@ -114,6 +142,7 @@ private: CategoryItem* m_playlists; CategoryItem* m_stations; }; + class PlaylistItem : public SourceTreeItem { Q_OBJECT @@ -122,8 +151,10 @@ public: virtual QString text() const; virtual Tomahawk::playlist_ptr playlist() const; - virtual Qt::ItemFlags flags(); + virtual Qt::ItemFlags flags() const; virtual void activate(); + virtual bool willAcceptDrag( const QMimeData* data ) const; + virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action ); protected: void setLoaded( bool loaded ); diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp index ebbe5b4eb..48c71c131 100644 --- a/src/sourcetree/sourcetreeview.cpp +++ b/src/sourcetree/sourcetreeview.cpp @@ -94,23 +94,25 @@ SourceTreeView::SourceTreeView( QWidget* parent ) header()->setStretchLastSection( false ); header()->setResizeMode( 0, QHeaderView::Stretch ); - connect( m_proxyModel, SIGNAL( clicked( QModelIndex ) ), SIGNAL( clicked( QModelIndex ) ) ); + connect( m_model, SIGNAL( clicked( QModelIndex ) ), SIGNAL( clicked( QModelIndex ) ) ); connect( this, SIGNAL( clicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) ); - - connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( onSelectionChanged() ) ); + connect( this, SIGNAL( expanded( QModelIndex ) ), this, SLOT( onItemExpanded( QModelIndex ) ) ); +// connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( onSelectionChanged() ) ); hideOfflineSources(); -// connect( PlaylistManager::instance(), SIGNAL( playlistActivated( Tomahawk::playlist_ptr ) ), -// SLOT( onPlaylistActivated( Tomahawk::playlist_ptr ) ) ); + connect( PlaylistManager::instance(), SIGNAL( playlistActivated( Tomahawk::playlist_ptr ) ), + SLOT( onPlaylistActivated( Tomahawk::playlist_ptr ) ) ); // connect( PlaylistManager::instance(), SIGNAL( dynamicPlaylistActivated( Tomahawk::dynplaylist_ptr ) ), // SLOT( onDynamicPlaylistActivated( Tomahawk::dynplaylist_ptr ) ) ); -// connect( PlaylistManager::instance(), SIGNAL( collectionActivated( Tomahawk::collection_ptr ) ), -// SLOT( onCollectionActivated( Tomahawk::collection_ptr ) ) ); -// connect( PlaylistManager::instance(), SIGNAL( superCollectionActivated() ), -// SLOT( onSuperCollectionActivated() ) ); -// connect( PlaylistManager::instance(), SIGNAL( tempPageActivated() ), -// SLOT( onTempPageActivated() ) ); + connect( PlaylistManager::instance(), SIGNAL( collectionActivated( Tomahawk::collection_ptr ) ), + SLOT( onCollectionActivated( Tomahawk::collection_ptr ) ) ); + connect( PlaylistManager::instance(), SIGNAL( superCollectionActivated() ), + SLOT( onSuperCollectionActivated() ) ); + connect( PlaylistManager::instance(), SIGNAL( tempPageActivated() ), + SLOT( onTempPageActivated() ) ); + connect( PlaylistManager::instance(), SIGNAL( newPlaylistActivated() ), + SLOT( onNewPlaylistPageActivated() ) ); } @@ -159,18 +161,19 @@ SourceTreeView::hideOfflineSources() m_proxyModel->hideOfflineSources(); } -/* + void SourceTreeView::onPlaylistActivated( const Tomahawk::playlist_ptr& playlist ) { - QModelIndex idx = m_proxyModel->mapFromSource( m_model->playlistToIndex( playlist ) ); + QModelIndex idx = m_proxyModel->mapFromSource( m_model->indexFromPlaylist( playlist ) ); if ( idx.isValid() ) { - setCurrentIndex( idx ); + selectionModel()->select( idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current ); +// setCurrentIndex( idx ); } } - +/* void SourceTreeView::onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist ) { @@ -179,28 +182,28 @@ SourceTreeView::onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& pla { setCurrentIndex( idx ); } -} +}*/ void SourceTreeView::onCollectionActivated( const Tomahawk::collection_ptr& collection ) { - QModelIndex idx = m_proxyModel->mapFromSource( m_model->collectionToIndex( collection ) ); - if ( idx.isValid() ) - { - setCurrentIndex( idx ); - } +// QModelIndex idx = m_proxyModel->mapFromSource( m_model->collectionToIndex( collection ) ); +// if ( idx.isValid() ) +// { +// setCurrentIndex( idx ); +// } } void SourceTreeView::onSuperCollectionActivated() { - QModelIndex idx = m_proxyModel->index( 0, 0 ); - if ( idx.isValid() ) - { - setCurrentIndex( idx ); - } +// QModelIndex idx = m_proxyModel->index( 0, 0 ); +// if ( idx.isValid() ) +// { +// setCurrentIndex( idx ); +// } } @@ -208,7 +211,13 @@ void SourceTreeView::onTempPageActivated() { clearSelection(); -} */ +} + +void +SourceTreeView::onNewPlaylistPageActivated() +{ + // nothing atm +} void @@ -222,6 +231,18 @@ SourceTreeView::onItemActivated( const QModelIndex& index ) } +void +SourceTreeView::onItemExpanded( const QModelIndex& idx ) +{ + // make sure to expand children nodes for collections + if( idx.data( SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::Collection ) { + for( int i = 0; i < model()->rowCount( idx ); i++ ) { + expand( model()->index( i, 0, idx ) ); + } + } +} + + void SourceTreeView::loadPlaylist() { @@ -322,14 +343,9 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event ) const QRect rect = visualRect( index ); m_dropRect = rect; - - if ( model()->data( index, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::StaticPlaylist ) - { - PlaylistItem* item = itemFromIndex< PlaylistItem >( index ); - playlist_ptr playlist = item->playlist(); - if ( !playlist.isNull() && playlist->author()->isLocal() ) - accept = true; - } + const SourceTreeItem* item = itemFromIndex< SourceTreeItem >( index ); + if( item->willAcceptDrag( event->mimeData() ) ) + accept = true; } else { m_dropRect = QRect(); } @@ -350,59 +366,6 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event ) void SourceTreeView::dropEvent( QDropEvent* event ) { - bool accept = false; - const QPoint pos = event->pos(); - const QModelIndex index = indexAt( pos ); - - if ( event->mimeData()->hasFormat( "application/tomahawk.query.list" ) ) - { - const QPoint pos = event->pos(); - const QModelIndex index = indexAt( pos ); - - if ( index.isValid() ) - { - if ( model()->data( index, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::StaticPlaylist ) - { - PlaylistItem* item = itemFromIndex< PlaylistItem >( index ); - playlist_ptr playlist = item->playlist(); - if ( !playlist.isNull() && playlist->author()->isLocal() ) - { - accept = true; - QByteArray itemData = event->mimeData()->data( "application/tomahawk.query.list" ); - QDataStream stream( &itemData, QIODevice::ReadOnly ); - QList queries; - - while ( !stream.atEnd() ) - { - qlonglong qptr; - stream >> qptr; - - Tomahawk::query_ptr* query = reinterpret_cast(qptr); - if ( query && !query->isNull() ) - { - qDebug() << "Dropped query item:" << query->data()->artist() << "-" << query->data()->track(); - queries << *query; - } - } - - qDebug() << "on playlist:" << playlist->title() << playlist->guid(); - - // TODO do we need to use this in the refactor? -// QString rev = item->currentlyLoadedPlaylistRevision( playlist->guid() ); - playlist->addEntries( queries, playlist->currentrevision() ); - } - } - } - - if ( accept ) - { - event->setDropAction( Qt::CopyAction ); - event->accept(); - } - else - event->ignore(); - } - QTreeView::dropEvent( event ); m_dragging = false; } diff --git a/src/sourcetree/sourcetreeview.h b/src/sourcetree/sourcetreeview.h index 87eda27a5..c63d69585 100644 --- a/src/sourcetree/sourcetreeview.h +++ b/src/sourcetree/sourcetreeview.h @@ -37,7 +37,6 @@ Q_OBJECT public: explicit SourceTreeView( QWidget* parent = 0 ); -public slots: void showOfflineSources(); void hideOfflineSources(); @@ -46,11 +45,15 @@ signals: void onOffline( const QModelIndex& index ); private slots: -// void onPlaylistActivated( const Tomahawk::playlist_ptr& playlist ); + void onPlaylistActivated( const Tomahawk::playlist_ptr& playlist ); // void onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist ); -// void onCollectionActivated( const Tomahawk::collection_ptr& collection ); -// void onSuperCollectionActivated(); -// void onTempPageActivated(); + + void onCollectionActivated( const Tomahawk::collection_ptr& collection ); + void onSuperCollectionActivated(); + void onTempPageActivated(); + void onNewPlaylistPageActivated(); + + void onItemExpanded( const QModelIndex& idx ); void onItemActivated( const QModelIndex& index );