File indexing completed on 2024-05-19 04:49:51

0001 /****************************************************************************************
0002  * Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@kde.org>                                *
0003  * Copyright (c) 2009 Téo Mrnjavac <teo@kde.org>                                        *
0004  * Copyright (c) 2010 Nanno Langstraat <langstr@gmail.com>                              *
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 "SortFilterProxy.h"
0020 
0021 #include "SortAlgorithms.h"
0022 #include "SortScheme.h"
0023 
0024 #include "core/support/Amarok.h"
0025 #include "amarokconfig.h"
0026 
0027 
0028 // Note: the 'sort' mode of QSortFilterProxyModel can Q_EMIT QAbstractItemModel::layoutChanged signals.
0029 
0030 // Note: the QSortFilterProxyModel sorting is always on, even with an empty SortScheme.
0031 //         - That case does not seem worth special-casing
0032 //         - Cleanly "disabling" QSortFilterProxyModel sort mode is "under-documented"
0033 //           and non-trivial (in Qt 4.6 at least).
0034 
0035 // Note: the sort and filter functions have been combined into 1 QSFPM because that gives
0036 //       optimal performance. If you have a reason to split sorting and filtering up into
0037 //       separate QSFPMs again: be sure to put the SortProxy closer to the bottom than
0038 //       the FilterProxy. Otherwise the FilterProxy's nicely-grouped 'rowsRemoved'
0039 //       signals (when changing the filter) get fragmented into thousands of pieces by
0040 //       the SortProxy, causing lousy performance on large playlists.
0041 
0042 
0043 namespace Playlist {
0044 
0045 SortFilterProxy::SortFilterProxy( AbstractModel *belowModel, QObject *parent )
0046     : ProxyBase( belowModel, parent )
0047 {
0048     // Tell QSortFilterProxyModel: keep the filter correct when the underlying source model changes.
0049     // Qt will do this by receiving the standard QAbstractItemModel signals: dataChanged, rowsInserted, etc.
0050     setDynamicSortFilter( true );
0051 
0052     // Tell QSortFilterProxyModel: activate sorting.
0053     sort( 0 );    // 0 is a dummy column.
0054 
0055     KConfigGroup config = Amarok::config(QStringLiteral("Playlist Search"));
0056     m_showOnlyMatches = config.readEntry( "ShowOnlyMatches", true );
0057 }
0058 
0059 SortFilterProxy::~SortFilterProxy()
0060 {
0061 }
0062 
0063 
0064 //! Sort-related functions
0065 
0066 bool
0067 SortFilterProxy::lessThan( const QModelIndex & sourceModelIndexA, const QModelIndex & sourceModelIndexB ) const
0068 {
0069     int rowA = sourceModelIndexA.row();
0070     int rowB = sourceModelIndexB.row();
0071     return m_mlt( sourceModel(), rowA, rowB );
0072 }
0073 
0074 bool
0075 SortFilterProxy::isSorted()
0076 {
0077     return m_scheme.length() > 0;
0078 }
0079 
0080 void
0081 SortFilterProxy::updateSortMap( const SortScheme &scheme )
0082 {
0083     m_scheme = scheme;
0084     m_mlt.setSortScheme( m_scheme );
0085 
0086     invalidate();    // Tell QSortFilterProxyModel: re-sort
0087 }
0088 
0089 
0090 //! Filter-related functions
0091 
0092 void
0093 SortFilterProxy::clearSearchTerm()
0094 {
0095     find( QString(), 0 );
0096     ProxyBase::clearSearchTerm();
0097 }
0098 
0099 void
0100 SortFilterProxy::filterUpdated()
0101 {
0102     if ( m_showOnlyMatches )
0103         invalidateFilter();    // Tell QSortFilterProxyModel: re-filter
0104     //else
0105     //  Search criteria are not being used for filtering, so we can ignore the update
0106 }
0107 
0108 int
0109 SortFilterProxy::find( const QString &searchTerm, int searchFields )
0110 {
0111     m_currentSearchTerm = searchTerm;
0112     m_currentSearchFields = searchFields;
0113 
0114     // Don't call 'filterUpdated()': our client must do that as part of the API.
0115     // This allows client 'PrettyListView' to give the user the time to type a few
0116     // characters before we do a filter run that might block for a few seconds.
0117 
0118     return -1;
0119 }
0120 
0121 void
0122 SortFilterProxy::showOnlyMatches( bool onlyMatches )
0123 {
0124     m_showOnlyMatches = onlyMatches;
0125 
0126     //make sure to update model when mode changes ( as we might have ignored any
0127     //number of changes to the search term )
0128     invalidateFilter();    // Tell QSortFilterProxyModel: re-filter.
0129 }
0130 
0131 bool
0132 SortFilterProxy::filterAcceptsRow( int sourceModelRow, const QModelIndex &sourceModelParent ) const
0133 {
0134     Q_UNUSED( sourceModelParent );
0135 
0136     if ( m_showOnlyMatches )
0137     {
0138         if ( m_currentSearchTerm.isEmpty() )
0139             return true;
0140         else
0141             return rowMatch( sourceModelRow, m_currentSearchTerm, m_currentSearchFields );
0142     } else
0143         return true;
0144 }
0145 
0146 
0147 }    //namespace Playlist
0148