File indexing completed on 2025-01-05 04:25:40
0001 /**************************************************************************************** 0002 * Copyright (c) 2008 Andreas Muetzel <andreas.muetzel@gmx.net> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #define DEBUG_PREFIX "AlbumsModel" 0018 0019 #include "AlbumsModel.h" 0020 #include "AlbumsDefs.h" 0021 #include "AlbumItem.h" 0022 #include "AmarokMimeData.h" 0023 #include "core/support/Debug.h" 0024 #include <support/MetaUtility.h> 0025 #include "TrackItem.h" 0026 0027 #include <QCollator> 0028 #include <QFontMetrics> 0029 #include <QGuiApplication> 0030 0031 AlbumsModel::AlbumsModel( QObject *parent ) 0032 : QStandardItemModel( parent ) 0033 , m_rowHeight( 0 ) 0034 { 0035 connect( qApp, &QGuiApplication::fontDatabaseChanged, this, &AlbumsModel::updateRowHeight ); 0036 updateRowHeight(); 0037 } 0038 0039 int 0040 AlbumsModel::rowHeight() const 0041 { 0042 return m_rowHeight; 0043 } 0044 0045 void 0046 AlbumsModel::updateRowHeight() 0047 { 0048 QFont font; 0049 m_rowHeight = QFontMetrics( font ).height(); 0050 } 0051 0052 QVariant 0053 AlbumsModel::data( const QModelIndex &index, int role ) const 0054 { 0055 if( !index.isValid() ) 0056 return QVariant(); 0057 0058 if( role == Qt::DisplayRole ) 0059 { 0060 const QStandardItem *item = itemFromIndex( index ); 0061 0062 if( const auto album = dynamic_cast<const AlbumItem *>( item ) ) 0063 { 0064 QString name = album->data( NameRole ).toString(); 0065 int year = album->data( AlbumYearRole ).toInt(); 0066 0067 QStringList texts; 0068 texts << ((year > 0) ? QString( "%1 (%2)" ).arg( name, QString::number(year) ) : name); 0069 texts << album->data( AlbumLengthRole ).toString(); 0070 0071 return texts.join('\n'); 0072 } 0073 0074 if( const auto track = dynamic_cast<const TrackItem *>( item ) ) 0075 { 0076 bool isCompilation = track->data( AlbumCompilationRole ).toBool(); 0077 const QString &name = track->data( NameRole ).toString(); 0078 const QString &artist = track->data( TrackArtistRole ).toString(); 0079 QString length = " (" + Meta::msToPrettyTime( track->data( TrackLengthRole ).toInt() ) + ')'; 0080 QString number = track->data( TrackNumberRole ).toString() + ". "; 0081 QString middle = isCompilation ? QString( "%1 - %2" ).arg( artist, name ) : name; 0082 0083 return QStringList( { number, middle, length } ).join( ' ' ); 0084 } 0085 } 0086 0087 if( role == Qt::SizeHintRole ) 0088 { 0089 const QStandardItem *item = itemFromIndex( index ); 0090 int h = 4; 0091 h += (item->type() != AlbumType) ? m_rowHeight : static_cast<const AlbumItem *>( item )->iconSize(); 0092 return QSize( -1, h ); 0093 } 0094 return itemFromIndex( index )->data( role ); 0095 } 0096 0097 QMimeData* 0098 AlbumsModel::mimeData( const QModelIndexList &indices ) const 0099 { 0100 DEBUG_BLOCK 0101 if( indices.isEmpty() ) 0102 return nullptr; 0103 0104 Meta::TrackList tracks; 0105 foreach( const QModelIndex &index, indices ) 0106 tracks << tracksForIndex( index ); 0107 QSet< AmarokSharedPointer<Meta::Track> > tracksSet(tracks.begin(), tracks.end()); 0108 tracks = tracksSet.values(); 0109 0110 // http://doc.trolltech.com/4.4/qabstractitemmodel.html#mimeData 0111 // If the list of indexes is empty, or there are no supported MIME types, 0112 // 0 is returned rather than a serialized empty list. 0113 if( tracks.isEmpty() ) 0114 return nullptr; 0115 0116 AmarokMimeData *mimeData = new AmarokMimeData(); 0117 mimeData->setTracks( tracks ); 0118 return mimeData; 0119 } 0120 0121 Meta::TrackList 0122 AlbumsModel::tracksForIndex( const QModelIndex &index ) const 0123 { 0124 Meta::TrackList tracks; 0125 if( !index.isValid() ) 0126 return tracks; 0127 0128 if( hasChildren( index ) ) 0129 { 0130 for( int i = 0, rows = rowCount( index ); i < rows; ++i ) 0131 tracks << tracksForIndex( index.model()->index( i, 0, index ) ); 0132 } 0133 else if( QStandardItem *item = itemFromIndex( index ) ) 0134 { 0135 if( item->type() == TrackType ) 0136 { 0137 TrackItem* trackItem = static_cast<TrackItem*>( item ); 0138 if( trackItem ) 0139 tracks << trackItem->track(); 0140 } 0141 } 0142 return tracks; 0143 } 0144 0145 QStringList 0146 AlbumsModel::mimeTypes() const 0147 { 0148 QStringList types; 0149 types << AmarokMimeData::TRACK_MIME; 0150 return types; 0151 } 0152 0153 AlbumsProxyModel::AlbumsProxyModel( QObject *parent ) 0154 : QSortFilterProxyModel( parent ) 0155 , m_mode( SortByCreateDate ) 0156 , m_collator( new QCollator ) 0157 { 0158 m_collator->setNumericMode( true ); 0159 } 0160 0161 AlbumsProxyModel::~AlbumsProxyModel() 0162 { 0163 delete m_collator; 0164 } 0165 0166 bool 0167 AlbumsProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const 0168 { 0169 const QStandardItemModel *model = static_cast<QStandardItemModel*>( sourceModel() ); 0170 const QStandardItem *leftItem = model->itemFromIndex( left ); 0171 int type = leftItem->type(); 0172 if( type == AlbumType && m_mode == SortByCreateDate ) 0173 { 0174 const AlbumItem *leftAlbum = static_cast<const AlbumItem *>( leftItem ); 0175 const AlbumItem *rightAlbum = static_cast<const AlbumItem *>( model->itemFromIndex( right ) ); 0176 QDateTime leftMaxCreateDate, rightMaxCreateDate; 0177 foreach( Meta::TrackPtr track, leftAlbum->album()->tracks() ) 0178 if( track->createDate() > leftMaxCreateDate ) 0179 leftMaxCreateDate = track->createDate(); 0180 foreach( Meta::TrackPtr track, rightAlbum->album()->tracks() ) 0181 if( track->createDate() > rightMaxCreateDate ) 0182 rightMaxCreateDate = track->createDate(); 0183 return leftMaxCreateDate > rightMaxCreateDate; 0184 } 0185 else if( type == AlbumType || type == TrackType ) 0186 return leftItem->operator<( *model->itemFromIndex( right ) ); 0187 else 0188 { 0189 return m_collator->compare( leftItem->text(), model->itemFromIndex(right)->text() ) < 0; 0190 } 0191 } 0192 0193 bool 0194 AlbumsProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const 0195 { 0196 const QStandardItemModel *model = static_cast<QStandardItemModel*>( sourceModel() ); 0197 const QModelIndex &srcIndex = sourceModel()->index( sourceRow, 0, sourceParent ); 0198 const QStandardItem *item = model->itemFromIndex( srcIndex ); 0199 0200 if( item->data( NameRole ).toString().contains( filterRegExp() ) ) 0201 return true; 0202 0203 if( item->type() == AlbumType ) 0204 { 0205 for( int i = 0, count = model->rowCount( srcIndex ); i < count; ++i ) 0206 { 0207 const QModelIndex &kid = model->index( i, 0, srcIndex ); 0208 if( kid.data( NameRole ).toString().contains( filterRegExp() ) ) 0209 return true; 0210 } 0211 } 0212 return false; 0213 } 0214 0215 AlbumsProxyModel::Mode 0216 AlbumsProxyModel::mode() const 0217 { 0218 return m_mode; 0219 } 0220 0221 void 0222 AlbumsProxyModel::setMode( Mode mode ) 0223 { 0224 m_mode = mode; 0225 } 0226 0227 QHash<int, QByteArray> 0228 AlbumsProxyModel::roleNames() const 0229 { 0230 QHash<int, QByteArray> roleNames; 0231 0232 roleNames.insert( Qt::DisplayRole, "display" ); 0233 roleNames.insert( Qt::SizeHintRole, "size" ); 0234 roleNames.insert( NameRole, "name" ); 0235 roleNames.insert( AlbumCompilationRole, "albumIsCompilation" ); 0236 roleNames.insert( AlbumMaxTrackNumberRole, "albumMaxTrackNumber" ); 0237 roleNames.insert( AlbumLengthRole, "albumLength" ); 0238 roleNames.insert( AlbumYearRole, "albumYear" ); 0239 roleNames.insert( AlbumCoverRole, "albumCover" ); 0240 roleNames.insert( TrackArtistRole, "trackArtist" ); 0241 roleNames.insert( TrackNumberRole, "trackNumber" ); 0242 roleNames.insert( TrackLengthRole, "trackLength" ); 0243 0244 return roleNames; 0245 } 0246