diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-01-09 14:31:27 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-01-10 13:03:04 +0100 |
commit | 490f787a1ebe3cee8e9f7793bb6919295b2aea47 (patch) | |
tree | 34513eb6a3c15d1cf184745cd9c36b82fe1595ba | |
parent | 3c23f5371a19991771bd29c27d377c6672e46cd1 (diff) |
QQuickItemView: Fix iteration/deletion logic
If a QVector has been modified from the outside, all its iterators are
invalid. Therefore, we need to do index-based iteration here.
Change-Id: I02b850daf6aadd8f8a81cc93b0d295e1170d7dd6
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/quick/items/qquickitemview.cpp | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 66be3c79f8..b5fb12fe89 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -1908,21 +1908,25 @@ void QQuickItemViewPrivate::layout() prepareVisibleItemTransitions(); - for (auto it = releasePendingTransition.begin(); it != releasePendingTransition.end(); ) { - auto old_count = releasePendingTransition.count(); - auto success = prepareNonVisibleItemTransition(*it, viewBounds); - // prepareNonVisibleItemTransition() may invalidate iterators while in fast flicking - // invisible animating items are kicked in or out the viewPort - // use old_count to test if the abrupt erasure occurs - if (old_count > releasePendingTransition.count()) { + // We cannot use iterators here as erasing from a container invalidates them. + for (int i = 0, count = releasePendingTransition.count(); i < count;) { + auto success = prepareNonVisibleItemTransition(releasePendingTransition[i], viewBounds); + // prepareNonVisibleItemTransition() may remove items while in fast flicking. + // Invisible animating items are kicked in or out the viewPort. + // Recheck count to test if the item got removed. In that case the same index points + // to a different item now. + const int old_count = count; + count = releasePendingTransition.count(); + if (old_count > count) continue; - } + if (!success) { - releaseItem(*it); - it = releasePendingTransition.erase(it); - continue; + releaseItem(releasePendingTransition[i]); + releasePendingTransition.remove(i); + --count; + } else { + ++i; } - ++it; } for (int i=0; i<visibleItems.count(); i++) |