diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2011-06-03 16:08:32 +1000 |
---|---|---|
committer | Michael Brasser <michael.brasser@nokia.com> | 2011-06-10 11:19:40 +1000 |
commit | 17bd3e24a18797e6b565235d2d922a807137041a (patch) | |
tree | 5b34d84f3fa3a27a523139313f776c67630cf3dd | |
parent | df4add062fc7368d9fee7c697405c43422b0af27 (diff) |
Introduce StateChange element.
-rw-r--r-- | src/declarative/qml/v8/qv8qobjectwrapper_p.h | 1 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativestate.cpp | 22 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativestate_p.h | 5 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativestate_p_p.h | 23 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativestatechange.cpp | 194 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativestatechange_p.h | 104 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativeutilmodule.cpp | 3 | ||||
-rw-r--r-- | src/declarative/util/util.pri | 6 |
8 files changed, 355 insertions, 3 deletions
diff --git a/src/declarative/qml/v8/qv8qobjectwrapper_p.h b/src/declarative/qml/v8/qv8qobjectwrapper_p.h index 5100c3f51b..fafa2f2830 100644 --- a/src/declarative/qml/v8/qv8qobjectwrapper_p.h +++ b/src/declarative/qml/v8/qv8qobjectwrapper_p.h @@ -90,6 +90,7 @@ private: friend class QDeclarativePropertyCache; friend class QV8QObjectConnectionList; friend class QV8QObjectInstance; + friend class QDeclarativeStateChange; v8::Local<v8::Object> newQObject(QObject *, QDeclarativeData *, QV8Engine *); static v8::Handle<v8::Value> GetProperty(QV8Engine *, QObject *, v8::Handle<v8::Value> *, diff --git a/src/declarative/util/qdeclarativestate.cpp b/src/declarative/util/qdeclarativestate.cpp index 9f56ccb02e..054d92ce7f 100644 --- a/src/declarative/util/qdeclarativestate.cpp +++ b/src/declarative/util/qdeclarativestate.cpp @@ -301,6 +301,14 @@ QDeclarativeState &QDeclarativeState::operator<<(QDeclarativeStateOperation *op) return *this; } +QDeclarativeListProperty<QDeclarativeStateChange> QDeclarativeState::stateChanges() +{ + Q_D(QDeclarativeState); + return QDeclarativeListProperty<QDeclarativeStateChange>(this, &d->stateChanges, QDeclarativeStatePrivate::stateChanges_append, + QDeclarativeStatePrivate::stateChanges_count, QDeclarativeStatePrivate::stateChanges_at, + QDeclarativeStatePrivate::stateChanges_clear); +} + void QDeclarativeStatePrivate::complete() { Q_Q(QDeclarativeState); @@ -315,6 +323,9 @@ void QDeclarativeStatePrivate::complete() } reverting.clear(); + for (int i = 0; i < stateChanges.count(); ++i) + stateChanges.at(i)->setActive(true); + emit q->completed(); } @@ -364,6 +375,15 @@ void QDeclarativeState::cancel() d->transitionManager.cancel(); } +void QDeclarativeState::prepareForExit() +{ + Q_D(QDeclarativeState); + cancel(); + + for (int i = 0; i < d->stateChanges.count(); ++i) + d->stateChanges.at(i)->setActive(false); +} + void QDeclarativeAction::deleteFromBinding() { if (fromBinding) { @@ -567,7 +587,7 @@ void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransit cancel(); if (revert) - revert->cancel(); + revert->prepareForExit(); d->revertList.clear(); d->reverting.clear(); diff --git a/src/declarative/util/qdeclarativestate_p.h b/src/declarative/util/qdeclarativestate_p.h index d24304ccf5..a875621600 100644 --- a/src/declarative/util/qdeclarativestate_p.h +++ b/src/declarative/util/qdeclarativestate_p.h @@ -47,6 +47,7 @@ #include <QtCore/qobject.h> #include <QtCore/qsharedpointer.h> #include <private/qdeclarativeglobal_p.h> +#include <private/qdeclarativestatechange_p.h> QT_BEGIN_HEADER @@ -148,6 +149,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeState : public QObject Q_PROPERTY(QDeclarativeBinding *when READ when WRITE setWhen) Q_PROPERTY(QString extend READ extends WRITE setExtends) Q_PROPERTY(QDeclarativeListProperty<QDeclarativeStateOperation> changes READ changes) + Q_PROPERTY(QDeclarativeListProperty<QDeclarativeStateChange> stateChanges READ stateChanges) Q_CLASSINFO("DefaultProperty", "changes") Q_CLASSINFO("DeferredPropertyNames", "changes") @@ -174,8 +176,11 @@ public: QDeclarativeState &operator<<(QDeclarativeStateOperation *); + QDeclarativeListProperty<QDeclarativeStateChange> stateChanges(); + void apply(QDeclarativeStateGroup *, QDeclarativeTransition *, QDeclarativeState *revert); void cancel(); + void prepareForExit(); QDeclarativeStateGroup *stateGroup() const; void setStateGroup(QDeclarativeStateGroup *); diff --git a/src/declarative/util/qdeclarativestate_p_p.h b/src/declarative/util/qdeclarativestate_p_p.h index ec18f59b08..011498048f 100644 --- a/src/declarative/util/qdeclarativestate_p_p.h +++ b/src/declarative/util/qdeclarativestate_p_p.h @@ -236,6 +236,29 @@ public: return list->at(index); } + //### should use same "guarded" approach as above + QList<QDeclarativeStateChange*> stateChanges; + static void stateChanges_append(QDeclarativeListProperty<QDeclarativeStateChange> *prop, QDeclarativeStateChange *change) { + QList<QDeclarativeStateChange*> *list = static_cast<QList<QDeclarativeStateChange*> *>(prop->data); + change->setState(qobject_cast<QDeclarativeState*>(prop->object)); + list->append(change); + } + static void stateChanges_clear(QDeclarativeListProperty<QDeclarativeStateChange> *prop) { + QList<QDeclarativeStateChange*> *list = static_cast<QList<QDeclarativeStateChange*> *>(prop->data); + QMutableListIterator<QDeclarativeStateChange*> listIterator(*list); + while(listIterator.hasNext()) + listIterator.next()->setState(0); + list->clear(); + } + static int stateChanges_count(QDeclarativeListProperty<QDeclarativeStateChange> *prop) { + QList<QDeclarativeStateChange*> *list = static_cast<QList<QDeclarativeStateChange*> *>(prop->data); + return list->count(); + } + static QDeclarativeStateChange *stateChanges_at(QDeclarativeListProperty<QDeclarativeStateChange> *prop, int index) { + QList<QDeclarativeStateChange*> *list = static_cast<QList<QDeclarativeStateChange*> *>(prop->data); + return list->at(index); + } + QDeclarativeTransitionManager transitionManager; SimpleActionList revertList; diff --git a/src/declarative/util/qdeclarativestatechange.cpp b/src/declarative/util/qdeclarativestatechange.cpp new file mode 100644 index 0000000000..d0b5800f77 --- /dev/null +++ b/src/declarative/util/qdeclarativestatechange.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 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 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativestatechange_p.h" + +#include <qdeclarativeexpression.h> +#include "qdeclarativeinfo.h" +#include "qdeclarativestate_p.h" +#include "qdeclarativestategroup_p.h" +#include "qdeclarativeexpression_p.h" +#include "qv8qobjectwrapper_p.h" + +QT_BEGIN_NAMESPACE + +int QDeclarativeStateChange::m_activateIdx = -1; + +QDeclarativeStateChange::QDeclarativeStateChange(QObject *parent) : + QObject(parent), m_state(0), m_expression(0), + m_triggerObject(0), m_triggerIdx(-1), m_triggerDirty(false) +{ +} + +QDeclarativeStateChange::~QDeclarativeStateChange() +{ + delete m_expression; +} + +QString QDeclarativeStateChange::toState() const +{ + return m_toState; +} + +void QDeclarativeStateChange::setToState(QString arg) +{ + if (m_toState == arg) + return; + + m_toState = arg; + emit toStateChanged(arg); +} + +QDeclarativeScriptString QDeclarativeStateChange::when() const +{ + return m_when; +} + +void QDeclarativeStateChange::setWhen(QDeclarativeScriptString arg) +{ + if (!m_when.script().isEmpty()) { + qmlInfo(this) << "'when' clause cannot be changed (can only be set once)."; + return; + } + + m_when = arg; +} + +QDeclarativeScriptString QDeclarativeStateChange::trigger() const +{ + return m_trigger; +} + +void QDeclarativeStateChange::setTrigger(QDeclarativeScriptString arg) +{ + if (!m_when.script().isEmpty()) { + qmlInfo(this) << "'trigger' clause cannot be changed (can only be set once)."; + return; + } + + m_trigger = arg; + m_triggerDirty = true; +} + +void QDeclarativeStateChange::createTrigger() +{ + if (!m_triggerDirty) + return; + + QDeclarativeExpression triggerExpression(m_trigger.context(), m_trigger.scopeObject(), m_trigger.script()); + QDeclarativeExpressionPrivate *exp = QDeclarativeExpressionPrivate::get(&triggerExpression); + + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_trigger.context()); + + QPair<QObject*, int> qtMethod; + { + v8::HandleScope handle_scope; + v8::Local<v8::Value> result = exp->v8value(); + if (!result->IsFunction()) + return; //### exception? + + qtMethod = QV8QObjectWrapper::ExtractQtMethod(&ep->v8engine, v8::Handle<v8::Function>::Cast(result)); + } + + if (!qtMethod.first) + return; //### exception? + + //verify that the method is a signal + QMetaMethod method = qtMethod.first->metaObject()->method(qtMethod.second); + if (method.methodType() != QMetaMethod::Signal) + return; //### exception? + + m_triggerObject = qtMethod.first; + m_triggerIdx = qtMethod.second; + + m_triggerDirty = false; +} + +void QDeclarativeStateChange::setState(QDeclarativeState *state) +{ + m_state = state; + + if (!m_state) + setActive(false); +} + +void QDeclarativeStateChange::setActive(bool active) +{ + //qDebug() << "activating" << active << this; + if (active) { + createTrigger(); + if (m_triggerObject) { + if (m_activateIdx < 0) + m_activateIdx = QDeclarativeStateChange::staticMetaObject.indexOfSlot("activate()"); + QMetaObject::connect(m_triggerObject, m_triggerIdx, this, m_activateIdx); + } + + if (!m_when.script().isEmpty()) { + if (!m_expression) { + m_expression = new QDeclarativeExpression(m_when.context(), m_when.scopeObject(), m_when.script()); + connect(m_expression, SIGNAL(valueChanged()), this, SLOT(updateState())); + } + if (!m_triggerObject) //when is only 'active' if there is no trigger. Otherwise it is 'passive' + m_expression->setNotifyOnValueChanged(true); + m_expression->evaluate(); + } + } else { + if (m_triggerObject) + QMetaObject::disconnect(m_triggerObject, m_triggerIdx, this, m_activateIdx); + if (m_expression) + m_expression->setNotifyOnValueChanged(false); + } +} + +void QDeclarativeStateChange::updateState() +{ + QVariant value = !m_when.script().isEmpty() ? m_expression->evaluate() : QVariant(true); + + if (value.toBool()) + m_state->stateGroup()->setState(m_toState); +} + +void QDeclarativeStateChange::activate() +{ + updateState(); +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativestatechange_p.h b/src/declarative/util/qdeclarativestatechange_p.h new file mode 100644 index 0000000000..fe79182128 --- /dev/null +++ b/src/declarative/util/qdeclarativestatechange_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 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 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVESTATECHANGE_P_H +#define QDECLARATIVESTATECHANGE_P_H + +#include <QObject> +#include <QtScript/qscriptvalue.h> +#include <qdeclarativescriptstring.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeState; +class QDeclarativeExpression; +class QDeclarativeStateChange : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString toState READ toState WRITE setToState NOTIFY toStateChanged) + Q_PROPERTY(QDeclarativeScriptString when READ when WRITE setWhen) + Q_PROPERTY(QDeclarativeScriptString trigger READ trigger WRITE setTrigger) +public: + explicit QDeclarativeStateChange(QObject *parent = 0); + ~QDeclarativeStateChange(); + + QString toState() const; + void setToState(QString arg); + + + QDeclarativeScriptString when() const; + void setWhen(QDeclarativeScriptString arg); + + QDeclarativeScriptString trigger() const; + void setTrigger(QDeclarativeScriptString arg); + + void setState(QDeclarativeState *); + void setActive(bool active); + +Q_SIGNALS: + void toStateChanged(QString arg); + +private Q_SLOTS: + void updateState(); + void activate(); + +private: + void createTrigger(); + QString m_toState; + QDeclarativeState *m_state; + QDeclarativeScriptString m_when; + QDeclarativeExpression *m_expression; + QDeclarativeScriptString m_trigger; + QObject *m_triggerObject; + int m_triggerIdx; + bool m_triggerDirty; + static int m_activateIdx; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVESTATECHANGE_P_H diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp index 4bea2e651a..dc7930bff0 100644 --- a/src/declarative/util/qdeclarativeutilmodule.cpp +++ b/src/declarative/util/qdeclarativeutilmodule.cpp @@ -73,6 +73,7 @@ #ifndef QT_NO_XMLPATTERNS #include "private/qdeclarativexmllistmodel_p.h" #endif +#include "qdeclarativestatechange_p.h" void QDeclarativeUtilModule::defineModule() { @@ -126,6 +127,8 @@ void QDeclarativeUtilModule::defineModule() qmlRegisterCustomType<QDeclarativePropertyChanges>("QtQuick",1,0,"PropertyChanges", new QDeclarativePropertyChangesParser); qmlRegisterCustomType<QDeclarativeConnections>("QtQuick",1,0,"Connections", new QDeclarativeConnectionsParser); + qmlRegisterType<QDeclarativeStateChange>("QtQuick",2,0,"StateChange"); + #ifndef QT_NO_IMPORT_QT47_QML qmlRegisterType<QDeclarativeAnchorAnimation>("Qt",4,7,"AnchorAnimation"); qmlRegisterType<QDeclarativeAnchorChanges>("Qt",4,7,"AnchorChanges"); diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index 5bc8b117c0..157c736bcc 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -28,7 +28,8 @@ SOURCES += \ $$PWD/qdeclarativefontloader.cpp \ $$PWD/qdeclarativestyledtext.cpp \ $$PWD/qdeclarativelistmodelworkeragent.cpp \ - $$PWD/qlistmodelinterface.cpp + $$PWD/qlistmodelinterface.cpp \ + util/qdeclarativestatechange.cpp HEADERS += \ $$PWD/qdeclarativeapplication_p.h \ @@ -63,7 +64,8 @@ HEADERS += \ $$PWD/qdeclarativefontloader_p.h \ $$PWD/qdeclarativestyledtext_p.h \ $$PWD/qdeclarativelistmodelworkeragent_p.h \ - $$PWD/qlistmodelinterface_p.h + $$PWD/qlistmodelinterface_p.h \ + util/qdeclarativestatechange_p.h contains(QT_CONFIG, xmlpatterns) { QT+=xmlpatterns |