[new compiler] Fix partial bindings on value types
authorSimon Hausmann <simon.hausmann@digia.com>
Tue, 4 Feb 2014 13:02:51 +0000 (14:02 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 4 Feb 2014 17:29:12 +0000 (18:29 +0100)
You can have a binding like this:

    property point blah: Qt.point(someX, someY);

and later you can have bindings on

    blah.x: { someExpression }

In that case we need to clear the binding on blah.

Change-Id: I27bfa6ab0f104bf989803c5910e6094767429c03
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/qml/qqmlobjectcreator.cpp

index e63d6a9f21374b4774b6ae9b3b32676c6b496e01..e2f1212e84abe8add76af8c73e6d89c4ca7d4342 100644 (file)
@@ -55,6 +55,7 @@
 #include <private/qqmlcustomparser_p.h>
 #include <private/qqmlscriptstring_p.h>
 #include <private/qqmlpropertyvalueinterceptor_p.h>
+#include <private/qqmlvaluetypeproxybinding_p.h>
 
 QT_USE_NAMESPACE
 
@@ -509,6 +510,17 @@ void QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::C
     }
 }
 
+static QQmlType *qmlTypeForObject(QObject *object)
+{
+    QQmlType *type = 0;
+    const QMetaObject *mo = object->metaObject();
+    while (mo && !type) {
+        type = QQmlMetaType::qmlType(mo);
+        mo = mo->superClass();
+    }
+    return type;
+}
+
 void QmlObjectCreator::setupBindings()
 {
     QQmlListProperty<void> savedList;
@@ -531,6 +543,36 @@ void QmlObjectCreator::setupBindings()
         }
     }
 
+    // ### this is best done through type-compile-time binding skip lists.
+    if (_valueTypeProperty) {
+        QQmlAbstractBinding *binding =
+            QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex, -1);
+
+        if (binding && binding->bindingType() != QQmlAbstractBinding::ValueTypeProxy) {
+            QQmlPropertyPrivate::setBinding(_bindingTarget, _valueTypeProperty->coreIndex, -1, 0);
+            binding->destroy();
+        } else if (binding) {
+            QQmlValueTypeProxyBinding *proxy =
+                static_cast<QQmlValueTypeProxyBinding *>(binding);
+
+            if (qmlTypeForObject(_bindingTarget)) {
+                quint32 bindingSkipList = 0;
+
+                const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
+                for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
+                    if (binding->type != QV4::CompiledData::Binding::Type_Script)
+                        continue;
+                    property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty;
+                    if (property)
+                        bindingSkipList |= (1 << property->coreIndex);
+                }
+                property = 0;
+
+                proxy->removeBindings(bindingSkipList);
+            }
+        }
+    }
+
     const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
     for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
 
@@ -661,7 +703,8 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI
     }
 
     if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
-        && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment))
+        && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
+        && !_valueTypeProperty)
         removeBindingOnProperty(_bindingTarget, property->coreIndex);
 
     if (binding->type == QV4::CompiledData::Binding::Type_Script) {
@@ -712,12 +755,7 @@ 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();
-            }
+            QQmlType *type = qmlTypeForObject(createdSubObject);
             Q_ASSERT(type);
 
             QQmlPropertyData targetCorePropertyData = *property;