File indexing completed on 2024-05-05 04:47:28
0001 /**************************************************************************************** 0002 * Copyright (c) 2007 Nikolaj Hald Nielsen <nhn@kde.org> * 0003 * Copyright (c) 2008 Seb Ruiz <ruiz@kde.org> * 0004 * Copyright (c) 2013 Ralf Engels <ralf-engels@gmx.de> * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify it under * 0007 * the terms of the GNU General Public License as published by the Free Software * 0008 * Foundation; either version 2 of the License, or (at your option) any later * 0009 * version. * 0010 * * 0011 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0013 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License along with * 0016 * this program. If not, see <http://www.gnu.org/licenses/>. * 0017 ****************************************************************************************/ 0018 0019 #include "CollectionSortFilterProxyModel.h" 0020 0021 #include "amarokconfig.h" 0022 #include "browsers/CollectionTreeItem.h" 0023 #include "core/meta/Meta.h" 0024 #include "core/support/Debug.h" 0025 #include "widgets/PrettyTreeRoles.h" 0026 0027 #include <QCollator> 0028 #include <QVariant> 0029 #include <QString> 0030 0031 CollectionSortFilterProxyModel::CollectionSortFilterProxyModel( QObject * parent ) 0032 : QSortFilterProxyModel( parent ) 0033 , m_col( new QCollator ) 0034 { 0035 setSortLocaleAware( true ); 0036 0037 setSortRole( PrettyTreeRoles::SortRole ); 0038 setFilterRole( PrettyTreeRoles::FilterRole ); 0039 setSortCaseSensitivity( Qt::CaseInsensitive ); 0040 setFilterCaseSensitivity( Qt::CaseInsensitive ); 0041 0042 setDynamicSortFilter( true ); 0043 0044 m_col->setCaseSensitivity( Qt::CaseInsensitive ); 0045 } 0046 0047 0048 CollectionSortFilterProxyModel::~CollectionSortFilterProxyModel() 0049 { 0050 delete m_col; 0051 } 0052 0053 bool 0054 CollectionSortFilterProxyModel::hasChildren(const QModelIndex & parent) const 0055 { 0056 QModelIndex sourceParent = mapToSource(parent); 0057 return sourceModel()->hasChildren(sourceParent); 0058 } 0059 0060 bool 0061 CollectionSortFilterProxyModel::filterAcceptsRow( int source_row, const QModelIndex& source_parent ) const 0062 { 0063 bool stringAccepted = QSortFilterProxyModel::filterAcceptsRow( source_row, source_parent ); 0064 0065 if( AmarokConfig::showYears()) 0066 { 0067 QModelIndex index = sourceModel()->index( source_row, 0, source_parent ); 0068 if( treeItem( index )->isAlbumItem() ) 0069 { 0070 bool yearLoaded = index.data( PrettyTreeRoles::YearRole ).toInt() >= 0; 0071 return yearLoaded && stringAccepted; 0072 } 0073 } 0074 0075 return stringAccepted; 0076 } 0077 0078 bool 0079 CollectionSortFilterProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const 0080 { 0081 CollectionTreeItem *leftItem = treeItem( left ); 0082 CollectionTreeItem *rightItem = treeItem( right ); 0083 0084 // various artists and no label items are always at the top 0085 if( !leftItem || leftItem->isVariousArtistItem() || leftItem->isNoLabelItem() ) 0086 return true; 0087 if( !rightItem || rightItem->isVariousArtistItem() || rightItem->isNoLabelItem() ) 0088 return false; 0089 0090 if( leftItem->isTrackItem() && rightItem->isTrackItem() ) 0091 return lessThanTrack( left, right ); 0092 0093 if( leftItem->isAlbumItem() && rightItem->isAlbumItem() ) 0094 return lessThanAlbum( left, right ); 0095 0096 if( leftItem->isDataItem() && rightItem->isDataItem() ) 0097 return lessThanItem( left, right ); 0098 0099 return QSortFilterProxyModel::lessThan( left, right ); 0100 } 0101 0102 bool 0103 CollectionSortFilterProxyModel::lessThanTrack( const QModelIndex &left, const QModelIndex &right ) const 0104 { 0105 const Meta::TrackPtr leftTrack = Meta::TrackPtr::dynamicCast( treeItem(left)->data() ); 0106 const Meta::TrackPtr rightTrack = Meta::TrackPtr::dynamicCast( treeItem(right)->data() ); 0107 if( !leftTrack || !rightTrack ) 0108 { 0109 DEBUG_BLOCK 0110 error() << "Should never have compared these two indexes" 0111 << left.data(Qt::DisplayRole) << "and" << right.data(Qt::DisplayRole); 0112 return QSortFilterProxyModel::lessThan( left, right ); 0113 } 0114 0115 if( AmarokConfig::showTrackNumbers() ) 0116 { 0117 //First compare by disc number 0118 if ( leftTrack->discNumber() < rightTrack->discNumber() ) 0119 return true; 0120 if ( leftTrack->discNumber() > rightTrack->discNumber() ) 0121 return false; 0122 0123 //Disc #'s are equal, compare by track number 0124 if( leftTrack->trackNumber() < rightTrack->trackNumber() ) 0125 return true; 0126 if( leftTrack->trackNumber() > rightTrack->trackNumber() ) 0127 return false; 0128 } 0129 0130 // compare by name 0131 { 0132 int comp = m_col->compare( leftTrack->sortableName(), rightTrack->sortableName() ); 0133 if( comp < 0 ) 0134 return true; 0135 if( comp > 0 ) 0136 return false; 0137 } 0138 0139 return leftTrack.data() < rightTrack.data(); // prevent expanded tracks from switching places (if that ever happens) 0140 } 0141 0142 bool 0143 CollectionSortFilterProxyModel::lessThanAlbum( const QModelIndex &left, const QModelIndex &right ) const 0144 { 0145 Meta::AlbumPtr leftAlbum = Meta::AlbumPtr::dynamicCast( treeItem(left)->data() ); 0146 Meta::AlbumPtr rightAlbum = Meta::AlbumPtr::dynamicCast( treeItem(right)->data() ); 0147 0148 if( !leftAlbum || !rightAlbum ) 0149 { 0150 DEBUG_BLOCK 0151 error() << "Should never have compared these two indexes" 0152 << left.data(Qt::DisplayRole) << "and" << right.data(Qt::DisplayRole); 0153 return QSortFilterProxyModel::lessThan( left, right ); 0154 } 0155 0156 // compare by year 0157 if( AmarokConfig::showYears() ) 0158 { 0159 int leftYear = left.data( PrettyTreeRoles::YearRole ).toInt(); 0160 int rightYear = right.data( PrettyTreeRoles::YearRole ).toInt(); 0161 0162 if( leftYear < rightYear ) 0163 return false; // left album is newer 0164 if( leftYear > rightYear ) 0165 return true; 0166 } 0167 0168 // compare by name 0169 { 0170 int comp = m_col->compare( leftAlbum->sortableName(), rightAlbum->sortableName() ); 0171 if( comp < 0 ) 0172 return true; 0173 if( comp > 0 ) 0174 return false; 0175 } 0176 0177 return leftAlbum.data() < rightAlbum.data(); // prevent expanded albums from switching places 0178 } 0179 0180 bool 0181 CollectionSortFilterProxyModel::lessThanItem( const QModelIndex &left, const QModelIndex &right ) const 0182 { 0183 Meta::DataPtr leftData = treeItem(left)->data(); 0184 Meta::DataPtr rightData = treeItem(right)->data(); 0185 0186 if( !leftData || !rightData ) 0187 { 0188 DEBUG_BLOCK 0189 error() << "Should never have compared these two indexes" 0190 << left.data(Qt::DisplayRole) << "and" << right.data(Qt::DisplayRole); 0191 return QSortFilterProxyModel::lessThan( left, right ); 0192 } 0193 0194 // compare by name 0195 { 0196 int comp = m_col->compare( leftData->sortableName(), rightData->sortableName() ); 0197 if( comp < 0 ) 0198 return true; 0199 if( comp > 0 ) 0200 return false; 0201 } 0202 0203 return leftData.data() < rightData.data(); // prevent expanded data from switching places 0204 } 0205 0206 inline CollectionTreeItem* 0207 CollectionSortFilterProxyModel::treeItem( const QModelIndex &index ) const 0208 { 0209 return static_cast<CollectionTreeItem*>( index.internalPointer() ); 0210 }