diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-09-23 11:26:16 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-25 13:13:30 +0200 |
commit | 443f99eafb2337f23272f02b1e4c28d9e8310c67 (patch) | |
tree | ea9943d1195f4377e4584b699ae8bc03ae60b64a /src | |
parent | f1901b9289d10eb4696336c969ae49512b9930b3 (diff) |
Fix bindings on properties in grouped value type properties
... such as
point.x: { someExpression }
This requires special handling to install the QQmlBinding not on the
value type itself (not possible) but on the point property itself.
Fixes tst_qqmllanguage::valueTypes
Change-Id: I8f95379e1872dff7cdcc0480c229a5e68f3cf575
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 43 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 5 |
2 files changed, 36 insertions, 12 deletions
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 292df56f24..b137d31dbb 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -480,6 +480,8 @@ QmlObjectCreator::QmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledD , vmeMetaObjectData(compiledData->datas) , compiledData(compiledData) , _qobject(0) + , _qobjectForBindings(0) + , _valueTypeProperty(0) , _compiledObject(0) , _ddata(0) , _propertyCache(0) @@ -1001,7 +1003,7 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI const int id = attachedType->attachedPropertiesId(); QObject *qmlObject = qmlAttachedPropertiesObjectById(id, _qobject); QQmlRefPointer<QQmlPropertyCache> cache = QQmlEnginePrivate::get(engine)->cache(qmlObject); - if (!populateInstance(binding->value.objectIndex, qmlObject, cache, _qobject)) + if (!populateInstance(binding->value.objectIndex, qmlObject, cache, _qobject, /*value type property*/0)) return false; return true; } @@ -1028,7 +1030,9 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine); QQmlRefPointer<QQmlPropertyCache> groupedObjCache; QObject *groupedObjInstance = 0; + QObject *objForBindings = _qobjectForBindings; QQmlValueType *valueType = 0; + QQmlPropertyData *valueTypeProperty = 0; if (QQmlValueTypeFactory::isValueType(property->propType)) { valueType = QQmlValueTypeFactory::valueType(property->propType); @@ -1041,13 +1045,13 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI groupedObjCache = enginePrivate->cache(valueType); groupedObjInstance = valueType; + valueTypeProperty = property; } else { groupedObjCache = enginePrivate->propertyCacheForType(property->propType); if (!groupedObjCache) { recordError(binding->location, tr("Invalid grouped property access")); return false; } - groupedObjInstance = valueType; void *argv[1] = { &groupedObjInstance }; QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv); @@ -1055,9 +1059,11 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI recordError(binding->location, tr("Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex))); return false; } + + objForBindings = groupedObjInstance; } - if (!populateInstance(binding->value.objectIndex, groupedObjInstance, groupedObjCache, _qobject)) + if (!populateInstance(binding->value.objectIndex, groupedObjInstance, groupedObjCache, objForBindings, valueTypeProperty)) return false; if (valueType) @@ -1084,7 +1090,17 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI } else { QQmlBinding *qmlBinding = new QQmlBinding(function, _qobject, context, QString(), 0, 0); // ### - qmlBinding->setTarget(_qobject, *property, context); + + // When writing bindings to grouped properties implemented as value types, + // such as point.x: { someExpression; }, then the binding is installed on + // the point property (_qobjectForBindings) and after evaluating the expression, + // the result is written to a value type virtual property, that contains the sub-index + // of the "x" property. + QQmlPropertyData targetCorePropertyData = *property; + if (_valueTypeProperty) + targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine); + + qmlBinding->setTarget(_qobjectForBindings, targetCorePropertyData, context); qmlBinding->addToObject(); _createdBindings[bindingIndex] = qmlBinding; @@ -1252,7 +1268,7 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent) QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.value(index); Q_ASSERT(!cache.isNull()); - if (!populateInstance(index, instance, cache, _qobject)) + if (!populateInstance(index, instance, cache, _qobject, /*value type property*/0)) return 0; } @@ -1304,17 +1320,20 @@ void QmlObjectCreator::finalize() } } -bool QmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache, QObject *scopeObjectForJavaScript) +bool QmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache, + QObject *scopeObjectForBindings, QQmlPropertyData *valueTypeProperty) { const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index); - if (!scopeObjectForJavaScript) - scopeObjectForJavaScript = instance; + if (!scopeObjectForBindings) + scopeObjectForBindings = instance; QQmlData *declarativeData = QQmlData::get(instance, /*create*/true); qSwap(_propertyCache, cache); qSwap(_qobject, instance); + qSwap(_qobjectForBindings, scopeObjectForBindings); + qSwap(_valueTypeProperty, valueTypeProperty); qSwap(_compiledObject, obj); qSwap(_ddata, declarativeData); @@ -1322,13 +1341,13 @@ bool QmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPoi const QByteArray data = vmeMetaObjectData.value(index); if (!data.isEmpty()) { // install on _object - vmeMetaObject = new QQmlVMEMetaObject(_qobject, _propertyCache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData())); + vmeMetaObject = new QQmlVMEMetaObject(_qobjectForBindings, _propertyCache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData())); if (_ddata->propertyCache) _ddata->propertyCache->release(); _ddata->propertyCache = _propertyCache; _ddata->propertyCache->addref(); } else { - vmeMetaObject = QQmlVMEMetaObject::get(_qobject); + vmeMetaObject = QQmlVMEMetaObject::get(_qobjectForBindings); } _ddata->lineNumber = _compiledObject->location.line; @@ -1341,7 +1360,7 @@ bool QmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPoi QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); QV4::Scope valueScope(v4); - QV4::ScopedValue scopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, scopeObjectForJavaScript)); + QV4::ScopedValue scopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _qobjectForBindings)); QV4::QmlBindingWrapper *qmlBindingWrapper = new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, scopeObject->asObject()); QV4::ScopedValue qmlScopeFunction(valueScope, QV4::Value::fromObject(qmlBindingWrapper)); QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context(); @@ -1360,6 +1379,8 @@ bool QmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPoi qSwap(_propertyCache, cache); qSwap(_ddata, declarativeData); qSwap(_compiledObject, obj); + qSwap(_valueTypeProperty, valueTypeProperty); + qSwap(_qobjectForBindings, scopeObjectForBindings); qSwap(_qobject, instance); return errors.isEmpty(); diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index fe3a4bb00a..131271c5c6 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -127,7 +127,8 @@ public: private: QObject *createInstance(int index, QObject *parent = 0); - bool populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache, QObject *scopeObjectForJavaScript); + bool populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache, + QObject *scopeObjectForJavaScript, QQmlPropertyData *valueTypeProperty); void setupBindings(); bool setPropertyValue(QQmlPropertyData *property, int index, const QV4::CompiledData::Binding *binding); @@ -146,6 +147,8 @@ private: QQmlCompiledData *compiledData; QObject *_qobject; + QObject *_qobjectForBindings; + QQmlPropertyData *_valueTypeProperty; // belongs to _qobjectForBindings's property cache const QV4::CompiledData::Object *_compiledObject; QQmlData *_ddata; QQmlRefPointer<QQmlPropertyCache> _propertyCache; |