aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-02-09 16:24:31 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2021-05-25 16:09:05 +0200
commite3c9fdfffb2f62da90938e8e5e76f1d15f30385d (patch)
treea0c929025f698b86055e3ff8ebf34beb84184455 /tests
parent14b8fc630f2a77b1382136e6943f2cafb44bd154 (diff)
Behavior: intercept bindings
Use the new API in QQmlPropertyValueInterceptor and QQmlInterceptorMetaObject to acutally intercept bindable properties in Behavior. This works as follows: We intercept the bindable metacall, and construct an untyped proxy property. The proxy property has storage for the property data (currently via constructing a QVariant for it). It also has its own binding data. We install an observer on the proxy binding data which notifies us whenever the proxy changes. That observer is actually the QQuickBehaviorPrivate (which now inherits QPropertyObserver). Whenever the observer triggers, we read the current value of the proxy property and call QQuickBehavior::write with it. That's how Behavior can now track updates. As binding updates end up calling the write method of the Behavior, we get support for toggling enabled for free. The final part of the puzzle is how to get the property system to use the proxy property instead of the real property. This is done when we intercept the Bindable metacall: Instead of returning the source's QUntypedBindable, we construct a custom one. Its functions do the following: - setting/getting values and bindings do not affect the source, but instead operate on the proxy - observers are still installed on the source; that way, they see all writes done by the interceptor, instead of only the direct writes to the source property - makeBinding forwards to the source - We make use of the metatype multiplexing hack in the getter Task-number: QTBUG-90999 Change-Id: Ib91a12b05975f1257026ba4d2b64ec14852d4a14 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/quick/qquickbehaviors/CMakeLists.txt9
-rw-r--r--tests/auto/quick/qquickbehaviors/bindable.h48
-rw-r--r--tests/auto/quick/qquickbehaviors/data/bindableProperty.qml12
-rw-r--r--tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp27
4 files changed, 95 insertions, 1 deletions
diff --git a/tests/auto/quick/qquickbehaviors/CMakeLists.txt b/tests/auto/quick/qquickbehaviors/CMakeLists.txt
index 330df778b6..b864b0c21b 100644
--- a/tests/auto/quick/qquickbehaviors/CMakeLists.txt
+++ b/tests/auto/quick/qquickbehaviors/CMakeLists.txt
@@ -14,6 +14,7 @@ qt_internal_add_test(tst_qquickbehaviors
SOURCES
../../shared/util.cpp ../../shared/util.h
tst_qquickbehaviors.cpp
+ bindable.h
INCLUDE_DIRECTORIES
../../shared
PUBLIC_LIBRARIES
@@ -25,6 +26,14 @@ qt_internal_add_test(tst_qquickbehaviors
TESTDATA ${test_data}
)
+set_target_properties(tst_qquickbehaviors PROPERTIES
+ QT_QML_MODULE_VERSION 1.0
+ QT_QML_MODULE_URI test
+)
+
+qt6_qml_type_registration(tst_qquickbehaviors)
+
+
#### Keys ignored in scope 1:.:.:qquickbehaviors.pro:<TRUE>:
# DISTFILES = "data/*"
diff --git a/tests/auto/quick/qquickbehaviors/bindable.h b/tests/auto/quick/qquickbehaviors/bindable.h
new file mode 100644
index 0000000000..ebdf8711a3
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/bindable.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BINDABLE_H
+#define BINDABLE_H
+
+#include <QObject>
+#include <QQuickItem>
+#include <qqmlregistration.h>
+
+class TestBindable : public QQuickItem
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(int prop READ prop WRITE setProp BINDABLE bindableProp)
+public:
+ int prop() { return m_prop; }
+ void setProp(int i) { m_prop = i; }
+ QBindable<int> bindableProp() { return &m_prop; }
+
+private:
+ QProperty<int> m_prop;
+};
+#endif
diff --git a/tests/auto/quick/qquickbehaviors/data/bindableProperty.qml b/tests/auto/quick/qquickbehaviors/data/bindableProperty.qml
new file mode 100644
index 0000000000..e4d76036aa
--- /dev/null
+++ b/tests/auto/quick/qquickbehaviors/data/bindableProperty.qml
@@ -0,0 +1,12 @@
+import QtQuick
+import test
+
+TestBindable {
+ property int targetValue: 0
+ prop: targetValue
+ property alias enableBehavior: behavior.enabled
+ Behavior on prop {
+ id: behavior
+ NumberAnimation {duration: 100}
+ }
+}
diff --git a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
index 3b46019f64..35423651f9 100644
--- a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
+++ b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -37,6 +37,7 @@
#include <QtQuick/private/qquicksmoothedanimation_p.h>
#include <private/qquickitem_p.h>
#include "../../shared/util.h"
+#include "bindable.h"
class tst_qquickbehaviors : public QQmlDataTest
{
@@ -76,6 +77,7 @@ private slots:
void oneWay();
void safeToDelete();
void targetProperty();
+ void bindableProperty();
};
void tst_qquickbehaviors::simpleBehavior()
@@ -678,6 +680,29 @@ void tst_qquickbehaviors::targetProperty()
QCOMPARE(item->property("emptyBehaviorName").toString(), "");
}
+void tst_qquickbehaviors::bindableProperty()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("bindableProperty.qml"));
+ QScopedPointer<QObject> root(c.create());
+ QVERIFY2(root, qPrintable(c.errorString()));
+ auto testBindable = qobject_cast<TestBindable *>(root.get());
+ QVERIFY(testBindable);
+
+ testBindable->setProperty("targetValue", 100);
+ QVERIFY(testBindable->prop() != 100);
+ QTRY_COMPARE(testBindable->prop(), 100);
+
+ testBindable->setProperty("enableBehavior", false);
+ testBindable->setProperty("targetValue", 200);
+ QCOMPARE(testBindable->prop(), 200);
+
+ testBindable->setProperty("enableBehavior", true);
+ testBindable->setProperty("prop", 300); // write through metaobject system gets intercepted
+ QVERIFY(testBindable->prop() != 300);
+ QTRY_COMPARE(testBindable->prop(), 300);
+}
+
QTEST_MAIN(tst_qquickbehaviors)