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-26 10:57:26 +0200
commitadc3d8b2e40ca2853b4baf5ea893021a799c21f4 (patch)
tree2d8a8218201015bfa0fe825513bf6a2cd80c5969
parente362381e5969da36766e01f064eee8ddae43b2d8 (diff)
Fix StackLayout to keep the current visible item after insert/removal
If an item is inserted or deleted at an index less than or equal to the current index, StackLayout.currentIndex will be updated in order to reflect which is the current visible item. This is consistent with QStackedLayout, QStackedWidget and TabBar [ChangeLog][QtQuick][Layouts] StackLayout will now update currentIndex if an Item is inserted or removed at an index less than or equal to the current index. Task-number: QTBUG-112691 Pick-to: 6.5 Change-Id: Id1d687e309c8f199a4f68698b53ca7c169f17dcd Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r--src/quicklayouts/qquickstacklayout.cpp31
-rw-r--r--src/quicklayouts/qquickstacklayout_p.h7
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml5
3 files changed, 37 insertions, 6 deletions
diff --git a/src/quicklayouts/qquickstacklayout.cpp b/src/quicklayouts/qquickstacklayout.cpp
index 9396d5bf89..dd80ff19f1 100644
--- a/src/quicklayouts/qquickstacklayout.cpp
+++ b/src/quicklayouts/qquickstacklayout.cpp
@@ -100,6 +100,9 @@ int QQuickStackLayout::count() const
This property holds the index of the child item that is currently visible in the StackLayout.
By default it will be \c -1 for an empty layout, otherwise the default is \c 0 (referring to the first item).
+
+ Since 6.5, inserting/removing a new Item at an index less than or equal to the current index
+ will increment/decrement the current index, but keep the current Item.
*/
int QQuickStackLayout::currentIndex() const
{
@@ -171,7 +174,7 @@ void QQuickStackLayout::itemChange(QQuickItem::ItemChange change, const QQuickIt
stackLayoutAttached->setIsCurrentItem(false);
}
m_cachedItemSizeHints.remove(item);
- childItemsChanged();
+ childItemsChanged(AdjustCurrentIndex); // removal; might have to adjust currentIndex
invalidate();
} else if (change == ItemChildAddedChange) {
childItemsChanged();
@@ -274,7 +277,7 @@ void QQuickStackLayout::invalidate(QQuickItem *childItem)
parentLayout->invalidate(this);
}
-void QQuickStackLayout::childItemsChanged()
+void QQuickStackLayout::childItemsChanged(AdjustCurrentIndexPolicy adjustCurrentIndexPolicy)
{
Q_D(QQuickStackLayout);
const int count = itemCount();
@@ -282,6 +285,28 @@ void QQuickStackLayout::childItemsChanged()
if (!d->explicitCurrentIndex)
d->currentIndex = (count > 0 ? 0 : -1);
+ if (adjustCurrentIndexPolicy == AdjustCurrentIndex) {
+ /*
+ * If an item is inserted or deleted at an index less than or equal to the current index it
+ * will affect the current index, but keep the current item. This is consistent with
+ * QStackedLayout, QStackedWidget and TabBar
+ *
+ * Unless the caller is componentComplete(), we can assume that only one of the children
+ * are visible, and we should keep that visible even if the stacking order has changed.
+ * This means that if the sibling order has changed (or an item stacked before the current
+ * item is added/removed), we must update the currentIndex so that it corresponds with the
+ * current visible item.
+ */
+ if (d->currentIndex < d->count) {
+ for (int i = 0; i < count; ++i) {
+ QQuickItem *child = itemAt(i);
+ if (child->isVisible()) {
+ d->currentIndex = i;
+ break;
+ }
+ }
+ }
+ }
if (d->currentIndex != oldIndex)
emit currentIndexChanged();
@@ -368,7 +393,7 @@ void QQuickStackLayout::itemSiblingOrderChanged(QQuickItem *)
{
if (!isReady())
return;
- childItemsChanged();
+ childItemsChanged(AdjustCurrentIndex);
invalidate();
}
diff --git a/src/quicklayouts/qquickstacklayout_p.h b/src/quicklayouts/qquickstacklayout_p.h
index 332e1b10fd..96ed06656f 100644
--- a/src/quicklayouts/qquickstacklayout_p.h
+++ b/src/quicklayouts/qquickstacklayout_p.h
@@ -62,9 +62,14 @@ Q_SIGNALS:
void countChanged();
private:
+ enum AdjustCurrentIndexPolicy {
+ DontAdjustCurrentIndex,
+ AdjustCurrentIndex
+ };
+
static void collectItemSizeHints(QQuickItem *item, QSizeF *sizeHints);
bool shouldIgnoreItem(QQuickItem *item) const;
- void childItemsChanged();
+ void childItemsChanged(AdjustCurrentIndexPolicy adjustCurrentIndexPolicy = DontAdjustCurrentIndex);
Q_DECLARE_PRIVATE(QQuickStackLayout)
friend class QQuickStackLayoutAttached;
diff --git a/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml b/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml
index e6200a3e23..ad5cafaddb 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_stacklayout.qml
@@ -828,7 +828,7 @@ Item {
verifyVisibilityOfItems()
model.insert(0, { "color": "black" })
- compare(layout.currentIndex, 0)
+ compare(layout.currentIndex, 1)
compare(layout.count, 4)
verifyVisibilityOfItems()
@@ -855,10 +855,11 @@ Item {
verifyVisibilityOfItems()
model.insert(1, { "color": "brown" })
- compare(layout.currentIndex, 1)
+ compare(layout.currentIndex, 2)
compare(layout.count, 3)
verifyVisibilityOfItems()
+ // remove red, currentIndex should decrease
model.remove(0, 1)
compare(layout.currentIndex, 1)
compare(layout.count, 2)