summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWarwick Allison <warwick.allison@nokia.com>2009-10-12 00:33:01 (GMT)
committerWarwick Allison <warwick.allison@nokia.com>2009-10-12 00:33:01 (GMT)
commite508e614ccb4406ce43abb2c230c9d9ac976a573 (patch)
tree6fadedce2c08561185e6d846e83416fe22d8c72c
parent86cd2fa6836c90ed329eb1f0507eeb311810c194 (diff)
parenteca4d3662d61aea60478772d8cfa477642d284df (diff)
downloadQt-e508e614ccb4406ce43abb2c230c9d9ac976a573.zip
Qt-e508e614ccb4406ce43abb2c230c9d9ac976a573.tar.gz
Qt-e508e614ccb4406ce43abb2c230c9d9ac976a573.tar.bz2
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
-rw-r--r--src/corelib/kernel/qmetaobject.cpp5
-rw-r--r--src/declarative/extra/qmlbehavior.cpp179
-rw-r--r--src/declarative/extra/qmlbehavior.h22
-rw-r--r--src/declarative/qml/qml.pri2
-rw-r--r--src/declarative/qml/qmlbinding.cpp20
-rw-r--r--src/declarative/qml/qmlbinding.h12
-rw-r--r--src/declarative/qml/qmlbindingoptimizations.cpp32
-rw-r--r--src/declarative/qml/qmlbindingoptimizations_p.h9
-rw-r--r--src/declarative/qml/qmlcompiler.cpp47
-rw-r--r--src/declarative/qml/qmlcompiler_p.h3
-rw-r--r--src/declarative/qml/qmlcomponent.cpp2
-rw-r--r--src/declarative/qml/qmlinstruction.cpp3
-rw-r--r--src/declarative/qml/qmlinstruction_p.h6
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp86
-rw-r--r--src/declarative/qml/qmlmetaproperty.h9
-rw-r--r--src/declarative/qml/qmlmetaproperty_p.h9
-rw-r--r--src/declarative/qml/qmlmetatype.cpp29
-rw-r--r--src/declarative/qml/qmlmetatype.h14
-rw-r--r--src/declarative/qml/qmlparser.cpp3
-rw-r--r--src/declarative/qml/qmlparser_p.h2
-rw-r--r--src/declarative/qml/qmlpropertyvalueinterceptor.cpp77
-rw-r--r--src/declarative/qml/qmlpropertyvalueinterceptor.h68
-rw-r--r--src/declarative/qml/qmlvaluetype.cpp40
-rw-r--r--src/declarative/qml/qmlvaluetype_p.h19
-rw-r--r--src/declarative/qml/qmlvaluetypescriptclass.cpp2
-rw-r--r--src/declarative/qml/qmlvme.cpp86
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp27
-rw-r--r--src/declarative/qml/qmlvmemetaobject_p.h4
-rw-r--r--src/declarative/util/qmlanimation.cpp24
-rw-r--r--src/declarative/util/qmlpropertychanges.cpp19
-rw-r--r--src/declarative/util/qmlstate.cpp4
-rw-r--r--src/declarative/util/qmltransitionmanager.cpp11
32 files changed, 536 insertions, 339 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index f98c449..10eb955 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -2237,7 +2237,10 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const
// -1 (unchanged): normal qt_metacall, result stored in argv[0]
// changed: result stored directly in value, return the value of status
int status = -1;
- void *argv[] = { 0, &v, &status };
+ // the flags variable is used by the declarative module to implement
+ // interception of property writes.
+ int flags = 0;
+ void *argv[] = { 0, &v, &status, &flags };
if (t == QVariant::LastType)
argv[0] = &v;
else
diff --git a/src/declarative/extra/qmlbehavior.cpp b/src/declarative/extra/qmlbehavior.cpp
index 7784ef5..e30bd39 100644
--- a/src/declarative/extra/qmlbehavior.cpp
+++ b/src/declarative/extra/qmlbehavior.cpp
@@ -44,180 +44,77 @@
#include "qmltransition.h"
#include "qmlbehavior.h"
#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlinfo.h>
#include <QtCore/qparallelanimationgroup.h>
QT_BEGIN_NAMESPACE
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Behavior,QmlBehavior)
-class QmlBehaviorData : public QObject
-{
-Q_OBJECT
-public:
- QmlBehaviorData(QObject *parent)
- : QObject(parent) {}
-
- Q_PROPERTY(QVariant endValue READ endValue NOTIFY valuesChanged)
- Q_PROPERTY(QVariant startValue READ startValue NOTIFY valuesChanged)
- QVariant endValue() const { return e; }
- QVariant startValue() const { return s; }
-
- QVariant e;
- QVariant s;
-
-Q_SIGNALS:
- void valuesChanged();
-
-private:
- friend class QmlBehavior;
-};
-
class QmlBehaviorPrivate : public QObjectPrivate
{
+ Q_DECLARE_PUBLIC(QmlBehavior)
public:
- QmlBehaviorPrivate() : operations(this) {}
+ QmlBehaviorPrivate() : animation(0) {}
+
QmlMetaProperty property;
QVariant currentValue;
-
- QVariant fromValue;
- QVariant toValue;
- class AnimationList : public QmlConcreteList<QmlAbstractAnimation *>
- {
- public:
- AnimationList(QmlBehaviorPrivate *parent) : _parent(parent) {}
- virtual void append(QmlAbstractAnimation *a)
- {
- QmlConcreteList<QmlAbstractAnimation *>::append(a);
- _parent->group->addAnimation(a->qtAnimation());
- if (_parent->property.isValid()) {
- a->setTarget(_parent->property);
- }
- }
- virtual void clear() { QmlConcreteList<QmlAbstractAnimation *>::clear(); } //###
- private:
- QmlBehaviorPrivate *_parent;
- };
- AnimationList operations;
- QParallelAnimationGroup *group;
+ QmlAbstractAnimation *animation;
};
-/*!
- \qmlclass Behavior QmlBehavior
- \brief The Behavior element allows you to specify a default animation for a property change.
-
- In example below, the rect will use a bounce easing curve over 200 millisecond for any changes to its y property:
- \code
- Rectangle {
- width: 20; height: 20
- color: "#00ff00"
- y: 200 //initial value
- y: Behavior {
- NumberAnimation {
- easing: "easeOutBounce(amplitude:100)"
- duration: 200
- }
- }
- }
- \endcode
-*/
-
QmlBehavior::QmlBehavior(QObject *parent)
-: QObject(*(new QmlBehaviorPrivate), parent)
-{
- Q_D(QmlBehavior);
- d->group = new QParallelAnimationGroup;
- QFx_setParent_noEvent(d->group, this);
-}
-
-/*!
- \qmlproperty QVariant Behavior::from
- This property holds a selector specifying a starting value for the behavior.
-
- If you only want the behavior to apply when the change starts at a
- specific value you can specify fromValue. This selector is used in conjunction
- with the to selector.
-*/
-
-QVariant QmlBehavior::fromValue() const
+ : QObject(*(new QmlBehaviorPrivate), parent)
{
- Q_D(const QmlBehavior);
- return d->fromValue;
}
-void QmlBehavior::setFromValue(const QVariant &v)
+QmlAbstractAnimation *QmlBehavior::animation()
{
Q_D(QmlBehavior);
- d->fromValue = v;
+ return d->animation;
}
-/*!
- \qmlproperty QVariant Behavior::to
- This property holds a selector specifying a ending value for the behavior.
-
- If you only want the behavior to apply when the change ends at a
- specific value you can specify toValue. This selector is used in conjunction
- with the from selector.
-*/
-
-QVariant QmlBehavior::toValue() const
-{
- Q_D(const QmlBehavior);
- return d->toValue;
-}
-
-void QmlBehavior::setToValue(const QVariant &v)
+void QmlBehavior::setAnimation(QmlAbstractAnimation *animation)
{
Q_D(QmlBehavior);
- d->toValue = v;
-}
+ if (d->animation) {
+ qmlInfo(this) << "Can't change the animation assigned to a Behavior.";
+ return;
+ }
-QmlList<QmlAbstractAnimation *>* QmlBehavior::operations()
-{
- Q_D(QmlBehavior);
- return &d->operations;
+ d->animation = animation;
+ if (d->animation)
+ d->animation->setTarget(d->property);
}
QmlBehavior::~QmlBehavior()
{
- //### do we need any other cleanup here?
}
-bool QmlBehavior::_ignore = false;
-void QmlBehavior::propertyValueChanged()
+void QmlBehavior::write(const QVariant &value)
{
Q_D(QmlBehavior);
- if (_ignore)
+ if (!d->animation) {
+ d->property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
return;
+ }
- QVariant newValue = d->property.read();
-
- if ((!fromValue().isValid() || fromValue() == d->currentValue) &&
- (!toValue().isValid() || toValue() == newValue)) {
-
- //### does this clean up everything needed?
- d->group->stop();
-
- QmlStateOperation::ActionList actions;
- Action action;
- action.property = d->property;
- action.fromValue = d->currentValue;
- action.toValue = newValue;
- actions << action;
+ d->currentValue = d->property.read();
- _ignore = true;
- d->property.write(d->currentValue);
+ d->animation->qtAnimation()->stop();
- QList<QmlMetaProperty> after;
- for (int ii = 0; ii < d->operations.count(); ++ii) {
- d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Forward);
- }
- d->group->start();
- if (!after.contains(d->property))
- d->property.write(newValue);
- _ignore = false;
- }
+ QmlStateOperation::ActionList actions;
+ Action action;
+ action.property = d->property;
+ action.fromValue = d->currentValue;
+ action.toValue = value;
+ actions << action;
- d->currentValue = newValue;
+ QList<QmlMetaProperty> after;
+ if (d->animation)
+ d->animation->transition(actions, after, QmlAbstractAnimation::Forward);
+ d->animation->qtAnimation()->start();
+ if (!after.contains(d->property))
+ d->property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
}
void QmlBehavior::setTarget(const QmlMetaProperty &property)
@@ -225,12 +122,8 @@ void QmlBehavior::setTarget(const QmlMetaProperty &property)
Q_D(QmlBehavior);
d->property = property;
d->currentValue = property.read();
- d->property.connectNotifier(this, SLOT(propertyValueChanged()));
- for (int ii = 0; ii < d->operations.count(); ++ii) {
- d->operations.at(ii)->setTarget(property);
- }
+ if (d->animation)
+ d->animation->setTarget(property);
}
QT_END_NAMESPACE
-
-#include "qmlbehavior.moc"
diff --git a/src/declarative/extra/qmlbehavior.h b/src/declarative/extra/qmlbehavior.h
index a4a0679..994d85c 100644
--- a/src/declarative/extra/qmlbehavior.h
+++ b/src/declarative/extra/qmlbehavior.h
@@ -43,6 +43,7 @@
#define QMLBEHAVIOR_H
#include <QtDeclarative/qmlpropertyvaluesource.h>
+#include <QtDeclarative/qmlpropertyvalueinterceptor.h>
#include <QtDeclarative/qml.h>
#include <QtDeclarative/qmlstate.h>
@@ -54,32 +55,23 @@ QT_MODULE(Declarative)
class QmlAbstractAnimation;
class QmlBehaviorPrivate;
-class Q_DECLARATIVE_EXPORT QmlBehavior : public QObject, public QmlPropertyValueSource
+class Q_DECLARATIVE_EXPORT QmlBehavior : public QObject, public QmlPropertyValueInterceptor
{
Q_OBJECT
Q_DECLARE_PRIVATE(QmlBehavior)
- Q_PROPERTY(QVariant from READ fromValue WRITE setFromValue)
- Q_PROPERTY(QVariant to READ toValue WRITE setToValue)
- Q_CLASSINFO("DefaultProperty", "operations")
- Q_PROPERTY(QmlList<QmlAbstractAnimation *>* operations READ operations)
+ Q_CLASSINFO("DefaultProperty", "animation")
+ Q_PROPERTY(QmlAbstractAnimation *animation READ animation WRITE setAnimation)
public:
QmlBehavior(QObject *parent=0);
~QmlBehavior();
- QVariant fromValue() const;
- void setFromValue(const QVariant &);
- QVariant toValue() const;
- void setToValue(const QVariant &);
virtual void setTarget(const QmlMetaProperty &);
+ virtual void write(const QVariant &value);
- QmlList<QmlAbstractAnimation *>* operations();
-
- static bool _ignore;
-
-private Q_SLOTS:
- void propertyValueChanged();
+ QmlAbstractAnimation *animation();
+ void setAnimation(QmlAbstractAnimation *);
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index a2e2050..2e62a3b 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -10,6 +10,7 @@ SOURCES += qml/qmlparser.cpp \
qml/qmlcontext.cpp \
qml/qmlcustomparser.cpp \
qml/qmlpropertyvaluesource.cpp \
+ qml/qmlpropertyvalueinterceptor.cpp \
qml/qmlproxymetaobject.cpp \
qml/qmlvme.cpp \
qml/qmlcompiler.cpp \
@@ -59,6 +60,7 @@ HEADERS += qml/qmlparser_p.h \
qml/qmlcustomparser_p.h \
qml/qmlcustomparser_p_p.h \
qml/qmlpropertyvaluesource.h \
+ qml/qmlpropertyvalueinterceptor.h \
qml/qmlboundsignal_p.h \
qml/qmlparserstatus.h \
qml/qmlproxymetaobject_p.h \
diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp
index 58ce02c..2435c40 100644
--- a/src/declarative/qml/qmlbinding.cpp
+++ b/src/declarative/qml/qmlbinding.cpp
@@ -97,7 +97,7 @@ QmlMetaProperty QmlBinding::property() const
return d->bindingData()->property;
}
-void QmlBinding::update()
+void QmlBinding::update(QmlMetaProperty::WriteFlags flags)
{
Q_D(QmlBinding);
@@ -119,17 +119,17 @@ void QmlBinding::update()
int idx = data->property.coreIndex();
Q_ASSERT(idx != -1);
- void *a[1];
+
QmlBinding *t = this;
- a[0] = (void *)&t;
- QMetaObject::metacall(data->property.object(),
+ int status = -1;
+ void *a[] = { &t, 0, &status, &flags };
+ QMetaObject::metacall(data->property.object(),
QMetaObject::WriteProperty,
idx, a);
} else {
-
QVariant value = this->value();
- data->property.write(value, QmlMetaProperty::Binding);
+ data->property.write(value, flags);
}
data->updating = false;
@@ -146,17 +146,17 @@ void QmlBinding::valueChanged()
update();
}
-void QmlBinding::setEnabled(bool e)
+void QmlBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
{
Q_D(QmlBinding);
d->bindingData()->enabled = e;
setTrackChange(e);
- QmlAbstractBinding::setEnabled(e);
+ QmlAbstractBinding::setEnabled(e, flags);
if (e) {
addToObject(d->bindingData()->property.object());
- update();
+ update(flags);
} else {
removeFromObject();
}
@@ -231,7 +231,7 @@ QString QmlAbstractBinding::expression() const
return QLatin1String("<Unknown>");
}
-void QmlAbstractBinding::setEnabled(bool e)
+void QmlAbstractBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags)
{
if (e) m_mePtr = 0;
}
diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h
index 1c0ccf1..6a3e92a 100644
--- a/src/declarative/qml/qmlbinding.h
+++ b/src/declarative/qml/qmlbinding.h
@@ -47,6 +47,7 @@
#include <QtDeclarative/qml.h>
#include <QtDeclarative/qmlpropertyvaluesource.h>
#include <QtDeclarative/qmlexpression.h>
+#include <QtCore/QMetaProperty>
QT_BEGIN_HEADER
@@ -62,10 +63,12 @@ public:
virtual QString expression() const;
- virtual void setEnabled(bool) = 0;
+ void setEnabled(bool e) { setEnabled(e, QmlMetaProperty::DontRemoveBinding); }
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags) = 0;
virtual int propertyIndex() = 0;
- virtual void update() = 0;
+ void update() { update(QmlMetaProperty::DontRemoveBinding); }
+ virtual void update(QmlMetaProperty::WriteFlags) = 0;
void addToObject(QObject *);
void removeFromObject();
@@ -100,12 +103,13 @@ public:
bool enabled() const;
// Inherited from QmlAbstractBinding
- virtual void setEnabled(bool);
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags);
virtual int propertyIndex();
+ virtual void update(QmlMetaProperty::WriteFlags flags);
virtual QString expression() const;
public Q_SLOTS:
- void update();
+ void update() { update(QmlMetaProperty::DontRemoveBinding); }
protected:
virtual void valueChanged();
diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp
index e4ca358..6dc221e 100644
--- a/src/declarative/qml/qmlbindingoptimizations.cpp
+++ b/src/declarative/qml/qmlbindingoptimizations.cpp
@@ -69,16 +69,16 @@ QmlBinding_Id::~QmlBinding_Id()
removeFromContext();
}
-void QmlBinding_Id::setEnabled(bool e)
+void QmlBinding_Id::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
{
if (e) {
addToObject(m_object);
- update();
+ update(flags);
} else {
removeFromObject();
}
- QmlAbstractBinding::setEnabled(e);
+ QmlAbstractBinding::setEnabled(e, flags);
}
int QmlBinding_Id::propertyIndex()
@@ -86,7 +86,7 @@ int QmlBinding_Id::propertyIndex()
return m_propertyIdx;
}
-void QmlBinding_Id::update()
+void QmlBinding_Id::update(QmlMetaProperty::WriteFlags flags)
{
QmlContextPrivate *ctxtPriv =
static_cast<QmlContextPrivate *>(QObjectPrivate::get(context()));
@@ -102,7 +102,8 @@ void QmlBinding_Id::update()
}
QObject *o = ctxtPriv->idValues[m_id].data();
- void *a[] = { &o, 0 };
+ int status = -1;
+ void *a[] = { &o, 0, &status, &flags };
QMetaObject::metacall(m_object, QMetaObject::WriteProperty,
m_propertyIdx, a);
}
@@ -123,7 +124,9 @@ void QmlBinding_Id::reset()
removeFromContext();
QObject *o = 0;
- void *a[] = { &o, 0 };
+ int status = -1;
+ QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding;
+ void *a[] = { &o, 0, &status, &flags };
QMetaObject::metacall(m_object, QMetaObject::WriteProperty,
m_propertyIdx, a);
}
@@ -150,17 +153,17 @@ QmlBinding_ObjProperty::QmlBinding_ObjProperty(QObject *object, int propertyIdx,
{
}
-void QmlBinding_ObjProperty::setEnabled(bool e)
+void QmlBinding_ObjProperty::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
{
m_enabled = e;
if (e) {
addToObject(m_object);
- update();
+ update(flags);
} else {
removeFromObject();
}
- QmlAbstractBinding::setEnabled(e);
+ QmlAbstractBinding::setEnabled(e, flags);
}
int QmlBinding_ObjProperty::propertyIndex()
@@ -168,21 +171,24 @@ int QmlBinding_ObjProperty::propertyIndex()
return m_propertyIdx;
}
-void QmlBinding_ObjProperty::update()
+void QmlBinding_ObjProperty::update(QmlMetaProperty::WriteFlags flags)
{
if (!m_enabled)
return;
QObject *value = 0;
- void *a[] = { &value, 0 };
+ int status = -1;
+ void *ra[] = { &value, 0, &status };
// Read
QMetaObject::metacall(m_context, QMetaObject::ReadProperty,
- m_contextIdx, a);
+ m_contextIdx, ra);
+
+ void *wa[] = { &value, 0, &status, &flags };
// Write
QMetaObject::metacall(m_object, QMetaObject::WriteProperty,
- m_propertyIdx, a);
+ m_propertyIdx, wa);
// Connect notify if needed. Only need to connect once, so we set
// m_notifyIdx back to -1 afterwards
diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h
index 4862007..d0a4df4 100644
--- a/src/declarative/qml/qmlbindingoptimizations_p.h
+++ b/src/declarative/qml/qmlbindingoptimizations_p.h
@@ -69,9 +69,9 @@ public:
virtual ~QmlBinding_Id();
// Inherited from QmlAbstractBinding
- virtual void setEnabled(bool);
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags);
virtual int propertyIndex();
- virtual void update();
+ virtual void update(QmlMetaProperty::WriteFlags flags);
void reset();
@@ -96,11 +96,12 @@ public:
QObject *context, int contextIdx, int notifyIdx);
// Inherited from QmlAbstractBinding
- virtual void setEnabled(bool);
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags);
virtual int propertyIndex();
+ virtual void update(QmlMetaProperty::WriteFlags flags);
private Q_SLOTS:
- virtual void update();
+ void update() { update(QmlMetaProperty::DontRemoveBinding); }
private:
bool m_enabled;
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 8856892..6fad513 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -1531,6 +1531,24 @@ void QmlCompiler::genPropertyAssignment(QmlParser::Property *prop,
store.assignValueSource.castValue = valueType->propertyValueSourceCast();
output->bytecode << store;
+ } else if (v->type == Value::ValueInterceptor) {
+ genObject(v->object);
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreValueInterceptor;
+ store.line = v->object->location.start.line;
+ if (valueTypeProperty) {
+ store.assignValueInterceptor.property = QmlMetaPropertyPrivate::saveValueType(valueTypeProperty->index, prop->index);
+ store.assignValueInterceptor.owner = 1;
+ } else {
+ store.assignValueInterceptor.property =
+ QmlMetaPropertyPrivate::saveProperty(prop->index);
+ store.assignValueInterceptor.owner = 0;
+ }
+ QmlType *valueType = QmlMetaType::qmlType(v->object->metatype);
+ store.assignValueInterceptor.castValue = valueType->propertyValueInterceptorCast();
+ output->bytecode << store;
+
} else if (v->type == Value::PropertyBinding) {
genBindingAssignment(v, prop, obj, valueTypeProperty);
@@ -1635,7 +1653,7 @@ bool QmlCompiler::buildAttachedProperty(QmlParser::Property *prop,
// font.pointSize: 12
// font.family: "Helvetica"
// }
-// font is a nested property. size and family are not.
+// font is a nested property. pointSize and family are not.
bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop,
QmlParser::Object *obj,
const BindingContext &ctxt)
@@ -1648,7 +1666,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop,
static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine));
if (ep->valueTypes[prop->type]) {
COMPILE_CHECK(buildValueTypeProperty(ep->valueTypes[prop->type],
- prop->value, ctxt.incr()));
+ prop->value, obj, ctxt.incr()));
obj->addValueTypeProperty(prop);
} else {
COMPILE_EXCEPTION(prop, "Invalid property access");
@@ -1672,6 +1690,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop,
bool QmlCompiler::buildValueTypeProperty(QObject *type,
QmlParser::Object *obj,
+ QmlParser::Object *baseObj,
const BindingContext &ctxt)
{
if (obj->defaultProperty)
@@ -1693,13 +1712,16 @@ bool QmlCompiler::buildValueTypeProperty(QObject *type,
if (value->object) {
bool isPropertyValue = output->types.at(value->object->type).type->propertyValueSourceCast() != -1;
- if (!isPropertyValue) {
+ bool isPropertyInterceptor = output->types.at(value->object->type).type->propertyValueInterceptorCast() != -1;
+ if (!isPropertyValue && !isPropertyInterceptor) {
COMPILE_EXCEPTION(prop, "Invalid property use");
} else {
COMPILE_CHECK(buildObject(value->object, ctxt));
- value->type = Value::ValueSource;
- }
+ if (isPropertyInterceptor && prop->parent->synthdata.isEmpty())
+ buildDynamicMeta(baseObj, ForceCreation);
+ value->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
+ }
} else if (value->value.isScript()) {
// ### Check for writability
BindingReference reference;
@@ -1864,8 +1886,12 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop,
// Will be true if the assigned type inherits QmlPropertyValueSource
bool isPropertyValue = false;
- if (QmlType *valueType = QmlMetaType::qmlType(v->object->metatype))
+ // Will be true if the assigned type inherits QmlPropertyValueInterceptor
+ bool isPropertyInterceptor = false;
+ if (QmlType *valueType = QmlMetaType::qmlType(v->object->metatype)) {
isPropertyValue = valueType->propertyValueSourceCast() != -1;
+ isPropertyInterceptor = valueType->propertyValueInterceptorCast() != -1;
+ }
// We want to raw metaObject here as the raw metaobject is the
// actual property type before we applied any extensions that might
@@ -1902,11 +1928,13 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop,
component->getDefaultProperty()->addValue(componentValue);
v->object = component;
COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
- } else if (isPropertyValue) {
+ } else if (isPropertyValue || isPropertyInterceptor) {
// Assign as a property value source
COMPILE_CHECK(buildObject(v->object, ctxt));
- v->type = Value::ValueSource;
+ if (isPropertyInterceptor && prop->parent->synthdata.isEmpty())
+ buildDynamicMeta(prop->parent, ForceCreation);
+ v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
} else {
COMPILE_EXCEPTION(v->object, "Cannot assign object to property");
}
@@ -2012,7 +2040,8 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode)
Q_ASSERT(obj);
Q_ASSERT(obj->metatype);
- if (obj->dynamicProperties.isEmpty() &&
+ if (mode != ForceCreation &&
+ obj->dynamicProperties.isEmpty() &&
obj->dynamicSignals.isEmpty() &&
obj->dynamicSlots.isEmpty())
return true;
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index 1d27342..3a35d58 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -191,6 +191,7 @@ private:
const BindingContext &ctxt);
bool buildValueTypeProperty(QObject *type,
QmlParser::Object *obj,
+ QmlParser::Object *baseObj,
const BindingContext &ctxt);
bool buildListProperty(QmlParser::Property *prop,
QmlParser::Object *obj,
@@ -209,7 +210,7 @@ private:
bool doesPropertyExist(QmlParser::Property *prop, QmlParser::Object *obj);
bool testLiteralAssignment(const QMetaProperty &prop,
QmlParser::Value *value);
- enum DynamicMetaMode { IgnoreAliases, ResolveAliases };
+ enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation };
bool mergeDynamicMetaProperties(QmlParser::Object *obj);
bool buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode);
bool checkDynamicMeta(QmlParser::Object *obj);
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
index 5b1cbeb..9a761b2 100644
--- a/src/declarative/qml/qmlcomponent.cpp
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -573,7 +573,7 @@ void QmlComponentPrivate::completeCreate()
bindValues.at(ii);
for (int jj = 0; jj < bv.count; ++jj) {
if(bv.at(jj))
- bv.at(jj)->setEnabled(true);
+ bv.at(jj)->setEnabled(true, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
}
QmlEnginePrivate::clear(bv);
}
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
index 18439f4..a465445 100644
--- a/src/declarative/qml/qmlinstruction.cpp
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -149,6 +149,9 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx)
case QmlInstruction::StoreValueSource:
qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t" << instr->assignValueSource.castValue;
break;
+ case QmlInstruction::StoreValueInterceptor:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_INTERCEPTOR\t" << instr->assignValueInterceptor.property << "\t" << instr->assignValueInterceptor.castValue;
+ break;
case QmlInstruction::BeginObject:
qWarning() << idx << "\t" << line << "\t" << "BEGIN\t\t\t" << instr->begin.castValue;
break;
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index 0da40c3..5265d42 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -130,6 +130,7 @@ public:
StoreIdOptBinding, /* assignIdOptBinding */
StoreObjPropBinding, /* assignObjPropBinding */
StoreValueSource, /* assignValueSource */
+ StoreValueInterceptor, /* assignValueInterceptor */
BeginObject, /* begin */
@@ -190,6 +191,11 @@ public:
} assignValueSource;
struct {
int property;
+ int owner;
+ int castValue;
+ } assignValueInterceptor; //### merge with above
+ struct {
+ int property;
int value;
short context;
short owner;
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index a43f6c3..8643301 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -559,17 +559,17 @@ QmlAbstractBinding *QmlMetaProperty::binding() const
is assumed by the caller.
*/
QmlAbstractBinding *
-QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const
+QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags) const
{
if (!isProperty() || (type() & Attached) || !d->object)
return 0;
- return d->setBinding(d->object, d->core, newBinding);
+ return d->setBinding(d->object, d->core, newBinding, flags);
}
QmlAbstractBinding *
QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data &core,
- QmlAbstractBinding *newBinding)
+ QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags)
{
QmlDeclarativeData *data = QmlDeclarativeData::get(object, 0 != newBinding);
@@ -581,7 +581,7 @@ QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data
binding->setEnabled(false);
if (newBinding)
- newBinding->setEnabled(true);
+ newBinding->setEnabled(true, flags);
return binding; // ### QmlAbstractBinding;
}
@@ -591,7 +591,7 @@ QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data
}
if (newBinding)
- newBinding->setEnabled(true);
+ newBinding->setEnabled(true, flags);
return 0;
}
@@ -728,11 +728,52 @@ QVariant QmlMetaPropertyPrivate::readValueProperty()
}
}
+//###
+//writeEnumProperty MIRRORS the relelvant bit of QMetaProperty::write AND MUST BE KEPT IN SYNC!
+//###
+bool QmlMetaPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags)
+{
+ if (!object || !prop.isWritable())
+ return false;
+
+ QVariant v = value;
+ uint t = QVariant::Invalid;
+ if (prop.isEnumType()) {
+ QMetaEnum menum = prop.enumerator();
+ if (v.type() == QVariant::String
+#ifdef QT3_SUPPORT
+ || v.type() == QVariant::CString
+#endif
+ ) {
+ if (prop.isFlagType())
+ v = QVariant(menum.keysToValue(value.toByteArray()));
+ else
+ v = QVariant(menum.keyToValue(value.toByteArray()));
+ } else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) {
+ int enumMetaTypeId = QMetaType::type(QByteArray(menum.scope()) + "::" + menum.name());
+ if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData())
+ return false;
+ v = QVariant(*reinterpret_cast<const int *>(v.constData()));
+ }
+ v.convert(QVariant::Int);
+ }
+
+ // the status variable is changed by qt_metacall to indicate what it did
+ // this feature is currently only used by QtDBus and should not be depended
+ // upon. Don't change it without looking into QDBusAbstractInterface first
+ // -1 (unchanged): normal qt_metacall, result stored in argv[0]
+ // changed: result stored directly in value, return the value of status
+ int status = -1;
+ void *argv[] = { v.data(), &v, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, idx, argv);
+ return status;
+}
+
void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
- QmlMetaProperty::WriteSource source)
+ QmlMetaProperty::WriteFlags flags)
{
// Remove any existing bindings on this property
- if (source != QmlMetaProperty::Binding)
+ if (!(flags & QmlMetaProperty::DontRemoveBinding))
delete q->setBinding(0);
uint type = q->type();
@@ -752,22 +793,23 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
QmlPropertyCache::Data data = core;
data.coreIndex = valueTypeCoreIdx;
data.propType = valueTypePropType;
- write(writeBack, data, value, context);
+ write(writeBack, data, value, context, flags);
- writeBack->write(object, core.coreIndex);
+ writeBack->write(object, core.coreIndex, flags);
if (!ep) delete writeBack;
} else {
- write(object, core, value, context);
+ write(object, core, value, context, flags);
}
}
void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data &property,
- const QVariant &value, QmlContext *context)
+ const QVariant &value, QmlContext *context, QmlMetaProperty::WriteFlags flags)
{
int coreIdx = property.coreIndex;
+ int status = -1; //for dbus
if (property.flags & QmlPropertyCache::Data::IsEnumType) {
QMetaProperty prop = object->metaObject()->property(property.coreIndex);
@@ -779,7 +821,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data
if (qFuzzyCompare(fractional, (double)0.0))
v.convert(QVariant::Int);
}
- prop.write(object, v);
+ writeEnumProperty(prop, coreIdx, object, v, flags);
return;
}
@@ -812,14 +854,12 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data
} else if (vt == t) {
- void *a[1];
- a[0] = (void *)value.constData();
+ void *a[] = { (void *)value.constData(), 0, &status, &flags };
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
} else if (qMetaTypeId<QVariant>() == t) {
- void *a[1];
- a[0] = (void *)&value;
+ void *a[] = { (void *)&value, 0, &status, &flags };
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
} else if (property.flags & QmlPropertyCache::Data::IsQObjectDerived) {
@@ -843,7 +883,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data
if (valMo || !o) {
- void *args[] = { &o, 0 };
+ void *args[] = { &o, 0, &status, &flags };
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx,
args);
@@ -909,16 +949,14 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data
QVariant v = value;
if (v.convert((QVariant::Type)t)) {
- void *a[1];
- a[0] = (void *)v.constData();
+ void *a[] = { (void *)v.constData(), 0, &status, &flags};
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
} else if ((uint)t >= QVariant::UserType && vt == QVariant::String) {
QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t);
if (con) {
QVariant v = con(value.toString());
if (v.userType() == t) {
- void *a[1];
- a[0] = (void *)v.constData();
+ void *a[] = { (void *)v.constData(), 0, &status, &flags};
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
}
}
@@ -931,17 +969,17 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data
*/
void QmlMetaProperty::write(const QVariant &value) const
{
- write(value, Other);
+ write(value, 0);
}
-void QmlMetaProperty::write(const QVariant &value, WriteSource source) const
+void QmlMetaProperty::write(const QVariant &value, QmlMetaProperty::WriteFlags flags) const
{
if (!d->object)
return;
if (type() & Property && d->core.isValid()) {
- d->writeValueProperty(value, source);
+ d->writeValueProperty(value, flags);
}
}
diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h
index 8c34ece..b0ae28c 100644
--- a/src/declarative/qml/qmlmetaproperty.h
+++ b/src/declarative/qml/qmlmetaproperty.h
@@ -88,8 +88,9 @@ public:
QVariant read() const;
void write(const QVariant &) const;
- enum WriteSource { Animation, Binding, Other };
- void write(const QVariant &, WriteSource) const;
+ enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02 };
+ Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
+ void write(const QVariant &, QmlMetaProperty::WriteFlags) const;
bool hasChangedNotifier() const;
bool needsChangedNotifier() const;
@@ -126,7 +127,8 @@ public:
QMetaProperty property() const;
QmlAbstractBinding *binding() const;
- QmlAbstractBinding *setBinding(QmlAbstractBinding *) const;
+ QmlAbstractBinding *setBinding(QmlAbstractBinding *,
+ QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding) const;
QmlExpression *signalExpression() const;
QmlExpression *setSignalExpression(QmlExpression *) const;
@@ -139,6 +141,7 @@ private:
QmlMetaPropertyPrivate *d;
};
typedef QList<QmlMetaProperty> QmlMetaProperties;
+ Q_DECLARE_OPERATORS_FOR_FLAGS(QmlMetaProperty::WriteFlags)
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h
index 4576b71..b74aa2d 100644
--- a/src/declarative/qml/qmlmetaproperty_p.h
+++ b/src/declarative/qml/qmlmetaproperty_p.h
@@ -97,9 +97,12 @@ public:
QmlMetaProperty::PropertyCategory propertyCategory() const;
QVariant readValueProperty();
- void writeValueProperty(const QVariant &, QmlMetaProperty::WriteSource);
- static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *);
- static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *);
+ void writeValueProperty(const QVariant &, QmlMetaProperty::WriteFlags);
+ static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags);
+ static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *,
+ QmlMetaProperty::WriteFlags flags = 0);
+ static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *,
+ QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding);
static quint32 saveValueType(int, int);
static quint32 saveProperty(int);
diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp
index c40232f..5198f9f 100644
--- a/src/declarative/qml/qmlmetatype.cpp
+++ b/src/declarative/qml/qmlmetatype.cpp
@@ -128,6 +128,7 @@ public:
const QMetaObject *m_attachedPropertiesType;
int m_parserStatusCast;
int m_propertyValueSourceCast;
+ int m_propertyValueInterceptorCast;
QmlPrivate::CreateFunc m_extFunc;
const QMetaObject *m_extMetaObject;
int m_index;
@@ -140,8 +141,8 @@ public:
QmlTypePrivate::QmlTypePrivate()
: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_qmlListId(0),
m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0),
- m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_extFunc(0), m_extMetaObject(0),
- m_index(-1), m_customParser(0), m_isSetup(false)
+ m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1),
+ m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false)
{
}
@@ -169,7 +170,8 @@ QmlType::QmlType(int type, int listType, int qmlListType,
const QMetaObject *metaObject,
QmlAttachedPropertiesFunc attachedPropertiesFunc,
const QMetaObject *attachedType,
- int parserStatusCast, int propertyValueSourceCast, QmlPrivate::CreateFunc extFunc,
+ int parserStatusCast, int propertyValueSourceCast, int propertyValueInterceptorCast,
+ QmlPrivate::CreateFunc extFunc,
const QMetaObject *extMetaObject, int index,
QmlCustomParser *customParser)
: d(new QmlTypePrivate)
@@ -187,6 +189,7 @@ QmlType::QmlType(int type, int listType, int qmlListType,
d->m_attachedPropertiesType = attachedType;
d->m_parserStatusCast = parserStatusCast;
d->m_propertyValueSourceCast = propertyValueSourceCast;
+ d->m_propertyValueInterceptorCast = propertyValueInterceptorCast;
d->m_extFunc = extFunc;
d->m_index = index;
d->m_customParser = customParser;
@@ -412,6 +415,11 @@ int QmlType::propertyValueSourceCast() const
return d->m_propertyValueSourceCast;
}
+int QmlType::propertyValueInterceptorCast() const
+{
+ return d->m_propertyValueInterceptorCast;
+}
+
QVariant QmlType::fromObject(QObject *obj) const
{
QVariant rv;
@@ -467,7 +475,7 @@ int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id,
int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func,
const char *uri, int version_maj, int version_min_from, int version_min_to, const char *cname,
const QMetaObject *mo, QmlAttachedPropertiesFunc attach, const QMetaObject *attachMo,
- int pStatus, int object, int valueSource, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser)
+ int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser)
{
Q_UNUSED(object);
@@ -492,7 +500,7 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun
QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId,
func, name, version_maj, version_min_from, version_min_to, mo, attach, attachMo, pStatus,
- valueSource, extFunc, extmo, index, parser);
+ valueSource, valueInterceptor, extFunc, extmo, index, parser);
data->types.append(type);
data->idToType.insert(type->typeId(), type);
@@ -539,6 +547,17 @@ int QmlMetaType::qmlPropertyValueSourceCast(int userType)
return -1;
}
+int QmlMetaType::qmlPropertyValueInterceptorCast(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ if (type && type->typeId() == userType)
+ return type->propertyValueInterceptorCast();
+ else
+ return -1;
+}
+
QObject *QmlMetaType::toQObject(const QVariant &v)
{
if (!isObject(v.userType()))
diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h
index 02c817d..42c278c 100644
--- a/src/declarative/qml/qmlmetatype.h
+++ b/src/declarative/qml/qmlmetatype.h
@@ -48,6 +48,7 @@
#include <QtDeclarative/qmlprivate.h>
#include <QtDeclarative/qmlparserstatus.h>
#include <QtDeclarative/qmlpropertyvaluesource.h>
+#include <QtDeclarative/qmlpropertyvalueinterceptor.h>
QT_BEGIN_HEADER
@@ -60,7 +61,7 @@ class QmlCustomParser;
class Q_DECLARATIVE_EXPORT QmlMetaType
{
public:
- static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin_from, int vmin_to, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *);
+ static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin_from, int vmin_to, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *);
static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *);
static bool copy(int type, void *data, const void *copy = 0);
@@ -80,6 +81,7 @@ public:
static QObject *toQObject(const QVariant &);
static int qmlParserStatusCast(int);
static int qmlPropertyValueSourceCast(int);
+ static int qmlPropertyValueInterceptorCast(int);
static int listType(int);
static bool clear(const QVariant &);
static bool append(const QVariant &, const QVariant &);
@@ -146,6 +148,7 @@ public:
QVariant fromObject(QObject *) const;
const char *interfaceIId() const;
int propertyValueSourceCast() const;
+ int propertyValueInterceptorCast() const;
int index() const;
private:
@@ -153,7 +156,7 @@ private:
friend class QmlTypePrivate;
friend class QmlMetaTypeData;
QmlType(int, int, int, QmlPrivate::Func, const char *, int);
- QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *);
+ QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *);
~QmlType();
QmlTypePrivate *d;
@@ -176,6 +179,7 @@ int qmlRegisterType(const char *typeName)
QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
QmlPrivate::StaticCastSelector<T,QObject>::cast(),
QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
0, 0, 0);
}
@@ -196,7 +200,8 @@ int qmlRegisterType(const char *uri, int version_maj, int version_min_from, int
QmlPrivate::attachedPropertiesMetaObject<T>(),
QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
QmlPrivate::StaticCastSelector<T,QObject>::cast(),
- QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
0, 0, 0);
}
@@ -224,6 +229,7 @@ int qmlRegisterExtendedType(const char *typeName)
QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
QmlPrivate::StaticCastSelector<T,QObject>::cast(),
QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
&QmlPrivate::CreateParent<E>::create, &E::staticMetaObject, 0);
}
@@ -253,6 +259,7 @@ int qmlRegisterExtendedType(const char *uri, int version_maj, int version_min_fr
QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
QmlPrivate::StaticCastSelector<T,QObject>::cast(),
QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
&QmlPrivate::CreateParent<E>::create,
&E::staticMetaObject, 0);
}
@@ -290,6 +297,7 @@ int qmlRegisterCustomType(const char *uri, int version_maj, int version_min_from
QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
QmlPrivate::StaticCastSelector<T,QObject>::cast(),
QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
0, 0, parser);
}
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
index 8c46939..bae263a 100644
--- a/src/declarative/qml/qmlparser.cpp
+++ b/src/declarative/qml/qmlparser.cpp
@@ -282,6 +282,9 @@ void QmlParser::Value::dump(int indent) const
case Value::ValueSource:
type = "ValueSource";
break;
+ case Value::ValueInterceptor:
+ type = "ValueInterceptor";
+ break;
case Value::CreatedObject:
type = "CreatedObject";
break;
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
index d05cc73..88d7d77 100644
--- a/src/declarative/qml/qmlparser_p.h
+++ b/src/declarative/qml/qmlparser_p.h
@@ -275,6 +275,8 @@ namespace QmlParser
PropertyBinding,
// This is used as a QmlPropertyValueSource assignment
ValueSource,
+ // This is used as a QmlPropertyValueInterceptor assignment
+ ValueInterceptor,
// This is used as a property QObject assignment
CreatedObject,
// This is used as a signal object assignment
diff --git a/src/declarative/qml/qmlpropertyvalueinterceptor.cpp b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp
new file mode 100644
index 0000000..86905e6
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpropertyvalueinterceptor.h"
+#include "qml.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlPropertyValueInterceptor
+ \brief The QmlPropertyValueInterceptor class is inherited by property interceptors such as Behavior.
+
+ This class intercepts property writes, allowing for custom handling. For example, Behavior uses this
+ interception to provide a default animation for all changes to a property's value.
+ */
+
+/*!
+ Constructs a QmlPropertyValueInterceptor.
+*/
+QmlPropertyValueInterceptor::QmlPropertyValueInterceptor()
+{
+}
+
+QmlPropertyValueInterceptor::~QmlPropertyValueInterceptor()
+{
+}
+
+/*!
+ \fn void QmlPropertyValueInterceptor::setTarget(const QmlMetaProperty &property)
+ Set the target \a property for the value interceptor. This method will
+ be called by the QML engine when assigning a value interceptor.
+*/
+
+/*!
+ \fn void QmlPropertyValueInterceptor::write(const QVariant &value)
+ This method will be called when a new \a value is assigned to the property being intercepted.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertyvalueinterceptor.h b/src/declarative/qml/qmlpropertyvalueinterceptor.h
new file mode 100644
index 0000000..678c12c
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvalueinterceptor.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYVALUEINTERCEPTOR_H
+#define QMLPROPERTYVALUEINTERCEPTOR_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlMetaProperty;
+class Q_DECLARATIVE_EXPORT QmlPropertyValueInterceptor
+{
+public:
+ QmlPropertyValueInterceptor();
+ virtual ~QmlPropertyValueInterceptor();
+ virtual void setTarget(const QmlMetaProperty &property) = 0;
+ virtual void write(const QVariant &value) = 0;
+};
+Q_DECLARE_INTERFACE(QmlPropertyValueInterceptor, "com.trolltech.qml.QmlPropertyValueInterceptor")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPROPERTYVALUEINTERCEPTOR_H
diff --git a/src/declarative/qml/qmlvaluetype.cpp b/src/declarative/qml/qmlvaluetype.cpp
index 4ae2070..84c9ecb 100644
--- a/src/declarative/qml/qmlvaluetype.cpp
+++ b/src/declarative/qml/qmlvaluetype.cpp
@@ -97,9 +97,10 @@ void QmlPointFValueType::read(QObject *obj, int idx)
QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
-void QmlPointFValueType::write(QObject *obj, int idx)
+void QmlPointFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
{
- void *a[] = { &point, 0 };
+ int status = -1;
+ void *a[] = { &point, 0, &status, &flags };
QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
@@ -144,9 +145,10 @@ void QmlPointValueType::read(QObject *obj, int idx)
QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
-void QmlPointValueType::write(QObject *obj, int idx)
+void QmlPointValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
{
- void *a[] = { &point, 0 };
+ int status = -1;
+ void *a[] = { &point, 0, &status, &flags };
QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
@@ -191,9 +193,10 @@ void QmlSizeFValueType::read(QObject *obj, int idx)
QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
-void QmlSizeFValueType::write(QObject *obj, int idx)
+void QmlSizeFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
{
- void *a[] = { &size, 0 };
+ int status = -1;
+ void *a[] = { &size, 0, &status, &flags };
QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
@@ -238,9 +241,10 @@ void QmlSizeValueType::read(QObject *obj, int idx)
QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
-void QmlSizeValueType::write(QObject *obj, int idx)
+void QmlSizeValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
{
- void *a[] = { &size, 0 };
+ int status = -1;
+ void *a[] = { &size, 0, &status, &flags };
QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
@@ -285,9 +289,10 @@ void QmlRectFValueType::read(QObject *obj, int idx)
QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
-void QmlRectFValueType::write(QObject *obj, int idx)
+void QmlRectFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
{
- void *a[] = { &rect, 0 };
+ int status = -1;
+ void *a[] = { &rect, 0, &status, &flags };
QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
@@ -352,9 +357,10 @@ void QmlRectValueType::read(QObject *obj, int idx)
QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
-void QmlRectValueType::write(QObject *obj, int idx)
+void QmlRectValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
{
- void *a[] = { &rect, 0 };
+ int status = -1;
+ void *a[] = { &rect, 0, &status, &flags };
QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
@@ -419,9 +425,10 @@ void QmlVector3DValueType::read(QObject *obj, int idx)
QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
-void QmlVector3DValueType::write(QObject *obj, int idx)
+void QmlVector3DValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
{
- void *a[] = { &vector, 0 };
+ int status = -1;
+ void *a[] = { &vector, 0, &status, &flags };
QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
@@ -476,9 +483,10 @@ void QmlFontValueType::read(QObject *obj, int idx)
QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
-void QmlFontValueType::write(QObject *obj, int idx)
+void QmlFontValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
{
- void *a[] = { &font, 0 };
+ int status = -1;
+ void *a[] = { &font, 0, &status, &flags };
QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
diff --git a/src/declarative/qml/qmlvaluetype_p.h b/src/declarative/qml/qmlvaluetype_p.h
index da5e972..d3adf1e 100644
--- a/src/declarative/qml/qmlvaluetype_p.h
+++ b/src/declarative/qml/qmlvaluetype_p.h
@@ -58,6 +58,7 @@
#include <QtCore/qvariant.h>
#include <QtGui/qvector3d.h>
#include <QtGui/qfont.h>
+#include <QmlMetaProperty>
QT_BEGIN_NAMESPACE
@@ -67,7 +68,7 @@ class QmlValueType : public QObject
public:
QmlValueType(QObject *parent = 0);
virtual void read(QObject *, int) = 0;
- virtual void write(QObject *, int) = 0;
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags flags) = 0;
virtual QVariant value() = 0;
virtual void setValue(QVariant) = 0;
};
@@ -92,7 +93,7 @@ public:
QmlPointFValueType(QObject *parent = 0);
virtual void read(QObject *, int);
- virtual void write(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
@@ -114,7 +115,7 @@ public:
QmlPointValueType(QObject *parent = 0);
virtual void read(QObject *, int);
- virtual void write(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
@@ -136,7 +137,7 @@ public:
QmlSizeFValueType(QObject *parent = 0);
virtual void read(QObject *, int);
- virtual void write(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
@@ -158,7 +159,7 @@ public:
QmlSizeValueType(QObject *parent = 0);
virtual void read(QObject *, int);
- virtual void write(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
@@ -182,7 +183,7 @@ public:
QmlRectFValueType(QObject *parent = 0);
virtual void read(QObject *, int);
- virtual void write(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
@@ -211,7 +212,7 @@ public:
QmlRectValueType(QObject *parent = 0);
virtual void read(QObject *, int);
- virtual void write(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
@@ -239,7 +240,7 @@ public:
QmlVector3DValueType(QObject *parent = 0);
virtual void read(QObject *, int);
- virtual void write(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
@@ -267,7 +268,7 @@ public:
QmlFontValueType(QObject *parent = 0);
virtual void read(QObject *, int);
- virtual void write(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
virtual QVariant value();
virtual void setValue(QVariant value);
diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp
index 6fd674a..6a7bdeb 100644
--- a/src/declarative/qml/qmlvaluetypescriptclass.cpp
+++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp
@@ -132,7 +132,7 @@ void QmlValueTypeScriptClass::setProperty(QScriptValue &object,
ref.type->read(ref.object, ref.property);
QMetaProperty p = ref.type->metaObject()->property(id);
p.write(ref.type, v);
- ref.type->write(ref.object, ref.property);
+ ref.type->write(ref.object, ref.property, 0);
}
QVariant QmlValueTypeScriptClass::toVariant(const QScriptValue &val)
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index a057f11..d4921b6 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -155,6 +155,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
QmlEnginePrivate *ep = QmlEnginePrivate::get(ctxt->engine());
QmlContextPrivate *cp = (QmlContextPrivate *)QObjectPrivate::get(ctxt);
+ int status = -1; //for dbus
+ QmlMetaProperty::WriteFlags flags = QmlMetaProperty::BypassInterceptor;
+
for (int ii = start; !isError() && ii < (start + count); ++ii) {
QmlInstruction &instr = comp->bytecode[ii];
@@ -275,10 +278,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreVariant:
{
QObject *target = stack.top();
- void *a[1];
// XXX - can be more efficient
QVariant v = QmlStringConverters::variantFromString(primitives.at(instr.storeString.value));
- a[0] = (void *)&v;
+ void *a[] = { &v, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeString.propertyIndex, a);
}
@@ -287,8 +289,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreString:
{
QObject *target = stack.top();
- void *a[1];
- a[0] = (void *)&primitives.at(instr.storeString.value);
+ void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeString.propertyIndex, a);
}
@@ -297,9 +298,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreUrl:
{
QObject *target = stack.top();
- void *a[1];
QUrl u(primitives.at(instr.storeUrl.value));
- a[0] = (void *)&u;
+ void *a[] = { &u, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeUrl.propertyIndex, a);
}
@@ -309,8 +309,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
{
QObject *target = stack.top();
float f = instr.storeFloat.value;
- void *a[1];
- a[0] = &f;
+ void *a[] = { &f, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeFloat.propertyIndex, a);
}
@@ -320,8 +319,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
{
QObject *target = stack.top();
double d = instr.storeDouble.value;
- void *a[1];
- a[0] = &d;
+ void *a[] = { &d, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeDouble.propertyIndex, a);
}
@@ -330,8 +328,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreBool:
{
QObject *target = stack.top();
- void *a[1];
- a[0] = (void *)&instr.storeBool.value;
+ void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeBool.propertyIndex, a);
}
@@ -340,8 +337,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreInteger:
{
QObject *target = stack.top();
- void *a[1];
- a[0] = (void *)&instr.storeInteger.value;
+ void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeInteger.propertyIndex, a);
}
@@ -350,9 +346,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreColor:
{
QObject *target = stack.top();
- void *a[1];
QColor c = QColor::fromRgba(instr.storeColor.value);
- a[0] = (void *)&c;
+ void *a[] = { &c, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeColor.propertyIndex, a);
}
@@ -361,9 +356,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreDate:
{
QObject *target = stack.top();
- void *a[1];
QDate d = QDate::fromJulianDay(instr.storeDate.value);
- a[0] = (void *)&d;
+ void *a[] = { &d, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeDate.propertyIndex, a);
}
@@ -372,13 +366,12 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreTime:
{
QObject *target = stack.top();
- void *a[1];
QTime t;
t.setHMS(intData.at(instr.storeTime.valueIndex),
intData.at(instr.storeTime.valueIndex+1),
intData.at(instr.storeTime.valueIndex+2),
intData.at(instr.storeTime.valueIndex+3));
- a[0] = (void *)&t;
+ void *a[] = { &t, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeTime.propertyIndex, a);
}
@@ -387,14 +380,13 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreDateTime:
{
QObject *target = stack.top();
- void *a[1];
QTime t;
t.setHMS(intData.at(instr.storeDateTime.valueIndex+1),
intData.at(instr.storeDateTime.valueIndex+2),
intData.at(instr.storeDateTime.valueIndex+3),
intData.at(instr.storeDateTime.valueIndex+4));
QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t);
- a[0] = (void *)&dt;
+ void *a[] = { &dt, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeDateTime.propertyIndex, a);
}
@@ -403,10 +395,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StorePoint:
{
QObject *target = stack.top();
- void *a[1];
QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex),
floatData.at(instr.storeRealPair.valueIndex+1)).toPoint();
- a[0] = (void *)&p;
+ void *a[] = { &p, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeRealPair.propertyIndex, a);
}
@@ -415,10 +406,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StorePointF:
{
QObject *target = stack.top();
- void *a[1];
QPointF p(floatData.at(instr.storeRealPair.valueIndex),
floatData.at(instr.storeRealPair.valueIndex+1));
- a[0] = (void *)&p;
+ void *a[] = { &p, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeRealPair.propertyIndex, a);
}
@@ -427,10 +417,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreSize:
{
QObject *target = stack.top();
- void *a[1];
QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex),
floatData.at(instr.storeRealPair.valueIndex+1)).toSize();
- a[0] = (void *)&p;
+ void *a[] = { &p, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeRealPair.propertyIndex, a);
}
@@ -439,10 +428,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreSizeF:
{
QObject *target = stack.top();
- void *a[1];
QSizeF s(floatData.at(instr.storeRealPair.valueIndex),
floatData.at(instr.storeRealPair.valueIndex+1));
- a[0] = (void *)&s;
+ void *a[] = { &s, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeRealPair.propertyIndex, a);
}
@@ -451,12 +439,11 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreRect:
{
QObject *target = stack.top();
- void *a[1];
QRect r = QRectF(floatData.at(instr.storeRect.valueIndex),
floatData.at(instr.storeRect.valueIndex+1),
floatData.at(instr.storeRect.valueIndex+2),
floatData.at(instr.storeRect.valueIndex+3)).toRect();
- a[0] = (void *)&r;
+ void *a[] = { &r, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeRect.propertyIndex, a);
}
@@ -465,12 +452,11 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreRectF:
{
QObject *target = stack.top();
- void *a[1];
QRectF r(floatData.at(instr.storeRect.valueIndex),
floatData.at(instr.storeRect.valueIndex+1),
floatData.at(instr.storeRect.valueIndex+2),
floatData.at(instr.storeRect.valueIndex+3));
- a[0] = (void *)&r;
+ void *a[] = { &r, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeRect.propertyIndex, a);
}
@@ -479,11 +465,10 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::StoreVector3D:
{
QObject *target = stack.top();
- void *a[1];
QVector3D p(floatData.at(instr.storeVector3D.valueIndex),
floatData.at(instr.storeVector3D.valueIndex+1),
floatData.at(instr.storeVector3D.valueIndex+2));
- a[0] = (void *)&p;
+ void *a[] = { &p, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeVector3D.propertyIndex, a);
}
@@ -494,9 +479,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
QObject *assignObj = stack.pop();
QObject *target = stack.top();
- void *a[1];
- a[0] = (void *)&assignObj;
-
+ void *a[] = { (void *)&assignObj, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeObject.propertyIndex, a);
}
@@ -506,7 +489,6 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
case QmlInstruction::AssignCustomType:
{
QObject *target = stack.top();
- void *a[1];
QmlCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex);
const QString &primitive = primitives.at(data.index);
QmlMetaType::StringConverter converter =
@@ -518,7 +500,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type))
VME_EXCEPTION("Cannot assign value" << primitive << "to property" << prop.name());
- a[0] = (void *)v.data();
+ void *a[] = { (void *)v.data(), 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.assignCustomType.propertyIndex, a);
}
@@ -655,6 +637,20 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
}
break;
+ case QmlInstruction::StoreValueInterceptor:
+ {
+ QObject *obj = stack.pop();
+ QmlPropertyValueInterceptor *vi = reinterpret_cast<QmlPropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.assignValueInterceptor.castValue);
+ QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner);
+ QmlMetaProperty prop;
+ prop.restore(instr.assignValueInterceptor.property, target, ctxt);
+ obj->setParent(target);
+ vi->setTarget(prop);
+ QmlVMEMetaObject *mo = static_cast<QmlVMEMetaObject *>((QMetaObject*)target->metaObject());
+ mo->registerInterceptor(prop.coreIndex(), vi);
+ }
+ break;
+
case QmlInstruction::StoreObjectQmlList:
{
QObject *assign = stack.pop();
@@ -706,8 +702,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
QObject *target = stack.top();
QVariant v = QVariant::fromValue(assign);
- void *a[1];
- a[0] = (void *)&v;
+ void *a[] = { &v, 0, &status, &flags };
QMetaObject::metacall(target, QMetaObject::WriteProperty,
instr.storeObject.propertyIndex, a);
}
@@ -726,8 +721,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
if (iid) {
void *ptr = assign->qt_metacast(iid);
if (ptr) {
- void *a[1];
- a[0] = &ptr;
+ void *a[] = { &ptr, 0, &status, &flags };
QMetaObject::metacall(target,
QMetaObject::WriteProperty,
coreIdx, a);
@@ -849,7 +843,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
QmlValueType *valueHandler =
static_cast<QmlValueType *>(stack.pop());
QObject *target = stack.top();
- valueHandler->write(target, instr.fetchValue.property);
+ valueHandler->write(target, instr.fetchValue.property, QmlMetaProperty::BypassInterceptor);
}
break;
diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp
index f473743..5ef1158 100644
--- a/src/declarative/qml/qmlvmemetaobject.cpp
+++ b/src/declarative/qml/qmlvmemetaobject.cpp
@@ -100,6 +100,24 @@ QmlVMEMetaObject::~QmlVMEMetaObject()
int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
{
int id = _id;
+ if(c == QMetaObject::WriteProperty) {
+ int flags = *reinterpret_cast<int*>(a[3]);
+ if (!(flags & QmlMetaProperty::BypassInterceptor)
+ && !aInterceptors.isEmpty()
+ && aInterceptors.testBit(id)) {
+ QmlPropertyValueInterceptor *vi = interceptors.value(id);
+ if (id >= propOffset) {
+ id -= propOffset;
+ if (id < metaData->propertyCount) {
+ vi->write(QVariant(data[id].type(), a[0]));
+ return -1;
+ }
+ } else {
+ vi->write(QVariant(property(id).type(), a[0]));
+ return -1;
+ }
+ }
+ }
if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) {
if (id >= propOffset) {
id -= propOffset;
@@ -253,4 +271,13 @@ void QmlVMEMetaObject::listChanged(int id)
activate(object, methodOffset + id, 0);
}
+void QmlVMEMetaObject::registerInterceptor(int index, QmlPropertyValueInterceptor *interceptor)
+{
+ if (aInterceptors.isEmpty())
+ aInterceptors.resize(propertyCount() + metaData->propertyCount);
+ aInterceptors.setBit(index);
+ interceptors.insert(index, interceptor);
+}
+
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h
index 1c26241..d376f4c 100644
--- a/src/declarative/qml/qmlvmemetaobject_p.h
+++ b/src/declarative/qml/qmlvmemetaobject_p.h
@@ -104,6 +104,8 @@ public:
QmlRefCount * = 0);
~QmlVMEMetaObject();
+ void registerInterceptor(int index, QmlPropertyValueInterceptor *interceptor);
+
protected:
virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
@@ -117,6 +119,8 @@ private:
QVariant *data;
QBitArray aConnected;
+ QBitArray aInterceptors;
+ QHash<int, QmlPropertyValueInterceptor*> interceptors;
QAbstractDynamicMetaObject *parent;
diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp
index 3edbc5f..247e64c 100644
--- a/src/declarative/util/qmlanimation.cpp
+++ b/src/declarative/util/qmlanimation.cpp
@@ -972,7 +972,7 @@ void QmlPropertyAction::setValue(const QVariant &v)
void QmlPropertyActionPrivate::doAction()
{
- property.write(value);
+ property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
}
QAbstractAnimation *QmlPropertyAction::qtAnimation()
@@ -1007,9 +1007,7 @@ void QmlPropertyAction::transition(QmlStateActions &actions,
{
for (int ii = 0; ii < actions.count(); ++ii) {
const Action &action = actions.at(ii);
- QmlBehavior::_ignore = true;
- action.property.write(action.toValue);
- QmlBehavior::_ignore = false;
+ action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
}
}
};
@@ -1020,9 +1018,11 @@ void QmlPropertyAction::transition(QmlStateActions &actions,
if (!d->propertyName.isEmpty() && !props.contains(d->propertyName))
props.append(d->propertyName);
+ bool targetNeedsReset = false;
if (d->userProperty.isValid() && props.isEmpty() && !target()) {
props.append(d->userProperty.value.name());
d->target = d->userProperty.value.object();
+ targetNeedsReset = true;
}
QmlSetPropertyAnimationAction *data = new QmlSetPropertyAnimationAction;
@@ -1070,6 +1070,8 @@ void QmlPropertyAction::transition(QmlStateActions &actions,
} else {
delete data;
}
+ if (targetNeedsReset)
+ d->target = 0;
}
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,PropertyAction,QmlPropertyAction)
@@ -1714,10 +1716,10 @@ void QmlPropertyAnimationPrivate::valueChanged(qreal r)
}
if (r == 1.) {
- property.write(to);
+ property.write(to, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
} else {
if (interpolator)
- property.write(interpolator(from.constData(), to.constData(), r));
+ property.write(interpolator(from.constData(), to.constData(), r), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
}
}
@@ -1773,9 +1775,8 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions,
for (int ii = 0; ii < actions.count(); ++ii) {
Action &action = actions[ii];
- QmlBehavior::_ignore = true;
if (v == 1.)
- action.property.write(action.toValue);
+ action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
else {
if (action.fromValue.isNull()) {
action.fromValue = action.property.read();
@@ -1790,9 +1791,8 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions,
}
}
if (interpolator)
- action.property.write(interpolator(action.fromValue.constData(), action.toValue.constData(), v));
+ action.property.write(interpolator(action.fromValue.constData(), action.toValue.constData(), v), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
}
- QmlBehavior::_ignore = false;
}
}
};
@@ -1805,9 +1805,11 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions,
bool useType = (props.isEmpty() && d->defaultToInterpolatorType) ? true : false;
+ bool targetNeedsReset = false;
if (d->userProperty.isValid() && props.isEmpty() && !target()) {
props.append(d->userProperty.value.name());
d->target = d->userProperty.value.object();
+ targetNeedsReset = true;
}
PropertyUpdater *data = new PropertyUpdater;
@@ -1874,6 +1876,8 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions,
} else {
delete data;
}
+ if (targetNeedsReset)
+ d->target = 0;
}
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,PropertyAnimation,QmlPropertyAnimation)
diff --git a/src/declarative/util/qmlpropertychanges.cpp b/src/declarative/util/qmlpropertychanges.cpp
index a5a08bc..b07a79f 100644
--- a/src/declarative/util/qmlpropertychanges.cpp
+++ b/src/declarative/util/qmlpropertychanges.cpp
@@ -230,17 +230,18 @@ void QmlPropertyChangesPrivate::decode()
ds >> isScript;
ds >> data;
- if (isScript) {
- QmlMetaProperty prop = property(name); //### can we avoid or reuse?
+ QmlMetaProperty prop = property(name); //### better way to check for signal property?
+ if (prop.type() == QmlMetaProperty::SignalProperty) {
QmlExpression *expression = new QmlExpression(qmlContext(q), data.toString(), object);
expression->setTrackChange(false);
- if (prop.type() == QmlMetaProperty::SignalProperty) {
- QmlReplaceSignalHandler *handler = new QmlReplaceSignalHandler;
- handler->property = prop;
- handler->expression = expression;
- signalReplacements << handler;
- } else
- expressions << qMakePair(name, expression);
+ QmlReplaceSignalHandler *handler = new QmlReplaceSignalHandler;
+ handler->property = prop;
+ handler->expression = expression;
+ signalReplacements << handler;
+ } else if (isScript) {
+ QmlExpression *expression = new QmlExpression(qmlContext(q), data.toString(), object);
+ expression->setTrackChange(false);
+ expressions << qMakePair(name, expression);
} else {
properties << qMakePair(name, data);
}
diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp
index 3c85db7..98facd9 100644
--- a/src/declarative/util/qmlstate.cpp
+++ b/src/declarative/util/qmlstate.cpp
@@ -350,6 +350,7 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever
if (action.event) {
if (!action.event->isReversable())
continue;
+ action.event->saveOriginals();
for (jj = 0; jj < d->revertList.count(); ++jj) {
ActionEvent *event = d->revertList.at(jj).event;
if (event && event->typeName() == action.event->typeName()) {
@@ -359,9 +360,6 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever
}
}
}
- if (!found)
- action.event->saveOriginals();
- //### do we ever need to do saveOriginals when found == true?
} else {
action.fromBinding = action.property.binding();
diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp
index 3e2e05f..7eaccac 100644
--- a/src/declarative/util/qmltransitionmanager.cpp
+++ b/src/declarative/util/qmltransitionmanager.cpp
@@ -144,9 +144,9 @@ void QmlTransitionManager::transition(const QList<Action> &list,
for (int ii = 0; ii < applyList.size(); ++ii) {
const Action &action = applyList.at(ii);
if (action.toBinding) {
- action.property.setBinding(action.toBinding);
+ action.property.setBinding(action.toBinding, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
} else if (!action.event) {
- action.property.write(action.toValue);
+ action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
} else if (action.event->isReversable()) {
if (action.reverseEvent)
action.event->reverse();
@@ -187,7 +187,7 @@ void QmlTransitionManager::transition(const QList<Action> &list,
if (action.toBinding)
action.property.setBinding(0); // Make sure this is disabled during the transition
- action.property.write(action.fromValue);
+ action.property.write(action.fromValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
}
}
@@ -223,7 +223,7 @@ void QmlTransitionManager::transition(const QList<Action> &list,
}
// Any actions remaining have not been handled by the transition and should
- // be applied immediately. We skip applying transitions, as they are all
+ // be applied immediately. We skip applying bindings, as they are all
// applied at the end in applyBindings() to avoid any nastiness mid
// transition
foreach(const Action &action, applyList) {
@@ -232,13 +232,12 @@ void QmlTransitionManager::transition(const QList<Action> &list,
action.event->reverse();
else
action.event->execute();
- } else if (!action.event) {
+ } else if (!action.event && !action.toBinding) {
action.property.write(action.toValue);
}
}
if (!transition)
d->applyBindings();
-
}
void QmlTransitionManager::cancel()