summaryrefslogtreecommitdiffstats
path: root/src/corelib/itemmodels/qsortfilterproxymodel.cpp
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2016-12-17 06:20:06 +0000
committerStephen Kelly <steveire@gmail.com>2016-12-21 01:37:31 +0000
commit3bd0fd8f97e7a33a874929a383a42e6c710bfff3 (patch)
tree59c22bb46eb3ee8e6b60232d34a22af0e65589f9 /src/corelib/itemmodels/qsortfilterproxymodel.cpp
parent1274a7e419c9f25d6dcd01b8dc86d764776ef1b4 (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.cpp31
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(