PageRenderTime 124ms CodeModel.GetById 40ms app.highlight 42ms RepoModel.GetById 38ms app.codeStats 1ms

/src/libtomahawk/widgets/RecentPlaylistsModel.cpp

http://github.com/tomahawk-player/tomahawk
C++ | 272 lines | 204 code | 49 blank | 19 comment | 26 complexity | 00515b5086f7149784bff584df4fc58c MD5 | raw file
  1/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2 *
  3 *   Copyright 2011, Leo Franchi <lfranchi@kde.org>
  4 *   Copyright 2013, Christian Muehlhaeuser <muesli@tomahawk-player.org>
  5 *
  6 *   Tomahawk is free software: you can redistribute it and/or modify
  7 *   it under the terms of the GNU General Public License as published by
  8 *   the Free Software Foundation, either version 3 of the License, or
  9 *   (at your option) any later version.
 10 *
 11 *   Tomahawk is distributed in the hope that it will be useful,
 12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 14 *   GNU General Public License for more details.
 15 *
 16 *   You should have received a copy of the GNU General Public License
 17 *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
 18 */
 19
 20#include "RecentPlaylistsModel.h"
 21
 22#include "audio/AudioEngine.h"
 23#include "collection/Collection.h"
 24#include "database/Database.h"
 25#include "database/DatabaseCommand_LoadAllSortedPlaylists.h"
 26#include "network/Servent.h"
 27#include "playlist/dynamic/DynamicPlaylist.h"
 28#include "utils/Logger.h"
 29
 30#include "PlaylistEntry.h"
 31#include "RecentlyPlayedPlaylistsModel.h"
 32#include "SourceList.h"
 33#include "TomahawkSettings.h"
 34#include "Track.h"
 35
 36#define REFRESH_TIMEOUT 1000
 37
 38using namespace Tomahawk;
 39
 40
 41RecentPlaylistsModel::RecentPlaylistsModel( unsigned int maxPlaylists, QObject* parent )
 42    : QAbstractListModel( parent )
 43    , m_maxPlaylists( maxPlaylists )
 44{
 45    m_timer = new QTimer( this );
 46
 47    connect( m_timer, SIGNAL( timeout() ), SLOT( onRefresh() ) );
 48    connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onReady() ) );
 49
 50    // Load recent playlists initially
 51    if ( SourceList::instance()->isReady() )
 52        onRefresh();
 53}
 54
 55
 56void
 57RecentPlaylistsModel::refresh()
 58{
 59    if ( m_timer->isActive() )
 60        m_timer->stop();
 61    m_timer->start( REFRESH_TIMEOUT );
 62}
 63
 64
 65void
 66RecentPlaylistsModel::onRefresh()
 67{
 68    if ( m_timer->isActive() )
 69        m_timer->stop();
 70
 71    emit loadingStarted();
 72
 73    DatabaseCommand_LoadAllSortedPlaylists* cmd = new DatabaseCommand_LoadAllSortedPlaylists( source_ptr() );
 74    cmd->setLimit( m_maxPlaylists );
 75    cmd->setSortOrder( DatabaseCommand_LoadAllPlaylists::ModificationTime );
 76    cmd->setSortAscDesc( DatabaseCommand_LoadAllPlaylists::Descending );
 77    connect( cmd, SIGNAL( done( QList<Tomahawk::DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair> ) ),
 78             this, SLOT( playlistsLoaded( QList<Tomahawk::DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair> ) ) );
 79    Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
 80}
 81
 82
 83void
 84RecentPlaylistsModel::onReady()
 85{
 86    foreach ( const source_ptr& s, SourceList::instance()->sources() )
 87        onSourceAdded( s );
 88
 89    connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), this, SLOT( onSourceAdded( Tomahawk::source_ptr ) ), Qt::QueuedConnection );
 90    onRefresh();
 91}
 92
 93
 94void
 95RecentPlaylistsModel::playlistsLoaded( const QList<DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair>& playlistGuids )
 96{
 97    beginResetModel();
 98    m_playlists.clear();
 99
100    DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair plPair;
101    foreach ( plPair, playlistGuids )
102    {
103        const playlist_ptr& pl = Playlist::get( plPair.second );
104        if ( !pl )
105        {
106            tDebug() << "ERROR: Found a playlist that is not associated with any source:" << plPair.first << plPair.second;
107            continue;
108        }
109
110        connect( pl.data(), SIGNAL( changed() ), SLOT( updatePlaylist() ) );
111        m_playlists << pl;
112
113        if ( !pl->loaded() )
114            pl->loadRevision();
115    }
116
117    endResetModel();
118
119    emit emptinessChanged( m_playlists.isEmpty() );
120    emit loadingFinished();
121}
122
123
124QVariant
125RecentPlaylistsModel::data( const QModelIndex& index, int role ) const
126{
127    if ( !index.isValid() || !hasIndex( index.row(), index.column(), index.parent() ) )
128        return QVariant();
129
130    playlist_ptr pl = m_playlists[index.row()];
131    switch( role )
132    {
133    case Qt::DisplayRole:
134        return pl->title();
135    case RecentlyPlayedPlaylistsModel::PlaylistRole:
136        return QVariant::fromValue< Tomahawk::playlist_ptr >( pl );
137    case RecentlyPlayedPlaylistsModel::ArtistRole:
138    {
139        if ( m_artists.value( pl ).isEmpty() )
140        {
141            QStringList artists;
142
143            foreach ( const Tomahawk::plentry_ptr& entry, pl->entries() )
144            {
145                if ( !artists.contains( entry->query()->track()->artist() ) )
146                    artists << entry->query()->track()->artist();
147            }
148
149            m_artists[pl] = artists.join( ", " );
150        }
151
152        return m_artists[pl];
153    }
154    case RecentlyPlayedPlaylistsModel::PlaylistTypeRole:
155    {
156        if ( !pl.dynamicCast< Tomahawk::DynamicPlaylist >().isNull() )
157        {
158            dynplaylist_ptr dynp = pl.dynamicCast< Tomahawk::DynamicPlaylist >();
159            if ( dynp->mode() == Static )
160                return RecentlyPlayedPlaylistsModel::AutoPlaylist;
161            else if ( dynp->mode() == OnDemand )
162                return RecentlyPlayedPlaylistsModel::Station;
163        }
164        else
165        {
166            return RecentlyPlayedPlaylistsModel::StaticPlaylist;
167        }
168    }
169    case RecentlyPlayedPlaylistsModel::DynamicPlaylistRole:
170    {
171        dynplaylist_ptr dynp = pl.dynamicCast< Tomahawk::DynamicPlaylist >();
172        return QVariant::fromValue< Tomahawk::dynplaylist_ptr >( dynp );
173    }
174    case RecentlyPlayedPlaylistsModel::TrackCountRole:
175    {
176        if ( !pl.dynamicCast< Tomahawk::DynamicPlaylist >().isNull() && pl.dynamicCast< Tomahawk::DynamicPlaylist >()->mode() == OnDemand )
177            return QString( QChar( 0x221E ) );
178        else
179            return pl->entries().count();
180    }
181    default:
182        return QVariant();
183    }
184}
185
186
187void
188RecentPlaylistsModel::updatePlaylist()
189{
190    Playlist* p = qobject_cast< Playlist* >( sender() );
191    Q_ASSERT( p );
192
193    for ( int i = 0; i < m_playlists.size(); i++ )
194    {
195        if ( m_playlists[ i ].isNull() )
196            continue;
197
198        if ( m_playlists[ i ]->guid() == p->guid() )
199        {
200            QModelIndex idx = index( i, 0, QModelIndex() );
201            emit dataChanged( idx, idx );
202        }
203    }
204}
205
206
207void
208RecentPlaylistsModel::onSourceAdded( const Tomahawk::source_ptr& source )
209{
210    connect( source.data(), SIGNAL( online() ), this, SLOT( sourceOnline() ) );
211    connect( source->dbCollection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ), SLOT( refresh() ), Qt::QueuedConnection );
212    connect( source->dbCollection().data(), SIGNAL( autoPlaylistsAdded(QList<Tomahawk::dynplaylist_ptr>)), SLOT( refresh() ), Qt::QueuedConnection );
213    connect( source->dbCollection().data(), SIGNAL( stationsAdded(QList<Tomahawk::dynplaylist_ptr>)), SLOT( refresh() ), Qt::QueuedConnection );
214    connect( source->dbCollection().data(), SIGNAL( playlistsDeleted( QList<Tomahawk::playlist_ptr> ) ), SLOT( onPlaylistsRemoved( QList<Tomahawk::playlist_ptr> ) ) );
215    connect( source->dbCollection().data(), SIGNAL( autoPlaylistsDeleted(QList<Tomahawk::dynplaylist_ptr>) ), SLOT( onDynPlaylistsRemoved( QList<Tomahawk::dynplaylist_ptr> ) ) );
216    connect( source->dbCollection().data(), SIGNAL( stationsDeleted(QList<Tomahawk::dynplaylist_ptr>) ), SLOT( onDynPlaylistsRemoved( QList<Tomahawk::dynplaylist_ptr> ) ) );
217}
218
219
220void
221RecentPlaylistsModel::sourceOnline()
222{
223    Source* s = qobject_cast< Source* >( sender() );
224    Q_ASSERT( s );
225
226    for ( int i = 0; i < m_playlists.size(); i++ )
227    {
228        if ( m_playlists[ i ]->author().data() == s )
229        {
230            QModelIndex idx = index( i, 0, QModelIndex() );
231            emit dataChanged( idx, idx );
232        }
233    }
234}
235
236
237void
238RecentPlaylistsModel::onDynPlaylistsRemoved( QList< dynplaylist_ptr > playlists )
239{
240    QList< playlist_ptr > pls;
241    foreach ( const dynplaylist_ptr& p, playlists )
242        pls << p;
243
244    onPlaylistsRemoved( pls );
245}
246
247
248void
249RecentPlaylistsModel::onPlaylistsRemoved( QList< playlist_ptr > playlists )
250{
251    foreach ( const playlist_ptr& pl, playlists )
252    {
253        if ( m_playlists.contains( pl ) )
254        {
255            m_artists.remove( pl );
256
257            int idx = m_playlists.indexOf( pl );
258            beginRemoveRows( QModelIndex(), idx, idx );
259            m_playlists.removeAt( idx );
260            endRemoveRows();
261        }
262    }
263
264    emit emptinessChanged( m_playlists.isEmpty() );
265}
266
267
268int
269RecentPlaylistsModel::rowCount( const QModelIndex& ) const
270{
271    return m_playlists.count();
272}