Update multiple value type properties despite interceptor
authorMatthew Vogt <matthew.vogt@nokia.com>
Fri, 13 Jul 2012 00:44:39 +0000 (10:44 +1000)
committerQt by Nokia <qt-info@nokia.com>
Fri, 13 Jul 2012 06:06:06 +0000 (08:06 +0200)
When an interceptor is present on a value type, ensure that multiple
properties of that value can be updated simultaneously.

Task-number: QTBUG-25139
Change-Id: I3042b9883d404aed4b6507e6d2f38a76caee1196
Reviewed-by: Glenn Watson <glenn.watson@nokia.com>
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
src/qml/qml/qqmlvmemetaobject.cpp
tests/auto/quick/qquickbehaviors/data/multipleChangesToValueType.qml [new file with mode: 0644]
tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp

index c982856..5dcff3e 100644 (file)
@@ -665,13 +665,21 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
                     valueType->setValue(newValue);
                     QVariant newComponentValue = valueProp.read(valueType);
 
-                    valueProp.write(valueType, prevComponentValue);
-                    valueType->write(object, id, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+                    // Don't apply the interceptor if the intercepted value has not changed
+                    bool updated = false;
+                    if (newComponentValue != prevComponentValue) {
+                        valueProp.write(valueType, prevComponentValue);
+                        valueType->write(object, id, QQmlPropertyPrivate::DontRemoveBinding | QQmlPropertyPrivate::BypassInterceptor);
+
+                        vi->write(newComponentValue);
+                        updated = true;
+                    }
 
-                    vi->write(newComponentValue);
+                    if (!ep)
+                        delete valueType;
 
-                    if (!ep) delete valueType;
-                    return -1;
+                    if (updated)
+                        return -1;
                 } else {
                     vi->write(QVariant(type, a[0]));
                     return -1;
diff --git a/tests/auto/quick/qquickbehaviors/data/multipleChangesToValueType.qml b/tests/auto/quick/qquickbehaviors/data/multipleChangesToValueType.qml
new file mode 100644 (file)
index 0000000..029a439
--- /dev/null
@@ -0,0 +1,19 @@
+import QtQuick 2.0
+
+Rectangle {
+    width: 400
+    height: 400
+
+    Text {
+        id: text
+        anchors.centerIn: parent
+        font.pointSize: 24
+        Behavior on font.pointSize { NumberAnimation {} }
+    }
+
+    function updateFontProperties() {
+        text.font.italic = true
+        text.font.pointSize = 48
+        text.font.weight = Font.Bold
+    }
+}
index bd17bf4..be7ad30 100644 (file)
@@ -80,6 +80,7 @@ private slots:
     void sameValue();
     void delayedRegistration();
     void startOnCompleted();
+    void multipleChangesToValueType();
 };
 
 void tst_qquickbehaviors::simpleBehavior()
@@ -468,6 +469,32 @@ void tst_qquickbehaviors::startOnCompleted()
     delete rect;
 }
 
+//QTBUG-25139
+void tst_qquickbehaviors::multipleChangesToValueType()
+{
+    QQmlEngine engine;
+
+    QQmlComponent c(&engine, testFileUrl("multipleChangesToValueType.qml"));
+    QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle *>(c.create()));
+    QVERIFY(rect != 0);
+
+    QQuickText *text = rect->findChild<QQuickText *>();
+    QVERIFY(text != 0);
+
+    QFont value;
+    value.setPointSize(24);
+    QCOMPARE(text->property("font").value<QFont>(), value);
+
+    QVERIFY(QMetaObject::invokeMethod(rect.data(), "updateFontProperties"));
+
+    value.setItalic(true);
+    value.setWeight(QFont::Bold);
+    QCOMPARE(text->property("font").value<QFont>(), value);
+
+    value.setPointSize(48);
+    QTRY_COMPARE(text->property("font").value<QFont>(), value);
+}
+
 QTEST_MAIN(tst_qquickbehaviors)
 
 #include "tst_qquickbehaviors.moc"