aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-09-16 17:25:53 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-20 14:26:43 +0200
commitf7cd6238ada2745eea13ceff168e7d65b7263866 (patch)
tree5c91c251eb3c2ddf1d56dae4ede28af3539b2345 /src/qml/qml
parent2b832d20185aff91dfa0515cc3f9268240c917a7 (diff)
[new compiler] Finish support for initializing list properties
Setting a value on a list property is always just appending to the list instead of replacing it. Based on that, initializing list properties with multiple items is done with one binding per item to the same list property. So myList: [ Item{}, Item{} ] is mapped to myList: Item {} myList: Item {} Change-Id: Iadc048ab3a8d73ac824aa6b2ae5dec33731fa362 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp279
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h2
2 files changed, 152 insertions, 129 deletions
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 9aaf3e4b6c..9260c1609e 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -881,164 +881,185 @@ void QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::C
void QmlObjectCreator::setupBindings(QV4::ExecutionContext *qmlContext)
{
+ QQmlListProperty<void> savedList;
+ qSwap(_currentList, savedList);
+
+ QQmlPropertyData *property = 0;
+
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
- if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
- const QV4::CompiledData::Object *obj = unit->objectAt(binding->value.objectIndex);
- Q_ASSERT(stringAt(obj->inheritedTypeNameIndex).isEmpty());
- QQmlType *attachedType = resolvedTypes.value(binding->propertyNameIndex).type;
- 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))
- break;
- continue;
- }
- QString name = stringAt(binding->propertyNameIndex);
+ if (!property || (i > 0 && (binding - 1)->propertyNameIndex != binding->propertyNameIndex)) {
+ QString name = stringAt(binding->propertyNameIndex);
+ if (!name.isEmpty())
+ property = _propertyCache->property(name, _qobject, context);
+ else
+ property = 0;
- QObject *createdSubObject = 0;
- if (binding->type == QV4::CompiledData::Binding::Type_Object) {
- createdSubObject = create(binding->value.objectIndex, _qobject);
- if (!createdSubObject)
- return;
- }
+ if (property && property->isQList()) {
+ void *argv[1] = { (void*)&_currentList };
+ QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
+ } else if (_currentList.object)
+ _currentList = QQmlListProperty<void>();
- // Child item:
- // ...
- // Item {
- // ...
- // }
- if (name.isEmpty())
- continue;
+ }
- QQmlPropertyData *property = _propertyCache->property(name, _qobject, context);
+ if (!setPropertyValue(qmlContext, property, i, binding))
+ return;
+ }
- if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty) {
- const QV4::CompiledData::Object *obj = unit->objectAt(binding->value.objectIndex);
- if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) {
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(property->propType);
+ qSwap(_currentList, savedList);
+}
- valueType->read(_qobject, property->coreIndex);
+bool QmlObjectCreator::setPropertyValue(QV4::ExecutionContext *qmlContext, QQmlPropertyData *property,
+ int bindingIndex, const QV4::CompiledData::Binding *binding)
+{
+ if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
+ const QV4::CompiledData::Object *obj = unit->objectAt(binding->value.objectIndex);
+ Q_ASSERT(stringAt(obj->inheritedTypeNameIndex).isEmpty());
+ QQmlType *attachedType = resolvedTypes.value(binding->propertyNameIndex).type;
+ 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))
+ return false;
+ return true;
+ }
- QQmlRefPointer<QQmlPropertyCache> cache = QQmlEnginePrivate::get(engine)->cache(valueType);
- if (!populateInstance(binding->value.objectIndex, valueType, cache))
- break;
+ QObject *createdSubObject = 0;
+ if (binding->type == QV4::CompiledData::Binding::Type_Object) {
+ createdSubObject = create(binding->value.objectIndex, _qobject);
+ if (!createdSubObject)
+ return false;
+ }
- valueType->write(_qobject, property->coreIndex, QQmlPropertyPrivate::BypassInterceptor);
- continue;
- }
- }
+ // Child item:
+ // ...
+ // Item {
+ // ...
+ // }
+ if (!property)
+ return true;
- if (_ddata->hasBindingBit(property->coreIndex))
- removeBindingOnProperty(_qobject, property->coreIndex);
+ if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty) {
+ const QV4::CompiledData::Object *obj = unit->objectAt(binding->value.objectIndex);
+ if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) {
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(property->propType);
- if (binding->type == QV4::CompiledData::Binding::Type_Script) {
- QV4::Function *runtimeFunction = jsUnit->runtimeFunctions[binding->value.compiledScriptIndex];
- QV4::Value function = QV4::Value::fromObject(QV4::FunctionObject::creatScriptFunction(qmlContext, runtimeFunction));
+ valueType->read(_qobject, property->coreIndex);
- if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
- int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex);
- QQmlBoundSignal *bs = new QQmlBoundSignal(_qobject, signalIndex, _qobject, engine);
- QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_qobject, signalIndex,
- context, _qobject, function);
+ QQmlRefPointer<QQmlPropertyCache> cache = QQmlEnginePrivate::get(engine)->cache(valueType);
+ if (!populateInstance(binding->value.objectIndex, valueType, cache))
+ return false;
- bs->takeExpression(expr);
- } else {
- QQmlBinding *qmlBinding = new QQmlBinding(function, _qobject, context,
- QString(), 0, 0); // ###
+ valueType->write(_qobject, property->coreIndex, QQmlPropertyPrivate::BypassInterceptor);
+ return true;
+ }
+ }
- qmlBinding->setTarget(_qobject, *property, context);
- qmlBinding->addToObject();
+ if (_ddata->hasBindingBit(property->coreIndex))
+ removeBindingOnProperty(_qobject, property->coreIndex);
- _createdBindings[i] = qmlBinding;
- qmlBinding->m_mePtr = &_createdBindings[i];
- }
- continue;
- }
+ if (binding->type == QV4::CompiledData::Binding::Type_Script) {
+ QV4::Function *runtimeFunction = jsUnit->runtimeFunctions[binding->value.compiledScriptIndex];
+ QV4::Value function = QV4::Value::fromObject(QV4::FunctionObject::creatScriptFunction(qmlContext, runtimeFunction));
- if (binding->type == QV4::CompiledData::Binding::Type_Object) {
- QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
- QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
- int propertyWriteStatus = -1;
- void *argv[] = { 0, 0, &propertyWriteStatus, &propertyWriteFlags };
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
+ int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex);
+ QQmlBoundSignal *bs = new QQmlBoundSignal(_qobject, signalIndex, _qobject, engine);
+ QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_qobject, signalIndex,
+ context, _qobject, function);
- if (const char *iid = QQmlMetaType::interfaceIId(property->propType)) {
- void *ptr = createdSubObject->qt_metacast(iid);
- if (ptr) {
- argv[0] = &ptr;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Cannot assign object to interface property"));
- break;
- }
- } else if (property->propType == QMetaType::QVariant) {
- if (property->isVarProperty()) {
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- QV4::Scope scope(v4);
- QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(QV8Engine::getV4(engine), createdSubObject));
- _vmeMetaObject->setVMEProperty(property->coreIndex, wrappedObject);
- } else {
- QVariant value = QVariant::fromValue(createdSubObject);
- argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- }
- } else if (property->isQList()) {
- QQmlListProperty<void> list;
- argv[0] = (void*)&list;
- QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
+ bs->takeExpression(expr);
+ } else {
+ QQmlBinding *qmlBinding = new QQmlBinding(function, _qobject, context,
+ QString(), 0, 0); // ###
+ qmlBinding->setTarget(_qobject, *property, context);
+ qmlBinding->addToObject();
- void *itemToAdd = createdSubObject;
+ _createdBindings[bindingIndex] = qmlBinding;
+ qmlBinding->m_mePtr = &_createdBindings[bindingIndex];
+ }
+ return true;
+ }
- const char *iid = 0;
- int listItemType = QQmlEnginePrivate::get(engine)->listType(property->propType);
- if (listItemType != -1)
- iid = QQmlMetaType::interfaceIId(listItemType);
- if (iid)
- itemToAdd = createdSubObject->qt_metacast(iid);
+ if (binding->type == QV4::CompiledData::Binding::Type_Object) {
+ QQmlPropertyPrivate::WriteFlags propertyWriteFlags = QQmlPropertyPrivate::BypassInterceptor |
+ QQmlPropertyPrivate::RemoveBindingOnAliasWrite;
+ int propertyWriteStatus = -1;
+ void *argv[] = { 0, 0, &propertyWriteStatus, &propertyWriteFlags };
- if (list.append)
- list.append(&list, itemToAdd);
+ if (const char *iid = QQmlMetaType::interfaceIId(property->propType)) {
+ void *ptr = createdSubObject->qt_metacast(iid);
+ if (ptr) {
+ argv[0] = &ptr;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
} else {
- QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
-
- // We want to raw metaObject here as the raw metaobject is the
- // actual property type before we applied any extensions that might
- // effect the properties on the type, but don't effect assignability
- QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType);
-
- // Will be true if the assgned type inherits propertyMetaObject
- bool isAssignable = false;
- // Determine isAssignable value
- if (propertyMetaObject) {
- QQmlPropertyCache *c = enginePrivate->cache(createdSubObject);
- while (c && !isAssignable) {
- isAssignable |= c == propertyMetaObject;
- c = c->parent();
- }
- }
+ recordError(binding->location, tr("Cannot assign object to interface property"));
+ return false;
+ }
+ } else if (property->propType == QMetaType::QVariant) {
+ if (property->isVarProperty()) {
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QV4::Scope scope(v4);
+ QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(QV8Engine::getV4(engine), createdSubObject));
+ _vmeMetaObject->setVMEProperty(property->coreIndex, wrappedObject);
+ } else {
+ QVariant value = QVariant::fromValue(createdSubObject);
+ argv[0] = &value;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ }
+ } else if (property->isQList()) {
+ Q_ASSERT(_currentList.object);
- if (isAssignable) {
- argv[0] = &createdSubObject;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
- } else {
- recordError(binding->location, tr("Cannot assign object to property"));
- break;
+ void *itemToAdd = createdSubObject;
+
+ const char *iid = 0;
+ int listItemType = QQmlEnginePrivate::get(engine)->listType(property->propType);
+ if (listItemType != -1)
+ iid = QQmlMetaType::interfaceIId(listItemType);
+ if (iid)
+ itemToAdd = createdSubObject->qt_metacast(iid);
+
+ if (_currentList.append)
+ _currentList.append(&_currentList, itemToAdd);
+ } else {
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
+
+ // We want to raw metaObject here as the raw metaobject is the
+ // actual property type before we applied any extensions that might
+ // effect the properties on the type, but don't effect assignability
+ QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType);
+
+ // Will be true if the assgned type inherits propertyMetaObject
+ bool isAssignable = false;
+ // Determine isAssignable value
+ if (propertyMetaObject) {
+ QQmlPropertyCache *c = enginePrivate->cache(createdSubObject);
+ while (c && !isAssignable) {
+ isAssignable |= c == propertyMetaObject;
+ c = c->parent();
}
}
- continue;
- }
- if (property->isQList()) {
- recordError(binding->location, tr("Cannot assign primitives to lists"));
- break;
+ if (isAssignable) {
+ argv[0] = &createdSubObject;
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ } else {
+ recordError(binding->location, tr("Cannot assign object to property"));
+ return false;
+ }
}
+ return true;
+ }
- setPropertyValue(property, binding);
-
- if (!errors.isEmpty())
- break;
+ if (property->isQList()) {
+ recordError(binding->location, tr("Cannot assign primitives to lists"));
+ return false;
}
+
+ setPropertyValue(property, binding);
+ return true;
}
void QmlObjectCreator::setupFunctions(QV4::ExecutionContext *qmlContext)
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index f3ff6f6e08..62c344194e 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -97,6 +97,7 @@ private:
bool populateInstance(int index, QObject *instance, QQmlRefPointer<QQmlPropertyCache> cache);
void setupBindings(QV4::ExecutionContext *qmlContext);
+ bool setPropertyValue(QV4::ExecutionContext *qmlContext, QQmlPropertyData *property, int index, const QV4::CompiledData::Binding *binding);
void setPropertyValue(QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
void setupFunctions(QV4::ExecutionContext *qmlContext);
@@ -120,6 +121,7 @@ private:
QQmlRefPointer<QQmlPropertyCache> _propertyCache;
QQmlVMEMetaObject *_vmeMetaObject;
QVector<QQmlAbstractBinding*> _createdBindings;
+ QQmlListProperty<void> _currentList;
};
QT_END_NAMESPACE