diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-01-21 20:02:17 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2021-02-03 09:28:40 +0100 |
commit | 0deb3961e6b0a1f15a491f7a19085df3a7a506b1 (patch) | |
tree | 28c9db4fd4bd0a334a1848d852f6394f83bc97d9 /src/qml/types/qqmlbind.cpp | |
parent | b322a971f06823a4356f2b3aa331501aa4d0dc7f (diff) |
QmlBind: support bindable properties
This patch ensures that the QML Binding element can also save and restore
C++ bindings. Should QQuickItem's x and y property be ported to the new
property system, we'd need new test cases to verify that "old-style"
bindings are still handled correctly. This task is however left for the
change porting the properties.
Task-number: QTBUG-90493
Change-Id: I506ffa1060ff32a7d722214e5ccd469bdaa61ff8
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/types/qqmlbind.cpp')
-rw-r--r-- | src/qml/types/qqmlbind.cpp | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index 6d762401d0..8fc26a2550 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -83,7 +83,10 @@ public: QString propName; QQmlNullableValue<QJSValue> value; QQmlProperty prop; - QQmlAbstractBinding::Ptr prevBind; + union { + QQmlAbstractBinding::Ptr prevBind; + QUntypedPropertyBinding prevPropertyBinding; + }; QV4::PersistentValue v4Value; QVariant prevValue; bool prevIsVariant:1; @@ -96,6 +99,7 @@ public: void validate(QObject *binding) const; void clearPrev(); + bool prevBindingSet() const; }; void QQmlBindPrivate::validate(QObject *binding) const @@ -444,12 +448,23 @@ void QQmlBind::prepareEval() void QQmlBindPrivate::clearPrev() { - prevBind = nullptr; + if (prop.property().isBindable()) + prevPropertyBinding = {}; + else + prevBind = nullptr; v4Value.clear(); prevValue.clear(); prevIsVariant = false; } +bool QQmlBindPrivate::prevBindingSet() const +{ + if (prop.property().isBindable()) + return !prevPropertyBinding.isNull(); + else + return prevBind; +} + void QQmlBind::eval() { Q_D(QQmlBind); @@ -460,11 +475,18 @@ void QQmlBind::eval() if (d->when.isValid()) { if (!d->when) { //restore any previous binding - if (d->prevBind) { + if (d->prevBindingSet()) { if (d->restoreBinding) { - QQmlAbstractBinding::Ptr p = d->prevBind; - d->clearPrev(); // Do that before setBinding(), as setBinding() may recurse. - QQmlPropertyPrivate::setBinding(p.data()); + QMetaProperty metaProp = d->prop.property(); + if (metaProp.isBindable()) { + auto prevBinding = d->prevPropertyBinding; + d->clearPrev(); // Do that before setBinding(), as setBinding() may recurse. + metaProp.bindable(d->prop.object()).setBinding(prevBinding); + } else { + QQmlAbstractBinding::Ptr p = d->prevBind; + d->clearPrev(); // Do that before setBinding(), as setBinding() may recurse. + QQmlPropertyPrivate::setBinding(p.data()); + } } } else if (!d->v4Value.isEmpty()) { if (d->restoreValue) { @@ -484,11 +506,18 @@ void QQmlBind::eval() } //save any set binding for restoration - if (!d->prevBind && d->v4Value.isEmpty() && !d->prevIsVariant) { + if (!d->prevBindingSet() && d->v4Value.isEmpty() && !d->prevIsVariant) { // try binding first - d->prevBind = QQmlPropertyPrivate::binding(d->prop); + d->prop.property().isBindable(); + QMetaProperty metaProp = d->prop.property(); + if (metaProp.isBindable()) { + QUntypedBindable bindable = d->prop.property().bindable(d->prop.object()); + d->prevPropertyBinding = bindable.takeBinding(); + } else { + d->prevBind = QQmlPropertyPrivate::binding(d->prop); + } - if (!d->prevBind) { // nope, try a V4 value next + if (!d->prevBindingSet()) { // nope, try a V4 value next auto propPriv = QQmlPropertyPrivate::get(d->prop); auto propData = propPriv->core; if (!propPriv->valueTypeData.isValid() && propData.isVarProperty()) { @@ -503,6 +532,8 @@ void QQmlBind::eval() } } + // NOTE: removeBinding has no effect on QProperty classes, but + // we already used takeBinding to remove it QQmlPropertyPrivate::removeBinding(d->prop); } |