Improve performance of State property changes

This patch is eliminating the switch from the state the base state and back if a property is changed.
 For that it is updating the internal caching values in QDeclarativeState.

Reviewed-by: Thomas Hartmann
This commit is contained in:
Marco Bubke
2010-03-22 13:18:52 +01:00
committed by Kai Koehne
parent d89d2db097
commit 5d3e4bacc0
16 changed files with 895 additions and 217 deletions

View File

@@ -43,9 +43,9 @@ FormEditorGraphicsView::FormEditorGraphicsView(QWidget *parent) :
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setResizeAnchor(QGraphicsView::AnchorViewCenter);
// setCacheMode(QGraphicsView::CacheNone);
setCacheMode(QGraphicsView::CacheBackground);
setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
// setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
// setCacheMode(QGraphicsView::CacheBackground);
// setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
setRenderHint(QPainter::Antialiasing, false);
setFrameShape(QFrame::NoFrame);

View File

@@ -329,8 +329,10 @@ void FormEditorScene::reparentItem(const QmlItemNode &node, const QmlItemNode &n
Q_ASSERT(hasItemForQmlItemNode(newParent));
FormEditorItem *item = itemForQmlItemNode(node);
FormEditorItem *parentItem = itemForQmlItemNode(newParent);
if (item->parentItem() != parentItem) {
item->setParentItem(parentItem);
item->setParent(parentItem);
item->update();
}
}
FormEditorItem* FormEditorScene::rootFormEditorItem() const

View File

@@ -58,6 +58,8 @@ class WidgetQueryView;
namespace Internal {
class ObjectNodeInstance;
class QmlGraphicsItemNodeInstance;
class QmlPropertyChangesNodeInstance;
class QmlStateNodeInstance;
}
class CORESHARED_EXPORT NodeInstance
@@ -71,6 +73,9 @@ class CORESHARED_EXPORT NodeInstance
friend CORESHARED_EXPORT class NodeMetaInfo;
friend class QmlDesigner::Internal::QmlGraphicsItemNodeInstance;
friend class QmlDesigner::Internal::ObjectNodeInstance;
friend class QmlDesigner::Internal::QmlPropertyChangesNodeInstance;
friend class QmlDesigner::Internal::QmlStateNodeInstance;
public:
NodeInstance();
~NodeInstance();
@@ -82,7 +87,7 @@ public:
NodeInstance parent() const;
bool hasParent() const;
ModelNode modelNode() const;
void setModelNode(const ModelNode &node);
bool isTopLevel() const;
@@ -119,13 +124,9 @@ public:
void makeInvalid();
bool hasContent() const;
const QObject *testHandle() const;
bool isWrappingThisObject(QObject *object) const;
void setPropertyVariant(const QString &name, const QVariant &value);
void setPropertyDynamicVariant(const QString &name, const QString &typeName, const QVariant &value);
void setPropertyBinding(const QString &name, const QString &expression);
void setPropertyDynamicBinding(const QString &name, const QString &typeName, const QString &expression);
QVariant resetVariant(const QString &name) const;
bool hasAnchor(const QString &name) const;
bool isAnchoredBy() const;
@@ -133,22 +134,35 @@ public:
int penWidth() const;
void activateState();
void deactivateState();
void refreshState();
static void registerDeclarativeTypes();
private: // functions
NodeInstance(const QSharedPointer<Internal::ObjectNodeInstance> &abstractInstance);
void setModelNode(const ModelNode &node);
void setPropertyVariant(const QString &name, const QVariant &value);
void setPropertyDynamicVariant(const QString &name, const QString &typeName, const QVariant &value);
void setPropertyBinding(const QString &name, const QString &expression);
void setPropertyDynamicBinding(const QString &name, const QString &typeName, const QString &expression);
void resetProperty(const QString &name);
void activateState();
void deactivateState();
void refreshState();
bool updateStateVariant(const NodeInstance &target, const QString &propertyName, const QVariant &value);
bool updateStateBinding(const NodeInstance &target, const QString &propertyName, const QString &expression);
bool resetStateProperty(const NodeInstance &target, const QString &propertyName, const QVariant &resetValue);
static NodeInstance create(NodeInstanceView *nodeInstanceView, const ModelNode &node, QObject *objectToBeWrapped);
static NodeInstance create(NodeInstanceView *nodeInstanceView, const NodeMetaInfo &metaInfo, QDeclarativeContext *context);
void setDeleteHeldInstance(bool deleteInstance);
void reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty);
void resetProperty(const QString &name);
void setId(const QString &id);

View File

