File indexing completed on 2025-01-05 04:55:04

0001 /*
0002     Copyright (c) 2009 Stephen Kelly <steveire@gmail.com>
0003 
0004     This library is free software; you can redistribute it and/or modify it
0005     under the terms of the GNU Library General Public License as published by
0006     the Free Software Foundation; either version 2 of the License, or (at your
0007     option) any later version.
0008 
0009     This library is distributed in the hope that it will be useful, but WITHOUT
0010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
0012     License for more details.
0013 
0014     You should have received a copy of the GNU Library General Public License
0015     along with this library; see the file COPYING.LIB.  If not, write to the
0016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0017     02110-1301, USA.
0018 */
0019 
0020 #ifndef KRECURSIVEFILTERPROXYMODEL_H
0021 #define KRECURSIVEFILTERPROXYMODEL_H
0022 
0023 #include <QtCore/QSortFilterProxyModel>
0024 
0025 class KRecursiveFilterProxyModelPrivate;
0026 
0027 /**
0028   @class KRecursiveFilterProxyModel krecursivefilterproxymodel.h KRecursiveFilterProxyModel
0029 
0030   @brief Implements recursive filtering of models
0031 
0032   Until Qt 5.10, QSortFilterProxyModel did not recurse when invoking a filtering stage, so that
0033   if a particular row is filtered out, its children are not even checked to see if they match the filter.
0034 
0035   If you can depend on Qt >= 5.10, then just use QSortFilterProxyModel::setRecursiveFiltering(true),
0036   and you don't need to use KRecursiveFilterProxyModel.
0037 
0038   For example, given a source model:
0039 
0040   @verbatim
0041     - A
0042     - B
0043     - - C
0044     - - - D
0045     - - - - E
0046     - - - F
0047     - - G
0048     - - H
0049     - I
0050   @endverbatim
0051 
0052   If a QSortFilterProxyModel is used with a filter matching A, D, G and I, the QSortFilterProxyModel will contain
0053 
0054   @verbatim
0055     - A
0056     - I
0057   @endverbatim
0058 
0059   That is, even though D and E match the filter, they are not represented in the proxy model because B does not
0060   match the filter and is filtered out.
0061 
0062   The KRecursiveFilterProxyModel checks child indexes for filter matching and ensures that all matching indexes
0063   are represented in the model.
0064 
0065   In the above example, the KRecursiveFilterProxyModel will contain
0066 
0067   @verbatim
0068     - A
0069     - B
0070     - - C
0071     - - - D
0072     - - G
0073     - I
0074   @endverbatim
0075 
0076   That is, the leaves in the model match the filter, but not necessarily the inner branches.
0077 
0078   QSortFilterProxyModel provides the virtual method filterAcceptsRow to allow custom filter implementations.
0079   Custom filter implementations can be written for KRecuriveFilterProxyModel using the acceptRow virtual method.
0080 
0081   Note that using this proxy model is additional overhead compared to QSortFilterProxyModel as every index in the
0082   model must be visited and queried.
0083 
0084   @author Stephen Kelly <steveire@gmail.com>
0085 
0086   @since 4.5
0087 
0088 */
0089 class KRecursiveFilterProxyModel : public QSortFilterProxyModel
0090 {
0091     Q_OBJECT
0092 public:
0093     /**
0094       Constructor
0095     */
0096     explicit KRecursiveFilterProxyModel(QObject *parent = nullptr);
0097 
0098     /**
0099       Destructor
0100     */
0101     virtual ~KRecursiveFilterProxyModel();
0102 
0103     /** @reimp */
0104     void setSourceModel(QAbstractItemModel *model) Q_DECL_OVERRIDE;
0105 
0106     /**
0107      * @reimplemented
0108      */
0109     QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits = 1,
0110                                   Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchStartsWith | Qt::MatchWrap)) const Q_DECL_OVERRIDE;
0111 
0112 protected:
0113     /**
0114       Reimplement this method for custom filtering strategies.
0115     */
0116     virtual bool acceptRow(int sourceRow, const QModelIndex &sourceParent) const;
0117 
0118     /** @reimp */
0119     bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE;
0120 
0121     KRecursiveFilterProxyModelPrivate *const d_ptr;
0122 
0123 private:
0124     //@cond PRIVATE
0125     Q_DECLARE_PRIVATE(KRecursiveFilterProxyModel)
0126 
0127     Q_PRIVATE_SLOT(d_func(), void sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right, const QVector<int> &roles = QVector<int>()))
0128     Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end))
0129     Q_PRIVATE_SLOT(d_func(), void sourceRowsInserted(const QModelIndex &source_parent, int start, int end))
0130     Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end))
0131     Q_PRIVATE_SLOT(d_func(), void sourceRowsRemoved(const QModelIndex &source_parent, int start, int end))
0132     //@endcond
0133 };
0134 
0135 #endif