File indexing completed on 2024-04-21 15:01:32

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2007 Rafael Fernández López <ereslibre@kde.org>
0004     SPDX-FileCopyrightText: 2007 John Tapsell <tapsell@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #ifndef KCATEGORIZEDSORTFILTERPROXYMODEL_H
0010 #define KCATEGORIZEDSORTFILTERPROXYMODEL_H
0011 
0012 #include <QSortFilterProxyModel>
0013 #include <memory>
0014 
0015 #include <kitemviews_export.h>
0016 class KCategorizedSortFilterProxyModelPrivate;
0017 
0018 class QItemSelection;
0019 
0020 /**
0021  * @class KCategorizedSortFilterProxyModel kcategorizedsortfilterproxymodel.h KCategorizedSortFilterProxyModel
0022  *
0023  * This class lets you categorize a view. It is meant to be used along with
0024  * KCategorizedView class.
0025  *
0026  * In general terms all you need to do is to reimplement subSortLessThan() and
0027  * compareCategories() methods. In order to make categorization work, you need
0028  * to also call setCategorizedModel() class to enable it, since the categorization
0029  * is disabled by default.
0030  *
0031  * @see KCategorizedView
0032  *
0033  * @author Rafael Fernández López <ereslibre@kde.org>
0034  */
0035 class KITEMVIEWS_EXPORT KCategorizedSortFilterProxyModel : public QSortFilterProxyModel
0036 {
0037 public:
0038     enum AdditionalRoles {
0039         // Note: use printf "0x%08X\n" $(($RANDOM*$RANDOM))
0040         // to define additional roles.
0041         CategoryDisplayRole = 0x17CE990A, ///< This role is used for asking the category to a given index
0042 
0043         CategorySortRole = 0x27857E60, ///< This role is used for sorting categories. You can return a
0044                                        ///< string or a long long value. Strings will be sorted alphabetically
0045                                        ///< while long long will be sorted by their value. Please note that this
0046                                        ///< value won't be shown on the view, is only for sorting purposes. What will
0047                                        ///< be shown as "Category" on the view will be asked with the role
0048                                        ///< CategoryDisplayRole.
0049     };
0050 
0051     KCategorizedSortFilterProxyModel(QObject *parent = nullptr);
0052     ~KCategorizedSortFilterProxyModel() override;
0053 
0054     /**
0055      * Overridden from QSortFilterProxyModel. Sorts the source model using
0056      * @p column for the given @p order.
0057      */
0058     void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
0059 
0060     /**
0061      * @return whether the model is categorized or not. Disabled by default.
0062      */
0063     bool isCategorizedModel() const;
0064 
0065     /**
0066      * Enables or disables the categorization feature.
0067      *
0068      * @param categorizedModel whether to enable or disable the categorization feature.
0069      */
0070     void setCategorizedModel(bool categorizedModel);
0071 
0072     /**
0073      * @return the column being used for sorting.
0074      */
0075     int sortColumn() const;
0076 
0077     /**
0078      * @return the sort order being used for sorting.
0079      */
0080     Qt::SortOrder sortOrder() const;
0081 
0082     /**
0083      * Set if the sorting using CategorySortRole will use a natural comparison
0084      * in the case that strings were returned. If enabled, QCollator
0085      * will be used for sorting.
0086      *
0087      * @param sortCategoriesByNaturalComparison whether to sort using a natural comparison or not.
0088      */
0089     void setSortCategoriesByNaturalComparison(bool sortCategoriesByNaturalComparison);
0090 
0091     /**
0092      * @return whether it is being used a natural comparison for sorting. Enabled by default.
0093      */
0094     bool sortCategoriesByNaturalComparison() const;
0095 
0096 #if KITEMVIEWS_ENABLE_DEPRECATED_SINCE(4, 4)
0097     /**
0098      * Does a natural comparing of the strings. A negative value is returned if \a a
0099      * is smaller than \a b. A positive value is returned if \a a is greater than \a b. 0
0100      * is returned if both values are equal.
0101      * @deprecated Since 4.4. Use QCollator instead.
0102      */
0103     KITEMVIEWS_DEPRECATED_VERSION(4, 4, "Use QCollator")
0104     static int naturalCompare(const QString &a, const QString &b);
0105 #endif
0106 
0107 protected:
0108     /**
0109      * Overridden from QSortFilterProxyModel. If you are subclassing
0110      * KCategorizedSortFilterProxyModel, you will probably not need to reimplement this
0111      * method.
0112      *
0113      * It calls compareCategories() to sort by category.  If the both items are in the
0114      * same category (i.e. compareCategories returns 0), then subSortLessThan is called.
0115      *
0116      * @return Returns true if the item @p left is less than the item @p right when sorting.
0117      *
0118      * @warning You usually won't need to reimplement this method when subclassing
0119      *          from KCategorizedSortFilterProxyModel.
0120      */
0121     bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
0122 
0123     /**
0124      * This method has a similar purpose as lessThan() has on QSortFilterProxyModel.
0125      * It is used for sorting items that are in the same category.
0126      *
0127      * @return Returns true if the item @p left is less than the item @p right when sorting.
0128      */
0129     virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const;
0130 
0131     /**
0132      * This method compares the category of the @p left index with the category
0133      * of the @p right index.
0134      *
0135      * Internally and if not reimplemented, this method will ask for @p left and
0136      * @p right models for role CategorySortRole. In order to correctly sort
0137      * categories, the data() method of the model should return a qlonglong (or numeric) value, or
0138      * a QString object. QString objects will be sorted with QString::localeAwareCompare if
0139      * sortCategoriesByNaturalComparison() is true.
0140      *
0141      * @note Please have present that:
0142      *       QString(QChar(QChar::ObjectReplacementCharacter)) >
0143      *       QString(QChar(QChar::ReplacementCharacter)) >
0144      *       [ all possible strings ] >
0145      *       QString();
0146      *
0147      *       This means that QString() will be sorted the first one, while
0148      *       QString(QChar(QChar::ObjectReplacementCharacter)) and
0149      *       QString(QChar(QChar::ReplacementCharacter)) will be sorted in last
0150      *       position.
0151      *
0152      * @warning Please note that data() method of the model should return always
0153      *          information of the same type. If you return a QString for an index,
0154      *          you should return always QStrings for all indexes for role CategorySortRole
0155      *          in order to correctly sort categories. You can't mix by returning
0156      *          a QString for one index, and a qlonglong for other.
0157      *
0158      * @note If you need a more complex layout, you will have to reimplement this
0159      *       method.
0160      *
0161      * @return A negative value if the category of @p left should be placed before the
0162      *         category of @p right. 0 if @p left and @p right are on the same category, and
0163      *         a positive value if the category of @p left should be placed after the
0164      *         category of @p right.
0165      */
0166     virtual int compareCategories(const QModelIndex &left, const QModelIndex &right) const;
0167 
0168 private:
0169     std::unique_ptr<KCategorizedSortFilterProxyModelPrivate> const d;
0170 };
0171 
0172 #endif // KCATEGORIZEDSORTFILTERPROXYMODEL_H