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
Change-Id: Ie768af34bf5ee9d15ca67d61a64115f3df31990f
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
(cherry picked from commit a0fb254915)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Jan Arve Sæther 2023-04-19 16:39:20 +02:00 committed by Qt Cherry-pick Bot
parent ef8b5344e7
commit 8d08d0d4e9
3 changed files with 118 additions and 0 deletions

View File

@ -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);

View File

@ -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:

View File

@ -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()
}
}
}