/src/libtomahawk/widgets/RecentPlaylistsModel.cpp

http://github.com/tomahawk-player/tomahawk · C++ · 272 lines · 204 code · 49 blank · 19 comment · 27 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. #include "RecentPlaylistsModel.h"
  20. #include "audio/AudioEngine.h"
  21. #include "collection/Collection.h"
  22. #include "database/Database.h"
  23. #include "database/DatabaseCommand_LoadAllSortedPlaylists.h"
  24. #include "network/Servent.h"
  25. #include "playlist/dynamic/DynamicPlaylist.h"
  26. #include "utils/Logger.h"
  27. #include "PlaylistEntry.h"
  28. #include "RecentlyPlayedPlaylistsModel.h"
  29. #include "SourceList.h"
  30. #include "TomahawkSettings.h"
  31. #include "Track.h"
  32. #define REFRESH_TIMEOUT 1000
  33. using namespace Tomahawk;
  34. RecentPlaylistsModel::RecentPlaylistsModel( unsigned int maxPlaylists, QObject* parent )
  35. : QAbstractListModel( parent )
  36. , m_maxPlaylists( maxPlaylists )
  37. {
  38. m_timer = new QTimer( this );
  39. connect( m_timer, SIGNAL( timeout() ), SLOT( onRefresh() ) );
  40. connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onReady() ) );
  41. // Load recent playlists initially
  42. if ( SourceList::instance()->isReady() )
  43. onRefresh();
  44. }
  45. void
  46. RecentPlaylistsModel::refresh()
  47. {
  48. if ( m_timer->isActive() )
  49. m_timer->stop();
  50. m_timer->start( REFRESH_TIMEOUT );
  51. }
  52. void
  53. RecentPlaylistsModel::onRefresh()
  54. {
  55. if ( m_timer->isActive() )
  56. m_timer->stop();
  57. emit loadingStarted();
  58. DatabaseCommand_LoadAllSortedPlaylists* cmd = new DatabaseCommand_LoadAllSortedPlaylists( source_ptr() );
  59. cmd->setLimit( m_maxPlaylists );
  60. cmd->setSortOrder( DatabaseCommand_LoadAllPlaylists::ModificationTime );
  61. cmd->setSortAscDesc( DatabaseCommand_LoadAllPlaylists::Descending );
  62. connect( cmd, SIGNAL( done( QList<Tomahawk::DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair> ) ),
  63. this, SLOT( playlistsLoaded( QList<Tomahawk::DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair> ) ) );
  64. Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
  65. }
  66. void
  67. RecentPlaylistsModel::onReady()
  68. {
  69. foreach ( const source_ptr& s, SourceList::instance()->sources() )
  70. onSourceAdded( s );
  71. connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), this, SLOT( onSourceAdded( Tomahawk::source_ptr ) ), Qt::QueuedConnection );
  72. onRefresh();
  73. }
  74. void
  75. RecentPlaylistsModel::playlistsLoaded( const QList<DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair>& playlistGuids )
  76. {
  77. beginResetModel();
  78. m_playlists.clear();
  79. DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair plPair;
  80. foreach ( plPair, playlistGuids )
  81. {
  82. const playlist_ptr& pl = Playlist::get( plPair.second );
  83. if ( !pl )
  84. {
  85. tDebug() << "ERROR: Found a playlist that is not associated with any source:" << plPair.first << plPair.second;
  86. continue;
  87. }
  88. connect( pl.data(), SIGNAL( changed() ), SLOT( updatePlaylist() ) );
  89. m_playlists << pl;
  90. if ( !pl->loaded() )
  91. pl->loadRevision();
  92. }
  93. endResetModel();
  94. emit emptinessChanged( m_playlists.isEmpty() );
  95. emit loadingFinished();
  96. }
  97. QVariant
  98. RecentPlaylistsModel::data( const QModelIndex& index, int role ) const
  99. {
  100. if ( !index.isValid() || !hasIndex( index.row(), index.column(), index.parent() ) )
  101. return QVariant();
  102. playlist_ptr pl = m_playlists[index.row()];
  103. switch( role )
  104. {
  105. case Qt::DisplayRole:
  106. return pl->title();
  107. case RecentlyPlayedPlaylistsModel::PlaylistRole:
  108. return QVariant::fromValue< Tomahawk::playlist_ptr >( pl );
  109. case RecentlyPlayedPlaylistsModel::ArtistRole:
  110. {
  111. if ( m_artists.value( pl ).isEmpty() )
  112. {
  113. QStringList artists;
  114. foreach ( const Tomahawk::plentry_ptr& entry, pl->entries() )
  115. {
  116. if ( !artists.contains( entry->query()->track()->artist() ) )
  117. artists << entry->query()->track()->artist();
  118. }
  119. m_artists[pl] = artists.join( ", " );
  120. }
  121. return m_artists[pl];
  122. }
  123. case RecentlyPlayedPlaylistsModel::PlaylistTypeRole:
  124. {
  125. if ( !pl.dynamicCast< Tomahawk::DynamicPlaylist >().isNull() )
  126. {
  127. dynplaylist_ptr dynp = pl.dynamicCast< Tomahawk::DynamicPlaylist >();
  128. if ( dynp->mode() == Static )
  129. return RecentlyPlayedPlaylistsModel::AutoPlaylist;
  130. else if ( dynp->mode() == OnDemand )
  131. return RecentlyPlayedPlaylistsModel::Station;
  132. }
  133. else
  134. {
  135. return RecentlyPlayedPlaylistsModel::StaticPlaylist;
  136. }
  137. }
  138. case RecentlyPlayedPlaylistsModel::DynamicPlaylistRole:
  139. {
  140. dynplaylist_ptr dynp = pl.dynamicCast< Tomahawk::DynamicPlaylist >();
  141. return QVariant::fromValue< Tomahawk::dynplaylist_ptr >( dynp );
  142. }
  143. case RecentlyPlayedPlaylistsModel::TrackCountRole:
  144. {
  145. if ( !pl.dynamicCast< Tomahawk::DynamicPlaylist >().isNull() && pl.dynamicCast< Tomahawk::DynamicPlaylist >()->mode() == OnDemand )
  146. return QString( QChar( 0x221E ) );
  147. else
  148. return pl->entries().count();
  149. }
  150. default:
  151. return QVariant();
  152. }
  153. }
  154. void
  155. RecentPlaylistsModel::updatePlaylist()
  156. {
  157. Playlist* p = qobject_cast< Playlist* >( sender() );
  158. Q_ASSERT( p );
  159. for ( int i = 0; i < m_playlists.size(); i++ )
  160. {
  161. if ( m_playlists[ i ].isNull() )
  162. continue;
  163. if ( m_playlists[ i ]->guid() == p->guid() )
  164. {
  165. QModelIndex idx = index( i, 0, QModelIndex() );
  166. emit dataChanged( idx, idx );
  167. }
  168. }
  169. }
  170. void
  171. RecentPlaylistsModel::onSourceAdded( const Tomahawk::source_ptr& source )
  172. {
  173. connect( source.data(), SIGNAL( online() ), this, SLOT( sourceOnline() ) );
  174. connect( source->dbCollection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ), SLOT( refresh() ), Qt::QueuedConnection );
  175. connect( source->dbCollection().data(), SIGNAL( autoPlaylistsAdded(QList<Tomahawk::dynplaylist_ptr>)), SLOT( refresh() ), Qt::QueuedConnection );
  176. connect( source->dbCollection().data(), SIGNAL( stationsAdded(QList<Tomahawk::dynplaylist_ptr>)), SLOT( refresh() ), Qt::QueuedConnection );
  177. connect( source->dbCollection().data(), SIGNAL( playlistsDeleted( QList<Tomahawk::playlist_ptr> ) ), SLOT( onPlaylistsRemoved( QList<Tomahawk::playlist_ptr> ) ) );
  178. connect( source->dbCollection().data(), SIGNAL( autoPlaylistsDeleted(QList<Tomahawk::dynplaylist_ptr>) ), SLOT( onDynPlaylistsRemoved( QList<Tomahawk::dynplaylist_ptr> ) ) );
  179. connect( source->dbCollection().data(), SIGNAL( stationsDeleted(QList<Tomahawk::dynplaylist_ptr>) ), SLOT( onDynPlaylistsRemoved( QList<Tomahawk::dynplaylist_ptr> ) ) );
  180. }
  181. void
  182. RecentPlaylistsModel::sourceOnline()
  183. {
  184. Source* s = qobject_cast< Source* >( sender() );
  185. Q_ASSERT( s );
  186. for ( int i = 0; i < m_playlists.size(); i++ )
  187. {
  188. if ( m_playlists[ i ]->author().data() == s )
  189. {
  190. QModelIndex idx = index( i, 0, QModelIndex() );
  191. emit dataChanged( idx, idx );
  192. }
  193. }
  194. }
  195. void
  196. RecentPlaylistsModel::onDynPlaylistsRemoved( QList< dynplaylist_ptr > playlists )
  197. {
  198. QList< playlist_ptr > pls;
  199. foreach ( const dynplaylist_ptr& p, playlists )
  200. pls << p;
  201. onPlaylistsRemoved( pls );
  202. }
  203. void
  204. RecentPlaylistsModel::onPlaylistsRemoved( QList< playlist_ptr > playlists )
  205. {
  206. foreach ( const playlist_ptr& pl, playlists )
  207. {
  208. if ( m_playlists.contains( pl ) )
  209. {
  210. m_artists.remove( pl );
  211. int idx = m_playlists.indexOf( pl );
  212. beginRemoveRows( QModelIndex(), idx, idx );
  213. m_playlists.removeAt( idx );
  214. endRemoveRows();
  215. }
  216. }
  217. emit emptinessChanged( m_playlists.isEmpty() );
  218. }
  219. int
  220. RecentPlaylistsModel::rowCount( const QModelIndex& ) const
  221. {
  222. return m_playlists.count();
  223. }