Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlfiltercompositor.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <QtQmlModels/private/qqmlfiltercompositor_p.h>
6#include <QtQmlModels/private/qqmlsortfilterproxymodel_p.h>
7
9
10Q_LOGGING_CATEGORY (lcSfpmFilterCompositor, "qt.qml.sfpmfiltercompositor")
11
12QQmlFilterCompositor::QQmlFilterCompositor(QObject *parent)
13 : QQmlFilterBase(new QQmlFilterCompositorPrivate, parent)
14{
15 Q_D(QQmlFilterCompositor);
16 d->init();
17 // Connect the model reset with the update in the filter
18 // The cache need to be updated once the model is reset with the
19 // source model data. This is because, there are chances that
20 // the filter can be enabled or disabled in effective filter list
21 // such as the configured role name in the filter doesn't match
22 // with any role name in the model
23 if (d->m_sfpmModel)
24 connect(d->m_sfpmModel, &QQmlSortFilterProxyModel::modelReset,
25 this, &QQmlFilterCompositor::updateFilters);
26}
27
28QQmlFilterCompositor::QQmlFilterCompositor(QQmlFilterBasePrivate *priv, QObject *parent)
29 : QQmlFilterBase(priv, parent)
30{
31
32}
33
34void QQmlFilterCompositorPrivate::init()
35{
36 Q_Q(QQmlFilterCompositor);
37 m_sfpmModel = qobject_cast<QQmlSortFilterProxyModel *>(q->parent());
38}
39
40void QQmlFilterCompositor::append(QQmlListProperty<QQmlFilterBase> *filterComp, QQmlFilterBase* filter)
41{
42 auto *filterCompositor = reinterpret_cast<QQmlFilterCompositor *> (filterComp->object);
43 filterCompositor->append(filter);
44}
45
46qsizetype QQmlFilterCompositor::count(QQmlListProperty<QQmlFilterBase> *filterComp)
47{
48 auto *filterCompositor = reinterpret_cast<QQmlFilterCompositor *> (filterComp->object);
49 return filterCompositor->count();
50}
51
52QQmlFilterBase *QQmlFilterCompositor::at(QQmlListProperty<QQmlFilterBase> *filterComp, qsizetype index)
53{
54 auto *filterCompositor = reinterpret_cast<QQmlFilterCompositor *> (filterComp->object);
55 return filterCompositor->at(index);
56}
57
58void QQmlFilterCompositor::clear(QQmlListProperty<QQmlFilterBase> *filterComp)
59{
60 auto *filterCompositor = reinterpret_cast<QQmlFilterCompositor *> (filterComp->object);
61 filterCompositor->clear();
62}
63
64void QQmlFilterCompositor::append(QQmlFilterBase *filter)
65{
66 if (!filter)
67 return;
68
69 Q_D(QQmlFilterCompositor);
70 d->m_filters.append(filter);
71 // This is needed as its required to update cache when there is any
72 // change in the filter itself (for instance, a change in the priority of
73 // the filter)
74 QObject::connect(filter, &QQmlFilterBase::invalidateCache,
75 this, &QQmlFilterCompositor::refreshCache);
76
77 if (d->m_sfpmModel) {
78 // Connect the filter to the corresponding slot to invalidate the model
79 // and the filter cache
80 QObject::connect(filter, &QQmlFilterBase::invalidateModel,
81 d->m_sfpmModel, &QQmlSortFilterProxyModel::invalidate);
82 // Validate the filter for any precondition which can be compared with
83 // sfpm and update the filter cache accordingly
84 filter->update(d->m_sfpmModel);
85 refreshCache();
86 // Since we added new filter to the list, emit the filter changed signal
87 // for the filters that have been appended to the list
88 emit d->m_sfpmModel->filtersChanged();
89 }
90}
91
92qsizetype QQmlFilterCompositor::count()
93{
94 Q_D(QQmlFilterCompositor);
95 return d->m_filters.count();
96}
97
98QQmlFilterBase *QQmlFilterCompositor::at(qsizetype index)
99{
100 Q_D(QQmlFilterCompositor);
101 return d->m_filters.at(index);
102}
103
104void QQmlFilterCompositor::clear()
105{
106 Q_D(QQmlFilterCompositor);
107 d->m_effectiveFilters.clear();
108 d->m_filters.clear();
109 // Emit the filter changed signal as we cleared the filter list
110 if (d->m_sfpmModel)
111 emit d->m_sfpmModel->filtersChanged();
112}
113
114QList<QQmlFilterBase *> QQmlFilterCompositor::filters()
115{
116 Q_D(QQmlFilterCompositor);
117 return d->m_filters;
118}
119
120QQmlListProperty<QQmlFilterBase> QQmlFilterCompositor::filtersListProperty()
121{
122 Q_D(QQmlFilterCompositor);
123 return QQmlListProperty<QQmlFilterBase>(reinterpret_cast<QObject*>(this), &d->m_filters,
124 QQmlFilterCompositor::append,
125 QQmlFilterCompositor::count,
126 QQmlFilterCompositor::at,
127 QQmlFilterCompositor::clear);
128}
129
130void QQmlFilterCompositor::updateFilters()
131{
132 Q_D(QQmlFilterCompositor);
133 // Update filters that have dependencies with the model data
134 for (auto &filter: d->m_filters)
135 filter->update(d->m_sfpmModel);
136 // Update the cache
137 refreshCache();
138}
139
140void QQmlFilterCompositor::refreshCache()
141{
142 Q_D(QQmlFilterCompositor);
143 // Clear the existing cache
144 d->m_effectiveFilters.clear();
145 if (d->m_sfpmModel && d->m_sfpmModel->sourceModel()) {
146 for (auto &filter: d->m_filters) {
147 if (filter->isActive())
148 d->m_effectiveFilters.append(filter);
149 }
150 }
151}
152
153bool QQmlFilterCompositor::filterAcceptsRowInternal(int row, const QModelIndex& sourceParent, const QQmlSortFilterProxyModel *proxyModel) const
154{
155 Q_D(const QQmlFilterCompositor);
156 // Check the data against the configured filters and if nothing configured,
157 // dont filter the data
158 return std::all_of(d->m_effectiveFilters.begin(), d->m_effectiveFilters.end(),
159 [row, &sourceParent, proxyModel](const QQmlFilterBase *filter) {
160 const bool filterStatus = filter->filterAcceptsRowInternal(row, sourceParent, proxyModel);
161 return filter->isInverted() != filterStatus;
162 });
163}
164
165bool QQmlFilterCompositor::filterAcceptsColumnInternal(int column, const QModelIndex& sourceParent, const QQmlSortFilterProxyModel *proxyModel) const
166{
167 Q_D(const QQmlFilterCompositor);
168 // Check the data against the configured filters and if nothing configured,
169 // dont filter the data
170 return std::all_of(d->m_effectiveFilters.begin(), d->m_effectiveFilters.end(),
171 [column, &sourceParent, proxyModel](const QQmlFilterBase *filter) {
172 if (!filter->supportColumnFiltering())
173 return true;
174 const bool filterStatus = filter->filterAcceptsColumnInternal(column, sourceParent, proxyModel);
175 return filter->isInverted() != filterStatus;
176 });
177}
178
179QT_END_NAMESPACE
180
181#include "moc_qqmlfiltercompositor_p.cpp"
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")