/src/sourcetree/items/collectionitem.cpp
http://github.com/tomahawk-player/tomahawk · C++ · 518 lines · 382 code · 98 blank · 38 comment · 63 complexity · 48e3d20a17454d5860d47a2df717cce1 MD5 · raw file
- /*
- * Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
- *
- * 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 "categoryitems.h"
- #include "playlistitems.h"
- #include "viewmanager.h"
- #include "playlist.h"
- #include "genericpageitems.h"
- #include "utils/tomahawkutils.h"
- #include "utils/logger.h"
- #include "widgets/SocialPlaylistWidget.h"
- #include "playlist/customplaylistview.h"
- #include "source.h"
- #include "temporarypageitem.h"
- #include <sourcelist.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 )
- , m_latchedOn( false )
- , m_sourceInfoItem( 0 )
- , m_coolPlaylistsItem( 0 )
- , m_lovedTracksItem()
- , m_sourceInfoPage( 0 )
- , m_coolPlaylistsPage( 0 )
- , m_lovedTracksPage( 0 )
- , m_whatsHotPage( 0 )
- {
- m_lovedTracksItem = new GenericPageItem( model(), this, ( m_source.isNull() ? tr( "Top Loved Tracks" ) : tr( "Loved Tracks" ) ), QIcon( RESPATH "images/loved_playlist.png" ),
- boost::bind( &CollectionItem::lovedTracksClicked, this ),
- boost::bind( &CollectionItem::getLovedTracksPage, this ) );
- m_lovedTracksItem->setSortValue( -250 );
- if ( m_source.isNull() )
- {
- // super collection
- connect( ViewManager::instance(), SIGNAL( tempPageActivated( Tomahawk::ViewPage*) ), this, SLOT( tempPageActivated( Tomahawk::ViewPage* ) ) );
- // add misc children of root node
- GenericPageItem* recent = new GenericPageItem( model(), this, tr( "Dashboard" ), QIcon( RESPATH "images/dashboard.png" ),
- boost::bind( &ViewManager::showWelcomePage, ViewManager::instance() ),
- boost::bind( &ViewManager::welcomeWidget, ViewManager::instance() )
- );
- recent->setSortValue( -300 );
- GenericPageItem* hot = new GenericPageItem( model(), this, tr( "Charts" ), QIcon( RESPATH "images/charts.png" ),
- boost::bind( &ViewManager::showWhatsHotPage, ViewManager::instance() ),
- boost::bind( &ViewManager::whatsHotWidget, ViewManager::instance() )
- );
- hot->setSortValue( -300 );
- // TODO finish implementing and making pretty
- // m_coolPlaylistsItem = new GenericPageItem( model(), this, tr( "Cool Stuff" ), QIcon( RESPATH "images/new-additions.png" ),
- // boost::bind( &CollectionItem::coolPlaylistsClicked, this ),
- // boost::bind( &CollectionItem::getCoolPlaylistsPage, this )
- // );
- // m_coolPlaylistsItem->setSortValue( 200 );
- m_superCol = TomahawkUtils::createAvatarFrame( QPixmap( RESPATH "images/supercollection.png" ) );
- return;
- }
- m_sourceInfoItem = new GenericPageItem( model(), this, tr( "New Additions" ), QIcon( RESPATH "images/new-additions.png" ),
- boost::bind( &CollectionItem::sourceInfoClicked, this ),
- boost::bind( &CollectionItem::getSourceInfoPage, this ) );
- m_sourceInfoItem->setSortValue( -300 );
- // 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() ) );
- m_defaultAvatar = TomahawkUtils::createAvatarFrame( QPixmap( RESPATH "images/user-avatar.png" ) );
- // load auto playlists and stations!
- connect( source.data(), SIGNAL( stats( QVariantMap ) ), this, SIGNAL( updated() ) );
- connect( source.data(), SIGNAL( syncedWithDatabase() ), 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( SourceList::instance(), SIGNAL( sourceLatchedOn( Tomahawk::source_ptr, Tomahawk::source_ptr ) ), this, SLOT( latchedOn( Tomahawk::source_ptr, Tomahawk::source_ptr ) ) );
- connect( SourceList::instance(), SIGNAL( sourceLatchedOff( Tomahawk::source_ptr, Tomahawk::source_ptr ) ), this, SLOT( latchedOff( Tomahawk::source_ptr, Tomahawk::source_ptr ) ) );
- connect( source->collection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ),
- SLOT( onPlaylistsAdded( QList<Tomahawk::playlist_ptr> ) ), Qt::QueuedConnection );
- connect( source->collection().data(), SIGNAL( autoPlaylistsAdded( QList< Tomahawk::dynplaylist_ptr > ) ),
- SLOT( onAutoPlaylistsAdded( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
- connect( source->collection().data(), SIGNAL( stationsAdded( QList<Tomahawk::dynplaylist_ptr> ) ),
- SLOT( onStationsAdded( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
- if ( m_source->isLocal() )
- QTimer::singleShot(0, this, SLOT(requestExpanding()));
- }
- Tomahawk::source_ptr
- CollectionItem::source() const
- {
- return m_source;
- }
- QString
- CollectionItem::text() const
- {
- return m_source.isNull() ? tr( "Super Collection" ) : m_source->friendlyName();
- }
- int
- CollectionItem::IDValue() const
- {
- if( m_source.isNull() )
- return -1;
- if( m_source->isLocal() )
- return 0;
- return m_source->id();
- }
- int
- CollectionItem::peerSortValue() const
- {
- if( m_source.isNull() )
- return -1;
- if( m_source->isLocal() )
- return 0;
- return 1;
- }
- void
- CollectionItem::activate()
- {
- ViewPage* p = 0;
- if ( source().isNull() )
- p = ViewManager::instance()->showSuperCollection();
- else
- p = ViewManager::instance()->show( source()->collection() );
- model()->linkSourceItemToPage( this, p );
- }
- QIcon
- CollectionItem::icon() const
- {
- if ( m_source.isNull() )
- return m_superCol;
- else
- {
- if( m_source->avatar().isNull() )
- return m_defaultAvatar;
- else
- return m_source->avatar( Source::FancyStyle );
- }
- }
- bool
- CollectionItem::localLatchedOn() const
- {
- // Don't show a listen icon if this is the local collection and we are latched on to someone who went offline
- // we are technically still latched on (if they come back online we'll be still listening along) but it's not visible
- // in the UI and confusing to the user why the red headphones are still there
- if ( !m_source.isNull() && m_source->isLocal() &&
- !m_latchedOnTo.isNull() && !m_latchedOnTo->isOnline() )
- return false;
- return m_latchedOn;
- }
- void
- CollectionItem::latchedOff( const source_ptr& from, const source_ptr& to )
- {
- if ( from->isLocal() && ( m_source == to || m_source == from ) )
- {
- m_latchedOn = false;
- m_latchedOnTo.clear();
- emit updated();
- }
- }
- void
- CollectionItem::latchedOn( const source_ptr& from, const source_ptr& to )
- {
- if ( from->isLocal() && ( m_source == to || m_source == from ) )
- {
- m_latchedOn = true;
- m_latchedOnTo = to;
- emit updated();
- }
- }
- 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;
- if( p->mode() == Static ) {
- if( m_source->isLocal() )
- connect( p.data(), SIGNAL( aboutToBeDeleted( Tomahawk::dynplaylist_ptr ) ),
- SLOT( onAutoPlaylistDeleted( Tomahawk::dynplaylist_ptr ) ), Qt::QueuedConnection );
- else
- connect( p.data(), SIGNAL( deleted( Tomahawk::dynplaylist_ptr ) ),
- SLOT( onAutoPlaylistDeleted( Tomahawk::dynplaylist_ptr ) ), Qt::QueuedConnection );
- } else {
- if( m_source->isLocal() )
- connect( p.data(), SIGNAL( aboutToBeDeleted( Tomahawk::dynplaylist_ptr ) ),
- SLOT( onStationDeleted( Tomahawk::dynplaylist_ptr ) ), Qt::QueuedConnection );
- else
- connect( p.data(), SIGNAL( deleted( Tomahawk::dynplaylist_ptr ) ),
- SLOT( onStationDeleted( Tomahawk::dynplaylist_ptr ) ), Qt::QueuedConnection );
- }
- }
- parent->endRowsAdded();
- }
- template< typename T >
- void
- CollectionItem::playlistDeletedInternal( SourceTreeItem* parent, const T& p )
- {
- Q_ASSERT( parent ); // How can we delete playlists if we have none?
- 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() == p )
- {
- parent->beginRowsRemoved( i, i );
- parent->removeChild( pl );
- parent->endRowsRemoved();
- delete pl;
- break;
- }
- }
- if( ( parent == m_playlists || parent == m_stations ) &&
- parent->children().isEmpty() && parent->parent() ) // Don't leave an empty Playlist or Station category
- {
- int idx = parent->parent()->children().indexOf( parent );
- if( idx < 0 )
- return;
- parent->parent()->beginRowsRemoved( idx, idx );
- parent->parent()->removeChild( parent );
- parent->parent()->endRowsRemoved();
- if( parent == m_playlists )
- m_playlists = 0;
- else if( parent == m_stations )
- m_stations = 0;
- delete parent;
- }
- }
- void
- CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists )
- {
- // qDebug() << Q_FUNC_INFO << m_source->friendlyName() << playlists.count();
- 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;
- if( m_source->isLocal() )
- connect( p.data(), SIGNAL( aboutToBeDeleted( Tomahawk::playlist_ptr ) ),
- SLOT( onPlaylistDeleted( Tomahawk::playlist_ptr ) ), Qt::QueuedConnection );
- else
- connect( p.data(), SIGNAL( deleted( Tomahawk::playlist_ptr ) ),
- SLOT( onPlaylistDeleted( Tomahawk::playlist_ptr ) ), Qt::QueuedConnection );
- }
- m_playlists->endRowsAdded();
- }
- void
- CollectionItem::onPlaylistDeleted( const playlist_ptr& playlist )
- {
- playlistDeletedInternal( m_playlists, playlist );
- }
- 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::onAutoPlaylistDeleted( const dynplaylist_ptr& playlist )
- {
- if( !m_playlists )
- qDebug() << "NO playlist category item for a deleting playlist..";
- playlistDeletedInternal( m_playlists, playlist );
- }
- 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::onStationDeleted( const dynplaylist_ptr& station )
- {
- playlistDeletedInternal( m_stations, station );
- }
- void
- CollectionItem::requestExpanding()
- {
- emit expandRequest(this);
- }
- void
- CollectionItem::tempPageActivated( Tomahawk::ViewPage* v )
- {
- const int idx = children().count();
- const int latest = children().last()->IDValue();
- foreach ( TemporaryPageItem* page, m_tempItems )
- {
- if ( page->page() == v )
- {
- emit selectRequest( page );
- return;
- }
- }
- // Only keep 5 temporary pages at once
- while ( m_tempItems.size() > 4 )
- {
- TemporaryPageItem* item = m_tempItems.takeFirst();
- QTimer::singleShot( 0, item, SLOT( removeFromList() ) );
- }
- emit beginRowsAdded( idx, idx );
- TemporaryPageItem* tempPage = new TemporaryPageItem( model(), this, v, latest + 1 );
- connect( tempPage, SIGNAL( removed() ), this, SLOT( temporaryPageDestroyed() ) );
- m_tempItems << tempPage;
- endRowsAdded();
- emit selectRequest( tempPage );
- }
- void
- CollectionItem::temporaryPageDestroyed()
- {
- TemporaryPageItem* tempPage = qobject_cast< TemporaryPageItem* >( sender() );
- Q_ASSERT( tempPage );
- m_tempItems.removeAll( tempPage );
- }
- ViewPage*
- CollectionItem::sourceInfoClicked()
- {
- if( m_source.isNull() )
- return 0;
- m_sourceInfoPage = ViewManager::instance()->show( m_source );
- return m_sourceInfoPage;
- }
- ViewPage*
- CollectionItem::getSourceInfoPage() const
- {
- return m_sourceInfoPage;
- }
- ViewPage*
- CollectionItem::coolPlaylistsClicked()
- {
- if( !m_source.isNull() )
- return 0;
- if( !m_coolPlaylistsPage )
- m_coolPlaylistsPage = new SocialPlaylistWidget( ViewManager::instance()->widget() );
- ViewManager::instance()->show( m_coolPlaylistsPage );
- return m_coolPlaylistsPage;
- }
- ViewPage*
- CollectionItem::getCoolPlaylistsPage() const
- {
- return m_coolPlaylistsPage;
- }
- ViewPage*
- CollectionItem::lovedTracksClicked()
- {
- if( !m_lovedTracksPage )
- m_lovedTracksPage = new CustomPlaylistView( m_source.isNull() ? CustomPlaylistView::AllLovedTracks : CustomPlaylistView::SourceLovedTracks, m_source, ViewManager::instance()->widget() );
- ViewManager::instance()->show( m_lovedTracksPage );
- return m_lovedTracksPage;
- }
- ViewPage*
- CollectionItem::getLovedTracksPage() const
- {
- return m_lovedTracksPage;
- }