aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-09-24 11:06:06 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2021-06-03 14:58:12 +0200
commit4017505cbcd553f25779a5f449c13863b2c0622c (patch)
tree6e349e76f1e33b2d1265d7030a28ed5edd5e5f4f /tests/auto
parent2028b74fd24a9e7f822203372fd96af9356e7cf7 (diff)
QQuickItem: Make x/y/width/height bindable
This ports the four properties properties to Q_OBJECT_COMPAT_PROPERTY. It is not possible to use Q_OBJECT_BINDABLE_PROPERTY, not even for the simpler x and y properties, as QQuickItem calls the virtual geometryChange method in the setters, making them non-trivial. For width/height, we use the new property system to improve the width/heightValid check: We return not only valid if the property has explictily been set (either via a direct setter call, or because the setter has been called when a binding evaluated), but also when a binding is set. This matches the fact that implicitWidth/Height should only be used when width/height is not specified. In theory, this could help in cases where one sets both implicit and explicit properties for Text, skipping one initial layout calculation. As the setters now remove the binding (this aligns with the behavior of writing through the meta-object system), a few test cases had to be adjusted, which relied on the setter not removing it. Further test changes were necessary because the location of a few warnings changed, due to differences in binding order evaluation and error reporting. [ChangeLog][QtQuick][QQuickItem] The x, y, width and height properties of QQuickItem are now bindable. This enables modifying their bindings from C++. One could for instance swap the width of two items, preserving the bindings: // QML Item { Rectangle { id: a; width: parent.width / 2 } Rectangle { id: b; width: parent.width / 3; anchors.right: a.left } } // C++ auto rootCtxt = engine.rootContext(); auto a = qobject_cast<QQuickItem*>(rootCtxt->objectForName(u"a"_qs)); auto b = qobject_cast<QQuickItem*>(rootCtxt->objectForName(u"b"_qs)); auto aBinding = a->bindableWidth().takeBinding(); auto bBinding = b->bindableWidth().takeBinding(); a->bindableWidth()->setBinding(bBinding); b->bindableWidth()->setBinding(aBinding); Afterwards, if the root item gets resized, the width of the rectangles will still be adjusted. [ChangeLog][QtQuick][QQuickItem][Important Behavior Changes] Calling the setWidth, setHeight, setX and setY properties now removes any existing binding from the corresponding property. Change-Id: I5e1553611cb92b033247ada715cea48c962395bc Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp4
-rw-r--r--tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp2
-rw-r--r--tests/auto/quick/qquickitem2/CMakeLists.txt2
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp33
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp12
5 files changed, 43 insertions, 10 deletions
diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
index bc1d86980f..c0c96ca6e5 100644
--- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
+++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
@@ -262,8 +262,8 @@ void tst_qqmlbinding::restoreBindingWithLoop()
QCOMPARE(myItem->x(), qreal(88));
//original binding restored
- QString warning = c.url().toString() + QLatin1String(":9:5: QML Rectangle: Binding loop detected for property \"x\"");
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+ QString warning = c.url().toString() + QLatin1String(R"(:\d+:\d+: QML Rectangle: Binding loop detected for property "x")");
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(warning));
rect->setProperty("activateBinding", false);
QCOMPARE(myItem->x(), qreal(88 + 100)); //if loop handling changes this could be 90 + 100
diff --git a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp
index bb96ba319c..7b7a12ee1b 100644
--- a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp
+++ b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp
@@ -242,7 +242,7 @@ void tst_qqmlinfo::attachedObject()
QVERIFY(warningSpy.isValid());
const QString qmlBindingLoopMessage = "QML Rectangle: Binding loop detected for property \"width\"";
- const QString qmlBindingLoopMessageFull = component.url().toString() + ":7:5: " + qmlBindingLoopMessage;
+ const QString qmlBindingLoopMessageFull = component.url().toString() + ":8:9: " + qmlBindingLoopMessage;
QTest::ignoreMessage(QtWarningMsg, qPrintable(qmlBindingLoopMessageFull));
const QString cppBindingLoopMessage = "QML AttachedObject (parent or ancestor of Attached): Binding loop detected for property \"a\"";
diff --git a/tests/auto/quick/qquickitem2/CMakeLists.txt b/tests/auto/quick/qquickitem2/CMakeLists.txt
index f60d1b2d55..6ecd164787 100644
--- a/tests/auto/quick/qquickitem2/CMakeLists.txt
+++ b/tests/auto/quick/qquickitem2/CMakeLists.txt
@@ -22,6 +22,8 @@ qt_internal_add_test(tst_qquickitem2
Qt::GuiPrivate
Qt::QmlPrivate
Qt::QuickPrivate
+ LIBRARIES
+ Qt::TestPrivate
TESTDATA ${test_data}
)
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index 94f71af394..b5e2f5e141 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -42,6 +42,7 @@
#include "../../shared/util.h"
#include "../shared/visualtestutil.h"
#include "../../shared/platforminputcontext.h"
+#include <QtTest/private/qpropertytesthelper_p.h>
using namespace QQuickVisualTestUtil;
@@ -117,6 +118,8 @@ private slots:
void childrenProperty();
void resourcesProperty();
+ void bindableProperties_data();
+ void bindableProperties();
void changeListener();
void transformCrash();
@@ -2843,6 +2846,30 @@ void tst_QQuickItem::resourcesProperty()
delete object;
}
+void tst_QQuickItem::bindableProperties_data()
+{
+ QTest::addColumn<qreal>("initialValue");
+ QTest::addColumn<qreal>("newValue");
+ QTest::addColumn<QString>("property");
+
+ // can't simply use 3. or 3.0 for the numbers as qreal might
+ // be float instead of double...
+ QTest::addRow("x") << qreal(3) << qreal(14) << "x";
+ QTest::addRow("y") << qreal(10) << qreal(20) << "y";
+ QTest::addRow("width") << qreal(100) << qreal(200) << "width";
+ QTest::addRow("height") << qreal(50) << qreal(40) << "height";
+}
+
+void tst_QQuickItem::bindableProperties()
+{
+ QQuickItem item;
+ QFETCH(qreal, initialValue);
+ QFETCH(qreal, newValue);
+ QFETCH(QString, property);
+
+ QTestPrivate::testReadWritePropertyBasics(item, initialValue, newValue, property.toUtf8().constData());
+}
+
void tst_QQuickItem::propertyChanges()
{
QQuickView *window = new QQuickView(nullptr);
@@ -2967,7 +2994,7 @@ void tst_QQuickItem::childrenRectBug()
{
QQuickView *window = new QQuickView(nullptr);
- QString warning = testFileUrl("childrenRectBug.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"height\"";
+ QString warning = testFileUrl("childrenRectBug.qml").toString() + ":11:9: QML Item: Binding loop detected for property \"height\"";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
@@ -2988,11 +3015,11 @@ void tst_QQuickItem::childrenRectBug2()
{
QQuickView *window = new QQuickView(nullptr);
- QString warning1 = testFileUrl("childrenRectBug2.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"width\"";
+ QString warning1 = testFileUrl("childrenRectBug2.qml").toString() + ":10:9: QML Item: Binding loop detected for property \"width\"";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
- QString warning2 = testFileUrl("childrenRectBug2.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"height\"";
+ QString warning2 = testFileUrl("childrenRectBug2.qml").toString() + ":11:9: QML Item: Binding loop detected for property \"height\"";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index b5ab520055..056028b3f0 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -28,6 +28,7 @@
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
+#include <private/qquickitem_p.h>
#include <private/qquickmultipointtoucharea_p.h>
#include <private/qquickflickable_p.h>
#include <private/qquickmousearea_p.h>
@@ -1051,10 +1052,13 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QPoint touch1(10,10);
QPoint touch2(100,10);
- touch1rect->setX(10);
- touch1rect->setY(10);
- touch2rect->setX(20);
- touch2rect->setY(10);
+ // do not break the QML bindings
+ auto t1priv = QQuickItemPrivate::get(touch1rect);
+ auto t2priv = QQuickItemPrivate::get(touch2rect);
+ t1priv->x.setValueBypassingBindings(10);
+ t1priv->y.setValueBypassingBindings(10);
+ t2priv->x.setValueBypassingBindings(20);
+ t2priv->y.setValueBypassingBindings(10);
// Start with mouse, move it, touch a point, move it, touch another.
// Mouse is ignored, both touch points are heeded.