diff options
author | Jan Arve Sæther <jan-arve.saether@qt.io> | 2023-04-19 16:39:20 +0200 |
---|---|---|
committer | Jan Arve Sæther <jan-arve.saether@qt.io> | 2023-04-25 10:07:20 +0200 |
commit | a0fb254915ba9d4507c2f17bdbe79ebeaabb3cdf (patch) | |
tree | b0186f145f06e411f53e7dc21421e83ba44a5d03 | |
parent | b9524e4e8d30781413cf200f440c182b9ade52e5 (diff) |
Fix StackLayout to react to reordering siblings
When siblings in a StackLayout are reordered, we need to react, since
the sibling order corresponds to the "stack order"
Fixes: QTBUG-112691
Pick-to: 6.5
Change-Id: Ie768af34bf5ee9d15ca67d61a64115f3df31990f
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r-- | src/quicklayouts/qquickstacklayout.cpp | 8 | ||||
-rw-r--r-- | src/quicklayouts/qquickstacklayout_p.h | 3 | ||||
-rw-r--r-- | tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml | 107 |
3 files changed, 118 insertions, 0 deletions
diff --git a/src/quicklayouts/qquickstacklayout.cpp b/src/quicklayouts/qquickstacklayout.cpp index 14ebcb434d..9396d5bf89 100644 --- a/src/quicklayouts/qquickstacklayout.cpp +++ b/src/quicklayouts/qquickstacklayout.cpp @@ -364,6 +364,14 @@ bool QQuickStackLayout::shouldIgnoreItem(QQuickItem *item) const return QQuickItemPrivate::get(item)->isTransparentForPositioner(); } +void QQuickStackLayout::itemSiblingOrderChanged(QQuickItem *) +{ + if (!isReady()) + return; + childItemsChanged(); + invalidate(); +} + QQuickStackLayoutAttached::QQuickStackLayoutAttached(QObject *object) { auto item = qobject_cast<QQuickItem*>(object); diff --git a/src/quicklayouts/qquickstacklayout_p.h b/src/quicklayouts/qquickstacklayout_p.h index 5ffa3d5c41..332e1b10fd 100644 --- a/src/quicklayouts/qquickstacklayout_p.h +++ b/src/quicklayouts/qquickstacklayout_p.h @@ -52,6 +52,9 @@ public: int itemCount() const override; int indexOf(QQuickItem *item) const; + /* QQuickItemChangeListener */ + void itemSiblingOrderChanged(QQuickItem *item) override; + static QQuickStackLayoutAttached *qmlAttachedProperties(QObject *object); Q_SIGNALS: diff --git a/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml b/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml index 99713991bd..e6200a3e23 100644 --- a/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml +++ b/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml @@ -757,5 +757,112 @@ Item { compare(stackLayoutObj.children[1].StackLayout.index, 1) compare(stackLayoutObj.children[2].StackLayout.index, 2) } + + Component { + id: test_repeater_Component + + Item { + property alias stackLayout : stackLayout + property var model : ListModel { + /* + * We cannot programmatically reorder siblings (QQuickItem::stackBefore() + * and QQuickItem::stackAfter() are not not available to QML, and we cannot + * alter the Item::children property to reorder siblings) + * Therefore, we have to go through the hoops with a ListModel and Repeater in + * order to trigger sibling reordering, just as reported in QTBUG-112691. + * Adding an item to a specific index (with model.insert()), will be done in + * two steps: + * 1. Append an Item to be the last of the siblings + * 2. Reorder that Rectangle to be at the correct child index that corresponds + * to the index given to model.insert() + * + * Adding an item to a specific index will therefore test sibling reordering + */ + id: listModel + } + StackLayout { + id: stackLayout + anchors.fill: parent + Layout.fillHeight: true + Layout.fillWidth: true + Repeater { + id: repeater + model:listModel + delegate: Rectangle { + implicitWidth: 100 + implicitHeight: 100 + objectName: model.color + color: model.color + } + } + } + } + } + + function test_repeater() { + let item = createTemporaryObject(test_repeater_Component, container) + let layout = item.stackLayout + let model = item.model + function verifyVisibilityOfItems() { + for (let i = 0; i < layout.count; ++i) { + compare(layout.children[i].visible, layout.currentIndex === i) + } + } + + compare(layout.currentIndex, -1) + compare(layout.count, 0) + + model.append({ "color": "red" }) + compare(layout.currentIndex, 0) + compare(layout.count, 1) + verifyVisibilityOfItems() + + model.append({ "color": "green" }) + compare(layout.currentIndex, 0) + compare(layout.count, 2) + verifyVisibilityOfItems() + + model.append({ "color": "blue" }) + compare(layout.currentIndex, 0) + compare(layout.count, 3) + verifyVisibilityOfItems() + + model.insert(0, { "color": "black" }) + compare(layout.currentIndex, 0) + compare(layout.count, 4) + verifyVisibilityOfItems() + + // An implicit currentIndex will reset back to -1 if + // the StackLayout is empty + model.clear() + compare(layout.currentIndex, -1) + compare(layout.count, 0) + + // set explicit index to out of bounds + layout.currentIndex = 1 + compare(layout.currentIndex, 1) + compare(layout.count, 0) + verifyVisibilityOfItems() + + model.append({ "color": "red" }) + compare(layout.currentIndex, 1) + compare(layout.count, 1) + verifyVisibilityOfItems() + + model.append({ "color": "green" }) + compare(layout.currentIndex, 1) + compare(layout.count, 2) + verifyVisibilityOfItems() + + model.insert(1, { "color": "brown" }) + compare(layout.currentIndex, 1) + compare(layout.count, 3) + verifyVisibilityOfItems() + + model.remove(0, 1) + compare(layout.currentIndex, 1) + compare(layout.count, 2) + verifyVisibilityOfItems() + } } } |