diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-09-30 17:39:49 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-01-17 08:10:07 +0100 |
commit | bf13e5045739f9766ed3c8ac1be1c672ce655dae (patch) | |
tree | 4506cbca3961567207f57c8eac92fdf705cfd29d /src/qml/qml/qqmlobjectcreator.cpp | |
parent | 2b00cb4fc62f64b75c906a9f65cfc2b60ecfcb43 (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/qqmlobjectcreator.cpp')
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 60 |
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; |