aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2023-04-14 14:29:19 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-04-19 20:05:46 +0000
commit35de689c6295c77c1588ebb1d2af6d5e6f23e954 (patch)
treeb275c19327d08fa0b7472540f88fe333c4fdd51b
parent08cf921344c859e73816a563b3e8dd7954369545 (diff)
Binding: Reevaluate when before the target changes
...and do not warn about missing properties if when is disabled. Besides avoiding spurious warnings, this also avoids modifying a property only to restore its binding/value directly afterwards. Note that when the binding gets re-enabled, we still trigger the warning. Fixes: QTBUG-112860 Change-Id: I5ddd32f2de2dec9da372b08ab4bb5bdb88873e51 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> (cherry picked from commit 82f2ee8027f733cec5961aac27a171cf0b78a70b) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/qml/types/qqmlbind.cpp21
-rw-r--r--tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml23
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp14
3 files changed, 56 insertions, 2 deletions
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index f69462b937..8bfe9d4c4e 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -463,10 +463,26 @@ void QQmlBind::setObject(QObject *obj)
eval();
d->when = true;
}
+ /* if "when" and "target" depend on the same property, we might
+ end up here before we could have updated "when". So reevaluate
+ when manually here.
+ */
+ const QQmlProperty whenProp(this, QLatin1StringView("when"));
+ const auto potentialWhenBinding = QQmlAnyBinding::ofProperty(whenProp);
+ if (auto abstractBinding = potentialWhenBinding.asAbstractBinding()) {
+ QQmlBinding *binding = static_cast<QQmlBinding *>(abstractBinding);
+ if (binding->hasValidContext()) {
+ const auto boolType = QMetaType::fromType<bool>();
+ bool when;
+ binding->evaluate(&when, boolType);
+ d->when = when;
+ }
+ }
d->obj = obj;
if (d->componentComplete) {
setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this)));
- d->validate(this);
+ if (d->when)
+ d->validate(this);
}
eval();
}
@@ -520,7 +536,8 @@ void QQmlBind::setProperty(const QString &p)
d->propName = p;
if (d->componentComplete) {
setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this)));
- d->validate(this);
+ if (d->when)
+ d->validate(this);
}
eval();
}
diff --git a/tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml b/tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml
new file mode 100644
index 0000000000..6245270e14
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml
@@ -0,0 +1,23 @@
+import QtQuick
+
+Item {
+ id: root
+ property bool toggle: true
+ property bool forceEnable: false
+
+ Item {
+ id: item1
+ property int i
+ }
+
+ Item {
+ id: item2
+ }
+
+ Binding {
+ target: root.toggle ? item1 : item2
+ when: root.forceEnable || (root.toggle ? item1 : item2).hasOwnProperty("i")
+ property: "i"
+ value: 42
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
index a6b734acd7..2d6d47c5b1 100644
--- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
+++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
@@ -38,6 +38,7 @@ private slots:
void intOverflow();
void generalizedGroupedProperties();
void localSignalHandler();
+ void whenEvaluatedEarlyEnough();
private:
QQmlEngine engine;
@@ -596,6 +597,19 @@ void tst_qqmlbinding::localSignalHandler()
QCOMPARE(o->property("output").toString(), QStringLiteral("abc"));
}
+void tst_qqmlbinding::whenEvaluatedEarlyEnough()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("whenEvaluatedEarlyEnough.qml"));
+ QTest::failOnWarning(QRegularExpression(".*"));
+ std::unique_ptr<QObject> root { c.create() };
+ root->setProperty("toggle", false); // should not cause warnings
+ // until "when" is actually true
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg,
+ QRegularExpression(".*QML Binding: Property 'i' does not exist on Item.*"));
+ root->setProperty("forceEnable", true);
+}
+
QTEST_MAIN(tst_qqmlbinding)
#include "tst_qqmlbinding.moc"