diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e339fa9a2..a2a87fe2f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,8 +53,12 @@ ENDIF(LIBLASTFM_FOUND) SET( tomahawkSourcesGui ${tomahawkSourcesGui} sourcetree/sourcesmodel.cpp sourcetree/sourcesproxymodel.cpp - sourcetree/sourcetreeitem.cpp sourcetree/sourcetreeview.cpp + sourcetree/items/sourcetreeitem.cpp + sourcetree/items/collectionitem.cpp + sourcetree/items/playlistitems.cpp + sourcetree/items/categoryitems.cpp + sourcetree/items/genericpageitems.cpp transferview.cpp tomahawktrayicon.cpp @@ -89,8 +93,12 @@ ENDIF(LIBLASTFM_FOUND) SET( tomahawkHeadersGui ${tomahawkHeadersGui} sourcetree/sourcesmodel.h sourcetree/sourcesproxymodel.h - sourcetree/sourcetreeitem.h sourcetree/sourcetreeview.h + sourcetree/items/sourcetreeitem.h + sourcetree/items/collectionitem.h + sourcetree/items/playlistitems.h + sourcetree/items/categoryitems.h + sourcetree/items/genericpageitems.h transferview.h tomahawktrayicon.h diff --git a/src/libtomahawk/viewmanager.cpp b/src/libtomahawk/viewmanager.cpp index a62abc51e..bc1359461 100644 --- a/src/libtomahawk/viewmanager.cpp +++ b/src/libtomahawk/viewmanager.cpp @@ -413,10 +413,10 @@ ViewManager::showSuperCollection() return shown; } -void +Tomahawk::ViewPage* ViewManager::showWelcomePage() { - show( m_welcomeWidget ); + return show( m_welcomeWidget ); } diff --git a/src/libtomahawk/viewmanager.h b/src/libtomahawk/viewmanager.h index 04fefe35a..e3976717c 100644 --- a/src/libtomahawk/viewmanager.h +++ b/src/libtomahawk/viewmanager.h @@ -123,7 +123,7 @@ signals: public slots: Tomahawk::ViewPage* showSuperCollection(); - void showWelcomePage(); + Tomahawk::ViewPage* showWelcomePage(); void showCurrentTrack(); void historyBack(); diff --git a/src/sourcetree/items/categoryitems.cpp b/src/sourcetree/items/categoryitems.cpp new file mode 100644 index 000000000..1106ead7c --- /dev/null +++ b/src/sourcetree/items/categoryitems.cpp @@ -0,0 +1,136 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "categoryitems.h" + +#include "utils/tomahawkutils.h" +#include "tomahawk/tomahawkapp.h" +#include "widgets/newplaylistwidget.h" +#include "viewmanager.h" +#include "viewpage.h" + +using namespace Tomahawk; + +/// 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( !ViewManager::instance()->isNewPlaylistPageVisible() ) { + ViewPage* p = ViewManager::instance()->show( new NewPlaylistWidget() ); + model()->linkSourceItemToPage( this, p ); + } + break; + case SourcesModel::StationsCategory: + APP->mainWindow()->createStation(); + break; + } +} + +Qt::ItemFlags +CategoryAddItem::flags() const +{ + switch( m_categoryType ) + { + case SourcesModel::PlaylistsCategory: + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + case SourcesModel::StationsCategory: + default: + return Qt::ItemIsEnabled; + break; + } +} + +QIcon +CategoryAddItem::icon() const +{ + return QIcon( RESPATH "images/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 ); + } + // 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(); +} + + +void +CategoryItem::activate() +{ + if( m_category == SourcesModel::StationsCategory ) { + // TODO activate stations page + } +} \ No newline at end of file diff --git a/src/sourcetree/items/categoryitems.h b/src/sourcetree/items/categoryitems.h new file mode 100644 index 000000000..05fa7a8dd --- /dev/null +++ b/src/sourcetree/items/categoryitems.h @@ -0,0 +1,70 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef CATEGORY_ITEM_H +#define CATEGORY_ITEM_H + +#include "sourcetreeitem.h" + +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, bool showAddItem ); + + virtual QString text() const { + switch( m_category ) + { + case SourcesModel::PlaylistsCategory: + return tr( "Playlists" ); + case SourcesModel::StationsCategory: + return tr( "Stations" ); + } + return QString(); + } + virtual void activate(); + 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; +}; + + +#endif diff --git a/src/sourcetree/items/collectionitem.cpp b/src/sourcetree/items/collectionitem.cpp new file mode 100644 index 000000000..a2097def1 --- /dev/null +++ b/src/sourcetree/items/collectionitem.cpp @@ -0,0 +1,231 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "collectionitem.h" + +#include "utils/tomahawkutils.h" +#include "categoryitems.h" +#include "playlistitems.h" +#include "viewmanager.h" +#include "playlist.h" + +/// CollectionItem + +using namespace Tomahawk; + +CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, const Tomahawk::source_ptr& source ) + : SourceTreeItem( mdl, parent, SourcesModel::Collection ) + , m_source( source ) + , m_playlists( 0 ) + , m_stations( 0 ) +{ + if( m_source.isNull() ) { // super collection + return; + } + // create category items if there are playlists to show, or stations to show + QList< playlist_ptr > playlists = source->collection()->playlists(); + QList< dynplaylist_ptr > autoplaylists = source->collection()->autoPlaylists(); + QList< dynplaylist_ptr > stations = source->collection()->stations(); + + if( !playlists.isEmpty() || !autoplaylists.isEmpty() || source->isLocal() ) { + m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source->isLocal() ); + onPlaylistsAdded( playlists ); + onAutoPlaylistsAdded( autoplaylists ); + } + if( !stations.isEmpty() || source->isLocal() ) { + m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source->isLocal() ); + onStationsAdded( stations ); + } + + if( ViewManager::instance()->pageForCollection( source->collection() ) ) + model()->linkSourceItemToPage( this, ViewManager::instance()->pageForCollection( source->collection() ) ); + + // load auto playlists and stations! + + connect( source.data(), SIGNAL( stats( QVariantMap ) ), this, SIGNAL( updated() ) ); + connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), this, SIGNAL( updated() ) ); + connect( source.data(), SIGNAL( stateChanged() ), this, SIGNAL( updated() ) ); + connect( source.data(), SIGNAL( offline() ), this, SIGNAL( updated() ) ); + connect( source.data(), SIGNAL( online() ), this, SIGNAL( updated() ) ); + + connect( source->collection().data(), SIGNAL( playlistsAdded( QList ) ), + SLOT( onPlaylistsAdded( QList ) ), Qt::QueuedConnection ); + connect( source->collection().data(), SIGNAL( playlistsDeleted( QList ) ), + SLOT( onPlaylistsDeleted( QList ) ), Qt::QueuedConnection ); + + connect( source->collection().data(), SIGNAL( autoPlaylistsAdded( QList< Tomahawk::dynplaylist_ptr > ) ), + SLOT( onAutoPlaylistsAdded( QList ) ), Qt::QueuedConnection ); + connect( source->collection().data(), SIGNAL( autoPlaylistsDeleted( QList ) ), + SLOT( onAutoPlaylistsDeleted( QList ) ), Qt::QueuedConnection ); + + connect( source->collection().data(), SIGNAL( stationsAdded( QList ) ), + SLOT( onStationsAdded( QList ) ), Qt::QueuedConnection ); + connect( source->collection().data(), SIGNAL( stationsDeleted( QList ) ), + SLOT( onStationsDeleted( QList ) ), Qt::QueuedConnection ); +} + +Tomahawk::source_ptr +CollectionItem::source() const +{ + return m_source; +} + +QString +CollectionItem::text() const +{ + return m_source.isNull() ? tr( "Super Collection" ) : m_source->friendlyName(); +} + +void +CollectionItem::activate() +{ + if( source().isNull() ) { + ViewPage* p = ViewManager::instance()->showSuperCollection(); + model()->linkSourceItemToPage( this, p ); + } else { + ViewPage* p = ViewManager::instance()->show( source()->collection() ); + model()->linkSourceItemToPage( this, p ); + } +} + +QIcon +CollectionItem::icon() const +{ + if( m_source.isNull() ) + return QIcon( RESPATH "images/supercollection.png" ); + else + return QIcon( RESPATH "images/user-avatar.png" ); +} + +void +CollectionItem::playlistsAddedInternal( SourceTreeItem* parent, const QList< dynplaylist_ptr >& playlists ) +{ + QList< SourceTreeItem* > items; + int addOffset = playlists.first()->author()->isLocal() ? 1 : 0; + + int from = parent->children().count() - addOffset; + parent->beginRowsAdded( from, from + playlists.count() - 1 ); + foreach( const dynplaylist_ptr& p, playlists ) + { + DynamicPlaylistItem* plItem = new DynamicPlaylistItem( model(), parent, p, parent->children().count() - addOffset ); + qDebug() << "Dynamic Playlist added:" << p->title() << p->creator() << p->info(); + p->loadRevision(); + items << plItem; + } + parent->endRowsAdded(); +} + +template< typename T > +void +CollectionItem::playlistsDeletedInternal( SourceTreeItem* parent, const QList< T >& playlists ) +{ + Q_ASSERT( parent ); // How can we delete playlists if we have none? + QList< SourceTreeItem* > items; + foreach( const T& playlist, playlists ) { + int curCount = parent->children().count(); + for( int i = 0; i < curCount; i++ ) { + PlaylistItem* pl = qobject_cast< PlaylistItem* >( parent->children().at( i ) ); + if( pl && pl->playlist() == playlist ) { + parent->beginRowsRemoved( i, i ); + parent->removeChild( pl ); + parent->endRowsRemoved(); + break; + } + } + } +} + + +void +CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists ) +{ + if( playlists.isEmpty() ) + return; + + if( !m_playlists ) { // add the category too + int cur = children().count(); + beginRowsAdded( cur, cur ); + m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source()->isLocal() ); + endRowsAdded(); + } + + QList< SourceTreeItem* > items; + int addOffset = playlists.first()->author()->isLocal() ? 1 : 0; + + int from = m_playlists->children().count() - addOffset; + m_playlists->beginRowsAdded( from, from + playlists.count() - 1 ); + foreach( const playlist_ptr& p, playlists ) + { + PlaylistItem* plItem = new PlaylistItem( model(), m_playlists, p, m_playlists->children().count() - addOffset ); + qDebug() << "Playlist added:" << p->title() << p->creator() << p->info(); + p->loadRevision(); + items << plItem; + } + m_playlists->endRowsAdded(); +} + +void +CollectionItem::onPlaylistsDeleted( const QList< playlist_ptr >& playlists ) +{ + playlistsDeletedInternal( m_playlists, playlists ); +} + +void +CollectionItem::onAutoPlaylistsAdded( const QList< dynplaylist_ptr >& playlists ) +{ + if( playlists.isEmpty() ) + return; + + if( !m_playlists ) { // add the category too + int cur = children().count(); + beginRowsAdded( cur, cur ); + m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source()->isLocal() ); + endRowsAdded(); + } + + playlistsAddedInternal( m_playlists, playlists ); +} + +void +CollectionItem::onAutoPlaylistsDeleted( const QList< dynplaylist_ptr >& playlists ) +{ + if( !m_playlists ) + qDebug() << "NO playlist category item for a deleting playlist.."; + + playlistsDeletedInternal( m_playlists, playlists ); +} + +void +CollectionItem::onStationsAdded( const QList< dynplaylist_ptr >& stations ) +{ + if( stations.isEmpty() ) + return; + + if( !m_stations ) { // add the category too + int cur = children().count(); + beginRowsAdded( cur, cur ); + m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source()->isLocal() ); + endRowsAdded(); + } + + playlistsAddedInternal( m_stations, stations ); +} + +void +CollectionItem::onStationsDeleted( const QList< dynplaylist_ptr >& stations ) +{ + playlistsDeletedInternal( m_stations, stations ); +} diff --git a/src/sourcetree/items/collectionitem.h b/src/sourcetree/items/collectionitem.h new file mode 100644 index 000000000..37886f397 --- /dev/null +++ b/src/sourcetree/items/collectionitem.h @@ -0,0 +1,59 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef COLLECTION_ITEM_H +#define COLLECTION_ITEM_H + +#include "sourcetreeitem.h" + +class CategoryItem; + +class CollectionItem : public SourceTreeItem +{ + Q_OBJECT +public: + CollectionItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::source_ptr& source ); + + virtual QString text() const; + virtual void activate(); + virtual QIcon icon() const; + + Tomahawk::source_ptr source() const; + + CategoryItem* stationsCategory() const { return m_stations; } + CategoryItem* playlistsCategory() const { return m_playlists; } + void setStationsCategory( CategoryItem* item ) { m_stations = item; } + void setPlaylistsCategory( CategoryItem* item ) { m_playlists = item; } +private slots: + void onPlaylistsAdded( const QList& playlists ); + void onPlaylistsDeleted( const QList& playlists ); + void onAutoPlaylistsAdded( const QList& playlists ); + void onAutoPlaylistsDeleted( const QList& playlists ); + void onStationsAdded( const QList& stations ); + void onStationsDeleted( const QList& stations ); + +private: + void playlistsAddedInternal( SourceTreeItem* parent, const QList< Tomahawk::dynplaylist_ptr >& playlists ); + template< typename T > + void playlistsDeletedInternal( SourceTreeItem* parent, const QList< T >& playlists ); + + Tomahawk::source_ptr m_source; + CategoryItem* m_playlists; + CategoryItem* m_stations; +}; + + +#endif diff --git a/src/sourcetree/items/genericpageitems.cpp b/src/sourcetree/items/genericpageitems.cpp new file mode 100644 index 000000000..f4ae25279 --- /dev/null +++ b/src/sourcetree/items/genericpageitems.cpp @@ -0,0 +1,63 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "genericpageitems.h" + +#include "utils/tomahawkutils.h" +#include "viewmanager.h" + +using namespace Tomahawk; + +/// Generic page item +GenericPageItem::GenericPageItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, const QIcon& icon, boost::function< ViewPage* () > func ) + : SourceTreeItem( model, parent, SourcesModel::GenericPage ) + , m_icon( icon ) + , m_text( text ) + , m_func( func ) +{ + +} + +GenericPageItem::~GenericPageItem() +{ + +} + +void +GenericPageItem::activate() +{ + ViewPage* p = m_func(); + model()->linkSourceItemToPage( this, p ); +} + +QString +GenericPageItem::text() const +{ + return m_text; +} + +QIcon +GenericPageItem::icon() const +{ + return m_icon; +} + + +bool +GenericPageItem::willAcceptDrag(const QMimeData* data) const +{ + return false; +} diff --git a/src/sourcetree/items/genericpageitems.h b/src/sourcetree/items/genericpageitems.h new file mode 100644 index 000000000..6507d1142 --- /dev/null +++ b/src/sourcetree/items/genericpageitems.h @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef GENERIC_PAGE_ITEM_H +#define GENERIC_PAGE_ITEM_H + +#include "sourcetreeitem.h" + +#include "boost/function.hpp" +#include "boost/bind.hpp" + +// generic item that has some name, some text, and calls a certain slot when activated. badabing! +class GenericPageItem : public SourceTreeItem +{ + Q_OBJECT +public: + GenericPageItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, const QIcon& icon, boost::function func ); + virtual ~GenericPageItem(); + + virtual QString text() const; + virtual void activate(); + virtual bool willAcceptDrag( const QMimeData* data ) const; + virtual QIcon icon() const; + +signals: + void activated(); + +private: + QIcon m_icon; + QString m_text; + boost::function< Tomahawk::ViewPage*() > m_func; +}; + +#endif diff --git a/src/sourcetree/items/playlistitems.cpp b/src/sourcetree/items/playlistitems.cpp new file mode 100644 index 000000000..787822b7a --- /dev/null +++ b/src/sourcetree/items/playlistitems.cpp @@ -0,0 +1,260 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "playlistitems.h" + +#include "utils/tomahawkutils.h" +#include "viewmanager.h" +#include "playlist/dynamic/GeneratorInterface.h" +#include "categoryitems.h" +#include "collectionitem.h" + +#include +using namespace Tomahawk; + +/// PlaylistItem + +PlaylistItem::PlaylistItem( SourcesModel* mdl, SourceTreeItem* parent, const playlist_ptr& pl, int index ) + : SourceTreeItem( mdl, parent, SourcesModel::StaticPlaylist, index ) + , m_loaded( false ) + , m_playlist( pl ) +{ + connect( pl.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), + SLOT( onPlaylistLoaded( Tomahawk::PlaylistRevision ) ), Qt::QueuedConnection ); + connect( pl.data(), SIGNAL( changed() ), + SIGNAL( updated() ), Qt::QueuedConnection ); + + if( ViewManager::instance()->pageForPlaylist( pl ) ) + model()->linkSourceItemToPage( this, ViewManager::instance()->pageForPlaylist( pl ) ); +} + + +QString +PlaylistItem::text() const +{ + return m_playlist->title(); +} + +Tomahawk::playlist_ptr +PlaylistItem::playlist() const +{ + return m_playlist; +} +void +PlaylistItem::onPlaylistLoaded( Tomahawk::PlaylistRevision revision ) +{ + m_loaded = true; + emit updated(); +} + +void +PlaylistItem::onPlaylistChanged() +{ + emit updated(); +} + +Qt::ItemFlags +PlaylistItem::flags() const +{ + Qt::ItemFlags flags = SourceTreeItem::flags(); + + if( !m_loaded ) + flags &= !Qt::ItemIsEnabled; + + flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; + if( playlist()->author()->isLocal() ) + flags |= Qt::ItemIsEditable; + + return flags; +} + +void +PlaylistItem::activate() +{ + ViewPage* p = ViewManager::instance()->show( m_playlist ); + model()->linkSourceItemToPage( this, p ); +} + +void +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; +} + +QIcon +PlaylistItem::icon() const +{ + return QIcon( RESPATH "images/playlist-icon.png" ); +} + +bool +PlaylistItem::setData(const QVariant& v, bool role) +{ + if( m_playlist->author()->isLocal() ) { + m_playlist->rename( v.toString() ); + + return true; + } + return false; +} + +DynamicPlaylistItem::DynamicPlaylistItem( SourcesModel* mdl, SourceTreeItem* parent, const dynplaylist_ptr& pl, int index ) + : PlaylistItem( mdl, parent, pl.staticCast< Playlist >(), index ) + , m_dynplaylist( pl ) +{ + setRowType( m_dynplaylist->mode() == Static ? SourcesModel::AutomaticPlaylist : SourcesModel::Station ); + + connect( pl.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), + SLOT( onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision ) ), Qt::QueuedConnection ); + + if( ViewManager::instance()->pageForDynPlaylist( pl ) ) + model()->linkSourceItemToPage( this, ViewManager::instance()->pageForDynPlaylist( pl ) ); +} + +DynamicPlaylistItem::~DynamicPlaylistItem() +{ +} + +void +DynamicPlaylistItem::activate() +{ + ViewPage* p = ViewManager::instance()->show( m_dynplaylist ); + model()->linkSourceItemToPage( this, p ); +} + +void +DynamicPlaylistItem::onDynamicPlaylistLoaded( DynamicPlaylistRevision revision ) +{ + setLoaded( true ); + checkReparentHackNeeded( revision ); + // END HACK + emit updated(); +} + +void +DynamicPlaylistItem::checkReparentHackNeeded( const DynamicPlaylistRevision& revision ) +{ + // HACK HACK HACK workaround for an ugly hack where we have to be compatible with older tomahawks (pre-0.1.0) that created dynplaylists as OnDemand then changed them to Static if they were static. + // we need to reparent this playlist to the correct category :-/. + CategoryItem* cat = qobject_cast< CategoryItem* >( parent() ); + qDebug() << "with category" << cat; + if( cat ) qDebug() << "and cat type:" << cat->categoryType(); + if( cat ) { + CategoryItem* from = cat; + CategoryItem* to = 0; + if( cat->categoryType() == SourcesModel::PlaylistsCategory && revision.mode == OnDemand ) { // WRONG + CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() ); + to = col->stationsCategory(); + if( !to ) { // you have got to be fucking kidding me + int fme = col->children().count(); + col->beginRowsAdded( fme, fme ); + to = new CategoryItem( model(), col, SourcesModel::StationsCategory, false ); + col->appendChild( to ); // we f'ing know it's not local b/c we're not getting into this mess ourselves + col->endRowsAdded(); + col->setStationsCategory( to ); + } + } else if( cat->categoryType() == SourcesModel::StationsCategory && revision.mode == Static ) { // WRONG + CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() ); + to = col->playlistsCategory(); + qDebug() << "TRYING TO HACK TO:" << to; + if( !to ) { // you have got to be fucking kidding me + int fme = col->children().count(); + col->beginRowsAdded( fme, fme ); + to = new CategoryItem( model(), col, SourcesModel::PlaylistsCategory, false ); + col->appendChild( to ); // we f'ing know it's not local b/c we're not getting into this mess ourselves + col->endRowsAdded(); + col->setPlaylistsCategory( to ); + } + } + if( to ) { + qDebug() << "HACKING! moving dynamic playlist from" << from->text() << "to:" << to->text(); + // remove and add + int idx = from->children().indexOf( this ); + from->beginRowsRemoved( idx, idx ); + from->removeChild( this ); + from->endRowsRemoved(); + + idx = to->children().count(); + to->beginRowsAdded( idx, idx ); + to->appendChild( this ); + to->endRowsAdded(); + + setParentItem( to ); + } + } +} + + +dynplaylist_ptr +DynamicPlaylistItem::dynPlaylist() const +{ + return m_dynplaylist; +} + +QString +DynamicPlaylistItem::text() const +{ + return m_dynplaylist->title(); +} + +bool +DynamicPlaylistItem::willAcceptDrag( const QMimeData* data ) const +{ + return false; +} diff --git a/src/sourcetree/items/playlistitems.h b/src/sourcetree/items/playlistitems.h new file mode 100644 index 000000000..0e884f377 --- /dev/null +++ b/src/sourcetree/items/playlistitems.h @@ -0,0 +1,73 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef PLAYLIST_ITEM_H +#define PLAYLIST_ITEM_H + +#include "sourcetreeitem.h" +#include "playlist/dynamic/DynamicPlaylist.h" + +class PlaylistItem : public SourceTreeItem +{ + Q_OBJECT +public: + PlaylistItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::playlist_ptr& pl, int index = -1 ); + + virtual QString text() const; + virtual Tomahawk::playlist_ptr playlist() const; + virtual Qt::ItemFlags flags() const; + virtual void activate(); + virtual bool willAcceptDrag( 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); + +protected: + void setLoaded( bool loaded ); + +private slots: + void onPlaylistLoaded( Tomahawk::PlaylistRevision revision ); + void onPlaylistChanged(); + +private: + bool m_loaded; + Tomahawk::playlist_ptr m_playlist; +}; + +// can be a station or an auto playlist +class DynamicPlaylistItem : public PlaylistItem +{ + Q_OBJECT +public: + DynamicPlaylistItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::dynplaylist_ptr& pl, int index = -1 ); + virtual ~DynamicPlaylistItem(); + + virtual QString text() const; + Tomahawk::dynplaylist_ptr dynPlaylist() const; + virtual bool willAcceptDrag( const QMimeData* data ) const; + virtual void activate(); + +private slots: + void onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision revision ); + +private: + void checkReparentHackNeeded( const Tomahawk::DynamicPlaylistRevision& rev ); + + Tomahawk::dynplaylist_ptr m_dynplaylist; +}; + + +#endif diff --git a/src/sourcetree/items/sourcetreeitem.cpp b/src/sourcetree/items/sourcetreeitem.cpp new file mode 100644 index 000000000..f1169cc28 --- /dev/null +++ b/src/sourcetree/items/sourcetreeitem.cpp @@ -0,0 +1,48 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + + +#include "sourcetreeitem.h" + +using namespace Tomahawk; + +SourceTreeItem::SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::RowType thisType, int index ) + : QObject() + , m_type( thisType ) + , m_parent( parent ) + , m_model( model ) +{ + 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() ) ); + connect( this, SIGNAL( childRowsRemoved() ), m_model, SLOT( onItemRowsRemovedDone() ) ); + connect( this, SIGNAL( updated() ), m_model, SLOT( itemUpdated() ) ); + + if( !m_parent ) + return; + + // caller must call begin/endInsertRows + if( index < 0 ) + m_parent->appendChild( this ); + else + m_parent->insertChild( index, this ); +} + + +SourceTreeItem::~SourceTreeItem() +{ + qDeleteAll( m_children ); +} diff --git a/src/sourcetree/items/sourcetreeitem.h b/src/sourcetree/items/sourcetreeitem.h new file mode 100644 index 000000000..6122d9f07 --- /dev/null +++ b/src/sourcetree/items/sourcetreeitem.h @@ -0,0 +1,84 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + + +#ifndef SOURCETREEITEM_H +#define SOURCETREEITEM_H + +#include "sourcesmodel.h" +#include "typedefs.h" +#include "playlist.h" +#include "playlist/dynamic/DynamicPlaylist.h" +#include "source.h" +#include + +class QMimeData; +class SourceTreeItem : public QObject +{ + Q_OBJECT +public: + SourceTreeItem() : m_type( SourcesModel::Invalid ), m_parent( 0 ), m_model( 0 ) {} + SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::RowType thisType, int index = -1 ); // if index is -1, append at end of parent's child list + virtual ~SourceTreeItem(); + + // generic info used by the tree model + SourcesModel::RowType type() const { return m_type; } + SourceTreeItem* parent() const { return m_parent; } + SourcesModel* model() const { return m_model; } + + 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() 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; } + virtual bool setData( const QVariant& v, bool role ) { return false; } + + /// don't call me unless you are a sourcetreeitem. i prefer this to making everyone a friend + void beginRowsAdded( int from, int to ) { emit beginChildRowsAdded( from, to ); } + void endRowsAdded() { emit childRowsAdded(); } + void beginRowsRemoved( int from, int to ) { emit beginChildRowsRemoved( from, to ); } + void endRowsRemoved() { emit childRowsRemoved(); } + +signals: + void updated(); + + void beginChildRowsAdded( int fromRow, int toRow ); + void childRowsAdded(); + + void beginChildRowsRemoved( int fromRow, int toRow ); + void childRowsRemoved(); + +protected: + void setRowType( SourcesModel::RowType t ) { m_type = t; } + void setParentItem( SourceTreeItem* item ) { m_parent = item; } +private: + SourcesModel::RowType m_type; + + SourceTreeItem* m_parent; + QList< SourceTreeItem* > m_children; + SourcesModel* m_model; +}; + +Q_DECLARE_METATYPE( SourceTreeItem* ); + +#endif // SOURCETREEITEM_H diff --git a/src/sourcetree/sourcesmodel.cpp b/src/sourcetree/sourcesmodel.cpp index ddd2af04f..d68e21c24 100644 --- a/src/sourcetree/sourcesmodel.cpp +++ b/src/sourcetree/sourcesmodel.cpp @@ -18,7 +18,9 @@ #include "sourcetree/sourcesmodel.h" -#include "sourcetree/sourcetreeitem.h" +#include "sourcetree/items/sourcetreeitem.h" +#include "sourcetree/items/collectionitem.h" +#include "sourcetree/items/genericpageitems.h" #include "sourcelist.h" #include "playlist.h" #include "collection.h" @@ -26,6 +28,8 @@ #include "tomahawk/tomahawkapp.h" #include "viewmanager.h" +#include + #include #include @@ -40,8 +44,7 @@ SourcesModel::SourcesModel( QObject* parent ) appendItem( source_ptr() ); // add misc children of root node - GenericPageItem* recent = new GenericPageItem( this, m_rootItem->children().at( 0 ), tr( "Recently Played" ), QIcon( RESPATH "images/recently-played.png" ) ); - connect( recent, SIGNAL( activated() ), ViewManager::instance(), SLOT( showWelcomePage() ) ); + GenericPageItem* recent = new GenericPageItem( this, m_rootItem->children().at( 0 ), tr( "Recently Played" ), QIcon( RESPATH "images/recently-played.png" ), boost::bind( &ViewManager::showWelcomePage, ViewManager::instance() ) ); onSourcesAdded( SourceList::instance()->sources() ); @@ -388,16 +391,6 @@ SourcesModel::indexFromItem( SourceTreeItem* item ) const return idx; } - -playlist_ptr -SourcesModel::playlistFromItem( SourceTreeItem* item ) const -{ - Q_ASSERT( item ); - Q_ASSERT( item->type() == StaticPlaylist ); - - return dynamic_cast< PlaylistItem* >( item )->playlist(); -} - int SourcesModel::rowForItem( SourceTreeItem* item ) const { diff --git a/src/sourcetree/sourcesmodel.h b/src/sourcetree/sourcesmodel.h index accd8c40f..dba7d6dae 100644 --- a/src/sourcetree/sourcesmodel.h +++ b/src/sourcetree/sourcesmodel.h @@ -107,11 +107,7 @@ public slots: void onItemRowsRemovedDone(); private: SourceTreeItem* itemFromIndex( const QModelIndex& idx ) const; - Tomahawk::playlist_ptr playlistFromItem( SourceTreeItem* item ) const; int rowForItem( SourceTreeItem* item ) const; -// QModelIndex indexForSource( Tomahawk::Source* source ) const; -// QModelIndex indexForPlaylist( Tomahawk::Playlist* pl ) const; -// QModelIndex indexForCategory( const QModelIndex& sourceIndex, CategoryType type ); SourceTreeItem* m_rootItem; diff --git a/src/sourcetree/sourcesproxymodel.cpp b/src/sourcetree/sourcesproxymodel.cpp index 5e22dea1a..589d6474e 100644 --- a/src/sourcetree/sourcesproxymodel.cpp +++ b/src/sourcetree/sourcesproxymodel.cpp @@ -22,7 +22,7 @@ #include #include "sourcesmodel.h" -#include "sourcetree/sourcetreeitem.h" +#include "sourcetree/items/collectionitem.h" SourcesProxyModel::SourcesProxyModel( SourcesModel* model, QObject* parent ) diff --git a/src/sourcetree/sourcetreeitem.cpp b/src/sourcetree/sourcetreeitem.cpp deleted file mode 100644 index aa6a25e28..000000000 --- a/src/sourcetree/sourcetreeitem.cpp +++ /dev/null @@ -1,698 +0,0 @@ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - - -#include "sourcetreeitem.h" - -#include "playlist.h" -#include "playlist/dynamic/DynamicPlaylist.h" -#include "source.h" -#include "viewmanager.h" -#include "tomahawk/tomahawkapp.h" -#include "widgets/newplaylistwidget.h" - -#include - -using namespace Tomahawk; - -SourceTreeItem::SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::RowType thisType, int index ) - : QObject() - , m_type( thisType ) - , m_parent( parent ) - , m_model( model ) -{ - 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() ) ); - connect( this, SIGNAL( childRowsRemoved() ), m_model, SLOT( onItemRowsRemovedDone() ) ); - connect( this, SIGNAL( updated() ), m_model, SLOT( itemUpdated() ) ); - - if( !m_parent ) - return; - - // caller must call begin/endInsertRows - if( index < 0 ) - m_parent->appendChild( this ); - else - m_parent->insertChild( index, this ); -} - - -SourceTreeItem::~SourceTreeItem() -{ - qDeleteAll( m_children ); -} - - -/// Category item - -void -CategoryItem::activate() -{ - if( m_category == SourcesModel::StationsCategory ) { - // TODO activate stations page - } -} - - -/// PlaylistItem - -PlaylistItem::PlaylistItem( SourcesModel* mdl, SourceTreeItem* parent, const playlist_ptr& pl, int index ) - : SourceTreeItem( mdl, parent, SourcesModel::StaticPlaylist, index ) - , m_loaded( false ) - , m_playlist( pl ) -{ - connect( pl.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), - SLOT( onPlaylistLoaded( Tomahawk::PlaylistRevision ) ), Qt::QueuedConnection ); - connect( pl.data(), SIGNAL( changed() ), - SIGNAL( updated() ), Qt::QueuedConnection ); - - if( ViewManager::instance()->pageForPlaylist( pl ) ) - model()->linkSourceItemToPage( this, ViewManager::instance()->pageForPlaylist( pl ) ); -} - - -QString -PlaylistItem::text() const -{ - return m_playlist->title(); -} - -Tomahawk::playlist_ptr -PlaylistItem::playlist() const -{ - return m_playlist; -} -void -PlaylistItem::onPlaylistLoaded( Tomahawk::PlaylistRevision revision ) -{ - m_loaded = true; - emit updated(); -} - -void -PlaylistItem::onPlaylistChanged() -{ - emit updated(); -} - -Qt::ItemFlags -PlaylistItem::flags() const -{ - Qt::ItemFlags flags = SourceTreeItem::flags(); - - if( !m_loaded ) - flags &= !Qt::ItemIsEnabled; - - flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; - if( playlist()->author()->isLocal() ) - flags |= Qt::ItemIsEditable; - - return flags; -} - -void -PlaylistItem::activate() -{ - ViewPage* p = ViewManager::instance()->show( m_playlist ); - model()->linkSourceItemToPage( this, p ); -} - -void -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; -} - -QIcon -PlaylistItem::icon() const -{ - return QIcon( RESPATH "images/playlist-icon.png" ); -} - -bool -PlaylistItem::setData(const QVariant& v, bool role) -{ - if( m_playlist->author()->isLocal() ) { - m_playlist->rename( v.toString() ); - - return true; - } - return false; -} - -DynamicPlaylistItem::DynamicPlaylistItem( SourcesModel* mdl, SourceTreeItem* parent, const dynplaylist_ptr& pl, int index ) - : PlaylistItem( mdl, parent, pl.staticCast< Playlist >(), index ) - , m_dynplaylist( pl ) -{ - setRowType( m_dynplaylist->mode() == Static ? SourcesModel::AutomaticPlaylist : SourcesModel::Station ); - - connect( pl.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), - SLOT( onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision ) ), Qt::QueuedConnection ); - - if( ViewManager::instance()->pageForDynPlaylist( pl ) ) - model()->linkSourceItemToPage( this, ViewManager::instance()->pageForDynPlaylist( pl ) ); -} - -DynamicPlaylistItem::~DynamicPlaylistItem() -{ -} - -void -DynamicPlaylistItem::activate() -{ - ViewPage* p = ViewManager::instance()->show( m_dynplaylist ); - model()->linkSourceItemToPage( this, p ); -} - -void -DynamicPlaylistItem::onDynamicPlaylistLoaded( DynamicPlaylistRevision revision ) -{ - setLoaded( true ); - checkReparentHackNeeded( revision ); - // END HACK - emit updated(); -} - -void -DynamicPlaylistItem::checkReparentHackNeeded( const DynamicPlaylistRevision& revision ) -{ - // HACK HACK HACK workaround for an ugly hack where we have to be compatible with older tomahawks (pre-0.1.0) that created dynplaylists as OnDemand then changed them to Static if they were static. - // we need to reparent this playlist to the correct category :-/. - CategoryItem* cat = qobject_cast< CategoryItem* >( parent() ); - qDebug() << "with category" << cat; - if( cat ) qDebug() << "and cat type:" << cat->categoryType(); - if( cat ) { - CategoryItem* from = cat; - CategoryItem* to = 0; - if( cat->categoryType() == SourcesModel::PlaylistsCategory && revision.mode == OnDemand ) { // WRONG - CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() ); - to = col->stationsCategory(); - if( !to ) { // you have got to be fucking kidding me - int fme = col->children().count(); - col->beginRowsAdded( fme, fme ); - to = new CategoryItem( model(), col, SourcesModel::StationsCategory, false ); - col->appendChild( to ); // we f'ing know it's not local b/c we're not getting into this mess ourselves - col->endRowsAdded(); - col->setStationsCategory( to ); - } - } else if( cat->categoryType() == SourcesModel::StationsCategory && revision.mode == Static ) { // WRONG - CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() ); - to = col->playlistsCategory(); - qDebug() << "TRYING TO HACK TO:" << to; - if( !to ) { // you have got to be fucking kidding me - int fme = col->children().count(); - col->beginRowsAdded( fme, fme ); - to = new CategoryItem( model(), col, SourcesModel::PlaylistsCategory, false ); - col->appendChild( to ); // we f'ing know it's not local b/c we're not getting into this mess ourselves - col->endRowsAdded(); - col->setPlaylistsCategory( to ); - } - } - if( to ) { - qDebug() << "HACKING! moving dynamic playlist from" << from->text() << "to:" << to->text(); - // remove and add - int idx = from->children().indexOf( this ); - from->beginRowsRemoved( idx, idx ); - from->removeChild( this ); - from->endRowsRemoved(); - - idx = to->children().count(); - to->beginRowsAdded( idx, idx ); - to->appendChild( this ); - to->endRowsAdded(); - - setParentItem( to ); - } - } -} - - -dynplaylist_ptr -DynamicPlaylistItem::dynPlaylist() const -{ - return m_dynplaylist; -} - -QString -DynamicPlaylistItem::text() const -{ - return m_dynplaylist->title(); -} - -bool -DynamicPlaylistItem::willAcceptDrag( const QMimeData* data ) const -{ - return false; -} - - -/// Dynamic Playlist Item -/* -DynPlaylistItem::DynPlaylistItem( SourcesModel* mdl, SourceTreeItem* parent, const dynplaylist_ptr& pl ) - : PlaylistItem( mdl, parent, pl.staticCast< Playlist >() ) -{ - setLoaded( false ); - connect( pl.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision) ), - SLOT( onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision ) ), Qt::QueuedConnection ); - connect( pl.data(), SIGNAL( changed() ), - SIGNAL( updated() ), Qt::QueuedConnection ); -} - - -QString -DynPlaylistItem::text() -{ - return m_dynplaylist->title(); -} - -Tomahawk::playlist_ptr -DynPlaylistItem::playlist() const -{ - return m_dynplaylist.staticCast(); -} - -// Tomahawk::dynplaylist_ptr -// DynPlaylistItem::playlist() const -// { -// return m_dynplaylist; -// } - -void -DynPlaylistItem::activate() -{ - ViewManager::instance()->show( m_playlist ); -} - - -void -DynPlaylistItem::onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision revision ) -{ - 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( !ViewManager::instance()->isNewPlaylistPageVisible() ) { - ViewPage* p = ViewManager::instance()->show( new NewPlaylistWidget() ); - model()->linkSourceItemToPage( this, p ); - } - break; - case SourcesModel::StationsCategory: - APP->mainWindow()->createStation(); - break; - } -} - -Qt::ItemFlags -CategoryAddItem::flags() const -{ - switch( m_categoryType ) - { - case SourcesModel::PlaylistsCategory: - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; - case SourcesModel::StationsCategory: - default: - return Qt::ItemIsEnabled; - break; - } -} - -QIcon -CategoryAddItem::icon() const -{ - return QIcon( RESPATH "images/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 ); - } -// 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 - -CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, const Tomahawk::source_ptr& source ) - : SourceTreeItem( mdl, parent, SourcesModel::Collection ) - , m_source( source ) - , m_playlists( 0 ) - , m_stations( 0 ) -{ - if( m_source.isNull() ) { // super collection - return; - } - // create category items if there are playlists to show, or stations to show - QList< playlist_ptr > playlists = source->collection()->playlists(); - QList< dynplaylist_ptr > autoplaylists = source->collection()->autoPlaylists(); - QList< dynplaylist_ptr > stations = source->collection()->stations(); - - if( !playlists.isEmpty() || !autoplaylists.isEmpty() || source->isLocal() ) { - m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source->isLocal() ); - onPlaylistsAdded( playlists ); - onAutoPlaylistsAdded( autoplaylists ); - } - if( !stations.isEmpty() || source->isLocal() ) { - m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source->isLocal() ); - onStationsAdded( stations ); - } - - if( ViewManager::instance()->pageForCollection( source->collection() ) ) - model()->linkSourceItemToPage( this, ViewManager::instance()->pageForCollection( source->collection() ) ); - - // load auto playlists and stations! - - connect( source.data(), SIGNAL( stats( QVariantMap ) ), this, SIGNAL( updated() ) ); - connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), this, SIGNAL( updated() ) ); - connect( source.data(), SIGNAL( stateChanged() ), this, SIGNAL( updated() ) ); - connect( source.data(), SIGNAL( offline() ), this, SIGNAL( updated() ) ); - connect( source.data(), SIGNAL( online() ), this, SIGNAL( updated() ) ); - - connect( source->collection().data(), SIGNAL( playlistsAdded( QList ) ), - SLOT( onPlaylistsAdded( QList ) ), Qt::QueuedConnection ); - connect( source->collection().data(), SIGNAL( playlistsDeleted( QList ) ), - SLOT( onPlaylistsDeleted( QList ) ), Qt::QueuedConnection ); - - connect( source->collection().data(), SIGNAL( autoPlaylistsAdded( QList< Tomahawk::dynplaylist_ptr > ) ), - SLOT( onAutoPlaylistsAdded( QList ) ), Qt::QueuedConnection ); - connect( source->collection().data(), SIGNAL( autoPlaylistsDeleted( QList ) ), - SLOT( onAutoPlaylistsDeleted( QList ) ), Qt::QueuedConnection ); - - connect( source->collection().data(), SIGNAL( stationsAdded( QList ) ), - SLOT( onStationsAdded( QList ) ), Qt::QueuedConnection ); - connect( source->collection().data(), SIGNAL( stationsDeleted( QList ) ), - SLOT( onStationsDeleted( QList ) ), Qt::QueuedConnection ); -} - -Tomahawk::source_ptr -CollectionItem::source() const -{ - return m_source; -} - -QString -CollectionItem::text() const -{ - return m_source.isNull() ? tr( "Super Collection" ) : m_source->friendlyName(); -} - -void -CollectionItem::activate() -{ - if( source().isNull() ) { - ViewPage* p = ViewManager::instance()->showSuperCollection(); - model()->linkSourceItemToPage( this, p ); - } else { - ViewPage* p = ViewManager::instance()->show( source()->collection() ); - model()->linkSourceItemToPage( this, p ); - } -} - -QIcon -CollectionItem::icon() const -{ - if( m_source.isNull() ) - return QIcon( RESPATH "images/supercollection.png" ); - else - return QIcon( RESPATH "images/user-avatar.png" ); -} - -void -CollectionItem::playlistsAddedInternal( SourceTreeItem* parent, const QList< dynplaylist_ptr >& playlists ) -{ - QList< SourceTreeItem* > items; - int addOffset = playlists.first()->author()->isLocal() ? 1 : 0; - - int from = parent->children().count() - addOffset; - parent->beginRowsAdded( from, from + playlists.count() - 1 ); - foreach( const dynplaylist_ptr& p, playlists ) - { - DynamicPlaylistItem* plItem = new DynamicPlaylistItem( model(), parent, p, parent->children().count() - addOffset ); - qDebug() << "Dynamic Playlist added:" << p->title() << p->creator() << p->info(); - p->loadRevision(); - items << plItem; - } - parent->endRowsAdded(); -} - -template< typename T > -void -CollectionItem::playlistsDeletedInternal( SourceTreeItem* parent, const QList< T >& playlists ) -{ - Q_ASSERT( parent ); // How can we delete playlists if we have none? - QList< SourceTreeItem* > items; - foreach( const T& playlist, playlists ) { - int curCount = parent->children().count(); - for( int i = 0; i < curCount; i++ ) { - PlaylistItem* pl = qobject_cast< PlaylistItem* >( parent->children().at( i ) ); - if( pl && pl->playlist() == playlist ) { - parent->beginRowsRemoved( i, i ); - parent->removeChild( pl ); - parent->endRowsRemoved(); - break; - } - } - } -} - - -void -CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists ) -{ - if( playlists.isEmpty() ) - return; - - if( !m_playlists ) { // add the category too - int cur = children().count(); - beginRowsAdded( cur, cur ); - m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source()->isLocal() ); - endRowsAdded(); - } - - QList< SourceTreeItem* > items; - int addOffset = playlists.first()->author()->isLocal() ? 1 : 0; - - int from = m_playlists->children().count() - addOffset; - m_playlists->beginRowsAdded( from, from + playlists.count() - 1 ); - foreach( const playlist_ptr& p, playlists ) - { - PlaylistItem* plItem = new PlaylistItem( model(), m_playlists, p, m_playlists->children().count() - addOffset ); - qDebug() << "Playlist added:" << p->title() << p->creator() << p->info(); - p->loadRevision(); - items << plItem; - } - m_playlists->endRowsAdded(); -} - -void -CollectionItem::onPlaylistsDeleted( const QList< playlist_ptr >& playlists ) -{ - playlistsDeletedInternal( m_playlists, playlists ); -} - -void -CollectionItem::onAutoPlaylistsAdded( const QList< dynplaylist_ptr >& playlists ) -{ - if( playlists.isEmpty() ) - return; - - if( !m_playlists ) { // add the category too - int cur = children().count(); - beginRowsAdded( cur, cur ); - m_playlists = new CategoryItem( model(), this, SourcesModel::PlaylistsCategory, source()->isLocal() ); - endRowsAdded(); - } - - playlistsAddedInternal( m_playlists, playlists ); -} - -void -CollectionItem::onAutoPlaylistsDeleted( const QList< dynplaylist_ptr >& playlists ) -{ - if( !m_playlists ) - qDebug() << "NO playlist category item for a deleting playlist.."; - - playlistsDeletedInternal( m_playlists, playlists ); -} - -void -CollectionItem::onStationsAdded( const QList< dynplaylist_ptr >& stations ) -{ - if( stations.isEmpty() ) - return; - - if( !m_stations ) { // add the category too - int cur = children().count(); - beginRowsAdded( cur, cur ); - m_stations = new CategoryItem( model(), this, SourcesModel::StationsCategory, source()->isLocal() ); - endRowsAdded(); - } - - playlistsAddedInternal( m_stations, stations ); -} - -void -CollectionItem::onStationsDeleted( const QList< dynplaylist_ptr >& stations ) -{ - playlistsDeletedInternal( m_stations, stations ); -} - - -/// Generic page item -GenericPageItem::GenericPageItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, const QIcon& icon ) - : SourceTreeItem( model, parent, SourcesModel::GenericPage ) - , m_icon( icon ) - , m_text( text ) -{ - -} - -GenericPageItem::~GenericPageItem() -{ - -} - -void -GenericPageItem::activate() -{ - emit activated(); -} - -QString -GenericPageItem::text() const -{ - return m_text; -} - -QIcon -GenericPageItem::icon() const -{ - return m_icon; -} - - -bool -GenericPageItem::willAcceptDrag(const QMimeData* data) const -{ - return false; -} - diff --git a/src/sourcetree/sourcetreeitem.h b/src/sourcetree/sourcetreeitem.h deleted file mode 100644 index c955083de..000000000 --- a/src/sourcetree/sourcetreeitem.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - - -#ifndef SOURCETREEITEM_H -#define SOURCETREEITEM_H - -#include "sourcesmodel.h" -#include "typedefs.h" -#include "playlist.h" -#include "playlist/dynamic/DynamicPlaylist.h" -#include "source.h" -#include - -class QMimeData; -class SourceTreeItem : public QObject -{ - Q_OBJECT -public: - SourceTreeItem() : m_type( SourcesModel::Invalid ), m_parent( 0 ), m_model( 0 ) {} - SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, SourcesModel::RowType thisType, int index = -1 ); // if index is -1, append at end of parent's child list - virtual ~SourceTreeItem(); - - // generic info used by the tree model - SourcesModel::RowType type() const { return m_type; } - SourceTreeItem* parent() const { return m_parent; } - SourcesModel* model() const { return m_model; } - - 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() 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; } - virtual bool setData( const QVariant& v, bool role ) { return false; } - - /// don't call me unless you are a sourcetreeitem. i prefer this to making everyone a friend - void beginRowsAdded( int from, int to ) { emit beginChildRowsAdded( from, to ); } - void endRowsAdded() { emit childRowsAdded(); } - void beginRowsRemoved( int from, int to ) { emit beginChildRowsRemoved( from, to ); } - void endRowsRemoved() { emit childRowsRemoved(); } - -signals: - void updated(); - - void beginChildRowsAdded( int fromRow, int toRow ); - void childRowsAdded(); - - void beginChildRowsRemoved( int fromRow, int toRow ); - void childRowsRemoved(); - -protected: - void setRowType( SourcesModel::RowType t ) { m_type = t; } - void setParentItem( SourceTreeItem* item ) { m_parent = item; } -private: - SourcesModel::RowType m_type; - - SourceTreeItem* m_parent; - QList< SourceTreeItem* > m_children; - 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, bool showAddItem ); - - virtual QString text() const { - switch( m_category ) - { - case SourcesModel::PlaylistsCategory: - return tr( "Playlists" ); - case SourcesModel::StationsCategory: - return tr( "Stations" ); - } - return QString(); - } - virtual void activate(); - 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 -public: - CollectionItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::source_ptr& source ); - - virtual QString text() const; - virtual void activate(); - virtual QIcon icon() const; - - Tomahawk::source_ptr source() const; - - CategoryItem* stationsCategory() const { return m_stations; } - CategoryItem* playlistsCategory() const { return m_playlists; } - void setStationsCategory( CategoryItem* item ) { m_stations = item; } - void setPlaylistsCategory( CategoryItem* item ) { m_playlists = item; } -private slots: - void onPlaylistsAdded( const QList& playlists ); - void onPlaylistsDeleted( const QList& playlists ); - void onAutoPlaylistsAdded( const QList& playlists ); - void onAutoPlaylistsDeleted( const QList& playlists ); - void onStationsAdded( const QList& stations ); - void onStationsDeleted( const QList& stations ); - -private: - void playlistsAddedInternal( SourceTreeItem* parent, const QList< Tomahawk::dynplaylist_ptr >& playlists ); - template< typename T > - void playlistsDeletedInternal( SourceTreeItem* parent, const QList< T >& playlists ); - - Tomahawk::source_ptr m_source; - CategoryItem* m_playlists; - CategoryItem* m_stations; -}; - -class PlaylistItem : public SourceTreeItem -{ - Q_OBJECT -public: - PlaylistItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::playlist_ptr& pl, int index = -1 ); - - virtual QString text() const; - virtual Tomahawk::playlist_ptr playlist() const; - virtual Qt::ItemFlags flags() const; - virtual void activate(); - virtual bool willAcceptDrag( 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); - -protected: - void setLoaded( bool loaded ); - -private slots: - void onPlaylistLoaded( Tomahawk::PlaylistRevision revision ); - void onPlaylistChanged(); - -private: - bool m_loaded; - Tomahawk::playlist_ptr m_playlist; -}; - -// can be a station or an auto playlist -class DynamicPlaylistItem : public PlaylistItem -{ - Q_OBJECT -public: - DynamicPlaylistItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::dynplaylist_ptr& pl, int index = -1 ); - virtual ~DynamicPlaylistItem(); - - virtual QString text() const; - Tomahawk::dynplaylist_ptr dynPlaylist() const; - virtual bool willAcceptDrag( const QMimeData* data ) const; - virtual void activate(); - -private slots: - void onDynamicPlaylistLoaded( Tomahawk::DynamicPlaylistRevision revision ); - -private: - void checkReparentHackNeeded( const Tomahawk::DynamicPlaylistRevision& rev ); - - Tomahawk::dynplaylist_ptr m_dynplaylist; -}; - -// generic item that has some name, some text, and calls a certain slot when activated. badabing! -class GenericPageItem : public SourceTreeItem -{ - Q_OBJECT -public: - GenericPageItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, const QIcon& icon ); - virtual ~GenericPageItem(); - - virtual QString text() const; - virtual void activate(); - virtual bool willAcceptDrag( const QMimeData* data ) const; - virtual QIcon icon() const; - -signals: - void activated(); - -private: - QIcon m_icon; - QString m_text; -}; - -Q_DECLARE_METATYPE( SourceTreeItem* ); - -#endif // SOURCETREEITEM_H diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp index a934ecac3..5a7da0e73 100644 --- a/src/sourcetree/sourcetreeview.cpp +++ b/src/sourcetree/sourcetreeview.cpp @@ -22,7 +22,8 @@ #include "viewmanager.h" #include "sourcesproxymodel.h" #include "sourcelist.h" -#include "sourcetree/sourcetreeitem.h" +#include "sourcetree/items/playlistitems.h" +#include "sourcetree/items/collectionitem.h" #include "tomahawk/tomahawkapp.h" #include