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