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 connect(d->m_sfpmModel, &QQmlSortFilterProxyModel::modelReset,
24 this, &QQmlFilterCompositor::updateFilters);
25}
26
27QQmlFilterCompositor::~QQmlFilterCompositor()
28{
29
30}
31
32void QQmlFilterCompositorPrivate::init()
33{
34 Q_Q(QQmlFilterCompositor);
35 m_sfpmModel = qobject_cast<QQmlSortFilterProxyModel *>(q->parent());
36}
37
38void QQmlFilterCompositor::append(QQmlListProperty<QQmlFilterBase> *filterComp, QQmlFilterBase* filter)
39{
40 auto *filterCompositor = reinterpret_cast<QQmlFilterCompositor *> (filterComp->object);
41 filterCompositor->append(filter);
42}
43
44qsizetype QQmlFilterCompositor::count(QQmlListProperty<QQmlFilterBase> *filterComp)
45{
46 auto *filterCompositor = reinterpret_cast<QQmlFilterCompositor *> (filterComp->object);
47 return filterCompositor->count();
48}
49
50QQmlFilterBase *QQmlFilterCompositor::at(QQmlListProperty<QQmlFilterBase> *filterComp, qsizetype index)
51{
52 auto *filterCompositor = reinterpret_cast<QQmlFilterCompositor *> (filterComp->object);
53 return filterCompositor->at(index);
54}
55
56void QQmlFilterCompositor::clear(QQmlListProperty<QQmlFilterBase> *filterComp)
57{
58 auto *filterCompositor = reinterpret_cast<QQmlFilterCompositor *> (filterComp->object);
59 filterCompositor->clear();
60}
61
62void QQmlFilterCompositor::append(QQmlFilterBase *filter)
63{
64 if (!filter)
65 return;
66
67 Q_D(QQmlFilterCompositor);
68 d->m_filters.append(filter);
69 // Connect the filter to the corresponding slot to invalidate the model
70 // and the filter cache
71 QObject::connect(filter, &QQmlFilterBase::invalidateModel,
72 d->m_sfpmModel, &QQmlSortFilterProxyModel::invalidate);
73 // This is needed as its required to update cache when there is any
74 // change in the filter itself (for instance, a change in the priority of
75 // the filter)
76 QObject::connect(filter, &QQmlFilterBase::invalidateCache,
77 this, &QQmlFilterCompositor::updateCache);
78 // Validate the filter for any precondition which can be compared with
79 // sfpm and update the filter cache accordingly
80 filter->update(d->m_sfpmModel);
81 updateCache();
82 // Since we added new filter to the list, emit the filter changed signal
83 // for the filters that have been appended to the list
84 emit d->m_sfpmModel->filtersChanged();
85}
86
87qsizetype QQmlFilterCompositor::count()
88{
89 Q_D(QQmlFilterCompositor);
90 return d->m_filters.count();
91}
92
93QQmlFilterBase *QQmlFilterCompositor::at(qsizetype index)
94{
95 Q_D(QQmlFilterCompositor);
96 return d->m_filters.at(index);
97}
98
99void QQmlFilterCompositor::clear()
100{
101 Q_D(QQmlFilterCompositor);
102 d->m_effectiveFilters.clear();
103 d->m_filters.clear();
104 // Emit the filter changed signal as we cleared the filter list
105 emit d->m_sfpmModel->filtersChanged();
106}
107
108QList<QQmlFilterBase *> QQmlFilterCompositor::filters()
109{
110 Q_D(QQmlFilterCompositor);
111 return d->m_filters;
112}
113
114QQmlListProperty<QQmlFilterBase> QQmlFilterCompositor::filtersListProperty()
115{
116 Q_D(QQmlFilterCompositor);
117 return QQmlListProperty<QQmlFilterBase>(reinterpret_cast<QObject*>(this), &d->m_filters,
118 QQmlFilterCompositor::append,
119 QQmlFilterCompositor::count,
120 QQmlFilterCompositor::at,
121 QQmlFilterCompositor::clear);
122}
123
124void QQmlFilterCompositor::updateFilters()
125{
126 Q_D(QQmlFilterCompositor);
127 // Update filters that have dependencies with the model data
128 for (auto &filter: d->m_filters)
129 filter->update(d->m_sfpmModel);
130 // Update the cache
131 updateCache();
132}
133
134void QQmlFilterCompositor::updateCache()
135{
136 Q_D(QQmlFilterCompositor);
137 // Clear the existing cache
138 d->m_effectiveFilters.clear();
139 if (d->m_sfpmModel && d->m_sfpmModel->sourceModel()) {
140 QList<QQmlFilterBase *> filters = d->m_filters;
141 // Cache only the filters that need to be evaluated (in order)
142 std::copy_if(filters.begin(), filters.end(), std::back_inserter(d->m_effectiveFilters),
143 [](QQmlFilterBase *filter){ return filter->enabled(); });
144 }
145}
146
147bool QQmlFilterCompositor::filterAcceptsRowInternal(int row, const QModelIndex& sourceParent, const QQmlSortFilterProxyModel *proxyModel) const
148{
149 Q_D(const QQmlFilterCompositor);
150 // Check the data against the configured filters and if nothing configured,
151 // dont filter the data
152 return std::all_of(d->m_effectiveFilters.begin(), d->m_effectiveFilters.end(),
153 [row, &sourceParent, proxyModel](const QQmlFilterBase *filter) {
154 const bool filterStatus = filter->filterAcceptsRowInternal(row, sourceParent, proxyModel);
155 return !(filter->isInverted()) ? filterStatus : !filterStatus;
156 });
157}
158
159bool QQmlFilterCompositor::filterAcceptsColumnInternal(int column, const QModelIndex& sourceParent, const QQmlSortFilterProxyModel *proxyModel) const
160{
161 Q_D(const QQmlFilterCompositor);
162 // Check the data against the configured filters and if nothing configured,
163 // dont filter the data
164 return std::all_of(d->m_effectiveFilters.begin(), d->m_effectiveFilters.end(),
165 [column, &sourceParent, proxyModel](const QQmlFilterBase *filter) {
166 return filter->filterAcceptsColumnInternal(column, sourceParent, proxyModel);
167 });
168}
169
170QT_END_NAMESPACE
171
172#include "moc_qqmlfiltercompositor_p.cpp"
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")