aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-09-30 17:39:49 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-17 08:10:07 +0100
commitbf13e5045739f9766ed3c8ac1be1c672ce655dae (patch)
tree4506cbca3961567207f57c8eac92fdf705cfd29d /src/qml/qml
parent2b00cb4fc62f64b75c906a9f65cfc2b60ecfcb43 (diff)
[new compiler] Add support for value interceptors / on-assignments
Behavior on x { NumberAnimation { ... } } is implemented by assigning a value interceptor (Behavior is a sub-class of that) to the x property in a special way. That requires various things: * A VME meta-object must be created and installed on the surrounding object, in order for the interceptors to work * On assignments need to be excluded from duplicate property assignment checks * Behaviours require also finalization callbacks on component creation Change-Id: I40250b71081a2e315cda3bdb6677fa4b227fa443 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp60
1 files changed, 58 insertions, 2 deletions
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 15f57f0761..963b8272f4 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -54,6 +54,7 @@
#include <private/qqmlcomponent_p.h>
#include <private/qqmlcustomparser_p.h>
#include <private/qqmlscriptstring_p.h>
+#include <private/qqmlpropertyvalueinterceptor_p.h>
QT_USE_NAMESPACE
@@ -670,7 +671,7 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI
QObject *createdSubObject = 0;
if (binding->type == QV4::CompiledData::Binding::Type_Object) {
- createdSubObject = createInstance(binding->value.objectIndex, _qobject);
+ createdSubObject = createInstance(binding->value.objectIndex, _bindingTarget);
if (!createdSubObject)
return false;
}
@@ -728,7 +729,8 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI
}
}
- if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression))
+ if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
+ && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment))
removeBindingOnProperty(_bindingTarget, property->coreIndex);
if (binding->type == QV4::CompiledData::Binding::Type_Script) {
@@ -767,6 +769,43 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI
}
if (binding->type == QV4::CompiledData::Binding::Type_Object) {
+ if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) {
+ // ### determine value source and interceptor casts ahead of time.
+ QQmlType *type = 0;
+ const QMetaObject *mo = createdSubObject->metaObject();
+ while (mo && !type) {
+ type = QQmlMetaType::qmlType(mo);
+ mo = mo->superClass();
+ }
+ Q_ASSERT(type);
+
+ QQmlPropertyData targetCorePropertyData = *property;
+ if (_valueTypeProperty)
+ targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
+
+ int valueSourceCast = type->propertyValueSourceCast();
+ if (valueSourceCast != -1) {
+ QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast);
+ QObject *target = createdSubObject->parent();
+ vs->setTarget(QQmlPropertyPrivate::restore(target, targetCorePropertyData, context));
+ return true;
+ }
+ int valueInterceptorCast = type->propertyValueInterceptorCast();
+ if (valueInterceptorCast != -1) {
+ QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(createdSubObject) + valueInterceptorCast);
+ QObject *target = createdSubObject->parent();
+
+ QQmlProperty prop =
+ QQmlPropertyPrivate::restore(target, targetCorePropertyData, context);
+ vi->setTarget(prop);
+ QQmlVMEMetaObject *mo = QQmlVMEMetaObject::get(target);
+ Q_ASSERT(mo);
+ mo->registerInterceptor(prop.index(), QQmlPropertyPrivate::valueTypeCoreIndex(prop), vi);
+ return true;
+ }
+ return false;
+ }
+
QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
int propertyWriteStatus = -1;
@@ -1032,6 +1071,23 @@ QQmlContextData *QmlObjectCreator::finalize()
}
{
+ QQmlTrace trace("VME Finalize Callbacks");
+ for (int ii = 0; ii < finalizeCallbacks.count(); ++ii) {
+ QQmlEnginePrivate::FinalizeCallback callback = finalizeCallbacks.at(ii);
+ QObject *obj = callback.first;
+ if (obj) {
+ void *args[] = { 0 };
+ QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args);
+ }
+#if 0 // ###
+ if (watcher.hasRecursed())
+ return 0;
+#endif
+ }
+ finalizeCallbacks.clear();
+ }
+
+ {
QQmlTrace trace("VME Component.onCompleted Callbacks");
while (componentAttached) {
QQmlComponentAttached *a = componentAttached;