diff options
author | Mitch Curtis <[email protected]> | 2021-08-12 14:39:51 +0200 |
---|---|---|
committer | Mitch Curtis <[email protected]> | 2021-08-16 12:52:59 +0200 |
commit | 809339d1484cf556512534367b8170bc26baf072 (patch) | |
tree | 12871313b658f36d058b5ef25af1e247e9c46ce9 /src/quicktemplates2/qquickstackview.cpp | |
parent | b01b4f00eae8022c6a97d90f54dac395144ae095 (diff) |
Now that qtquickcontrols2 has been merged into qtdeclarative,
we should make it obvious that this repo should no longer be
used, by preventing it from being built.
Task-number: QTBUG-95173
Pick-to: 6.2
Change-Id: I95bd6a214f3d75a865ab163ee0a1f9ffbeb7a051
Reviewed-by: Alexandru Croitor <[email protected]>
Reviewed-by: Volker Hilsheimer <[email protected]>
Diffstat (limited to 'src/quicktemplates2/qquickstackview.cpp')
-rw-r--r-- | src/quicktemplates2/qquickstackview.cpp | 1404 |
1 files changed, 0 insertions, 1404 deletions
diff --git a/src/quicktemplates2/qquickstackview.cpp b/src/quicktemplates2/qquickstackview.cpp deleted file mode 100644 index 7bf4c3d3..00000000 --- a/src/quicktemplates2/qquickstackview.cpp +++ /dev/null @@ -1,1404 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** 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 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.LGPLv3 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.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 later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickstackview_p.h" -#include "qquickstackview_p_p.h" -#include "qquickstackelement_p_p.h" -#include "qquickstacktransition_p_p.h" - -#include <QtCore/qscopedvaluerollback.h> -#include <QtQml/qjsvalue.h> -#include <QtQml/qqmlengine.h> -#include <QtQml/qqmlinfo.h> - -#include <private/qv4qobjectwrapper_p.h> -#include <private/qqmlengine_p.h> - -QT_BEGIN_NAMESPACE - -/*! - \qmltype StackView - \inherits Control -//! \instantiates QQuickStackView - \inqmlmodule QtQuick.Controls - \since 5.7 - \ingroup qtquickcontrols2-navigation - \ingroup qtquickcontrols2-containers - \ingroup qtquickcontrols2-focusscopes - \brief Provides a stack-based navigation model. - - \image qtquickcontrols2-stackview-wireframe.png - - StackView can be used with a set of inter-linked information pages. For - example, an email application with separate views to list the latest emails, - view a specific email, and list/view the attachments. The email list view - is pushed onto the stack as users open an email, and popped out as they - choose to go back. - - The following snippet demonstrates a simple use case, where the \c mainView - is pushed onto and popped out of the stack on relevant button click: - - \qml - ApplicationWindow { - title: qsTr("Hello World") - width: 640 - height: 480 - visible: true - - StackView { - id: stack - initialItem: mainView - anchors.fill: parent - } - - Component { - id: mainView - - Row { - spacing: 10 - - Button { - text: "Push" - onClicked: stack.push(mainView) - } - Button { - text: "Pop" - enabled: stack.depth > 1 - onClicked: stack.pop() - - } - Text { - text: stack.depth - } - } - } - } - \endqml - - \section1 Using StackView in an Application - - Using StackView in an application is as simple as adding it as a child to - a Window. The stack is usually anchored to the edges of the window, except - at the top or bottom where it might be anchored to a status bar, or some - other similar UI component. The stack can then be used by invoking its - navigation methods. The first item to show in the StackView is the one - that was assigned to \l initialItem, or the topmost item if \l initialItem - is not set. - - \section1 Basic Navigation - - StackView supports three primary navigation operations: push(), pop(), and - replace(). These correspond to classic stack operations where "push" adds - an item to the top of a stack, "pop" removes the top item from the - stack, and "replace" is like a pop followed by a push, which replaces the - topmost item with the new item. The topmost item in the stack - corresponds to the one that is \l{StackView::currentItem}{currently} - visible on screen. Logically, "push" navigates forward or deeper into the - application UI, "pop" navigates backward, and "replace" replaces the - \l currentItem. - - \section2 Pushing Items - - In the following animation, three \l Label controls are pushed onto a - stack view with the \l push() function: - - \image qtquickcontrols2-stackview-push.gif - - The stack now contains the following items: \c [A, B, C]. - - \note When the stack is empty, a push() operation will not have a - transition animation because there is nothing to transition from (typically - on application start-up). - - \section2 Popping Items - - Continuing on from the example above, the topmost item on the stack is - removed with a call to \l pop(): - - \image qtquickcontrols2-stackview-pop.gif - - The stack now contains the following items: \c [A, B]. - - \note A pop() operation on a stack with depth 1 or 0 does nothing. In such - cases, the stack can be emptied using the \l clear() method. - - \section3 Unwinding Items via Pop - - Sometimes, it is necessary to go back more than a single step in the stack. - For example, to return to a "main" item or some kind of section item in the - application. In such cases, it is possible to specify an item as a - parameter for pop(). This is called an "unwind" operation, where the stack - unwinds till the specified item. If the item is not found, stack unwinds - until it is left with one item, which becomes the \l currentItem. To - explicitly unwind to the bottom of the stack, it is recommended to use - \l{pop()}{pop(null)}, although any non-existent item will do. - - In the following animation, we unwind the stack to the first item by - calling \c pop(null): - - \image qtquickcontrols2-stackview-unwind.gif - - The stack now contains a single item: \c [A]. - - \section2 Replacing Items - - In the following animation, we \l replace the topmost item with \c D: - - \image qtquickcontrols2-stackview-replace.gif - - The stack now contains the following items: \c [A, B, D]. - - \section1 Deep Linking - - \e{Deep linking} means launching an application into a particular state. For - example, a newspaper application could be launched into showing a - particular article, bypassing the topmost item. In terms of StackView, deep linking means the ability to modify - the state of the stack, so much so that it is possible to push a set of - items to the top of the stack, or to completely reset the stack to a given - state. - - The API for deep linking in StackView is the same as for basic navigation. - Pushing an array instead of a single item adds all the items in that array - to the stack. The transition animation, however, is applied only for the - last item in the array. The normal semantics of push() apply for deep - linking, that is, it adds whatever is pushed onto the stack. - - \note Only the last item of the array is loaded. The rest of the items are - loaded only when needed, either on subsequent calls to pop or on request to - get an item using get(). - - This gives us the following result, given the stack [A, B, C]: - - \list - \li \l{push()}{push([D, E, F])} => [A, B, C, D, E, F] - "push" transition - animation between C and F - \li \l{replace()}{replace([D, E, F])} => [A, B, D, E, F] - "replace" - transition animation between C and F - \li \l{clear()} followed by \l{push()}{push([D, E, F])} => [D, E, F] - no - transition animation for pushing items as the stack was empty. - \endlist - - \section1 Finding Items - - An Item for which the application does not have a reference can be found - by calling find(). The method needs a callback function, which is invoked - for each item in the stack (starting at the top) until a match is found. - If the callback returns \c true, find() stops and returns the matching - item, otherwise \c null is returned. - - The code below searches the stack for an item named "order_id" and unwinds - to that item. - - \badcode - stackView.pop(stackView.find(function(item) { - return item.name == "order_id"; - })); - \endcode - - You can also get to an item in the stack using \l {get()}{get(index)}. - - \badcode - previousItem = stackView.get(myItem.StackView.index - 1)); - \endcode - - \section1 Transitions - - For each push or pop operation, different transition animations are applied - to entering and exiting items. These animations define how the entering item - should animate in, and the exiting item should animate out. The animations - can be customized by assigning different \l{Transition}s for the - \l pushEnter, \l pushExit, \l popEnter, \l popExit, \l replaceEnter, and - \l replaceExit properties of StackView. - - \note The transition animations affect each others' transitional behavior. - Customizing the animation for one and leaving the other may give unexpected - results. - - The following snippet defines a simple fade transition for push and pop - operations: - - \qml - StackView { - id: stackview - anchors.fill: parent - - pushEnter: Transition { - PropertyAnimation { - property: "opacity" - from: 0 - to:1 - duration: 200 - } - } - pushExit: Transition { - PropertyAnimation { - property: "opacity" - from: 1 - to:0 - duration: 200 - } - } - popEnter: Transition { - PropertyAnimation { - property: "opacity" - from: 0 - to:1 - duration: 200 - } - } - popExit: Transition { - PropertyAnimation { - property: "opacity" - from: 1 - to:0 - duration: 200 - } - } - } - \endqml - - \note Using anchors on the items added to a StackView is not supported. - Typically push, pop, and replace transitions animate the position, - which is not possible when anchors are applied. Notice that this - only applies to the root of the item. Using anchors for its children - works as expected. - - \section1 Item Ownership - - StackView only takes ownership of items that it creates itself. This means - that any item pushed onto a StackView will never be destroyed by the - StackView; only items that StackView creates from \l {Component}{Components} - or \l [QML] {url}{URLs} are destroyed by the StackView. To illustrate this, - the messages in the example below will only be printed when the StackView - is destroyed, not when the items are popped off the stack: - - \qml - Component { - id: itemComponent - - Item { - Component.onDestruction: print("Destroying second item") - } - } - - StackView { - initialItem: Item { - Component.onDestruction: print("Destroying initial item") - } - - Component.onCompleted: push(itemComponent.createObject(window)) - } - \endqml - - However, both of the items created from the URL and Component in the - following example will be destroyed by the StackView when they are popped - off of it: - - \qml - Component { - id: itemComponent - - Item { - Component.onDestruction: print("Destroying second item") - } - } - - StackView { - initialItem: "Item1.qml" - - Component.onCompleted: push(itemComponent) - } - \endqml - - \section1 Size - - StackView does not inherit an implicit size from items that are pushed onto - it. This means that using it as the \l {Popup::}{contentItem} of a - \l Dialog, for example, will not work as expected: - - \code - Dialog { - StackView { - initialItem: Rectangle { - width: 200 - height: 200 - color: "salmon" - } - } - } - \endcode - - There are several ways to ensure that StackView has a size in this - situation: - - \list - \li Set \l[QtQuick]{Item::}{implicitWidth} and - \l[QtQuick]{Item::}{implicitHeight} on the StackView itself. - \li Set \l[QtQuick]{Item::}{implicitWidth} and - \l[QtQuick]{Item::}{implicitHeight} on the \l Rectangle. - \li Set \l {Popup::}{contentWidth} and \l {Popup::}{contentHeight} on - the Dialog. - \li Give the Dialog a size. - \endlist - - \sa {Customizing StackView}, {Navigation Controls}, {Container Controls}, - {Focus Management in Qt Quick Controls} -*/ - -QQuickStackView::QQuickStackView(QQuickItem *parent) - : QQuickControl(*(new QQuickStackViewPrivate), parent) -{ - setFlag(ItemIsFocusScope); -} - -QQuickStackView::~QQuickStackView() -{ - Q_D(QQuickStackView); - if (d->transitioner) { - d->transitioner->setChangeListener(nullptr); - delete d->transitioner; - } - qDeleteAll(d->removing); - qDeleteAll(d->removed); - qDeleteAll(d->elements); -} - -QQuickStackViewAttached *QQuickStackView::qmlAttachedProperties(QObject *object) -{ - return new QQuickStackViewAttached(object); -} - -/*! - \qmlproperty bool QtQuick.Controls::StackView::busy - \readonly - This property holds whether a transition is running. -*/ -bool QQuickStackView::isBusy() const -{ - Q_D(const QQuickStackView); - return d->busy; -} - -/*! - \qmlproperty int QtQuick.Controls::StackView::depth - \readonly - This property holds the number of items currently pushed onto the stack. -*/ -int QQuickStackView::depth() const -{ - Q_D(const QQuickStackView); - return d->elements.count(); -} - -/*! - \qmlproperty Item QtQuick.Controls::StackView::currentItem - \readonly - This property holds the current top-most item in the stack. -*/ -QQuickItem *QQuickStackView::currentItem() const -{ - Q_D(const QQuickStackView); - return d->currentItem; -} - -/*! - \qmlmethod Item QtQuick.Controls::StackView::get(index, behavior) - - Returns the item at position \a index in the stack, or \c null if the index - is out of bounds. - - Supported \a behavior values: - \value StackView.DontLoad The item is not forced to load (and \c null is returned if not yet loaded). - \value StackView.ForceLoad The item is forced to load. -*/ -QQuickItem *QQuickStackView::get(int index, LoadBehavior behavior) -{ - Q_D(QQuickStackView); - QQuickStackElement *element = d->elements.value(index); - if (element) { - if (behavior == ForceLoad) - element->load(this); - return element->item; - } - return nullptr; -} - -/*! - \qmlmethod Item QtQuick.Controls::StackView::find(callback, behavior) - - Search for a specific item inside the stack. The \a callback function is called - for each item in the stack (with the item and index as arguments) until the callback - function returns \c true. The return value is the item found. For example: - - \code - stackView.find(function(item, index) { - return item.isTheOne - }) - \endcode - - Supported \a behavior values: - \value StackView.DontLoad Unloaded items are skipped (the callback function is not called for them). - \value StackView.ForceLoad Unloaded items are forced to load. -*/ -QQuickItem *QQuickStackView::find(const QJSValue &callback, LoadBehavior behavior) -{ - Q_D(QQuickStackView); - QJSValue func(callback); - QQmlEngine *engine = qmlEngine(this); - if (!engine || !func.isCallable()) // TODO: warning? - return nullptr; - - for (int i = d->elements.count() - 1; i >= 0; --i) { - QQuickStackElement *element = d->elements.at(i); - if (behavior == ForceLoad) - element->load(this); - if (element->item) { - QJSValue rv = func.call(QJSValueList() << engine->newQObject(element->item) << i); - if (rv.toBool()) - return element->item; - } - } - - return nullptr; -} - -/*! - \qmlmethod Item QtQuick.Controls::StackView::push(item, properties, operation) - - Pushes an \a item onto the stack using an optional \a operation, and - optionally applies a set of \a properties on the item. The item can be - an \l Item, \l Component, or a \l [QML] url. Returns the item that became - current. - - StackView creates an instance automatically if the pushed item is a \l Component, - or a \l [QML] url, and the instance will be destroyed when it is popped - off the stack. See \l {Item Ownership} for more information. - - The optional \a properties argument specifies a map of initial - property values for the pushed item. For dynamically created items, these values - are applied before the creation is finalized. This is more efficient than setting - property values after creation, particularly where large sets of property values - are defined, and also allows property bindings to be set up (using \l{Qt::binding} - {Qt.binding()}) before the item is created. - - Pushing a single item: - \code - stackView.push(rect) - - // or with properties: - stackView.push(rect, {"color": "red"}) - \endcode - - Multiple items can be pushed at the same time either by passing them as - additional arguments, or as an array. The last item becomes the current - item. Each item can be followed by a set of properties to apply. - - Passing a variable amount of arguments: - \code - stackView.push(rect1, rect2, rect3) - - // or with properties: - stackView.push(rect1, {"color": "red"}, rect2, {"color": "green"}, rect3, {"color": "blue"}) - \endcode - - Pushing an array of items: - \code - stackView.push([rect1, rect2, rect3]) - - // or with properties: - stackView.push([rect1, {"color": "red"}, rect2, {"color": "green"}, rect3, {"color": "blue"}]) - \endcode - - An \a operation can be optionally specified as the last argument. Supported - operations: - - \value StackView.Immediate An immediate operation without transitions. - \value StackView.PushTransition An operation with push transitions (since QtQuick.Controls 2.1). - \value StackView.ReplaceTransition An operation with replace transitions (since QtQuick.Controls 2.1). - \value StackView.PopTransition An operation with pop transitions (since QtQuick.Controls 2.1). - - If no operation is provided, \c PushTransition will be used. - - \note Items that already exist in the stack are not pushed. - - \sa initialItem, {Pushing Items} -*/ -void QQuickStackView::push(QQmlV4Function *args) -{ - Q_D(QQuickStackView); - const QString operationName = QStringLiteral("push"); - if (d->modifyingElements) { - d->warnOfInterruption(operationName); - return; - } - - QScopedValueRollback<bool> modifyingElements(d->modifyingElements, true); - QScopedValueRollback<QString> operationNameRollback(d->operation, operationName); - if (args->length() <= 0) { - d->warn(QStringLiteral("missing arguments")); - args->setReturnValue(QV4::Encode::null()); - return; - } - - QV4::ExecutionEngine *v4 = args->v4engine(); - QV4::Scope scope(v4); - - Operation operation = d->elements.isEmpty() ? Immediate : PushTransition; - QV4::ScopedValue lastArg(scope, (*args)[args->length() - 1]); - if (lastArg->isInt32()) - operation = static_cast<Operation>(lastArg->toInt32()); - - QStringList errors; - QList<QQuickStackElement *> elements = d->parseElements(0, args, &errors); - // Remove any items that are already in the stack, as they can't be in two places at once. - for (int i = 0; i < elements.size(); ) { - QQuickStackElement *element = elements.at(i); - if (element->item && d->findElement(element->item)) - elements.removeAt(i); - else - ++i; - } - - if (!errors.isEmpty() || elements.isEmpty()) { - if (!errors.isEmpty()) { - for (const QString &error : qAsConst(errors)) - d->warn(error); - } else { - d->warn(QStringLiteral("nothing to push")); - } - args->setReturnValue(QV4::Encode::null()); - return; - } - - QQuickStackElement *exit = nullptr; - if (!d->elements.isEmpty()) - exit = d->elements.top(); - - int oldDepth = d->elements.count(); - if (d->pushElements(elements)) { - d->depthChange(d->elements.count(), oldDepth); - QQuickStackElement *enter = d->elements.top(); - d->startTransition(QQuickStackTransition::pushEnter(operation, enter, this), - QQuickStackTransition::pushExit(operation, exit, this), - operation == Immediate); - d->setCurrentItem(enter); - } - - if (d->currentItem) { - QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(v4, d->currentItem)); - args->setReturnValue(rv->asReturnedValue()); - } else { - args->setReturnValue(QV4::Encode::null()); - } -} - -/*! - \qmlmethod Item QtQuick.Controls::StackView::pop(item, operation) - - Pops one or more items off the stack. Returns the last item removed from the stack. - - If the \a item argument is specified, all items down to (but not - including) \a item will be popped. If \a item is \c null, all - items down to (but not including) the first item is popped. - If not specified, only the current item is popped. - - \note A pop() operation on a stack with depth 1 or 0 does nothing. In such - cases, the stack can be emptied using the \l clear() method. - - \include qquickstackview.qdocinc pop-ownership - - An \a operation can be optionally specified as the last argument. Supported - operations: - - \value StackView.Immediate An immediate operation without transitions. - \value StackView.PushTransition An operation with push transitions (since QtQuick.Controls 2.1). - \value StackView.ReplaceTransition An operation with replace transitions (since QtQuick.Controls 2.1). - \value StackView.PopTransition An operation with pop transitions (since QtQuick.Controls 2.1). - - If no operation is provided, \c PopTransition will be used. - - Examples: - \code - stackView.pop() - stackView.pop(someItem, StackView.Immediate) - stackView.pop(StackView.Immediate) - stackView.pop(null) - \endcode - - \sa clear(), {Popping Items}, {Unwinding Items via Pop} -*/ -void QQuickStackView::pop(QQmlV4Function *args) -{ - Q_D(QQuickStackView); - const QString operationName = QStringLiteral("pop"); - if (d->modifyingElements) { - d->warnOfInterruption(operationName); - args->setReturnValue(QV4::Encode::null()); - return; - } - - QScopedValueRollback<bool> modifyingElements(d->modifyingElements, true); - QScopedValueRollback<QString> operationNameRollback(d->operation, operationName); - int argc = args->length(); - if (d->elements.count() <= 1 || argc > 2) { - if (argc > 2) - d->warn(QStringLiteral("too many arguments")); - args->setReturnValue(QV4::Encode::null()); - return; - } - - int oldDepth = d->elements.count(); - QQuickStackElement *exit = d->elements.pop(); - QQuickStackElement *enter = d->elements.top(); - - QV4::ExecutionEngine *v4 = args->v4engine(); - QV4::Scope scope(v4); - - if (argc > 0) { - QV4::ScopedValue value(scope, (*args)[0]); - if (value->isNull()) { - enter = d->elements.value(0); - } else if (const QV4::QObjectWrapper *o = value->as<QV4::QObjectWrapper>()) { - QQuickItem *item = qobject_cast<QQuickItem *>(o->object()); - enter = d->findElement(item); - if (!enter) { - if (item != d->currentItem) - d->warn(QStringLiteral("unknown argument: ") + value->toQString()); // TODO: safe? - args->setReturnValue(QV4::Encode::null()); - d->elements.push(exit); // restore - return; - } - } - } - - Operation operation = PopTransition; - if (argc > 0) { - QV4::ScopedValue lastArg(scope, (*args)[argc - 1]); - if (lastArg->isInt32()) - operation = static_cast<Operation>(lastArg->toInt32()); - } - - QQuickItem *previousItem = nullptr; - - if (d->popElements(enter)) { - if (exit) { - exit->removal = true; - d->removing.insert(exit); - previousItem = exit->item; - } - d->depthChange(d->elements.count(), oldDepth); - d->startTransition(QQuickStackTransition::popExit(operation, exit, this), - QQuickStackTransition::popEnter(operation, enter, this), - operation == Immediate); - d->setCurrentItem(enter); - } - - if (previousItem) { - QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(v4, previousItem)); - args->setReturnValue(rv->asReturnedValue()); - } else { - args->setReturnValue(QV4::Encode::null()); - } -} - -/*! - \qmlmethod Item QtQuick.Controls::StackView::replace(target, item, properties, operation) - - Replaces one or more items on the stack with the specified \a item and - optional \a operation, and optionally applies a set of \a properties on the - item. The item can be an \l Item, \l Component, or a \l [QML] url. - Returns the item that became current. - - \include qquickstackview.qdocinc pop-ownership - - If the \a target argument is specified, all items down to the \target - item will be replaced. If \a target is \c null, all items in the stack - will be replaced. If not specified, only the top item will be replaced. - - StackView creates an instance automatically if the replacing item is a \l Component, - or a \l [QML] url. The optional \a properties argument specifies a map of initial - property values for the replacing item. For dynamically created items, these values - are applied before the creation is finalized. This is more efficient than setting - property values after creation, particularly where large sets of property values - are defined, and also allows property bindings to be set up (using \l{Qt::binding} - {Qt.binding()}) before the item is created. - - Replace the top item: - \code - stackView.replace(rect) - - // or with properties: - stackView.replace(rect, {"color": "red"}) - \endcode - - Multiple items can be replaced at the same time either by passing them as - additional arguments, or as an array. Each item can be followed by a set - of properties to apply. - - Passing a variable amount of arguments: - \code - stackView.replace(rect1, rect2, rect3) - - // or with properties: - stackView.replace(rect1, {"color": "red"}, rect2, {"color": "green"}, rect3, {"color": "blue"}) - \endcode - - Replacing an array of items: - \code - stackView.replace([rect1, rect2, rect3]) - - // or with properties: - stackView.replace([rect1, {"color": "red"}, rect2, {"color": "green"}, rect3, {"color": "blue"}]) - \endcode - - An \a operation can be optionally specified as the last argument. Supported - operations: - - \value StackView.Immediate An immediate operation without transitions. - \value StackView.PushTransition An operation with push transitions (since QtQuick.Controls 2.1). - \value StackView.ReplaceTransition An operation with replace transitions (since QtQuick.Controls 2.1). - \value StackView.PopTransition An operation with pop transitions (since QtQuick.Controls 2.1). - - If no operation is provided, \c ReplaceTransition will be used. - - The following example illustrates the use of push and pop transitions with replace(). - - \code - StackView { - id: stackView - - initialItem: Component { - id: page - - Page { - Row { - spacing: 20 - anchors.centerIn: parent - - Button { - text: "<" - onClicked: stackView.replace(page, StackView.PopTransition) - } - Button { - text: ">" - onClicked: stackView.replace(page, StackView.PushTransition) - } - } - } - } - } - \endcode - - \sa push(), {Replacing Items} -*/ -void QQuickStackView::replace(QQmlV4Function *args) -{ - Q_D(QQuickStackView); - const QString operationName = QStringLiteral("replace"); - if (d->modifyingElements) { - d->warnOfInterruption(operationName); - args->setReturnValue(QV4::Encode::null()); - return; - } - - QScopedValueRollback<bool> modifyingElements(d->modifyingElements, true); - QScopedValueRollback<QString> operationNameRollback(d->operation, operationName); - if (args->length() <= 0) { - d->warn(QStringLiteral("missing arguments")); - args->setReturnValue(QV4::Encode::null()); - return; - } - - QV4::ExecutionEngine *v4 = args->v4engine(); - QV4::Scope scope(v4); - - Operation operation = d->elements.isEmpty() ? Immediate : ReplaceTransition; - QV4::ScopedValue lastArg(scope, (*args)[args->length() - 1]); - if (lastArg->isInt32()) - operation = static_cast<Operation>(lastArg->toInt32()); - - QQuickStackElement *target = nullptr; - QV4::ScopedValue firstArg(scope, (*args)[0]); - if (firstArg->isNull()) - target = d->elements.value(0); - else if (!firstArg->isInt32()) - target = d->findElement(firstArg); - - QStringList errors; - QList<QQuickStackElement *> elements = d->parseElements(target ? 1 : 0, args, &errors); - if (!errors.isEmpty() || elements.isEmpty()) { - if (!errors.isEmpty()) { - for (const QString &error : qAsConst(errors)) - d->warn(error); - } else { - d->warn(QStringLiteral("nothing to push")); - } - args->setReturnValue(QV4::Encode::null()); - return; - } - - int oldDepth = d->elements.count(); - QQuickStackElement* exit = nullptr; - if (!d->elements.isEmpty()) - exit = d->elements.pop(); - - if (exit != target ? d->replaceElements(target, elements) : d->pushElements(elements)) { - d->depthChange(d->elements.count(), oldDepth); - if (exit) { - exit->removal = true; - d->removing.insert(exit); - } - QQuickStackElement *enter = d->elements.top(); - d->startTransition(QQuickStackTransition::replaceExit(operation, exit, this), - QQuickStackTransition::replaceEnter(operation, enter, this), - operation == Immediate); - d->setCurrentItem(enter); - } - - if (d->currentItem) { - QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(v4, d->currentItem)); - args->setReturnValue(rv->asReturnedValue()); - } else { - args->setReturnValue(QV4::Encode::null()); - } -} - -/*! - \since QtQuick.Controls 2.3 (Qt 5.10) - \qmlproperty bool QtQuick.Controls::StackView::empty - \readonly - - This property holds whether the stack is empty. - - \sa depth -*/ -bool QQuickStackView::isEmpty() const -{ - Q_D(const QQuickStackView); - return d->elements.isEmpty(); -} - -/*! - \qmlmethod void QtQuick.Controls::StackView::clear(transition) - - Removes all items from the stack. - - \include qquickstackview.qdocinc pop-ownership - - Since QtQuick.Controls 2.3, a \a transition can be optionally specified. Supported transitions: - - \value StackView.Immediate Clear the stack immediately without any transition (default). - \value StackView.PushTransition Clear the stack with a push transition. - \value StackView.ReplaceTransition Clear the stack with a replace transition. - \value StackView.PopTransition Clear the stack with a pop transition. -*/ -void QQuickStackView::clear(Operation operation) -{ - Q_D(QQuickStackView); - if (d->elements.isEmpty()) - return; - - const QString operationName = QStringLiteral("clear"); - if (d->modifyingElements) { - d->warnOfInterruption(operationName); - return; - } - - QScopedValueRollback<bool> modifyingElements(d->modifyingElements, true); - QScopedValueRollback<QString> operationNameRollback(d->operation, operationName); - if (operation != Immediate) { - QQuickStackElement *exit = d->elements.pop(); - exit->removal = true; - d->removing.insert(exit); - d->startTransition(QQuickStackTransition::popExit(operation, exit, this), - QQuickStackTransition::popEnter(operation, nullptr, this), false); - } - - int oldDepth = d->elements.count(); - d->setCurrentItem(nullptr); - qDeleteAll(d->elements); - d->elements.clear(); - d->depthChange(0, oldDepth); -} - -/*! - \qmlproperty var QtQuick.Controls::StackView::initialItem - - This property holds the initial item that should be shown when the StackView - is created. The initial item can be an \l Item, \l Component, or a \l [QML] url. - Specifying an initial item is equivalent to: - \code - Component.onCompleted: stackView.push(myInitialItem) - \endcode - - \sa push() -*/ -QJSValue QQuickStackView::initialItem() const -{ - Q_D(const QQuickStackView); - return d->initialItem; -} - -void QQuickStackView::setInitialItem(const QJSValue &item) -{ - Q_D(QQuickStackView); - d->initialItem = item; -} - -/*! - \qmlproperty Transition QtQuick.Controls::StackView::popEnter - - This property holds the transition that is applied to the item that - enters the stack when another item is popped off of it. - - \sa {Customizing StackView} -*/ -QQuickTransition *QQuickStackView::popEnter() const -{ - Q_D(const QQuickStackView); - if (d->transitioner) - return d->transitioner->removeDisplacedTransition; - return nullptr; -} - -void QQuickStackView::setPopEnter(QQuickTransition *enter) -{ - Q_D(QQuickStackView); - d->ensureTransitioner(); - if (d->transitioner->removeDisplacedTransition == enter) - return; - - d->transitioner->removeDisplacedTransition = enter; - emit popEnterChanged(); -} - -/*! - \qmlproperty Transition QtQuick.Controls::StackView::popExit - - This property holds the transition that is applied to the item that - exits the stack when the item is popped off of it. - - \sa {Customizing StackView} -*/ -QQuickTransition *QQuickStackView::popExit() const -{ - Q_D(const QQuickStackView); - if (d->transitioner) - return d->transitioner->removeTransition; - return nullptr; -} - -void QQuickStackView::setPopExit(QQuickTransition *exit) -{ - Q_D(QQuickStackView); - d->ensureTransitioner(); - if (d->transitioner->removeTransition == exit) - return; - - d->transitioner->removeTransition = exit; - emit popExitChanged(); -} - -/*! - \qmlproperty Transition QtQuick.Controls::StackView::pushEnter - - This property holds the transition that is applied to the item that - enters the stack when the item is pushed onto it. - - \sa {Customizing StackView} -*/ -QQuickTransition *QQuickStackView::pushEnter() const -{ - Q_D(const QQuickStackView); - if (d->transitioner) - return d->transitioner->addTransition; - return nullptr; -} - -void QQuickStackView::setPushEnter(QQuickTransition *enter) -{ - Q_D(QQuickStackView); - d->ensureTransitioner(); - if (d->transitioner->addTransition == enter) - return; - - d->transitioner->addTransition = enter; - emit pushEnterChanged(); -} - -/*! - \qmlproperty Transition QtQuick.Controls::StackView::pushExit - - This property holds the transition that is applied to the item that - exits the stack when another item is pushed onto it. - - \sa {Customizing StackView} -*/ -QQuickTransition *QQuickStackView::pushExit() const -{ - Q_D(const QQuickStackView); - if (d->transitioner) - return d->transitioner->addDisplacedTransition; - return nullptr; -} - -void QQuickStackView::setPushExit(QQuickTransition *exit) -{ - Q_D(QQuickStackView); - d->ensureTransitioner(); - if (d->transitioner->addDisplacedTransition == exit) - return; - - d->transitioner->addDisplacedTransition = exit; - emit pushExitChanged(); -} - -/*! - \qmlproperty Transition QtQuick.Controls::StackView::replaceEnter - - This property holds the transition that is applied to the item that - enters the stack when another item is replaced by it. - - \sa {Customizing StackView} -*/ -QQuickTransition *QQuickStackView::replaceEnter() const -{ - Q_D(const QQuickStackView); - if (d->transitioner) - return d->transitioner->moveTransition; - return nullptr; -} - -void QQuickStackView::setReplaceEnter(QQuickTransition *enter) -{ - Q_D(QQuickStackView); - d->ensureTransitioner(); - if (d->transitioner->moveTransition == enter) - return; - - d->transitioner->moveTransition = enter; - emit replaceEnterChanged(); -} - -/*! - \qmlproperty Transition QtQuick.Controls::StackView::replaceExit - - This property holds the transition that is applied to the item that - exits the stack when it is replaced by another item. - - \sa {Customizing StackView} -*/ -QQuickTransition *QQuickStackView::replaceExit() const -{ - Q_D(const QQuickStackView); - if (d->transitioner) - return d->transitioner->moveDisplacedTransition; - return nullptr; -} - -void QQuickStackView::setReplaceExit(QQuickTransition *exit) -{ - Q_D(QQuickStackView); - d->ensureTransitioner(); - if (d->transitioner->moveDisplacedTransition == exit) - return; - - d->transitioner->moveDisplacedTransition = exit; - emit replaceExitChanged(); -} - -void QQuickStackView::componentComplete() -{ - QQuickControl::componentComplete(); - - Q_D(QQuickStackView); - QScopedValueRollback<QString> operationNameRollback(d->operation, QStringLiteral("initialItem")); - QQuickStackElement *element = nullptr; - QString error; - int oldDepth = d->elements.count(); - if (QObject *o = d->initialItem.toQObject()) - element = QQuickStackElement::fromObject(o, this, &error); - else if (d->initialItem.isString()) - element = QQuickStackElement::fromString(d->initialItem.toString(), this, &error); - if (!error.isEmpty()) { - d->warn(error); - delete element; - } else if (d->pushElement(element)) { - d->depthChange(d->elements.count(), oldDepth); - d->setCurrentItem(element); - element->setStatus(QQuickStackView::Active); - } -} - -void QQuickStackView::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) -{ - QQuickControl::geometryChange(newGeometry, oldGeometry); - - Q_D(QQuickStackView); - for (QQuickStackElement *element : qAsConst(d->elements)) { - if (element->item) { - if (!element->widthValid) - element->item->setWidth(newGeometry.width()); - if (!element->heightValid) - element->item->setHeight(newGeometry.height()); - } - } -} - -bool QQuickStackView::childMouseEventFilter(QQuickItem *item, QEvent *event) -{ - // in order to block accidental user interaction while busy/transitioning, - // StackView filters out childrens' mouse events. therefore we block all - // press events. however, since push() may be called from signal handlers - // such as onPressed or onDoubleClicked, we must let the current mouse - // grabber item receive the respective mouse release event to avoid - // breaking its state (QTBUG-50305). - if (event->type() == QEvent::MouseButtonPress) - return true; - if (event->type() == QEvent::UngrabMouse) - return false; - QQuickWindow *window = item->window(); - return window && !window->mouseGrabberItem(); -} - -#if QT_CONFIG(quicktemplates2_multitouch) -void QQuickStackView::touchEvent(QTouchEvent *event) -{ - event->ignore(); // QTBUG-65084 -} -#endif - -#if QT_CONFIG(accessibility) -QAccessible::Role QQuickStackView::accessibleRole() const -{ - return QAccessible::LayeredPane; -} -#endif - -void QQuickStackViewAttachedPrivate::itemParentChanged(QQuickItem *item, QQuickItem *parent) -{ - Q_Q(QQuickStackViewAttached); - int oldIndex = element ? element->index : -1; - QQuickStackView *oldView = element ? element->view : nullptr; - QQuickStackView::Status oldStatus = element ? element->status : QQuickStackView::Inactive; - - QQuickStackView *newView = qobject_cast<QQuickStackView *>(parent); - element = newView ? QQuickStackViewPrivate::get(newView)->findElement(item) : nullptr; - - int newIndex = element ? element->index : -1; - QQuickStackView::Status newStatus = element ? element->status : QQuickStackView::Inactive; - - if (oldIndex != newIndex) - emit q->indexChanged(); - if (oldView != newView) - emit q->viewChanged(); - if (oldStatus != newStatus) - emit q->statusChanged(); -} - -QQuickStackViewAttached::QQuickStackViewAttached(QObject *parent) - : QObject(*(new QQuickStackViewAttachedPrivate), 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) { - qmlWarning(parent) << "StackView must be attached to an Item"; - } -} - -QQuickStackViewAttached::~QQuickStackViewAttached() -{ - Q_D(QQuickStackViewAttached); - QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); - if (parentItem) - QQuickItemPrivate::get(parentItem)->removeItemChangeListener(d, QQuickItemPrivate::Parent); -} - -/*! - \qmlattachedproperty int QtQuick.Controls::StackView::index - \readonly - - This attached property holds the stack index of the item it's - attached to, or \c -1 if the item is not in a stack. -*/ -int QQuickStackViewAttached::index() const -{ - Q_D(const QQuickStackViewAttached); - return d->element ? d->element->index : -1; -} - -/*! - \qmlattachedproperty StackView QtQuick.Controls::StackView::view - \readonly - - This attached property holds the stack view of the item it's - attached to, or \c null if the item is not in a stack. -*/ -QQuickStackView *QQuickStackViewAttached::view() const -{ - Q_D(const QQuickStackViewAttached); - return d->element ? d->element->view : nullptr; -} - -/*! - \qmlattachedproperty enumeration QtQuick.Controls::StackView::status - \readonly - - This attached property holds the stack status of the item it's - attached to, or \c StackView.Inactive if the item is not in a stack. - - Available values: - \value StackView.Inactive The item is inactive (or not in a stack). - \value StackView.Deactivating The item is being deactivated (popped off). - \value StackView.Activating The item is being activated (becoming the current item). - \value StackView.Active The item is active, that is, the current item. -*/ -QQuickStackView::Status QQuickStackViewAttached::status() const -{ - Q_D(const QQuickStackViewAttached); - return d->element ? d->element->status : QQuickStackView::Inactive; -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \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 (Qt 5.8) - - This attached signal is emitted when the item it's attached to is activated in the stack. - - \sa status -*/ - -/*! - \qmlattachedsignal QtQuick.Controls::StackView::deactivated() - \since QtQuick.Controls 2.1 (Qt 5.8) - - This attached signal is emitted when the item it's attached to is deactivated in the stack. - - \sa status -*/ - -/*! - \qmlattachedsignal QtQuick.Controls::StackView::activating() - \since QtQuick.Controls 2.1 (Qt 5.8) - - This attached signal is emitted when the item it's attached to is in the process of being - activated in the stack. - - \sa status -*/ - -/*! - \qmlattachedsignal QtQuick.Controls::StackView::deactivating() - \since QtQuick.Controls 2.1 (Qt 5.8) - - This attached signal is emitted when the item it's attached to is in the process of being - dectivated in the stack. - - \sa status -*/ - -/*! - \qmlattachedsignal QtQuick.Controls::StackView::removed() - \since QtQuick.Controls 2.1 (Qt 5.8) - - This attached signal is emitted when the item it's attached to has been - removed from the stack. It can be used to safely destroy an Item that was - pushed onto the stack, for example: - - \code - Item { - StackView.onRemoved: destroy() // Will be destroyed sometime after this call. - } - \endcode - - \sa status -*/ - -QT_END_NAMESPACE - -#include "moc_qquickstackview_p.cpp" |