diff options
author | Stephen Kelly <stephen.kelly@kdab.com> | 2012-09-14 15:42:34 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-09-14 20:16:44 +0200 |
commit | 989e6c5ee6f3e38b24632ec5caf49c5b03d17aed (patch) | |
tree | 800318a2f552fb1f16ff3ba7f1ffd13057db0d61 /src | |
parent | ecc432a5b7ae269220f86c6f0b3dd364f8643191 (diff) | |
download | qt4-tools-989e6c5ee6f3e38b24632ec5caf49c5b03d17aed.tar.gz |
Fix crash when invalidating a QSortFilterProxyModel
Backport of d7a15fbfd93fb566c7793596ea50d8786b9eb654 from qtbase.
Task-number: QTBUG-27122
Change-Id: I0b1eda292fd9648e6f08629f7a069b66bb8b59e8
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/itemviews/qsortfilterproxymodel.cpp | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index d937b63efb..9fe224e237 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -1036,18 +1036,34 @@ void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_pare Mapping *m = it.value(); QSet<int> rows_removed = handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical); QSet<int> columns_removed = handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal); - QVector<QModelIndex> mappedChildren = m->mapped_children; - QVector<QModelIndex>::iterator it2 = mappedChildren.end(); - while (it2 != mappedChildren.begin()) { - --it2; - const QModelIndex source_child_index = *it2; + + // 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 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); + } } /*! |