diff --git a/data/images/back.png b/data/images/back.png new file mode 100644 index 000000000..88db1dc23 Binary files /dev/null and b/data/images/back.png differ diff --git a/data/images/forward.png b/data/images/forward.png new file mode 100644 index 000000000..3e0c42476 Binary files /dev/null and b/data/images/forward.png differ diff --git a/resources.qrc b/resources.qrc index fe25dfcaa..fc3705795 100644 --- a/resources.qrc +++ b/resources.qrc @@ -71,6 +71,8 @@ ./data/images/echonest_logo.png ./data/images/loading-animation.gif ./data/images/home.png +./data/images/back.png +./data/images/forward.png ./data/topbar-radiobuttons.css ./data/icons/tomahawk-icon-16x16.png ./data/icons/tomahawk-icon-32x32.png diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 6465a3ec6..d92d048ff 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -24,10 +24,10 @@ set( libSources query.cpp result.cpp source.cpp + viewpage.cpp sip/SipPlugin.cpp - audio/madtranscode.cpp audio/vorbistranscode.cpp audio/flactranscode.cpp @@ -161,6 +161,7 @@ set( libHeaders resolver.h result.h source.h + viewpage.h artist.h album.h diff --git a/src/libtomahawk/playlist/albummodel.cpp b/src/libtomahawk/playlist/albummodel.cpp index f22d389d8..c7efad856 100644 --- a/src/libtomahawk/playlist/albummodel.cpp +++ b/src/libtomahawk/playlist/albummodel.cpp @@ -225,6 +225,8 @@ AlbumModel::addCollection( const collection_ptr& collection ) SLOT( onAlbumsAdded( QList, Tomahawk::collection_ptr ) ) ); Database::instance()->enqueue( QSharedPointer( cmd ) ); + + m_title = tr( "All albums from %1" ).arg( collection->source()->friendlyName() ); } @@ -245,6 +247,8 @@ AlbumModel::addFilteredCollection( const collection_ptr& collection, unsigned in SLOT( onAlbumsAdded( QList, Tomahawk::collection_ptr ) ) ); Database::instance()->enqueue( QSharedPointer( cmd ) ); + + m_title = tr( "All albums by %1" ).arg( collection->source()->friendlyName() ); } diff --git a/src/libtomahawk/playlist/albummodel.h b/src/libtomahawk/playlist/albummodel.h index 445538b86..f25724ad4 100644 --- a/src/libtomahawk/playlist/albummodel.h +++ b/src/libtomahawk/playlist/albummodel.h @@ -40,9 +40,6 @@ public: virtual void removeIndex( const QModelIndex& index ); virtual void removeIndexes( const QList& indexes ); - virtual PlaylistInterface::RepeatMode repeatMode() const { return PlaylistInterface::NoRepeat; } - virtual bool shuffled() const { return false; } - virtual QMimeData* mimeData( const QModelIndexList& indexes ) const; virtual QStringList mimeTypes() const; virtual Qt::ItemFlags flags( const QModelIndex& index ) const; @@ -50,6 +47,11 @@ public: void addCollection( const Tomahawk::collection_ptr& collection ); void addFilteredCollection( const Tomahawk::collection_ptr& collection, unsigned int amount, DatabaseCommand_AllAlbums::SortOrder order ); + virtual QString title() const { return m_title; } + virtual QString description() const { return m_description; } + virtual void setTitle( const QString& title ) { m_title = title; } + virtual void setDescription( const QString& description ) { m_description = description; } + AlbumItem* itemFromIndex( const QModelIndex& index ) const { if ( index.isValid() ) @@ -81,6 +83,9 @@ private: QPersistentModelIndex m_currentIndex; AlbumItem* m_rootItem; QPixmap m_defaultCover; + + QString m_title; + QString m_description; }; #endif // ALBUMMODEL_H diff --git a/src/libtomahawk/playlist/albumproxymodel.h b/src/libtomahawk/playlist/albumproxymodel.h index d87c855db..3e694e2a6 100644 --- a/src/libtomahawk/playlist/albumproxymodel.h +++ b/src/libtomahawk/playlist/albumproxymodel.h @@ -33,7 +33,8 @@ public: virtual PlaylistInterface::RepeatMode repeatMode() const { return m_repeatMode; } virtual bool shuffled() const { return m_shuffled; } - + virtual PlaylistInterface::ViewMode viewMode() const { return PlaylistInterface::Album; } + signals: void repeatModeChanged( PlaylistInterface::RepeatMode mode ); void shuffleModeChanged( bool enabled ); diff --git a/src/libtomahawk/playlist/albumview.cpp b/src/libtomahawk/playlist/albumview.cpp index 9e954cc7f..83ecb28b9 100644 --- a/src/libtomahawk/playlist/albumview.cpp +++ b/src/libtomahawk/playlist/albumview.cpp @@ -10,8 +10,6 @@ #include "tomahawksettings.h" #include "albumitemdelegate.h" -#include "albummodel.h" -#include "albumproxymodel.h" #include "playlistmanager.h" using namespace Tomahawk; diff --git a/src/libtomahawk/playlist/albumview.h b/src/libtomahawk/playlist/albumview.h index a2445971f..d4616cd3c 100644 --- a/src/libtomahawk/playlist/albumview.h +++ b/src/libtomahawk/playlist/albumview.h @@ -4,12 +4,13 @@ #include #include +#include "albummodel.h" +#include "albumproxymodel.h" +#include "viewpage.h" + #include "dllmacro.h" -class AlbumModel; -class AlbumProxyModel; - -class DLLEXPORT AlbumView : public QListView +class DLLEXPORT AlbumView : public QListView, public Tomahawk::ViewPage { Q_OBJECT @@ -19,12 +20,22 @@ public: void setProxyModel( AlbumProxyModel* model ); - AlbumModel* model() { return m_model; } - AlbumProxyModel* proxyModel() { return m_proxyModel; } + AlbumModel* model() const { return m_model; } + AlbumProxyModel* proxyModel() const { return m_proxyModel; } // PlaylistItemDelegate* delegate() { return m_delegate; } void setModel( AlbumModel* model ); + virtual QWidget* widget() { return this; } + virtual PlaylistInterface* playlistInterface() const { return proxyModel(); } + + virtual QString title() const { return m_model->title(); } + virtual QString description() const { return m_model->description(); } + + virtual bool showModes() const { return true; } + + virtual bool jumpToCurrentTrack() { return false; } + public slots: void onItemActivated( const QModelIndex& index ); diff --git a/src/libtomahawk/playlist/collectionflatmodel.cpp b/src/libtomahawk/playlist/collectionflatmodel.cpp index 54c4bdc04..6e63feeba 100644 --- a/src/libtomahawk/playlist/collectionflatmodel.cpp +++ b/src/libtomahawk/playlist/collectionflatmodel.cpp @@ -60,6 +60,11 @@ CollectionFlatModel::addCollection( const collection_ptr& collection ) SLOT( onTracksAdded( QList, Tomahawk::collection_ptr ) ) ); connect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ), SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) ); + + if ( collection->source()->isLocal() ) + setTitle( tr( "Your Collection" ) ); + else + setTitle( tr( "Collection of %1" ).arg( collection->source()->friendlyName() ) ); } diff --git a/src/libtomahawk/playlist/collectionproxymodel.h b/src/libtomahawk/playlist/collectionproxymodel.h index e6ea9311d..af46be8c4 100644 --- a/src/libtomahawk/playlist/collectionproxymodel.h +++ b/src/libtomahawk/playlist/collectionproxymodel.h @@ -12,6 +12,8 @@ Q_OBJECT public: explicit CollectionProxyModel( QObject* parent = 0 ); + virtual PlaylistInterface::ViewMode viewMode() const { return PlaylistInterface::Flat; } + protected: bool lessThan( const QModelIndex& left, const QModelIndex& right ) const; }; diff --git a/src/libtomahawk/playlist/collectionview.cpp b/src/libtomahawk/playlist/collectionview.cpp index dc1490595..09b557611 100644 --- a/src/libtomahawk/playlist/collectionview.cpp +++ b/src/libtomahawk/playlist/collectionview.cpp @@ -45,7 +45,6 @@ CollectionView::setModel( TrackModel* model ) void CollectionView::dragEnterEvent( QDragEnterEvent* event ) { - qDebug() << Q_FUNC_INFO; event->ignore(); } @@ -94,3 +93,10 @@ CollectionView::onTrackCountChanged( unsigned int tracks ) else overlay()->hide(); } + + +bool +CollectionView::jumpToCurrentTrack() +{ + scrollTo( proxyModel()->currentItem(), QAbstractItemView::PositionAtCenter ); +} diff --git a/src/libtomahawk/playlist/collectionview.h b/src/libtomahawk/playlist/collectionview.h index 9fd3f3483..cddd1e98c 100644 --- a/src/libtomahawk/playlist/collectionview.h +++ b/src/libtomahawk/playlist/collectionview.h @@ -3,11 +3,14 @@ #include +#include "trackproxymodel.h" +#include "trackmodel.h" #include "trackview.h" +#include "viewpage.h" #include "dllmacro.h" -class DLLEXPORT CollectionView : public TrackView +class DLLEXPORT CollectionView : public TrackView, public Tomahawk::ViewPage { Q_OBJECT @@ -17,6 +20,16 @@ public: virtual void setModel( TrackModel* model ); + virtual QWidget* widget() { return this; } + virtual PlaylistInterface* playlistInterface() const { return proxyModel(); } + + virtual QString title() const { return model()->title(); } + virtual QString description() const { return model()->description(); } + + virtual bool showModes() const { return true; } + + virtual bool jumpToCurrentTrack(); + private slots: void onCustomContextMenu( const QPoint& pos ); void onTrackCountChanged( unsigned int tracks ); diff --git a/src/libtomahawk/playlist/dynamic/DynamicView.h b/src/libtomahawk/playlist/dynamic/DynamicView.h index d7ad8103e..26a63e4f1 100644 --- a/src/libtomahawk/playlist/dynamic/DynamicView.h +++ b/src/libtomahawk/playlist/dynamic/DynamicView.h @@ -45,7 +45,7 @@ public: void setDynamicWorking( bool working ); - virtual void paintEvent(QPaintEvent* event); + virtual void paintEvent( QPaintEvent* event ); public slots: void showMessageTimeout( const QString& title, const QString& body ); diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp index 8bea35d94..20ec27727 100644 --- a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp +++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp @@ -386,3 +386,9 @@ DynamicWidget::paintRoundedFilledRect( QPainter& p, QPalette& pal, QRect& r, qre p.setPen( pen ); p.drawRoundedRect( r, 10, 10 ); } + +bool +DynamicWidget::jumpToCurrentTrack() +{ + m_view->scrollTo( m_view->proxyModel()->currentItem(), QAbstractItemView::PositionAtCenter ); +} diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h index 17d31d882..e8653b2b7 100644 --- a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h +++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h @@ -20,8 +20,11 @@ #include #include "typedefs.h" +#include "viewpage.h" + #include "dynamic/DynamicPlaylist.h" #include "dynamic/DynamicControl.h" +#include "dynamic/DynamicModel.h" class LoadingSpinner; class QShowEvent; @@ -43,20 +46,15 @@ namespace Tomahawk class DynamicSetupWidget; - -class DynamicModel; - - class DynamicView; - class CollapsibleControls; /** * This class contains the dynamic playlist config and the playlist view itself */ -class DynamicWidget : public QWidget +class DynamicWidget : public QWidget, public Tomahawk::ViewPage { Q_OBJECT public: @@ -65,7 +63,7 @@ public: void loadDynamicPlaylist( const dynplaylist_ptr& playlist ); - PlaylistInterface* playlistInterface() const; + virtual PlaylistInterface* playlistInterface() const; virtual QSize sizeHint() const; virtual void resizeEvent( QResizeEvent* ); @@ -73,6 +71,14 @@ public: virtual void showEvent(QShowEvent* ); static void paintRoundedFilledRect( QPainter& p, QPalette& pal, QRect& r, qreal opacity = .95 ); + + virtual QWidget* widget() { return this; } + + virtual QString title() const { return m_model->title(); } + virtual QString description() const { return m_model->description(); } + + virtual bool jumpToCurrentTrack(); + public slots: void onRevisionLoaded( const Tomahawk::DynamicPlaylistRevision& rev ); void playlistTypeChanged(QString); @@ -94,6 +100,7 @@ private slots: void controlChanged( const Tomahawk::dyncontrol_ptr& control ); void layoutFloatingWidgets(); + private: dynplaylist_ptr m_playlist; QVBoxLayout* m_layout; diff --git a/src/libtomahawk/playlist/playlistmanager.cpp b/src/libtomahawk/playlist/playlistmanager.cpp index 40ee565d3..c2425aa78 100644 --- a/src/libtomahawk/playlist/playlistmanager.cpp +++ b/src/libtomahawk/playlist/playlistmanager.cpp @@ -30,6 +30,8 @@ #define FILTER_TIMEOUT 280 +using namespace Tomahawk; + PlaylistManager* PlaylistManager::s_instance = 0; @@ -44,14 +46,12 @@ PlaylistManager::PlaylistManager( QObject* parent ) : QObject( parent ) , m_widget( new QWidget() ) , m_welcomeWidget( new WelcomeWidget() ) - , m_currentInterface( 0 ) , m_currentMode( 0 ) , m_superCollectionVisible( true ) - , m_statsAvailable( false ) - , m_modesAvailable( false ) { s_instance = this; + setHistoryPosition( -1 ); m_widget->setLayout( new QVBoxLayout() ); m_topbar = new TopBar(); @@ -91,11 +91,8 @@ PlaylistManager::PlaylistManager( QObject* parent ) m_superAlbumView = new AlbumView(); m_superAlbumModel = new AlbumModel( m_superAlbumView ); m_superAlbumView->setModel( m_superAlbumModel ); - - m_stack->addWidget( m_superCollectionView ); - m_stack->addWidget( m_superAlbumView ); - - m_currentInterface = m_superCollectionView->proxyModel(); + m_superAlbumView->setFrameShape( QFrame::NoFrame ); + m_superAlbumView->setAttribute( Qt::WA_MacShowFocusRect, 0 ); m_stack->setContentsMargins( 0, 0, 0, 0 ); m_widget->setContentsMargins( 0, 0, 0, 0 ); @@ -106,34 +103,16 @@ PlaylistManager::PlaylistManager( QObject* parent ) connect( &m_filterTimer, SIGNAL( timeout() ), SLOT( applyFilter() ) ); connect( m_topbar, SIGNAL( filterTextChanged( QString ) ), - this, SLOT( setFilter( QString ) ) ); - - connect( this, SIGNAL( numSourcesChanged( unsigned int ) ), - m_topbar, SLOT( setNumSources( unsigned int ) ) ); - - connect( this, SIGNAL( numTracksChanged( unsigned int ) ), - m_topbar, SLOT( setNumTracks( unsigned int ) ) ); - - connect( this, SIGNAL( numArtistsChanged( unsigned int ) ), - m_topbar, SLOT( setNumArtists( unsigned int ) ) ); - - connect( this, SIGNAL( numShownChanged( unsigned int ) ), - m_topbar, SLOT( setNumShown( unsigned int ) ) ); + SLOT( setFilter( QString ) ) ); connect( m_topbar, SIGNAL( flatMode() ), - this, SLOT( setTableMode() ) ); - + SLOT( setTableMode() ) ); + connect( m_topbar, SIGNAL( artistMode() ), - this, SLOT( setTreeMode() ) ); - + SLOT( setTreeMode() ) ); + connect( m_topbar, SIGNAL( albumMode() ), - this, SLOT( setAlbumMode() ) ); - - connect( this, SIGNAL( statsAvailable( bool ) ), - m_topbar, SLOT( setStatsVisible( bool ) ) ); - - connect( this, SIGNAL( modesAvailable( bool ) ), - m_topbar, SLOT( setModesVisible( bool ) ) ); + SLOT( setAlbumMode() ) ); } @@ -153,11 +132,10 @@ PlaylistManager::queue() const bool PlaylistManager::show( const Tomahawk::playlist_ptr& playlist ) { - unlinkPlaylist(); - + PlaylistView* view; if ( !m_playlistViews.contains( playlist ) ) { - PlaylistView* view = new PlaylistView(); + view = new PlaylistView(); PlaylistModel* model = new PlaylistModel(); view->setModel( model ); view->setFrameShape( QFrame::NoFrame ); @@ -165,27 +143,15 @@ PlaylistManager::show( const Tomahawk::playlist_ptr& playlist ) model->loadPlaylist( playlist ); playlist->resolve(); - m_currentInterface = view->proxyModel(); m_playlistViews.insert( playlist, view ); - - m_stack->addWidget( view ); - m_stack->setCurrentWidget( view ); } else { - PlaylistView* view = m_playlistViews.value( playlist ); - m_stack->setCurrentWidget( view ); - m_currentInterface = view->proxyModel(); + view = m_playlistViews.value( playlist ); } - m_queueView->show(); - m_infobar->setCaption( playlist->title() ); - m_infobar->setDescription( tr( "A playlist by %1" ).arg( playlist->author()->isLocal() ? tr( "you" ) : playlist->author()->friendlyName() ) ); - + setPage( view ); m_superCollectionVisible = false; - m_statsAvailable = true; - m_modesAvailable = false; - linkPlaylist(); TomahawkSettings::instance()->appendRecentlyPlayedPlaylist( playlist ); @@ -197,34 +163,25 @@ PlaylistManager::show( const Tomahawk::playlist_ptr& playlist ) bool PlaylistManager::show( const Tomahawk::dynplaylist_ptr& playlist ) { - unlinkPlaylist(); - - if( !m_dynamicWidgets.contains( playlist ) ) + if ( !m_dynamicWidgets.contains( playlist ) ) { m_dynamicWidgets[ playlist ] = new Tomahawk::DynamicWidget( playlist, m_stack ); - m_stack->addWidget( m_dynamicWidgets[ playlist ] ); + playlist->resolve(); } - m_stack->setCurrentWidget( m_dynamicWidgets.value( playlist ) ); - m_currentInterface = m_dynamicWidgets.value( playlist )->playlistInterface(); + setPage( m_dynamicWidgets.value( playlist ) ); - m_infobar->setCaption( playlist->title() ); - m_infobar->setDescription( tr( "A playlist by %1" ).arg( playlist->author()->isLocal() ? tr( "you" ) : playlist->author()->friendlyName() ) ); - - if( playlist->mode() == Tomahawk::OnDemand ) + if ( playlist->mode() == Tomahawk::OnDemand ) m_queueView->hide(); - + else + m_queueView->show(); m_superCollectionVisible = false; - m_statsAvailable = true; - m_modesAvailable = false; - linkPlaylist(); TomahawkSettings::instance()->appendRecentlyPlayedPlaylist( playlist ); emit numSourcesChanged( SourceList::instance()->count() ); - return true; } @@ -232,39 +189,26 @@ PlaylistManager::show( const Tomahawk::dynplaylist_ptr& playlist ) bool PlaylistManager::show( const Tomahawk::artist_ptr& artist ) { - qDebug() << Q_FUNC_INFO << &artist << artist.data(); - unlinkPlaylist(); + PlaylistView* view; if ( !m_artistViews.contains( artist ) ) { - PlaylistView* view = new PlaylistView(); + view = new PlaylistView(); PlaylistModel* model = new PlaylistModel(); view->setModel( model ); view->setFrameShape( QFrame::NoFrame ); view->setAttribute( Qt::WA_MacShowFocusRect, 0 ); model->append( artist ); - m_currentInterface = view->proxyModel(); m_artistViews.insert( artist, view ); - - m_stack->addWidget( view ); - m_stack->setCurrentWidget( view ); } else { - PlaylistView* view = m_artistViews.value( artist ); - m_stack->setCurrentWidget( view ); - m_currentInterface = view->proxyModel(); + view = m_artistViews.value( artist ); } - m_queueView->show(); - m_infobar->setCaption( tr( "All tracks by %1" ).arg( artist->name() ) ); - m_infobar->setDescription( "" ); - + setPage( view ); m_superCollectionVisible = false; - m_statsAvailable = false; - m_modesAvailable = false; - linkPlaylist(); emit numSourcesChanged( 1 ); return true; @@ -274,39 +218,25 @@ PlaylistManager::show( const Tomahawk::artist_ptr& artist ) bool PlaylistManager::show( const Tomahawk::album_ptr& album ) { - qDebug() << Q_FUNC_INFO << &album << album.data(); - unlinkPlaylist(); - + PlaylistView* view; if ( !m_albumViews.contains( album ) ) { - PlaylistView* view = new PlaylistView(); + view = new PlaylistView(); PlaylistModel* model = new PlaylistModel(); view->setModel( model ); view->setFrameShape( QFrame::NoFrame ); view->setAttribute( Qt::WA_MacShowFocusRect, 0 ); model->append( album ); - m_currentInterface = view->proxyModel(); m_albumViews.insert( album, view ); - - m_stack->addWidget( view ); - m_stack->setCurrentWidget( view ); } else { - PlaylistView* view = m_albumViews.value( album ); - m_stack->setCurrentWidget( view ); - m_currentInterface = view->proxyModel(); + view = m_albumViews.value( album ); } - m_queueView->show(); - m_infobar->setCaption( tr( "All tracks on %1 by %2" ).arg( album->name() ).arg( album->artist()->name() ) ); - m_infobar->setDescription( "" ); - + setPage( view ); m_superCollectionVisible = false; - m_statsAvailable = false; - m_modesAvailable = false; - linkPlaylist(); emit numSourcesChanged( 1 ); return true; @@ -316,70 +246,52 @@ PlaylistManager::show( const Tomahawk::album_ptr& album ) bool PlaylistManager::show( const Tomahawk::collection_ptr& collection ) { - unlinkPlaylist(); - m_currentCollection = collection; if ( m_currentMode == 0 ) { + CollectionView* view; if ( !m_collectionViews.contains( collection ) ) { - CollectionView* view = new CollectionView(); + view = new CollectionView(); CollectionFlatModel* model = new CollectionFlatModel(); view->setModel( model ); view->setFrameShape( QFrame::NoFrame ); view->setAttribute( Qt::WA_MacShowFocusRect, 0 ); model->addCollection( collection ); - m_currentInterface = view->proxyModel(); m_collectionViews.insert( collection, view ); - - m_stack->addWidget( view ); - m_stack->setCurrentWidget( view ); } else { - CollectionView* view = m_collectionViews.value( collection ); - m_stack->setCurrentWidget( view ); - m_currentInterface = view->proxyModel(); + view = m_collectionViews.value( collection ); } + + setPage( view ); } if ( m_currentMode == 2 ) { + AlbumView* aview; if ( !m_collectionAlbumViews.contains( collection ) ) { - AlbumView* aview = new AlbumView(); + aview = new AlbumView(); AlbumModel* amodel = new AlbumModel( aview ); aview->setModel( amodel ); aview->setFrameShape( QFrame::NoFrame ); aview->setAttribute( Qt::WA_MacShowFocusRect, 0 ); amodel->addCollection( collection ); - m_currentInterface = aview->proxyModel(); m_collectionAlbumViews.insert( collection, aview ); - - m_stack->addWidget( aview ); - m_stack->setCurrentWidget( aview ); } else { - AlbumView* view = m_collectionAlbumViews.value( collection ); - m_stack->setCurrentWidget( view ); - m_currentInterface = view->proxyModel(); + aview = m_collectionAlbumViews.value( collection ); } + + setPage( aview ); } - m_infobar->setDescription( "" ); - if ( collection->source()->isLocal() ) - m_infobar->setCaption( tr( "Your Collection" ) ); - else - m_infobar->setCaption( tr( "Collection of %1" ).arg( collection->source()->friendlyName() ) ); - - m_queueView->show(); m_superCollectionVisible = false; - m_statsAvailable = ( m_currentMode == 0 ); - m_modesAvailable = true; - linkPlaylist(); emit numSourcesChanged( 1 ); return true; @@ -389,32 +301,19 @@ PlaylistManager::show( const Tomahawk::collection_ptr& collection ) bool PlaylistManager::show( const Tomahawk::source_ptr& source ) { - unlinkPlaylist(); - - m_currentInterface = 0; - + SourceInfoWidget* swidget; if ( !m_sourceViews.contains( source ) ) { - SourceInfoWidget* swidget = new SourceInfoWidget( source ); - m_currentInfoWidget = swidget; - m_stack->addWidget( m_currentInfoWidget ); + swidget = new SourceInfoWidget( source ); m_sourceViews.insert( source, swidget ); } else { - m_currentInfoWidget = m_sourceViews.value( source ); + swidget = m_sourceViews.value( source ); } - m_infobar->setCaption( tr( "Info about %1" ).arg( source->isLocal() ? tr( "Your Collection" ) : source->friendlyName() ) ); - m_infobar->setDescription( "" ); - - m_queueView->show(); - m_stack->setCurrentWidget( m_currentInfoWidget ); + setPage( swidget ); m_superCollectionVisible = false; - m_statsAvailable = false; - m_modesAvailable = false; - - linkPlaylist(); emit numSourcesChanged( 1 ); return true; @@ -422,28 +321,15 @@ PlaylistManager::show( const Tomahawk::source_ptr& source ) bool -PlaylistManager::show( QWidget* widget, const QString& title, const QString& desc, const QPixmap& pixmap ) +PlaylistManager::show( ViewPage* page ) { - unlinkPlaylist(); - - if ( m_stack->indexOf( widget ) < 0 ) + if ( m_stack->indexOf( page->widget() ) < 0 ) { - connect( widget, SIGNAL( destroyed( QWidget* ) ), SLOT( onWidgetDestroyed( QWidget* ) ) ); - m_stack->addWidget( widget ); + connect( page->widget(), SIGNAL( destroyed( QWidget* ) ), SLOT( onWidgetDestroyed( QWidget* ) ) ); } - m_stack->setCurrentWidget( widget ); - m_infobar->setCaption( title ); - m_infobar->setDescription( desc ); - m_infobar->setPixmap( pixmap.isNull() ? QPixmap( RESPATH "icons/tomahawk-icon-128x128.png" ) : pixmap ); - - m_queueView->show(); + setPage( page ); m_superCollectionVisible = false; - m_statsAvailable = false; - m_modesAvailable = false; - m_currentInterface = 0; - - linkPlaylist(); return true; } @@ -460,27 +346,21 @@ PlaylistManager::showSuperCollection() m_superCollectionFlatModel->addCollection( source->collection() ); m_superAlbumModel->addCollection( source->collection() ); } + + m_superCollectionFlatModel->setTitle( tr( "All available tracks" ) ); + m_superAlbumModel->setTitle( tr( "All available albums" ) ); } if ( m_currentMode == 0 ) { - m_stack->setCurrentWidget( m_superCollectionView ); - m_currentInterface = m_superCollectionView->proxyModel(); + setPage( m_superCollectionView ); } else if ( m_currentMode == 2 ) { - m_stack->setCurrentWidget( m_superAlbumView ); - m_currentInterface = m_superAlbumView->proxyModel(); + setPage( m_superAlbumView ); } - m_infobar->setCaption( tr( "Super Collection" ) ); - m_infobar->setDescription( tr( "All available tracks" ) ); - - m_queueView->show(); m_superCollectionVisible = true; - m_statsAvailable = ( m_currentMode == 0 ); - m_modesAvailable = true; - linkPlaylist(); emit numSourcesChanged( m_superCollections.count() ); return true; @@ -490,8 +370,7 @@ PlaylistManager::showSuperCollection() void PlaylistManager::showWelcomePage() { - qDebug() << Q_FUNC_INFO; - show( m_welcomeWidget, tr( "Welcome to Tomahawk!" ) ); + show( m_welcomeWidget ); } @@ -545,8 +424,7 @@ PlaylistManager::showQueue() if ( QThread::currentThread() != thread() ) { qDebug() << "Reinvoking in correct thread:" << Q_FUNC_INFO; - QMetaObject::invokeMethod( this, "showQueue", - Qt::QueuedConnection ); + QMetaObject::invokeMethod( this, "showQueue", Qt::QueuedConnection ); return; } @@ -560,8 +438,7 @@ PlaylistManager::hideQueue() if ( QThread::currentThread() != thread() ) { qDebug() << "Reinvoking in correct thread:" << Q_FUNC_INFO; - QMetaObject::invokeMethod( this, "hideQueue", - Qt::QueuedConnection ); + QMetaObject::invokeMethod( this, "hideQueue", Qt::QueuedConnection ); return; } @@ -569,6 +446,42 @@ PlaylistManager::hideQueue() } +void +PlaylistManager::historyBack() +{ + if ( m_historyPosition < 1 ) + return; + + showHistory( m_historyPosition - 1 ); +} + + +void +PlaylistManager::historyForward() +{ + if ( m_historyPosition >= m_pageHistory.count() - 1 ) + return; + + showHistory( m_historyPosition + 1 ); +} + + +void +PlaylistManager::showHistory( int historyPosition ) +{ + if ( historyPosition < 0 || historyPosition >= m_pageHistory.count() ) + { + qDebug() << "History position out of bounds!" << historyPosition << m_pageHistory.count(); + Q_ASSERT( false ); + return; + } + + setHistoryPosition( historyPosition ); + ViewPage* page = m_pageHistory.at( historyPosition ); + setPage( page, false ); +} + + void PlaylistManager::setFilter( const QString& filter ) { @@ -586,67 +499,111 @@ PlaylistManager::applyFilter() { qDebug() << Q_FUNC_INFO; - if ( m_currentInterface && m_currentInterface->filter() != m_filter ) - m_currentInterface->setFilter( m_filter ); + if ( currentPlaylistInterface() && currentPlaylistInterface()->filter() != m_filter ) + currentPlaylistInterface()->setFilter( m_filter ); +} + + +void +PlaylistManager::setPage( ViewPage* page, bool trackHistory ) +{ + unlinkPlaylist(); + + if ( !m_pageHistory.contains( page ) ) + { + m_stack->addWidget( page->widget() ); + } + else + { + if ( trackHistory ) + m_pageHistory.removeAll( page ); + } + + if ( trackHistory ) + { + m_pageHistory << page; + setHistoryPosition( m_pageHistory.count() - 1 ); + } + + if ( playlistForInterface( currentPlaylistInterface() ) ) + emit playlistActivated( playlistForInterface( currentPlaylistInterface() ) ); + if ( dynamicPlaylistForInterface( currentPlaylistInterface() ) ) + emit dynamicPlaylistActivated( dynamicPlaylistForInterface( currentPlaylistInterface() ) ); + if ( collectionForInterface( currentPlaylistInterface() ) ) + emit collectionActivated( collectionForInterface( currentPlaylistInterface() ) ); + if ( !currentPlaylistInterface() ) + emit tempPageActivated(); + + m_stack->setCurrentWidget( page->widget() ); + updateView(); } void PlaylistManager::unlinkPlaylist() { - if ( m_currentInterface ) + if ( currentPlaylistInterface() ) { - disconnect( m_currentInterface->object(), SIGNAL( sourceTrackCountChanged( unsigned int ) ), - this, SIGNAL( numTracksChanged( unsigned int ) ) ); + disconnect( currentPlaylistInterface()->object(), SIGNAL( sourceTrackCountChanged( unsigned int ) ), + this, SIGNAL( numTracksChanged( unsigned int ) ) ); - disconnect( m_currentInterface->object(), SIGNAL( trackCountChanged( unsigned int ) ), - this, SIGNAL( numShownChanged( unsigned int ) ) ); + disconnect( currentPlaylistInterface()->object(), SIGNAL( trackCountChanged( unsigned int ) ), + this, SIGNAL( numShownChanged( unsigned int ) ) ); - disconnect( m_currentInterface->object(), SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ), - this, SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ) ); + disconnect( currentPlaylistInterface()->object(), SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ), + this, SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ) ); - disconnect( m_currentInterface->object(), SIGNAL( shuffleModeChanged( bool ) ), - this, SIGNAL( shuffleModeChanged( bool ) ) ); + disconnect( currentPlaylistInterface()->object(), SIGNAL( shuffleModeChanged( bool ) ), + this, SIGNAL( shuffleModeChanged( bool ) ) ); } } void -PlaylistManager::linkPlaylist() +PlaylistManager::updateView() { - if ( m_currentInterface ) + if ( currentPlaylistInterface() ) { - connect( m_currentInterface->object(), SIGNAL( sourceTrackCountChanged( unsigned int ) ), - this, SIGNAL( numTracksChanged( unsigned int ) ) ); + connect( currentPlaylistInterface()->object(), SIGNAL( sourceTrackCountChanged( unsigned int ) ), + SIGNAL( numTracksChanged( unsigned int ) ) ); - connect( m_currentInterface->object(), SIGNAL( trackCountChanged( unsigned int ) ), - this, SIGNAL( numShownChanged( unsigned int ) ) ); + connect( currentPlaylistInterface()->object(), SIGNAL( trackCountChanged( unsigned int ) ), + SIGNAL( numShownChanged( unsigned int ) ) ); - connect( m_currentInterface->object(), SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ), - this, SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ) ); + connect( currentPlaylistInterface()->object(), SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ), + SIGNAL( repeatModeChanged( PlaylistInterface::RepeatMode ) ) ); - connect( m_currentInterface->object(), SIGNAL( shuffleModeChanged( bool ) ), - this, SIGNAL( shuffleModeChanged( bool ) ) ); + connect( currentPlaylistInterface()->object(), SIGNAL( shuffleModeChanged( bool ) ), + SIGNAL( shuffleModeChanged( bool ) ) ); - m_interfaceHistory.removeAll( m_currentInterface ); - m_interfaceHistory << m_currentInterface; + m_topbar->setFilter( currentPlaylistInterface()->filter() ); } - AudioEngine::instance()->setPlaylist( m_currentInterface ); - - if ( m_currentInterface && m_statsAvailable ) + if ( currentPage()->showStatsBar() && currentPlaylistInterface() ) { - m_topbar->setFilter( m_currentInterface->filter() ); - - emit numTracksChanged( m_currentInterface->unfilteredTrackCount() ); - emit numShownChanged( m_currentInterface->trackCount() ); - emit repeatModeChanged( m_currentInterface->repeatMode() ); - emit shuffleModeChanged( m_currentInterface->shuffled() ); - + emit numTracksChanged( currentPlaylistInterface()->unfilteredTrackCount() ); + emit numShownChanged( currentPlaylistInterface()->trackCount() ); + emit repeatModeChanged( currentPlaylistInterface()->repeatMode() ); + emit shuffleModeChanged( currentPlaylistInterface()->shuffled() ); + emit modeChanged( currentPlaylistInterface()->viewMode() ); } - emit statsAvailable( m_statsAvailable ); - emit modesAvailable( m_modesAvailable ); + if ( currentPage()->queueVisible() ) + m_queueView->show(); + else + m_queueView->hide(); + + emit statsAvailable( currentPage()->showStatsBar() ); + emit modesAvailable( currentPage()->showModes() ); + + if ( !currentPage()->showStatsBar() && !currentPage()->showModes() ) + m_topbar->setVisible( false ); + else + m_topbar->setVisible( true ); + + m_infobar->setCaption( currentPage()->title() ); + m_infobar->setDescription( currentPage()->description() ); + m_infobar->setPixmap( currentPage()->pixmap() ); } @@ -658,17 +615,20 @@ PlaylistManager::onWidgetDestroyed( QWidget* widget ) bool resetWidget = ( m_stack->currentWidget() == widget ); m_stack->removeWidget( widget ); - if ( resetWidget && m_interfaceHistory.count() ) + for ( int i = 0; i < m_pageHistory.count(); i++ ) { - unlinkPlaylist(); + ViewPage* page = m_pageHistory.at( i ); + if ( page->widget() == widget ) + { + m_pageHistory.removeAt( i ); + break; + } + } - m_currentInterface = m_interfaceHistory.last(); - qDebug() << "Last interface:" << m_currentInterface << m_currentInterface->widget(); - - if ( m_currentInterface->widget() ) - m_stack->setCurrentWidget( m_currentInterface->widget() ); - - linkPlaylist(); + if ( resetWidget ) + { + if ( m_pageHistory.count() ) + showHistory( m_pageHistory.count() - 1 ); } } @@ -676,16 +636,16 @@ PlaylistManager::onWidgetDestroyed( QWidget* widget ) void PlaylistManager::setRepeatMode( PlaylistInterface::RepeatMode mode ) { - if ( m_currentInterface ) - m_currentInterface->setRepeatMode( mode ); + if ( currentPlaylistInterface() ) + currentPlaylistInterface()->setRepeatMode( mode ); } void PlaylistManager::setShuffled( bool enabled ) { - if ( m_currentInterface ) - m_currentInterface->setShuffled( enabled ); + if ( currentPlaylistInterface() ) + currentPlaylistInterface()->setShuffled( enabled ); } @@ -709,20 +669,120 @@ PlaylistManager::createDynamicPlaylist( const Tomahawk::source_ptr& src, } +ViewPage* +PlaylistManager::pageForInterface( PlaylistInterface* interface ) const +{ + for ( int i = 0; i < m_pageHistory.count(); i++ ) + { + ViewPage* page = m_pageHistory.at( i ); + if ( page->playlistInterface() == interface ) + return page; + } + + return 0; +} + + +int +PlaylistManager::positionInHistory( ViewPage* page ) const +{ + for ( int i = 0; i < m_pageHistory.count(); i++ ) + { + if ( page == m_pageHistory.at( i ) ) + return i; + } + + return -1; +} + + +PlaylistInterface* +PlaylistManager::currentPlaylistInterface() const +{ + if ( currentPage() ) + return currentPage()->playlistInterface(); + else + return 0; +} + + +Tomahawk::ViewPage* +PlaylistManager::currentPage() const +{ + if ( m_historyPosition >= 0 ) + return m_pageHistory.at( m_historyPosition ); + else + return 0; +} + + +void +PlaylistManager::setHistoryPosition( int position ) +{ + m_historyPosition = position; + + emit historyBackAvailable( m_historyPosition > 0 ); + emit historyForwardAvailable( m_historyPosition < m_pageHistory.count() - 1 ); +} + + +Tomahawk::playlist_ptr +PlaylistManager::playlistForInterface( PlaylistInterface* interface ) const +{ + foreach ( PlaylistView* view, m_playlistViews.values() ) + { + if ( view->playlistInterface() == interface ) + { + return m_playlistViews.key( view ); + } + } + + return playlist_ptr(); +} + + +Tomahawk::dynplaylist_ptr +PlaylistManager::dynamicPlaylistForInterface( PlaylistInterface* interface ) const +{ + foreach ( DynamicWidget* view, m_dynamicWidgets.values() ) + { + if ( view->playlistInterface() == interface ) + { + return m_dynamicWidgets.key( view ); + } + } + + return dynplaylist_ptr(); +} + + +Tomahawk::collection_ptr +PlaylistManager::collectionForInterface( PlaylistInterface* interface ) const +{ + foreach ( CollectionView* view, m_collectionViews.values() ) + { + if ( view->playlistInterface() == interface ) + { + return m_collectionViews.key( view ); + } + } + foreach ( AlbumView* view, m_collectionAlbumViews.values() ) + { + if ( view->playlistInterface() == interface ) + { + return m_collectionAlbumViews.key( view ); + } + } + + return collection_ptr(); +} + + void PlaylistManager::showCurrentTrack() { - unlinkPlaylist(); - - m_currentInterface = AudioEngine::instance()->currentTrackPlaylist(); - - if ( m_currentInterface->widget() ) - m_stack->setCurrentWidget( m_currentInterface->widget() ); - - linkPlaylist(); - -/* if ( m_currentView && m_currentProxyModel ) - m_currentView->scrollTo( m_currentProxyModel->currentItem(), QAbstractItemView::PositionAtCenter );*/ + ViewPage* page = pageForInterface( AudioEngine::instance()->currentTrackPlaylist() ); + setPage( page ); } @@ -737,4 +797,4 @@ void PlaylistManager::onPauseClicked() { emit pauseClicked(); -} \ No newline at end of file +} diff --git a/src/libtomahawk/playlist/playlistmanager.h b/src/libtomahawk/playlist/playlistmanager.h index 3923b6f4c..722f7286e 100644 --- a/src/libtomahawk/playlist/playlistmanager.h +++ b/src/libtomahawk/playlist/playlistmanager.h @@ -7,6 +7,7 @@ #include "collection.h" #include "playlistinterface.h" +#include "viewpage.h" #include "dllmacro.h" @@ -27,7 +28,8 @@ class InfoBar; class TopBar; class WelcomeWidget; -namespace Tomahawk { +namespace Tomahawk +{ class DynamicWidget; } @@ -46,7 +48,10 @@ public: bool isSuperCollectionVisible() const { return true; } - PlaylistInterface* currentPlaylistInterface() const { return m_currentInterface; } + PlaylistInterface* currentPlaylistInterface() const; + Tomahawk::ViewPage* currentPage() const; + Tomahawk::ViewPage* pageForInterface( PlaylistInterface* interface ) const; + int positionInHistory( Tomahawk::ViewPage* page ) const; bool show( const Tomahawk::playlist_ptr& playlist ); bool show( const Tomahawk::dynplaylist_ptr& playlist ); @@ -55,7 +60,7 @@ public: bool show( const Tomahawk::collection_ptr& collection ); bool show( const Tomahawk::source_ptr& source ); - bool show( QWidget* widget, const QString& title = QString(), const QString& desc = QString(), const QPixmap& pixmap = QPixmap() ); + bool show( Tomahawk::ViewPage* page ); signals: void numSourcesChanged( unsigned int sources ); @@ -68,15 +73,29 @@ signals: void statsAvailable( bool b ); void modesAvailable( bool b ); + void modeChanged( PlaylistInterface::ViewMode mode ); void playClicked(); void pauseClicked(); + void historyBackAvailable( bool avail ); + void historyForwardAvailable( bool avail ); + + void tempPageActivated(); + void superCollectionActivated(); + void collectionActivated( const Tomahawk::collection_ptr& collection ); + void playlistActivated( const Tomahawk::playlist_ptr& playlist ); + void dynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist ); + public slots: bool showSuperCollection(); void showWelcomePage(); void showCurrentTrack(); - + + void historyBack(); + void historyForward(); + void showHistory( int historyPosition ); + void setTreeMode(); void setTableMode(); void setAlbumMode(); @@ -103,9 +122,15 @@ private slots: void onWidgetDestroyed( QWidget* widget ); private: + void setHistoryPosition( int position ); + void setPage( Tomahawk::ViewPage* page, bool trackHistory = true ); + void updateView(); void unlinkPlaylist(); - void linkPlaylist(); + Tomahawk::playlist_ptr playlistForInterface( PlaylistInterface* interface ) const; + Tomahawk::dynplaylist_ptr dynamicPlaylistForInterface( PlaylistInterface* interface ) const; + Tomahawk::collection_ptr collectionForInterface( PlaylistInterface* interface ) const; + QWidget* m_widget; InfoBar* m_infobar; TopBar* m_topbar; @@ -130,19 +155,15 @@ private: QHash< Tomahawk::album_ptr, PlaylistView* > m_albumViews; QHash< Tomahawk::playlist_ptr, PlaylistView* > m_playlistViews; QHash< Tomahawk::source_ptr, SourceInfoWidget* > m_sourceViews; - - PlaylistInterface* m_currentInterface; - QList m_interfaceHistory; - - QWidget* m_currentInfoWidget; + + QList m_pageHistory; + int m_historyPosition; Tomahawk::collection_ptr m_currentCollection; int m_currentMode; bool m_superCollectionVisible; - bool m_statsAvailable; - bool m_modesAvailable; - + QTimer m_filterTimer; QString m_filter; diff --git a/src/libtomahawk/playlist/playlistmodel.cpp b/src/libtomahawk/playlist/playlistmodel.cpp index 620cc240b..660e9a1a7 100644 --- a/src/libtomahawk/playlist/playlistmodel.cpp +++ b/src/libtomahawk/playlist/playlistmodel.cpp @@ -67,8 +67,10 @@ PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist, bool loadEn connect( playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), SLOT( onRevisionLoaded( Tomahawk::PlaylistRevision ) ) ); setReadOnly( !m_playlist->author()->isLocal() ); + setTitle( playlist->title() ); + setDescription( tr( "A playlist by %1" ).arg( playlist->author()->isLocal() ? tr( "you" ) : playlist->author()->friendlyName() ) ); - if( !loadEntries ) + if ( !loadEntries ) return; PlItem* plitem; diff --git a/src/libtomahawk/playlist/playlistview.cpp b/src/libtomahawk/playlist/playlistview.cpp index b2a367dfc..18abb0d01 100644 --- a/src/libtomahawk/playlist/playlistview.cpp +++ b/src/libtomahawk/playlist/playlistview.cpp @@ -4,7 +4,6 @@ #include #include -#include "playlist/playlistmodel.h" #include "playlist/playlistproxymodel.h" #include "widgets/overlaywidget.h" @@ -129,3 +128,10 @@ PlaylistView::onTrackCountChanged( unsigned int tracks ) else overlay()->hide(); } + + +bool +PlaylistView::jumpToCurrentTrack() +{ + scrollTo( proxyModel()->currentItem(), QAbstractItemView::PositionAtCenter ); +} diff --git a/src/libtomahawk/playlist/playlistview.h b/src/libtomahawk/playlist/playlistview.h index 1e7c80c70..26a543316 100644 --- a/src/libtomahawk/playlist/playlistview.h +++ b/src/libtomahawk/playlist/playlistview.h @@ -3,13 +3,16 @@ #include +#include "playlist/trackproxymodel.h" +#include "playlist/playlistmodel.h" #include "trackview.h" +#include "viewpage.h" #include "dllmacro.h" class PlaylistModel; -class DLLEXPORT PlaylistView : public TrackView +class DLLEXPORT PlaylistView : public TrackView, public Tomahawk::ViewPage { Q_OBJECT @@ -20,6 +23,14 @@ public: PlaylistModel* playlistModel() const { return m_model; } virtual void setModel( PlaylistModel* model ); + virtual QWidget* widget() { return this; } + virtual PlaylistInterface* playlistInterface() const { return proxyModel(); } + + virtual QString title() const { return playlistModel()->title(); } + virtual QString description() const { return m_model->description(); } + + virtual bool jumpToCurrentTrack(); + protected: void keyPressEvent( QKeyEvent* event ); diff --git a/src/libtomahawk/playlist/topbar/topbar.cpp b/src/libtomahawk/playlist/topbar/topbar.cpp index dd6705bfd..3aa584bf5 100644 --- a/src/libtomahawk/playlist/topbar/topbar.cpp +++ b/src/libtomahawk/playlist/topbar/topbar.cpp @@ -65,7 +65,28 @@ TopBar::TopBar( QWidget* parent ) setNumArtists( 0 ); setNumShown( 0 ); - ui->radioNormal->setChecked( true ); + onFlatMode(); + + connect( PlaylistManager::instance(), SIGNAL( numSourcesChanged( unsigned int ) ), + SLOT( setNumSources( unsigned int ) ) ); + + connect( PlaylistManager::instance(), SIGNAL( numTracksChanged( unsigned int ) ), + SLOT( setNumTracks( unsigned int ) ) ); + + connect( PlaylistManager::instance(), SIGNAL( numArtistsChanged( unsigned int ) ), + SLOT( setNumArtists( unsigned int ) ) ); + + connect( PlaylistManager::instance(), SIGNAL( numShownChanged( unsigned int ) ), + SLOT( setNumShown( unsigned int ) ) ); + + connect( PlaylistManager::instance(), SIGNAL( statsAvailable( bool ) ), + SLOT( setStatsVisible( bool ) ) ); + + connect( PlaylistManager::instance(), SIGNAL( modesAvailable( bool ) ), + SLOT( setModesVisible( bool ) ) ); + + connect( PlaylistManager::instance(), SIGNAL( modeChanged( PlaylistInterface::ViewMode ) ), + SLOT( onModeChanged( PlaylistInterface::ViewMode ) ) ); } @@ -238,3 +259,48 @@ TopBar::setFilter( const QString& filter ) { ui->filterEdit->setText( filter ); } + + +void +TopBar::onModeChanged( PlaylistInterface::ViewMode mode ) +{ + qDebug() << Q_FUNC_INFO << mode; + switch ( mode ) + { + case PlaylistInterface::Flat: + onFlatMode(); + break; + + case PlaylistInterface::Tree: + onArtistMode(); + break; + + case PlaylistInterface::Album: + onAlbumMode(); + break; + + default: + break; + } +} + + +void +TopBar::onFlatMode() +{ + ui->radioNormal->setChecked( true ); +} + + +void +TopBar::onArtistMode() +{ + ui->radioDetailed->setChecked( true ); +} + + +void +TopBar::onAlbumMode() +{ + ui->radioCloud->setChecked( true ); +} diff --git a/src/libtomahawk/playlist/topbar/topbar.h b/src/libtomahawk/playlist/topbar/topbar.h index f51b27e30..439768029 100644 --- a/src/libtomahawk/playlist/topbar/topbar.h +++ b/src/libtomahawk/playlist/topbar/topbar.h @@ -5,6 +5,7 @@ #include #include +#include "playlist/playlistmanager.h" #include "sourcelist.h" #include "dllmacro.h" @@ -42,6 +43,12 @@ public slots: void setFilter( const QString& filter ); +private slots: + void onModeChanged( PlaylistInterface::ViewMode mode ); + void onFlatMode(); + void onArtistMode(); + void onAlbumMode(); + protected: void changeEvent( QEvent* e ); void resizeEvent( QResizeEvent* e ); diff --git a/src/libtomahawk/playlist/trackmodel.h b/src/libtomahawk/playlist/trackmodel.h index ad43006be..f67b6631a 100644 --- a/src/libtomahawk/playlist/trackmodel.h +++ b/src/libtomahawk/playlist/trackmodel.h @@ -35,6 +35,11 @@ public: virtual bool isReadOnly() const { return m_readOnly; } + virtual QString title() const { return m_title; } + virtual void setTitle( const QString& title ) { m_title = title; } + virtual QString description() const { return m_description; } + virtual void setDescription( const QString& description ) { m_description = description; } + virtual int trackCount() const { return rowCount( QModelIndex() ); } virtual int rowCount( const QModelIndex& parent ) const; @@ -84,6 +89,9 @@ private slots: private: QPersistentModelIndex m_currentIndex; bool m_readOnly; + + QString m_title; + QString m_description; }; #endif // TRACKMODEL_H diff --git a/src/libtomahawk/playlist/trackview.cpp b/src/libtomahawk/playlist/trackview.cpp index c2a972ed1..bdc139773 100644 --- a/src/libtomahawk/playlist/trackview.cpp +++ b/src/libtomahawk/playlist/trackview.cpp @@ -73,7 +73,6 @@ void TrackView::setProxyModel( TrackProxyModel* model ) { m_proxyModel = model; - m_proxyModel->setWidget( this ); m_delegate = new PlaylistItemDelegate( this, m_proxyModel ); setItemDelegate( m_delegate ); diff --git a/src/libtomahawk/playlistinterface.h b/src/libtomahawk/playlistinterface.h index 7ef4fefd1..f8a56fa32 100644 --- a/src/libtomahawk/playlistinterface.h +++ b/src/libtomahawk/playlistinterface.h @@ -13,8 +13,9 @@ class DLLEXPORT PlaylistInterface { public: enum RepeatMode { NoRepeat, RepeatOne, RepeatAll }; - - PlaylistInterface( QObject* parent = 0 ) : m_widget( 0 ), m_object( parent ) {} + enum ViewMode { Unknown, Flat, Tree, Album }; + + PlaylistInterface( QObject* parent = 0 ) : m_object( parent ) {} virtual ~PlaylistInterface() {} virtual QList< Tomahawk::query_ptr > tracks() = 0; @@ -28,13 +29,11 @@ public: virtual PlaylistInterface::RepeatMode repeatMode() const = 0; virtual bool shuffled() const = 0; + virtual PlaylistInterface::ViewMode viewMode() const { return Unknown; } virtual QString filter() const { return m_filter; } virtual void setFilter( const QString& pattern ) { m_filter = pattern; } - QWidget* widget() const { return m_widget; } - void setWidget( QWidget* widget ) { m_widget = widget; } - QObject* object() const { return m_object; } public slots: @@ -48,7 +47,6 @@ signals: virtual void sourceTrackCountChanged( unsigned int tracks ) = 0; private: - QWidget* m_widget; QObject* m_object; QString m_filter; diff --git a/src/libtomahawk/viewpage.cpp b/src/libtomahawk/viewpage.cpp new file mode 100644 index 000000000..321bbbdf8 --- /dev/null +++ b/src/libtomahawk/viewpage.cpp @@ -0,0 +1,6 @@ +#include "viewpage.h" + +#include + +using namespace Tomahawk; + diff --git a/src/libtomahawk/viewpage.h b/src/libtomahawk/viewpage.h new file mode 100644 index 000000000..af087c669 --- /dev/null +++ b/src/libtomahawk/viewpage.h @@ -0,0 +1,38 @@ +#ifndef VIEWPAGE_H +#define VIEWPAGE_H + +#include + +#include "typedefs.h" +#include "playlistinterface.h" +#include "utils/tomahawkutils.h" + +#include "dllmacro.h" + +namespace Tomahawk +{ + +class DLLEXPORT ViewPage +{ +public: + ViewPage() {} + + virtual QWidget* widget() = 0; + virtual PlaylistInterface* playlistInterface() const = 0; + + virtual QString title() const = 0; + virtual QString description() const = 0; + virtual QPixmap pixmap() const { return QPixmap( RESPATH "icons/tomahawk-icon-128x128.png" ); } + + virtual bool showStatsBar() const { return true; } + virtual bool showModes() const { return false; } + virtual bool queueVisible() const { return true; } + + virtual bool jumpToCurrentTrack() = 0; + +private: +}; + +}; // ns + +#endif //VIEWPAGE_H diff --git a/src/libtomahawk/widgets/infowidgets/sourceinfowidget.cpp b/src/libtomahawk/widgets/infowidgets/sourceinfowidget.cpp index ad57103d2..80469499e 100644 --- a/src/libtomahawk/widgets/infowidgets/sourceinfowidget.cpp +++ b/src/libtomahawk/widgets/infowidgets/sourceinfowidget.cpp @@ -43,6 +43,8 @@ SourceInfoWidget::SourceInfoWidget( const Tomahawk::source_ptr& source, QWidget* m_recentAlbumModel = new AlbumModel( ui->recentAlbumView ); ui->recentAlbumView->setModel( m_recentAlbumModel ); m_recentAlbumModel->addFilteredCollection( source->collection(), 20, DatabaseCommand_AllAlbums::ModificationTime ); + + m_title = tr( "Info about %1" ).arg( source->isLocal() ? tr( "Your Collection" ) : source->friendlyName() ); } diff --git a/src/libtomahawk/widgets/infowidgets/sourceinfowidget.h b/src/libtomahawk/widgets/infowidgets/sourceinfowidget.h index 8d369a97e..f12fd942d 100644 --- a/src/libtomahawk/widgets/infowidgets/sourceinfowidget.h +++ b/src/libtomahawk/widgets/infowidgets/sourceinfowidget.h @@ -6,6 +6,7 @@ #include "album.h" #include "result.h" #include "playlistinterface.h" +#include "viewpage.h" #include "dllmacro.h" @@ -18,7 +19,7 @@ namespace Ui class SourceInfoWidget; } -class DLLEXPORT SourceInfoWidget : public QWidget +class DLLEXPORT SourceInfoWidget : public QWidget, public Tomahawk::ViewPage { Q_OBJECT @@ -26,6 +27,16 @@ public: SourceInfoWidget( const Tomahawk::source_ptr& source, QWidget* parent = 0 ); ~SourceInfoWidget(); + virtual QWidget* widget() { return this; } + virtual PlaylistInterface* playlistInterface() const { return 0; } + + virtual QString title() const { return m_title; } + virtual QString description() const { return m_description; } + + virtual bool showStatsBar() const { return false; } + + virtual bool jumpToCurrentTrack() { return false; } + protected: void changeEvent( QEvent* e ); @@ -38,6 +49,9 @@ private: CollectionFlatModel* m_recentCollectionModel; PlaylistModel* m_historyModel; AlbumModel* m_recentAlbumModel; + + QString m_title; + QString m_description; }; #endif // SOURCEINFOWIDGET_H diff --git a/src/libtomahawk/widgets/newplaylistwidget.h b/src/libtomahawk/widgets/newplaylistwidget.h index f19590aa7..dfe54a988 100644 --- a/src/libtomahawk/widgets/newplaylistwidget.h +++ b/src/libtomahawk/widgets/newplaylistwidget.h @@ -7,6 +7,7 @@ #include "album.h" #include "result.h" #include "playlistinterface.h" +#include "viewpage.h" #include "dllmacro.h" @@ -18,7 +19,7 @@ namespace Ui class NewPlaylistWidget; } -class DLLEXPORT NewPlaylistWidget : public QWidget +class DLLEXPORT NewPlaylistWidget : public QWidget, public Tomahawk::ViewPage { Q_OBJECT @@ -26,6 +27,16 @@ public: NewPlaylistWidget( QWidget* parent = 0 ); ~NewPlaylistWidget(); + virtual QWidget* widget() { return this; } + virtual PlaylistInterface* playlistInterface() const { return 0; } + + virtual QString title() const { return tr( "Create a new playlist" ); } + virtual QString description() const { return QString(); } + + virtual bool showStatsBar() const { return false; } + + virtual bool jumpToCurrentTrack() { return false; } + protected: void changeEvent( QEvent* e ); diff --git a/src/libtomahawk/widgets/newplaylistwidget.ui b/src/libtomahawk/widgets/newplaylistwidget.ui index 8b30f4780..6a2701ee8 100644 --- a/src/libtomahawk/widgets/newplaylistwidget.ui +++ b/src/libtomahawk/widgets/newplaylistwidget.ui @@ -11,28 +11,11 @@ - - - - - 20 - 75 - true - - - - Create A New Playlist - - - false - - - - 14 + 13 @@ -54,7 +37,7 @@ - 14 + 13 @@ -69,7 +52,7 @@ - 14 + 13 diff --git a/src/libtomahawk/widgets/welcomewidget.h b/src/libtomahawk/widgets/welcomewidget.h index 79f700448..9d14859e8 100644 --- a/src/libtomahawk/widgets/welcomewidget.h +++ b/src/libtomahawk/widgets/welcomewidget.h @@ -9,6 +9,7 @@ #include "playlist.h" #include "result.h" +#include "viewpage.h" #include "utils/tomahawkutils.h" @@ -73,7 +74,7 @@ private: }; -class DLLEXPORT WelcomeWidget : public QWidget +class DLLEXPORT WelcomeWidget : public QWidget, public Tomahawk::ViewPage { Q_OBJECT @@ -81,6 +82,16 @@ public: WelcomeWidget( QWidget* parent = 0 ); ~WelcomeWidget(); + virtual QWidget* widget() { return this; } + virtual PlaylistInterface* playlistInterface() const { return 0; } + + virtual QString title() const { return tr( "Welcome to Tomahawk" ); } + virtual QString description() const { return QString(); } + + virtual bool showStatsBar() const { return false; } + + virtual bool jumpToCurrentTrack() { return false; } + protected: void changeEvent( QEvent* e ); diff --git a/src/sip/jabber/jabber_p.cpp b/src/sip/jabber/jabber_p.cpp index a891973a9..cf090c107 100644 --- a/src/sip/jabber/jabber_p.cpp +++ b/src/sip/jabber/jabber_p.cpp @@ -526,7 +526,7 @@ Jabber_p::handleRosterPresence( const RosterItem& item, const std::string& resou // convert to QString to get proper regex support QString res( jid.resource().c_str() ); QRegExp regex( "tomahawk\\d+" ); - if( res != "tomahawk-tomahawk" && !res.contains( regex ) ) + if( res != "tomahawk-tomahawk" && !res.startsWith( "tomahawk" ) ) { //qDebug() << "not considering resource of" << res; // Disco them to check if they are tomahawk-capable diff --git a/src/sourcetree/sourcesmodel.cpp b/src/sourcetree/sourcesmodel.cpp index a84c7da7a..e2a95de0c 100644 --- a/src/sourcetree/sourcesmodel.cpp +++ b/src/sourcetree/sourcesmodel.cpp @@ -58,7 +58,8 @@ SourcesModel::flags( const QModelIndex& index ) const playlist_ptr playlist = indexToPlaylist( index ); if ( !playlist.isNull() && playlist->author()->isLocal() ) defaultFlags |= Qt::ItemIsEditable; - } else if ( indexType( index ) == DynamicPlaylistSource ) + } + else if ( indexType( index ) == DynamicPlaylistSource ) { dynplaylist_ptr playlist = indexToDynamicPlaylist( index ); if ( !playlist.isNull() && playlist->author()->isLocal() ) @@ -261,6 +262,75 @@ SourcesModel::indexToTreeItem( const QModelIndex& index ) } +QModelIndex +SourcesModel::playlistToIndex( const Tomahawk::playlist_ptr& playlist ) +{ + for ( int i = 0; i < rowCount(); i++ ) + { + QModelIndex pidx = index( i, 0 ); + + for ( int j = 0; j < rowCount( pidx ); j++ ) + { + QModelIndex idx = index( j, 0, pidx ); + SourcesModel::SourceType type = SourcesModel::indexType( idx ); + + if ( type == SourcesModel::PlaylistSource ) + { + playlist_ptr p = SourcesModel::indexToPlaylist( idx ); + if ( playlist.data() == p.data() ) + return idx; + } + } + } + + return QModelIndex(); +} + + +QModelIndex +SourcesModel::dynamicPlaylistToIndex( const Tomahawk::dynplaylist_ptr& playlist ) +{ + for ( int i = 0; i < rowCount(); i++ ) + { + QModelIndex pidx = index( i, 0 ); + + for ( int j = 0; j < rowCount( pidx ); j++ ) + { + QModelIndex idx = index( j, 0, pidx ); + SourcesModel::SourceType type = SourcesModel::indexType( idx ); + + if ( type == SourcesModel::DynamicPlaylistSource ) + { + playlist_ptr p = SourcesModel::indexToDynamicPlaylist( idx ); + if ( playlist.data() == p.data() ) + return idx; + } + } + } + + return QModelIndex(); +} + + +QModelIndex +SourcesModel::collectionToIndex( const Tomahawk::collection_ptr& collection ) +{ + for ( int i = 0; i < rowCount(); i++ ) + { + QModelIndex idx = index( i, 0 ); + SourcesModel::SourceType type = SourcesModel::indexType( idx ); + if ( type == SourcesModel::CollectionSource ) + { + SourceTreeItem* sti = SourcesModel::indexToTreeItem( idx ); + if ( sti && !sti->source().isNull() && sti->source()->collection().data() == collection.data() ) + return idx; + } + } + + return QModelIndex(); +} + + bool SourcesModel::setData( const QModelIndex& index, const QVariant& value, int role ) { diff --git a/src/sourcetree/sourcesmodel.h b/src/sourcetree/sourcesmodel.h index 2b761637b..e258e73ff 100644 --- a/src/sourcetree/sourcesmodel.h +++ b/src/sourcetree/sourcesmodel.h @@ -37,6 +37,10 @@ public: static Tomahawk::dynplaylist_ptr indexToDynamicPlaylist( const QModelIndex& index ); static SourceTreeItem* indexToTreeItem( const QModelIndex& index ); + QModelIndex playlistToIndex( const Tomahawk::playlist_ptr& playlist ); + QModelIndex dynamicPlaylistToIndex( const Tomahawk::dynplaylist_ptr& playlist ); + QModelIndex collectionToIndex( const Tomahawk::collection_ptr& collection ); + signals: void clicked( const QModelIndex& ); diff --git a/src/sourcetree/sourcetreeitem.cpp b/src/sourcetree/sourcetreeitem.cpp index 0e4ec8748..96fa06a8d 100644 --- a/src/sourcetree/sourcetreeitem.cpp +++ b/src/sourcetree/sourcetreeitem.cpp @@ -237,8 +237,8 @@ void SourceTreeItem::playlistAddedInternal( qlonglong ptr, const Tomahawk::playl subitem->setData( (qlonglong)this, SourceItemPointer ); m_columns.at( 0 )->appendRow( subitem ); - Q_ASSERT( qobject_cast((parent()->parent()) ) ); - qobject_cast((parent()->parent()))->expandAll(); +// Q_ASSERT( qobject_cast((parent()->parent()) ) ); +// qobject_cast((parent()->parent()))->expandAll(); p->loadRevision(); } diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp index 916d725a0..177482a61 100644 --- a/src/sourcetree/sourcetreeview.cpp +++ b/src/sourcetree/sourcetreeview.cpp @@ -67,7 +67,7 @@ SourceTreeView::SourceTreeView( QWidget* parent ) setItemDelegate( new SourceDelegate( this ) ); setContextMenuPolicy( Qt::CustomContextMenu ); - connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) ); + connect( this, SIGNAL( customContextMenuRequested( QPoint ) ), SLOT( onCustomContextMenu( QPoint ) ) ); m_model = new SourcesModel( this ); m_proxyModel = new SourcesProxyModel( m_model, this ); @@ -77,14 +77,25 @@ SourceTreeView::SourceTreeView( QWidget* parent ) header()->setResizeMode( 0, QHeaderView::Stretch ); connect( m_model, SIGNAL( clicked( QModelIndex ) ), SIGNAL( clicked( QModelIndex ) ) ); - connect( this, SIGNAL( clicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) ); + connect( this, SIGNAL( clicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) ); - connect( selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ), SLOT( onSelectionChanged() ) ); + connect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), SLOT( onSelectionChanged() ) ); connect( SourceList::instance(), SIGNAL( sourceRemoved( Tomahawk::source_ptr ) ), SLOT( onSourceOffline( Tomahawk::source_ptr ) ) ); m_model->appendItem( source_ptr() ); hideOfflineSources(); + + 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() ) ); } @@ -143,6 +154,57 @@ SourceTreeView::onSourceOffline( Tomahawk::source_ptr src ) } +void +SourceTreeView::onPlaylistActivated( const Tomahawk::playlist_ptr& playlist ) +{ + QModelIndex idx = m_proxyModel->mapFromSource( m_model->playlistToIndex( playlist ) ); + if ( idx.isValid() ) + { + setCurrentIndex( idx ); + } +} + + +void +SourceTreeView::onDynamicPlaylistActivated( const Tomahawk::dynplaylist_ptr& playlist ) +{ + QModelIndex idx = m_proxyModel->mapFromSource( m_model->dynamicPlaylistToIndex( playlist ) ); + if ( idx.isValid() ) + { + setCurrentIndex( idx ); + } +} + + +void +SourceTreeView::onCollectionActivated( const Tomahawk::collection_ptr& collection ) +{ + 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 ); + } +} + + +void +SourceTreeView::onTempPageActivated() +{ + clearSelection(); +} + + void SourceTreeView::onItemActivated( const QModelIndex& index ) { diff --git a/src/sourcetree/sourcetreeview.h b/src/sourcetree/sourcetreeview.h index 10df5d54d..077fb2937 100644 --- a/src/sourcetree/sourcetreeview.h +++ b/src/sourcetree/sourcetreeview.h @@ -27,6 +27,12 @@ signals: void onOffline( const QModelIndex& index ); private slots: + 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 onItemActivated( const QModelIndex& index ); void onSelectionChanged(); diff --git a/src/tomahawkwindow.cpp b/src/tomahawkwindow.cpp index b873accac..0fb8fd67d 100644 --- a/src/tomahawkwindow.cpp +++ b/src/tomahawkwindow.cpp @@ -56,6 +56,8 @@ TomahawkWindow::TomahawkWindow( QWidget* parent ) #endif PlaylistManager* pm = new PlaylistManager( this ); + connect( pm, SIGNAL( historyBackAvailable( bool ) ), SLOT( onHistoryBackAvailable( bool ) ) ); + connect( pm, SIGNAL( historyForwardAvailable( bool ) ), SLOT( onHistoryForwardAvailable( bool ) ) ); connect( m_audioControls, SIGNAL( playPressed() ), pm, SLOT( onPlayClicked() ) ); connect( m_audioControls, SIGNAL( pausePressed() ), pm, SLOT( onPauseClicked() ) ); @@ -119,9 +121,11 @@ TomahawkWindow::TomahawkWindow( QWidget* parent ) toolbar->setMovable( false ); toolbar->setFloatable( false ); toolbar->setIconSize( QSize( 32, 32 ) ); - toolbar->setToolButtonStyle( Qt::ToolButtonTextUnderIcon ); + toolbar->setToolButtonStyle( Qt::ToolButtonFollowStyle ); toolbar->installEventFilter( new WidgetDragFilter( toolbar ) ); + m_backAvailable = toolbar->addAction( QIcon( RESPATH "images/back.png" ), tr( "Back" ), PlaylistManager::instance(), SLOT( historyBack() ) ); + m_forwardAvailable = toolbar->addAction( QIcon( RESPATH "images/forward.png" ), tr( "Forward" ), PlaylistManager::instance(), SLOT( historyForward() ) ); toolbar->addAction( QIcon( RESPATH "images/home.png" ), tr( "Home" ), PlaylistManager::instance(), SLOT( showWelcomePage() ) ); statusBar()->addPermanentWidget( m_audioControls, 1 ); @@ -355,6 +359,20 @@ TomahawkWindow::onPlaybackLoading( const Tomahawk::result_ptr& result ) } +void +TomahawkWindow::onHistoryBackAvailable( bool avail ) +{ + m_backAvailable->setEnabled( avail ); +} + + +void +TomahawkWindow::onHistoryForwardAvailable( bool avail ) +{ + m_forwardAvailable->setEnabled( avail ); +} + + void TomahawkWindow::onSipConnected() { diff --git a/src/tomahawkwindow.h b/src/tomahawkwindow.h index 5e6a24472..766066cd8 100644 --- a/src/tomahawkwindow.h +++ b/src/tomahawkwindow.h @@ -54,7 +54,9 @@ private slots: void addPeerManually(); void onPlaybackLoading( const Tomahawk::result_ptr& result ); - + void onHistoryBackAvailable( bool avail ); + void onHistoryForwardAvailable( bool avail ); + void showAboutTomahawk(); private: @@ -68,6 +70,9 @@ private: QNetworkAccessManager m_nam; QPushButton* m_statusButton; + QAction* m_backAvailable; + QAction* m_forwardAvailable; + Tomahawk::result_ptr m_currentTrack; QString m_windowTitle; };