diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2021-04-23 16:00:17 +0200 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2021-05-11 21:05:09 +0200 |
commit | bdaaf99228f9d7385ec18ca7cc741535017e0033 (patch) | |
tree | dd77f32777db3b1cd8c6fe7f3cf20fc68d34c03b /src/corelib/itemmodels/qsortfilterproxymodel.cpp | |
parent | 9134113c4f7d168faa609bbab78fb4901562439c (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.cpp | 127 |
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 ®ularExpression) { 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()); } /*! |