diff options
Diffstat (limited to 'src/corelib/itemmodels')
-rw-r--r-- | src/corelib/itemmodels/qabstractitemmodel.cpp | 61 | ||||
-rw-r--r-- | src/corelib/itemmodels/qabstractitemmodel.h | 11 | ||||
-rw-r--r-- | src/corelib/itemmodels/qabstractproxymodel.h | 6 | ||||
-rw-r--r-- | src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp | 2 | ||||
-rw-r--r-- | src/corelib/itemmodels/qidentityproxymodel.cpp | 2 | ||||
-rw-r--r-- | src/corelib/itemmodels/qitemselectionmodel.h | 5 | ||||
-rw-r--r-- | src/corelib/itemmodels/qsortfilterproxymodel.cpp | 351 | ||||
-rw-r--r-- | src/corelib/itemmodels/qsortfilterproxymodel.h | 8 | ||||
-rw-r--r-- | src/corelib/itemmodels/qtransposeproxymodel.cpp | 2 |
9 files changed, 163 insertions, 285 deletions
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index d88960ba0c..3bc3b546da 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -46,7 +46,9 @@ #include <qdebug.h> #include <qvector.h> #include <qregexp.h> -#include <qregularexpression.h> +#if QT_CONFIG(regularexpression) +# include <qregularexpression.h> +#endif #include <qstack.h> #include <qbitarray.h> #include <qdatetime.h> @@ -63,7 +65,7 @@ QPersistentModelIndexData *QPersistentModelIndexData::create(const QModelIndex & Q_ASSERT(index.isValid()); // we will _never_ insert an invalid index in the list QPersistentModelIndexData *d = nullptr; QAbstractItemModel *model = const_cast<QAbstractItemModel *>(index.model()); - QHash<QModelIndex, QPersistentModelIndexData *> &indexes = model->d_func()->persistent.indexes; + QMultiHash<QModelIndex, QPersistentModelIndexData *> &indexes = model->d_func()->persistent.indexes; const auto it = indexes.constFind(index); if (it != indexes.cend()) { d = (*it); @@ -665,8 +667,7 @@ void QAbstractItemModelPrivate::rowsAboutToBeInserted(const QModelIndex &parent, Q_UNUSED(last); QVector<QPersistentModelIndexData *> persistent_moved; if (first < q->rowCount(parent)) { - for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin(); - it != persistent.indexes.constEnd(); ++it) { + for (auto it = persistent.indexes.constBegin(); it != persistent.indexes.constEnd(); ++it) { QPersistentModelIndexData *data = *it; const QModelIndex &index = data->index; if (index.row() >= first && index.isValid() && index.parent() == parent) { @@ -702,14 +703,13 @@ void QAbstractItemModelPrivate::itemsAboutToBeMoved(const QModelIndex &srcParent QVector<QPersistentModelIndexData *> persistent_moved_in_source; QVector<QPersistentModelIndexData *> persistent_moved_in_destination; - QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it; - const QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator begin = persistent.indexes.constBegin(); - const QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator end = persistent.indexes.constEnd(); + const auto begin = persistent.indexes.constBegin(); + const auto end = persistent.indexes.constEnd(); const bool sameParent = (srcParent == destinationParent); const bool movingUp = (srcFirst > destinationChild); - for ( it = begin; it != end; ++it) { + for (auto it = begin; it != end; ++it) { QPersistentModelIndexData *data = *it; const QModelIndex &index = data->index; const QModelIndex &parent = index.parent(); @@ -814,8 +814,7 @@ void QAbstractItemModelPrivate::rowsAboutToBeRemoved(const QModelIndex &parent, QVector<QPersistentModelIndexData *> persistent_invalidated; // find the persistent indexes that are affected by the change, either by being in the removed subtree // or by being on the same level and below the removed rows - for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin(); - it != persistent.indexes.constEnd(); ++it) { + for (auto it = persistent.indexes.constBegin(); it != persistent.indexes.constEnd(); ++it) { QPersistentModelIndexData *data = *it; bool level_changed = false; QModelIndex current = data->index; @@ -858,7 +857,9 @@ void QAbstractItemModelPrivate::rowsRemoved(const QModelIndex &parent, for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_invalidated.constBegin(); it != persistent_invalidated.constEnd(); ++it) { QPersistentModelIndexData *data = *it; - persistent.indexes.erase(persistent.indexes.constFind(data->index)); + auto pit = persistent.indexes.constFind(data->index); + if (pit != persistent.indexes.cend()) + persistent.indexes.erase(pit); data->index = QModelIndex(); } } @@ -870,8 +871,7 @@ void QAbstractItemModelPrivate::columnsAboutToBeInserted(const QModelIndex &pare Q_UNUSED(last); QVector<QPersistentModelIndexData *> persistent_moved; if (first < q->columnCount(parent)) { - for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin(); - it != persistent.indexes.constEnd(); ++it) { + for (auto it = persistent.indexes.constBegin(); it != persistent.indexes.constEnd(); ++it) { QPersistentModelIndexData *data = *it; const QModelIndex &index = data->index; if (index.column() >= first && index.isValid() && index.parent() == parent) @@ -907,8 +907,7 @@ void QAbstractItemModelPrivate::columnsAboutToBeRemoved(const QModelIndex &paren QVector<QPersistentModelIndexData *> persistent_invalidated; // find the persistent indexes that are affected by the change, either by being in the removed subtree // or by being on the same level and to the right of the removed columns - for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin(); - it != persistent.indexes.constEnd(); ++it) { + for (auto it = persistent.indexes.constBegin(); it != persistent.indexes.constEnd(); ++it) { QPersistentModelIndexData *data = *it; bool level_changed = false; QModelIndex current = data->index; @@ -952,7 +951,9 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent, for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_invalidated.constBegin(); it != persistent_invalidated.constEnd(); ++it) { QPersistentModelIndexData *data = *it; - persistent.indexes.erase(persistent.indexes.constFind(data->index)); + auto index = persistent.indexes.constFind(data->index); + if (index != persistent.indexes.constEnd()) + persistent.indexes.erase(index); data->index = QModelIndex(); } } @@ -2362,7 +2363,9 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role, bool wrap = flags & Qt::MatchWrap; bool allHits = (hits == -1); QString text; // only convert to a string if it is needed +#if QT_CONFIG(regularexpression) QRegularExpression rx; // only create it if needed +#endif const int column = start.column(); QModelIndex p = parent(start); int from = start.row(); @@ -2380,6 +2383,7 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role, if (value == v) result.append(idx); } else { // QString or regular expression based matching +#if QT_CONFIG(regularexpression) if (matchType == Qt::MatchRegularExpression) { if (rx.pattern().isEmpty()) { if (value.userType() == QMetaType::QRegularExpression) { @@ -2395,25 +2399,23 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role, rx.setPattern(QRegularExpression::wildcardToRegularExpression(value.toString())); if (cs == Qt::CaseInsensitive) rx.setPatternOptions(QRegularExpression::CaseInsensitiveOption); - } else { + } else +#endif + { if (text.isEmpty()) // lazy conversion text = value.toString(); } QString t = v.toString(); switch (matchType) { -#if QT_DEPRECATED_SINCE(5, 15) - case Qt::MatchRegExp: - if (QRegExp(text, cs).exactMatch(t)) - result.append(idx); - break; -#endif +#if QT_CONFIG(regularexpression) case Qt::MatchRegularExpression: Q_FALLTHROUGH(); case Qt::MatchWildcard: if (t.contains(rx)) result.append(idx); break; +#endif case Qt::MatchStartsWith: if (t.startsWith(text, cs)) result.append(idx); @@ -3297,7 +3299,11 @@ void QAbstractItemModel::endResetModel() { Q_D(QAbstractItemModel); d->invalidatePersistentIndexes(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + resetInternalData(); +#else QMetaObject::invokeMethod(this, "resetInternalData"); +#endif emit modelReset(QPrivateSignal()); } @@ -3375,8 +3381,7 @@ QModelIndexList QAbstractItemModel::persistentIndexList() const Q_D(const QAbstractItemModel); QModelIndexList result; result.reserve(d->persistent.indexes.count()); - for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = d->persistent.indexes.constBegin(); - it != d->persistent.indexes.constEnd(); ++it) { + for (auto it = d->persistent.indexes.constBegin(); it != d->persistent.indexes.constEnd(); ++it) { QPersistentModelIndexData *data = *it; result.append(data->index); } @@ -3973,7 +3978,7 @@ bool QAbstractListModel::dropMimeData(const QMimeData *data, Qt::DropAction acti */ /*! - \fn uint qHash(const QPersistentModelIndex &index, uint seed = 0) + \fn size_t qHash(const QPersistentModelIndex &index, size_t seed = 0) \since 5.0 \relates QPersistentModelIndex @@ -3994,8 +3999,8 @@ bool QAbstractListModel::dropMimeData(const QMimeData *data, Qt::DropAction acti */ void QAbstractItemModelPrivate::Persistent::insertMultiAtEnd(const QModelIndex& key, QPersistentModelIndexData *data) { - QHash<QModelIndex,QPersistentModelIndexData *>::iterator newIt = indexes.insert(key, data); - QHash<QModelIndex,QPersistentModelIndexData *>::iterator it = newIt; + auto newIt = indexes.insert(key, data); + auto it = newIt; ++it; while (it != indexes.end() && it.key() == key) { qSwap(*newIt,*it); diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h index 43649cf79b..86ff361ccb 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -103,7 +103,7 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QModelIndex &); class QPersistentModelIndexData; // qHash is a friend, but we can't use default arguments for friends (ยง8.3.6.4) -uint qHash(const QPersistentModelIndex &index, uint seed = 0) noexcept; +size_t qHash(const QPersistentModelIndex &index, size_t seed = 0) noexcept; class Q_CORE_EXPORT QPersistentModelIndex { @@ -141,14 +141,14 @@ public: bool isValid() const; private: QPersistentModelIndexData *d; - friend uint qHash(const QPersistentModelIndex &, uint seed) noexcept; + friend size_t qHash(const QPersistentModelIndex &, size_t seed) noexcept; #ifndef QT_NO_DEBUG_STREAM friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QPersistentModelIndex &); #endif }; Q_DECLARE_SHARED(QPersistentModelIndex) -inline uint qHash(const QPersistentModelIndex &index, uint seed) noexcept +inline size_t qHash(const QPersistentModelIndex &index, size_t seed) noexcept { return qHash(index.d, seed); } @@ -156,7 +156,6 @@ inline uint qHash(const QPersistentModelIndex &index, uint seed) noexcept Q_CORE_EXPORT QDebug operator<<(QDebug, const QPersistentModelIndex &); #endif -template<typename T> class QList; typedef QList<QModelIndex> QModelIndexList; class QMimeData; @@ -462,8 +461,8 @@ inline QVariant QModelIndex::data(int arole) const inline Qt::ItemFlags QModelIndex::flags() const { return m ? m->flags(*this) : Qt::ItemFlags(); } -inline uint qHash(const QModelIndex &index) noexcept -{ return uint((uint(index.row()) << 4) + index.column() + index.internalId()); } +inline size_t qHash(const QModelIndex &index, size_t seed) noexcept +{ return size_t((size_t(index.row()) << 4) + size_t(index.column()) + index.internalId()) ^ seed; } QT_END_NAMESPACE diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h index c9a73b6a31..f6f6e45c1a 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.h +++ b/src/corelib/itemmodels/qabstractproxymodel.h @@ -103,7 +103,11 @@ Q_SIGNALS: void sourceModelChanged(QPrivateSignal); protected Q_SLOTS: - void resetInternalData(); + void resetInternalData() +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + override +#endif + ; protected: QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent); diff --git a/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp index a2597faa93..0e29714677 100644 --- a/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp +++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp @@ -642,7 +642,7 @@ void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutAboutToBeChanged(co layoutChangePersistentIndexes.reserve(persistentIndexList.size()); layoutChangeProxyIndexes.reserve(persistentIndexList.size()); - for (const QPersistentModelIndex &proxyPersistentIndex : persistentIndexList) { + for (const QModelIndex &proxyPersistentIndex : persistentIndexList) { layoutChangeProxyIndexes.append(proxyPersistentIndex); Q_ASSERT(proxyPersistentIndex.isValid()); const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex); diff --git a/src/corelib/itemmodels/qidentityproxymodel.cpp b/src/corelib/itemmodels/qidentityproxymodel.cpp index f5684c6eda..8210e27f8a 100644 --- a/src/corelib/itemmodels/qidentityproxymodel.cpp +++ b/src/corelib/itemmodels/qidentityproxymodel.cpp @@ -532,7 +532,7 @@ void QIdentityProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<QPe emit q->layoutAboutToBeChanged(parents, hint); const auto proxyPersistentIndexes = q->persistentIndexList(); - for (const QPersistentModelIndex &proxyPersistentIndex : proxyPersistentIndexes) { + for (const QModelIndex &proxyPersistentIndex : proxyPersistentIndexes) { proxyIndexes << proxyPersistentIndex; Q_ASSERT(proxyPersistentIndex.isValid()); const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex); diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h index 5820695592..a1badc7693 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.h +++ b/src/corelib/itemmodels/qitemselectionmodel.h @@ -223,9 +223,6 @@ private: Q_DECLARE_OPERATORS_FOR_FLAGS(QItemSelectionModel::SelectionFlags) -// dummy implentation of qHash() necessary for instantiating QList<QItemSelectionRange>::toSet() with MSVC -inline uint qHash(const QItemSelectionRange &) { return 0; } - #ifdef Q_CC_MSVC /* @@ -241,7 +238,7 @@ inline uint qHash(const QItemSelectionRange &) { return 0; } # define Q_TEMPLATE_EXTERN extern # endif # endif -Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QList<QItemSelectionRange>; +Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QItemSelectionRange>; #endif // Q_CC_MSVC class Q_CORE_EXPORT QItemSelection : public QList<QItemSelectionRange> diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index 4f5593e0a0..79a9875073 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -142,145 +142,24 @@ private: int end; }; -class RegularExpressionData { - -private: - enum class ExpressionType { - RegExp, -#if QT_CONFIG(regularexpression) - RegularExpression -#endif - }; - -public: - RegularExpressionData() : - m_type(ExpressionType::RegExp) - {} - -#if QT_CONFIG(regularexpression) - QRegularExpression regularExpression() const - { - if (m_type == ExpressionType::RegularExpression) - return m_regularExpression; - return QRegularExpression(); - } - - void setRegularExpression(const QRegularExpression &rx) - { - m_type = ExpressionType::RegularExpression; - m_regularExpression = rx; - m_regExp = QRegExp(); - } -#endif - - QRegExp regExp() const - { - if (m_type == ExpressionType::RegExp) - return m_regExp; - return QRegExp(); - } - - void setRegExp(const QRegExp &rx) - { - m_type = ExpressionType::RegExp; - m_regExp = rx; -#if QT_CONFIG(regularexpression) - m_regularExpression = QRegularExpression(); -#endif - - } - - bool isEmpty() const - { - bool result = true; - switch (m_type) { - case ExpressionType::RegExp: - result = m_regExp.isEmpty(); - break; -#if QT_CONFIG(regularexpression) - case ExpressionType::RegularExpression: - result = m_regularExpression.pattern().isEmpty(); - break; -#endif - } - return result; - } - - Qt::CaseSensitivity caseSensitivity() const - { - Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive; - switch (m_type) { - case ExpressionType::RegExp: - sensitivity = m_regExp.caseSensitivity(); - break; -#if QT_CONFIG(regularexpression) - case ExpressionType::RegularExpression: - { - QRegularExpression::PatternOptions options = m_regularExpression.patternOptions(); - if (!(options & QRegularExpression::CaseInsensitiveOption)) - sensitivity = Qt::CaseSensitive; - } - break; -#endif - } - return sensitivity; - } - - void setCaseSensitivity(Qt::CaseSensitivity cs) - { - switch (m_type) { - case ExpressionType::RegExp: - m_regExp.setCaseSensitivity(cs); - break; -#if QT_CONFIG(regularexpression) - case ExpressionType::RegularExpression: - { - QRegularExpression::PatternOptions options = m_regularExpression.patternOptions(); - options.setFlag(QRegularExpression::CaseInsensitiveOption, cs == Qt::CaseSensitive); - m_regularExpression.setPatternOptions(options); - } - break; -#endif - } - } - - bool hasMatch(const QString &str) const - { - bool result = false; - switch (m_type) { - case ExpressionType::RegExp: - result = str.contains(m_regExp); - break; -#if QT_CONFIG(regularexpression) - case ExpressionType::RegularExpression: - result = str.contains(m_regularExpression); - break; -#endif - } - return result; - } - -private: - ExpressionType m_type; - QRegExp m_regExp; -#if QT_CONFIG(regularexpression) - QRegularExpression m_regularExpression; -#endif -}; - - class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate { Q_DECLARE_PUBLIC(QSortFilterProxyModel) public: + enum class Direction { + Rows = 1, + Columns = 2, + All = Rows | Columns + }; + struct Mapping { QVector<int> source_rows; QVector<int> source_columns; QVector<int> proxy_rows; QVector<int> proxy_columns; QVector<QModelIndex> mapped_children; - QHash<QModelIndex, Mapping *>::const_iterator map_iter; + QModelIndex source_parent; }; mutable QHash<QModelIndex, Mapping*> source_index_mapping; @@ -294,7 +173,7 @@ public: int filter_column; int filter_role; - RegularExpressionData filter_data; + QRegularExpression filter_data; QModelIndex last_top_source; bool filter_recursive; @@ -321,7 +200,7 @@ public: const void *p = proxy_index.internalPointer(); Q_ASSERT(p); QHash<QModelIndex, Mapping *>::const_iterator it = - static_cast<const Mapping*>(p)->map_iter; + source_index_mapping.constFind(static_cast<const Mapping*>(p)->source_parent); Q_ASSERT(it != source_index_mapping.constEnd()); Q_ASSERT(it.value()); return it; @@ -397,8 +276,8 @@ public: QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, int proxy_start, int proxy_end, const QModelIndex &proxy_parent, Qt::Orientation orient, bool emit_signal = true); - void build_source_to_proxy_mapping( - const QVector<int> &proxy_to_source, QVector<int> &source_to_proxy) const; + static inline void build_source_to_proxy_mapping( + const QVector<int> &proxy_to_source, QVector<int> &source_to_proxy, int start = 0); void source_items_inserted(const QModelIndex &source_parent, int start, int end, Qt::Orientation orient); void source_items_about_to_be_removed(const QModelIndex &source_parent, @@ -413,7 +292,7 @@ public: void update_persistent_indexes(const QModelIndexPairList &source_indexes); void filter_about_to_be_changed(const QModelIndex &source_parent = QModelIndex()); - void filter_changed(const QModelIndex &source_parent = QModelIndex()); + void filter_changed(Direction dir, const QModelIndex &source_parent = QModelIndex()); QSet<int> handle_filter_changed( QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, const QModelIndex &source_parent, Qt::Orientation orient); @@ -431,6 +310,11 @@ public: typedef QHash<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap; +static bool operator&(QSortFilterProxyModelPrivate::Direction a, QSortFilterProxyModelPrivate::Direction b) +{ + return int(a) & int(b); +} + void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed() { QAbstractProxyModelPrivate::_q_sourceModelDestroyed(); @@ -517,8 +401,7 @@ IndexMap::const_iterator QSortFilterProxyModelPrivate::create_mapping( m->proxy_columns.resize(source_cols); build_source_to_proxy_mapping(m->source_columns, m->proxy_columns); - it = IndexMap::const_iterator(source_index_mapping.insert(source_parent, m)); - m->map_iter = it; + m->source_parent = source_parent; if (source_parent.isValid()) { QModelIndex source_grand_parent = source_parent.parent(); @@ -527,6 +410,7 @@ IndexMap::const_iterator QSortFilterProxyModelPrivate::create_mapping( it2.value()->mapped_children.append(source_parent); } + it = IndexMap::const_iterator(source_index_mapping.insert(source_parent, m)); Q_ASSERT(it != source_index_mapping.constEnd()); Q_ASSERT(it.value()); @@ -787,9 +671,11 @@ void QSortFilterProxyModelPrivate::remove_proxy_interval( } // Remove items from proxy-to-source mapping + for (int i = proxy_start; i <= proxy_end; ++i) + source_to_proxy[proxy_to_source.at(i)] = -1; proxy_to_source.remove(proxy_start, proxy_end - proxy_start + 1); - build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); + build_source_to_proxy_mapping(proxy_to_source, source_to_proxy, proxy_start); if (emit_signal) { if (orient == Qt::Vertical) @@ -915,7 +801,7 @@ void QSortFilterProxyModelPrivate::insert_source_items( for (int i = 0; i < source_items.size(); ++i) proxy_to_source.insert(proxy_start + i, source_items.at(i)); - build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); + build_source_to_proxy_mapping(proxy_to_source, source_to_proxy, proxy_start); if (emit_signal) { if (orient == Qt::Vertical) @@ -1169,7 +1055,8 @@ void QSortFilterProxyModelPrivate::updateChildrenMapping(const QModelIndex &sour // reinsert moved, mapped indexes QVector<QPair<QModelIndex, Mapping*> >::iterator it = moved_source_index_mappings.begin(); for (; it != moved_source_index_mappings.end(); ++it) { - (*it).second->map_iter = QHash<QModelIndex, Mapping *>::const_iterator(source_index_mapping.insert((*it).first, (*it).second)); + it->second->source_parent = it->first; + source_index_mapping.insert(it->first, it->second); } } @@ -1196,11 +1083,12 @@ void QSortFilterProxyModelPrivate::proxy_item_range( \internal */ void QSortFilterProxyModelPrivate::build_source_to_proxy_mapping( - const QVector<int> &proxy_to_source, QVector<int> &source_to_proxy) const + const QVector<int> &proxy_to_source, QVector<int> &source_to_proxy, int start) { - source_to_proxy.fill(-1); - int proxy_count = proxy_to_source.size(); - for (int i = 0; i < proxy_count; ++i) + if (start == 0) + source_to_proxy.fill(-1); + const int proxy_count = proxy_to_source.size(); + for (int i = start; i < proxy_count; ++i) source_to_proxy[proxy_to_source.at(i)] = i; } @@ -1256,7 +1144,7 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes( */ void QSortFilterProxyModelPrivate::filter_about_to_be_changed(const QModelIndex &source_parent) { - if (!filter_data.isEmpty() && + if (!filter_data.pattern().isEmpty() && source_index_mapping.constFind(source_parent) == source_index_mapping.constEnd()) create_mapping(source_parent); } @@ -1268,14 +1156,14 @@ void QSortFilterProxyModelPrivate::filter_about_to_be_changed(const QModelIndex Updates the proxy model (adds/removes rows) based on the new filter. */ -void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_parent) +void QSortFilterProxyModelPrivate::filter_changed(Direction dir, const QModelIndex &source_parent) { IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); if (it == source_index_mapping.constEnd()) return; Mapping *m = it.value(); - QSet<int> rows_removed = handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical); - QSet<int> columns_removed = handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal); + const QSet<int> rows_removed = (dir & Direction::Rows) ? handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical) : QSet<int>(); + const QSet<int> columns_removed = (dir & Direction::Columns) ? handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal) : QSet<int>(); // We need to iterate over a copy of m->mapped_children because otherwise it may be changed by other code, invalidating // the iterator it2. @@ -1289,7 +1177,7 @@ void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_pare indexesToRemove.push_back(i); remove_from_mapping(source_child_index); } else { - filter_changed(source_child_index); + filter_changed(dir, source_child_index); } } QVector<int>::const_iterator removeIt = indexesToRemove.constEnd(); @@ -1919,9 +1807,9 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved( \section1 Filtering In addition to sorting, QSortFilterProxyModel can be used to hide items - that do not match a certain filter. The filter is specified using a QRegExp + that do not match a certain filter. The filter is specified using a QRegularExpression object and is applied to the filterRole() (Qt::DisplayRole by default) of - each item, for a given column. The QRegExp object can be used to match a + each item, for a given column. The QRegularExpression object can be used to match a regular expression, a wildcard pattern, or a fixed string. For example: \snippet qsortfilterproxymodel-details/main.cpp 5 @@ -1970,21 +1858,6 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved( \note Some general guidelines for subclassing models are available in the \l{Model Subclassing Reference}. - \note With Qt 5, regular expression support has been improved through the - QRegularExpression class. QSortFilterProxyModel dating back prior to that - class creation, it originally supported only QRegExp. Since Qt 5.12, - QRegularExpression APIs have been added. Therefore, QRegExp APIs should be - considered deprecated and the QRegularExpression version should be used in - place. - - \warning Don't mix calls to the getters and setters of different regexp types - as this will lead to unexpected results. For maximum compatibility, the original - implementation has been kept. Therefore, if, for example, a call to - setFilterRegularExpression is made followed by another one to - setFilterFixedString, the first call will setup a QRegularExpression object - to use as filter while the second will setup a QRegExp in FixedString mode. - However, this is an implementation detail that might change in the future. - \sa QAbstractProxyModel, QAbstractItemModel, {Model/View Programming}, {Basic Sort/Filter Model Example}, {Custom Sort/Filter Model Example}, QIdentityProxyModel */ @@ -2580,33 +2453,6 @@ Qt::SortOrder QSortFilterProxyModel::sortOrder() const return d->sort_order; } -/*! - \property QSortFilterProxyModel::filterRegExp - \brief the QRegExp used to filter the contents of the source model - - Setting this property overwrites the current - \l{QSortFilterProxyModel::filterCaseSensitivity}{filterCaseSensitivity}. - By default, the QRegExp is an empty string matching all contents. - - If no QRegExp or an empty string is set, everything in the source model - will be accepted. - - \sa filterCaseSensitivity, setFilterWildcard(), setFilterFixedString() -*/ -QRegExp QSortFilterProxyModel::filterRegExp() const -{ - Q_D(const QSortFilterProxyModel); - return d->filter_data.regExp(); -} - -void QSortFilterProxyModel::setFilterRegExp(const QRegExp ®Exp) -{ - Q_D(QSortFilterProxyModel); - d->filter_about_to_be_changed(); - d->filter_data.setRegExp(regExp); - d->filter_changed(); -} - #if QT_CONFIG(regularexpression) /*! \since 5.12 @@ -2625,15 +2471,15 @@ void QSortFilterProxyModel::setFilterRegExp(const QRegExp ®Exp) QRegularExpression QSortFilterProxyModel::filterRegularExpression() const { Q_D(const QSortFilterProxyModel); - return d->filter_data.regularExpression(); + return d->filter_data; } void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression ®ularExpression) { Q_D(QSortFilterProxyModel); d->filter_about_to_be_changed(); - d->filter_data.setRegularExpression(regularExpression); - d->filter_changed(); + d->filter_data = regularExpression; + d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); } #endif @@ -2656,18 +2502,18 @@ void QSortFilterProxyModel::setFilterKeyColumn(int column) Q_D(QSortFilterProxyModel); d->filter_about_to_be_changed(); d->filter_column = column; - d->filter_changed(); + d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); } /*! \property QSortFilterProxyModel::filterCaseSensitivity - \brief the case sensitivity of the QRegExp pattern used to filter the + \brief the case sensitivity of the QRegularExpression pattern used to filter the contents of the source model. By default, the filter is case sensitive. - \sa filterRegExp, sortCaseSensitivity + \sa filterRegularExpression, sortCaseSensitivity */ /*! @@ -2679,17 +2525,21 @@ void QSortFilterProxyModel::setFilterKeyColumn(int column) Qt::CaseSensitivity QSortFilterProxyModel::filterCaseSensitivity() const { Q_D(const QSortFilterProxyModel); - return d->filter_data.caseSensitivity(); + return d->filter_data.patternOptions() & QRegularExpression::CaseInsensitiveOption ? + Qt::CaseInsensitive : Qt::CaseSensitive; } void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs) { Q_D(QSortFilterProxyModel); - if (cs == d->filter_data.caseSensitivity()) + QRegularExpression::PatternOptions o = QRegularExpression::NoPatternOption; + if (cs == Qt::CaseInsensitive) + o = QRegularExpression::CaseInsensitiveOption; + if (o == d->filter_data.patternOptions()) return; d->filter_about_to_be_changed(); - d->filter_data.setCaseSensitivity(cs); - d->filter_changed(); + d->filter_data.setPatternOptions(o); + d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); emit filterCaseSensitivityChanged(cs); } @@ -2759,24 +2609,6 @@ void QSortFilterProxyModel::setSortLocaleAware(bool on) emit sortLocaleAwareChanged(on); } -/*! - \overload - - Sets the regular expression used to filter the contents - of the source model to \a pattern. - - \sa setFilterCaseSensitivity(), setFilterWildcard(), setFilterFixedString(), filterRegExp() -*/ -void QSortFilterProxyModel::setFilterRegExp(const QString &pattern) -{ - Q_D(QSortFilterProxyModel); - d->filter_about_to_be_changed(); - QRegExp rx(pattern); - rx.setCaseSensitivity(d->filter_data.caseSensitivity()); - d->filter_data.setRegExp(rx); - d->filter_changed(); -} - #if QT_CONFIG(regularexpression) /*! \since 5.12 @@ -2794,8 +2626,8 @@ void QSortFilterProxyModel::setFilterRegularExpression(const QString &pattern) Q_D(QSortFilterProxyModel); d->filter_about_to_be_changed(); QRegularExpression rx(pattern); - d->filter_data.setRegularExpression(rx); - d->filter_changed(); + d->filter_data.setPattern(pattern); + d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); } #endif @@ -2803,30 +2635,29 @@ void QSortFilterProxyModel::setFilterRegularExpression(const QString &pattern) Sets the wildcard expression used to filter the contents of the source model to the given \a pattern. - \sa setFilterCaseSensitivity(), setFilterRegExp(), setFilterFixedString(), filterRegExp() + \sa setFilterCaseSensitivity(), setFilterRegularExpression(), setFilterFixedString(), filterRegularExpression() */ void QSortFilterProxyModel::setFilterWildcard(const QString &pattern) { Q_D(QSortFilterProxyModel); d->filter_about_to_be_changed(); - QRegExp rx(pattern, d->filter_data.caseSensitivity(), QRegExp::Wildcard); - d->filter_data.setRegExp(rx); - d->filter_changed(); + QString p = QRegularExpression::wildcardToRegularExpression(pattern, QRegularExpression::UnanchoredWildcardConversion); + d->filter_data.setPattern(p); + d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); } /*! Sets the fixed string used to filter the contents of the source model to the given \a pattern. - \sa setFilterCaseSensitivity(), setFilterRegExp(), setFilterWildcard(), filterRegExp() + \sa setFilterCaseSensitivity(), setFilterRegularExpression(), setFilterWildcard(), filterRegularExpression() */ void QSortFilterProxyModel::setFilterFixedString(const QString &pattern) { Q_D(QSortFilterProxyModel); d->filter_about_to_be_changed(); - QRegExp rx(pattern, d->filter_data.caseSensitivity(), QRegExp::FixedString); - d->filter_data.setRegExp(rx); - d->filter_changed(); + d->filter_data.setPattern(QRegularExpression::escape(pattern)); + d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); } /*! @@ -2920,7 +2751,7 @@ void QSortFilterProxyModel::setFilterRole(int role) return; d->filter_about_to_be_changed(); d->filter_role = role; - d->filter_changed(); + d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); emit filterRoleChanged(role); } @@ -2954,7 +2785,7 @@ void QSortFilterProxyModel::setRecursiveFilteringEnabled(bool recursive) return; d->filter_about_to_be_changed(); d->filter_recursive = recursive; - d->filter_changed(); + d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); emit recursiveFilteringEnabledChanged(recursive); } @@ -3005,11 +2836,57 @@ void QSortFilterProxyModel::filterChanged() (e.g. filterAcceptsRow()), and your filter parameters have changed. \sa invalidate() + \sa invalidateColumnsFilter() + \sa invalidateRowsFilter() */ void QSortFilterProxyModel::invalidateFilter() { Q_D(QSortFilterProxyModel); - d->filter_changed(); + d->filter_changed(QSortFilterProxyModelPrivate::Direction::All); +} + +/*! + \since 6.0 + + Invalidates the current filtering for the columns. + + This function should be called if you are implementing custom filtering + (by filterAcceptsColumn()), and your filter parameters have changed. + This differs from invalidateFilter() in that it will not invoke + filterAcceptsRow(), but only filterAcceptsColumn(). You can use this + instead of invalidateFilter() if you want to hide or show a column where + the rows don't change. + + \sa invalidate() + \sa invalidateFilter() + \sa invalidateRowsFilter() +*/ +void QSortFilterProxyModel::invalidateColumnsFilter() +{ + Q_D(QSortFilterProxyModel); + d->filter_changed(QSortFilterProxyModelPrivate::Direction::Columns); +} + +/*! + \since 6.0 + + Invalidates the current filtering for the rows. + + This function should be called if you are implementing custom filtering + (by filterAcceptsRow()), and your filter parameters have changed. + This differs from invalidateFilter() in that it will not invoke + filterAcceptsColumn(), but only filterAcceptsRow(). You can use this + instead of invalidateFilter() if you want to hide or show a row where + the columns don't change. + + \sa invalidate() + \sa invalidateFilter() + \sa invalidateColumnsFilter() +*/ +void QSortFilterProxyModel::invalidateRowsFilter() +{ + Q_D(QSortFilterProxyModel); + d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows); } /*! @@ -3069,20 +2946,20 @@ bool QSortFilterProxyModel::lessThan(const QModelIndex &source_left, const QMode should be accepted or not. This can be changed by setting the \l{QSortFilterProxyModel::filterRole}{filterRole} property. - \sa filterAcceptsColumn(), setFilterFixedString(), setFilterRegExp(), setFilterWildcard() + \sa filterAcceptsColumn(), setFilterFixedString(), setFilterRegularExpression(), setFilterWildcard() */ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { Q_D(const QSortFilterProxyModel); - if (d->filter_data.isEmpty()) + if (d->filter_data.pattern().isEmpty()) return true; if (d->filter_column == -1) { int column_count = d->model->columnCount(source_parent); 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 (d->filter_data.hasMatch(key)) + if (d->filter_data.match(key).hasMatch()) return true; } return false; @@ -3091,7 +2968,7 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex & if (!source_index.isValid()) // the column may not exist return true; QString key = d->model->data(source_index, d->filter_role).toString(); - return d->filter_data.hasMatch(key); + return d->filter_data.match(key).hasMatch(); } /*! @@ -3101,7 +2978,7 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex & \note The default implementation always returns \c true. You must reimplement this method to get the described behavior. - \sa filterAcceptsRow(), setFilterFixedString(), setFilterRegExp(), setFilterWildcard() + \sa filterAcceptsRow(), setFilterFixedString(), setFilterRegularExpression(), setFilterWildcard() */ bool QSortFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const { diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h index 91253dd601..b7d4e69cb9 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.h +++ b/src/corelib/itemmodels/qsortfilterproxymodel.h @@ -41,7 +41,6 @@ #define QSORTFILTERPROXYMODEL_H #include <QtCore/qabstractproxymodel.h> -#include <QtCore/qregexp.h> #if QT_CONFIG(regularexpression) # include <QtCore/qregularexpression.h> @@ -62,7 +61,6 @@ class Q_CORE_EXPORT QSortFilterProxyModel : public QAbstractProxyModel friend class QSortFilterProxyModelGreaterThan; Q_OBJECT - Q_PROPERTY(QRegExp filterRegExp READ filterRegExp WRITE setFilterRegExp) #if QT_CONFIG(regularexpression) Q_PROPERTY(QRegularExpression filterRegularExpression READ filterRegularExpression WRITE setFilterRegularExpression) #endif @@ -87,8 +85,6 @@ public: QItemSelection mapSelectionToSource(const QItemSelection &proxySelection) const override; QItemSelection mapSelectionFromSource(const QItemSelection &sourceSelection) const override; - QRegExp filterRegExp() const; - #if QT_CONFIG(regularexpression) QRegularExpression filterRegularExpression() const; #endif @@ -121,8 +117,6 @@ public: void setRecursiveFilteringEnabled(bool recursive); public Q_SLOTS: - void setFilterRegExp(const QString &pattern); - void setFilterRegExp(const QRegExp ®Exp); #if QT_CONFIG(regularexpression) void setFilterRegularExpression(const QString &pattern); void setFilterRegularExpression(const QRegularExpression ®ularExpression); @@ -143,6 +137,8 @@ protected: QT_DEPRECATED_X("Use QSortFilterProxyModel::invalidateFilter") void filterChanged(); #endif void invalidateFilter(); + void invalidateRowsFilter(); + void invalidateColumnsFilter(); public: using QObject::parent; diff --git a/src/corelib/itemmodels/qtransposeproxymodel.cpp b/src/corelib/itemmodels/qtransposeproxymodel.cpp index 4853f90632..207faa6151 100644 --- a/src/corelib/itemmodels/qtransposeproxymodel.cpp +++ b/src/corelib/itemmodels/qtransposeproxymodel.cpp @@ -92,7 +92,7 @@ void QTransposeProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersiste layoutChangePersistentIndexes.clear(); layoutChangeProxyIndexes.reserve(proxyPersistentIndexes.size()); layoutChangePersistentIndexes.reserve(proxyPersistentIndexes.size()); - for (const QPersistentModelIndex &proxyPersistentIndex : proxyPersistentIndexes) { + for (const QModelIndex &proxyPersistentIndex : proxyPersistentIndexes) { layoutChangeProxyIndexes << proxyPersistentIndex; Q_ASSERT(proxyPersistentIndex.isValid()); const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex); |