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
qqmlrangefilter.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 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/qqmlrangefilter_p.h>
6#include <QtCore/qabstractitemmodel.h>
7#include <QtQmlModels/private/qqmlsortfilterproxymodel_p.h>
8
9QT_BEGIN_NAMESPACE
10
11/*!
12 \qmltype RangeFilter
13 \inherits RoleFilter
14 \inqmlmodule QtQml.Models
15 \since 6.12
16 \preliminary
17 \brief Filters data in a \l SortFilterProxyModel by testing whether a role
18 value falls within a given range.
19
20 RangeFilter accepts rows where the value of the configured role falls
21 between \l minimum and \l maximum. Both bounds are inclusive by default.
22
23 The following example shows processes with the cpu usage in the range
24 between 70 and 100:
25
26 \qml
27 SortFilterProxyModel {
28 sourceModel: processModel
29 filters: [
30 RangeFilter {
31 roleName: "cpuUsage"
32 minimum: 70
33 maximum: 100
34 }
35 ]
36 }
37 \endqml
38
39 Use \l exclusive() when a bound should exclude the boundary value itself:
40
41 \qml
42 RangeFilter {
43 roleName: "cpuUsage"
44 minimum: exclusive(70)
45 maximum: 100
46 }
47 \endqml
48*/
49
50QQmlRangeFilter::QQmlRangeFilter(QObject *parent)
51 : QQmlRoleFilter(new QQmlRangeFilterPrivate, parent)
52{
53}
54
55/*!
56 \qmlproperty variant RangeFilter::minimum
57
58 The lower bound of the range. Rows whose role value is less than this
59 value are excluded. When not set, there is no lower bound.
60
61 Assigning a plain value makes the bound inclusive — rows equal to
62 \c minimum are accepted. Use \l exclusive() to exclude the boundary
63 value itself.
64*/
65const QVariant &QQmlRangeFilter::minimum() const
66{
67 Q_D(const QQmlRangeFilter);
68 return d->m_minimum;
69}
70
71void QQmlRangeFilter::setMinimum(const QVariant &minimum)
72{
73 Q_D(QQmlRangeFilter);
74
75 QVariant minValue = minimum;
76 bool minInclusive = true;
77 if (minimum.metaType() == QMetaType::fromType<QQmlRangeFilter::RangeExclusiveBoundary>()) {
78 minValue = minimum.value<QQmlRangeFilter::RangeExclusiveBoundary>().value;
79 minInclusive = false;
80 }
81 if (d->m_minimum == minValue && d->m_minimumInclusive == minInclusive)
82 return;
83 d->m_minimum = minValue;
84 d->m_minimumInclusive = minInclusive;
85 emit minimumChanged();
86 invalidate();
87}
88
89void QQmlRangeFilter::resetMinimum()
90{
91 Q_D(QQmlRangeFilter);
92 if (!d->m_minimum.isValid())
93 return;
94 d->m_minimum = QVariant();
95 d->m_minimumInclusive = true;
96 emit minimumChanged();
97 invalidate();
98}
99
100/*!
101 \qmlproperty variant RangeFilter::maximum
102
103 The upper bound of the range. Rows whose role value is greater than this
104 value are excluded. When not set, there is no upper bound.
105
106 Assigning a plain value makes the bound inclusive — rows equal to
107 \c maximum are accepted. Use \l exclusive() to exclude the boundary
108 value itself.
109*/
110const QVariant &QQmlRangeFilter::maximum() const
111{
112 Q_D(const QQmlRangeFilter);
113 return d->m_maximum;
114}
115
116void QQmlRangeFilter::setMaximum(const QVariant &maximum)
117{
118 Q_D(QQmlRangeFilter);
119 QVariant maxValue = maximum;
120 bool maxInclusive = true;
121 if (maximum.metaType() == QMetaType::fromType<QQmlRangeFilter::RangeExclusiveBoundary>()) {
122 maxValue = maximum.value<QQmlRangeFilter::RangeExclusiveBoundary>().value;
123 maxInclusive = false;
124 }
125 d->m_maximum = maxValue;
126 d->m_maximumInclusive = maxInclusive;
127 emit maximumChanged();
128 invalidate();
129}
130
131void QQmlRangeFilter::resetMaximum()
132{
133 Q_D(QQmlRangeFilter);
134 if (!d->m_maximum.isValid())
135 return;
136 d->m_maximum = QVariant();
137 d->m_maximumInclusive = true;
138 emit maximumChanged();
139 invalidate();
140}
141
142/*!
143 \qmlmethod variant RangeFilter::exclusive(value)
144
145 Returns a boundary that excludes \a value from the range.
146 Rows whose role value equals \a value are rejected.
147
148 \qml
149 RangeFilter {
150 roleName: "score"
151 minimum: 0
152 maximum: RangeFilter.exclusive(100)
153 \endqml
154*/
155QVariant QQmlRangeFilter::exclusive(const QVariant &value)
156{
157 return QVariant::fromValue(QQmlRangeFilter::RangeExclusiveBoundary{value});
158}
159
160/*!
161 \internal
162*/
163bool QQmlRangeFilter::filterAcceptsRowInternal(int row, const QModelIndex &sourceParent,
164 const QQmlSortFilterProxyModel *proxyModel) const
165{
166 Q_D(const QQmlRangeFilter);
167 if (d->m_roleName.isEmpty())
168 return true;
169
170 const int role = itemRole(proxyModel);
171 if (role < 0) {
172 if (!d->m_roleNameValidated) {
173 qWarning("Provided role name %s doesn't exist in the model",
174 d->m_roleName.toUtf8().constData());
175 d->m_roleNameValidated = true;
176 }
177 return false;
178 }
179
180 const bool isMinimumSet = d->m_minimum.isValid() && !d->m_minimum.isNull();
181 const bool isMaximumSet = d->m_maximum.isValid() && !d->m_maximum.isNull();
182
183 if (!isMinimumSet && !isMaximumSet)
184 return true;
185
186 auto filterData = [&](const QVariant &value) -> bool {
187 if (!value.isValid())
188 return false;
189 auto *pModel = const_cast<QQmlSortFilterProxyModel *>(proxyModel);
190 if (isMinimumSet) {
191 const auto order = pModel->compareData(value, d->m_minimum);
192 if (d->m_minimumInclusive ? order == Qt::weak_ordering::less :
193 order != Qt::weak_ordering::greater)
194 return false;
195 }
196 if (isMaximumSet) {
197 const auto order = pModel->compareData(value, d->m_maximum);
198 if (d->m_maximumInclusive ? order == Qt::weak_ordering::greater :
199 order != Qt::weak_ordering::less)
200 return false;
201 }
202 return true;
203 };
204
205 if (column() > -1) {
206 const QModelIndex &index = proxyModel->sourceModel()->index(row, column(), sourceParent);
207 return filterData(proxyModel->sourceModel()->data(index, role));
208 } else {
209 const int columnCount = proxyModel->sourceModel()->columnCount(sourceParent);
210 for (int col = 0; col < columnCount; ++col) {
211 const QModelIndex &index = proxyModel->sourceModel()->index(row, col, sourceParent);
212 if (filterData(proxyModel->sourceModel()->data(index, role)))
213 return true;
214 }
215 }
216
217 return false;
218}
219
220QT_END_NAMESPACE
221
222#include "moc_qqmlrangefilter_p.cpp"