summaryrefslogtreecommitdiffstats
path: root/src/corelib/itemmodels
diff options
context:
space:
mode:
authorStephen Kelly <stephen.kelly@kdab.com>2012-09-13 15:23:15 +0200
committerQt by Nokia <qt-info@nokia.com>2012-09-13 16:20:11 +0200
commitd7a15fbfd93fb566c7793596ea50d8786b9eb654 (patch)
tree06eb637c90dcfd7a0c9da615386c9eef78775991 /src/corelib/itemmodels
parent5c412fd74c9164f1e73a7287ca603295ce73bcf5 (diff)
Fix crash when invalidating a QSortFilterProxyModel
Task-number: QTBUG-27122 Change-Id: Ibca46b88442f4f92422d9b3182e4bbf25716a07f Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'src/corelib/itemmodels')
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp28
1 files changed, 19 insertions, 9 deletions
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 53cea5eeec..e3cd2f5fd7 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -1052,21 +1052,31 @@ void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_pare
// We need to iterate over a copy of m->mapped_children because otherwise it may be changed by other code, invalidating
// the iterator it2.
- // The m->mapped_children vector can be appended to when this function recurses for child indexes.
- // The handle_filter_changed implementation can cause source_parent.parent() to be called, which will create
- // a mapping (and do appending) while we are invalidating the filter.
- QVector<QModelIndex> mappedChildren = m->mapped_children;
- QVector<QModelIndex>::iterator it2 = mappedChildren.end();
- while (it2 != mappedChildren.begin()) {
- --it2;
- const QModelIndex source_child_index = *it2;
+ // The m->mapped_children vector can be appended to with indexes which are no longer filtered
+ // out (in create_mapping) when this function recurses for child indexes.
+ const QVector<QModelIndex> mappedChildren = m->mapped_children;
+ QVector<int> indexesToRemove;
+ for (int i = 0; i < mappedChildren.size(); ++i) {
+ const QModelIndex source_child_index = mappedChildren.at(i);
if (rows_removed.contains(source_child_index.row()) || columns_removed.contains(source_child_index.column())) {
- it2 = mappedChildren.erase(it2);
+ indexesToRemove.push_back(i);
remove_from_mapping(source_child_index);
} else {
filter_changed(source_child_index);
}
}
+ QVector<int>::const_iterator removeIt = indexesToRemove.constEnd();
+ const QVector<int>::const_iterator removeBegin = indexesToRemove.constBegin();
+
+ // We can't just remove these items from mappedChildren while iterating above and then
+ // do something like m->mapped_children = mappedChildren, because mapped_children might
+ // be appended to in create_mapping, and we would lose those new items.
+ // Because they are always appended in create_mapping, we can still remove them by
+ // position here.
+ while (removeIt != removeBegin) {
+ --removeIt;
+ m->mapped_children.remove(*removeIt);
+ }
}
/*!