/src/libtomahawk/widgets/RecentlyPlayedPlaylistsModel.cpp

http://github.com/tomahawk-player/tomahawk · C++ · 277 lines · 206 code · 48 blank · 23 comment · 35 complexity · 9f8de9621a8d94119e4f0521f9db565e 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 2011, Jeff Mitchell <jeff@tomahawk-player.org>
  5. * Copyright 2013, Christian Muehlhaeuser <muesli@tomahawk-player.org>
  6. *
  7. * Tomahawk is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * Tomahawk is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include "RecentlyPlayedPlaylistsModel.h"
  21. #include "audio/AudioEngine.h"
  22. #include "collection/Collection.h"
  23. #include "playlist/dynamic/DynamicPlaylist.h"
  24. #include "utils/Logger.h"
  25. #include "Playlist.h"
  26. #include "PlaylistEntry.h"
  27. #include "PlaylistInterface.h"
  28. #include "SourceList.h"
  29. #include "TomahawkSettings.h"
  30. #include "Track.h"
  31. using namespace Tomahawk;
  32. RecentlyPlayedPlaylistsModel::RecentlyPlayedPlaylistsModel( QObject* parent )
  33. : QAbstractListModel( parent )
  34. , m_maxPlaylists( 0 )
  35. , m_waitingForSome( true )
  36. {
  37. loadFromSettings();
  38. connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), this, SLOT( onSourceAdded( Tomahawk::source_ptr ) ), Qt::QueuedConnection );
  39. connect( TomahawkSettings::instance(), SIGNAL( recentlyPlayedPlaylistAdded( QString, int ) ), this, SLOT( plAdded( QString, int ) ) );
  40. connect( AudioEngine::instance(),SIGNAL( playlistChanged( Tomahawk::playlistinterface_ptr ) ), this, SLOT( playlistChanged( Tomahawk::playlistinterface_ptr ) ), Qt::QueuedConnection );
  41. emit emptinessChanged( m_recplaylists.isEmpty() );
  42. }
  43. void
  44. RecentlyPlayedPlaylistsModel::loadFromSettings()
  45. {
  46. // qDebug() << Q_FUNC_INFO;
  47. if ( !m_waitingForSome )
  48. return;
  49. beginResetModel();
  50. m_recplaylists.clear();
  51. m_waitingForSome = false;
  52. QStringList playlist_guids = TomahawkSettings::instance()->recentlyPlayedPlaylistGuids( m_maxPlaylists );
  53. for( int i = playlist_guids.size() - 1; i >= 0; i-- )
  54. {
  55. // qDebug() << "loading playlist" << playlist_guids[i];
  56. playlist_ptr pl = m_cached.value( playlist_guids[i], Tomahawk::playlist_ptr() );
  57. if ( !pl )
  58. pl = Tomahawk::Playlist::get( playlist_guids[i] );
  59. if ( !pl )
  60. pl = Tomahawk::DynamicPlaylist::get( playlist_guids[i] );
  61. if ( pl )
  62. {
  63. m_recplaylists << pl;
  64. if ( !m_cached.contains( playlist_guids[i] ) )
  65. {
  66. if ( pl.dynamicCast< DynamicPlaylist >().isNull() )
  67. connect( pl.data(), SIGNAL(revisionLoaded(Tomahawk::PlaylistRevision)), this, SLOT(playlistRevisionLoaded()) );
  68. else
  69. connect( pl.data(), SIGNAL(dynamicRevisionLoaded(Tomahawk::DynamicPlaylistRevision)), this, SLOT(playlistRevisionLoaded()) );
  70. m_cached[playlist_guids[i]] = pl;
  71. }
  72. } else
  73. m_waitingForSome = true;
  74. }
  75. endResetModel();
  76. emit emptinessChanged( m_recplaylists.isEmpty() );
  77. }
  78. QVariant
  79. RecentlyPlayedPlaylistsModel::data( const QModelIndex& index, int role ) const
  80. {
  81. if ( !index.isValid() || !hasIndex( index.row(), index.column(), index.parent() ) )
  82. return QVariant();
  83. playlist_ptr pl = m_recplaylists[index.row()];
  84. switch( role )
  85. {
  86. case Qt::DisplayRole:
  87. return pl->title();
  88. case PlaylistRole:
  89. return QVariant::fromValue< Tomahawk::playlist_ptr >( pl );
  90. case ArtistRole:
  91. {
  92. if ( m_artists.value( pl ).isEmpty() )
  93. {
  94. QStringList artists;
  95. foreach ( const Tomahawk::plentry_ptr& entry, pl->entries() )
  96. {
  97. if ( !artists.contains( entry->query()->track()->artist() ) )
  98. artists << entry->query()->track()->artist();
  99. }
  100. m_artists[pl] = artists.join( ", " );
  101. }
  102. return m_artists[pl];
  103. }
  104. case PlaylistTypeRole:
  105. {
  106. if ( !pl.dynamicCast< Tomahawk::DynamicPlaylist >().isNull() )
  107. {
  108. dynplaylist_ptr dynp = pl.dynamicCast< Tomahawk::DynamicPlaylist >();
  109. if ( dynp->mode() == Static )
  110. return AutoPlaylist;
  111. else if ( dynp->mode() == OnDemand )
  112. return Station;
  113. } else
  114. {
  115. return StaticPlaylist;
  116. }
  117. }
  118. case DynamicPlaylistRole:
  119. {
  120. dynplaylist_ptr dynp = pl.dynamicCast< Tomahawk::DynamicPlaylist >();
  121. return QVariant::fromValue< Tomahawk::dynplaylist_ptr >( dynp );
  122. }
  123. case TrackCountRole:
  124. {
  125. if ( !pl.dynamicCast< Tomahawk::DynamicPlaylist >().isNull() && pl.dynamicCast< Tomahawk::DynamicPlaylist >()->mode() == OnDemand )
  126. return QString( QChar( 0x221E ) );
  127. else
  128. return pl->entries().count();
  129. }
  130. default:
  131. return QVariant();
  132. }
  133. }
  134. void
  135. RecentlyPlayedPlaylistsModel::playlistRevisionLoaded()
  136. {
  137. Playlist* p = qobject_cast< Playlist* >( sender() );
  138. Q_ASSERT( p );
  139. for ( int i = 0; i < m_recplaylists.size(); i++ )
  140. {
  141. if ( m_recplaylists[ i ]->guid() == p->guid() )
  142. {
  143. QModelIndex idx = index( i, 0, QModelIndex() );
  144. emit dataChanged( idx, idx );
  145. }
  146. }
  147. }
  148. void
  149. RecentlyPlayedPlaylistsModel::onSourceAdded( const Tomahawk::source_ptr& source )
  150. {
  151. connect( source.data(), SIGNAL( online() ),
  152. SLOT( sourceOnline() ) );
  153. connect( source->dbCollection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ),
  154. SLOT( loadFromSettings() ) );
  155. connect( source->dbCollection().data(), SIGNAL( playlistsDeleted( QList<Tomahawk::playlist_ptr> ) ),
  156. SLOT( onPlaylistsRemoved( QList<Tomahawk::playlist_ptr> ) ) );
  157. }
  158. void
  159. RecentlyPlayedPlaylistsModel::sourceOnline()
  160. {
  161. Source* s = qobject_cast< Source* >( sender() );
  162. Q_ASSERT( s );
  163. for ( int i = 0; i < m_recplaylists.size(); i++ )
  164. {
  165. if ( m_recplaylists[ i ]->author().data() == s )
  166. {
  167. QModelIndex idx = index( i, 0, QModelIndex() );
  168. emit dataChanged( idx, idx );
  169. }
  170. }
  171. }
  172. void
  173. RecentlyPlayedPlaylistsModel::onPlaylistsRemoved( QList< playlist_ptr > playlists )
  174. {
  175. foreach ( const playlist_ptr& pl, playlists )
  176. {
  177. if ( m_recplaylists.contains( pl ) )
  178. {
  179. m_artists.remove( pl );
  180. m_cached.remove( pl->guid() );
  181. int idx = m_recplaylists.indexOf( pl );
  182. beginRemoveRows( QModelIndex(), idx, idx );
  183. m_recplaylists.removeAt( idx );
  184. endRemoveRows();
  185. }
  186. }
  187. emit emptinessChanged( m_recplaylists.isEmpty() );
  188. }
  189. int
  190. RecentlyPlayedPlaylistsModel::rowCount( const QModelIndex& ) const
  191. {
  192. return m_recplaylists.count();
  193. }
  194. void
  195. RecentlyPlayedPlaylistsModel::plAdded( const QString& plguid, int sourceId )
  196. {
  197. Q_UNUSED( sourceId );
  198. const playlist_ptr& pl = Playlist::get( plguid );
  199. if ( !pl )
  200. return;
  201. onPlaylistsRemoved( QList< playlist_ptr >() << pl );
  202. beginInsertRows( QModelIndex(), 0, 0 );
  203. m_recplaylists.prepend( pl );;
  204. endInsertRows();
  205. emit emptinessChanged( m_recplaylists.isEmpty() );
  206. }
  207. void
  208. RecentlyPlayedPlaylistsModel::playlistChanged( Tomahawk::playlistinterface_ptr pli )
  209. {
  210. // ARG
  211. if ( !pli )
  212. return;
  213. if ( Playlist *pl = dynamic_cast< Playlist* >( pli.data() ) )
  214. {
  215. // look for it, qsharedpointer fail
  216. playlist_ptr ptr;
  217. foreach ( const playlist_ptr& test, m_recplaylists )
  218. {
  219. if ( test.data() == pl )
  220. ptr = test;
  221. }
  222. if ( ptr && m_artists.contains( ptr ) )
  223. {
  224. m_artists[ ptr ] = QString();
  225. }
  226. QModelIndex idx = index( m_recplaylists.indexOf( ptr ), 0, QModelIndex() );
  227. emit dataChanged( idx, idx );
  228. }
  229. }