diff options
Diffstat (limited to 'src/controls')
-rw-r--r-- | src/controls/controls.pri | 2 | ||||
-rw-r--r-- | src/controls/qquickabstractstackview.cpp | 565 | ||||
-rw-r--r-- | src/controls/qquickabstractstackview_p.cpp | 507 | ||||
-rw-r--r-- | src/controls/qquickabstractstackview_p.h | 84 | ||||
-rw-r--r-- | src/controls/qquickabstractstackview_p_p.h | 158 |
5 files changed, 1108 insertions, 208 deletions
diff --git a/src/controls/controls.pri b/src/controls/controls.pri index b1d2a0ea..aea9b06f 100644 --- a/src/controls/controls.pri +++ b/src/controls/controls.pri @@ -20,6 +20,7 @@ HEADERS += \ $$PWD/qquickabstractscrollindicator_p.h \ $$PWD/qquickabstractslider_p.h \ $$PWD/qquickabstractstackview_p.h \ + $$PWD/qquickabstractstackview_p_p.h \ $$PWD/qquickabstractswitch_p.h \ $$PWD/qquickabstracttabbar_p.h \ $$PWD/qquickabstracttabbutton_p.h \ @@ -49,6 +50,7 @@ SOURCES += \ $$PWD/qquickabstractscrollindicator.cpp \ $$PWD/qquickabstractslider.cpp \ $$PWD/qquickabstractstackview.cpp \ + $$PWD/qquickabstractstackview_p.cpp \ $$PWD/qquickabstractswitch.cpp \ $$PWD/qquickabstracttabbar.cpp \ $$PWD/qquickabstracttabbutton.cpp \ diff --git a/src/controls/qquickabstractstackview.cpp b/src/controls/qquickabstractstackview.cpp index a849bd94..e5496697 100644 --- a/src/controls/qquickabstractstackview.cpp +++ b/src/controls/qquickabstractstackview.cpp @@ -35,7 +35,10 @@ ****************************************************************************/ #include "qquickabstractstackview_p.h" -#include "qquickabstractcontainer_p_p.h" +#include "qquickabstractstackview_p_p.h" + +#include <QtQml/qjsvalue.h> +#include <QtQml/qqmlengine.h> QT_BEGIN_NAMESPACE @@ -50,243 +53,407 @@ QT_BEGIN_NAMESPACE TODO */ -class QQuickStackElement +QQuickAbstractStackView::QQuickAbstractStackView(QQuickItem *parent) : + QQuickAbstractContainer(*(new QQuickAbstractStackViewPrivate), parent) { - QQuickStackElement() : ownItem(false), item(Q_NULLPTR), ownComponent(false), component(Q_NULLPTR) { } - -public: - static QQuickStackElement *fromString(const QString &str, QQmlEngine *engine, QObject *parent) - { - QQuickStackElement *element = new QQuickStackElement; - element->component = new QQmlComponent(engine, QUrl(str), parent); - element->ownComponent = true; - return element; - } + setFlag(ItemIsFocusScope); +} - static QQuickStackElement *fromObject(QObject *object) - { - QQuickStackElement *element = new QQuickStackElement; - element->component = qobject_cast<QQmlComponent *>(object); - element->item = qobject_cast<QQuickItem *>(object); - return element; +QQuickAbstractStackView::~QQuickAbstractStackView() +{ + Q_D(QQuickAbstractStackView); + if (d->transitioner) { + d->transitioner->setChangeListener(Q_NULLPTR); + delete d->transitioner; } + qDeleteAll(d->elements); +} - bool ownItem; - QQuickItem *item; - - bool ownComponent; - QQmlComponent *component; -}; +QQuickStackAttached *QQuickAbstractStackView::qmlAttachedProperties(QObject *object) +{ + QQuickItem *item = qobject_cast<QQuickItem *>(object); + if (!item) { + qmlInfo(object) << "StackView must be attached to an Item"; + return Q_NULLPTR; + } + return new QQuickStackAttached(item); +} -class QQuickAbstractStackViewPrivate : public QQuickAbstractContainerPrivate +/*! + \qmlproperty bool QtQuickControls2::StackView::busy + \readonly + This property holds whether a transition is running. +*/ +bool QQuickAbstractStackView::busy() const { - Q_DECLARE_PUBLIC(QQuickAbstractStackView) + Q_D(const QQuickAbstractStackView); + return d->transitioner && !d->transitioner->runningJobs.isEmpty(); +} -public: - QQuickAbstractStackViewPrivate() : busy(false), depth(0), currentItem(Q_NULLPTR) { } +/*! + \qmlproperty int QtQuickControls2::StackView::depth + \readonly + This property holds the number of items currently pushed onto the stack. +*/ +int QQuickAbstractStackView::depth() const +{ + Q_D(const QQuickAbstractStackView); + return d->elements.count(); +} - void setBusy(bool busy); - void setDepth(int depth); - void setCurrentItem(QQuickItem *item); +/*! + \qmlproperty Item QtQuickControls2::StackView::currentItem + \readonly + This property holds the current top-most item in the stack. +*/ +QQuickItem *QQuickAbstractStackView::currentItem() const +{ + Q_D(const QQuickAbstractStackView); + return d->currentItem; +} - QList<QQuickStackElement *> createElements(const QV4::ScopedValue &value); - QQuickItem *pushElements(const QList<QQuickStackElement *> &elements, QQuickAbstractStackView::Operation operation); +/*! + \qmlmethod Item QtQuickControls2::StackView::get(index, behavior = DontLoad) - bool busy; - int depth; - QVariant initialItem; - QQuickItem *currentItem; - QStack<QQuickStackElement *> elements; -}; + Supported behavior values: + \li StackView.DontLoad + \li StackView.ForceLoad -void QQuickAbstractStackViewPrivate::setBusy(bool value) + TODO +*/ +QQuickItem *QQuickAbstractStackView::get(int index, LoadBehavior behavior) { - Q_Q(QQuickAbstractStackView); - if (busy != value) { - busy = value; - emit q->busyChanged(); + Q_D(QQuickAbstractStackView); + QQuickStackElement *element = d->elements.value(index); + if (element) { + if (behavior == ForceLoad) + element->load(this); + return element->item; } + return Q_NULLPTR; } -void QQuickAbstractStackViewPrivate::setDepth(int value) +/*! + \qmlmethod Item QtQuickControls2::StackView::find(callback, behavior = DontLoad) + + Supported behavior values: + \li StackView.DontLoad + \li StackView.ForceLoad + + TODO +*/ +QQuickItem *QQuickAbstractStackView::find(const QJSValue &callback, LoadBehavior behavior) { - Q_Q(QQuickAbstractStackView); - if (depth != value) { - depth = value; - emit q->depthChanged(); + Q_D(QQuickAbstractStackView); + QJSValue func(callback); + QQmlEngine *engine = qmlEngine(this); + if (!engine || !func.isCallable()) // TODO: warning? + return Q_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 Q_NULLPTR; } -void QQuickAbstractStackViewPrivate::setCurrentItem(QQuickItem *item) +/*! + \qmlmethod Item QtQuickControls2::StackView::push(item, properties, operation) + + TODO +*/ +void QQuickAbstractStackView::push(QQmlV4Function *args) { - Q_Q(QQuickAbstractStackView); - if (currentItem != item) { - currentItem = item; - emit q->currentItemChanged(); + Q_D(QQuickAbstractStackView); + if (args->length() <= 0) { + qmlInfo(this) << "push: missing arguments"; + args->setReturnValue(QV4::Encode::null()); + return; } -} -QList<QQuickStackElement *> QQuickAbstractStackViewPrivate::createElements(const QV4::ScopedValue &value) -{ - Q_Q(QQuickAbstractStackView); - QList<QQuickStackElement *> elements; - if (QV4::String *s = value->asString()) { - qDebug() << "### STRING:" << s->toQString(); - elements += QQuickStackElement::fromString(s->toQString(), qmlEngine(q), q); - } else if (QV4::ArrayObject *a = value->asArrayObject()) { - int len = a->getLength(); - qDebug() << "### ARRAY:" << len; - for (int i = 0; i < len; ++i) { - QV4::Scope scope(a->engine()); - QV4::ScopedValue v(scope, a->getIndexed(i)); - elements += createElements(v); - } - } else if (const QV4::QObjectWrapper *o =value->as<QV4::QObjectWrapper>()) { - qDebug() << "### QOBJECT:" << o->object(); - elements += QQuickStackElement::fromObject(o->object()); + QV4::ExecutionEngine *v4 = args->v4engine(); + QV4::Scope scope(v4); + + Operation operation = d->elements.isEmpty() ? Immediate : Transition; + QV4::ScopedValue lastArg(scope, (*args)[args->length() - 1]); + if (lastArg->isInt32()) + operation = static_cast<Operation>(lastArg->toInt32()); + + QList<QQuickStackElement *> elements = d->parseElements(args); + if (elements.isEmpty()) { + qmlInfo(this) << "push: nothing to push"; + args->setReturnValue(QV4::Encode::null()); + return; + } + + QQuickStackElement *exit = Q_NULLPTR; + if (!d->elements.isEmpty()) + exit = d->elements.top(); + + if (d->pushElements(elements)) { + emit depthChanged(); + QQuickStackElement *enter = d->elements.top(); + d->pushTransition(enter, exit, boundingRect(), operation == Immediate); + d->setCurrentItem(enter->item); + } + + if (d->currentItem) { + QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(v4, d->currentItem)); + args->setReturnValue(rv->asReturnedValue()); } else { - qDebug("### UNKNOWN"); + args->setReturnValue(QV4::Encode::null()); } - return elements; } -QQuickItem *QQuickAbstractStackViewPrivate::pushElements(const QList<QQuickStackElement *> &elems, QQuickAbstractStackView::Operation operation) +/*! + \qmlmethod Item QtQuickControls2::StackView::pop(item = null, operation = Transition) + + TODO +*/ +void QQuickAbstractStackView::pop(QQmlV4Function *args) { - Q_Q(QQuickAbstractStackView); - Q_UNUSED(operation); // TODO - if (!elems.isEmpty()) { - foreach (QQuickStackElement *elem, elems) { - elements.push(elem); + Q_D(QQuickAbstractStackView); + int argc = args->length(); + if (d->elements.count() <= 1 || argc > 2) { + if (argc > 2) + qmlInfo(this) << "pop: too many arguments"; + args->setReturnValue(QV4::Encode::null()); + return; + } + + 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 (!value->isUndefined() && !value->isInt32()) { + enter = d->findElement(value); + if (!enter) { + qmlInfo(this) << "pop: unknown argument: " << value->toQString(); // TODO: safe? + args->setReturnValue(QV4::Encode::null()); + d->elements.push(exit); // restore + return; + } } - emit q->depthChanged(); - // TODO: load - return elems.last()->item; } - return Q_NULLPTR; + + Operation operation = Transition; + if (argc > 0) { + QV4::ScopedValue lastArg(scope, (*args)[argc - 1]); + if (lastArg->isInt32()) + operation = static_cast<Operation>(lastArg->toInt32()); + } + + QQuickItem *previousItem = Q_NULLPTR; + + if (d->popElements(enter)) { + if (exit) + previousItem = exit->item; + emit depthChanged(); + d->popTransition(enter, exit, boundingRect(), operation == Immediate); + d->setCurrentItem(enter->item); + } + + if (previousItem) { + QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(v4, previousItem)); + args->setReturnValue(rv->asReturnedValue()); + } else { + args->setReturnValue(QV4::Encode::null()); + } } -QQuickAbstractStackView::QQuickAbstractStackView(QQuickItem *parent) : - QQuickAbstractContainer(*(new QQuickAbstractStackViewPrivate), parent) +/*! + \qmlmethod Item QtQuickControls2::StackView::push(item, properties, operation = Transition) + + TODO +*/ +void QQuickAbstractStackView::replace(QQmlV4Function *args) { - setFlag(ItemIsFocusScope); + Q_D(QQuickAbstractStackView); + if (args->length() <= 0) { + qmlInfo(this) << "replace: missing arguments"; + args->setReturnValue(QV4::Encode::null()); + return; + } + + QV4::ExecutionEngine *v4 = args->v4engine(); + QV4::Scope scope(v4); + + Operation operation = d->elements.isEmpty() ? Immediate : Transition; + QV4::ScopedValue lastArg(scope, (*args)[args->length() - 1]); + if (lastArg->isInt32()) + operation = static_cast<Operation>(lastArg->toInt32()); + + QQuickStackElement *target = Q_NULLPTR; + QV4::ScopedValue firstArg(scope, (*args)[0]); + if (firstArg->isNull()) + target = d->elements.value(0); + else if (!firstArg->isInt32()) + target = d->findElement(firstArg); + + QList<QQuickStackElement *> elements = d->parseElements(args, target ? 1 : 0); + if (elements.isEmpty()) { + qmlInfo(this) << "replace: nothing to push"; + args->setReturnValue(QV4::Encode::null()); + return; + } + + int depth = d->elements.count(); + QQuickStackElement* exit = Q_NULLPTR; + if (!d->elements.isEmpty()) + exit = d->elements.pop(); + + if (d->replaceElements(target, elements)) { + if (depth != d->elements.count()) + emit depthChanged(); + QQuickStackElement *enter = d->elements.top(); + d->replaceTransition(enter, exit, boundingRect(), operation == Immediate); + d->setCurrentItem(enter->item); + } + + if (d->currentItem) { + QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(v4, d->currentItem)); + args->setReturnValue(rv->asReturnedValue()); + } else { + args->setReturnValue(QV4::Encode::null()); + } } -QQuickAbstractStackView::~QQuickAbstractStackView() +/*! + \qmlmethod Item QtQuickControls2::StackView::clear() + + TODO +*/ +void QQuickAbstractStackView::clear() { Q_D(QQuickAbstractStackView); + d->setCurrentItem(Q_NULLPTR); qDeleteAll(d->elements); + d->elements.clear(); + emit depthChanged(); } /*! - \qmlproperty bool QtQuickControls2::StackView::busy - \readonly - \c true if a transition is running, and \c false otherwise. + \qmlproperty var QtQuickControls2::StackView::initialItem + + This property holds the initial item. + + \sa push() */ -bool QQuickAbstractStackView::busy() const +QVariant QQuickAbstractStackView::initialItem() const { Q_D(const QQuickAbstractStackView); - return d->busy; + return d->initialItem; } -// TODO: remove -void QQuickAbstractStackView::setBusy(bool busy) +void QQuickAbstractStackView::setInitialItem(const QVariant &item) { Q_D(QQuickAbstractStackView); - d->setBusy(busy); + d->initialItem = item; } /*! - \qmlproperty int QtQuickControls2::StackView::depth - \readonly - The number of items currently pushed onto the stack. + \qmlproperty Transition QtQuickControls2::StackView::popEnter + + TODO */ -int QQuickAbstractStackView::depth() const +QQuickTransition *QQuickAbstractStackView::popEnter() const { Q_D(const QQuickAbstractStackView); - return d->depth; + if (d->transitioner) + return d->transitioner->removeDisplacedTransition; + return Q_NULLPTR; } -// TODO: remove -void QQuickAbstractStackView::setDepth(int depth) +void QQuickAbstractStackView::setPopEnter(QQuickTransition *enter) { Q_D(QQuickAbstractStackView); - d->setDepth(depth); + d->ensureTransitioner(); + if (d->transitioner->removeDisplacedTransition != enter) { + d->transitioner->removeDisplacedTransition = enter; + emit popEnterChanged(); + } } /*! - \qmlproperty Item QtQuickControls2::StackView::currentItem - \readonly - The currently top-most item in the stack. + \qmlproperty Transition QtQuickControls2::StackView::popExit + + TODO */ -QQuickItem *QQuickAbstractStackView::currentItem() const +QQuickTransition *QQuickAbstractStackView::popExit() const { Q_D(const QQuickAbstractStackView); - return d->currentItem; -} - -// TODO: remove -void QQuickAbstractStackView::setCurrentItem(QQuickItem *item) -{ - Q_D(QQuickAbstractStackView); - d->setCurrentItem(item); + if (d->transitioner) + return d->transitioner->removeTransition; + return Q_NULLPTR; } -QQuickItem *QQuickAbstractStackView::qpush(QQmlV4Function *args) +void QQuickAbstractStackView::setPopExit(QQuickTransition *exit) { Q_D(QQuickAbstractStackView); - QV4::ExecutionEngine *v4 = args->v4engine(); - QV4::Scope scope(v4); - - Operation operation = d->elements.isEmpty() ? Immediate : Transition; - QList<QQuickStackElement *> elements; - for (int i = 0; i < args->length(); ++i) { - QV4::ScopedValue value(scope, (*args)[i]); - if (value->isInt32()) - operation = static_cast<Operation>(value->toInt32()); - else - elements += d->createElements(value); + d->ensureTransitioner(); + if (d->transitioner->removeTransition != exit) { + d->transitioner->removeTransition = exit; + emit popExitChanged(); } - return d->pushElements(elements, operation); } -QQuickItem *QQuickAbstractStackView::qpop(QQmlV4Function *args) +/*! + \qmlproperty Transition QtQuickControls2::StackView::pushEnter + + TODO +*/ +QQuickTransition *QQuickAbstractStackView::pushEnter() const { - Q_UNUSED(args); // TODO + Q_D(const QQuickAbstractStackView); + if (d->transitioner) + return d->transitioner->addTransition; return Q_NULLPTR; } -void QQuickAbstractStackView::qclear() +void QQuickAbstractStackView::setPushEnter(QQuickTransition *enter) { - // TODO + Q_D(QQuickAbstractStackView); + d->ensureTransitioner(); + if (d->transitioner->addTransition != enter) { + d->transitioner->addTransition = enter; + emit pushEnterChanged(); + } } /*! - \qmlproperty var QtQuickControls2::StackView::initialItem - - The first \l item that should be shown when the StackView is created. - \a initialItem can take same value as the first argument to \l{StackView::push()} - {StackView.push()}. Note that this is just a convenience for writing - \c{Component.onCompleted: stackView.push(myInitialItem)} - - Examples: + \qmlproperty Transition QtQuickControls2::StackView::pushExit - \list - \li initialItem: Qt.resolvedUrl("MyItem.qml") - \li initialItem: myItem - \li initialItem: {"item" : Qt.resolvedUrl("MyRectangle.qml"), "properties" : {"color" : "red"}} - \endlist - \sa push + TODO */ -QVariant QQuickAbstractStackView::initialItem() const +QQuickTransition *QQuickAbstractStackView::pushExit() const { Q_D(const QQuickAbstractStackView); - return d->initialItem; + if (d->transitioner) + return d->transitioner->addDisplacedTransition; + return Q_NULLPTR; } -void QQuickAbstractStackView::setInitialItem(const QVariant &item) +void QQuickAbstractStackView::setPushExit(QQuickTransition *exit) { Q_D(QQuickAbstractStackView); - d->initialItem = item; + d->ensureTransitioner(); + if (d->transitioner->addDisplacedTransition != exit) { + d->transitioner->addDisplacedTransition = exit; + emit pushExitChanged(); + } } void QQuickAbstractStackView::componentComplete() @@ -294,59 +461,93 @@ void QQuickAbstractStackView::componentComplete() QQuickAbstractContainer::componentComplete(); Q_D(QQuickAbstractStackView); + QQuickStackElement *element = Q_NULLPTR; if (QObject *o = d->initialItem.value<QObject *>()) - d->pushElements(QList<QQuickStackElement *>() << QQuickStackElement::fromObject(o), Immediate); + element = QQuickStackElement::fromObject(o, this); else if (d->initialItem.canConvert<QString>()) - d->pushElements(QList<QQuickStackElement *>() << QQuickStackElement::fromString(d->initialItem.toString(), qmlEngine(this), this), Immediate); + element = QQuickStackElement::fromString(d->initialItem.toString(), this); + if (d->pushElement(element)) { + emit depthChanged(); + d->setCurrentItem(element->item); + } } -/*! - \qmltype Stack - \inherits QtObject - \instantiates QQuickStackAttached - \inqmlmodule QtQuick.Controls - \ingroup navigation - \brief TODO +void QQuickAbstractStackView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + QQuickAbstractContainer::geometryChanged(newGeometry, oldGeometry); - TODO -*/ + Q_D(QQuickAbstractStackView); + foreach (QQuickStackElement *element, d->elements) { + if (element->item) { + QQuickItemPrivate *p = QQuickItemPrivate::get(element->item); + if (!p->widthValid) { + element->item->setWidth(newGeometry.width()); + p->widthValid = false; + } + if (!p->heightValid) { + element->item->setHeight(newGeometry.height()); + p->heightValid = false; + } + } + } +} -class QQuickStackAttachedPrivate : public QObjectPrivate +void QQuickStackAttachedPrivate::init() { -public: - QQuickStackAttachedPrivate() : status(QQuickStackAttached::Inactive) { } - - QQuickStackAttached::Status status; -}; + QQuickItem *item = qobject_cast<QQuickItem *>(parent); + if (item) { + QQuickAbstractStackView *view = qobject_cast<QQuickAbstractStackView *>(item->parentItem()); + if (view) { + element = QQuickAbstractStackViewPrivate::get(view)->findElement(item); + if (element) + initialized = true; + } + } +} -QQuickStackAttached::QQuickStackAttached(QObject *parent) : - QObject(*(new QQuickStackAttachedPrivate), parent) +void QQuickStackAttachedPrivate::reset() { + Q_Q(QQuickStackAttached); + int oldIndex = element ? element->index : -1; + QQuickAbstractStackView::Status oldStatus = element ? element->status : QQuickAbstractStackView::Inactive; + + element = Q_NULLPTR; + + if (oldIndex != -1) + emit q->indexChanged(); + if (oldStatus != QQuickAbstractStackView::Inactive) + emit q->statusChanged(); } -QQuickStackAttached *QQuickStackAttached::qmlAttachedProperties(QObject *object) +QQuickStackAttached::QQuickStackAttached(QQuickItem *parent) : + QObject(*(new QQuickStackAttachedPrivate), parent) { - return new QQuickStackAttached(object); } /*! - \qmlattachedproperty enumeration QtQuickControls2::Stack::status + \qmlattachedproperty int QtQuickControls2::StackView::index TODO */ -QQuickStackAttached::Status QQuickStackAttached::status() const +int QQuickStackAttached::index() const { Q_D(const QQuickStackAttached); - return d->status; + if (!d->initialized) + const_cast<QQuickStackAttachedPrivate *>(d)->init(); + return d->element ? d->element->index : -1; } -void QQuickStackAttached::setStatus(Status status) +/*! + \qmlattachedproperty enumeration QtQuickControls2::StackView::status + + TODO +*/ +QQuickAbstractStackView::Status QQuickStackAttached::status() const { - Q_D(QQuickStackAttached); - if (d->status != status) { - d->status = status; - emit statusChanged(); - } + Q_D(const QQuickStackAttached); + if (!d->initialized) + const_cast<QQuickStackAttachedPrivate *>(d)->init(); + return d->element ? d->element->status : QQuickAbstractStackView::Inactive; } QT_END_NAMESPACE diff --git a/src/controls/qquickabstractstackview_p.cpp b/src/controls/qquickabstractstackview_p.cpp new file mode 100644 index 00000000..76061461 --- /dev/null +++ b/src/controls/qquickabstractstackview_p.cpp @@ -0,0 +1,507 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 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 "qquickabstractstackview_p_p.h" + +#include <QtQml/qqmllist.h> +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlcomponent.h> +#include <QtQml/qqmlincubator.h> +#include <QtQml/private/qqmlcomponent_p.h> +#include <QtQuick/private/qquickanimation_p.h> +#include <QtQuick/private/qquicktransition_p.h> +#include <QtQuick/private/qquickitemviewtransition_p.h> + +QT_BEGIN_NAMESPACE + +static QQuickStackAttached *attachedStackObject(QQuickItem *item) +{ + return qobject_cast<QQuickStackAttached *>(qmlAttachedPropertiesObject<QQuickAbstractStackView>(item, false)); +} + +class QQuickStackIncubator : public QQmlIncubator +{ +public: + QQuickStackIncubator(QQuickStackElement *element) : QQmlIncubator(Synchronous), element(element) { } + +protected: + void setInitialState(QObject *object) Q_DECL_OVERRIDE { element->initItem(object); } + +private: + QQuickStackElement *element; +}; + +QQuickStackElement::QQuickStackElement() : QQuickItemViewTransitionableItem(Q_NULLPTR), + index(-1), removal(false), ownItem(false), ownComponent(false), + context(Q_NULLPTR), component(Q_NULLPTR), incubator(Q_NULLPTR), view(Q_NULLPTR), + status(QQuickAbstractStackView::Inactive) +{ +} + +QQuickStackElement::~QQuickStackElement() +{ + if (item) { + QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed); + + QQuickStackAttached *attached = attachedStackObject(item); + if (attached) + QQuickStackAttachedPrivate::get(attached)->reset(); + } + + if (ownComponent) + delete component; + + if (ownItem && item) { + item->setParentItem(Q_NULLPTR); + item->deleteLater(); + item = Q_NULLPTR; + } else if (item) { + item->setVisible(false); + item->setParentItem(originalParent); + } + + delete context; + delete incubator; +} + +QQuickStackElement *QQuickStackElement::fromString(const QString &str, QQuickAbstractStackView *view) +{ + QQuickStackElement *element = new QQuickStackElement; + element->component = new QQmlComponent(qmlEngine(view), QUrl(str), view); + element->ownComponent = true; + return element; +} + +QQuickStackElement *QQuickStackElement::fromObject(QObject *object, QQuickAbstractStackView *view) +{ + QQuickStackElement *element = new QQuickStackElement; + element->component = qobject_cast<QQmlComponent *>(object); + if (!element->component) { + element->component = new QQmlComponent(qmlEngine(view), view); + element->ownComponent = true; + } + element->item = qobject_cast<QQuickItem *>(object); + if (element->item) { + element->originalParent = element->item->parentItem(); + element->item->setParentItem(view); + QQuickItemPrivate::get(element->item)->addItemChangeListener(element, QQuickItemPrivate::Destroyed); + } + return element; +} + +bool QQuickStackElement::load(QQuickAbstractStackView *parent) +{ + view = parent; + if (!item) { + ownItem = true; + + QQmlContext *creationContext = component->creationContext(); + if (!creationContext) + creationContext = qmlContext(parent); + context = new QQmlContext(creationContext); + context->setContextObject(parent); + + delete incubator; + incubator = new QQuickStackIncubator(this); + component->create(*incubator, context); + } + initProperties(); + return item; +} + +void QQuickStackElement::initItem(QObject *object) +{ + item = qmlobject_cast<QQuickItem *>(object); + if (item) { + QQmlEngine::setObjectOwnership(item, QQmlEngine::CppOwnership); + QQuickItemPrivate *p = QQuickItemPrivate::get(item); + if (!p->widthValid) { + item->setWidth(view->width()); + p->widthValid = false; + } + if (!p->heightValid) { + item->setHeight(view->height()); + p->heightValid = false; + } + item->setParentItem(view); + p->addItemChangeListener(this, QQuickItemPrivate::Destroyed); + } + initProperties(); +} + +void QQuickStackElement::initProperties() +{ + if (!properties.isUndefined()) { + QQmlComponentPrivate *d = QQmlComponentPrivate::get(component); + Q_ASSERT(d && d->engine); + QV4::ExecutionEngine *v4 = qmlGlobal.engine(); + Q_ASSERT(v4); + QV4::Scope scope(v4); + QV4::ScopedValue ipv(scope, properties.value()); + d->initializeObjectWithInitialProperties(*qmlGlobal.valueRef(), ipv, item); + properties.clear(); + } +} + +void QQuickStackElement::setIndex(int value) +{ + if (index != value) { + index = value; + QQuickStackAttached *attached = attachedStackObject(item); + if (attached) + emit attached->indexChanged(); + } +} + +void QQuickStackElement::setStatus(QQuickAbstractStackView::Status value) +{ + if (status != value) { + status = value; + QQuickStackAttached *attached = attachedStackObject(item); + if (attached) + emit attached->statusChanged(); + } +} + +void QQuickStackElement::transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget) +{ + if (transitioner) + transitioner->transitionNextReposition(this, type, asTarget); +} + +bool QQuickStackElement::prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds) +{ + if (transitioner) { + // TODO: add force argument to QQuickItemViewTransitionableItem::prepareTransition()? + nextTransitionToSet = true; + nextTransitionFromSet = true; + nextTransitionFrom += QPointF(1, 1); + return QQuickItemViewTransitionableItem::prepareTransition(transitioner, index, viewBounds); + } + return false; +} + +void QQuickStackElement::startTransition(QQuickItemViewTransitioner *transitioner) +{ + if (transitioner) + QQuickItemViewTransitionableItem::startTransition(transitioner, index); +} + +void QQuickStackElement::itemDestroyed(QQuickItem *) +{ + item = Q_NULLPTR; +} + +QQuickAbstractStackViewPrivate::QQuickAbstractStackViewPrivate() : currentItem(Q_NULLPTR), transitioner(Q_NULLPTR) +{ +} + +void QQuickAbstractStackViewPrivate::setCurrentItem(QQuickItem *item) +{ + Q_Q(QQuickAbstractStackView); + if (currentItem != item) { + currentItem = item; + if (item) + item->setVisible(true); + emit q->currentItemChanged(); + } +} + +static bool initProperties(QQuickStackElement *element, const QV4::Value &props, QQmlV4Function *args) +{ + if (props.isObject()) { + const QV4::QObjectWrapper *wrapper = props.as<QV4::QObjectWrapper>(); + if (!wrapper) { + QV4::ExecutionEngine *v4 = args->v4engine(); + element->properties.set(v4, props); + element->qmlGlobal.set(v4, args->qmlGlobal()); + return true; + } + } + return false; +} + +QList<QQuickStackElement *> QQuickAbstractStackViewPrivate::parseElements(QQmlV4Function *args, int from) +{ + QV4::ExecutionEngine *v4 = args->v4engine(); + QV4::Scope scope(v4); + + QList<QQuickStackElement *> elements; + + int argc = args->length(); + for (int i = from; i < argc; ++i) { + QV4::ScopedValue arg(scope, (*args)[i]); + if (QV4::ArrayObject *array = arg->asArrayObject()) { + int len = array->getLength(); + for (int j = 0; j < len; ++j) { + QV4::ScopedValue value(scope, array->getIndexed(j)); + QQuickStackElement *element = createElement(value); + if (element) { + if (j < len - 1) { + QV4::ScopedValue props(scope, array->getIndexed(j + 1)); + if (initProperties(element, props, args)) + ++j; + } + elements += element; + } + } + } else { + QQuickStackElement *element = createElement(arg); + if (element) { + if (i < argc - 1) { + QV4::ScopedValue props(scope, (*args)[i + 1]); + if (initProperties(element, props, args)) + ++i; + } + elements += element; + } + } + } + return elements; +} + +QQuickStackElement *QQuickAbstractStackViewPrivate::findElement(QQuickItem *item) const +{ + if (item) { + foreach (QQuickStackElement *e, elements) { + if (e->item == item) + return e; + } + } + return Q_NULLPTR; +} + +QQuickStackElement *QQuickAbstractStackViewPrivate::findElement(const QV4::Value &value) const +{ + if (const QV4::QObjectWrapper *o = value.as<QV4::QObjectWrapper>()) + return findElement(qobject_cast<QQuickItem *>(o->object())); + return Q_NULLPTR; +} + +QQuickStackElement *QQuickAbstractStackViewPrivate::createElement(const QV4::Value &value) +{ + Q_Q(QQuickAbstractStackView); + if (QV4::String *s = value.asString()) + return QQuickStackElement::fromString(s->toQString(), q); + if (const QV4::QObjectWrapper *o = value.as<QV4::QObjectWrapper>()) + return QQuickStackElement::fromObject(o->object(), q); + return Q_NULLPTR; +} + +bool QQuickAbstractStackViewPrivate::pushElements(const QList<QQuickStackElement *> &elems) +{ + Q_Q(QQuickAbstractStackView); + if (!elems.isEmpty()) { + foreach (QQuickStackElement *e, elems) { + e->setIndex(elements.count()); + elements += e; + } + return elements.top()->load(q); + } + return false; +} + +bool QQuickAbstractStackViewPrivate::pushElement(QQuickStackElement *element) +{ + if (element) + return pushElements(QList<QQuickStackElement *>() << element); + return false; +} + +bool QQuickAbstractStackViewPrivate::popElements(QQuickStackElement *element) +{ + Q_Q(QQuickAbstractStackView); + if (elements.count() > 1) { + while (elements.count() > 1 && elements.top() != element) { + delete elements.pop(); + if (!element) + break; + } + } + return elements.top()->load(q); +} + +bool QQuickAbstractStackViewPrivate::replaceElements(QQuickStackElement *target, const QList<QQuickStackElement *> &elems) +{ + if (target) { + while (!elements.isEmpty()) { + QQuickStackElement* top = elements.pop(); + delete top; + if (top == target) + break; + } + } + return pushElements(elems); +} + +void QQuickAbstractStackViewPrivate::ensureTransitioner() +{ + if (!transitioner) { + transitioner = new QQuickItemViewTransitioner; + transitioner->setChangeListener(this); + } +} + +void QQuickAbstractStackViewPrivate::popTransition(QQuickStackElement *enter, QQuickStackElement *exit, const QRectF &viewBounds, bool immediate) +{ + Q_Q(QQuickAbstractStackView); + if (exit) { + exit->setStatus(QQuickAbstractStackView::Deactivating); + exit->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, true); + } + if (enter) { + enter->setStatus(QQuickAbstractStackView::Activating); + enter->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, false); + } + + if (exit && exit->prepareTransition(transitioner, viewBounds)) { + if (immediate) + completeTransition(exit, transitioner->removeTransition); + else + exit->startTransition(transitioner); + } + if (enter && enter->prepareTransition(transitioner, viewBounds)) { + if (immediate) + completeTransition(enter, transitioner->removeDisplacedTransition); + else + enter->startTransition(transitioner); + } + + if (!immediate) + emit q->busyChanged(); + + if (transitioner) + transitioner->resetTargetLists(); +} + +void QQuickAbstractStackViewPrivate::pushTransition(QQuickStackElement *enter, QQuickStackElement *exit, const QRectF &viewBounds, bool immediate) +{ + Q_Q(QQuickAbstractStackView); + if (enter) { + enter->setStatus(QQuickAbstractStackView::Activating); + enter->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true); + } + if (exit) { + exit->setStatus(QQuickAbstractStackView::Deactivating); + exit->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, false); + } + + if (enter && enter->prepareTransition(transitioner, viewBounds)) { + if (immediate) + completeTransition(enter, transitioner->addTransition); + else + enter->startTransition(transitioner); + } + if (exit && exit->prepareTransition(transitioner, viewBounds)) { + if (immediate) + completeTransition(exit, transitioner->addDisplacedTransition); + else + exit->startTransition(transitioner); + } + + if (!immediate) + emit q->busyChanged(); + + if (transitioner) + transitioner->resetTargetLists(); +} + +void QQuickAbstractStackViewPrivate::replaceTransition(QQuickStackElement *enter, QQuickStackElement *exit, const QRectF &viewBounds, bool immediate) +{ + Q_Q(QQuickAbstractStackView); + if (enter) { + enter->setStatus(QQuickAbstractStackView::Activating); + enter->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true); + } + if (exit) { + exit->removal = true; + exit->setStatus(QQuickAbstractStackView::Deactivating); + exit->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, false); + } + + if (enter && enter->prepareTransition(transitioner, viewBounds)) { + if (immediate) + completeTransition(enter, transitioner->addTransition); + else + enter->startTransition(transitioner); + } + if (exit && exit->prepareTransition(transitioner, viewBounds)) { + if (immediate) + completeTransition(exit, transitioner->addDisplacedTransition); + else + exit->startTransition(transitioner); + } + + if (!immediate) + emit q->busyChanged(); + + if (transitioner) + transitioner->resetTargetLists(); +} + +void QQuickAbstractStackViewPrivate::completeTransition(QQuickStackElement *element, QQuickTransition *transition) +{ + if (transition) { + // TODO: add a proper way to complete a transition + QQmlListProperty<QQuickAbstractAnimation> animations = transition->animations(); + int count = animations.count(&animations); + for (int i = 0; i < count; ++i) { + QQuickAbstractAnimation *anim = animations.at(&animations, i); + anim->complete(); + } + viewItemTransitionFinished(element); + } +} + +void QQuickAbstractStackViewPrivate::viewItemTransitionFinished(QQuickItemViewTransitionableItem *transitionable) +{ + Q_Q(QQuickAbstractStackView); + + QQuickStackElement *element = static_cast<QQuickStackElement *>(transitionable); + if (element->status == QQuickAbstractStackView::Activating) { + element->setStatus(QQuickAbstractStackView::Active); + } else if (element->status == QQuickAbstractStackView::Deactivating) { + element->setStatus(QQuickAbstractStackView::Inactive); + element->item->setVisible(false); + if (element->removal || element->isPendingRemoval()) + delete element; + } + + if (transitioner->runningJobs.isEmpty()) + emit q->busyChanged(); +} + +QT_END_NAMESPACE diff --git a/src/controls/qquickabstractstackview_p.h b/src/controls/qquickabstractstackview_p.h index 5bb09464..d15a7be4 100644 --- a/src/controls/qquickabstractstackview_p.h +++ b/src/controls/qquickabstractstackview_p.h @@ -53,51 +53,90 @@ QT_BEGIN_NAMESPACE class QQmlV4Function; +class QQuickTransition; +class QQuickStackElement; +class QQuickStackAttached; class QQuickAbstractStackViewPrivate; class Q_QUICKCONTROLS_EXPORT QQuickAbstractStackView : public QQuickAbstractContainer { Q_OBJECT - Q_PROPERTY(bool busy READ busy WRITE setBusy NOTIFY busyChanged FINAL) // TODO: hide setBusy - Q_PROPERTY(int depth READ depth WRITE setDepth NOTIFY depthChanged FINAL) // TODO: hide setDepth - Q_PROPERTY(QQuickItem *currentItem READ currentItem WRITE setCurrentItem NOTIFY currentItemChanged FINAL) // TODO: hide setCurrentItem + Q_PROPERTY(bool busy READ busy NOTIFY busyChanged FINAL) + Q_PROPERTY(int depth READ depth NOTIFY depthChanged FINAL) + Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged FINAL) Q_PROPERTY(QVariant initialItem READ initialItem WRITE setInitialItem FINAL) + Q_PROPERTY(QQuickTransition *popEnter READ popEnter WRITE setPopEnter NOTIFY popEnterChanged FINAL) + Q_PROPERTY(QQuickTransition *popExit READ popExit WRITE setPopExit NOTIFY popExitChanged FINAL) + Q_PROPERTY(QQuickTransition *pushEnter READ pushEnter WRITE setPushEnter NOTIFY pushEnterChanged FINAL) + Q_PROPERTY(QQuickTransition *pushExit READ pushExit WRITE setPushExit NOTIFY pushExitChanged FINAL) public: explicit QQuickAbstractStackView(QQuickItem *parent = Q_NULLPTR); ~QQuickAbstractStackView(); - bool busy() const; - void setBusy(bool busy); // TODO: hide + static QQuickStackAttached *qmlAttachedProperties(QObject *object); + bool busy() const; int depth() const; - void setDepth(int depth); // TODO: hide - QQuickItem *currentItem() const; - void setCurrentItem(QQuickItem *item); // TODO: hide + + enum Status { + Inactive = 0, + Deactivating = 1, + Activating = 2, + Active = 3 + }; + Q_ENUM(Status) QVariant initialItem() const; void setInitialItem(const QVariant &item); + QQuickTransition *popEnter() const; + void setPopEnter(QQuickTransition *enter); + + QQuickTransition *popExit() const; + void setPopExit(QQuickTransition *exit); + + QQuickTransition *pushEnter() const; + void setPushEnter(QQuickTransition *enter); + + QQuickTransition *pushExit() const; + void setPushExit(QQuickTransition *exit); + + enum LoadBehavior { + DontLoad, + ForceLoad + }; + Q_ENUM(LoadBehavior) + + Q_INVOKABLE QQuickItem *get(int index, LoadBehavior behavior = DontLoad); + Q_INVOKABLE QQuickItem *find(const QJSValue &callback, LoadBehavior behavior = DontLoad); + enum Operation { Transition, Immediate }; Q_ENUM(Operation) - Q_INVOKABLE QQuickItem *qpush(QQmlV4Function *args); - Q_INVOKABLE QQuickItem *qpop(QQmlV4Function *args); + Q_INVOKABLE void push(QQmlV4Function *args); + Q_INVOKABLE void pop(QQmlV4Function *args); + Q_INVOKABLE void replace(QQmlV4Function *args); public Q_SLOTS: - void qclear(); + void clear(); Q_SIGNALS: void busyChanged(); void depthChanged(); void currentItemChanged(); + void popEnterChanged(); + void popExitChanged(); + void pushEnterChanged(); + void pushExitChanged(); protected: void componentComplete() Q_DECL_OVERRIDE; + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; private: Q_DISABLE_COPY(QQuickAbstractStackView) @@ -109,25 +148,17 @@ class QQuickStackAttachedPrivate; class Q_QUICKCONTROLS_EXPORT QQuickStackAttached : public QObject { Q_OBJECT - Q_PROPERTY(Status status READ status WRITE setStatus NOTIFY statusChanged) + Q_PROPERTY(int index READ index NOTIFY indexChanged FINAL) + Q_PROPERTY(QQuickAbstractStackView::Status status READ status NOTIFY statusChanged FINAL) public: - explicit QQuickStackAttached(QObject *parent = Q_NULLPTR); - - static QQuickStackAttached *qmlAttachedProperties(QObject *object); - - enum Status { - Inactive = 0, - Deactivating = 1, - Activating = 2, - Active = 3 - }; - Q_ENUM(Status) + explicit QQuickStackAttached(QQuickItem *parent = Q_NULLPTR); - Status status() const; - void setStatus(Status status); + int index() const; + QQuickAbstractStackView::Status status() const; Q_SIGNALS: + void indexChanged(); void statusChanged(); private: @@ -137,6 +168,7 @@ private: QT_END_NAMESPACE -QML_DECLARE_TYPEINFO(QQuickStackAttached, QML_HAS_ATTACHED_PROPERTIES) +QML_DECLARE_TYPEINFO(QQuickAbstractStackView, QML_HAS_ATTACHED_PROPERTIES) +QML_DECLARE_TYPE(QQuickAbstractStackView) #endif // QQUICKABSTRACTSTACKVIEW_P_H diff --git a/src/controls/qquickabstractstackview_p_p.h b/src/controls/qquickabstractstackview_p_p.h new file mode 100644 index 00000000..5cda34f9 --- /dev/null +++ b/src/controls/qquickabstractstackview_p_p.h @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Controls 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$ +** +****************************************************************************/ + +#ifndef QQUICKABSTRACTSTACKVIEW_P_P_H +#define QQUICKABSTRACTSTACKVIEW_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuickControls/private/qquickabstractstackview_p.h> +#include <QtQuickControls/private/qquickabstractcontainer_p_p.h> +#include <QtQuick/private/qquickitemviewtransition_p.h> +#include <QtQuick/private/qquickitemchangelistener_p.h> +#include <QtQml/private/qv4persistent_p.h> + +QT_BEGIN_NAMESPACE + +class QQmlContext; +class QQmlComponent; +class QQmlIncubator; + +class QQuickStackElement : public QQuickItemViewTransitionableItem, public QQuickItemChangeListener +{ + QQuickStackElement(); + +public: + ~QQuickStackElement(); + + static QQuickStackElement *fromString(const QString &str, QQuickAbstractStackView *view); + static QQuickStackElement *fromObject(QObject *object, QQuickAbstractStackView *view); + + bool load(QQuickAbstractStackView *parent); + void initItem(QObject *object); + void initProperties(); + + void setIndex(int index); + void setStatus(QQuickAbstractStackView::Status status); + + void transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget); + bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds); + void startTransition(QQuickItemViewTransitioner *transitioner); + + void itemDestroyed(QQuickItem *item) Q_DECL_OVERRIDE; + + int index; + bool removal; + bool ownItem; + bool ownComponent; + QQmlContext *context; + QQmlComponent *component; + QQmlIncubator *incubator; + QQuickAbstractStackView *view; + QPointer<QQuickItem> originalParent; + QQuickAbstractStackView::Status status; + QV4::PersistentValue properties; + QV4::PersistentValue qmlGlobal; +}; + +class QQuickAbstractStackViewPrivate : public QQuickAbstractContainerPrivate, public QQuickItemViewTransitionChangeListener +{ + Q_DECLARE_PUBLIC(QQuickAbstractStackView) + +public: + QQuickAbstractStackViewPrivate(); + + static QQuickAbstractStackViewPrivate *get(QQuickAbstractStackView *view) + { + return view->d_func(); + } + + void setCurrentItem(QQuickItem *item); + + QList<QQuickStackElement *> parseElements(QQmlV4Function *args, int from = 0); + QQuickStackElement *findElement(QQuickItem *item) const; + QQuickStackElement *findElement(const QV4::Value &value) const; + QQuickStackElement *createElement(const QV4::Value &value); + bool pushElements(const QList<QQuickStackElement *> &elements); + bool pushElement(QQuickStackElement *element); + bool popElements(QQuickStackElement *element); + bool replaceElements(QQuickStackElement *element, const QList<QQuickStackElement *> &elements); + + void ensureTransitioner(); + void popTransition(QQuickStackElement *enter, QQuickStackElement *exit, const QRectF &viewBounds, bool immediate); + void pushTransition(QQuickStackElement *enter, QQuickStackElement *exit, const QRectF &viewBounds, bool immediate); + void replaceTransition(QQuickStackElement *enter, QQuickStackElement *exit, const QRectF &viewBounds, bool immediate); + void completeTransition(QQuickStackElement *element, QQuickTransition *transition); + + void viewItemTransitionFinished(QQuickItemViewTransitionableItem *item) Q_DECL_OVERRIDE; + + QVariant initialItem; + QQuickItem *currentItem; + QStack<QQuickStackElement *> elements; + QQuickItemViewTransitioner *transitioner; +}; + +class QQuickStackAttachedPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickStackAttached) + +public: + QQuickStackAttachedPrivate() : initialized(false), element(Q_NULLPTR) { } + + static QQuickStackAttachedPrivate *get(QQuickStackAttached *attached) + { + return attached->d_func(); + } + + void init(); + void reset(); + + bool initialized; + QQuickStackElement *element; +}; + +QT_END_NAMESPACE + +#endif // QQUICKABSTRACTSTACKVIEW_P_P_H |