aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/types/qqmlbind.cpp
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-01-21 20:02:17 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2021-02-03 09:28:40 +0100
commit0deb3961e6b0a1f15a491f7a19085df3a7a506b1 (patch)
tree28c9db4fd4bd0a334a1848d852f6394f83bc97d9 /src/qml/types/qqmlbind.cpp
parentb322a971f06823a4356f2b3aa331501aa4d0dc7f (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.cpp49
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);
}