From 0c5917ee5b4a3b0d200beb6bf790509c08de5d05 Mon Sep 17 00:00:00 2001 From: Olaf Mandel Date: Tue, 27 Oct 2020 16:47:31 +0100 Subject: [PATCH 1/7] Implement own lessThan(QVariant, QVariant) Qt 5.15 deprecated the operator<(QVariant, QVariant). Do get rid of the warning and to prepare for the eventual removal of the operator, implement our own needs in a lessThan() function. The function is based on the description of QSortFilterProxyModel::lessThan(). Fixes #77 --- CMakeLists.txt | 1 + SortFilterProxyModel.pri | 2 + filters/rangefilter.cpp | 7 +++- qvariantlessthan.cpp | 79 ++++++++++++++++++++++++++++++++++++++++ qvariantlessthan.h | 12 ++++++ sorters/rolesorter.cpp | 5 ++- 6 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 qvariantlessthan.cpp create mode 100644 qvariantlessthan.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d3bf2b..7b4e1f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) # This is to find generated *.moc and *.h file add_library(SortFilterProxyModel OBJECT qqmlsortfilterproxymodel.cpp + qvariantlessthan.cpp filters/filter.cpp filters/filtercontainer.cpp filters/rolefilter.cpp diff --git a/SortFilterProxyModel.pri b/SortFilterProxyModel.pri index 22f7a83..c5c5dd4 100644 --- a/SortFilterProxyModel.pri +++ b/SortFilterProxyModel.pri @@ -3,6 +3,7 @@ INCLUDEPATH += $$PWD HEADERS += $$PWD/qqmlsortfilterproxymodel.h \ + $$PWD/qvariantlessthan.h \ $$PWD/filters/filter.h \ $$PWD/filters/filtercontainer.h \ $$PWD/filters/rolefilter.h \ @@ -30,6 +31,7 @@ HEADERS += $$PWD/qqmlsortfilterproxymodel.h \ $$PWD/proxyroles/filterrole.h SOURCES += $$PWD/qqmlsortfilterproxymodel.cpp \ + $$PWD/qvariantlessthan.cpp \ $$PWD/filters/filter.cpp \ $$PWD/filters/filtercontainer.cpp \ $$PWD/filters/rolefilter.cpp \ diff --git a/filters/rangefilter.cpp b/filters/rangefilter.cpp index 2a6fde2..ce683a5 100644 --- a/filters/rangefilter.cpp +++ b/filters/rangefilter.cpp @@ -1,4 +1,5 @@ #include "rangefilter.h" +#include "qvariantlessthan.h" namespace qqsfpm { @@ -130,9 +131,11 @@ bool RangeFilter::filterRow(const QModelIndex& sourceIndex, const QQmlSortFilter { QVariant value = sourceData(sourceIndex, proxyModel); bool lessThanMin = m_minimumValue.isValid() && - (m_minimumInclusive ? value < m_minimumValue : value <= m_minimumValue); + (m_minimumInclusive ? qqsfpm::lessThan(value, m_minimumValue) + : !qqsfpm::lessThan(m_minimumValue, value)); bool moreThanMax = m_maximumValue.isValid() && - (m_maximumInclusive ? value > m_maximumValue : value >= m_maximumValue); + (m_maximumInclusive ? qqsfpm::lessThan(m_maximumValue, value) + : !qqsfpm::lessThan(value, m_maximumValue)); return !(lessThanMin || moreThanMax); } diff --git a/qvariantlessthan.cpp b/qvariantlessthan.cpp new file mode 100644 index 0000000..d93b6fe --- /dev/null +++ b/qvariantlessthan.cpp @@ -0,0 +1,79 @@ +#include "qvariantlessthan.h" + +#include + +namespace qqsfpm { + +/*! + \brief Less-than operator for generic QVariants + + Since Qt 5.15 deprecated the less-than operator of QVariant, we + have to provide our own implementation. On older Qt versions, + use the original implementation. + + Includes special implementations for numberic types, char, date and + time. Everything else is converted to String and compared then. +*/ +bool lessThan(const QVariant &lhs, const QVariant &rhs) +{ +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + return lhs < rhs; +#else + static const auto numericTypes = QVector{ + QMetaType::Int, + QMetaType::UInt, + QMetaType::LongLong, + QMetaType::ULongLong, + QMetaType::Float, + QMetaType::Double, + }; + static const auto unsignedTypes = QVector{ + QMetaType::UInt, + QMetaType::ULongLong, + }; + static const auto dateTimeTypes = QVector{ + QMetaType::QDate, + QMetaType::QTime, + QMetaType::QDateTime, + }; + + const auto lt = static_cast(lhs.type()); + const auto rt = static_cast(rhs.type()); + if (numericTypes.contains(lt) && numericTypes.contains(rt)) { + if (lt == QMetaType::Double || lt == QMetaType::Float + || rt == QMetaType::Double || rt == QMetaType::Float) { + return lhs.toDouble() < rhs.toDouble(); + } else { + const auto ul = unsignedTypes.contains(lt); + const auto ur = unsignedTypes.contains(rt); + if (ul && ur) { + return lhs.toULongLong() < rhs.toULongLong(); + } else if (!ul && !ur) { + return lhs.toLongLong() < rhs.toLongLong(); + } else if (ul) { + const auto r = rhs.toLongLong(); + return r > 0 && + lhs.toULongLong() < static_cast(r); + } else { + const auto l = lhs.toLongLong(); + return l < 0 || + static_cast(l) < rhs.toULongLong(); + } + } + } else if (dateTimeTypes.contains(lt) && dateTimeTypes.contains(rt)) { + if (lt == QMetaType::QDate && rt == QMetaType::QDate) { + return lhs.toDate() < rhs.toDate(); + } else if (lt == QMetaType::QTime && rt == QMetaType::QTime) { + return lhs.toTime() < rhs.toTime(); + } else { + return lhs.toDateTime() < rhs.toDateTime(); + } + } else if (lt == QMetaType::Char && rt == QMetaType::Char) { + return lhs.toChar() < rhs.toChar(); + } else { + return lhs.toString() < rhs.toString(); + } +#endif +} + +} // namespace qqsfpm diff --git a/qvariantlessthan.h b/qvariantlessthan.h new file mode 100644 index 0000000..6f6a572 --- /dev/null +++ b/qvariantlessthan.h @@ -0,0 +1,12 @@ +#ifndef QVARIANTLESSTHAN_H +#define QVARIANTLESSTHAN_H + +#include + +namespace qqsfpm { + +bool lessThan(const QVariant &lhs, const QVariant &rhs); + +} // namespace qqsfpm + +#endif // QVARIANTLESSTHAN_H diff --git a/sorters/rolesorter.cpp b/sorters/rolesorter.cpp index db2d446..4f6b2c3 100644 --- a/sorters/rolesorter.cpp +++ b/sorters/rolesorter.cpp @@ -1,5 +1,6 @@ #include "rolesorter.h" #include "qqmlsortfilterproxymodel.h" +#include "qvariantlessthan.h" namespace qqsfpm { @@ -59,9 +60,9 @@ int RoleSorter::compare(const QModelIndex &sourceLeft, const QModelIndex& source QPair pair = sourceData(sourceLeft, sourceRight, proxyModel); QVariant leftValue = pair.first; QVariant rightValue = pair.second; - if (leftValue < rightValue) + if (qqsfpm::lessThan(leftValue, rightValue)) return -1; - if (leftValue > rightValue) + if (qqsfpm::lessThan(rightValue, leftValue)) return 1; return 0; } From beac174a304151a91d7778c5bebd1192b223983a Mon Sep 17 00:00:00 2001 From: Prashant Vaibhav Date: Wed, 28 Oct 2020 11:36:02 +0100 Subject: [PATCH 2/7] Recognize C++17 usage in parent projects Avoids printing an error message that C++11 is required, if C++17 is already being used. --- SortFilterProxyModel.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SortFilterProxyModel.pri b/SortFilterProxyModel.pri index 22f7a83..d8a8e9b 100644 --- a/SortFilterProxyModel.pri +++ b/SortFilterProxyModel.pri @@ -1,4 +1,4 @@ -!contains( CONFIG, c\+\+1[14] ): warning("SortFilterProxyModel needs at least c++11, add CONFIG += c++11 to your .pro") +!contains( CONFIG, c\+\+1[147] ): warning("SortFilterProxyModel needs at least c++11, add CONFIG += c++11 to your .pro") INCLUDEPATH += $$PWD From c46079d31d9684e1db3322d4b70485b2b5290d8e Mon Sep 17 00:00:00 2001 From: Petr Nechaev Date: Wed, 30 Jun 2021 18:51:53 +0300 Subject: [PATCH 3/7] Remove unused lambda capture This fixes an error ' error: lambda capture 'source_parent' is not used [-Werror,-Wunused-lambda-capture]' produced by clang with -Wall -Wextra -pedantic -Wno-deprecated-declarations -Wno-deprecated-copy -Werror --- qqmlsortfilterproxymodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qqmlsortfilterproxymodel.cpp b/qqmlsortfilterproxymodel.cpp index bd06435..43d5319 100644 --- a/qqmlsortfilterproxymodel.cpp +++ b/qqmlsortfilterproxymodel.cpp @@ -339,7 +339,7 @@ bool QQmlSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelInde bool valueAccepted = !m_filterValue.isValid() || ( m_filterValue == sourceModel()->data(sourceIndex, filterRole()) ); bool baseAcceptsRow = valueAccepted && QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); baseAcceptsRow = baseAcceptsRow && std::all_of(m_filters.begin(), m_filters.end(), - [=, &source_parent] (Filter* filter) { + [=] (Filter* filter) { return filter->filterAcceptsRow(sourceIndex, *this); } ); From dc6800b745cd6d635a1bd4b960030236bdab5383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20M=C3=BCller-Guthof?= Date: Fri, 9 Jul 2021 17:44:30 +0200 Subject: [PATCH 4/7] Add support for Qt versions < 5.9 Qt versions prior to Qt 5.9 do not have the qmlWarning(). For those versions redefine qmlWarning() to call qmlInfo() instead. --- filters/filtercontainer.cpp | 4 ++++ sorters/sortercontainer.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/filters/filtercontainer.cpp b/filters/filtercontainer.cpp index 5bba02d..2e21151 100644 --- a/filters/filtercontainer.cpp +++ b/filters/filtercontainer.cpp @@ -2,6 +2,10 @@ #include "filter.h" #include +#if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0)) +#define qmlWarning(me) qmlInfo(me) +#endif + namespace qqsfpm { /*! diff --git a/sorters/sortercontainer.cpp b/sorters/sortercontainer.cpp index f986e37..d934425 100644 --- a/sorters/sortercontainer.cpp +++ b/sorters/sortercontainer.cpp @@ -2,6 +2,10 @@ #include "sorter.h" #include +#if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0)) +#define qmlWarning(me) qmlInfo(me) +#endif + namespace qqsfpm { /*! From 6d90ab4a31cf51882729df45956701d10de8729b Mon Sep 17 00:00:00 2001 From: Caspar Kielwein Date: Sun, 7 Nov 2021 14:41:31 +0100 Subject: [PATCH 5/7] WIP of making it QT6 compatible --- CMakeLists.txt | 13 ++++++++----- filters/expressionfilter.cpp | 2 +- filters/filtercontainer.cpp | 12 ++++++------ filters/filtercontainer.h | 4 ++-- filters/regexpfilter.cpp | 2 +- filters/regexpfilter.h | 15 ++++++++------- proxyroles/proxyrole.h | 2 +- proxyroles/proxyrolecontainer.cpp | 12 ++++++------ proxyroles/proxyrolecontainer.h | 4 ++-- proxyroles/switchrole.h | 2 +- qqmlsortfilterproxymodel.cpp | 6 +++--- qqmlsortfilterproxymodel.h | 14 +++++++------- sorters/sorter.h | 3 +-- sorters/sortercontainer.cpp | 12 ++++++------ sorters/sortercontainer.h | 8 ++++---- 15 files changed, 57 insertions(+), 54 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b4e1f9..73cb52a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,9 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.14) +project(qqmlsortfilterproxymodel) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) -find_package(Qt5 REQUIRED +find_package(Qt6 REQUIRED Core Qml ) @@ -45,6 +46,8 @@ add_library(SortFilterProxyModel OBJECT target_include_directories(SortFilterProxyModel PUBLIC ${CMAKE_CURRENT_LIST_DIR} - $ - $ + $ + $ ) + +target_compile_options(SortFilterProxyModel PRIVATE -fPIC) diff --git a/filters/expressionfilter.cpp b/filters/expressionfilter.cpp index f3673ce..1747ff8 100644 --- a/filters/expressionfilter.cpp +++ b/filters/expressionfilter.cpp @@ -116,7 +116,7 @@ void ExpressionFilter::updateExpression() return; delete m_expression; - m_expression = new QQmlExpression(m_scriptString, m_context, 0, this); + m_expression = new QQmlExpression(m_scriptString, m_context, nullptr, this); connect(m_expression, &QQmlExpression::valueChanged, this, &ExpressionFilter::invalidate); m_expression->setNotifyOnValueChanged(true); m_expression->evaluate(); diff --git a/filters/filtercontainer.cpp b/filters/filtercontainer.cpp index 2e21151..41da8d4 100644 --- a/filters/filtercontainer.cpp +++ b/filters/filtercontainer.cpp @@ -56,25 +56,25 @@ void FilterContainer::append_filter(QQmlListProperty* list, Filter* filt if (!filter) return; - FilterContainer* that = reinterpret_cast(list->object); + auto* that = reinterpret_cast(list->object); that->appendFilter(filter); } -int FilterContainer::count_filter(QQmlListProperty* list) +qsizetype FilterContainer::count_filter(QQmlListProperty* list) { - QList* filters = static_cast*>(list->data); + auto* filters = static_cast*>(list->data); return filters->count(); } -Filter* FilterContainer::at_filter(QQmlListProperty* list, int index) +Filter* FilterContainer::at_filter(QQmlListProperty* list, qsizetype index) { - QList* filters = static_cast*>(list->data); + auto* filters = static_cast*>(list->data); return filters->at(index); } void FilterContainer::clear_filters(QQmlListProperty *list) { - FilterContainer* that = reinterpret_cast(list->object); + auto* that = reinterpret_cast(list->object); that->clearFilters(); } diff --git a/filters/filtercontainer.h b/filters/filtercontainer.h index 4fc06f3..9adf41f 100644 --- a/filters/filtercontainer.h +++ b/filters/filtercontainer.h @@ -31,8 +31,8 @@ class FilterContainer { virtual void onFiltersCleared() = 0; static void append_filter(QQmlListProperty* list, Filter* filter); - static int count_filter(QQmlListProperty* list); - static Filter* at_filter(QQmlListProperty* list, int index); + static qsizetype count_filter(QQmlListProperty* list); + static Filter* at_filter(QQmlListProperty* list, qsizetype index); static void clear_filters(QQmlListProperty* list); }; diff --git a/filters/regexpfilter.cpp b/filters/regexpfilter.cpp index f308765..dbb6a2e 100644 --- a/filters/regexpfilter.cpp +++ b/filters/regexpfilter.cpp @@ -78,7 +78,7 @@ void RegExpFilter::setSyntax(RegExpFilter::PatternSyntax syntax) return; m_syntax = syntax; - m_regExp.setPatternSyntax(static_cast(syntax)); + m_regExp.setPatternSyntax(static_cast(syntax)); Q_EMIT syntaxChanged(); invalidate(); } diff --git a/filters/regexpfilter.h b/filters/regexpfilter.h index 2c20a6a..3227e69 100644 --- a/filters/regexpfilter.h +++ b/filters/regexpfilter.h @@ -2,6 +2,7 @@ #define REGEXPFILTER_H #include "rolefilter.h" +#include namespace qqsfpm { @@ -13,12 +14,12 @@ class RegExpFilter : public RoleFilter { public: enum PatternSyntax { - RegExp = QRegExp::RegExp, - Wildcard = QRegExp::Wildcard, - FixedString = QRegExp::FixedString, - RegExp2 = QRegExp::RegExp2, - WildcardUnix = QRegExp::WildcardUnix, - W3CXmlSchema11 = QRegExp::W3CXmlSchema11 }; + RegExp,// = QRegularExpression::RegExp, + Wildcard,// = QRegularExpression::Wildcard, + FixedString,// = QRegularExpression::FixedString, + RegExp2,// = QRegularExpression::RegExp2, + WildcardUnix,// = QRegularExpression::WildcardUnix, + W3CXmlSchema11,/* = QRegularExpression::W3CXmlSchema11*/ }; Q_ENUMS(PatternSyntax) using RoleFilter::RoleFilter; @@ -41,7 +42,7 @@ class RegExpFilter : public RoleFilter { void caseSensitivityChanged(); private: - QRegExp m_regExp; + QRegularExpression m_regExp; Qt::CaseSensitivity m_caseSensitivity = m_regExp.caseSensitivity(); PatternSyntax m_syntax = static_cast(m_regExp.patternSyntax()); QString m_pattern = m_regExp.pattern(); diff --git a/proxyroles/proxyrole.h b/proxyroles/proxyrole.h index 5c1ff93..09e06b9 100644 --- a/proxyroles/proxyrole.h +++ b/proxyroles/proxyrole.h @@ -14,7 +14,7 @@ class ProxyRole : public QObject public: using QObject::QObject; - virtual ~ProxyRole() = default; + ~ProxyRole() override = default; QVariant roleData(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel, const QString& name); virtual void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel); diff --git a/proxyroles/proxyrolecontainer.cpp b/proxyroles/proxyrolecontainer.cpp index f8ea665..6c5f838 100644 --- a/proxyroles/proxyrolecontainer.cpp +++ b/proxyroles/proxyrolecontainer.cpp @@ -39,25 +39,25 @@ void ProxyRoleContainer::append_proxyRole(QQmlListProperty* list, Pro if (!proxyRole) return; - ProxyRoleContainer* that = reinterpret_cast(list->object); + auto* that = reinterpret_cast(list->object); that->appendProxyRole(proxyRole); } -int ProxyRoleContainer::count_proxyRole(QQmlListProperty* list) +qsizetype ProxyRoleContainer::count_proxyRole(QQmlListProperty* list) { - QList* ProxyRoles = static_cast*>(list->data); + auto* ProxyRoles = static_cast*>(list->data); return ProxyRoles->count(); } -ProxyRole* ProxyRoleContainer::at_proxyRole(QQmlListProperty* list, int index) +ProxyRole* ProxyRoleContainer::at_proxyRole(QQmlListProperty* list, qsizetype index) { - QList* ProxyRoles = static_cast*>(list->data); + auto* ProxyRoles = static_cast*>(list->data); return ProxyRoles->at(index); } void ProxyRoleContainer::clear_proxyRoles(QQmlListProperty *list) { - ProxyRoleContainer* that = reinterpret_cast(list->object); + auto* that = reinterpret_cast(list->object); that->clearProxyRoles(); } diff --git a/proxyroles/proxyrolecontainer.h b/proxyroles/proxyrolecontainer.h index bcd932e..415b8c0 100644 --- a/proxyroles/proxyrolecontainer.h +++ b/proxyroles/proxyrolecontainer.h @@ -29,8 +29,8 @@ class ProxyRoleContainer { virtual void onProxyRolesCleared() = 0; static void append_proxyRole(QQmlListProperty* list, ProxyRole* proxyRole); - static int count_proxyRole(QQmlListProperty* list); - static ProxyRole* at_proxyRole(QQmlListProperty* list, int index); + static qsizetype count_proxyRole(QQmlListProperty* list); + static ProxyRole* at_proxyRole(QQmlListProperty* list, qsizetype index); static void clear_proxyRoles(QQmlListProperty* list); }; diff --git a/proxyroles/switchrole.h b/proxyroles/switchrole.h index 203a8eb..1deb2d1 100644 --- a/proxyroles/switchrole.h +++ b/proxyroles/switchrole.h @@ -12,7 +12,7 @@ class SwitchRoleAttached : public QObject Q_OBJECT Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged) public: - SwitchRoleAttached(QObject* parent); + explicit SwitchRoleAttached(QObject* parent); QVariant value() const; void setValue(QVariant value); diff --git a/qqmlsortfilterproxymodel.cpp b/qqmlsortfilterproxymodel.cpp index 43d5319..267ec12 100644 --- a/qqmlsortfilterproxymodel.cpp +++ b/qqmlsortfilterproxymodel.cpp @@ -97,7 +97,7 @@ QString QQmlSortFilterProxyModel::filterPattern() const void QQmlSortFilterProxyModel::setFilterPattern(const QString& filterPattern) { - QRegExp regExp = filterRegExp(); + QRegularExpression regExp = filterRegExp(); if (regExp.pattern() == filterPattern) return; @@ -113,8 +113,8 @@ QQmlSortFilterProxyModel::PatternSyntax QQmlSortFilterProxyModel::filterPatternS void QQmlSortFilterProxyModel::setFilterPatternSyntax(QQmlSortFilterProxyModel::PatternSyntax patternSyntax) { - QRegExp regExp = filterRegExp(); - QRegExp::PatternSyntax patternSyntaxTmp = static_cast(patternSyntax); + QRegularExpression regExp = filterRegExp(); + QRegularExpression::PatternSyntax patternSyntaxTmp = static_cast(patternSyntax); if (regExp.patternSyntax() == patternSyntaxTmp) return; diff --git a/qqmlsortfilterproxymodel.h b/qqmlsortfilterproxymodel.h index dbe0229..23f1c09 100644 --- a/qqmlsortfilterproxymodel.h +++ b/qqmlsortfilterproxymodel.h @@ -37,13 +37,13 @@ class QQmlSortFilterProxyModel : public QSortFilterProxyModel, Q_PROPERTY(QQmlListProperty proxyRoles READ proxyRolesListProperty) public: - enum PatternSyntax { - RegExp = QRegExp::RegExp, - Wildcard = QRegExp::Wildcard, - FixedString = QRegExp::FixedString, - RegExp2 = QRegExp::RegExp2, - WildcardUnix = QRegExp::WildcardUnix, - W3CXmlSchema11 = QRegExp::W3CXmlSchema11 }; + enum PatternSyntax { + RegExp,// = QRegularExpression::RegExp, + Wildcard,// = QRegularExpression::Wildcard, + FixedString,// = QRegularExpression::FixedString, + RegExp2,// = QRegularExpression::RegExp2, + WildcardUnix,// = QRegularExpression::WildcardUnix, + W3CXmlSchema11,/* = QRegularExpression::W3CXmlSchema11*/ }; Q_ENUMS(PatternSyntax) QQmlSortFilterProxyModel(QObject* parent = 0); diff --git a/sorters/sorter.h b/sorters/sorter.h index f7ecd88..80e3386 100644 --- a/sorters/sorter.h +++ b/sorters/sorter.h @@ -16,8 +16,7 @@ class Sorter : public QObject Q_PROPERTY(int priority READ priority WRITE setPriority NOTIFY priorityChanged) public: - Sorter(QObject* parent = nullptr); - virtual ~Sorter() = 0; + explicit Sorter(QObject* parent = nullptr); bool enabled() const; void setEnabled(bool enabled); diff --git a/sorters/sortercontainer.cpp b/sorters/sortercontainer.cpp index d934425..74f7641 100644 --- a/sorters/sortercontainer.cpp +++ b/sorters/sortercontainer.cpp @@ -56,25 +56,25 @@ void SorterContainer::append_sorter(QQmlListProperty* list, Sorter* sort if (!sorter) return; - SorterContainer* that = reinterpret_cast(list->object); + auto* that = reinterpret_cast(list->object); that->appendSorter(sorter); } -int SorterContainer::count_sorter(QQmlListProperty* list) +qsizetype SorterContainer::count_sorter(QQmlListProperty* list) { - QList* sorters = static_cast*>(list->data); + auto* sorters = static_cast*>(list->data); return sorters->count(); } -Sorter* SorterContainer::at_sorter(QQmlListProperty* list, int index) +Sorter* SorterContainer::at_sorter(QQmlListProperty* list, qsizetype index) { - QList* sorters = static_cast*>(list->data); + auto* sorters = static_cast*>(list->data); return sorters->at(index); } void SorterContainer::clear_sorters(QQmlListProperty *list) { - SorterContainer* that = reinterpret_cast(list->object); + auto* that = reinterpret_cast(list->object); that->clearSorters(); } diff --git a/sorters/sortercontainer.h b/sorters/sortercontainer.h index 016cc6d..e6bdc1b 100644 --- a/sorters/sortercontainer.h +++ b/sorters/sortercontainer.h @@ -31,8 +31,8 @@ class SorterContainer { virtual void onSortersCleared() = 0; static void append_sorter(QQmlListProperty* list, Sorter* sorter); - static int count_sorter(QQmlListProperty* list); - static Sorter* at_sorter(QQmlListProperty* list, int index); + static qsizetype count_sorter(QQmlListProperty* list); + static Sorter* at_sorter(QQmlListProperty* list, qsizetype index); static void clear_sorters(QQmlListProperty* list); }; @@ -42,8 +42,8 @@ class SorterContainerAttached : public QObject Q_PROPERTY(QObject* container READ container WRITE setContainer NOTIFY containerChanged) public: - SorterContainerAttached(QObject* object); - ~SorterContainerAttached(); + explicit SorterContainerAttached(QObject* object); + ~SorterContainerAttached() override; QObject* container() const; void setContainer(QObject* object); From fcdc75d509298f7678d12df0ceb75674405e8954 Mon Sep 17 00:00:00 2001 From: r-vitanov Date: Fri, 12 Nov 2021 11:21:23 +0100 Subject: [PATCH 6/7] Removed pattern syntax and allowed for filtering and sorting only on specific roles --- .gitignore | 1 + filters/regexpfilter.cpp | 97 ++--- filters/regexpfilter.h | 47 +-- qqmlsortfilterproxymodel.cpp | 724 +++++++++++++++++------------------ qqmlsortfilterproxymodel.h | 230 ++++++----- sorters/sorter.cpp | 128 +++---- sorters/sorter.h | 67 ++-- 7 files changed, 607 insertions(+), 687 deletions(-) diff --git a/.gitignore b/.gitignore index 73d1dfd..a91bdd4 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ Thumbs.db # qtcreator generated files *.pro.user* +*.user # qtcreator shadow builds build-SortFilterProxyModel-* diff --git a/filters/regexpfilter.cpp b/filters/regexpfilter.cpp index dbb6a2e..a30bb3c 100644 --- a/filters/regexpfilter.cpp +++ b/filters/regexpfilter.cpp @@ -10,12 +10,12 @@ namespace qqsfpm { \ingroup Filters \brief Filters rows matching a regular expression. - A RegExpFilter is a \l RoleFilter that accepts rows matching a regular rexpression. + A RegExpFilter is a \l RoleFilter that accepts rows matching a regular + rexpression. - In the following example, only rows with their \c lastName role beggining with the content of textfield the will be accepted: - \code - TextField { - id: nameTextField + In the following example, only rows with their \c lastName role beggining + with the content of textfield the will be accepted: \code TextField { id: + nameTextField } SortFilterProxyModel { @@ -35,52 +35,16 @@ namespace qqsfpm { \sa syntax */ -QString RegExpFilter::pattern() const -{ - return m_pattern; -} - -void RegExpFilter::setPattern(const QString& pattern) -{ - if (m_pattern == pattern) - return; - - m_pattern = pattern; - m_regExp.setPattern(pattern); - Q_EMIT patternChanged(); - invalidate(); -} - -/*! - \qmlproperty enum RegExpFilter::syntax - - The pattern used to filter the contents of the source model. - - Only the source model's value having their \l RoleFilter::roleName data matching this \l pattern with the specified \l syntax will be kept. +QString RegExpFilter::pattern() const { return m_pattern; } - \value RegExpFilter.RegExp A rich Perl-like pattern matching syntax. This is the default. - \value RegExpFilter.Wildcard This provides a simple pattern matching syntax similar to that used by shells (command interpreters) for "file globbing". - \value RegExpFilter.FixedString The pattern is a fixed string. This is equivalent to using the RegExp pattern on a string in which all metacharacters are escaped. - \value RegExpFilter.RegExp2 Like RegExp, but with greedy quantifiers. - \value RegExpFilter.WildcardUnix This is similar to Wildcard but with the behavior of a Unix shell. The wildcard characters can be escaped with the character "\". - \value RegExpFilter.W3CXmlSchema11 The pattern is a regular expression as defined by the W3C XML Schema 1.1 specification. +void RegExpFilter::setPattern(const QString &pattern) { + if (m_pattern == pattern) + return; - \sa pattern -*/ -RegExpFilter::PatternSyntax RegExpFilter::syntax() const -{ - return m_syntax; -} - -void RegExpFilter::setSyntax(RegExpFilter::PatternSyntax syntax) -{ - if (m_syntax == syntax) - return; - - m_syntax = syntax; - m_regExp.setPatternSyntax(static_cast(syntax)); - Q_EMIT syntaxChanged(); - invalidate(); + m_pattern = pattern; + m_regularExpression.setPattern(pattern); + Q_EMIT patternChanged(); + invalidate(); } /*! @@ -88,26 +52,29 @@ void RegExpFilter::setSyntax(RegExpFilter::PatternSyntax syntax) This property holds the caseSensitivity of the filter. */ -Qt::CaseSensitivity RegExpFilter::caseSensitivity() const -{ - return m_caseSensitivity; +Qt::CaseSensitivity RegExpFilter::caseSensitivity() const { + return m_regularExpression.patternOptions() & + QRegularExpression::CaseInsensitiveOption + ? Qt::CaseInsensitive + : Qt::CaseSensitive; } -void RegExpFilter::setCaseSensitivity(Qt::CaseSensitivity caseSensitivity) -{ - if (m_caseSensitivity == caseSensitivity) - return; +void RegExpFilter::setCaseSensitivity(Qt::CaseSensitivity caseSensitivity) { + if (this->caseSensitivity() == caseSensitivity) + return; - m_caseSensitivity = caseSensitivity; - m_regExp.setCaseSensitivity(caseSensitivity); - Q_EMIT caseSensitivityChanged(); - invalidate(); + m_regularExpression.setPatternOptions( + m_regularExpression.patternOptions() ^ + QRegularExpression::CaseInsensitiveOption); // toggle the option + Q_EMIT caseSensitivityChanged(); + invalidate(); } -bool RegExpFilter::filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const -{ - QString string = sourceData(sourceIndex, proxyModel).toString(); - return m_regExp.indexIn(string) != -1; +bool RegExpFilter::filterRow(const QModelIndex &sourceIndex, + const QQmlSortFilterProxyModel &proxyModel) const { + QString string = sourceData(sourceIndex, proxyModel).toString(); + QRegularExpressionMatch match = m_regularExpression.match(string); + return match.hasMatch(); } -} +} // namespace qqsfpm diff --git a/filters/regexpfilter.h b/filters/regexpfilter.h index 3227e69..83c34cc 100644 --- a/filters/regexpfilter.h +++ b/filters/regexpfilter.h @@ -7,47 +7,34 @@ namespace qqsfpm { class RegExpFilter : public RoleFilter { - Q_OBJECT - Q_PROPERTY(QString pattern READ pattern WRITE setPattern NOTIFY patternChanged) - Q_PROPERTY(PatternSyntax syntax READ syntax WRITE setSyntax NOTIFY syntaxChanged) - Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE setCaseSensitivity NOTIFY caseSensitivityChanged) + Q_OBJECT + Q_PROPERTY( + QString pattern READ pattern WRITE setPattern NOTIFY patternChanged) + Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE + setCaseSensitivity NOTIFY caseSensitivityChanged) public: - enum PatternSyntax { - RegExp,// = QRegularExpression::RegExp, - Wildcard,// = QRegularExpression::Wildcard, - FixedString,// = QRegularExpression::FixedString, - RegExp2,// = QRegularExpression::RegExp2, - WildcardUnix,// = QRegularExpression::WildcardUnix, - W3CXmlSchema11,/* = QRegularExpression::W3CXmlSchema11*/ }; - Q_ENUMS(PatternSyntax) + using RoleFilter::RoleFilter; - using RoleFilter::RoleFilter; + QString pattern() const; + void setPattern(const QString &pattern); - QString pattern() const; - void setPattern(const QString& pattern); - - PatternSyntax syntax() const; - void setSyntax(PatternSyntax syntax); - - Qt::CaseSensitivity caseSensitivity() const; - void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity); + Qt::CaseSensitivity caseSensitivity() const; + void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity); protected: - bool filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override; + bool filterRow(const QModelIndex &sourceIndex, + const QQmlSortFilterProxyModel &proxyModel) const override; Q_SIGNALS: - void patternChanged(); - void syntaxChanged(); - void caseSensitivityChanged(); + void patternChanged(); + void caseSensitivityChanged(); private: - QRegularExpression m_regExp; - Qt::CaseSensitivity m_caseSensitivity = m_regExp.caseSensitivity(); - PatternSyntax m_syntax = static_cast(m_regExp.patternSyntax()); - QString m_pattern = m_regExp.pattern(); + QRegularExpression m_regularExpression; + QString m_pattern{m_regularExpression.pattern()}; }; -} +} // namespace qqsfpm #endif // REGEXPFILTER_H diff --git a/qqmlsortfilterproxymodel.cpp b/qqmlsortfilterproxymodel.cpp index 267ec12..29b51ea 100644 --- a/qqmlsortfilterproxymodel.cpp +++ b/qqmlsortfilterproxymodel.cpp @@ -1,9 +1,9 @@ #include "qqmlsortfilterproxymodel.h" -#include -#include #include "filters/filter.h" -#include "sorters/sorter.h" #include "proxyroles/proxyrole.h" +#include "sorters/sorter.h" +#include +#include namespace qqsfpm { @@ -13,27 +13,35 @@ namespace qqsfpm { \ingroup SortFilterProxyModel \ingroup FilterContainer \ingroup SorterContainer - \brief Filters and sorts data coming from a source \l {http://doc.qt.io/qt-5/qabstractitemmodel.html} {QAbstractItemModel}. + \brief Filters and sorts data coming from a source \l + {http://doc.qt.io/qt-5/qabstractitemmodel.html} {QAbstractItemModel}. - The SortFilterProxyModel type provides support for filtering and sorting data coming from a source model. - \sa FilterContainer, SorterContainer + The SortFilterProxyModel type provides support for filtering and sorting + data coming from a source model. \sa FilterContainer, SorterContainer */ -QQmlSortFilterProxyModel::QQmlSortFilterProxyModel(QObject *parent) : - QSortFilterProxyModel(parent), +QQmlSortFilterProxyModel::QQmlSortFilterProxyModel(QObject *parent) + : QSortFilterProxyModel(parent), #ifdef SFPM_DELAYED - m_delayed(true) + m_delayed(true) #else - m_delayed(false) + m_delayed(false) #endif { - connect(this, &QAbstractProxyModel::sourceModelChanged, this, &QQmlSortFilterProxyModel::updateRoles); - connect(this, &QAbstractItemModel::modelReset, this, &QQmlSortFilterProxyModel::updateRoles); - connect(this, &QAbstractItemModel::rowsInserted, this, &QQmlSortFilterProxyModel::countChanged); - connect(this, &QAbstractItemModel::rowsRemoved, this, &QQmlSortFilterProxyModel::countChanged); - connect(this, &QAbstractItemModel::modelReset, this, &QQmlSortFilterProxyModel::countChanged); - connect(this, &QAbstractItemModel::layoutChanged, this, &QQmlSortFilterProxyModel::countChanged); - connect(this, &QAbstractItemModel::dataChanged, this, &QQmlSortFilterProxyModel::onDataChanged); - setDynamicSortFilter(true); + connect(this, &QAbstractProxyModel::sourceModelChanged, this, + &QQmlSortFilterProxyModel::updateRoles); + connect(this, &QAbstractItemModel::modelReset, this, + &QQmlSortFilterProxyModel::updateRoles); + connect(this, &QAbstractItemModel::rowsInserted, this, + &QQmlSortFilterProxyModel::countChanged); + connect(this, &QAbstractItemModel::rowsRemoved, this, + &QQmlSortFilterProxyModel::countChanged); + connect(this, &QAbstractItemModel::modelReset, this, + &QQmlSortFilterProxyModel::countChanged); + connect(this, &QAbstractItemModel::layoutChanged, this, + &QQmlSortFilterProxyModel::countChanged); + connect(this, &QAbstractItemModel::dataChanged, this, + &QQmlSortFilterProxyModel::onDataChanged); + setDynamicSortFilter(true); } /*! @@ -47,95 +55,69 @@ QQmlSortFilterProxyModel::QQmlSortFilterProxyModel(QObject *parent) : The number of rows in the proxy model (not filtered out the source model) */ -int QQmlSortFilterProxyModel::count() const -{ - return rowCount(); -} +int QQmlSortFilterProxyModel::count() const { return rowCount(); } /*! \qmlproperty bool SortFilterProxyModel::delayed - Delay the execution of filters, sorters and proxyRoles until the next event loop. - This can be used as an optimization when multiple filters, sorters or proxyRoles are changed in a single event loop. - They will be executed once in a single batch at the next event loop instead of being executed in multiple sequential batches. + Delay the execution of filters, sorters and proxyRoles until the next event + loop. This can be used as an optimization when multiple filters, sorters or + proxyRoles are changed in a single event loop. They will be executed once in + a single batch at the next event loop instead of being executed in multiple + sequential batches. - By default, the SortFilterProxyModel is not delayed, unless the \c SFPM_DELAYED environment variable is defined at compile time. + By default, the SortFilterProxyModel is not delayed, unless the \c + SFPM_DELAYED environment variable is defined at compile time. */ -bool QQmlSortFilterProxyModel::delayed() const -{ - return m_delayed; -} +bool QQmlSortFilterProxyModel::delayed() const { return m_delayed; } -void QQmlSortFilterProxyModel::setDelayed(bool delayed) -{ - if (m_delayed == delayed) - return; +void QQmlSortFilterProxyModel::setDelayed(bool delayed) { + if (m_delayed == delayed) + return; - m_delayed = delayed; - Q_EMIT delayedChanged(); + m_delayed = delayed; + Q_EMIT delayedChanged(); } -const QString& QQmlSortFilterProxyModel::filterRoleName() const -{ - return m_filterRoleName; +const QString &QQmlSortFilterProxyModel::filterRoleName() const { + return m_filterRoleName; } -void QQmlSortFilterProxyModel::setFilterRoleName(const QString& filterRoleName) -{ - if (m_filterRoleName == filterRoleName) - return; +void QQmlSortFilterProxyModel::setFilterRoleName( + const QString &filterRoleName) { + if (m_filterRoleName == filterRoleName) + return; - m_filterRoleName = filterRoleName; - updateFilterRole(); - Q_EMIT filterRoleNameChanged(); + m_filterRoleName = filterRoleName; + updateFilterRole(); + Q_EMIT filterRoleNameChanged(); } -QString QQmlSortFilterProxyModel::filterPattern() const -{ - return filterRegExp().pattern(); +QString QQmlSortFilterProxyModel::filterPattern() const { + return filterRegularExpression().pattern(); } -void QQmlSortFilterProxyModel::setFilterPattern(const QString& filterPattern) -{ - QRegularExpression regExp = filterRegExp(); - if (regExp.pattern() == filterPattern) - return; +void QQmlSortFilterProxyModel::setFilterPattern(const QString &filterPattern) { + QRegularExpression regExp = filterRegularExpression(); + if (regExp.pattern() == filterPattern) + return; - regExp.setPattern(filterPattern); - QSortFilterProxyModel::setFilterRegExp(regExp); - Q_EMIT filterPatternChanged(); + regExp.setPattern(filterPattern); + QSortFilterProxyModel::setFilterRegularExpression(regExp); + Q_EMIT filterPatternChanged(); } -QQmlSortFilterProxyModel::PatternSyntax QQmlSortFilterProxyModel::filterPatternSyntax() const -{ - return static_cast(filterRegExp().patternSyntax()); +const QVariant &QQmlSortFilterProxyModel::filterValue() const { + return m_filterValue; } -void QQmlSortFilterProxyModel::setFilterPatternSyntax(QQmlSortFilterProxyModel::PatternSyntax patternSyntax) -{ - QRegularExpression regExp = filterRegExp(); - QRegularExpression::PatternSyntax patternSyntaxTmp = static_cast(patternSyntax); - if (regExp.patternSyntax() == patternSyntaxTmp) - return; +void QQmlSortFilterProxyModel::setFilterValue(const QVariant &filterValue) { + if (m_filterValue == filterValue) + return; - regExp.setPatternSyntax(patternSyntaxTmp); - QSortFilterProxyModel::setFilterRegExp(regExp); - Q_EMIT filterPatternSyntaxChanged(); -} - -const QVariant& QQmlSortFilterProxyModel::filterValue() const -{ - return m_filterValue; -} - -void QQmlSortFilterProxyModel::setFilterValue(const QVariant& filterValue) -{ - if (m_filterValue == filterValue) - return; - - m_filterValue = filterValue; - queueInvalidateFilter(); - Q_EMIT filterValueChanged(); + m_filterValue = filterValue; + queueInvalidateFilter(); + Q_EMIT filterValueChanged(); } /*! @@ -143,42 +125,41 @@ void QQmlSortFilterProxyModel::setFilterValue(const QVariant& filterValue) The role name of the source model's data used for the sorting. - \sa {http://doc.qt.io/qt-5/qsortfilterproxymodel.html#sortRole-prop} {sortRole}, roleForName + \sa {http://doc.qt.io/qt-5/qsortfilterproxymodel.html#sortRole-prop} + {sortRole}, roleForName */ -const QString& QQmlSortFilterProxyModel::sortRoleName() const -{ - return m_sortRoleName; +const QString &QQmlSortFilterProxyModel::sortRoleName() const { + return m_sortRoleName; } -void QQmlSortFilterProxyModel::setSortRoleName(const QString& sortRoleName) -{ - if (m_sortRoleName == sortRoleName) - return; +void QQmlSortFilterProxyModel::setSortRoleName(const QString &sortRoleName) { + if (m_sortRoleName == sortRoleName) + return; - m_sortRoleName = sortRoleName; - updateSortRole(); - Q_EMIT sortRoleNameChanged(); + m_sortRoleName = sortRoleName; + updateSortRole(); + Q_EMIT sortRoleNameChanged(); } -bool QQmlSortFilterProxyModel::ascendingSortOrder() const -{ - return m_ascendingSortOrder; +bool QQmlSortFilterProxyModel::ascendingSortOrder() const { + return m_ascendingSortOrder; } -void QQmlSortFilterProxyModel::setAscendingSortOrder(bool ascendingSortOrder) -{ - if (m_ascendingSortOrder == ascendingSortOrder) - return; +void QQmlSortFilterProxyModel::setAscendingSortOrder(bool ascendingSortOrder) { + if (m_ascendingSortOrder == ascendingSortOrder) + return; - m_ascendingSortOrder = ascendingSortOrder; - Q_EMIT ascendingSortOrderChanged(); - queueInvalidate(); + m_ascendingSortOrder = ascendingSortOrder; + Q_EMIT ascendingSortOrderChanged(); + queueInvalidate(); } /*! \qmlproperty list SortFilterProxyModel::filters - This property holds the list of filters for this proxy model. To be included in the model, a row of the source model has to be accepted by all the top level filters of this list. + This property holds the list of filters for this proxy model. To be included + in the model, a row of the source model has to be accepted by all the top + level filters of this list. \sa Filter, FilterContainer */ @@ -186,7 +167,9 @@ void QQmlSortFilterProxyModel::setAscendingSortOrder(bool ascendingSortOrder) /*! \qmlproperty list SortFilterProxyModel::sorters - This property holds the list of sorters for this proxy model. The rows of the source model are sorted by the sorters of this list, in their order of insertion. + This property holds the list of sorters for this proxy model. The rows of + the source model are sorted by the sorters of this list, in their order of + insertion. \sa Sorter, SorterContainer */ @@ -194,54 +177,51 @@ void QQmlSortFilterProxyModel::setAscendingSortOrder(bool ascendingSortOrder) /*! \qmlproperty list SortFilterProxyModel::proxyRoles - This property holds the list of proxy roles for this proxy model. Each proxy role adds a new custom role to the model. + This property holds the list of proxy roles for this proxy model. Each proxy + role adds a new custom role to the model. \sa ProxyRole */ -void QQmlSortFilterProxyModel::classBegin() -{ +void QQmlSortFilterProxyModel::classBegin() {} -} +void QQmlSortFilterProxyModel::componentComplete() { + m_completed = true; -void QQmlSortFilterProxyModel::componentComplete() -{ - m_completed = true; + for (const auto &filter : m_filters) + filter->proxyModelCompleted(*this); + for (const auto &sorter : m_sorters) + sorter->proxyModelCompleted(*this); + for (const auto &proxyRole : m_proxyRoles) + proxyRole->proxyModelCompleted(*this); - for (const auto& filter : m_filters) - filter->proxyModelCompleted(*this); - for (const auto& sorter : m_sorters) - sorter->proxyModelCompleted(*this); - for (const auto& proxyRole : m_proxyRoles) - proxyRole->proxyModelCompleted(*this); - - invalidate(); - sort(0); + invalidate(); + sort(0); } -QVariant QQmlSortFilterProxyModel::sourceData(const QModelIndex& sourceIndex, const QString& roleName) const -{ - int role = roleNames().key(roleName.toUtf8()); - return sourceData(sourceIndex, role); +QVariant QQmlSortFilterProxyModel::sourceData(const QModelIndex &sourceIndex, + const QString &roleName) const { + int role = roleNames().key(roleName.toUtf8()); + return sourceData(sourceIndex, role); } -QVariant QQmlSortFilterProxyModel::sourceData(const QModelIndex &sourceIndex, int role) const -{ - QPair proxyRolePair = m_proxyRoleMap[role]; - if (ProxyRole* proxyRole = proxyRolePair.first) - return proxyRole->roleData(sourceIndex, *this, proxyRolePair.second); - else - return sourceModel()->data(sourceIndex, role); +QVariant QQmlSortFilterProxyModel::sourceData(const QModelIndex &sourceIndex, + int role) const { + QPair proxyRolePair = m_proxyRoleMap[role]; + if (ProxyRole *proxyRole = proxyRolePair.first) + return proxyRole->roleData(sourceIndex, *this, proxyRolePair.second); + else + return sourceModel()->data(sourceIndex, role); } -QVariant QQmlSortFilterProxyModel::data(const QModelIndex &index, int role) const -{ - return sourceData(mapToSource(index), role); +QVariant QQmlSortFilterProxyModel::data(const QModelIndex &index, + int role) const { + return sourceData(mapToSource(index), role); } -QHash QQmlSortFilterProxyModel::roleNames() const -{ - return m_roleNames.isEmpty() && sourceModel() ? sourceModel()->roleNames() : m_roleNames; +QHash QQmlSortFilterProxyModel::roleNames() const { + return m_roleNames.isEmpty() && sourceModel() ? sourceModel()->roleNames() + : m_roleNames; } /*! @@ -251,329 +231,323 @@ QHash QQmlSortFilterProxyModel::roleNames() const If no role is found for this \a roleName, \c -1 is returned. */ -int QQmlSortFilterProxyModel::roleForName(const QString& roleName) const -{ - return m_roleNames.key(roleName.toUtf8(), -1); +int QQmlSortFilterProxyModel::roleForName(const QString &roleName) const { + return m_roleNames.key(roleName.toUtf8(), -1); } /*! \qmlmethod object SortFilterProxyModel::get(int row) - Return the item at \a row in the proxy model as a map of all its roles. This allows the item data to be read (not modified) from JavaScript. + Return the item at \a row in the proxy model as a map of all its roles. This + allows the item data to be read (not modified) from JavaScript. */ -QVariantMap QQmlSortFilterProxyModel::get(int row) const -{ - QVariantMap map; - QModelIndex modelIndex = index(row, 0); - QHash roles = roleNames(); - for (QHash::const_iterator it = roles.begin(); it != roles.end(); ++it) - map.insert(it.value(), data(modelIndex, it.key())); - return map; +QVariantMap QQmlSortFilterProxyModel::get(int row) const { + QVariantMap map; + QModelIndex modelIndex = index(row, 0); + QHash roles = roleNames(); + for (QHash::const_iterator it = roles.begin(); + it != roles.end(); ++it) + map.insert(it.value(), data(modelIndex, it.key())); + return map; } /*! \qmlmethod variant SortFilterProxyModel::get(int row, string roleName) - Return the data for the given \a roleName of the item at \a row in the proxy model. This allows the role data to be read (not modified) from JavaScript. + Return the data for the given \a roleName of the item at \a row in the proxy + model. This allows the role data to be read (not modified) from JavaScript. This equivalent to calling \c {data(index(row, 0), roleForName(roleName))}. */ -QVariant QQmlSortFilterProxyModel::get(int row, const QString& roleName) const -{ - return data(index(row, 0), roleForName(roleName)); +QVariant QQmlSortFilterProxyModel::get(int row, const QString &roleName) const { + return data(index(row, 0), roleForName(roleName)); } /*! \qmlmethod index SortFilterProxyModel::mapToSource(index proxyIndex) - Returns the source model index corresponding to the given \a proxyIndex from the SortFilterProxyModel. + Returns the source model index corresponding to the given \a proxyIndex from + the SortFilterProxyModel. */ -QModelIndex QQmlSortFilterProxyModel::mapToSource(const QModelIndex& proxyIndex) const -{ - return QSortFilterProxyModel::mapToSource(proxyIndex); +QModelIndex +QQmlSortFilterProxyModel::mapToSource(const QModelIndex &proxyIndex) const { + return QSortFilterProxyModel::mapToSource(proxyIndex); } /*! \qmlmethod int SortFilterProxyModel::mapToSource(int proxyRow) - Returns the source model row corresponding to the given \a proxyRow from the SortFilterProxyModel. - Returns -1 if there is no corresponding row. + Returns the source model row corresponding to the given \a proxyRow from the + SortFilterProxyModel. Returns -1 if there is no corresponding row. */ -int QQmlSortFilterProxyModel::mapToSource(int proxyRow) const -{ - QModelIndex proxyIndex = index(proxyRow, 0); - QModelIndex sourceIndex = mapToSource(proxyIndex); - return sourceIndex.isValid() ? sourceIndex.row() : -1; +int QQmlSortFilterProxyModel::mapToSource(int proxyRow) const { + QModelIndex proxyIndex = index(proxyRow, 0); + QModelIndex sourceIndex = mapToSource(proxyIndex); + return sourceIndex.isValid() ? sourceIndex.row() : -1; } /*! - \qmlmethod QModelIndex SortFilterProxyModel::mapFromSource(QModelIndex sourceIndex) + \qmlmethod QModelIndex SortFilterProxyModel::mapFromSource(QModelIndex + sourceIndex) - Returns the model index in the SortFilterProxyModel given the \a sourceIndex from the source model. + Returns the model index in the SortFilterProxyModel given the \a sourceIndex + from the source model. */ -QModelIndex QQmlSortFilterProxyModel::mapFromSource(const QModelIndex& sourceIndex) const -{ - return QSortFilterProxyModel::mapFromSource(sourceIndex); +QModelIndex +QQmlSortFilterProxyModel::mapFromSource(const QModelIndex &sourceIndex) const { + return QSortFilterProxyModel::mapFromSource(sourceIndex); } /*! \qmlmethod int SortFilterProxyModel::mapFromSource(int sourceRow) - Returns the row in the SortFilterProxyModel given the \a sourceRow from the source model. - Returns -1 if there is no corresponding row. + Returns the row in the SortFilterProxyModel given the \a sourceRow from the + source model. Returns -1 if there is no corresponding row. */ -int QQmlSortFilterProxyModel::mapFromSource(int sourceRow) const -{ - QModelIndex proxyIndex; - if (QAbstractItemModel* source = sourceModel()) { - QModelIndex sourceIndex = source->index(sourceRow, 0); - proxyIndex = mapFromSource(sourceIndex); +int QQmlSortFilterProxyModel::mapFromSource(int sourceRow) const { + QModelIndex proxyIndex; + if (QAbstractItemModel *source = sourceModel()) { + QModelIndex sourceIndex = source->index(sourceRow, 0); + proxyIndex = mapFromSource(sourceIndex); + } + return proxyIndex.isValid() ? proxyIndex.row() : -1; +} + +bool QQmlSortFilterProxyModel::filterAcceptsRow( + int source_row, const QModelIndex &source_parent) const { + if (!m_completed) + return true; + QModelIndex sourceIndex = sourceModel()->index(source_row, 0, source_parent); + bool valueAccepted = + !m_filterValue.isValid() || + (m_filterValue == sourceModel()->data(sourceIndex, filterRole())); + bool baseAcceptsRow = + valueAccepted && + QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); + baseAcceptsRow = + baseAcceptsRow && + std::all_of(m_filters.begin(), m_filters.end(), [=](Filter *filter) { + return filter->filterAcceptsRow(sourceIndex, *this); + }); + return baseAcceptsRow; +} + +bool QQmlSortFilterProxyModel::lessThan(const QModelIndex &source_left, + const QModelIndex &source_right) const { + if (m_completed) { + if (!m_sortRoleName.isEmpty()) { + if (QSortFilterProxyModel::lessThan(source_left, source_right)) + return m_ascendingSortOrder; + if (QSortFilterProxyModel::lessThan(source_right, source_left)) + return !m_ascendingSortOrder; } - return proxyIndex.isValid() ? proxyIndex.row() : -1; -} - -bool QQmlSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const -{ - if (!m_completed) - return true; - QModelIndex sourceIndex = sourceModel()->index(source_row, 0, source_parent); - bool valueAccepted = !m_filterValue.isValid() || ( m_filterValue == sourceModel()->data(sourceIndex, filterRole()) ); - bool baseAcceptsRow = valueAccepted && QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); - baseAcceptsRow = baseAcceptsRow && std::all_of(m_filters.begin(), m_filters.end(), - [=] (Filter* filter) { - return filter->filterAcceptsRow(sourceIndex, *this); - } - ); - return baseAcceptsRow; -} - -bool QQmlSortFilterProxyModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const -{ - if (m_completed) { - if (!m_sortRoleName.isEmpty()) { - if (QSortFilterProxyModel::lessThan(source_left, source_right)) - return m_ascendingSortOrder; - if (QSortFilterProxyModel::lessThan(source_right, source_left)) - return !m_ascendingSortOrder; - } - auto sortedSorters = m_sorters; - std::stable_sort(sortedSorters.begin(), - sortedSorters.end(), - [] (Sorter* a, Sorter* b) { - return a->priority() > b->priority(); - }); - for(auto sorter : sortedSorters) { - if (sorter->enabled()) { - int comparison = sorter->compareRows(source_left, source_right, *this); - if (comparison != 0) - return comparison < 0; - } - } + auto sortedSorters = m_sorters; + std::stable_sort( + sortedSorters.begin(), sortedSorters.end(), + [](Sorter *a, Sorter *b) { return a->priority() > b->priority(); }); + for (auto sorter : sortedSorters) { + if (sorter->enabled()) { + int comparison = sorter->compareRows(source_left, source_right, *this); + if (comparison != 0) + return comparison < 0; + } } - return source_left.row() < source_right.row(); + } + return source_left.row() < source_right.row(); } -void QQmlSortFilterProxyModel::resetInternalData() -{ - QSortFilterProxyModel::resetInternalData(); - updateRoleNames(); +void QQmlSortFilterProxyModel::resetInternalData() { + QSortFilterProxyModel::resetInternalData(); + updateRoleNames(); } -void QQmlSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel) -{ - if (sourceModel && sourceModel->roleNames().isEmpty()) { // workaround for when a model has no roles and roles are added when the model is populated (ListModel) - // QTBUG-57971 - connect(sourceModel, &QAbstractItemModel::rowsInserted, this, &QQmlSortFilterProxyModel::initRoles); - } - QSortFilterProxyModel::setSourceModel(sourceModel); +void QQmlSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel) { + if (sourceModel && + sourceModel->roleNames() + .isEmpty()) { // workaround for when a model has no roles and roles + // are added when the model is populated (ListModel) + // QTBUG-57971 + connect(sourceModel, &QAbstractItemModel::rowsInserted, this, + &QQmlSortFilterProxyModel::initRoles); + } + QSortFilterProxyModel::setSourceModel(sourceModel); } -void QQmlSortFilterProxyModel::queueInvalidateFilter() -{ - if (m_delayed) { - if (!m_invalidateFilterQueued && !m_invalidateQueued) { - m_invalidateFilterQueued = true; - QMetaObject::invokeMethod(this, "invalidateFilter", Qt::QueuedConnection); - } - } else { - invalidateFilter(); +void QQmlSortFilterProxyModel::queueInvalidateFilter() { + if (m_delayed) { + if (!m_invalidateFilterQueued && !m_invalidateQueued) { + m_invalidateFilterQueued = true; + QMetaObject::invokeMethod(this, "invalidateFilter", Qt::QueuedConnection); } + } else { + invalidateFilter(); + } } -void QQmlSortFilterProxyModel::invalidateFilter() -{ - m_invalidateFilterQueued = false; - if (m_completed && !m_invalidateQueued) - QSortFilterProxyModel::invalidateFilter(); +void QQmlSortFilterProxyModel::invalidateFilter() { + m_invalidateFilterQueued = false; + if (m_completed && !m_invalidateQueued) + QSortFilterProxyModel::invalidateFilter(); } -void QQmlSortFilterProxyModel::queueInvalidate() -{ - if (m_delayed) { - if (!m_invalidateQueued) { - m_invalidateQueued = true; - QMetaObject::invokeMethod(this, "invalidate", Qt::QueuedConnection); - } - } else { - invalidate(); +void QQmlSortFilterProxyModel::queueInvalidate() { + if (m_delayed) { + if (!m_invalidateQueued) { + m_invalidateQueued = true; + QMetaObject::invokeMethod(this, "invalidate", Qt::QueuedConnection); } -} - -void QQmlSortFilterProxyModel::invalidate() -{ - m_invalidateQueued = false; - if (m_completed) - QSortFilterProxyModel::invalidate(); -} - -void QQmlSortFilterProxyModel::updateRoleNames() -{ - if (!sourceModel()) - return; - m_roleNames = sourceModel()->roleNames(); - m_proxyRoleMap.clear(); - m_proxyRoleNumbers.clear(); - - auto roles = m_roleNames.keys(); - auto maxIt = std::max_element(roles.cbegin(), roles.cend()); - int maxRole = maxIt != roles.cend() ? *maxIt : -1; - for (auto proxyRole : m_proxyRoles) { - for (auto roleName : proxyRole->names()) { - ++maxRole; - m_roleNames[maxRole] = roleName.toUtf8(); - m_proxyRoleMap[maxRole] = {proxyRole, roleName}; - m_proxyRoleNumbers.append(maxRole); - } + } else { + invalidate(); + } +} + +void QQmlSortFilterProxyModel::invalidate() { + m_invalidateQueued = false; + if (m_completed) + QSortFilterProxyModel::invalidate(); +} + +void QQmlSortFilterProxyModel::updateRoleNames() { + if (!sourceModel()) + return; + m_roleNames = sourceModel()->roleNames(); + m_proxyRoleMap.clear(); + m_proxyRoleNumbers.clear(); + + auto roles = m_roleNames.keys(); + auto maxIt = std::max_element(roles.cbegin(), roles.cend()); + int maxRole = maxIt != roles.cend() ? *maxIt : -1; + for (auto proxyRole : m_proxyRoles) { + for (auto roleName : proxyRole->names()) { + ++maxRole; + m_roleNames[maxRole] = roleName.toUtf8(); + m_proxyRoleMap[maxRole] = {proxyRole, roleName}; + m_proxyRoleNumbers.append(maxRole); } + } } -void QQmlSortFilterProxyModel::updateFilterRole() -{ - QList filterRoles = roleNames().keys(m_filterRoleName.toUtf8()); - if (!filterRoles.empty()) - { - setFilterRole(filterRoles.first()); - } +void QQmlSortFilterProxyModel::updateFilterRole() { + QList filterRoles = roleNames().keys(m_filterRoleName.toUtf8()); + if (!filterRoles.empty()) { + setFilterRole(filterRoles.first()); + } } -void QQmlSortFilterProxyModel::updateSortRole() -{ - QList sortRoles = roleNames().keys(m_sortRoleName.toUtf8()); - if (!sortRoles.empty()) - { - setSortRole(sortRoles.first()); - queueInvalidate(); - } +void QQmlSortFilterProxyModel::updateSortRole() { + QList sortRoles = roleNames().keys(m_sortRoleName.toUtf8()); + if (!sortRoles.empty()) { + setSortRole(sortRoles.first()); + queueInvalidate(); + } } -void QQmlSortFilterProxyModel::updateRoles() -{ - updateFilterRole(); - updateSortRole(); +void QQmlSortFilterProxyModel::updateRoles() { + updateFilterRole(); + updateSortRole(); } -void QQmlSortFilterProxyModel::initRoles() -{ - disconnect(sourceModel(), &QAbstractItemModel::rowsInserted, this, &QQmlSortFilterProxyModel::initRoles); - resetInternalData(); - updateRoles(); +void QQmlSortFilterProxyModel::initRoles() { + disconnect(sourceModel(), &QAbstractItemModel::rowsInserted, this, + &QQmlSortFilterProxyModel::initRoles); + resetInternalData(); + updateRoles(); } -void QQmlSortFilterProxyModel::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles) -{ - Q_UNUSED(roles); - if (!roles.isEmpty() && !m_proxyRoleNumbers.empty() && roles != m_proxyRoleNumbers) - Q_EMIT dataChanged(topLeft, bottomRight, m_proxyRoleNumbers); +void QQmlSortFilterProxyModel::onDataChanged(const QModelIndex &topLeft, + const QModelIndex &bottomRight, + const QVector &roles) { + Q_UNUSED(roles); + bool proxyRoleChanged = + !m_proxyRoleNumbers.empty() && + std::any_of(m_proxyRoleNumbers.begin(), m_proxyRoleNumbers.end(), + [&roles](const auto &it) { return roles.contains(it); }); + if (proxyRoleChanged) + Q_EMIT dataChanged(topLeft, bottomRight, m_proxyRoleNumbers); } -void QQmlSortFilterProxyModel::queueInvalidateProxyRoles() -{ - queueInvalidate(); - if (m_delayed) { - if (!m_invalidateProxyRolesQueued) { - m_invalidateProxyRolesQueued = true; - QMetaObject::invokeMethod(this, "invalidateProxyRoles", Qt::QueuedConnection); - } - } else { - invalidateProxyRoles(); +void QQmlSortFilterProxyModel::queueInvalidateProxyRoles() { + queueInvalidate(); + if (m_delayed) { + if (!m_invalidateProxyRolesQueued) { + m_invalidateProxyRolesQueued = true; + QMetaObject::invokeMethod(this, "invalidateProxyRoles", + Qt::QueuedConnection); } + } else { + invalidateProxyRoles(); + } } -void QQmlSortFilterProxyModel::invalidateProxyRoles() -{ - m_invalidateProxyRolesQueued = false; - if (m_completed) - Q_EMIT dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1), m_proxyRoleNumbers); +void QQmlSortFilterProxyModel::invalidateProxyRoles() { + m_invalidateProxyRolesQueued = false; + if (m_completed) + Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1), + m_proxyRoleNumbers); } -QVariantMap QQmlSortFilterProxyModel::modelDataMap(const QModelIndex& modelIndex) const -{ - QVariantMap map; - QHash roles = roleNames(); - for (QHash::const_iterator it = roles.begin(); it != roles.end(); ++it) - map.insert(it.value(), sourceModel()->data(modelIndex, it.key())); - return map; +QVariantMap +QQmlSortFilterProxyModel::modelDataMap(const QModelIndex &modelIndex) const { + QVariantMap map; + QHash roles = roleNames(); + for (QHash::const_iterator it = roles.begin(); + it != roles.end(); ++it) + map.insert(it.value(), sourceModel()->data(modelIndex, it.key())); + return map; } -void QQmlSortFilterProxyModel::onFilterAppended(Filter* filter) -{ - connect(filter, &Filter::invalidated, this, &QQmlSortFilterProxyModel::queueInvalidateFilter); - queueInvalidateFilter(); +void QQmlSortFilterProxyModel::onFilterAppended(Filter *filter) { + connect(filter, &Filter::invalidated, this, + &QQmlSortFilterProxyModel::queueInvalidateFilter); + queueInvalidateFilter(); } -void QQmlSortFilterProxyModel::onFilterRemoved(Filter* filter) -{ - Q_UNUSED(filter) - queueInvalidateFilter(); +void QQmlSortFilterProxyModel::onFilterRemoved(Filter *filter) { + Q_UNUSED(filter) + queueInvalidateFilter(); } -void QQmlSortFilterProxyModel::onFiltersCleared() -{ - queueInvalidateFilter(); -} +void QQmlSortFilterProxyModel::onFiltersCleared() { queueInvalidateFilter(); } -void QQmlSortFilterProxyModel::onSorterAppended(Sorter* sorter) -{ - connect(sorter, &Sorter::invalidated, this, &QQmlSortFilterProxyModel::queueInvalidate); - queueInvalidate(); +void QQmlSortFilterProxyModel::onSorterAppended(Sorter *sorter) { + connect(sorter, &Sorter::invalidated, this, + &QQmlSortFilterProxyModel::queueInvalidate); + queueInvalidate(); } -void QQmlSortFilterProxyModel::onSorterRemoved(Sorter* sorter) -{ - Q_UNUSED(sorter) - queueInvalidate(); +void QQmlSortFilterProxyModel::onSorterRemoved(Sorter *sorter) { + Q_UNUSED(sorter) + queueInvalidate(); } -void QQmlSortFilterProxyModel::onSortersCleared() -{ - queueInvalidate(); -} +void QQmlSortFilterProxyModel::onSortersCleared() { queueInvalidate(); } -void QQmlSortFilterProxyModel::onProxyRoleAppended(ProxyRole *proxyRole) -{ - beginResetModel(); - connect(proxyRole, &ProxyRole::invalidated, this, &QQmlSortFilterProxyModel::queueInvalidateProxyRoles); - connect(proxyRole, &ProxyRole::namesAboutToBeChanged, this, &QQmlSortFilterProxyModel::beginResetModel); - connect(proxyRole, &ProxyRole::namesChanged, this, &QQmlSortFilterProxyModel::endResetModel); - endResetModel(); +void QQmlSortFilterProxyModel::onProxyRoleAppended(ProxyRole *proxyRole) { + beginResetModel(); + connect(proxyRole, &ProxyRole::invalidated, this, + &QQmlSortFilterProxyModel::queueInvalidateProxyRoles); + connect(proxyRole, &ProxyRole::namesAboutToBeChanged, this, + &QQmlSortFilterProxyModel::beginResetModel); + connect(proxyRole, &ProxyRole::namesChanged, this, + &QQmlSortFilterProxyModel::endResetModel); + endResetModel(); } -void QQmlSortFilterProxyModel::onProxyRoleRemoved(ProxyRole *proxyRole) -{ - Q_UNUSED(proxyRole) - beginResetModel(); - endResetModel(); +void QQmlSortFilterProxyModel::onProxyRoleRemoved(ProxyRole *proxyRole) { + Q_UNUSED(proxyRole) + beginResetModel(); + endResetModel(); } -void QQmlSortFilterProxyModel::onProxyRolesCleared() -{ - beginResetModel(); - endResetModel(); +void QQmlSortFilterProxyModel::onProxyRolesCleared() { + beginResetModel(); + endResetModel(); } void registerQQmlSortFilterProxyModelTypes() { - qmlRegisterType("SortFilterProxyModel", 0, 2, "SortFilterProxyModel"); + qmlRegisterType("SortFilterProxyModel", 0, 2, + "SortFilterProxyModel"); } Q_COREAPP_STARTUP_FUNCTION(registerQQmlSortFilterProxyModelTypes) -} +} // namespace qqsfpm diff --git a/qqmlsortfilterproxymodel.h b/qqmlsortfilterproxymodel.h index 23f1c09..0697e15 100644 --- a/qqmlsortfilterproxymodel.h +++ b/qqmlsortfilterproxymodel.h @@ -1,11 +1,11 @@ #ifndef QQMLSORTFILTERPROXYMODEL_H #define QQMLSORTFILTERPROXYMODEL_H -#include -#include #include "filters/filtercontainer.h" -#include "sorters/sortercontainer.h" #include "proxyroles/proxyrolecontainer.h" +#include "sorters/sortercontainer.h" +#include +#include namespace qqsfpm { @@ -13,148 +13,146 @@ class QQmlSortFilterProxyModel : public QSortFilterProxyModel, public QQmlParserStatus, public FilterContainer, public SorterContainer, - public ProxyRoleContainer -{ - Q_OBJECT - Q_INTERFACES(QQmlParserStatus) - Q_INTERFACES(qqsfpm::FilterContainer) - Q_INTERFACES(qqsfpm::SorterContainer) - Q_INTERFACES(qqsfpm::ProxyRoleContainer) - - Q_PROPERTY(int count READ count NOTIFY countChanged) - Q_PROPERTY(bool delayed READ delayed WRITE setDelayed NOTIFY delayedChanged) - - Q_PROPERTY(QString filterRoleName READ filterRoleName WRITE setFilterRoleName NOTIFY filterRoleNameChanged) - Q_PROPERTY(QString filterPattern READ filterPattern WRITE setFilterPattern NOTIFY filterPatternChanged) - Q_PROPERTY(PatternSyntax filterPatternSyntax READ filterPatternSyntax WRITE setFilterPatternSyntax NOTIFY filterPatternSyntaxChanged) - Q_PROPERTY(QVariant filterValue READ filterValue WRITE setFilterValue NOTIFY filterValueChanged) - - Q_PROPERTY(QString sortRoleName READ sortRoleName WRITE setSortRoleName NOTIFY sortRoleNameChanged) - Q_PROPERTY(bool ascendingSortOrder READ ascendingSortOrder WRITE setAscendingSortOrder NOTIFY ascendingSortOrderChanged) - - Q_PROPERTY(QQmlListProperty filters READ filtersListProperty) - Q_PROPERTY(QQmlListProperty sorters READ sortersListProperty) - Q_PROPERTY(QQmlListProperty proxyRoles READ proxyRolesListProperty) + public ProxyRoleContainer { + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + Q_INTERFACES(qqsfpm::FilterContainer) + Q_INTERFACES(qqsfpm::SorterContainer) + Q_INTERFACES(qqsfpm::ProxyRoleContainer) + + Q_PROPERTY(int count READ count NOTIFY countChanged) + Q_PROPERTY(bool delayed READ delayed WRITE setDelayed NOTIFY delayedChanged) + + Q_PROPERTY(QString filterRoleName READ filterRoleName WRITE setFilterRoleName + NOTIFY filterRoleNameChanged) + Q_PROPERTY(QString filterPattern READ filterPattern WRITE setFilterPattern + NOTIFY filterPatternChanged) + Q_PROPERTY(QVariant filterValue READ filterValue WRITE setFilterValue NOTIFY + filterValueChanged) + + Q_PROPERTY(QString sortRoleName READ sortRoleName WRITE setSortRoleName NOTIFY + sortRoleNameChanged) + Q_PROPERTY(bool ascendingSortOrder READ ascendingSortOrder WRITE + setAscendingSortOrder NOTIFY ascendingSortOrderChanged) + + Q_PROPERTY(QQmlListProperty filters READ filtersListProperty) + Q_PROPERTY(QQmlListProperty sorters READ sortersListProperty) + Q_PROPERTY(QQmlListProperty proxyRoles READ + proxyRolesListProperty) public: - enum PatternSyntax { - RegExp,// = QRegularExpression::RegExp, - Wildcard,// = QRegularExpression::Wildcard, - FixedString,// = QRegularExpression::FixedString, - RegExp2,// = QRegularExpression::RegExp2, - WildcardUnix,// = QRegularExpression::WildcardUnix, - W3CXmlSchema11,/* = QRegularExpression::W3CXmlSchema11*/ }; - Q_ENUMS(PatternSyntax) - - QQmlSortFilterProxyModel(QObject* parent = 0); - - int count() const; + QQmlSortFilterProxyModel(QObject *parent = 0); - bool delayed() const; - void setDelayed(bool delayed); + int count() const; - const QString& filterRoleName() const; - void setFilterRoleName(const QString& filterRoleName); + bool delayed() const; + void setDelayed(bool delayed); - QString filterPattern() const; - void setFilterPattern(const QString& filterPattern); + const QString &filterRoleName() const; + void setFilterRoleName(const QString &filterRoleName); - PatternSyntax filterPatternSyntax() const; - void setFilterPatternSyntax(PatternSyntax patternSyntax); + QString filterPattern() const; + void setFilterPattern(const QString &filterPattern); - const QVariant& filterValue() const; - void setFilterValue(const QVariant& filterValue); + const QVariant &filterValue() const; + void setFilterValue(const QVariant &filterValue); - const QString& sortRoleName() const; - void setSortRoleName(const QString& sortRoleName); + const QString &sortRoleName() const; + void setSortRoleName(const QString &sortRoleName); - bool ascendingSortOrder() const; - void setAscendingSortOrder(bool ascendingSortOrder); + bool ascendingSortOrder() const; + void setAscendingSortOrder(bool ascendingSortOrder); - void classBegin() override; - void componentComplete() override; + void classBegin() override; + void componentComplete() override; - QVariant sourceData(const QModelIndex& sourceIndex, const QString& roleName) const; - QVariant sourceData(const QModelIndex& sourceIndex, int role) const; + QVariant sourceData(const QModelIndex &sourceIndex, + const QString &roleName) const; + QVariant sourceData(const QModelIndex &sourceIndex, int role) const; - QVariant data(const QModelIndex& index, int role) const override; - QHash roleNames() const override; + QVariant data(const QModelIndex &index, int role) const override; + QHash roleNames() const override; - Q_INVOKABLE int roleForName(const QString& roleName) const; + Q_INVOKABLE int roleForName(const QString &roleName) const; - Q_INVOKABLE QVariantMap get(int row) const; - Q_INVOKABLE QVariant get(int row, const QString& roleName) const; + Q_INVOKABLE QVariantMap get(int row) const; + Q_INVOKABLE QVariant get(int row, const QString &roleName) const; - Q_INVOKABLE QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; - Q_INVOKABLE int mapToSource(int proxyRow) const; - Q_INVOKABLE QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override; - Q_INVOKABLE int mapFromSource(int sourceRow) const; + Q_INVOKABLE QModelIndex + mapToSource(const QModelIndex &proxyIndex) const override; + Q_INVOKABLE int mapToSource(int proxyRow) const; + Q_INVOKABLE QModelIndex + mapFromSource(const QModelIndex &sourceIndex) const override; + Q_INVOKABLE int mapFromSource(int sourceRow) const; - void setSourceModel(QAbstractItemModel *sourceModel) override; + void setSourceModel(QAbstractItemModel *sourceModel) override; Q_SIGNALS: - void countChanged(); - void delayedChanged(); + void countChanged(); + void delayedChanged(); - void filterRoleNameChanged(); - void filterPatternSyntaxChanged(); - void filterPatternChanged(); - void filterValueChanged(); + void filterRoleNameChanged(); + void filterPatternSyntaxChanged(); + void filterPatternChanged(); + void filterValueChanged(); - void sortRoleNameChanged(); - void ascendingSortOrderChanged(); + void sortRoleNameChanged(); + void ascendingSortOrderChanged(); protected: - bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; - bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override; + bool filterAcceptsRow(int source_row, + const QModelIndex &source_parent) const override; + bool lessThan(const QModelIndex &source_left, + const QModelIndex &source_right) const override; protected Q_SLOTS: - void resetInternalData(); + void resetInternalData() override; private Q_SLOTS: - void queueInvalidateFilter(); - void invalidateFilter(); - void queueInvalidate(); - void invalidate(); - void updateRoleNames(); - void updateFilterRole(); - void updateSortRole(); - void updateRoles(); - void initRoles(); - void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles); - void queueInvalidateProxyRoles(); - void invalidateProxyRoles(); + void queueInvalidateFilter(); + void invalidateFilter(); + void queueInvalidate(); + void invalidate(); + void updateRoleNames(); + void updateFilterRole(); + void updateSortRole(); + void updateRoles(); + void initRoles(); + void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, + const QVector &roles); + void queueInvalidateProxyRoles(); + void invalidateProxyRoles(); private: - QVariantMap modelDataMap(const QModelIndex& modelIndex) const; - - void onFilterAppended(Filter* filter) override; - void onFilterRemoved(Filter* filter) override; - void onFiltersCleared() override; - - void onSorterAppended(Sorter* sorter) override; - void onSorterRemoved(Sorter* sorter) override; - void onSortersCleared() override; - - void onProxyRoleAppended(ProxyRole *proxyRole) override; - void onProxyRoleRemoved(ProxyRole *proxyRole) override; - void onProxyRolesCleared() override; - - bool m_delayed; - QString m_filterRoleName; - QVariant m_filterValue; - QString m_sortRoleName; - bool m_ascendingSortOrder = true; - bool m_completed = false; - QHash m_roleNames; - QHash> m_proxyRoleMap; - QVector m_proxyRoleNumbers; - - bool m_invalidateFilterQueued = false; - bool m_invalidateQueued = false; - bool m_invalidateProxyRolesQueued = false; + QVariantMap modelDataMap(const QModelIndex &modelIndex) const; + + void onFilterAppended(Filter *filter) override; + void onFilterRemoved(Filter *filter) override; + void onFiltersCleared() override; + + void onSorterAppended(Sorter *sorter) override; + void onSorterRemoved(Sorter *sorter) override; + void onSortersCleared() override; + + void onProxyRoleAppended(ProxyRole *proxyRole) override; + void onProxyRoleRemoved(ProxyRole *proxyRole) override; + void onProxyRolesCleared() override; + + bool m_delayed; + QString m_filterRoleName; + QVariant m_filterValue; + QString m_sortRoleName; + bool m_ascendingSortOrder = true; + bool m_completed = false; + QHash m_roleNames; + QHash> m_proxyRoleMap; + QVector m_proxyRoleNumbers; + + bool m_invalidateFilterQueued = false; + bool m_invalidateQueued = false; + bool m_invalidateProxyRolesQueued = false; }; -} +} // namespace qqsfpm #endif // QQMLSORTFILTERPROXYMODEL_H diff --git a/sorters/sorter.cpp b/sorters/sorter.cpp index e9d0547..dd469d3 100644 --- a/sorters/sorter.cpp +++ b/sorters/sorter.cpp @@ -16,11 +16,7 @@ namespace qqsfpm { Attempting to use the Sorter type directly will result in an error. */ -Sorter::Sorter(QObject *parent) : QObject(parent) -{ -} - -Sorter::~Sorter() = default; +Sorter::Sorter(QObject *parent) : QObject(parent) {} /*! \qmlproperty bool Sorter::enabled @@ -30,55 +26,46 @@ Sorter::~Sorter() = default; By default, sorters are enabled. */ -bool Sorter::enabled() const -{ - return m_enabled; -} +bool Sorter::enabled() const { return m_enabled; } -void Sorter::setEnabled(bool enabled) -{ - if (m_enabled == enabled) - return; +void Sorter::setEnabled(bool enabled) { + if (m_enabled == enabled) + return; - m_enabled = enabled; - Q_EMIT enabledChanged(); - Q_EMIT invalidated(); + m_enabled = enabled; + Q_EMIT enabledChanged(); + Q_EMIT invalidated(); } -bool Sorter::ascendingOrder() const -{ - return sortOrder() == Qt::AscendingOrder; +bool Sorter::ascendingOrder() const { + return sortOrder() == Qt::AscendingOrder; } -void Sorter::setAscendingOrder(bool ascendingOrder) -{ - setSortOrder(ascendingOrder ? Qt::AscendingOrder : Qt::DescendingOrder); +void Sorter::setAscendingOrder(bool ascendingOrder) { + setSortOrder(ascendingOrder ? Qt::AscendingOrder : Qt::DescendingOrder); } - /*! \qmlproperty Qt::SortOrder Sorter::sortOrder This property holds the sort order of this sorter. - \value Qt.AscendingOrder The items are sorted ascending e.g. starts with 'AAA' ends with 'ZZZ' in Latin-1 locales - \value Qt.DescendingOrder The items are sorted descending e.g. starts with 'ZZZ' ends with 'AAA' in Latin-1 locales + \value Qt.AscendingOrder The items are sorted ascending e.g. starts with + 'AAA' ends with 'ZZZ' in Latin-1 locales \value Qt.DescendingOrder The items + are sorted descending e.g. starts with 'ZZZ' ends with 'AAA' in Latin-1 + locales By default, sorting is in ascending order. */ -Qt::SortOrder Sorter::sortOrder() const -{ - return m_sortOrder; -} +Qt::SortOrder Sorter::sortOrder() const { return m_sortOrder; } -void Sorter::setSortOrder(Qt::SortOrder sortOrder) -{ - if (m_sortOrder == sortOrder) - return; +void Sorter::setSortOrder(Qt::SortOrder sortOrder) { + if (m_sortOrder == sortOrder) + return; - m_sortOrder = sortOrder; - Q_EMIT sortOrderChanged(); - invalidate(); + m_sortOrder = sortOrder; + Q_EMIT sortOrderChanged(); + invalidate(); } /*! @@ -90,53 +77,50 @@ void Sorter::setSortOrder(Qt::SortOrder sortOrder) By default, the priority is 0. */ -int Sorter::priority() const -{ - return m_priority; -} +int Sorter::priority() const { return m_priority; } -void Sorter::setPriority(int priority) -{ - if (m_priority == priority) - return; +void Sorter::setPriority(int priority) { + if (m_priority == priority) + return; - m_priority = priority; - Q_EMIT priorityChanged(); - invalidate(); + m_priority = priority; + Q_EMIT priorityChanged(); + invalidate(); } -int Sorter::compareRows(const QModelIndex &source_left, const QModelIndex &source_right, const QQmlSortFilterProxyModel& proxyModel) const -{ - int comparison = compare(source_left, source_right, proxyModel); - return (m_sortOrder == Qt::AscendingOrder) ? comparison : -comparison; +int Sorter::compareRows(const QModelIndex &source_left, + const QModelIndex &source_right, + const QQmlSortFilterProxyModel &proxyModel) const { + int comparison = compare(source_left, source_right, proxyModel); + return (m_sortOrder == Qt::AscendingOrder) ? comparison : -comparison; } -int Sorter::compare(const QModelIndex &sourceLeft, const QModelIndex &sourceRight, const QQmlSortFilterProxyModel& proxyModel) const -{ - if (lessThan(sourceLeft, sourceRight, proxyModel)) - return -1; - if (lessThan(sourceRight, sourceLeft, proxyModel)) - return 1; - return 0; +int Sorter::compare(const QModelIndex &sourceLeft, + const QModelIndex &sourceRight, + const QQmlSortFilterProxyModel &proxyModel) const { + if (lessThan(sourceLeft, sourceRight, proxyModel)) + return -1; + if (lessThan(sourceRight, sourceLeft, proxyModel)) + return 1; + return 0; } -void Sorter::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) -{ - Q_UNUSED(proxyModel) +void Sorter::proxyModelCompleted(const QQmlSortFilterProxyModel &proxyModel) { + Q_UNUSED(proxyModel) } -bool Sorter::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight, const QQmlSortFilterProxyModel& proxyModel) const -{ - Q_UNUSED(sourceLeft) - Q_UNUSED(sourceRight) - Q_UNUSED(proxyModel) - return false; +bool Sorter::lessThan(const QModelIndex &sourceLeft, + const QModelIndex &sourceRight, + const QQmlSortFilterProxyModel &proxyModel) const { + Q_UNUSED(sourceLeft) + Q_UNUSED(sourceRight) + Q_UNUSED(proxyModel) + return false; } -void Sorter::invalidate() -{ - if (m_enabled) - Q_EMIT invalidated(); +void Sorter::invalidate() { + if (m_enabled) + Q_EMIT invalidated(); } -} +} // namespace qqsfpm diff --git a/sorters/sorter.h b/sorters/sorter.h index 80e3386..68762aa 100644 --- a/sorters/sorter.h +++ b/sorters/sorter.h @@ -7,51 +7,60 @@ namespace qqsfpm { class QQmlSortFilterProxyModel; -class Sorter : public QObject -{ - Q_OBJECT - Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) - Q_PROPERTY(bool ascendingOrder READ ascendingOrder WRITE setAscendingOrder NOTIFY sortOrderChanged) - Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder NOTIFY sortOrderChanged) - Q_PROPERTY(int priority READ priority WRITE setPriority NOTIFY priorityChanged) +class Sorter : public QObject { + Q_OBJECT + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + Q_PROPERTY(bool ascendingOrder READ ascendingOrder WRITE setAscendingOrder + NOTIFY sortOrderChanged) + Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder NOTIFY + sortOrderChanged) + Q_PROPERTY( + int priority READ priority WRITE setPriority NOTIFY priorityChanged) public: - explicit Sorter(QObject* parent = nullptr); + explicit Sorter(QObject *parent = nullptr); + ~Sorter() = default; - bool enabled() const; - void setEnabled(bool enabled); + bool enabled() const; + void setEnabled(bool enabled); - bool ascendingOrder() const; - void setAscendingOrder(bool ascendingOrder); + bool ascendingOrder() const; + void setAscendingOrder(bool ascendingOrder); - Qt::SortOrder sortOrder() const; - void setSortOrder(Qt::SortOrder sortOrder); + Qt::SortOrder sortOrder() const; + void setSortOrder(Qt::SortOrder sortOrder); - int priority() const; - void setPriority(int priority); + int priority() const; + void setPriority(int priority); - int compareRows(const QModelIndex& source_left, const QModelIndex& source_right, const QQmlSortFilterProxyModel& proxyModel) const; + int compareRows(const QModelIndex &source_left, + const QModelIndex &source_right, + const QQmlSortFilterProxyModel &proxyModel) const; - virtual void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel); + virtual void proxyModelCompleted(const QQmlSortFilterProxyModel &proxyModel); Q_SIGNALS: - void enabledChanged(); - void sortOrderChanged(); - void priorityChanged(); + void enabledChanged(); + void sortOrderChanged(); + void priorityChanged(); - void invalidated(); + void invalidated(); protected: - virtual int compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const; - virtual bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const; - void invalidate(); + virtual int compare(const QModelIndex &sourceLeft, + const QModelIndex &sourceRight, + const QQmlSortFilterProxyModel &proxyModel) const; + virtual bool lessThan(const QModelIndex &sourceLeft, + const QModelIndex &sourceRight, + const QQmlSortFilterProxyModel &proxyModel) const; + void invalidate(); private: - bool m_enabled = true; - Qt::SortOrder m_sortOrder = Qt::AscendingOrder; - int m_priority = 0; + bool m_enabled = true; + Qt::SortOrder m_sortOrder = Qt::AscendingOrder; + int m_priority = 0; }; -} +} // namespace qqsfpm #endif // SORTER_H From 3ba9b422bcceed6df0e9a67852494b00c0cd99b3 Mon Sep 17 00:00:00 2001 From: r-vitanov Date: Fri, 12 Nov 2021 13:46:33 +0100 Subject: [PATCH 7/7] Fixed tests (by removing the custom role matching --- qqmlsortfilterproxymodel.cpp | 6 ++---- qqmlsortfilterproxymodel.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/qqmlsortfilterproxymodel.cpp b/qqmlsortfilterproxymodel.cpp index 29b51ea..abbff16 100644 --- a/qqmlsortfilterproxymodel.cpp +++ b/qqmlsortfilterproxymodel.cpp @@ -457,10 +457,8 @@ void QQmlSortFilterProxyModel::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles) { Q_UNUSED(roles); - bool proxyRoleChanged = - !m_proxyRoleNumbers.empty() && - std::any_of(m_proxyRoleNumbers.begin(), m_proxyRoleNumbers.end(), - [&roles](const auto &it) { return roles.contains(it); }); + bool proxyRoleChanged = !roles.empty() && !m_proxyRoleNumbers.empty() && + roles != m_proxyRoleNumbers; if (proxyRoleChanged) Q_EMIT dataChanged(topLeft, bottomRight, m_proxyRoleNumbers); } diff --git a/qqmlsortfilterproxymodel.h b/qqmlsortfilterproxymodel.h index 0697e15..9a6d807 100644 --- a/qqmlsortfilterproxymodel.h +++ b/qqmlsortfilterproxymodel.h @@ -138,7 +138,7 @@ private Q_SLOTS: void onProxyRoleRemoved(ProxyRole *proxyRole) override; void onProxyRolesCleared() override; - bool m_delayed; + bool m_delayed{false}; QString m_filterRoleName; QVariant m_filterValue; QString m_sortRoleName;