From f328a68d898ebe74897132e3dae1ce75de496d3b Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 16 Apr 2009 19:56:00 +0200 Subject: QSortFilterProxyModel: remove the mapping of the child that are filtered away when the filter change Task-Number: relates to 251296 Reviewed-by: Marius Bugge Monsen --- src/gui/itemviews/qsortfilterproxymodel.cpp | 51 +++++++++++++++------- .../tst_qsortfilterproxymodel.cpp | 10 +++++ 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index 91431c4..fee19c9 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -56,6 +56,15 @@ QT_BEGIN_NAMESPACE typedef QList > QModelIndexPairList; +static inline QSet qVectorToSet(const QVector &vector) +{ + QSet set; + set.reserve(vector.size()); + for(int i=0; i < vector.size(); ++i) + set << vector.at(i); + return set; +} + class QSortFilterProxyModelLessThan { public: @@ -223,8 +232,8 @@ public: QModelIndexPairList store_persistent_indexes(); void update_persistent_indexes(const QModelIndexPairList &source_indexes); - void filter_changed(); - void handle_filter_changed( + void filter_changed(const QModelIndex &source_parent = QModelIndex()); + QSet handle_filter_changed( QVector &source_to_proxy, QVector &proxy_to_source, const QModelIndex &source_parent, Qt::Orientation orient); @@ -928,27 +937,39 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes( q->changePersistentIndexList(from, to); } + /*! \internal Updates the proxy model (adds/removes rows) based on the new filter. */ -void QSortFilterProxyModelPrivate::filter_changed() +void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_parent) { - QMap::const_iterator it; - for (it = source_index_mapping.constBegin(); it != source_index_mapping.constEnd(); ++it) { - QModelIndex source_parent = it.key(); - Mapping *m = it.value(); - handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical); - handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal); + IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); + if (it == source_index_mapping.constEnd()) + return; + Mapping *m = it.value(); + QSet rows_removed = handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical); + QSet columns_removed = handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal); + QVector::iterator it2 = m->mapped_children.end(); + while (it2 != m->mapped_children.begin()) { + --it2; + const QModelIndex source_child_index = *it2; + if (rows_removed.contains(source_child_index.row()) || columns_removed.contains(source_child_index.column())) { + it2 = m->mapped_children.erase(it2); + remove_from_mapping(source_child_index); + } else { + filter_changed(source_child_index); + } } } /*! \internal + returns the removed items indexes */ -void QSortFilterProxyModelPrivate::handle_filter_changed( +QSet QSortFilterProxyModelPrivate::handle_filter_changed( QVector &source_to_proxy, QVector &proxy_to_source, const QModelIndex &source_parent, Qt::Orientation orient) { @@ -985,6 +1006,7 @@ void QSortFilterProxyModelPrivate::handle_filter_changed( insert_source_items(source_to_proxy, proxy_to_source, source_items_insert, source_parent, orient); } + return qVectorToSet(source_items_remove); } void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &source_top_left, @@ -1035,15 +1057,14 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc if (!source_rows_remove.isEmpty()) { remove_source_items(m->proxy_rows, m->source_rows, source_rows_remove, source_parent, Qt::Vertical); - QSet source_rows_remove_set = source_rows_remove.toList().toSet(); - QVector::iterator it = m->mapped_children.begin(); - while (it != m->mapped_children.end()) { + QSet source_rows_remove_set = qVectorToSet(source_rows_remove); + QVector::iterator it = m->mapped_children.end(); + while (it != m->mapped_children.begin()) { + --it; const QModelIndex source_child_index = *it; if (source_rows_remove_set.contains(source_child_index.row())) { it = m->mapped_children.erase(it); remove_from_mapping(source_child_index); - } else { - ++it; } } } diff --git a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index 18aa5fc..ea73a5e 100644 --- a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp @@ -2715,6 +2715,16 @@ void tst_QSortFilterProxyModel::task251296_hiddenChildren() QCOMPARE(proxy.rowCount(indexA) , 1); QModelIndex indexC = proxy.index(0, 0, indexA); QCOMPARE(proxy.data(indexC).toString(), QString::fromLatin1("C VISIBLE")); + + proxy.setFilterRegExp("C"); + QCOMPARE(proxy.rowCount(QModelIndex()), 0); + itemC->setText("invisible"); + itemA->setText("AC"); + + QCOMPARE(proxy.rowCount(QModelIndex()), 1); + indexA = proxy.index(0,0); + QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("AC")); + QCOMPARE(proxy.rowCount(indexA) , 0); } -- cgit v0.12