aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-09-16 16:41:27 +0200
committerUlf Hermann <ulf.hermann@qt.io>2020-09-23 14:54:46 +0200
commit8e222a70d19d5eef616e1d6306415da64fbab4cb (patch)
tree535e4cd02c2dbca0289bc6ec39f2699856554737 /tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
parent90b5d7fa03f9818fa5edc897ee6a109fcc182b9e (diff)
Allow proper registration of value types
You can now have an extension object on a value type that offers additional properties. This is how we model the QtQuick value types. It allows us to retrieve the extension's metaobject without using the virtual functions in the value type provider. As before, this mechanism is still rather dangerous and not fit for public consumption. It relies on the extension object having exactly the same layout as the original value type, and it hides any properties the original value type might expose. Furthermore we enforce now that gadgets should have lowercase names. The ones that didn't before are split up into an anonymous value type and a namespace that contains all the addressable bits. Task-number: QTBUG-82443 Change-Id: Ic93d6764538d6ccc0774b3c5648eee08ba0939c0 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp')
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp78
1 files changed, 78 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 1311319266..582b4e0126 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -338,6 +338,7 @@ private slots:
void checkUncreatableNoReason();
void checkURLtoURLObject();
+ void registerValueTypes();
private:
QQmlEngine engine;
@@ -5923,6 +5924,83 @@ void tst_qqmllanguage::checkURLtoURLObject()
QCOMPARE(c.errors().count(), 0);
}
+struct TestValueType
+{
+ Q_GADGET
+ Q_PROPERTY(int foo MEMBER foo)
+public:
+ int foo = 12;
+
+ friend bool operator==(const TestValueType &a, const TestValueType &b)
+ {
+ return a.foo == b.foo;
+ }
+
+ friend bool operator!=(const TestValueType &a, const TestValueType &b)
+ {
+ return a.foo != b.foo;
+ }
+};
+
+struct TestExtendedValueType
+{
+ Q_GADGET
+ Q_PROPERTY(int bar READ bar WRITE setBar)
+public:
+ TestValueType wrapped;
+
+ int bar() const { return wrapped.foo; }
+ void setBar(int bar) { wrapped.foo = bar; }
+};
+
+class TestObjectType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(TestValueType test MEMBER test)
+public:
+ TestValueType test;
+};
+
+void tst_qqmllanguage::registerValueTypes()
+{
+ QTest::ignoreMessage(QtWarningMsg, "Invalid QML element name \"UpperCase\"; value type names must begin with a lowercase letter");
+ QCOMPARE(qmlRegisterType<TestValueType>("DoesNotWork", 1, 0, "UpperCase"), -1);
+ QVERIFY(qmlRegisterType<TestObjectType>("DoesWork", 1, 0, "TestObject") >= 0);
+
+ {
+ QQmlEngine engine;
+ QQmlComponent c(&engine);
+ c.setData("import QtQml\nimport DoesWork\nTestObject { Component.onCompleted: test.foo = 14 }", QUrl());
+ QVERIFY(c.isReady());
+ QScopedPointer<QObject> obj(c.create());
+ QCOMPARE(obj->property("test").value<TestValueType>().foo, 14);
+
+ QQmlComponent c2(&engine);
+ c2.setData("import QtQml\nimport DoesWork\n TestObject { Component.onCompleted: test.bar = 14 }", QUrl());
+ QVERIFY(c2.isReady());
+ QScopedPointer<QObject> obj2(c2.create());
+ QCOMPARE(obj2->property("test").value<TestValueType>().foo, 12);
+ }
+
+ QVERIFY((qmlRegisterExtendedType<TestValueType, TestExtendedValueType>("DoesWork", 1, 0, "lowerCase")) >= 0);
+
+ {
+ QQmlEngine engine;
+ QQmlComponent c(&engine);
+ c.setData("import QtQml\nimport DoesWork\nTestObject { Component.onCompleted: test.foo = 14 }", QUrl());
+ QVERIFY(c.isReady());
+ QScopedPointer<QObject> obj(c.create());
+ // The foo property is hidden now.
+ QCOMPARE(obj->property("test").value<TestValueType>().foo, 12);
+
+ QQmlComponent c2(&engine);
+ c2.setData("import QtQml\nimport DoesWork\n TestObject { Component.onCompleted: test.bar = 14 }", QUrl());
+ QVERIFY(c2.isReady());
+ QScopedPointer<QObject> obj2(c2.create());
+ QCOMPARE(obj2->property("test").value<TestValueType>().foo, 14);
+ }
+}
+
void tst_qqmllanguage::accessNullPointerPropertyCache()
{
QQmlEngine engine;