summaryrefslogtreecommitdiffstats
path: root/src/corelib/itemmodels/qsortfilterproxymodel.cpp
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2021-04-23 16:00:17 +0200
committerIvan Solovev <ivan.solovev@qt.io>2021-05-11 21:05:09 +0200
commitbdaaf99228f9d7385ec18ca7cc741535017e0033 (patch)
treedd77f32777db3b1cd8c6fe7f3cf20fc68d34c03b /src/corelib/itemmodels/qsortfilterproxymodel.cpp
parent9134113c4f7d168faa609bbab78fb4901562439c (diff)
QSFPM: make filterRegularExpression and filterCaseSensitivity bindable
This takes care of the last two QSFPM properties. They were postponed because of the tricky relation between them and some bugs in handling the changes. The bug was fixed in bcbbbdb2d640c059c19e9337c7418b83b1b7e4ea and now the behavior is well-determined: updating filter regexp does trigger case sensitivity change and vice versa. However updating only regexp pattern (via QString overload or setFilterFixedString or setFilterWildcard) does not change case sensitivity. Task-number: QTBUG-85520 Change-Id: Idc41cf817de9e6263ed65a80fa40fc8415c8c856 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Andreas Buhr <andreas.buhr@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/corelib/itemmodels/qsortfilterproxymodel.cpp')
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp127
1 files changed, 108 insertions, 19 deletions
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 9ef75f6073..1b5dc0dec2 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -202,6 +202,20 @@ public:
void setDynamicSortFilterForwarder(bool enable) { q_func()->setDynamicSortFilter(enable); }
+ void setFilterCaseSensitivityForwarder(Qt::CaseSensitivity cs)
+ {
+ q_func()->setFilterCaseSensitivity(cs);
+ }
+ void filterCaseSensitivityChangedForwarder(Qt::CaseSensitivity cs)
+ {
+ emit q_func()->filterCaseSensitivityChanged(cs);
+ }
+
+ void setFilterRegularExpressionForwarder(const QRegularExpression &re)
+ {
+ q_func()->setFilterRegularExpression(re);
+ }
+
int source_sort_column = -1;
int proxy_sort_column = -1;
Qt::SortOrder sort_order = Qt::AscendingOrder;
@@ -245,7 +259,15 @@ public:
&QSortFilterProxyModelPrivate::setDynamicSortFilterForwarder,
true)
- QRegularExpression filter_regularexpression;
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(
+ QSortFilterProxyModelPrivate, Qt::CaseSensitivity, filter_casesensitive,
+ &QSortFilterProxyModelPrivate::setFilterCaseSensitivityForwarder,
+ &QSortFilterProxyModelPrivate::filterCaseSensitivityChangedForwarder, Qt::CaseSensitive)
+
+ Q_OBJECT_COMPAT_PROPERTY(QSortFilterProxyModelPrivate, QRegularExpression,
+ filter_regularexpression,
+ &QSortFilterProxyModelPrivate::setFilterRegularExpressionForwarder)
+
QModelIndex last_top_source;
QRowsRemoval itemsBeingRemoved;
@@ -266,9 +288,14 @@ public:
*/
void set_filter_pattern(const QString &pattern)
{
- filter_regularexpression.setPattern(pattern);
- filter_regularexpression.setPatternOptions(filter_regularexpression.patternOptions()
- & QRegularExpression::CaseInsensitiveOption);
+ QRegularExpression re = filter_regularexpression.value();
+ const auto cs = re.patternOptions() & QRegularExpression::CaseInsensitiveOption;
+ re.setPattern(pattern);
+ re.setPatternOptions(cs);
+ // This is a helper function, which is supposed to be called from a
+ // more complicated context. Because of that, the caller is responsible
+ // for calling notify() and removeBindingUnlessInWrapper(), if needed.
+ filter_regularexpression.setValueBypassingBindings(re);
}
inline QHash<QModelIndex, Mapping *>::const_iterator index_to_iterator(
@@ -1247,7 +1274,7 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes(
*/
void QSortFilterProxyModelPrivate::filter_about_to_be_changed(const QModelIndex &source_parent)
{
- if (!filter_regularexpression.pattern().isEmpty()
+ if (!filter_regularexpression.value().pattern().isEmpty()
&& source_index_mapping.constFind(source_parent) == source_index_mapping.constEnd()) {
create_mapping(source_parent);
}
@@ -2567,6 +2594,12 @@ Qt::SortOrder QSortFilterProxyModel::sortOrder() const
If no QRegularExpression or an empty string is set, everything in the source
model will be accepted.
+ \note Setting this property propagates the case sensitivity of the new
+ regular expression to the \l filterCaseSensitivity property, and so breaks
+ its binding. Likewise explicitly setting \l filterCaseSensitivity changes
+ the case sensitivity of the current regular expression, thereby breaking
+ its binding.
+
\sa filterCaseSensitivity, setFilterWildcard(), setFilterFixedString()
*/
QRegularExpression QSortFilterProxyModel::filterRegularExpression() const
@@ -2575,16 +2608,35 @@ QRegularExpression QSortFilterProxyModel::filterRegularExpression() const
return d->filter_regularexpression;
}
+QBindable<QRegularExpression> QSortFilterProxyModel::bindableFilterRegularExpression()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<QRegularExpression>(&d->filter_regularexpression);
+}
+
void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression &regularExpression)
{
Q_D(QSortFilterProxyModel);
+ Qt::beginPropertyUpdateGroup();
+ const bool regExpChanged = regularExpression != d->filter_regularexpression.value();
+ d->filter_regularexpression.removeBindingUnlessInWrapper();
+ d->filter_casesensitive.removeBindingUnlessInWrapper();
const Qt::CaseSensitivity cs = filterCaseSensitivity();
d->filter_about_to_be_changed();
- d->filter_regularexpression = regularExpression;
+ const Qt::CaseSensitivity updatedCs =
+ regularExpression.patternOptions() & QRegularExpression::CaseInsensitiveOption
+ ? Qt::CaseInsensitive : Qt::CaseSensitive;
+ d->filter_regularexpression.setValueBypassingBindings(regularExpression);
+ if (cs != updatedCs)
+ d->filter_casesensitive.setValueBypassingBindings(updatedCs);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
- const Qt::CaseSensitivity updatedCs = filterCaseSensitivity();
+ // Do not change the evaluation logic, but notify only if the regular
+ // expression has actually changed.
+ if (regExpChanged)
+ d->filter_regularexpression.notify();
if (cs != updatedCs)
- emit filterCaseSensitivityChanged(updatedCs);
+ d->filter_casesensitive.notify();
+ Qt::endPropertyUpdateGroup();
}
/*!
@@ -2632,6 +2684,11 @@ QBindable<int> QSortFilterProxyModel::bindableFilterKeyColumn()
By default, the filter is case sensitive.
+ \note Setting this property propagates the new case sensitivity to the
+ \l filterRegularExpression property, and so breaks its binding. Likewise
+ explicitly setting \l filterRegularExpression changes the current case
+ sensitivity, thereby breaking its binding.
+
\sa filterRegularExpression, sortCaseSensitivity
*/
@@ -2644,23 +2701,37 @@ QBindable<int> QSortFilterProxyModel::bindableFilterKeyColumn()
Qt::CaseSensitivity QSortFilterProxyModel::filterCaseSensitivity() const
{
Q_D(const QSortFilterProxyModel);
- return d->filter_regularexpression.patternOptions() & QRegularExpression::CaseInsensitiveOption
- ? Qt::CaseInsensitive
- : Qt::CaseSensitive;
+ return d->filter_casesensitive;
}
void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs)
{
Q_D(QSortFilterProxyModel);
- QRegularExpression::PatternOptions options = d->filter_regularexpression.patternOptions();
- options.setFlag(QRegularExpression::CaseInsensitiveOption, cs == Qt::CaseInsensitive);
- if (d->filter_regularexpression.patternOptions() == options)
+ d->filter_casesensitive.removeBindingUnlessInWrapper();
+ d->filter_regularexpression.removeBindingUnlessInWrapper();
+ if (cs == d->filter_casesensitive)
return;
+ Qt::beginPropertyUpdateGroup();
+ QRegularExpression::PatternOptions options =
+ d->filter_regularexpression.value().patternOptions();
+ options.setFlag(QRegularExpression::CaseInsensitiveOption, cs == Qt::CaseInsensitive);
+ d->filter_casesensitive.setValueBypassingBindings(cs);
+
d->filter_about_to_be_changed();
- d->filter_regularexpression.setPatternOptions(options);
+ QRegularExpression re = d->filter_regularexpression;
+ re.setPatternOptions(options);
+ d->filter_regularexpression.setValueBypassingBindings(re);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
- emit filterCaseSensitivityChanged(cs);
+ d->filter_regularexpression.notify();
+ d->filter_casesensitive.notify();
+ Qt::endPropertyUpdateGroup();
+}
+
+QBindable<Qt::CaseSensitivity> QSortFilterProxyModel::bindableFilterCaseSensitivity()
+{
+ Q_D(QSortFilterProxyModel);
+ return QBindable<Qt::CaseSensitivity>(&d->filter_casesensitive);
}
/*!
@@ -2755,14 +2826,20 @@ QBindable<bool> QSortFilterProxyModel::bindableIsSortLocaleAware()
This method will reset the regular expression options
but respect case sensitivity.
+ \note Calling this method updates the regular expression, thereby breaking
+ the binding for \l filterRegularExpression. However it has no effect on the
+ \l filterCaseSensitivity bindings.
+
\sa setFilterCaseSensitivity(), setFilterWildcard(), setFilterFixedString(), filterRegularExpression()
*/
void QSortFilterProxyModel::setFilterRegularExpression(const QString &pattern)
{
Q_D(QSortFilterProxyModel);
+ d->filter_regularexpression.removeBindingUnlessInWrapper();
d->filter_about_to_be_changed();
d->set_filter_pattern(pattern);
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
+ d->filter_regularexpression.notify();
}
/*!
@@ -2772,15 +2849,21 @@ void QSortFilterProxyModel::setFilterRegularExpression(const QString &pattern)
This method will reset the regular expression options
but respect case sensitivity.
+ \note Calling this method updates the regular expression, thereby breaking
+ the binding for \l filterRegularExpression. However it has no effect on the
+ \l filterCaseSensitivity bindings.
+
\sa setFilterCaseSensitivity(), setFilterRegularExpression(), setFilterFixedString(), filterRegularExpression()
*/
void QSortFilterProxyModel::setFilterWildcard(const QString &pattern)
{
Q_D(QSortFilterProxyModel);
+ d->filter_regularexpression.removeBindingUnlessInWrapper();
d->filter_about_to_be_changed();
d->set_filter_pattern(QRegularExpression::wildcardToRegularExpression(
pattern, QRegularExpression::UnanchoredWildcardConversion));
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
+ d->filter_regularexpression.notify();
}
/*!
@@ -2790,14 +2873,20 @@ void QSortFilterProxyModel::setFilterWildcard(const QString &pattern)
This method will reset the regular expression options
but respect case sensitivity.
+ \note Calling this method updates the regular expression, thereby breaking
+ the binding for \l filterRegularExpression. However it has no effect on the
+ \l filterCaseSensitivity bindings.
+
\sa setFilterCaseSensitivity(), setFilterRegularExpression(), setFilterWildcard(), filterRegularExpression()
*/
void QSortFilterProxyModel::setFilterFixedString(const QString &pattern)
{
Q_D(QSortFilterProxyModel);
+ d->filter_regularexpression.removeBindingUnlessInWrapper();
d->filter_about_to_be_changed();
d->set_filter_pattern(QRegularExpression::escape(pattern));
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
+ d->filter_regularexpression.notify();
}
/*!
@@ -3151,7 +3240,7 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &
{
Q_D(const QSortFilterProxyModel);
- if (d->filter_regularexpression.pattern().isEmpty())
+ if (d->filter_regularexpression.value().pattern().isEmpty())
return true;
int column_count = d->model->columnCount(source_parent);
@@ -3159,7 +3248,7 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &
for (int column = 0; column < column_count; ++column) {
QModelIndex source_index = d->model->index(source_row, column, source_parent);
QString key = d->model->data(source_index, d->filter_role).toString();
- if (key.contains(d->filter_regularexpression))
+ if (key.contains(d->filter_regularexpression.value()))
return true;
}
return false;
@@ -3169,7 +3258,7 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &
return true;
QModelIndex source_index = d->model->index(source_row, d->filter_column, source_parent);
QString key = d->model->data(source_index, d->filter_role).toString();
- return key.contains(d->filter_regularexpression);
+ return key.contains(d->filter_regularexpression.value());
}
/*!