From 52535d21f084bae67b845a1ff2cf70f03b5fa6a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Wed, 21 Sep 2022 13:44:19 +0200 Subject: Fix wrong item-sizeHint-cache when StackLayout children were reordered This fixes the Tests_StackLayout::test_addAndRemoveItems() autotest The code uses an index to look up the cached size hints. This index corresponds to the layout's item child index (which doesn't have to correspond to the children index). The vector of sizeHints then had to be in sync with the index of the child layout items for this to work. The problem here was that if the first item in the stack was removed (or siblings was reordered), the vector was not adjusted for this (basically we could get the size hint of an previously removed item). In order to avoid to keep the QVector index in sync with the layout children index, we change it to use a QHash instead, where we look up by QQuickItem*. QHash Task-number: QTBUG-106520 Task-number: QTBUG-106521 Change-Id: I7c1f9fb018fcab093b074c45dfaba264f76749f4 Reviewed-by: Mitch Curtis (cherry picked from commit c41075d9e2808f636d793c93e237f80a8ecadb2e) --- src/imports/layouts/qquickstacklayout.cpp | 22 +++++++++++++--------- src/imports/layouts/qquickstacklayout_p.h | 2 +- .../quick/qquicklayouts/data/tst_stacklayout.qml | 1 - 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/imports/layouts/qquickstacklayout.cpp b/src/imports/layouts/qquickstacklayout.cpp index bd2f93c630..d3d140abc8 100644 --- a/src/imports/layouts/qquickstacklayout.cpp +++ b/src/imports/layouts/qquickstacklayout.cpp @@ -171,6 +171,7 @@ void QQuickStackLayout::itemChange(QQuickItem::ItemChange change, const QQuickIt QQuickLayout::itemChange(change, value); if (change == ItemChildRemovedChange) { + m_cachedItemSizeHints.remove(value.item); invalidate(); } else if (change == ItemChildAddedChange) { invalidate(); @@ -254,11 +255,12 @@ void QQuickStackLayout::setAlignment(QQuickItem * /*item*/, Qt::Alignment /*alig void QQuickStackLayout::invalidate(QQuickItem *childItem) { - const int indexOfChild = indexOf(childItem); - if (indexOfChild >= 0 && indexOfChild < m_cachedItemSizeHints.count()) { - m_cachedItemSizeHints[indexOfChild].min() = QSizeF(); - m_cachedItemSizeHints[indexOfChild].pref() = QSizeF(); - m_cachedItemSizeHints[indexOfChild].max() = QSizeF(); + ensureLayoutItemsUpdated(); + if (childItem) { + SizeHints &hints = m_cachedItemSizeHints[childItem]; + hints.min() = QSizeF(); + hints.pref() = QSizeF(); + hints.max() = QSizeF(); } for (int i = 0; i < Qt::NSizeHints; ++i) @@ -284,7 +286,6 @@ void QQuickStackLayout::updateLayoutItems() if (count != d->count) { d->count = count; emit countChanged(); - m_cachedItemSizeHints.resize(count); } for (int i = 0; i < count; ++i) { QQuickItem *child = itemAt(i); @@ -293,10 +294,13 @@ void QQuickStackLayout::updateLayoutItems() } } -QQuickStackLayout::SizeHints &QQuickStackLayout::cachedItemSizeHints(int index) const { - SizeHints &hints = m_cachedItemSizeHints[index]; +QQuickStackLayout::SizeHints &QQuickStackLayout::cachedItemSizeHints(int index) const +{ + QQuickItem *item = itemAt(index); + Q_ASSERT(item); + SizeHints &hints = m_cachedItemSizeHints[item]; // will create an entry if it doesn't exist if (!hints.min().isValid()) - QQuickStackLayout::collectItemSizeHints(itemAt(index), hints.array); + QQuickStackLayout::collectItemSizeHints(item, hints.array); return hints; } diff --git a/src/imports/layouts/qquickstacklayout_p.h b/src/imports/layouts/qquickstacklayout_p.h index e46c608926..41aac01ec8 100644 --- a/src/imports/layouts/qquickstacklayout_p.h +++ b/src/imports/layouts/qquickstacklayout_p.h @@ -95,7 +95,7 @@ private: QSizeF array[Qt::NSizeHints]; } SizeHints; - mutable QVector m_cachedItemSizeHints; + mutable QHash m_cachedItemSizeHints; mutable QSizeF m_cachedSizeHints[Qt::NSizeHints]; SizeHints &cachedItemSizeHints(int index) const; }; diff --git a/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml b/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml index 32b149336a..2536b9789f 100644 --- a/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml +++ b/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml @@ -255,7 +255,6 @@ Item { function test_addAndRemoveItems() { - skip("There is a bug with the internal StackLayout cache that causes this to fail") var stack = emtpy_StackLayout_Component.createObject(container) stack.currentIndex = 2 compare(stack.implicitWidth, 0) -- cgit v1.2.3