diff options
author | Thomas Hartmann <Thomas.Hartmann@nokia.com> | 2010-09-14 14:43:47 (GMT) |
---|---|---|
committer | Thomas Hartmann <Thomas.Hartmann@nokia.com> | 2010-09-14 14:43:47 (GMT) |
commit | 6454f4db1697af1d36ad4c0ea83ccd0bb490fd39 (patch) | |
tree | c0971fdbf74a70d5d1c1a31b9dfcc4411bceb099 | |
parent | 37b9c2df53b281bddee26291855e0c7f01f52a7c (diff) | |
download | Qt-6454f4db1697af1d36ad4c0ea83ccd0bb490fd39.zip Qt-6454f4db1697af1d36ad4c0ea83ccd0bb490fd39.tar.gz Qt-6454f4db1697af1d36ad4c0ea83ccd0bb490fd39.tar.bz2 |
This patch allows modifications on PropertyChanges on the fly
This is important for Bauhaus to ensure that we can
edit properties and states dynamically in the visual
editor
Most of the changes consist of added functions
for Bauhaus, that do not affect any current
behaviour.
Important changes:
QDeclarativeAbstractBinding is holding a
QSharedPointer to itself so that other classes
can hold a weak reference to avoid accessing
dangling pointers while keeping track of bindings.
QDeclarativeStateOperation now has its own private class
QDeclarativeStateOperationPrivate to hold a pointer back
to QDeclarativeState since the parent is not set correctly
in every context.
QDeclarativePropertyChangesPrivate does now hold a
QDeclarativeGuard instead of a raw pointer to the
target QObject. In Bauhaus the target object might
be deleted.
Reviewed-by: Aaron Kennedy
-rw-r--r-- | src/declarative/qml/qdeclarativebinding.cpp | 13 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativebinding_p.h | 6 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativecomponent_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeengine.cpp | 2 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativepropertychanges.cpp | 275 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativepropertychanges_p.h | 16 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativestate.cpp | 238 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativestate_p.h | 21 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativestate_p_p.h | 135 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativestateoperations.cpp | 7 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativetransitionmanager.cpp | 4 |
11 files changed, 670 insertions, 49 deletions
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index e096305..cb6ad8c 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -48,6 +48,7 @@ #include "private/qdeclarativecontext_p.h" #include "private/qdeclarativedata_p.h" #include "private/qdeclarativestringconverters_p.h" +#include "private/qdeclarativestate_p_p.h" #include <QVariant> #include <QtCore/qdebug.h> @@ -373,6 +374,18 @@ void QDeclarativeAbstractBinding::removeFromObject() } } +static void bindingDummyDeleter(QDeclarativeAbstractBinding *) +{ +} + +QDeclarativeAbstractBinding::Pointer QDeclarativeAbstractBinding::weakPointer() +{ + if (m_selfPointer.isNull()) + m_selfPointer = QSharedPointer<QDeclarativeAbstractBinding>(this, bindingDummyDeleter); + + return m_selfPointer.toWeakRef(); +} + void QDeclarativeAbstractBinding::clear() { if (m_mePtr) { diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h index 598f09f..f38ed23 100644 --- a/src/declarative/qml/qdeclarativebinding_p.h +++ b/src/declarative/qml/qdeclarativebinding_p.h @@ -67,6 +67,8 @@ QT_BEGIN_NAMESPACE class Q_DECLARATIVE_EXPORT QDeclarativeAbstractBinding { public: + typedef QWeakPointer<QDeclarativeAbstractBinding> Pointer; + QDeclarativeAbstractBinding(); virtual void destroy(); @@ -86,6 +88,8 @@ public: void addToObject(QObject *); void removeFromObject(); + Pointer weakPointer(); + protected: virtual ~QDeclarativeAbstractBinding(); void clear(); @@ -96,11 +100,13 @@ private: friend class QDeclarativeValueTypeProxyBinding; friend class QDeclarativePropertyPrivate; friend class QDeclarativeVME; + friend class QtSharedPointer::ExternalRefCount<QDeclarativeAbstractBinding>; QObject *m_object; QDeclarativeAbstractBinding **m_mePtr; QDeclarativeAbstractBinding **m_prevBinding; QDeclarativeAbstractBinding *m_nextBinding; + QSharedPointer<QDeclarativeAbstractBinding> m_selfPointer; }; class QDeclarativeValueTypeProxyBinding : public QDeclarativeAbstractBinding diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index 1b1454b..a551cc8 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -74,7 +74,7 @@ class QDeclarativeEngine; class QDeclarativeCompiledData; class QDeclarativeComponentAttached; -class QDeclarativeComponentPrivate : public QObjectPrivate, public QDeclarativeTypeData::TypeDataCallback +class Q_AUTOTEST_EXPORT QDeclarativeComponentPrivate : public QObjectPrivate, public QDeclarativeTypeData::TypeDataCallback { Q_DECLARE_PUBLIC(QDeclarativeComponent) diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 9de5a77..80db230 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -906,7 +906,7 @@ QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject return ddata->indestructible?CppOwnership:JavaScriptOwnership; } -void qmlExecuteDeferred(QObject *object) +Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object) { QDeclarativeData *data = QDeclarativeData::get(object); diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index e897458..8d01b80 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -52,6 +52,7 @@ #include <qdeclarativeguard_p.h> #include <qdeclarativeproperty_p.h> #include <qdeclarativecontext_p.h> +#include <qdeclarativestate_p_p.h> #include <QtCore/qdebug.h> @@ -200,14 +201,14 @@ public: }; -class QDeclarativePropertyChangesPrivate : public QObjectPrivate +class QDeclarativePropertyChangesPrivate : public QDeclarativeStateOperationPrivate { Q_DECLARE_PUBLIC(QDeclarativePropertyChanges) public: - QDeclarativePropertyChangesPrivate() : object(0), decoded(true), restore(true), + QDeclarativePropertyChangesPrivate() : decoded(true), restore(true), isExplicit(false) {} - QObject *object; + QDeclarativeGuard<QObject> object; QByteArray data; bool decoded : 1; @@ -497,4 +498,272 @@ void QDeclarativePropertyChanges::setIsExplicit(bool e) d->isExplicit = e; } +bool QDeclarativePropertyChanges::containsValue(const QByteArray &name) const +{ + Q_D(const QDeclarativePropertyChanges); + typedef QPair<QByteArray, QVariant> PropertyEntry; + + QListIterator<PropertyEntry> propertyIterator(d->properties); + while (propertyIterator.hasNext()) { + const PropertyEntry &entry = propertyIterator.next(); + if (entry.first == name) { + return true; + } + } + + return false; +} + +bool QDeclarativePropertyChanges::containsExpression(const QByteArray &name) const +{ + Q_D(const QDeclarativePropertyChanges); + typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + + QListIterator<ExpressionEntry> expressionIterator(d->expressions); + while (expressionIterator.hasNext()) { + const ExpressionEntry &entry = expressionIterator.next(); + if (entry.first == name) { + return true; + } + } + + return false; +} + +bool QDeclarativePropertyChanges::containsProperty(const QByteArray &name) const +{ + return containsValue(name) || containsExpression(name); +} + +void QDeclarativePropertyChanges::changeValue(const QByteArray &name, const QVariant &value) +{ + Q_D(QDeclarativePropertyChanges); + typedef QPair<QByteArray, QVariant> PropertyEntry; + typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + + QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions); + while (expressionIterator.hasNext()) { + const ExpressionEntry &entry = expressionIterator.next(); + if (entry.first == name) { + expressionIterator.remove(); + if (state() && state()->isStateActive()) { + QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name)); + if (oldBinding) { + QDeclarativePropertyPrivate::setBinding(d->property(name), 0); + oldBinding->destroy(); + } + d->property(name).write(value); + } + + d->properties.append(PropertyEntry(name, value)); + return; + } + } + + QMutableListIterator<PropertyEntry> propertyIterator(d->properties); + while (propertyIterator.hasNext()) { + PropertyEntry &entry = propertyIterator.next(); + if (entry.first == name) { + entry.second = value; + if (state() && state()->isStateActive()) + d->property(name).write(value); + return; + } + } + + QDeclarativeAction action; + action.restore = restoreEntryValues(); + action.property = d->property(name); + action.fromValue = action.property.read(); + action.specifiedObject = object(); + action.specifiedProperty = QString::fromUtf8(name); + action.toValue = value; + + propertyIterator.insert(PropertyEntry(name, value)); + if (state() && state()->isStateActive()) { + state()->addEntryToRevertList(action); + QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(action.property); + if (oldBinding) + oldBinding->setEnabled(false, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor); + d->property(name).write(value); + } +} + +void QDeclarativePropertyChanges::changeExpression(const QByteArray &name, const QString &expression) +{ + Q_D(QDeclarativePropertyChanges); + typedef QPair<QByteArray, QVariant> PropertyEntry; + typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + + bool hadValue = false; + + QMutableListIterator<PropertyEntry> propertyIterator(d->properties); + while (propertyIterator.hasNext()) { + PropertyEntry &entry = propertyIterator.next(); + if (entry.first == name) { + propertyIterator.remove(); + hadValue = true; + break; + } + } + + QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions); + while (expressionIterator.hasNext()) { + const ExpressionEntry &entry = expressionIterator.next(); + if (entry.first == name) { + entry.second->setExpression(expression); + if (state() && state()->isStateActive()) { + QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name)); + if (oldBinding) { + QDeclarativePropertyPrivate::setBinding(d->property(name), 0); + oldBinding->destroy(); + } + + QDeclarativeBinding *newBinding = new QDeclarativeBinding(expression, object(), qmlContext(this)); + newBinding->setTarget(d->property(name)); + QDeclarativePropertyPrivate::setBinding(d->property(name), newBinding, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor); + } + return; + } + } + + QDeclarativeExpression *newExpression = new QDeclarativeExpression(qmlContext(this), d->object, expression); + expressionIterator.insert(ExpressionEntry(name, newExpression)); + + if (state() && state()->isStateActive()) { + if (hadValue) { + QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name)); + if (oldBinding) { + oldBinding->setEnabled(false, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor); + state()->changeBindingInRevertList(object(), name, oldBinding); + } + + QDeclarativeBinding *newBinding = new QDeclarativeBinding(expression, object(), qmlContext(this)); + newBinding->setTarget(d->property(name)); + QDeclarativePropertyPrivate::setBinding(d->property(name), newBinding, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor); + } else { + QDeclarativeAction action; + action.restore = restoreEntryValues(); + action.property = d->property(name); + action.fromValue = action.property.read(); + action.specifiedObject = object(); + action.specifiedProperty = QString::fromUtf8(name); + + + if (d->isExplicit) { + action.toValue = newExpression->evaluate(); + } else { + QDeclarativeBinding *newBinding = new QDeclarativeBinding(newExpression->expression(), object(), qmlContext(this)); + newBinding->setTarget(d->property(name)); + action.toBinding = newBinding; + action.deletableToBinding = true; + + state()->addEntryToRevertList(action); + QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(action.property); + if (oldBinding) + oldBinding->setEnabled(false, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor); + + QDeclarativePropertyPrivate::setBinding(action.property, newBinding, QDeclarativePropertyPrivate::DontRemoveBinding | QDeclarativePropertyPrivate::BypassInterceptor); + } + } + } + // what about the signal handler? +} + +QVariant QDeclarativePropertyChanges::property(const QByteArray &name) const +{ + Q_D(const QDeclarativePropertyChanges); + typedef QPair<QByteArray, QVariant> PropertyEntry; + typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + + QListIterator<PropertyEntry> propertyIterator(d->properties); + while (propertyIterator.hasNext()) { + const PropertyEntry &entry = propertyIterator.next(); + if (entry.first == name) { + return entry.second; + } + } + + QListIterator<ExpressionEntry> expressionIterator(d->expressions); + while (expressionIterator.hasNext()) { + const ExpressionEntry &entry = expressionIterator.next(); + if (entry.first == name) { + return QVariant(entry.second->expression()); + } + } + + return QVariant(); +} + +void QDeclarativePropertyChanges::removeProperty(const QByteArray &name) +{ + Q_D(QDeclarativePropertyChanges); + typedef QPair<QByteArray, QVariant> PropertyEntry; + typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + + QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions); + while (expressionIterator.hasNext()) { + const ExpressionEntry &entry = expressionIterator.next(); + if (entry.first == name) { + expressionIterator.remove(); + state()->removeEntryFromRevertList(object(), name); + return; + } + } + + QMutableListIterator<PropertyEntry> propertyIterator(d->properties); + while (propertyIterator.hasNext()) { + const PropertyEntry &entry = propertyIterator.next(); + if (entry.first == name) { + propertyIterator.remove(); + state()->removeEntryFromRevertList(object(), name); + return; + } + } +} + +QVariant QDeclarativePropertyChanges::value(const QByteArray &name) const +{ + Q_D(const QDeclarativePropertyChanges); + typedef QPair<QByteArray, QVariant> PropertyEntry; + + QListIterator<PropertyEntry> propertyIterator(d->properties); + while (propertyIterator.hasNext()) { + const PropertyEntry &entry = propertyIterator.next(); + if (entry.first == name) { + return entry.second; + } + } + + return QVariant(); +} + +QString QDeclarativePropertyChanges::expression(const QByteArray &name) const +{ + Q_D(const QDeclarativePropertyChanges); + typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + + QListIterator<ExpressionEntry> expressionIterator(d->expressions); + while (expressionIterator.hasNext()) { + const ExpressionEntry &entry = expressionIterator.next(); + if (entry.first == name) { + return entry.second->expression(); + } + } + + return QString(); +} + +void QDeclarativePropertyChanges::detachFromState() +{ + if (state()) + state()->removeAllEntriesFromRevertList(object()); +} + +void QDeclarativePropertyChanges::attachToState() +{ + if (state()) + state()->addEntriesToRevertList(actions()); +} + QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativepropertychanges_p.h b/src/declarative/util/qdeclarativepropertychanges_p.h index 8578086..199928f 100644 --- a/src/declarative/util/qdeclarativepropertychanges_p.h +++ b/src/declarative/util/qdeclarativepropertychanges_p.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativePropertyChangesPrivate; -class Q_AUTOTEST_EXPORT QDeclarativePropertyChanges : public QDeclarativeStateOperation +class Q_DECLARATIVE_EXPORT QDeclarativePropertyChanges : public QDeclarativeStateOperation { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativePropertyChanges) @@ -74,6 +74,20 @@ public: void setIsExplicit(bool); virtual ActionList actions(); + + bool containsProperty(const QByteArray &name) const; + bool containsValue(const QByteArray &name) const; + bool containsExpression(const QByteArray &name) const; + void changeValue(const QByteArray &name, const QVariant &value); + void changeExpression(const QByteArray &name, const QString &expression); + void removeProperty(const QByteArray &name); + QVariant value(const QByteArray &name) const; + QString expression(const QByteArray &name) const; + + void detachFromState(); + void attachToState(); + + QVariant property(const QByteArray &name) const; }; class QDeclarativePropertyChangesParser : public QDeclarativeCustomParser diff --git a/src/declarative/util/qdeclarativestate.cpp b/src/declarative/util/qdeclarativestate.cpp index 1ed7923..0f5413e 100644 --- a/src/declarative/util/qdeclarativestate.cpp +++ b/src/declarative/util/qdeclarativestate.cpp @@ -304,7 +304,7 @@ void QDeclarativeStatePrivate::complete() for (int ii = 0; ii < reverting.count(); ++ii) { for (int jj = 0; jj < revertList.count(); ++jj) { - if (revertList.at(jj).property == reverting.at(ii)) { + if (revertList.at(jj).property() == reverting.at(ii)) { revertList.removeAt(jj); break; } @@ -370,6 +370,192 @@ void QDeclarativeAction::deleteFromBinding() } } +bool QDeclarativeState::containsPropertyInRevertList(QObject *target, const QByteArray &name) const +{ + Q_D(const QDeclarativeState); + + if (isStateActive()) { + QListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList); + + while (revertListIterator.hasNext()) { + const QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) + return true; + } + } + + return false; +} + +bool QDeclarativeState::changeValueInRevertList(QObject *target, const QByteArray &name, const QVariant &revertValue) +{ + Q_D(QDeclarativeState); + + if (isStateActive()) { + QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList); + + while (revertListIterator.hasNext()) { + QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) { + simpleAction.setValue(revertValue); + return true; + } + } + } + + return false; +} + +bool QDeclarativeState::changeBindingInRevertList(QObject *target, const QByteArray &name, QDeclarativeAbstractBinding *binding) +{ + Q_D(QDeclarativeState); + + if (isStateActive()) { + QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList); + + while (revertListIterator.hasNext()) { + QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) { + if (simpleAction.binding()) + simpleAction.binding()->destroy(); + + simpleAction.setBinding(binding); + return true; + } + } + } + + return false; +} + +bool QDeclarativeState::removeEntryFromRevertList(QObject *target, const QByteArray &name) +{ + Q_D(QDeclarativeState); + + if (isStateActive()) { + QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList); + + while (revertListIterator.hasNext()) { + QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); + if (simpleAction.property().object() == target && simpleAction.property().name().toUtf8() == name) { + QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property()); + if (oldBinding) { + QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0); + oldBinding->destroy(); + } + + simpleAction.property().write(simpleAction.value()); + if (simpleAction.binding()) + QDeclarativePropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding()); + + revertListIterator.remove(); + return true; + } + } + } + + return false; +} + +void QDeclarativeState::addEntryToRevertList(const QDeclarativeAction &action) +{ + Q_D(QDeclarativeState); + + QDeclarativeSimpleAction simpleAction(action); + + d->revertList.append(simpleAction); +} + +void QDeclarativeState::removeAllEntriesFromRevertList(QObject *target) +{ + Q_D(QDeclarativeState); + + if (isStateActive()) { + QMutableListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList); + + while (revertListIterator.hasNext()) { + QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); + if (simpleAction.property().object() == target) { + QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property()); + if (oldBinding) { + QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0); + oldBinding->destroy(); + } + + simpleAction.property().write(simpleAction.value()); + if (simpleAction.binding()) + QDeclarativePropertyPrivate::setBinding(simpleAction.property(), simpleAction.binding()); + + revertListIterator.remove(); + } + } + } +} + +void QDeclarativeState::addEntriesToRevertList(const QList<QDeclarativeAction> &actionList) +{ + Q_D(QDeclarativeState); + if (isStateActive()) { + QList<QDeclarativeSimpleAction> simpleActionList; + + QListIterator<QDeclarativeAction> actionListIterator(actionList); + while(actionListIterator.hasNext()) { + const QDeclarativeAction &action = actionListIterator.next(); + QDeclarativeSimpleAction simpleAction(action); + action.property.write(action.toValue); + if (action.toBinding) { + QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property()); + if (oldBinding) + QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0); + QDeclarativePropertyPrivate::setBinding(simpleAction.property(), action.toBinding, QDeclarativePropertyPrivate::DontRemoveBinding); + } + + simpleActionList.append(simpleAction); + } + + d->revertList.append(simpleActionList); + } +} + +QVariant QDeclarativeState::valueInRevertList(QObject *target, const QByteArray &name) const +{ + Q_D(const QDeclarativeState); + + if (isStateActive()) { + QListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList); + + while (revertListIterator.hasNext()) { + const QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) + return simpleAction.value(); + } + } + + return QVariant(); +} + +QDeclarativeAbstractBinding *QDeclarativeState::bindingInRevertList(QObject *target, const QByteArray &name) const +{ + Q_D(const QDeclarativeState); + + if (isStateActive()) { + QListIterator<QDeclarativeSimpleAction> revertListIterator(d->revertList); + + while (revertListIterator.hasNext()) { + const QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) + return simpleAction.binding(); + } + } + + return 0; +} + +bool QDeclarativeState::isStateActive() const +{ + return stateGroup() && stateGroup()->state() == name(); +} + void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransition *trans, QDeclarativeState *revert) { Q_D(QDeclarativeState); @@ -403,13 +589,13 @@ void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransit continue; bool found = false; for (int jj = 0; jj < d->revertList.count(); ++jj) { - QDeclarativeActionEvent *event = d->revertList.at(jj).event; + QDeclarativeActionEvent *event = d->revertList.at(jj).event(); if (event && event->typeName() == action.event->typeName()) { if (action.event->override(event)) { found = true; - if (action.event != d->revertList.at(jj).event && action.event->needsCopy()) { - action.event->copyOriginals(d->revertList.at(jj).event); + if (action.event != d->revertList.at(jj).event() && action.event->needsCopy()) { + action.event->copyOriginals(d->revertList.at(jj).event()); QDeclarativeSimpleAction r(action); additionalReverts << r; @@ -434,9 +620,9 @@ void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransit action.fromBinding = QDeclarativePropertyPrivate::binding(action.property); for (int jj = 0; jj < d->revertList.count(); ++jj) { - if (d->revertList.at(jj).property == action.property) { + if (d->revertList.at(jj).property() == action.property) { found = true; - if (d->revertList.at(jj).binding != action.fromBinding) { + if (d->revertList.at(jj).binding() != action.fromBinding) { action.deleteFromBinding(); } break; @@ -445,7 +631,7 @@ void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransit if (!found) { if (!action.restore) { - action.deleteFromBinding(); + action.deleteFromBinding();; } else { // Only need to revert the applyList action if the previous // state doesn't have a higher priority revert already @@ -460,8 +646,8 @@ void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransit // into this state need to be translated into apply actions for (int ii = 0; ii < d->revertList.count(); ++ii) { bool found = false; - if (d->revertList.at(ii).event) { - QDeclarativeActionEvent *event = d->revertList.at(ii).event; + if (d->revertList.at(ii).event()) { + QDeclarativeActionEvent *event = d->revertList.at(ii).event(); if (!event->isReversable()) continue; for (int jj = 0; !found && jj < applyList.count(); ++jj) { @@ -474,31 +660,31 @@ void QDeclarativeState::apply(QDeclarativeStateGroup *group, QDeclarativeTransit } else { for (int jj = 0; !found && jj < applyList.count(); ++jj) { const QDeclarativeAction &action = applyList.at(jj); - if (action.property == d->revertList.at(ii).property) + if (action.property == d->revertList.at(ii).property()) found = true; } } if (!found) { - QVariant cur = d->revertList.at(ii).property.read(); + QVariant cur = d->revertList.at(ii).property().read(); QDeclarativeAbstractBinding *delBinding = - QDeclarativePropertyPrivate::setBinding(d->revertList.at(ii).property, 0); + QDeclarativePropertyPrivate::setBinding(d->revertList.at(ii).property(), 0); if (delBinding) delBinding->destroy(); QDeclarativeAction a; - a.property = d->revertList.at(ii).property; + a.property = d->revertList.at(ii).property(); a.fromValue = cur; - a.toValue = d->revertList.at(ii).value; - a.toBinding = d->revertList.at(ii).binding; - a.specifiedObject = d->revertList.at(ii).specifiedObject; - a.specifiedProperty = d->revertList.at(ii).specifiedProperty; - a.event = d->revertList.at(ii).event; - a.reverseEvent = d->revertList.at(ii).reverseEvent; + a.toValue = d->revertList.at(ii).value(); + a.toBinding = d->revertList.at(ii).binding(); + a.specifiedObject = d->revertList.at(ii).specifiedObject(); + a.specifiedProperty = d->revertList.at(ii).specifiedProperty(); + a.event = d->revertList.at(ii).event(); + a.reverseEvent = d->revertList.at(ii).reverseEvent(); if (a.event && a.event->isRewindable()) a.event->saveCurrentValues(); applyList << a; // Store these special reverts in the reverting list - d->reverting << d->revertList.at(ii).property; + d->reverting << d->revertList.at(ii).property(); } } // All the local reverts now become part of the ongoing revertList @@ -526,4 +712,16 @@ QDeclarativeStateOperation::ActionList QDeclarativeStateOperation::actions() return ActionList(); } +QDeclarativeState *QDeclarativeStateOperation::state() const +{ + Q_D(const QDeclarativeStateOperation); + return d->m_state; +} + +void QDeclarativeStateOperation::setState(QDeclarativeState *state) +{ + Q_D(QDeclarativeStateOperation); + d->m_state = state; +} + QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativestate_p.h b/src/declarative/util/qdeclarativestate_p.h index 2e2ce7b..a0ab11b 100644 --- a/src/declarative/util/qdeclarativestate_p.h +++ b/src/declarative/util/qdeclarativestate_p.h @@ -111,6 +111,8 @@ public: //### rename to QDeclarativeStateChange? class QDeclarativeStateGroup; +class QDeclarativeState; +class QDeclarativeStateOperationPrivate; class Q_DECLARATIVE_EXPORT QDeclarativeStateOperation : public QObject { Q_OBJECT @@ -121,8 +123,15 @@ public: virtual ActionList actions(); + QDeclarativeState *state() const; + void setState(QDeclarativeState *state); + protected: QDeclarativeStateOperation(QObjectPrivate &dd, QObject *parent = 0); + +private: + Q_DECLARE_PRIVATE(QDeclarativeStateOperation) + Q_DISABLE_COPY(QDeclarativeStateOperation) }; typedef QDeclarativeStateOperation::ActionList QDeclarativeStateActions; @@ -169,6 +178,18 @@ public: QDeclarativeStateGroup *stateGroup() const; void setStateGroup(QDeclarativeStateGroup *); + bool containsPropertyInRevertList(QObject *target, const QByteArray &name) const; + bool changeValueInRevertList(QObject *target, const QByteArray &name, const QVariant &revertValue); + bool changeBindingInRevertList(QObject *target, const QByteArray &name, QDeclarativeAbstractBinding *binding); + bool removeEntryFromRevertList(QObject *target, const QByteArray &name); + void addEntryToRevertList(const QDeclarativeAction &action); + void removeAllEntriesFromRevertList(QObject *target); + void addEntriesToRevertList(const QList<QDeclarativeAction> &actions); + QVariant valueInRevertList(QObject *target, const QByteArray &name) const; + QDeclarativeAbstractBinding *bindingInRevertList(QObject *target, const QByteArray &name) const; + + bool isStateActive() const; + Q_SIGNALS: void completed(); diff --git a/src/declarative/util/qdeclarativestate_p_p.h b/src/declarative/util/qdeclarativestate_p_p.h index 2ef9bb0..c3c7bb4 100644 --- a/src/declarative/util/qdeclarativestate_p_p.h +++ b/src/declarative/util/qdeclarativestate_p_p.h @@ -61,6 +61,8 @@ #include <private/qdeclarativeproperty_p.h> #include <private/qdeclarativeguard_p.h> +#include <private/qdeclarativebinding_p.h> + #include <private/qobject_p.h> QT_BEGIN_NAMESPACE @@ -69,30 +71,123 @@ class QDeclarativeSimpleAction { public: enum State { StartState, EndState }; - QDeclarativeSimpleAction(const QDeclarativeAction &a, State state = StartState) + QDeclarativeSimpleAction(const QDeclarativeAction &a, State state = StartState) { - property = a.property; - specifiedObject = a.specifiedObject; - specifiedProperty = a.specifiedProperty; - event = a.event; + m_property = a.property; + m_specifiedObject = a.specifiedObject; + m_specifiedProperty = a.specifiedProperty; + m_event = a.event; if (state == StartState) { - value = a.fromValue; - binding = QDeclarativePropertyPrivate::binding(property); - reverseEvent = true; + m_value = a.fromValue; + if (QDeclarativePropertyPrivate::binding(m_property)) { + m_binding = QDeclarativePropertyPrivate::binding(m_property)->weakPointer(); + } + m_reverseEvent = true; } else { - value = a.toValue; - binding = a.toBinding; - reverseEvent = false; + m_value = a.toValue; + m_binding = a.toBinding->weakPointer(); + m_reverseEvent = false; } } - QDeclarativeProperty property; - QVariant value; - QDeclarativeAbstractBinding *binding; - QObject *specifiedObject; - QString specifiedProperty; - QDeclarativeActionEvent *event; - bool reverseEvent; + ~QDeclarativeSimpleAction() + { + } + + QDeclarativeSimpleAction(const QDeclarativeSimpleAction &other) + : m_property(other.m_property), + m_value(other.m_value), + m_binding(other.binding() ? other.binding()->weakPointer() : QDeclarativeAbstractBinding::Pointer()), + m_specifiedObject(other.m_specifiedObject), + m_specifiedProperty(other.m_specifiedProperty), + m_event(other.m_event), + m_reverseEvent(other.m_reverseEvent) + { + } + + QDeclarativeSimpleAction &operator =(const QDeclarativeSimpleAction &other) + { + m_property = other.m_property; + m_value = other.m_value; + m_binding = other.binding() ? other.binding()->weakPointer() : QDeclarativeAbstractBinding::Pointer(); + m_specifiedObject = other.m_specifiedObject; + m_specifiedProperty = other.m_specifiedProperty; + m_event = other.m_event; + m_reverseEvent = other.m_reverseEvent; + + return *this; + } + + void setProperty(const QDeclarativeProperty &property) + { + m_property = property; + } + + const QDeclarativeProperty &property() const + { + return m_property; + } + + void setValue(const QVariant &value) + { + m_value = value; + } + + const QVariant &value() const + { + return m_value; + } + + void setBinding(QDeclarativeAbstractBinding *binding) + { + m_binding = binding->weakPointer(); + } + + QDeclarativeAbstractBinding *binding() const + { + return m_binding.data(); + } + + QObject *specifiedObject() const + { + return m_specifiedObject; + } + + const QString &specifiedProperty() const + { + return m_specifiedProperty; + } + + QDeclarativeActionEvent *event() const + { + return m_event; + } + + bool reverseEvent() const + { + return m_reverseEvent; + } + +private: + QDeclarativeProperty m_property; + QVariant m_value; + QDeclarativeAbstractBinding::Pointer m_binding; + QObject *m_specifiedObject; + QString m_specifiedProperty; + QDeclarativeActionEvent *m_event; + bool m_reverseEvent; +}; + +class QDeclarativeStateOperationPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeStateOperation) + +public: + + QDeclarativeStateOperationPrivate() + : m_state(0) {} + + QDeclarativeState *m_state; }; class QDeclarativeStatePrivate : public QObjectPrivate @@ -122,10 +217,14 @@ public: static void operations_append(QDeclarativeListProperty<QDeclarativeStateOperation> *prop, QDeclarativeStateOperation *op) { QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data); + op->setState(qobject_cast<QDeclarativeState*>(prop->object)); list->append(OperationGuard(op, list)); } static void operations_clear(QDeclarativeListProperty<QDeclarativeStateOperation> *prop) { QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data); + QMutableListIterator<OperationGuard> listIterator(*list); + while(listIterator.hasNext()) + listIterator.next()->setState(0); list->clear(); } static int operations_count(QDeclarativeListProperty<QDeclarativeStateOperation> *prop) { diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp index a78fc54..ccbc4cd 100644 --- a/src/declarative/util/qdeclarativestateoperations.cpp +++ b/src/declarative/util/qdeclarativestateoperations.cpp @@ -52,6 +52,7 @@ #include "private/qdeclarativecontext_p.h" #include "private/qdeclarativeproperty_p.h" #include "private/qdeclarativebinding_p.h" +#include "private/qdeclarativestate_p_p.h" #include <QtCore/qdebug.h> #include <QtGui/qgraphicsitem.h> @@ -61,7 +62,7 @@ QT_BEGIN_NAMESPACE -class QDeclarativeParentChangePrivate : public QObjectPrivate +class QDeclarativeParentChangePrivate : public QDeclarativeStateOperationPrivate { Q_DECLARE_PUBLIC(QDeclarativeParentChange) public: @@ -580,7 +581,7 @@ void QDeclarativeParentChange::rewind() d->doChange(d->rewindParent, d->rewindStackBefore); } -class QDeclarativeStateChangeScriptPrivate : public QObjectPrivate +class QDeclarativeStateChangeScriptPrivate : public QDeclarativeStateOperationPrivate { public: QDeclarativeStateChangeScriptPrivate() {} @@ -965,7 +966,7 @@ void QDeclarativeAnchorSet::resetCenterIn() } -class QDeclarativeAnchorChangesPrivate : public QObjectPrivate +class QDeclarativeAnchorChangesPrivate : public QDeclarativeStateOperationPrivate { public: QDeclarativeAnchorChangesPrivate() diff --git a/src/declarative/util/qdeclarativetransitionmanager.cpp b/src/declarative/util/qdeclarativetransitionmanager.cpp index d82c4bb..89b0044 100644 --- a/src/declarative/util/qdeclarativetransitionmanager.cpp +++ b/src/declarative/util/qdeclarativetransitionmanager.cpp @@ -86,8 +86,8 @@ void QDeclarativeTransitionManager::complete() d->applyBindings(); for (int ii = 0; ii < d->completeList.count(); ++ii) { - const QDeclarativeProperty &prop = d->completeList.at(ii).property; - prop.write(d->completeList.at(ii).value); + const QDeclarativeProperty &prop = d->completeList.at(ii).property(); + prop.write(d->completeList.at(ii).value()); } d->completeList.clear(); |