aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2017-01-11 15:44:16 +0100
committerJ-P Nurmi <jpnurmi@qt.io>2017-01-12 14:36:13 +0000
commitdef88e018576e6e2185ff6fa4b6e4fac885a6e10 (patch)
tree6a5debfca7d07fd33f02526fa24607f9f2a3187f
parentf0508c72750d5c44834b6a0f9db3a76431350158 (diff)
Add attached StackView.visible property
[ChangeLog][Controls][StackView] Added attached StackView.visible property that can be used to control whether items below the top- most item are kept visible. Task-number: QTBUG-56801 Change-Id: Ieead0d476f254886cff5f8457bb5c5d23cb7de8a Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r--src/imports/controls/doc/images/qtquickcontrols2-stackview-visible.pngbin0 -> 1083 bytes
-rw-r--r--src/imports/controls/doc/snippets/qtquickcontrols2-stackview-visible.qml76
-rw-r--r--src/quicktemplates2/qquickstackelement.cpp11
-rw-r--r--src/quicktemplates2/qquickstackelement_p_p.h1
-rw-r--r--src/quicktemplates2/qquickstackview.cpp57
-rw-r--r--src/quicktemplates2/qquickstackview_p.cpp10
-rw-r--r--src/quicktemplates2/qquickstackview_p.h7
-rw-r--r--src/quicktemplates2/qquickstackview_p_p.h5
-rw-r--r--tests/auto/controls/data/tst_stackview.qml53
9 files changed, 208 insertions, 12 deletions
diff --git a/src/imports/controls/doc/images/qtquickcontrols2-stackview-visible.png b/src/imports/controls/doc/images/qtquickcontrols2-stackview-visible.png
new file mode 100644
index 00000000..9d21ce9c
--- /dev/null
+++ b/src/imports/controls/doc/images/qtquickcontrols2-stackview-visible.png
Binary files differ
diff --git a/src/imports/controls/doc/snippets/qtquickcontrols2-stackview-visible.qml b/src/imports/controls/doc/snippets/qtquickcontrols2-stackview-visible.qml
new file mode 100644
index 00000000..4689faa3
--- /dev/null
+++ b/src/imports/controls/doc/snippets/qtquickcontrols2-stackview-visible.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+
+//! [1]
+StackView {
+ id: stackView
+ property real offset: 10
+ width: 100; height: 100
+
+ initialItem: Component {
+ id: page
+ Rectangle {
+ property real pos: StackView.index * stackView.offset
+ property real hue: Math.random()
+ color: Qt.hsla(hue, 0.5, 0.8, 0.6)
+ border.color: Qt.hsla(hue, 0.5, 0.5, 0.9)
+ StackView.visible: true
+ }
+ }
+
+ pushEnter: Transition {
+ id: pushEnter
+ ParallelAnimation {
+ PropertyAction { property: "x"; value: pushEnter.ViewTransition.item.pos }
+ NumberAnimation { properties: "y"; from: pushEnter.ViewTransition.item.pos + stackView.offset; to: pushEnter.ViewTransition.item.pos; duration: 400; easing.type: Easing.OutCubic }
+ NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 400; easing.type: Easing.OutCubic }
+ }
+ }
+ popExit: Transition {
+ id: popExit
+ ParallelAnimation {
+ PropertyAction { property: "x"; value: popExit.ViewTransition.item.pos }
+ NumberAnimation { properties: "y"; from: popExit.ViewTransition.item.pos; to: popExit.ViewTransition.item.pos + stackView.offset; duration: 400; easing.type: Easing.OutCubic }
+ NumberAnimation { property: "opacity"; from: 1; to: 0; duration: 400; easing.type: Easing.OutCubic }
+ }
+ }
+
+ pushExit: Transition {
+ id: pushExit
+ PropertyAction { property: "x"; value: pushExit.ViewTransition.item.pos }
+ PropertyAction { property: "y"; value: pushExit.ViewTransition.item.pos }
+ }
+ popEnter: Transition {
+ id: popEnter
+ PropertyAction { property: "x"; value: popEnter.ViewTransition.item.pos }
+ PropertyAction { property: "y"; value: popEnter.ViewTransition.item.pos }
+ }
+}
+//! [1]
diff --git a/src/quicktemplates2/qquickstackelement.cpp b/src/quicktemplates2/qquickstackelement.cpp
index c67c0015..7bd6efc9 100644
--- a/src/quicktemplates2/qquickstackelement.cpp
+++ b/src/quicktemplates2/qquickstackelement.cpp
@@ -89,7 +89,7 @@ QQuickStackElement::~QQuickStackElement()
item->deleteLater();
item = nullptr;
} else {
- item->setVisible(false);
+ setVisible(false);
if (!widthValid)
item->resetWidth();
if (!heightValid)
@@ -252,6 +252,15 @@ void QQuickStackElement::setStatus(QQuickStackView::Status value)
emit attached->statusChanged();
}
+void QQuickStackElement::setVisible(bool visible)
+{
+ QQuickStackViewAttached *attached = attachedStackObject(this);
+ if (!item || (attached && QQuickStackViewAttachedPrivate::get(attached)->explicitVisible))
+ return;
+
+ item->setVisible(visible);
+}
+
void QQuickStackElement::transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget)
{
if (transitioner)
diff --git a/src/quicktemplates2/qquickstackelement_p_p.h b/src/quicktemplates2/qquickstackelement_p_p.h
index 192726b6..9cb11855 100644
--- a/src/quicktemplates2/qquickstackelement_p_p.h
+++ b/src/quicktemplates2/qquickstackelement_p_p.h
@@ -77,6 +77,7 @@ public:
void setIndex(int index);
void setView(QQuickStackView *view);
void setStatus(QQuickStackView::Status status);
+ void setVisible(bool visible);
void transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget);
bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds);
diff --git a/src/quicktemplates2/qquickstackview.cpp b/src/quicktemplates2/qquickstackview.cpp
index b185a2dc..4fb153ab 100644
--- a/src/quicktemplates2/qquickstackview.cpp
+++ b/src/quicktemplates2/qquickstackview.cpp
@@ -513,7 +513,7 @@ void QQuickStackView::push(QQmlV4Function *args)
d->startTransition(QQuickStackTransition::pushEnter(operation, enter, this),
QQuickStackTransition::pushExit(operation, exit, this),
operation == Immediate);
- d->setCurrentItem(enter->item);
+ d->setCurrentItem(enter);
}
if (d->currentItem) {
@@ -605,7 +605,7 @@ void QQuickStackView::pop(QQmlV4Function *args)
d->startTransition(QQuickStackTransition::popExit(operation, exit, this),
QQuickStackTransition::popEnter(operation, enter, this),
operation == Immediate);
- d->setCurrentItem(enter->item);
+ d->setCurrentItem(enter);
}
if (previousItem) {
@@ -748,7 +748,7 @@ void QQuickStackView::replace(QQmlV4Function *args)
d->startTransition(QQuickStackTransition::replaceExit(operation, exit, this),
QQuickStackTransition::replaceEnter(operation, enter, this),
operation == Immediate);
- d->setCurrentItem(enter->item);
+ d->setCurrentItem(enter);
}
if (d->currentItem) {
@@ -971,7 +971,7 @@ void QQuickStackView::componentComplete()
element = QQuickStackElement::fromString(d->initialItem.toString(), this);
if (d->pushElement(element)) {
emit depthChanged();
- d->setCurrentItem(element->item);
+ d->setCurrentItem(element);
element->setStatus(QQuickStackView::Active);
}
}
@@ -1039,6 +1039,7 @@ QQuickStackViewAttached::QQuickStackViewAttached(QObject *parent) :
Q_D(QQuickStackViewAttached);
QQuickItem *item = qobject_cast<QQuickItem *>(parent);
if (item) {
+ connect(item, &QQuickItem::visibleChanged, this, &QQuickStackViewAttached::visibleChanged);
QQuickItemPrivate::get(item)->addItemChangeListener(d, QQuickItemPrivate::Parent);
d->itemParentChanged(item, item->parentItem());
} else if (parent) {
@@ -1100,6 +1101,54 @@ QQuickStackView::Status QQuickStackViewAttached::status() const
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlattachedproperty bool QtQuick.Controls::StackView::visible
+
+ This attached property holds the visibility of the item it's attached to.
+ The value follows the value of \l Item::visible.
+
+ By default, StackView shows incoming items when the enter transition begins,
+ and hides outgoing items when the exit transition ends. Setting this property
+ explicitly allows the default behavior to be overridden, making it possible
+ to keep items that are below the top-most item visible.
+
+ \note The default transitions of most styles slide outgoing items outside the
+ view, and may also animate their opacity. In order to keep a full stack
+ of items visible, consider customizing the \l transitions so that the
+ items underneath can be seen.
+
+ \image qtquickcontrols2-stackview-visible.png
+
+ \snippet qtquickcontrols2-stackview-visible.qml 1
+*/
+bool QQuickStackViewAttached::isVisible() const
+{
+ const QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
+ return parentItem && parentItem->isVisible();
+}
+
+void QQuickStackViewAttached::setVisible(bool visible)
+{
+ Q_D(QQuickStackViewAttached);
+ d->explicitVisible = true;
+ QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
+ if (parentItem)
+ parentItem->setVisible(visible);
+}
+
+void QQuickStackViewAttached::resetVisible()
+{
+ Q_D(QQuickStackViewAttached);
+ d->explicitVisible = false;
+ if (!d->element || !d->element->view)
+ return;
+
+ QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
+ if (parentItem)
+ parentItem->setVisible(parentItem == d->element->view->currentItem());
+}
+
+/*!
\qmlattachedsignal QtQuick.Controls::StackView::activated()
\since QtQuick.Controls 2.1
diff --git a/src/quicktemplates2/qquickstackview_p.cpp b/src/quicktemplates2/qquickstackview_p.cpp
index 441768f7..4f592f45 100644
--- a/src/quicktemplates2/qquickstackview_p.cpp
+++ b/src/quicktemplates2/qquickstackview_p.cpp
@@ -50,15 +50,16 @@ QQuickStackViewPrivate::QQuickStackViewPrivate() : busy(false), currentItem(null
{
}
-void QQuickStackViewPrivate::setCurrentItem(QQuickItem *item)
+void QQuickStackViewPrivate::setCurrentItem(QQuickStackElement *element)
{
Q_Q(QQuickStackView);
+ QQuickItem *item = element ? element->item : nullptr;
if (currentItem == item)
return;
currentItem = item;
- if (item)
- item->setVisible(true);
+ if (element)
+ element->setVisible(true);
emit q->currentItemChanged();
}
@@ -243,8 +244,7 @@ void QQuickStackViewPrivate::viewItemTransitionFinished(QQuickItemViewTransition
element->setStatus(QQuickStackView::Active);
} else if (element->status == QQuickStackView::Deactivating) {
element->setStatus(QQuickStackView::Inactive);
- if (element->item)
- element->item->setVisible(false);
+ element->setVisible(false);
if (element->removal || element->isPendingRemoval())
removals += element;
}
diff --git a/src/quicktemplates2/qquickstackview_p.h b/src/quicktemplates2/qquickstackview_p.h
index eea59334..cc2e4ee2 100644
--- a/src/quicktemplates2/qquickstackview_p.h
+++ b/src/quicktemplates2/qquickstackview_p.h
@@ -168,6 +168,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickStackViewAttached : public QObject
Q_PROPERTY(int index READ index NOTIFY indexChanged FINAL)
Q_PROPERTY(QQuickStackView *view READ view NOTIFY viewChanged FINAL)
Q_PROPERTY(QQuickStackView::Status status READ status NOTIFY statusChanged FINAL)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible RESET resetVisible NOTIFY visibleChanged FINAL) // REVISION 2
public:
explicit QQuickStackViewAttached(QObject *parent = nullptr);
@@ -177,10 +178,16 @@ public:
QQuickStackView *view() const;
QQuickStackView::Status status() const;
+ bool isVisible() const;
+ void setVisible(bool visible);
+ void resetVisible();
+
Q_SIGNALS:
void indexChanged();
void viewChanged();
void statusChanged();
+ /*Q_REVISION(2)*/ void visibleChanged();
+
/*Q_REVISION(1)*/ void activated();
/*Q_REVISION(1)*/ void activating();
/*Q_REVISION(1)*/ void deactivated();
diff --git a/src/quicktemplates2/qquickstackview_p_p.h b/src/quicktemplates2/qquickstackview_p_p.h
index 915f4160..7c2e6c3f 100644
--- a/src/quicktemplates2/qquickstackview_p_p.h
+++ b/src/quicktemplates2/qquickstackview_p_p.h
@@ -71,7 +71,7 @@ public:
return view->d_func();
}
- void setCurrentItem(QQuickItem *item);
+ void setCurrentItem(QQuickStackElement *element);
QList<QQuickStackElement *> parseElements(QQmlV4Function *args, int from = 0);
QQuickStackElement *findElement(QQuickItem *item) const;
@@ -102,7 +102,7 @@ class QQuickStackViewAttachedPrivate : public QObjectPrivate, public QQuickItemC
Q_DECLARE_PUBLIC(QQuickStackViewAttached)
public:
- QQuickStackViewAttachedPrivate() : element(nullptr) { }
+ QQuickStackViewAttachedPrivate() : explicitVisible(false), element(nullptr) { }
static QQuickStackViewAttachedPrivate *get(QQuickStackViewAttached *attached)
{
@@ -111,6 +111,7 @@ public:
void itemParentChanged(QQuickItem *item, QQuickItem *parent);
+ bool explicitVisible;
QQuickStackElement *element;
};
diff --git a/tests/auto/controls/data/tst_stackview.qml b/tests/auto/controls/data/tst_stackview.qml
index 8034b79c..327d114f 100644
--- a/tests/auto/controls/data/tst_stackview.qml
+++ b/tests/auto/controls/data/tst_stackview.qml
@@ -1048,4 +1048,57 @@ TestCase {
control.destroy()
}
+
+ function test_visible() {
+ var control = stackView.createObject(testCase)
+ verify(control)
+
+ var item1 = component.createObject(control)
+ control.push(item1, StackView.Immediate)
+ compare(item1.visible, true)
+ compare(item1.StackView.visible, item1.visible)
+
+ var item2 = component.createObject(control)
+ control.push(item2, StackView.Immediate)
+ compare(item1.visible, false)
+ compare(item2.visible, true)
+ compare(item1.StackView.visible, false)
+ compare(item2.StackView.visible, true)
+
+ // keep explicitly visible
+ item2.StackView.visible = true
+ control.push(component, StackView.Immediate)
+ compare(item2.visible, true)
+ compare(item2.StackView.visible, true)
+
+ // show underneath
+ item1.StackView.visible = true
+ compare(item1.visible, true)
+ compare(item1.StackView.visible, true)
+
+ control.pop(StackView.Immediate)
+ compare(item2.visible, true)
+ compare(item2.StackView.visible, true)
+
+ // hide the top-most
+ item2.StackView.visible = false
+ compare(item2.visible, false)
+ compare(item2.StackView.visible, false)
+
+ // reset the top-most
+ item2.StackView.visible = undefined
+ compare(item2.visible, true)
+ compare(item2.StackView.visible, true)
+
+ // reset underneath
+ item1.StackView.visible = undefined
+ compare(item1.visible, false)
+ compare(item1.StackView.visible, false)
+
+ control.pop(StackView.Immediate)
+ compare(item1.visible, true)
+ compare(item1.StackView.visible, true)
+
+ control.destroy()
+ }
}