aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2024-02-27 12:54:27 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-03-01 08:13:23 +0000
commitae9905b0c2cced7beb1bb4114b4296dfdbc32b19 (patch)
tree1322f1ab015d77f80a5dd427188b47b0a21aee2c
parent372a231ccfdde541331a6a3c75f79b19db6572b6 (diff)
Binding: fix restore logic
Consider a Binding affecting a property which initially has a value (not a binding). When restoring the initial value of a property, we did not remove any binding that might have been installed on it by Binding. Then, when the Binding would subsequently get enabled again, it would pick up the still installed binding instead of the actually restored property. From that point on, the original value would have been lost. Fix this by clearing any existing bindings when we restore a value. Pick-to: 6.5 Fixes: QTBUG-122707 Change-Id: Ife7c43c7e799c71257fc04bbd76ff902422bd49d Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> (cherry picked from commit 98ecc9adbbb0f032f4ef4341d4cdd896158d4409) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit a262824c22c069779900a9ddeda903c1ee33700c)
-rw-r--r--src/qml/types/qqmlbind.cpp2
-rw-r--r--tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml13
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp25
3 files changed, 40 insertions, 0 deletions
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index e400c3a515..5146b30df4 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -1026,6 +1026,7 @@ void QQmlBind::eval()
break;
case QQmlBindEntryKind::V4Value:
if (d->restoreValue) {
+ QQmlAnyBinding::takeFrom(entry.prop); // we don't want to have a binding active
auto propPriv = QQmlPropertyPrivate::get(entry.prop);
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
Q_ASSERT(vmemo);
@@ -1036,6 +1037,7 @@ void QQmlBind::eval()
break;
case QQmlBindEntryKind::Variant:
if (d->restoreValue) {
+ QQmlAnyBinding::takeFrom(entry.prop); // we don't want to have a binding active
entry.prop.write(entry.previous.variant);
entry.clearPrev();
}
diff --git a/tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml b/tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml
new file mode 100644
index 0000000000..251e71f771
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+ id: root
+ property bool enabled: false
+ property var func: function() { return 1 }
+ property var arr: [1, 2]
+ property Binding b: Binding {
+ root.func: function() { return 2 };
+ root.arr: [1, 2, 3]
+ when: root.enabled
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
index fbb805d86a..9503ec80c5 100644
--- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
+++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
@@ -40,6 +40,7 @@ private slots:
void localSignalHandler();
void whenEvaluatedEarlyEnough();
void propertiesAttachedToBindingItself();
+ void toggleEnableProperlyRemembersValues();
private:
QQmlEngine engine;
@@ -629,6 +630,30 @@ void tst_qqmlbinding::propertiesAttachedToBindingItself()
QTRY_COMPARE(root->property("check").toInt(), 3);
}
+void tst_qqmlbinding::toggleEnableProperlyRemembersValues()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("toggleEnableProperlyRemembersValues.qml"));
+ std::unique_ptr<QObject> root { c.create() };
+ QVERIFY2(root, qPrintable(c.errorString()));
+ for (int i = 0; i < 3; ++i) {
+ {
+ QJSManagedValue arr(root->property("arr"), &e);
+ QJSManagedValue func(root->property("func"), &e);
+ QCOMPARE(arr.property("length").toInt(), 2);
+ QCOMPARE(func.call().toInt(), 1);
+ }
+ root->setProperty("enabled", true);
+ {
+ QJSManagedValue arr(root->property("arr"), &e);
+ QJSManagedValue func(root->property("func"), &e);
+ QCOMPARE(arr.property("length").toInt(), 3);
+ QCOMPARE(func.call().toInt(), 2);
+ }
+ root->setProperty("enabled", false);
+ }
+}
+
QTEST_MAIN(tst_qqmlbinding)
#include "tst_qqmlbinding.moc"