diff options
author | Stephen Kelly <steveire@gmail.com> | 2016-12-17 06:20:06 +0000 |
---|---|---|
committer | Stephen Kelly <steveire@gmail.com> | 2016-12-21 01:37:31 +0000 |
commit | 3bd0fd8f97e7a33a874929a383a42e6c710bfff3 (patch) | |
tree | 59c22bb46eb3ee8e6b60232d34a22af0e65589f9 /src/corelib/itemmodels/qsortfilterproxymodel.cpp | |
parent | 1274a7e419c9f25d6dcd01b8dc86d764776ef1b4 (diff) |
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 <david.faure@kdab.com>
Diffstat (limited to 'src/corelib/itemmodels/qsortfilterproxymodel.cpp')
-rw-r--r-- | src/corelib/itemmodels/qsortfilterproxymodel.cpp | 31 |
1 files changed, 11 insertions, 20 deletions
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<QPersistentModelIndex> saved_layoutChange_parents; QHash<QModelIndex, Mapping *>::const_iterator create_mapping( const QModelIndex &source_parent) const; @@ -1331,23 +1332,23 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<Q Q_UNUSED(hint); // We can't forward Hint because we might filter additional rows or columns saved_persistent_indexes.clear(); - QList<QPersistentModelIndex> 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<QPersisten Q_Q(QSortFilterProxyModel); Q_UNUSED(hint); // We can't forward Hint because we might filter additional rows or columns + if (!sourceParents.isEmpty() && saved_layoutChange_parents.isEmpty()) + return; + // Optimize: We only actually have to clear the mapping related to the contents of // sourceParents, not everything. qDeleteAll(source_index_mapping); @@ -1373,21 +1377,8 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(const QList<QPersisten source_index_mapping.clear(); } - QList<QPersistentModelIndex> 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( |