1 /*
2     SPDX-FileCopyrightText: 2009 Stephen Kelly <steveire@gmail.com>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #ifndef KRECURSIVEFILTERPROXYMODEL_H
8 #define KRECURSIVEFILTERPROXYMODEL_H
9 
10 #include "kitemmodels_export.h"
11 
12 #if KITEMMODELS_ENABLE_DEPRECATED_SINCE(5, 65)
13 #include <QSortFilterProxyModel>
14 
15 #include <memory>
16 
17 class KRecursiveFilterProxyModelPrivate;
18 
19 /**
20   @class KRecursiveFilterProxyModel krecursivefilterproxymodel.h KRecursiveFilterProxyModel
21 
22   @brief Implements recursive filtering of models
23 
24   Until Qt 5.10, QSortFilterProxyModel did not recurse when invoking a filtering stage, so that
25   if a particular row is filtered out, its children are not even checked to see if they match the filter.
26 
27   If you can depend on Qt >= 5.10, then just use QSortFilterProxyModel::setRecursiveFilteringEnabled(true),
28   and you don't need to use KRecursiveFilterProxyModel.
29 
30   For example, given a source model:
31 
32   @verbatim
33     - A
34     - B
35     - - C
36     - - - D
37     - - - - E
38     - - - F
39     - - G
40     - - H
41     - I
42   @endverbatim
43 
44   If a QSortFilterProxyModel is used with a filter matching A, D, G and I, the QSortFilterProxyModel will contain
45 
46   @verbatim
47     - A
48     - I
49   @endverbatim
50 
51   That is, even though D and G match the filter, they are not represented in the proxy model because B does not
52   match the filter and is filtered out.
53 
54   The KRecursiveFilterProxyModel checks child indexes for filter matching and ensures that all matching indexes
55   are represented in the model.
56 
57   In the above example, the KRecursiveFilterProxyModel will contain
58 
59   @verbatim
60     - A
61     - B
62     - - C
63     - - - D
64     - - G
65     - I
66   @endverbatim
67 
68   That is, the leaves in the model match the filter, but not necessarily the inner branches.
69 
70   QSortFilterProxyModel provides the virtual method filterAcceptsRow to allow custom filter implementations.
71   Custom filter implementations can be written for KRecuriveFilterProxyModel using the acceptRow virtual method.
72 
73   Note that using this proxy model is additional overhead compared to QSortFilterProxyModel as every index in the
74   model must be visited and queried.
75 
76   @author Stephen Kelly <steveire@gmail.com>
77 
78   @since 4.5
79 
80   @deprecated since 5.65, use QSortFilterProxyModel::setRecursiveFilteringEnabled(true) instead. See detailed description.
81 */
82 class KITEMMODELS_EXPORT KRecursiveFilterProxyModel : public QSortFilterProxyModel
83 {
84     Q_OBJECT
85 public:
86     /**
87       Constructor
88     */
89     KITEMMODELS_DEPRECATED_VERSION(5, 65, "Use QSortFilterProxyModel directly and QSortFilterProxyModel::setRecursiveFilteringEnabled(true)")
90     explicit KRecursiveFilterProxyModel(QObject *parent = nullptr);
91 
92     /**
93       Destructor
94     */
95     ~KRecursiveFilterProxyModel() override;
96 
97     /** @reimp */
98     void setSourceModel(QAbstractItemModel *model) override;
99 
100     /**
101      * @reimplemented
102      */
103     QModelIndexList match(const QModelIndex &start,
104                           int role,
105                           const QVariant &value,
106                           int hits = 1,
107                           Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchStartsWith | Qt::MatchWrap)) const override;
108 
109 protected:
110     /**
111       Reimplement this method for custom filtering strategies.
112     */
113     virtual bool acceptRow(int sourceRow, const QModelIndex &sourceParent) const;
114 
115     /** @reimp */
116     bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
117 
118     std::unique_ptr<KRecursiveFilterProxyModelPrivate> const d_ptr;
119 
120 private:
121     //@cond PRIVATE
122     Q_DECLARE_PRIVATE(KRecursiveFilterProxyModel)
123 
124     Q_PRIVATE_SLOT(d_func(),
125                    void sourceDataChanged(const QModelIndex &source_top_left,
126                                           const QModelIndex &source_bottom_right,
127                                           const QVector<int> &roles = QVector<int>()))
128     Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end))
129     Q_PRIVATE_SLOT(d_func(), void sourceRowsInserted(const QModelIndex &source_parent, int start, int end))
130     Q_PRIVATE_SLOT(d_func(), void sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end))
131     Q_PRIVATE_SLOT(d_func(), void sourceRowsRemoved(const QModelIndex &source_parent, int start, int end))
132     //@endcond
133 };
134 
135 #endif
136 
137 #endif
138