File indexing completed on 2024-05-12 11:55:20

0001 /*
0002  *   Copyright 2010 by Marco Martin <mart@kde.org>
0003  *   Copyright 2019 by David Edmundson <davidedmundson@kde.org>
0004  *
0005  *   This program is free software; you can redistribute it and/or modify
0006  *   it under the terms of the GNU Library General Public License as
0007  *   published by the Free Software Foundation; either version 2, or
0008  *   (at your option) any later version.
0009  *
0010  *   This program is distributed in the hope that it will be useful,
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013  *   GNU General Public License for more details
0014  *
0015  *   You should have received a copy of the GNU Library General Public
0016  *   License along with this program; if not, write to the
0017  *   Free Software Foundation, Inc.,
0018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0019  */
0020 
0021 #ifndef KSORTFILTERPROXYMODEL_H
0022 #define KSORTFILTERPROXYMODEL_H
0023 
0024 #include <QAbstractItemModel>
0025 #include <QJSValue>
0026 #include <QQmlParserStatus>
0027 #include <QSortFilterProxyModel>
0028 #include <QVector>
0029 
0030 /**
0031  * @class SortFilterModel
0032  * @short Filter and sort an existing QAbstractItemModel
0033  *
0034  * @since 5.67
0035  */
0036 class KSortFilterProxyModel : public QSortFilterProxyModel, public QQmlParserStatus
0037 {
0038     Q_OBJECT
0039     Q_INTERFACES(QQmlParserStatus)
0040     /**
0041      * The source model of this sorting proxy model.
0042      */
0043     Q_PROPERTY(QAbstractItemModel *sourceModel READ sourceModel WRITE setModel NOTIFY sourceModelChanged)
0044 
0045     /**
0046      * The string for the filter, only rows with their filterRole matching filterString will be displayed
0047      */
0048     Q_PROPERTY(QString filterString READ filterString WRITE setFilterString NOTIFY filterStringChanged)
0049     /**
0050      * A JavaScript callable that can be used to perform advanced filters on a given row.
0051      * The callback is passed the source row, and source parent for a given row as arguments
0052      *
0053      * The callable's return value is evaluated as boolean to determine
0054      * whether the row is accepted (true) or filtered out (false). It overrides the default implementation
0055      * that uses filterRegExp or filterString; while filterCallback is set those two properties are
0056      * ignored. Attempts to write a non-callable to this property are silently ignored, but you can set
0057      * it to null.
0058      *
0059      * @code
0060      * filterRowCallback: function(source_row, source_parent) {
0061      *   return sourceModel.data(sourceModel.index(source_row, 0, source_parent), Qt.DisplayRole) == "...";
0062      * };
0063      * @endcode
0064      */
0065     Q_PROPERTY(QJSValue filterRowCallback READ filterRowCallback WRITE setFilterRowCallback NOTIFY filterRowCallbackChanged)
0066 
0067     /**
0068      * A JavaScript callable that can be used to perform advanced filters on a given column.
0069      * The callback is passed the source column, and source parent for a given column as arguments.
0070      *
0071      * @see filterRowCallback
0072      */
0073     Q_PROPERTY(QJSValue filterColumnCallback READ filterColumnCallback WRITE setFilterColumnCallback NOTIFY filterColumnCallbackChanged)
0074 
0075     /**
0076      * The role of the sourceModel on which the filter will be applied.
0077      * This can either be the numerical role value or the role name as a string.
0078      */
0079     Q_PROPERTY(QVariant filterRole READ filterRole WRITE setFilterRole NOTIFY filterRoleChanged)
0080 
0081     /**
0082      * The role of the sourceModel that will be used for sorting. if empty the order will be left unaltered
0083      * This can either be the numerical role value or the role name as a string.
0084      */
0085     Q_PROPERTY(QVariant sortRole READ sortRole WRITE setSortRole NOTIFY sortRoleChanged)
0086 
0087     /**
0088      * One of Qt.AscendingOrder or Qt.DescendingOrder
0089      */
0090     Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder NOTIFY sortOrderChanged)
0091 
0092     /**
0093      * Specify which column should be used for sorting
0094      * The default value is -1.
0095      * If \a sortRole is set, the default value is 0.
0096      */
0097     Q_PROPERTY(int sortColumn READ sortColumn WRITE setSortColumn NOTIFY sortColumnChanged)
0098 
0099     /**
0100      * The number of top level rows.
0101      */
0102     Q_PROPERTY(int count READ rowCount NOTIFY rowCountChanged)
0103 
0104 public:
0105     explicit KSortFilterProxyModel(QObject *parent = nullptr);
0106     ~KSortFilterProxyModel() override;
0107 
0108     void setModel(QAbstractItemModel *source);
0109 
0110     void setFilterRowCallback(const QJSValue &callback);
0111     QJSValue filterRowCallback() const;
0112 
0113     void setFilterString(const QString &filterString);
0114     QString filterString() const;
0115 
0116     void setFilterColumnCallback(const QJSValue &callback);
0117     QJSValue filterColumnCallback() const;
0118 
0119     void setFilterRole(const QVariant &role);
0120     QVariant filterRole() const;
0121 
0122     void setSortRole(const QVariant &role);
0123     QVariant sortRole() const;
0124 
0125     void setSortOrder(const Qt::SortOrder order);
0126     void setSortColumn(int column);
0127 
0128     void classBegin() override;
0129     void componentComplete() override;
0130 
0131     // TODO KF6: those two can be dropped once we depend on Qt 6.4
0132     Q_INVOKABLE bool removeRow(int row, const QModelIndex &parent = QModelIndex());
0133     Q_INVOKABLE bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
0134 
0135 public Q_SLOTS:
0136     /**
0137      * Invalidates the current filtering.
0138      *
0139      * This function should be called if you are implementing custom filtering through
0140      * filterRowCallback or filterColumnCallback, and your filter parameters have changed.
0141      *
0142      * @since 5.70
0143      */
0144     void invalidateFilter();
0145 
0146 Q_SIGNALS:
0147     void filterStringChanged();
0148     void filterRoleChanged();
0149     void sortRoleChanged();
0150     void sortOrderChanged();
0151     void sortColumnChanged();
0152     void sourceModelChanged(QObject *);
0153     void filterRowCallbackChanged(const QJSValue &);
0154     void filterColumnCallbackChanged(const QJSValue &);
0155     void rowCountChanged();
0156 
0157 protected:
0158     int roleNameToId(const QString &name) const;
0159     bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
0160     bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const override;
0161 
0162 protected Q_SLOTS:
0163     void syncRoleNames();
0164 
0165 private:
0166     bool m_componentCompleted = false;
0167     QVariant m_filterRole;
0168     QString m_filterString;
0169     QVariant m_sortRole;
0170     QJSValue m_filterRowCallback;
0171     QJSValue m_filterColumnCallback;
0172     QHash<QString, int> m_roleIds;
0173 };
0174 #endif