aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicklayouts/qquickstacklayout.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicklayouts/qquickstacklayout.cpp')
-rw-r--r--src/quicklayouts/qquickstacklayout.cpp145
1 files changed, 83 insertions, 62 deletions
diff --git a/src/quicklayouts/qquickstacklayout.cpp b/src/quicklayouts/qquickstacklayout.cpp
index 19d0033e8b..0f745be9f9 100644
--- a/src/quicklayouts/qquickstacklayout.cpp
+++ b/src/quicklayouts/qquickstacklayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qquickstacklayout_p.h"
@@ -52,6 +16,10 @@
\brief The StackLayout class provides a stack of items where
only one item is visible at a time.
+ To be able to use this type more efficiently, it is recommended that you
+ understand the general mechanism of the Qt Quick Layouts module. Refer to
+ \l{Qt Quick Layouts Overview} for more information.
+
The current visible item can be modified by setting the \l currentIndex property.
The index corresponds to the order of the StackLayout's children.
@@ -98,6 +66,7 @@
\sa GridLayout
\sa RowLayout
\sa {QtQuick.Controls::StackView}{StackView}
+ \sa {Qt Quick Layouts Overview}
*/
QT_BEGIN_NAMESPACE
@@ -115,6 +84,7 @@ QQuickStackLayout::QQuickStackLayout(QQuickItem *parent) :
/*!
\qmlproperty int StackLayout::count
+ \readonly
This property holds the number of items that belong to the layout.
@@ -123,7 +93,6 @@ QQuickStackLayout::QQuickStackLayout(QQuickItem *parent) :
int QQuickStackLayout::count() const
{
Q_D(const QQuickStackLayout);
- ensureLayoutItemsUpdated();
return d->count;
}
@@ -132,18 +101,19 @@ 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
{
Q_D(const QQuickStackLayout);
- ensureLayoutItemsUpdated();
return d->currentIndex;
}
void QQuickStackLayout::setCurrentIndex(int index)
{
Q_D(QQuickStackLayout);
- ensureLayoutItemsUpdated();
if (index == d->currentIndex)
return;
@@ -179,7 +149,9 @@ void QQuickStackLayout::componentComplete()
{
QQuickLayout::componentComplete(); // will call our geometryChange(), (where isComponentComplete() == true)
- ensureLayoutItemsUpdated();
+ childItemsChanged();
+ invalidate();
+ ensureLayoutItemsUpdated(ApplySizeHints);
QQuickItem *par = parentItem();
if (qobject_cast<QQuickLayout*>(par))
@@ -191,6 +163,8 @@ void QQuickStackLayout::componentComplete()
void QQuickStackLayout::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
{
QQuickLayout::itemChange(change, value);
+ if (!isReady())
+ return;
if (change == ItemChildRemovedChange) {
QQuickItem *item = value.item;
@@ -200,8 +174,11 @@ void QQuickStackLayout::itemChange(QQuickItem::ItemChange change, const QQuickIt
stackLayoutAttached->setIndex(-1);
stackLayoutAttached->setIsCurrentItem(false);
}
+ m_cachedItemSizeHints.remove(item);
+ childItemsChanged(AdjustCurrentIndex); // removal; might have to adjust currentIndex
invalidate();
} else if (change == ItemChildAddedChange) {
+ childItemsChanged();
invalidate();
}
}
@@ -209,7 +186,6 @@ void QQuickStackLayout::itemChange(QQuickItem::ItemChange change, const QQuickIt
QSizeF QQuickStackLayout::sizeHint(Qt::SizeHint whichSizeHint) const
{
Q_D(const QQuickStackLayout);
- ensureLayoutItemsUpdated();
QSizeF &askingFor = m_cachedSizeHints[whichSizeHint];
if (!askingFor.isValid()) {
QSizeF &minS = m_cachedSizeHints[Qt::MinimumSize];
@@ -221,10 +197,8 @@ QSizeF QQuickStackLayout::sizeHint(Qt::SizeHint whichSizeHint) const
maxS = QSizeF(std::numeric_limits<qreal>::infinity(), std::numeric_limits<qreal>::infinity());
const int count = itemCount();
- m_cachedItemSizeHints.resize(count);
for (int i = 0; i < count; ++i) {
- SizeHints &hints = m_cachedItemSizeHints[i];
- QQuickStackLayout::collectItemSizeHints(itemAt(i), hints.array);
+ SizeHints &hints = cachedItemSizeHints(i);
minS = minS.expandedTo(hints.min());
prefS = prefS.expandedTo(hints.pref());
//maxS = maxS.boundedTo(hints.max()); // Can be resized to be larger than any of its items.
@@ -238,7 +212,6 @@ QSizeF QQuickStackLayout::sizeHint(Qt::SizeHint whichSizeHint) const
int QQuickStackLayout::indexOf(QQuickItem *childItem) const
{
- ensureLayoutItemsUpdated();
if (childItem) {
int indexOfItem = 0;
const auto items = childItems();
@@ -290,11 +263,11 @@ 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();
+ if (childItem) {
+ SizeHints &hints = m_cachedItemSizeHints[childItem];
+ hints.min() = QSizeF();
+ hints.pref() = QSizeF();
+ hints.max() = QSizeF();
}
for (int i = 0; i < Qt::NSizeHints; ++i)
@@ -305,15 +278,36 @@ void QQuickStackLayout::invalidate(QQuickItem *childItem)
parentLayout->invalidate(this);
}
-void QQuickStackLayout::updateLayoutItems()
+void QQuickStackLayout::childItemsChanged(AdjustCurrentIndexPolicy adjustCurrentIndexPolicy)
{
Q_D(QQuickStackLayout);
- d->m_ignoredItems.clear();
const int count = itemCount();
- int oldIndex = d->currentIndex;
+ const int oldIndex = d->currentIndex;
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();
@@ -335,6 +329,17 @@ void QQuickStackLayout::updateLayoutItems()
}
}
+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(item, hints.array);
+ return hints;
+}
+
+
void QQuickStackLayout::rearrange(const QSizeF &newSize)
{
Q_D(QQuickStackLayout);
@@ -342,11 +347,10 @@ void QQuickStackLayout::rearrange(const QSizeF &newSize)
return;
qCDebug(lcQuickLayouts) << "QQuickStackLayout::rearrange";
- ensureLayoutItemsUpdated();
- if (d->currentIndex == -1 || d->currentIndex >= m_cachedItemSizeHints.count())
+ if (d->currentIndex == -1 || d->currentIndex >= m_cachedItemSizeHints.size())
return;
- QQuickStackLayout::SizeHints &hints = m_cachedItemSizeHints[d->currentIndex];
+ QQuickStackLayout::SizeHints &hints = cachedItemSizeHints(d->currentIndex);
QQuickItem *item = itemAt(d->currentIndex);
Q_ASSERT(item);
item->setPosition(QPointF(0,0)); // ### respect alignment?
@@ -358,6 +362,10 @@ void QQuickStackLayout::rearrange(const QSizeF &newSize)
QQuickLayout::rearrange(newSize);
}
+void QQuickStackLayout::setStretchFactor(QQuickItem * /*item*/, int /*stretchFactor*/, Qt::Orientation /*orient*/)
+{
+}
+
void QQuickStackLayout::collectItemSizeHints(QQuickItem *item, QSizeF *sizeHints)
{
QQuickLayoutAttached *info = nullptr;
@@ -379,10 +387,15 @@ void QQuickStackLayout::collectItemSizeHints(QQuickItem *item, QSizeF *sizeHints
bool QQuickStackLayout::shouldIgnoreItem(QQuickItem *item) const
{
- const bool ignored = QQuickItemPrivate::get(item)->isTransparentForPositioner();
- if (ignored)
- d_func()->m_ignoredItems << item;
- return ignored;
+ return QQuickItemPrivate::get(item)->isTransparentForPositioner();
+}
+
+void QQuickStackLayout::itemSiblingOrderChanged(QQuickItem *)
+{
+ if (!isReady())
+ return;
+ childItemsChanged(AdjustCurrentIndex);
+ invalidate();
}
QQuickStackLayoutAttached::QQuickStackLayoutAttached(QObject *object)
@@ -410,10 +423,16 @@ QQuickStackLayoutAttached::QQuickStackLayoutAttached(QObject *object)
setLayout(stackLayout);
setIndex(index);
setIsCurrentItem(stackLayout->currentIndex() == index);
+
+ // In case of lazy loading in loader, attachedProperties are created and updated for the
+ // object after adding the child object to the stack layout, which leads to entries with
+ // same index. Triggering childItemsChanged() resets to right index in the stack layout.
+ stackLayout->childItemsChanged();
}
/*!
\qmlattachedproperty int StackLayout::index
+ \readonly
This attached property holds the index of each child item in the
\l StackLayout.
@@ -438,6 +457,7 @@ void QQuickStackLayoutAttached::setIndex(int index)
/*!
\qmlattachedproperty bool StackLayout::isCurrentItem
+ \readonly
This attached property is \c true if this child is the current item
in the \l StackLayout.
@@ -462,6 +482,7 @@ void QQuickStackLayoutAttached::setIsCurrentItem(bool isCurrentItem)
/*!
\qmlattachedproperty StackLayout StackLayout::layout
+ \readonly
This attached property holds the \l StackLayout that manages this child
item.