aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-09-23 11:26:16 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-25 13:13:30 +0200
commit443f99eafb2337f23272f02b1e4c28d9e8310c67 (patch)
treeea9943d1195f4377e4584b699ae8bc03ae60b64a /src
parentf1901b9289d10eb4696336c969ae49512b9930b3 (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.cpp43
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h5
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;