From 3bd0fd8f97e7a33a874929a383a42e6c710bfff3 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 17 Dec 2016 06:20:06 +0000 Subject: QSFPM: Fix handling of source model layout change In sourceLayoutAboutToBeChanged the source model update is ignored if the affected parents are filtered out anyway. The same logic is attempted in the sourceLayoutChanged slot, but there the early-return logic is applied too late - the mapping is cleared before performing the early-return. Because pointers into the mapping are used in the internalPointer of QModelIndexes in this class, persistent indexes used later will segfault when attempting to dereference it. Additionally, if a parent becomes invalid as a result of the layoutChange, it would be filtered out by the condition in the loop, resulting in a different result in the comparison of emptiness of the parents container. Fix that by persisting the parent's container, and performing the test for early-return before clearing the mapping. Task-number: QTBUG-47711 Task-number: QTBUG-32981 Change-Id: If45e8a1c97d39454160f52041bc9ae7e337dce97 Reviewed-by: David Faure --- src/corelib/itemmodels/qsortfilterproxymodel.cpp | 31 +++++++++--------------- 1 file changed, 11 insertions(+), 20 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index b0ddfa879d..333152138e 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -171,6 +171,7 @@ public: QRowsRemoval itemsBeingRemoved; QModelIndexPairList saved_persistent_indexes; + QList saved_layoutChange_parents; QHash::const_iterator create_mapping( const QModelIndex &source_parent) const; @@ -1331,23 +1332,23 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList parents; + saved_layoutChange_parents.clear(); for (const QPersistentModelIndex &parent : sourceParents) { if (!parent.isValid()) { - parents << QPersistentModelIndex(); + saved_layoutChange_parents << QPersistentModelIndex(); continue; } const QModelIndex mappedParent = q->mapFromSource(parent); // Might be filtered out. if (mappedParent.isValid()) - parents << mappedParent; + saved_layoutChange_parents << mappedParent; } // All parents filtered out. - if (!sourceParents.isEmpty() && parents.isEmpty()) + if (!sourceParents.isEmpty() && saved_layoutChange_parents.isEmpty()) return; - emit q->layoutAboutToBeChanged(parents); + emit q->layoutAboutToBeChanged(saved_layoutChange_parents); if (persistent.indexes.isEmpty()) return; @@ -1359,6 +1360,9 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(const QList parents; - for (const QPersistentModelIndex &parent : sourceParents) { - if (!parent.isValid()) { - parents << QPersistentModelIndex(); - continue; - } - const QModelIndex mappedParent = q->mapFromSource(parent); - if (mappedParent.isValid()) - parents << mappedParent; - } - - if (!sourceParents.isEmpty() && parents.isEmpty()) - return; - - emit q->layoutChanged(parents); + emit q->layoutChanged(saved_layoutChange_parents); + saved_layoutChange_parents.clear(); } void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted( -- cgit v1.2.3