/src/libtomahawk/playlist/trackproxymodel.cpp

http://github.com/tomahawk-player/tomahawk · C++ · 299 lines · 227 code · 54 blank · 18 comment · 61 complexity · a96984eaa47a6945754e043b02204e9c MD5 · raw file

  1. /* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2. *
  3. * Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
  4. *
  5. * Tomahawk is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * Tomahawk is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "trackproxymodel.h"
  19. #include <QTreeView>
  20. #include "trackproxymodelplaylistinterface.h"
  21. #include "artist.h"
  22. #include "album.h"
  23. #include "query.h"
  24. #include "utils/logger.h"
  25. TrackProxyModel::TrackProxyModel( QObject* parent )
  26. : QSortFilterProxyModel( parent )
  27. , m_model( 0 )
  28. , m_showOfflineResults( true )
  29. {
  30. setFilterCaseSensitivity( Qt::CaseInsensitive );
  31. setSortCaseSensitivity( Qt::CaseInsensitive );
  32. setDynamicSortFilter( true );
  33. setSourceTrackModel( 0 );
  34. }
  35. void
  36. TrackProxyModel::setSourceModel( QAbstractItemModel* model )
  37. {
  38. Q_UNUSED( model );
  39. qDebug() << "Explicitly use setSourceTrackModel instead";
  40. Q_ASSERT( false );
  41. }
  42. void
  43. TrackProxyModel::setSourceTrackModel( TrackModel* sourceModel )
  44. {
  45. m_model = sourceModel;
  46. if ( m_model && m_model->metaObject()->indexOfSignal( "trackCountChanged(uint)" ) > -1 )
  47. connect( m_model, SIGNAL( trackCountChanged( unsigned int ) ), playlistInterface().data(), SIGNAL( sourceTrackCountChanged( unsigned int ) ) );
  48. QSortFilterProxyModel::setSourceModel( m_model );
  49. }
  50. bool
  51. TrackProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
  52. {
  53. TrackModelItem* pi = itemFromIndex( sourceModel()->index( sourceRow, 0, sourceParent ) );
  54. if ( !pi )
  55. return false;
  56. const Tomahawk::query_ptr& q = pi->query();
  57. if( q.isNull() ) // uh oh? filter out invalid queries i guess
  58. return false;
  59. Tomahawk::result_ptr r;
  60. if ( q->numResults() )
  61. r = q->results().first();
  62. if ( !m_showOfflineResults && !r.isNull() && !r->isOnline() )
  63. return false;
  64. if ( filterRegExp().isEmpty() )
  65. return true;
  66. QStringList sl = filterRegExp().pattern().split( " ", QString::SkipEmptyParts );
  67. foreach( QString s, sl )
  68. {
  69. s = s.toLower();
  70. if ( !r.isNull() )
  71. {
  72. if ( !r->artist()->name().toLower().contains( s ) &&
  73. !r->album()->name().toLower().contains( s ) &&
  74. !r->track().toLower().contains( s ) )
  75. {
  76. return false;
  77. }
  78. }
  79. else
  80. {
  81. if ( !q->artist().toLower().contains( s ) &&
  82. !q->album().toLower().contains( s ) &&
  83. !q->track().toLower().contains( s ) )
  84. {
  85. return false;
  86. }
  87. }
  88. }
  89. return true;
  90. }
  91. void
  92. TrackProxyModel::remove( const QModelIndex& index )
  93. {
  94. if ( !sourceModel() )
  95. return;
  96. if ( !index.isValid() )
  97. return;
  98. sourceModel()->remove( mapToSource( index ) );
  99. }
  100. void
  101. TrackProxyModel::remove( const QModelIndexList& indexes )
  102. {
  103. if ( !sourceModel() )
  104. return;
  105. QList<QPersistentModelIndex> pil;
  106. foreach ( const QModelIndex& idx, indexes )
  107. {
  108. if ( idx.isValid() )
  109. pil << mapToSource( idx );
  110. }
  111. sourceModel()->remove( pil );
  112. }
  113. void
  114. TrackProxyModel::remove( const QList< QPersistentModelIndex >& indexes )
  115. {
  116. if ( !sourceModel() )
  117. return;
  118. QList<QPersistentModelIndex> pil;
  119. foreach ( const QPersistentModelIndex& idx, indexes )
  120. {
  121. if ( idx.isValid() )
  122. pil << mapToSource( idx );
  123. }
  124. sourceModel()->remove( pil );
  125. }
  126. bool
  127. TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
  128. {
  129. TrackModelItem* p1 = itemFromIndex( left );
  130. TrackModelItem* p2 = itemFromIndex( right );
  131. if ( !p1 )
  132. return true;
  133. if ( !p2 )
  134. return false;
  135. const Tomahawk::query_ptr& q1 = p1->query();
  136. const Tomahawk::query_ptr& q2 = p2->query();
  137. QString artist1 = q1->artistSortname();
  138. QString artist2 = q2->artistSortname();
  139. QString album1 = q1->album();
  140. QString album2 = q2->album();
  141. QString track1 = q1->track();
  142. QString track2 = q2->track();
  143. unsigned int albumpos1 = 0, albumpos2 = 0;
  144. unsigned int discnumber1 = 0, discnumber2 = 0;
  145. unsigned int bitrate1 = 0, bitrate2 = 0;
  146. unsigned int mtime1 = 0, mtime2 = 0;
  147. unsigned int size1 = 0, size2 = 0;
  148. qint64 id1 = 0, id2 = 0;
  149. if ( q1->numResults() )
  150. {
  151. const Tomahawk::result_ptr& r = q1->results().at( 0 );
  152. artist1 = r->artist()->sortname();
  153. album1 = r->album()->name();
  154. track1 = r->track();
  155. albumpos1 = r->albumpos();
  156. discnumber1 = r->discnumber();
  157. bitrate1 = r->bitrate();
  158. mtime1 = r->modificationTime();
  159. id1 = r->trackId();
  160. size1 = r->size();
  161. }
  162. if ( q2->numResults() )
  163. {
  164. const Tomahawk::result_ptr& r = q2->results().at( 0 );
  165. artist2 = r->artist()->sortname();
  166. album2 = r->album()->name();
  167. track2 = r->track();
  168. albumpos2 = r->albumpos();
  169. discnumber2 = r->discnumber();
  170. bitrate2 = r->bitrate();
  171. mtime2 = r->modificationTime();
  172. id2 = r->trackId();
  173. size2 = r->size();
  174. }
  175. // This makes it a stable sorter and prevents items from randomly jumping about.
  176. if ( id1 == id2 )
  177. {
  178. id1 = (qint64)&q1;
  179. id2 = (qint64)&q2;
  180. }
  181. if ( left.column() == TrackModel::Artist ) // sort by artist
  182. {
  183. if ( artist1 == artist2 )
  184. {
  185. if ( album1 == album2 )
  186. {
  187. if( discnumber1 == discnumber2 )
  188. {
  189. if ( albumpos1 == albumpos2 )
  190. return id1 < id2;
  191. return albumpos1 < albumpos2;
  192. }
  193. return discnumber1 < discnumber2;
  194. }
  195. return QString::localeAwareCompare( album1, album2 ) < 0;
  196. }
  197. return QString::localeAwareCompare( artist1, artist2 ) < 0;
  198. }
  199. else if ( left.column() == TrackModel::Album ) // sort by album
  200. {
  201. if ( album1 == album2 )
  202. {
  203. if( discnumber1 == discnumber2 )
  204. {
  205. if ( albumpos1 == albumpos2 )
  206. return id1 < id2;
  207. return albumpos1 < albumpos2;
  208. }
  209. return discnumber1 < discnumber2;
  210. }
  211. return QString::localeAwareCompare( album1, album2 ) < 0;
  212. }
  213. else if ( left.column() == TrackModel::Bitrate ) // sort by bitrate
  214. {
  215. if ( bitrate1 == bitrate2 )
  216. return id1 < id2;
  217. return bitrate1 < bitrate2;
  218. }
  219. else if ( left.column() == TrackModel::Age ) // sort by mtime
  220. {
  221. if ( mtime1 == mtime2 )
  222. return id1 < id2;
  223. return mtime1 < mtime2;
  224. }
  225. else if ( left.column() == TrackModel::Filesize ) // sort by file size
  226. {
  227. if ( size1 == size2 )
  228. return id1 < id2;
  229. return size1 < size2;
  230. }
  231. const QString& lefts = sourceModel()->data( left ).toString();
  232. const QString& rights = sourceModel()->data( right ).toString();
  233. if ( lefts == rights )
  234. return id1 < id2;
  235. return QString::localeAwareCompare( lefts, rights ) < 0;
  236. }
  237. Tomahawk::playlistinterface_ptr
  238. TrackProxyModel::playlistInterface()
  239. {
  240. if ( m_playlistInterface.isNull() )
  241. {
  242. m_playlistInterface = Tomahawk::playlistinterface_ptr( new Tomahawk::TrackProxyModelPlaylistInterface( this ) );
  243. }
  244. return m_playlistInterface;
  245. }