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 Pick-to: 6.5 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>
This commit is contained in:
parent
3bd201c4da
commit
82f2ee8027
|
@ -463,10 +463,26 @@ void QQmlBind::setObject(QObject *obj)
|
||||||
eval();
|
eval();
|
||||||
d->when = true;
|
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;
|
d->obj = obj;
|
||||||
if (d->componentComplete) {
|
if (d->componentComplete) {
|
||||||
setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this)));
|
setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this)));
|
||||||
d->validate(this);
|
if (d->when)
|
||||||
|
d->validate(this);
|
||||||
}
|
}
|
||||||
eval();
|
eval();
|
||||||
}
|
}
|
||||||
|
@ -520,7 +536,8 @@ void QQmlBind::setProperty(const QString &p)
|
||||||
d->propName = p;
|
d->propName = p;
|
||||||
if (d->componentComplete) {
|
if (d->componentComplete) {
|
||||||
setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this)));
|
setTarget(QQmlProperty(d->obj, d->propName, qmlContext(this)));
|
||||||
d->validate(this);
|
if (d->when)
|
||||||
|
d->validate(this);
|
||||||
}
|
}
|
||||||
eval();
|
eval();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,6 +38,7 @@ private slots:
|
||||||
void intOverflow();
|
void intOverflow();
|
||||||
void generalizedGroupedProperties();
|
void generalizedGroupedProperties();
|
||||||
void localSignalHandler();
|
void localSignalHandler();
|
||||||
|
void whenEvaluatedEarlyEnough();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QQmlEngine engine;
|
QQmlEngine engine;
|
||||||
|
@ -596,6 +597,19 @@ void tst_qqmlbinding::localSignalHandler()
|
||||||
QCOMPARE(o->property("output").toString(), QStringLiteral("abc"));
|
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)
|
QTEST_MAIN(tst_qqmlbinding)
|
||||||
|
|
||||||
#include "tst_qqmlbinding.moc"
|
#include "tst_qqmlbinding.moc"
|
||||||
|
|
Loading…
Reference in New Issue