aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Arve Sæther <jan-arve.saether@qt.io>2023-04-19 16:39:20 +0200
committerJan Arve Sæther <jan-arve.saether@qt.io>2023-04-25 10:07:20 +0200
commita0fb254915ba9d4507c2f17bdbe79ebeaabb3cdf (patch)
treeb0186f145f06e411f53e7dc21421e83ba44a5d03
parentb9524e4e8d30781413cf200f440c182b9ade52e5 (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.cpp8
-rw-r--r--src/quicklayouts/qquickstacklayout_p.h3
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml107
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()
+ }
}
}