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();
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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 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"
|
||||
|
|
Loading…
Reference in New Issue