@@ -51,6 +51,7 @@ namespace QmlDesigner {
namespace Internal {
class ChildrenChangeEventFilter;
class QmlStateNodeInstance;
}
class CORESHARED_EXPORT NodeInstanceView : public AbstractView
@@ -59,6 +60,7 @@ class CORESHARED_EXPORT NodeInstanceView : public AbstractView
friend class NodeInstance;
friend class Internal::ObjectNodeInstance;
friend class Internal::QmlStateNodeInstance;
public:
typedef QWeakPointer<NodeInstanceView> Pointer;
@@ -116,6 +118,11 @@ public:
void setBlockStatePropertyChanges(bool block);
NodeInstance activeStateInstance() const;
void activateState(const NodeInstance &instance);
void activateBaseState();
signals:
void instanceRemoved(const NodeInstance &nodeInstance);
@@ -138,8 +145,16 @@ private: // functions
Internal::ChildrenChangeEventFilter *childrenChangeEventFilter();
void removeInstanceAndSubInstances(const ModelNode &node);
void setInstancePropertyVariant(const VariantProperty &property);
void setInstancePropertyBinding(const BindingProperty &property);
void resetInstanceProperty(const AbstractProperty &property);
void setStateInstance(const NodeInstance &stateInstance);
void clearStateInstance();
private: //variables
NodeInstance m_rootNodeInstance;
NodeInstance m_activeStateInstance;
QScopedPointer<QGraphicsView> m_graphicsView;
QHash<ModelNode, NodeInstance> m_nodeInstanceHash;

View File

@@ -369,6 +369,7 @@ QRectF NodeInstance::boundingRect() const
void NodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
{
m_nodeInstance->setPropertyVariant(name, value);
}
void NodeInstance::setPropertyDynamicVariant(const QString &name, const QString &typeName, const QVariant &value)
@@ -485,9 +486,9 @@ bool operator==(const NodeInstance &first, const NodeInstance &second)
return first.m_nodeInstance.data() == second.m_nodeInstance.data();
}
const QObject *NodeInstance::testHandle() const
bool NodeInstance::isWrappingThisObject(QObject *object) const
{
return internalObject();
return internalObject() && internalObject() == object;
}
/*!
@@ -606,9 +607,24 @@ void NodeInstance::deactivateState()
m_nodeInstance->deactivateState();
}
void NodeInstance::refreshState()
bool NodeInstance::updateStateVariant(const NodeInstance &target, const QString &propertyName, const QVariant &value)
{
m_nodeInstance->refreshState();
return m_nodeInstance->updateStateVariant(target, propertyName, value);
}
bool NodeInstance::updateStateBinding(const NodeInstance &target, const QString &propertyName, const QString &expression)
{
return m_nodeInstance->updateStateBinding(target, propertyName, expression);
}
QVariant NodeInstance::resetVariant(const QString &propertyName) const
{
return m_nodeInstance->resetValue(propertyName);
}
bool NodeInstance::resetStateProperty(const NodeInstance &target, const QString &propertyName, const QVariant &resetValue)
{
return m_nodeInstance->resetStateProperty(target, propertyName, resetValue);
}
/*!

View File

@@ -13,6 +13,7 @@ namespace Internal {
NodeInstanceSignalSpy::NodeInstanceSignalSpy() :
QObject()
{
blockSignals(true);
}
void NodeInstanceSignalSpy::setObjectNodeInstance(const ObjectNodeInstance::Pointer &nodeInstance)

View File

@@ -83,8 +83,8 @@ namespace QmlDesigner {
The class will be rendered offscreen if not set otherwise.
\param Parent of this object. If this parent is deleted this instance is
deleted too.
\param Parent of this object. If this parent is d this instance is
d too.
\see ~NodeInstanceView setRenderOffScreen
*/
@@ -173,10 +173,7 @@ void NodeInstanceView::nodeRemoved(const ModelNode &/*removedNode*/, const NodeA
void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
{
foreach (const AbstractProperty &property, propertyList) {
if (hasInstanceForNode(property.parentModelNode())) { // TODO ugly workaround
NodeInstance instance = instanceForNode(property.parentModelNode());
instance.resetProperty(property.name());
}
resetInstanceProperty(property);
if (property.isNodeAbstractProperty()) {
foreach (const ModelNode &subNode, property.toNodeAbstractProperty().allSubNodes())
@@ -189,6 +186,93 @@ void NodeInstanceView::propertiesRemoved(const QList<AbstractProperty>& /*proper
{
}
void NodeInstanceView::resetInstanceProperty(const AbstractProperty &property)
{
if (hasInstanceForNode(property.parentModelNode())) { // TODO ugly workaround
NodeInstance instance = instanceForNode(property.parentModelNode());
Q_ASSERT(instance.isValid());
const QString name = property.name();
if (activeStateInstance().isValid()) {
bool statePropertyWasReseted = activeStateInstance().resetStateProperty(instance, name, instance.resetVariant(name));
if (!statePropertyWasReseted)
instance.resetProperty(name);
} else {
instance.resetProperty(name);
}
}
}
void NodeInstanceView::setInstancePropertyBinding(const BindingProperty &property)
{
NodeInstance instance = instanceForNode(property.parentModelNode());
const QString name = property.name();
const QString expression = property.expression();
if (activeStateInstance().isValid()) {
bool stateBindingWasUpdated = activeStateInstance().updateStateBinding(instance, name, expression);
if (!stateBindingWasUpdated) {
if (property.isDynamic())
instance.setPropertyDynamicBinding(name, property.dynamicTypeName(), expression);
else
instance.setPropertyBinding(name, expression);
}
} else {
if (property.isDynamic())
instance.setPropertyDynamicBinding(name, property.dynamicTypeName(), expression);
else
instance.setPropertyBinding(name, expression);
}
if (property.parentModelNode().isRootNode()
&& (name == "width" || name == "height")) {
QGraphicsObject *rootGraphicsObject = qobject_cast<QGraphicsObject*>(instance.internalObject());
if (rootGraphicsObject) {
m_graphicsView->setSceneRect(rootGraphicsObject->boundingRect());
}
}
instance.paintUpdate();
}
void NodeInstanceView::setInstancePropertyVariant(const VariantProperty &property)
{
NodeInstance instance = instanceForNode(property.parentModelNode());
const QString name = property.name();
const QVariant value = property.value();
if (activeStateInstance().isValid()) {
bool stateValueWasUpdated = activeStateInstance().updateStateVariant(instance, name, value);
if (!stateValueWasUpdated) {
if (property.isDynamic())
instance.setPropertyDynamicVariant(name, property.dynamicTypeName(), value);
else
instance.setPropertyVariant(name, value);
}
} else { //base state
if (property.isDynamic())
instance.setPropertyDynamicVariant(name, property.dynamicTypeName(), value);
else
instance.setPropertyVariant(name, value);
}
if (property.parentModelNode().isRootNode()
&& (name == "width" || name == "height")) {
QGraphicsObject *rootGraphicsObject = qobject_cast<QGraphicsObject*>(instance.internalObject());
if (rootGraphicsObject) {
m_graphicsView->setSceneRect(rootGraphicsObject->boundingRect());
}
}
instance.paintUpdate();
}
void NodeInstanceView::removeInstanceAndSubInstances(const ModelNode &node)
{
foreach(const ModelNode &subNode, node.allSubModelNodes()) {
@@ -213,22 +297,8 @@ void NodeInstanceView::rootNodeTypeChanged(const QString &/*type*/, int /*majorV
void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
{
foreach (const BindingProperty &property, propertyList) {
NodeInstance instance = instanceForNode(property.parentModelNode());
if (property.isDynamic())
instance.setPropertyDynamicBinding(property.name(), property.dynamicTypeName(), property.expression());
else
instance.setPropertyBinding(property.name(), property.expression());
if (property.parentModelNode().isRootNode()
&& (property.name() == "width" || property.name() == "height")) {
QGraphicsObject *rootGraphicsObject = qobject_cast<QGraphicsObject*>(instance.internalObject());
m_graphicsView->setSceneRect(rootGraphicsObject->boundingRect());
}
instance.paintUpdate();
}
foreach (const BindingProperty &property, propertyList)
setInstancePropertyBinding(property);
}
/*! \brief Notifing the view that a AbstractProperty value was changed to a ModelNode.
@@ -244,24 +314,8 @@ void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& pr
void NodeInstanceView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
{
foreach (const VariantProperty &property, propertyList) {
NodeInstance instance = instanceForNode(property.parentModelNode());
if (property.isDynamic())
instance.setPropertyDynamicVariant(property.name(), property.dynamicTypeName(), property.value());
else
instance.setPropertyVariant(property.name(), property.value());
if (property.parentModelNode().isRootNode()
&& (property.name() == "width" || property.name() == "height")) {
QGraphicsObject *rootGraphicsObject = qobject_cast<QGraphicsObject*>(instance.internalObject());
if (rootGraphicsObject) {
m_graphicsView->setSceneRect(rootGraphicsObject->boundingRect());
}
}
instance.paintUpdate();
}
foreach (const VariantProperty &property, propertyList)
setInstancePropertyVariant(property);
}
/*! \brief Notifing the view that a ModelNode has a new Parent.
@@ -361,7 +415,7 @@ void NodeInstanceView::removeAllInstanceNodeRelationships()
{
// prevent destroyed() signals calling back
//first delete the root object
//first the root object
if (rootNodeInstance().internalObject())
rootNodeInstance().internalObject()->disconnect();
@@ -502,7 +556,7 @@ void NodeInstanceView::removeInstanceNodeRelationship(const ModelNode &node)
void NodeInstanceView::notifyPropertyChange(const ModelNode &node, const QString &propertyName)
{
if (m_blockStatePropertyChanges && propertyName == "state")
if (m_blockStatePropertyChanges)
return;
if (qmlModelView()) {
@@ -526,6 +580,21 @@ void NodeInstanceView::setBlockStatePropertyChanges(bool block)
m_blockStatePropertyChanges = block;
}
void NodeInstanceView::setStateInstance(const NodeInstance &stateInstance)
{
m_activeStateInstance = stateInstance;
}
void NodeInstanceView::clearStateInstance()
{
m_activeStateInstance = NodeInstance();
}
NodeInstance NodeInstanceView::activeStateInstance() const
{
return m_activeStateInstance;
}
void NodeInstanceView::emitParentChanged(QObject *child)
{
if (hasInstanceForObject(child)) {
@@ -552,6 +621,18 @@ NodeInstance NodeInstanceView::loadNode(const ModelNode &node, QObject *objectTo
return instance;
}
void NodeInstanceView::activateState(const NodeInstance &instance)
{
NodeInstance stateInstance(instance);
stateInstance.activateState();
}
void NodeInstanceView::activateBaseState()
{
if (activeStateInstance().isValid())
activeStateInstance().deactivateState();
}
void NodeInstanceView::removeRecursiveChildRelationship(const ModelNode &removedNode)
{
foreach (const ModelNode &childNode, removedNode.allDirectSubModelNodes())

View File

@@ -121,11 +121,7 @@ void ObjectNodeInstance::destroy()
ModelNode parentNode = parentProperty.parentModelNode();
if (parentNode.isValid() && nodeInstanceView()->hasInstanceForNode(parentNode)) {
NodeInstance parentInstance = nodeInstanceView()->instanceForNode(parentNode);
if (parentInstance.isQmlGraphicsItem() && isChildrenProperty(parentProperty.name())) {
specialRemoveParentForQmlGraphicsItemChildren(object());
} else {
removeFromOldProperty(object(), parentInstance.internalObject(), parentProperty.name());
}
reparent(parentInstance, parentProperty.name(), NodeInstance() , QString());
}
}
@@ -330,9 +326,23 @@ static QVariant objectToVariant(QObject *object)
return QVariant::fromValue(object);
}
static void removeObjectFromList(const QDeclarativeProperty & /*metaProperty*/, QObject * /*object*/, QDeclarativeEngine * /*engine*/)
static void removeObjectFromList(const QDeclarativeProperty &metaProperty, QObject *objectToBeRemoved, QDeclarativeEngine * engine)
{
// ### Very few QML lists ever responded to removes
QDeclarativeListReference listReference(metaProperty.object(), metaProperty.name().toLatin1(), engine);
int count = listReference.count();
QObjectList objectList;
for(int i = 0; i < count; i ++) {
QObject *listItem = listReference.at(i);
if (listItem != objectToBeRemoved)
objectList.append(listItem);
}
listReference.clear();
foreach(QObject *object, objectList)
listReference.append(object);
}
void ObjectNodeInstance::removeFromOldProperty(QObject *object, QObject *oldParent, const QString &oldParentProperty)
@@ -394,7 +404,6 @@ void ObjectNodeInstance::reparent(const NodeInstance &oldParentInstance, const Q
void ObjectNodeInstance::setPropertyVariant(const QString &name, const QVariant &value)
{
QDeclarativeProperty QDeclarativeProperty(object(), name, context());
QDeclarativeProperty.write(value);
}
@@ -579,10 +588,6 @@ void ObjectNodeInstance::deactivateState()
{
}
void ObjectNodeInstance::refreshState()
{
}
QStringList propertyNameForWritableProperties(QObject *object, const QString &baseName = QString())
{
QStringList propertyNameList;
@@ -695,6 +700,21 @@ void ObjectNodeInstance::refreshBindings(QDeclarativeContext *context)
context->setContextProperty(QString("__dummy_%1").arg(i++), true);
}
bool ObjectNodeInstance::updateStateVariant(const NodeInstance &/*target*/, const QString &/*propertyName*/, const QVariant &/*value*/)
{
return false;
}
bool ObjectNodeInstance::updateStateBinding(const NodeInstance &/*target*/, const QString &/*propertyName*/, const QString &/*expression*/)
{
return false;
}
bool ObjectNodeInstance::resetStateProperty(const NodeInstance &/*target*/, const QString &/*propertyName*/, const QVariant &/*resetValue*/)
{
return false;
}
}
}

View File

@@ -102,7 +102,7 @@ public:
virtual QObject *parent() const;
void reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty);
virtual void reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty);
void setId(const QString &id);
@@ -155,7 +155,6 @@ public:
virtual void activateState();
virtual void deactivateState();
virtual void refreshState();
void populateResetValueHash();
QVariant resetValue(const QString &propertyName) const;
@@ -166,6 +165,10 @@ public:
QDeclarativeContext *context() const;
virtual bool updateStateVariant(const NodeInstance &target, const QString &propertyName, const QVariant &value);
virtual bool updateStateBinding(const NodeInstance &target, const QString &propertyName, const QString &expression);
virtual bool resetStateProperty(const NodeInstance &target, const QString &propertyName, const QVariant &resetValue);
protected:
static QObject* createObject(const NodeMetaInfo &metaInfo, QDeclarativeContext *context);

View File

@@ -34,6 +34,11 @@
#include <QDeclarativeExpression>
#include <private/qdeclarativebinding_p.h>
#include <metainfo.h>
#include <QMutableListIterator>
#include <private/qdeclarativestate_p_p.h>
#include <private/qdeclarativestategroup_p.h>
#include <private/qdeclarativeproperty_p.h>
namespace QmlDesigner {
namespace Internal {
@@ -47,61 +52,72 @@ QmlPropertyChangesObject::QmlPropertyChangesObject() :
QDeclarativeStateOperation::ActionList QmlPropertyChangesObject::actions()
{
ActionList list;
QMutableListIterator<QDeclarativeAction> actionIterator(m_qmlActionList);
foreach (const QString &property, m_properties.keys()) {
QDeclarativeAction a(m_targetObject.data(), property, m_properties.value(property));
if (a.property.isValid()) {
a.restore = restoreEntryValues();
if (a.property.propertyType() == QVariant::Url &&
(a.toValue.type() == QVariant::String || a.toValue.type() == QVariant::ByteArray) && !a.toValue.isNull())
a.toValue.setValue(qmlContext(this)->resolvedUrl(QUrl(a.toValue.toString())));
list << a;
}
}
// for (int ii = 0; ii < d->signalReplacements.count(); ++ii) {
//
// QmlReplaceSignalHandler *handler = d->signalReplacements.at(ii);
//
// if (handler->property.isValid()) {
// Action a;
// a.event = handler;
// list << a;
// }
// }
foreach (const QString &property, m_expressions.keys()) {
QDeclarativeProperty mProperty = metaProperty(property);
if (mProperty.isValid()) {
QDeclarativeAction a;
a.restore = restoreEntryValues();
a.property = mProperty;
a.fromValue = a.property.read();
a.specifiedObject = m_targetObject.data();
a.specifiedProperty = property;
if (m_isExplicit) {
a.toValue = QDeclarativeExpression(qmlContext(object()), m_expressions.value(property), object()).value();
while (actionIterator.hasNext()) {
QDeclarativeAction &action = actionIterator.next();
action.fromBinding = QDeclarativePropertyPrivate::binding(action.property);
action.fromValue = action.property.read();
if (m_expressionHash.contains(action.specifiedProperty)) {
if(m_expressionHash[action.specifiedProperty].second.isNull()) {
QDeclarativeBinding *binding = new QDeclarativeBinding(m_expressionHash[action.specifiedProperty].first, targetObject(), QDeclarativeEngine::contextForObject(targetObject()), this);
binding->setTarget(action.property);
binding->setNotifyOnValueChanged(true);
action.toBinding = binding;
action.toValue = binding->value();
m_expressionHash.insert(action.specifiedProperty, ExpressionPair(m_expressionHash[action.specifiedProperty].first, binding));
} else {
QDeclarativeBinding *newBinding = new QDeclarativeBinding(m_expressions.value(property), object(), qmlContext(object()));
newBinding->setTarget(mProperty);
a.toBinding = newBinding;
a.deletableToBinding = true;
action.toBinding = m_expressionHash[action.specifiedProperty].second.data();
action.toValue = m_expressionHash[action.specifiedProperty].second->value();
}
list << a;
} else {
action.toBinding = 0;
}
}
return list;
return m_qmlActionList;
}
QDeclarativeProperty QmlPropertyChangesObject::metaProperty(const QString &property)
QObject *QmlPropertyChangesObject::targetObject() const
{
return m_targetObject.data();
}
void QmlPropertyChangesObject::setTargetObject(QObject *object)
{
m_targetObject = object;
QMutableListIterator<QDeclarativeAction> actionIterator(m_qmlActionList);
while (actionIterator.hasNext()) {
QDeclarativeAction &qmlAction = actionIterator.next();
qmlAction.specifiedObject = object;
qmlAction.property = createMetaProperty(qmlAction.specifiedProperty);
qmlAction.fromValue = qmlAction.property.read();
qmlAction.fromBinding = QDeclarativePropertyPrivate::binding(qmlAction.property);
}
}
bool QmlPropertyChangesObject::restoreEntryValues() const
{
return m_restoreEntryValues;
}
void QmlPropertyChangesObject::setRestoreEntryValues(bool restore)
{
m_restoreEntryValues = restore;
}
bool QmlPropertyChangesObject::isExplicit() const
{
return m_isExplicit;
}
void QmlPropertyChangesObject::setIsExplicit(bool isExplicit)
{
m_isExplicit = isExplicit;
}
QDeclarativeProperty QmlPropertyChangesObject::createMetaProperty(const QString &property)
{
QDeclarativeProperty prop(m_targetObject.data(), property);
if (!prop.isValid()) {
@@ -138,9 +154,14 @@ void QmlPropertyChangesNodeInstance::setPropertyVariant(const QString &name, con
if (metaObject.indexOfProperty(name.toLatin1()) > 0) { // 'restoreEntryValues', 'explicit'
ObjectNodeInstance::setPropertyVariant(name, value);
return;
} else {
changesObject()->m_properties.insert(name, value); updateStateInstance();
changesObject()->setVariantValue(name, value);
QObject *targetObject = changesObject()->targetObject();
if (targetObject && nodeInstanceView()->activeStateInstance().isWrappingThisObject(changesObject()->state())) {
changesObject()->updateRevertValueAndBinding(name);
NodeInstance targetInstance = nodeInstanceView()->instanceForObject(targetObject);
targetInstance.setPropertyVariant(name, value);
}
}
}
@@ -150,32 +171,68 @@ void QmlPropertyChangesNodeInstance::setPropertyBinding(const QString &name, con
if (metaObject.indexOfProperty(name.toLatin1()) > 0) { // 'restoreEntryValues', 'explicit'
ObjectNodeInstance::setPropertyBinding(name, expression);
return;
} else {
changesObject()->m_expressions.insert(name, expression);
updateStateInstance();
changesObject()->setExpression(name, expression);
}
}
QVariant QmlPropertyChangesNodeInstance::property(const QString &name) const
{
if (changesObject()->m_properties.contains(name))
return changesObject()->m_properties.value(name);
if (changesObject()->m_expressions.contains(name))
return changesObject()->m_expressions.value(name);
if (changesObject()->hasVariantValue(name))
return changesObject()->variantValue(name);
if (changesObject()->hasExpression(name))
return QVariant(changesObject()->expression(name));
return QVariant();
}
void QmlPropertyChangesNodeInstance::resetProperty(const QString &name)
{
if (changesObject()->m_properties.contains(name))
changesObject()->m_properties.remove(name);
else if (changesObject()->m_expressions.contains(name))
changesObject()->m_expressions.remove(name);
// TODO: How to force states object to update?
changesObject()->resetProperty(name);
}
updateStateInstance();
void QmlPropertyChangesNodeInstance::reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty)
{
if (oldParentProperty == "changes") {
if (changesObject()) {
changesObject()->removeFromStateRevertList();
}
}
ObjectNodeInstance::reparent(oldParentInstance, oldParentProperty, newParentInstance, newParentProperty);
if (newParentProperty == "changes") {
if (changesObject()) {
changesObject()->addToStateRevertList();
}
}
}
QDeclarativeState *QmlPropertyChangesObject::state() const
{
if (!parent())
return 0;
Q_ASSERT(qobject_cast<QDeclarativeState*>(parent()));
return static_cast<QDeclarativeState*>(parent());
}
QDeclarativeStateGroup *QmlPropertyChangesObject::stateGroup() const
{
if (!state())
return 0;
return state()->stateGroup();
}
QDeclarativeStatePrivate *QmlPropertyChangesObject::statePrivate() const
{
if (!parent())
return 0;
Q_ASSERT(qobject_cast<QDeclarativeState*>(parent()));
return static_cast<QDeclarativeStatePrivate*>(QObjectPrivate::get(parent()));
}
QmlPropertyChangesObject *QmlPropertyChangesNodeInstance::changesObject() const
@@ -184,20 +241,358 @@ QmlPropertyChangesObject *QmlPropertyChangesNodeInstance::changesObject() const
return static_cast<QmlPropertyChangesObject*>(object());
}
void QmlPropertyChangesNodeInstance::updateStateInstance() const
QDeclarativeAction QmlPropertyChangesObject::createQDeclarativeAction(const QString &propertyName)
{
if (!nodeInstanceView()->hasInstanceForNode(modelNode()))
return;
QDeclarativeProperty qmlMetaProperty = createMetaProperty(propertyName);
NodeInstance myInstance = nodeInstanceView()->instanceForNode(modelNode());
Q_ASSERT(myInstance.isValid());
QDeclarativeAction qmlAction;
qmlAction.restore = true;
qmlAction.property = qmlMetaProperty;
qmlAction.fromValue = qmlMetaProperty.read();
qmlAction.fromBinding = QDeclarativePropertyPrivate::binding(qmlMetaProperty);
qmlAction.specifiedObject = m_targetObject.data();
qmlAction.specifiedProperty = propertyName;
qmlAction.event = 0;
NodeInstance qmlStateInstance = myInstance.parent();
if (!qmlStateInstance.isValid()
|| !qmlStateInstance.modelNode().isValid())
return;
return qmlAction;
}
qmlStateInstance.refreshState();
bool QmlPropertyChangesObject::hasActionForProperty(const QString &propertyName) const
{
for(ActionList::iterator actionIterator = m_qmlActionList.begin();
actionIterator != m_qmlActionList.end();
++actionIterator) {
QDeclarativeAction &qmlAction = *actionIterator;
if (qmlAction.specifiedProperty == propertyName) {
return true;
}
}
return false;
}
QDeclarativeAction &QmlPropertyChangesObject::qmlActionForProperty(const QString &propertyName) const
{
for(ActionList::iterator actionIterator = m_qmlActionList.begin();
actionIterator != m_qmlActionList.end();
++actionIterator) {
QDeclarativeAction &qmlAction = *actionIterator;
if (qmlAction.specifiedProperty == propertyName)
return qmlAction;
}
Q_ASSERT(false);
return m_qmlActionList[0];
}
void QmlPropertyChangesObject::removeActionForProperty(const QString &propertyName)
{
QMutableListIterator<QDeclarativeAction> actionIterator(m_qmlActionList);
while (actionIterator.hasNext()) {
QDeclarativeAction &qmlAction = actionIterator.next();
if (qmlAction.specifiedProperty == propertyName)
actionIterator.remove();
}
QMutableListIterator<QDeclarativeSimpleAction> simpleActionIterator(statePrivate()->revertList);
while (simpleActionIterator.hasNext()) {
QDeclarativeSimpleAction &qmlSimpleAction = simpleActionIterator.next();
if (qmlSimpleAction.specifiedProperty == propertyName && qmlSimpleAction.specifiedObject == targetObject()) {
simpleActionIterator.remove();
}
}
}
bool QmlPropertyChangesObject::isActive() const
{
if (state() && stateGroup())
return state()->name() == stateGroup()->state();
return false;
}
QmlPropertyChangesObject::~QmlPropertyChangesObject()
{
removeFromStateRevertList();
}
void QmlPropertyChangesObject::removeFromStateRevertList()
{
if (statePrivate()) {
QMutableListIterator<QDeclarativeSimpleAction> simpleActionIterator(statePrivate()->revertList);
while(simpleActionIterator.hasNext()) {
QDeclarativeSimpleAction &simpleAction = simpleActionIterator.next();
if (simpleAction.specifiedObject == targetObject()) {
Q_ASSERT(simpleAction.property.isValid());
if (simpleAction.binding) {
QDeclarativePropertyPrivate::setBinding(simpleAction.property, simpleAction.binding);
} else if (simpleAction.value.isValid()) {
QDeclarativePropertyPrivate::setBinding(simpleAction.property, 0);
simpleAction.property.write(simpleAction.value);
}
simpleActionIterator.remove();
}
}
}
}
void QmlPropertyChangesObject::addToStateRevertList()
{
if (isActive() && statePrivate()) {
QListIterator<QDeclarativeAction> actionIterator(m_qmlActionList);
while (actionIterator.hasNext()) {
const QDeclarativeAction &qmlAction = actionIterator.next();
QDeclarativeSimpleAction simpleAction(qmlAction);
simpleAction.binding = qmlAction.fromBinding;
simpleAction.value = qmlAction.fromValue;
statePrivate()->revertList.append(simpleAction);
if (qmlAction.toBinding)
QDeclarativePropertyPrivate::setBinding(qmlAction.property, qmlAction.toBinding);
else
qmlAction.property.write(qmlAction.toValue);
}
}
}
void QmlPropertyChangesObject::updateRevertValueAndBinding(const QString &name)
{
if (isActive() && statePrivate()) {
typedef QList<QDeclarativeSimpleAction> SimpleActionList;
if (!statePrivate()->revertList.isEmpty()) {
for(SimpleActionList::iterator actionIterator = statePrivate()->revertList.begin();
actionIterator != statePrivate()->revertList.end();
++actionIterator) {
//simple action defines values and bindings to revert current state
QDeclarativeSimpleAction &simpleAction = *actionIterator;
if (simpleAction.specifiedObject == targetObject()
&& simpleAction.specifiedProperty == name) {
const QDeclarativeAction &qmlAction = qmlActionForProperty(name);
simpleAction.value = qmlAction.fromValue;
simpleAction.binding = qmlAction.fromBinding;
return; //return since we just had to update exisisting simple action
}
}
}
//simple action does not exist, yet
const QDeclarativeAction &qmlAction = qmlActionForProperty(name);
QDeclarativeSimpleAction simpleAction(qmlAction);
simpleAction.binding = qmlAction.fromBinding;
simpleAction.value = qmlAction.fromValue;
statePrivate()->revertList.append(simpleAction);
}
}
void QmlPropertyChangesObject::setVariantValue(const QString &name, const QVariant & value)
{
if (!hasActionForProperty(name)) {
m_qmlActionList.append(createQDeclarativeAction(name));
}
QDeclarativeAction &qmlAction = qmlActionForProperty(name);
qmlAction.toValue = value;
}
void QmlPropertyChangesObject::setExpression(const QString &name, const QString &expression)
{
if (!hasActionForProperty(name)) {
m_qmlActionList.append(createQDeclarativeAction(name));
}
QDeclarativeAction &qmlAction = qmlActionForProperty(name);
if (m_expressionHash.contains(name) && m_expressionHash[name].second) {
m_expressionHash[name].second->destroy();
}
QDeclarativeContext *context = QDeclarativeEngine::contextForObject(targetObject());
QDeclarativeBinding *binding = 0;
QDeclarativeProperty metaProperty(targetObject(), name, context);
if (metaProperty.isValid() && metaProperty.isProperty()) {
binding = new QDeclarativeBinding(expression, targetObject(), context, this);
binding->setTarget(metaProperty);
binding->setNotifyOnValueChanged(true);
qmlAction.toBinding = binding;
m_expressionHash.insert(name, ExpressionPair(expression, binding));
} else {
qWarning() << "Cannot set binding for property" << name << ": property is unknown for type";
}
updateRevertValueAndBinding(name);
if (isActive())
QDeclarativePropertyPrivate::setBinding(metaProperty, binding, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
}
void QmlPropertyChangesObject::removeVariantValue(const QString &name)
{
if (hasActionForProperty(name)) {
QDeclarativeAction &qmlAction = qmlActionForProperty(name);
if (hasExpression(name)) {
qmlAction.toValue = QVariant();
updateRevertValueAndBinding(name);
} else {
if (qmlAction.fromBinding)
QDeclarativePropertyPrivate::setBinding(qmlAction.property, qmlAction.fromBinding);
else
qmlAction.property.write(qmlAction.fromValue);
removeActionForProperty(name);
}
}
}
void QmlPropertyChangesObject::removeExpression(const QString &name)
{
if (hasActionForProperty(name)) {
QDeclarativeAction &qmlAction = qmlActionForProperty(name);
if (hasVariantValue(name)) {
ExpressionPair expr = m_expressionHash.take(name);
if (expr.second)
expr.second.data()->destroy();
qmlAction.toBinding = 0;
updateRevertValueAndBinding(name);
qmlAction.property.write(qmlAction.toValue);
} else {
if (qmlAction.fromBinding)
QDeclarativePropertyPrivate::setBinding(qmlAction.property, qmlAction.fromBinding);
else
qmlAction.property.write(qmlAction.fromValue);
removeActionForProperty(name);
}
}
}
void QmlPropertyChangesObject::resetProperty(const QString &name)
{
if (statePrivate()) {
QMutableListIterator<QDeclarativeSimpleAction> simpleActionIterator(statePrivate()->revertList);
while (simpleActionIterator.hasNext()) {
QDeclarativeSimpleAction &qmlSimpleAction = simpleActionIterator.next();
if (qmlSimpleAction.specifiedProperty == name && qmlSimpleAction.specifiedObject == targetObject()) {
if (qmlSimpleAction.binding) {
qDebug() << qmlSimpleAction.binding->expression();
QDeclarativePropertyPrivate::setBinding(qmlSimpleAction.property, qmlSimpleAction.binding);
} else {
QDeclarativePropertyPrivate::setBinding(qmlSimpleAction.property, 0);
qmlSimpleAction.property.write(qmlSimpleAction.value);
}
}
}
}
if (m_expressionHash.contains(name)) {
if (m_expressionHash[name].second)
m_expressionHash[name].second.data()->destroy();
m_expressionHash.remove(name);
}
if (hasActionForProperty(name)) {
removeActionForProperty(name);
}
}
QVariant QmlPropertyChangesObject::variantValue(const QString &name) const
{
if (hasActionForProperty(name)) {
QDeclarativeAction &qmlAction = qmlActionForProperty(name);
return qmlAction.toValue;
}
return QVariant();
}
QString QmlPropertyChangesObject::expression(const QString &name) const
{
if (hasActionForProperty(name)) {
QDeclarativeAction &qmlAction = qmlActionForProperty(name);
if (qmlAction.toBinding)
return qmlAction.toBinding->expression();
}
return QString();
}
bool QmlPropertyChangesObject::hasVariantValue(const QString &name) const
{
if (hasActionForProperty(name))
return qmlActionForProperty(name).toValue.isValid();
return false;
}
bool QmlPropertyChangesObject::hasExpression(const QString &name) const
{
return m_expressionHash.contains(name);
}
bool QmlPropertyChangesObject::updateStateVariant(const QString &name, const QVariant &value)
{
if (hasActionForProperty(name)) {
QDeclarativeAction &qmlAction = qmlActionForProperty(name);
if (qmlAction.fromValue.isValid()) {
qmlAction.fromValue = value;
updateRevertValueAndBinding(name);
return true;
}
}
return false;
}
bool QmlPropertyChangesObject::updateStateBinding(const QString &name, const QString &expression)
{
if (hasActionForProperty(name)) {
QDeclarativeContext *context = QDeclarativeEngine::contextForObject(targetObject());
QDeclarativeProperty metaProperty(targetObject(), name, context);
QDeclarativeAction &qmlAction = qmlActionForProperty(name);
if (qmlAction.fromBinding) {
if (QDeclarativePropertyPrivate::binding(qmlAction.property) == qmlAction.fromBinding)
QDeclarativePropertyPrivate::setBinding(qmlAction.property, 0);
qmlAction.fromBinding->destroy();
}
QDeclarativeBinding *binding = new QDeclarativeBinding(expression, targetObject(), context, this);
binding->setTarget(metaProperty);
binding->setNotifyOnValueChanged(true);
qmlAction.fromBinding = binding;
if (m_expressionHash.contains(name))
QDeclarativePropertyPrivate::setBinding(qmlAction.property, binding);
updateRevertValueAndBinding(name);
return true;
}
return false;
}
bool QmlPropertyChangesObject::resetStateProperty(const QString &name, const QVariant &resetValue)
{
if (hasActionForProperty(name)) {
QDeclarativeContext *context = QDeclarativeEngine::contextForObject(targetObject());
QDeclarativeProperty metaProperty(targetObject(), name, context);
QDeclarativeAction &qmlAction = qmlActionForProperty(name);
if (m_expressionHash.contains(name) && m_expressionHash[name].second) {
m_expressionHash[name].second.data()->destroy();
qmlAction.toBinding = 0;
}
qmlAction.fromValue = resetValue;
updateRevertValueAndBinding(name);
removeActionForProperty(name);
return true;
}
return false;
}
} // namespace Internal

View File

@@ -33,6 +33,11 @@
#include "objectnodeinstance.h"
#include <private/qdeclarativestateoperations_p.h>
#include <QPair>
#include <QWeakPointer>
class QDeclarativeProperty;
namespace QmlDesigner {
namespace Internal {
@@ -44,35 +49,70 @@ class QmlPropertyChangesNodeInstance;
class QmlPropertyChangesObject : public QDeclarativeStateOperation
{
Q_OBJECT
Q_PROPERTY(QObject *target READ object WRITE setObject)
Q_PROPERTY(QObject *target READ targetObject WRITE setTargetObject)
Q_PROPERTY(bool restoreEntryValues READ restoreEntryValues WRITE setRestoreEntryValues)
Q_PROPERTY(bool explicit READ isExplicit WRITE setIsExplicit)
typedef QPair<QString, QWeakPointer<QDeclarativeBinding> > ExpressionPair;
public:
QObject *object() const { return m_targetObject.data(); }
void setObject(QObject *object) {m_targetObject = object; }
~QmlPropertyChangesObject();
QObject *targetObject() const;
void setTargetObject(QObject *object);
bool restoreEntryValues() const { return m_restoreEntryValues; }
void setRestoreEntryValues(bool restore) { m_restoreEntryValues = restore; }
bool restoreEntryValues() const;
void setRestoreEntryValues(bool restore);
bool isExplicit() const { return m_isExplicit; }
void setIsExplicit(bool isExplicit) { m_isExplicit = isExplicit; }
bool isExplicit() const;
void setIsExplicit(bool isExplicit);
virtual ActionList actions();
private:
friend class QmlPropertyChangesNodeInstance;
void setVariantValue(const QString &name, const QVariant & value);
void setExpression(const QString &name, const QString &expression);
void removeVariantValue(const QString &name);
void removeExpression(const QString &name);
void resetProperty(const QString &name);
QVariant variantValue(const QString &name) const;
QString expression(const QString &name) const;
bool hasVariantValue(const QString &name) const;
bool hasExpression(const QString &name) const;
QmlPropertyChangesObject();
QDeclarativeProperty metaProperty(const QString &property);
bool updateStateVariant(const QString &propertyName, const QVariant &value);
bool updateStateBinding(const QString &propertyName, const QString &expression);
bool resetStateProperty(const QString &propertyName, const QVariant &resetValue);
QDeclarativeState *state() const;
void updateRevertValueAndBinding(const QString &name);
void removeFromStateRevertList();
void addToStateRevertList();
private: // functions
bool isActive() const;
QDeclarativeStatePrivate *statePrivate() const;
QDeclarativeStateGroup *stateGroup() const;
QDeclarativeProperty createMetaProperty(const QString &property);
QDeclarativeAction &qmlActionForProperty(const QString &propertyName) const;
bool hasActionForProperty(const QString &propertyName) const;
void removeActionForProperty(const QString &propertyName);
QDeclarativeAction createQDeclarativeAction(const QString &propertyName);
private: // variables
QWeakPointer<QObject> m_targetObject;
bool m_restoreEntryValues;
bool m_isExplicit;
QHash<QString, QVariant> m_properties;
QHash<QString, QString> m_expressions;
// QList<QmlReplaceSignalHandler*> signalReplacements;
mutable ActionList m_qmlActionList;
QHash<QString, ExpressionPair> m_expressionHash;
};
class QmlPropertyChangesNodeInstance : public ObjectNodeInstance
@@ -88,7 +128,7 @@ public:
virtual QVariant property(const QString &name) const;
virtual void resetProperty(const QString &name);
void updateStateInstance() const;
void reparent(const NodeInstance &oldParentInstance, const QString &oldParentProperty, const NodeInstance &newParentInstance, const QString &newParentProperty);
protected:
QmlPropertyChangesNodeInstance(QmlPropertyChangesObject *object);

View File

@@ -32,14 +32,16 @@
#include <private/qdeclarativestategroup_p.h>
#include "qmlpropertychangesnodeinstance.h"
#include <private/qdeclarativestateoperations_p.h>
namespace QmlDesigner {
namespace Internal {
/**
\class QmlStateNodeInstance
QmlStateNodeInstance manages a QDeclarativeState object. One can activate / deactivate a state
by setting/unsetting the special "__activateState" boolean property.
QmlStateNodeInstance manages a QDeclarativeState object.
*/
QmlStateNodeInstance::QmlStateNodeInstance(QDeclarativeState *object) :
@@ -68,6 +70,7 @@ void QmlStateNodeInstance::activateState()
{
if (stateGroup()) {
if (!isStateActive())
nodeInstanceView()->setStateInstance(nodeInstanceView()->instanceForNode(modelNode()));
stateGroup()->setState(property("name").toString());
}
}
@@ -75,17 +78,11 @@ void QmlStateNodeInstance::activateState()
void QmlStateNodeInstance::deactivateState()
{
if (stateGroup()) {
if (isStateActive())
if (isStateActive()) {
nodeInstanceView()->clearStateInstance();
stateGroup()->setState(QString());
}
}
void QmlStateNodeInstance::refreshState()
{
nodeInstanceView()->setBlockStatePropertyChanges(true);
deactivateState();
activateState();
nodeInstanceView()->setBlockStatePropertyChanges(false);
}
QDeclarativeState *QmlStateNodeInstance::stateObject() const
@@ -127,5 +124,45 @@ void QmlStateNodeInstance::setPropertyBinding(const QString &name, const QString
ObjectNodeInstance::setPropertyBinding(name, expression);
}
bool QmlStateNodeInstance::updateStateVariant(const NodeInstance &target, const QString &propertyName, const QVariant &value)
{
// iterate over propertychange object and update values
QDeclarativeListReference listReference(stateObject(), "changes");
for (int i = 0; i < listReference.count(); i++) {
//We also have parent and anchor changes
QmlPropertyChangesObject *changeObject = qobject_cast<QmlPropertyChangesObject*>(listReference.at(i));
if (changeObject && target.isWrappingThisObject(changeObject->targetObject()))
return changeObject->updateStateVariant(propertyName, value);
}
return false;
}
bool QmlStateNodeInstance::updateStateBinding(const NodeInstance &target, const QString &propertyName, const QString &expression)
{
// iterate over propertychange object and update binding
QDeclarativeListReference listReference(stateObject(), "changes");
for (int i = 0; i < listReference.count(); i++) {
QmlPropertyChangesObject *changeObject = qobject_cast<QmlPropertyChangesObject*>(listReference.at(i));
if (changeObject && target.isWrappingThisObject(changeObject->targetObject()))
return changeObject->updateStateBinding(propertyName, expression);
}
return false;
}
bool QmlStateNodeInstance::resetStateProperty(const NodeInstance &target, const QString &propertyName, const QVariant &resetValue)
{
// iterate over propertychange object and reset propertry
QDeclarativeListReference listReference(stateObject(), "changes");
for (int i = 0; i < listReference.count(); i++) {
QmlPropertyChangesObject *changeObject = qobject_cast<QmlPropertyChangesObject*>(listReference.at(i));
if (changeObject && target.isWrappingThisObject(changeObject->targetObject()))
return changeObject->resetStateProperty(propertyName, resetValue);
}
return false;
}
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -54,9 +54,14 @@ public:
void activateState();
void deactivateState();
void refreshState();
bool updateStateVariant(const NodeInstance &target, const QString &propertyName, const QVariant &value);
bool updateStateBinding(const NodeInstance &target, const QString &propertyName, const QString &expression);
bool resetStateProperty(const NodeInstance &target, const QString &propertyName, const QVariant &resetValue);
protected:
QmlStateNodeInstance(QDeclarativeState *object);
bool isStateActive() const;

View File

@@ -272,6 +272,7 @@ static bool isTransformProperty(const QString &name)
void QmlModelView::nodeInstancePropertyChanged(const ModelNode &node, const QString &propertyName)
{
QmlObjectNode qmlObjectNode(node);
if (!qmlObjectNode.isValid())
@@ -298,18 +299,16 @@ void QmlModelView::activateState(const QmlModelState &state)
QmlModelState oldState = m_state;
NodeInstance newStateInstance = instanceForModelNode(state.modelNode());
NodeInstance oldStateInstance = oldState.isValid() ? instanceForModelNode(oldState.modelNode()) : NodeInstance();
if (state.isBaseState()) {
if (oldStateInstance.isValid())
oldStateInstance.deactivateState();
nodeInstanceView()->activateBaseState();
} else {
newStateInstance.activateState();
nodeInstanceView()->activateState(newStateInstance);
}
m_state = state;
stateChanged(state, oldState);
}
stateChanged(state, oldState);}
void QmlModelView::changeToState(const ModelNode &node, const QString &stateName)
{

View File

@@ -64,6 +64,8 @@ void QmlObjectNode::setBindingProperty(const QString &name, const QString &expre
if (isInBaseState()) {
modelNode().bindingProperty(name) = expression; //basestate
} else {
modelNode().validId();
QmlPropertyChanges changeSet(currentState().propertyChanges(modelNode()));
Q_ASSERT(changeSet.isValid());
changeSet.modelNode().bindingProperty(name) = expression;

View File

@@ -3651,36 +3651,36 @@ void TestCore::testInstancesStates()
// base state
QVERIFY(textInstance.isValid());
QCOMPARE(state1Instance.property("__activateState").toBool(), false);
QCOMPARE(state2Instance.property("__activateState").toBool(), false);
QCOMPARE(state1Instance == instanceView->stateInstance(), false);
QCOMPARE(state2Instance == instanceView->stateInstance(), false);
QCOMPARE(textInstance.property("x").toInt(), 0);
QCOMPARE(textInstance.property("text").toString(), QString("base state"));
// base state -> state
state1Instance.setPropertyVariant("__activateState", true);
QCOMPARE(state1Instance.property("__activateState").toBool(), true);
QCOMPARE(state2Instance.property("__activateState").toBool(), false);
instanceView->activateState(state1Instance);
QCOMPARE(state1Instance == instanceView->stateInstance(), true);
QCOMPARE(state2Instance == instanceView->stateInstance(), false);
QCOMPARE(textInstance.property("x").toInt(), 10);
QCOMPARE(textInstance.property("text").toString(), QString("state1"));
// state 1 -> state 2
state2Instance.setPropertyVariant("__activateState", true);
QCOMPARE(state1Instance.property("__activateState").toBool(), false);
QCOMPARE(state2Instance.property("__activateState").toBool(), true);
instanceView->activateState(state2Instance);
QCOMPARE(state1Instance == instanceView->stateInstance(), false);
QCOMPARE(state2Instance == instanceView->stateInstance(), true);
QCOMPARE(textInstance.property("x").toInt(), 0);
QCOMPARE(textInstance.property("text").toString(), QString("state2"));
// state 1 -> base state
state2Instance.setPropertyVariant("__activateState", false);
QCOMPARE(state1Instance.property("__activateState").toBool(), false);
QCOMPARE(state2Instance.property("__activateState").toBool(), false);
instanceView->activateBaseState();
QCOMPARE(state1Instance == instanceView->stateInstance(), false);
QCOMPARE(state2Instance == instanceView->stateInstance(), false);
QCOMPARE(textInstance.property("x").toInt(), 0);
QCOMPARE(textInstance.property("text").toString(), QString("base state"));
//
// Add/Change/Remove properties in current state
//
state1Instance.setPropertyVariant("__activateState", true);
instanceView->activateState(state1Instance);
propertyChanges1Node.variantProperty("x").setValue(20);
QCOMPARE(textInstance.property("x").toInt(), 20);
@@ -3707,37 +3707,85 @@ void TestCore::testInstancesStates()
// Reparenting state actions (while state is active)
//
// state1Instance.setPropertyVariant("__activateState", true);
// // move property changes of current state out of state
// ModelNode state3Node = view->createModelNode("Qt/State", 4, 6);
// state3Node.nodeListProperty("changes").reparentHere(propertyChanges1Node);
//
// QCOMPARE(state1->changes()->count(), 0);
// QCOMPARE(textInstance.property("text").toString(), QString("base state"));
//
// // undo
// state1Node.nodeListProperty("changes").reparentHere(propertyChanges1Node);
// QCOMPARE(state1->changes()->count(), 1);
// QCOMPARE(textInstance.property("text").toString(), QString("state 1"));
// move property changes of current state out of state
ModelNode state3Node = view->createModelNode("Qt/State", 4, 6);
QDeclarativeListReference changes(state1, "changes");
QCOMPARE(changes.count(), 1);
state3Node.nodeListProperty("changes").reparentHere(propertyChanges1Node);
QCOMPARE(changes.count(), 0);
QCOMPARE(textInstance.property("text").toString(), QString("base state"));
// undo
state1Node.nodeListProperty("changes").reparentHere(propertyChanges1Node);
QCOMPARE(changes.count(), 1);
QCOMPARE(textInstance.property("text").toString(), QString("state1"));
// change base state if in state1
textNode.variantProperty("text").setValue("state1 and base state");
QCOMPARE(textInstance.property("text").toString(), QString("state1"));
instanceView->activateBaseState();
QCOMPARE(textInstance.property("text").toString(), QString("state1 and base state"));
textNode.variantProperty("text").setValue("base state");
// expressions
ModelNode textNode2 = view->createModelNode("Qt/Text", 4, 6);
textNode2.setId("targetObject2");
textNode2.variantProperty("text").setValue("textNode2");
rootNode.nodeListProperty("data").reparentHere(textNode2);
propertyChanges1Node.bindingProperty("text").setExpression("targetObject2.text");
instanceView->activateState(state1Instance);
QCOMPARE(textInstance.property("text").toString(), QString("textNode2"));
propertyChanges1Node.removeProperty("text");
QCOMPARE(textInstance.property("text").toString(), QString("base state"));
propertyChanges1Node.variantProperty("text").setValue("state1");
QCOMPARE(textInstance.property("text").toString(), QString("state1"));
propertyChanges1Node.bindingProperty("text").setExpression("targetObject2.text");
QCOMPARE(textInstance.property("text").toString(), QString("textNode2"));
instanceView->activateBaseState();
QCOMPARE(textInstance.property("text").toString(), QString("base state"));
propertyChanges1Node.variantProperty("text").setValue("state1");
QCOMPARE(textInstance.property("text").toString(), QString("base state"));
textNode.bindingProperty("text").setExpression("targetObject2.text");
QCOMPARE(textInstance.property("text").toString(), QString("textNode2"));
instanceView->activateState(state1Instance);
QCOMPARE(textInstance.property("text").toString(), QString("state1"));
instanceView->activateBaseState();
QCOMPARE(textInstance.property("text").toString(), QString("textNode2"));
textNode.variantProperty("text").setValue("base state");
instanceView->activateState(state1Instance);
//
// Removing state actions (while state is active)
//
// state1Instance.setPropertyVariant("__activateState", true);
// QCOMPARE(textInstance.property("text").toString(), QString("state1"));
// propertyChanges1Node.destroy();
// QCOMPARE(state1->changes()->count(), 0);
// QCOMPARE(textInstance.property("text").toString(), QString("base state"));
QCOMPARE(textInstance.property("text").toString(), QString("state1"));
propertyChanges1Node.destroy();
QCOMPARE(changes.count(), 0);
QCOMPARE(textInstance.property("text").toString(), QString("base state"));
//
// Removing state (while active)
//
// state2Instance.setPropertyVariant("__activateState", true);
// QCOMPARE(textInstance.property("text").toString(), QString("state2"));
// state2Node.destroy();
// QCOMPARE(textInstance.property("text").toString(), QString("base state"));
instanceView->activateState(state2Instance);
QCOMPARE(textInstance.property("text").toString(), QString("state2"));
state2Node.destroy();
QCOMPARE(textInstance.property("text").toString(), QString("base state"));
}
void TestCore::testStates()
@@ -3796,14 +3844,14 @@ void TestCore::testStates()
NodeInstance state1Instance = view->nodeInstanceView()->instanceForNode(state1);
QVERIFY(state1Instance.isValid());
QCOMPARE(state1Instance.property("__activateState").toBool(), false);
QCOMPARE(state1Instance == view->nodeInstanceView()->stateInstance(), false);
QCOMPARE(state1Instance.property("name").toString(), QString("state 1"));
view->setCurrentState(state1); //set currentState "state 1"
QCOMPARE(view->currentState(), state1);
QCOMPARE(state1Instance.property("__activateState").toBool(), true);
QCOMPARE(state1Instance == view->nodeInstanceView()->stateInstance(), true);
QVERIFY(!textItem.propertyAffectedByCurrentState("text"));
@@ -3825,7 +3873,7 @@ void TestCore::testStates()
QCOMPARE(changes.modelNode().parentProperty().name(), QString("changes"));
QCOMPARE(changes.modelNode().parentProperty().parentModelNode(), state1.modelNode());
QCOMPARE(state1Instance.property("__activateState").toBool(), true);
QCOMPARE(state1Instance == view->nodeInstanceView()->stateInstance(), true);
QVERIFY(textItem.propertyAffectedByCurrentState("text"));