diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2020-03-10 15:09:37 +0100 |
---|---|---|
committer | Alexandru Croitor <alexandru.croitor@qt.io> | 2020-03-12 15:03:03 +0100 |
commit | 26c5243491f495194f04b449128dae36118e28da (patch) | |
tree | 7fb14678a6fc9e44a10c9224d005e2cbdc6bcb63 /tests/auto/qml/qqmllanguage | |
parent | 1c7d264e3b2e9a2f0021786ea6967185f8282af0 (diff) | |
parent | c24c5baeda4101b0058689adf9200b77a722c3a2 (diff) |
Merge remote-tracking branch 'origin/dev' into wip/cmake
Conflicts:
dependencies.yaml
src/qml/qml/qqmlengine.cpp
Change-Id: I6a73fd1064286f4a2232de85c2ce7f80452d4641
Diffstat (limited to 'tests/auto/qml/qqmllanguage')
24 files changed, 455 insertions, 19 deletions
diff --git a/tests/auto/qml/qqmllanguage/data/Action.qml b/tests/auto/qml/qqmllanguage/data/Action.qml new file mode 100644 index 0000000000..4db2bacf6e --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/Action.qml @@ -0,0 +1,21 @@ +import QtQuick 2.12 + +QtObject { + id:root + property Item parent + property Item displayComponent: null + + property list<QtObject> children + + readonly property var visibleChildren: { + var visible = []; + var child; + for (var i in children) { + child = children[i]; + if (!child.hasOwnProperty("visible") || child.visible) { + visible.push(child) + } + } + return visible; + } +} diff --git a/tests/auto/qml/qqmllanguage/data/NonRequiredBase.qml b/tests/auto/qml/qqmllanguage/data/NonRequiredBase.qml new file mode 100644 index 0000000000..60d45c2b1e --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/NonRequiredBase.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + property int i +} diff --git a/tests/auto/qml/qqmllanguage/data/RequiredBase.qml b/tests/auto/qml/qqmllanguage/data/RequiredBase.qml new file mode 100644 index 0000000000..4effdbf1c7 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/RequiredBase.qml @@ -0,0 +1,3 @@ +NonRequiredBase { + required i +} diff --git a/tests/auto/qml/qqmllanguage/data/SimpleItem.qml b/tests/auto/qml/qqmllanguage/data/SimpleItem.qml new file mode 100644 index 0000000000..c7bce2bc78 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/SimpleItem.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + property int i: 42 +} diff --git a/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml b/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml new file mode 100644 index 0000000000..ee400eb41f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml @@ -0,0 +1,7 @@ +import QtQml 2.14 +import qt.test 1.0 + +TestItem { + property var vector + positions: vector +} diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml new file mode 100644 index 0000000000..76673f6409 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredProperty.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +MyClass {test: 42} diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml new file mode 100644 index 0000000000..d4c059581c --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParent.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +Child2 {test: test2; test2: 18} diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml new file mode 100644 index 0000000000..082e22dc3f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInChildAndParentNotSet.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +Child2 { test: 13 } diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml new file mode 100644 index 0000000000..6602684542 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParent.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +Child {test: 42} diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml new file mode 100644 index 0000000000..5971b0c263 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyInParentNotSet.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +Child {} diff --git a/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml new file mode 100644 index 0000000000..dab48a3d71 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppRequiredPropertyNotSet.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import example.org 1.0 + +MyClass {} diff --git a/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.2.qml b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.2.qml new file mode 100644 index 0000000000..3b37c29b18 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.2.qml @@ -0,0 +1,5 @@ +import StaticTest 1.0 + +MyStaticSecondNamespacedType { + list: [ MyStaticNamespacedType {} ] +} diff --git a/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.qml b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.qml new file mode 100644 index 0000000000..2778baadb9 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cppstaticnamespace.qml @@ -0,0 +1,6 @@ +import StaticTest 1.0 + +MyStaticNamespacedType { + myEnum: MyStaticNamespace.Key5 + property int intProperty: MyStaticNamespace.MyOtherNSEnum.OtherKey2 +} diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml new file mode 100644 index 0000000000..ab125e9323 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/inlineComponentWithAlias.qml @@ -0,0 +1,17 @@ +import QtQuick 2.15 + +Item { + id: root + component IC: SimpleItem { + width: i + Rectangle { + id: rect + color: "lime" + } + property alias color: rect.color + } + width: 200 + IC { + objectName: "icInstance" + } +} diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml new file mode 100644 index 0000000000..c4093bad2f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/inlineComponentWithId.qml @@ -0,0 +1,14 @@ +import QtQuick 2.15 + +Item { + id: root + component IC: SimpleItem { + id: root + width: root.i + property color color: "red" + } + width: 200 + IC { + objectName: "icInstance" + } +} diff --git a/tests/auto/qml/qqmllanguage/data/listPropertiesChild.qml b/tests/auto/qml/qqmllanguage/data/listPropertiesChild.qml new file mode 100644 index 0000000000..b1635a9409 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/listPropertiesChild.qml @@ -0,0 +1,7 @@ +import QtQuick 2.12 + +Action +{ + id: action + property color color +} diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml index 534322215f..2585cf361e 100644 --- a/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.3.qml @@ -1,4 +1,6 @@ -import QtQuick 2.13 +import QtQuick 2.15 + Item { - default required property int test // cannot have required default property + property int i; + required i; } diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.4.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.4.qml new file mode 100644 index 0000000000..1126f845c9 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.4.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + required objectName +} diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.5.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.5.qml new file mode 100644 index 0000000000..c2d155b123 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.5.qml @@ -0,0 +1 @@ +RequiredBase {} diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.6.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.6.qml new file mode 100644 index 0000000000..e8802aef20 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.6.qml @@ -0,0 +1,3 @@ +RequiredBase { + i: 42 +} diff --git a/tests/auto/qml/qqmllanguage/data/requiredProperties.7.qml b/tests/auto/qml/qqmllanguage/data/requiredProperties.7.qml new file mode 100644 index 0000000000..40987f5c56 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/requiredProperties.7.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + required blub +} diff --git a/tests/auto/qml/qqmllanguage/qqmllanguage.pro b/tests/auto/qml/qqmllanguage/qqmllanguage.pro index 724a27320c..6c54525544 100644 --- a/tests/auto/qml/qqmllanguage/qqmllanguage.pro +++ b/tests/auto/qml/qqmllanguage/qqmllanguage.pro @@ -1,4 +1,7 @@ -CONFIG += testcase +CONFIG += testcase qmltypes +QML_IMPORT_NAME = StaticTest +QML_IMPORT_VERSION = 1.0 + TARGET = tst_qqmllanguage macx:CONFIG -= app_bundle diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index 39502372e6..8852bf7af9 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -750,6 +750,47 @@ private: bool m_ownRWObj; }; +namespace MyStaticNamespace { + Q_NAMESPACE + QML_ELEMENT + + enum MyNSEnum { + Key1 = 1, + Key2, + Key5 = 5 + }; + Q_ENUM_NS(MyNSEnum); + + enum class MyOtherNSEnum { + OtherKey1 = 1, + OtherKey2 + }; + Q_ENUM_NS(MyOtherNSEnum); + + + class MyNamespacedType : public QObject + { + Q_OBJECT + Q_PROPERTY(MyStaticNamespace::MyNSEnum myEnum MEMBER m_myEnum) + QML_NAMED_ELEMENT(MyStaticNamespacedType) + MyStaticNamespace::MyNSEnum m_myEnum = MyNSEnum::Key1; + }; + + class MySecondNamespacedType : public QObject + { + Q_OBJECT + Q_PROPERTY(QQmlListProperty<MyStaticNamespace::MyNamespacedType> list READ list) + QML_NAMED_ELEMENT(MyStaticSecondNamespacedType) + public: + QQmlListProperty<MyNamespacedType> list() + { + return QQmlListProperty<MyNamespacedType>(this, &m_list); + } + + private: + QList<MyNamespacedType *> m_list; + }; +} namespace MyNamespace { Q_NAMESPACE @@ -1440,17 +1481,22 @@ public: int base() const { return 43; } }; +class Local : public QObject +{ + Q_OBJECT +}; + class Foreign { Q_GADGET - QML_FOREIGN(QObject) + QML_FOREIGN(Local) QML_NAMED_ELEMENT(Foreign) }; class ForeignExtended { Q_GADGET - QML_FOREIGN(QObject) + QML_FOREIGN(Local) QML_NAMED_ELEMENT(ForeignExtended) QML_EXTENDED(Extension) }; diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 4d2f773dbf..c6076410b2 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -123,6 +123,7 @@ private slots: void dynamicProperties(); void dynamicPropertiesNested(); void listProperties(); + void listPropertiesInheritanceNoCrash(); void badListItemType(); void dynamicObjectProperties(); void dynamicSignalsAndSlots(); @@ -133,6 +134,8 @@ private slots: void autoComponentCreationInGroupProperty(); void propertyValueSource(); void requiredProperty(); + void requiredPropertyFromCpp_data(); + void requiredPropertyFromCpp(); void attachedProperties(); void dynamicObjects(); void customVariantTypes(); @@ -321,6 +324,10 @@ private slots: void listContainingDeletedObject(); void overrideSingleton(); + void revisionedPropertyOfAttachedObjectProperty(); + + void arrayToContainer(); + void qualifiedScopeInCustomParser(); private: QQmlEngine engine; @@ -1486,6 +1493,16 @@ void tst_qqmllanguage::listProperties() QCOMPARE(object->property("test").toInt(), 2); } +// Tests that initializing list properties of a base class does not crash +// (QTBUG-82171) +void tst_qqmllanguage::listPropertiesInheritanceNoCrash() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("listPropertiesChild.qml")); + QScopedPointer<QObject> object(component.create()); // should not crash + QVERIFY(object != nullptr); +} + void tst_qqmllanguage::badListItemType() { QQmlComponent component(&engine, testFileUrl("badListItemType.qml")); @@ -1674,8 +1691,103 @@ void tst_qqmllanguage::requiredProperty() QVERIFY(!component.errors().empty()); } { + QQmlComponent component(&engine, testFileUrl("requiredProperties.4.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!component.errors().empty()); + QVERIFY(component.errorString().contains("Required property objectName was not initialized")); + } + { QQmlComponent component(&engine, testFileUrl("requiredProperties.3.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!component.errors().empty()); + QVERIFY(component.errorString().contains("Required property i was not initialized")); + } + { + QQmlComponent component(&engine, testFileUrl("requiredProperties.5.qml")); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!component.errors().empty()); + QVERIFY(component.errorString().contains("Required property i was not initialized")); + } + { + QQmlComponent component(&engine, testFileUrl("requiredProperties.6.qml")); + VERIFY_ERRORS(0); + QScopedPointer<QObject> object(component.create()); + QVERIFY(object); + } + { + QQmlComponent component(&engine, testFileUrl("requiredProperties.7.qml")); + QScopedPointer<QObject> object(component.create()); QVERIFY(!component.errors().empty()); + QVERIFY(component.errorString().contains("Property blub was marked as required but does not exist")); + } +} + +class MyClassWithRequiredProperty : public QObject +{ +public: + Q_OBJECT + Q_PROPERTY(int test MEMBER m_test REQUIRED NOTIFY testChanged) + Q_SIGNAL void testChanged(); +private: + int m_test; +}; + +class ChildClassWithoutOwnRequired : public MyClassWithRequiredProperty +{ +public: + Q_OBJECT + Q_PROPERTY(int test2 MEMBER m_test2 NOTIFY test2Changed) + Q_SIGNAL void test2Changed(); +private: + int m_test2; +}; + +class ChildClassWithOwnRequired : public MyClassWithRequiredProperty +{ +public: + Q_OBJECT + Q_PROPERTY(int test2 MEMBER m_test2 REQUIRED NOTIFY test2Changed) + Q_SIGNAL void test2Changed(); +private: + int m_test2; +}; + +void tst_qqmllanguage::requiredPropertyFromCpp_data() +{ + qmlRegisterType<MyClassWithRequiredProperty>("example.org", 1, 0, "MyClass"); + qmlRegisterType<ChildClassWithoutOwnRequired>("example.org", 1, 0, "Child"); + qmlRegisterType<ChildClassWithOwnRequired>("example.org", 1, 0, "Child2"); + + + QTest::addColumn<QUrl>("setFile"); + QTest::addColumn<QUrl>("notSetFile"); + QTest::addColumn<QString>("errorMessage"); + QTest::addColumn<int>("expectedValue"); + + QTest::addRow("direct") << testFileUrl("cppRequiredProperty.qml") << testFileUrl("cppRequiredPropertyNotSet.qml") << QString(":4 Required property test was not initialized\n") << 42; + QTest::addRow("in parent") << testFileUrl("cppRequiredPropertyInParent.qml") << testFileUrl("cppRequiredPropertyInParentNotSet.qml") << QString(":4 Required property test was not initialized\n") << 42; + QTest::addRow("in child and parent") << testFileUrl("cppRequiredPropertyInChildAndParent.qml") << testFileUrl("cppRequiredPropertyInChildAndParentNotSet.qml") << QString(":4 Required property test2 was not initialized\n") << 18; +} + +void tst_qqmllanguage::requiredPropertyFromCpp() +{ + QQmlEngine engine; + QFETCH(QUrl, setFile); + QFETCH(QUrl, notSetFile); + QFETCH(QString, errorMessage); + QFETCH(int, expectedValue); + { + QQmlComponent comp(&engine, notSetFile); + QScopedPointer<QObject> o { comp.create() }; + QVERIFY(o.isNull()); + QVERIFY(comp.isError()); + QCOMPARE(comp.errorString(), notSetFile.toString() + errorMessage); + } + { + QQmlComponent comp(&engine, setFile); + QScopedPointer<QObject> o { comp.create() }; + QVERIFY(!o.isNull()); + QCOMPARE(o->property("test").toInt(), expectedValue); } } @@ -1747,21 +1859,30 @@ void tst_qqmllanguage::valueTypes() void tst_qqmllanguage::cppnamespace() { - { - QQmlComponent component(&engine, testFileUrl("cppnamespace.qml")); + QScopedPointer<QObject> object; + + auto create = [&](const char *file) { + QQmlComponent component(&engine, testFileUrl(file)); VERIFY_ERRORS(0); - QScopedPointer<QObject> object(component.create()); + object.reset(component.create()); QVERIFY(object != nullptr); + }; - QCOMPARE(object->property("intProperty").toInt(), (int)MyNamespace::MyOtherNSEnum::OtherKey2); - } + auto createAndCheck = [&](const char *file) { + create(file); + return !QTest::currentTestFailed(); + }; - { - QQmlComponent component(&engine, testFileUrl("cppnamespace.2.qml")); - VERIFY_ERRORS(0); - QScopedPointer<QObject> object(component.create()); - QVERIFY(object != nullptr); - } + QVERIFY(createAndCheck("cppnamespace.qml")); + QCOMPARE(object->property("intProperty").toInt(), + (int)MyNamespace::MyOtherNSEnum::OtherKey2); + + QVERIFY(createAndCheck("cppstaticnamespace.qml")); + QCOMPARE(object->property("intProperty").toInt(), + (int)MyStaticNamespace::MyOtherNSEnum::OtherKey2); + + QVERIFY(createAndCheck("cppnamespace.2.qml")); + QVERIFY(createAndCheck("cppstaticnamespace.2.qml")); } void tst_qqmllanguage::aliasProperties() @@ -5318,7 +5439,7 @@ void tst_qqmllanguage::selfReference() const QMetaObject *metaObject = o->metaObject(); QMetaProperty selfProperty = metaObject->property(metaObject->indexOfProperty("self")); - QCOMPARE(selfProperty.userType(), compilationUnit->metaTypeId); + QCOMPARE(selfProperty.userType(), compilationUnit->metaTypeId.id()); QByteArray typeName = selfProperty.typeName(); QVERIFY(typeName.endsWith('*')); @@ -5327,7 +5448,7 @@ void tst_qqmllanguage::selfReference() QMetaMethod selfFunction = metaObject->method(metaObject->indexOfMethod("returnSelf()")); QVERIFY(selfFunction.isValid()); - QCOMPARE(selfFunction.returnType(), compilationUnit->metaTypeId); + QCOMPARE(selfFunction.returnType(), compilationUnit->metaTypeId.id()); QMetaMethod selfSignal; @@ -5341,7 +5462,7 @@ void tst_qqmllanguage::selfReference() QVERIFY(selfSignal.isValid()); QCOMPARE(selfSignal.parameterCount(), 1); - QCOMPARE(selfSignal.parameterType(0), compilationUnit->metaTypeId); + QCOMPARE(selfSignal.parameterType(0), compilationUnit->metaTypeId.id()); } void tst_qqmllanguage::selfReferencingSingleton() @@ -5418,6 +5539,85 @@ void tst_qqmllanguage::overrideSingleton() check("uncreatable", "UncreatableSingleton"); } +class AttachedObject; +class InnerObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool revisionedProperty READ revisionedProperty WRITE setRevisionedProperty + NOTIFY revisionedPropertyChanged REVISION 2) + +public: + InnerObject(QObject *parent = nullptr) : QObject(parent) {} + + bool revisionedProperty() const { return m_revisionedProperty; } + void setRevisionedProperty(bool revisionedProperty) + { + if (revisionedProperty != m_revisionedProperty) { + m_revisionedProperty = revisionedProperty; + emit revisionedPropertyChanged(); + } + } + + static AttachedObject *qmlAttachedProperties(QObject *object); + +signals: + Q_REVISION(2) void revisionedPropertyChanged(); + +private: + bool m_revisionedProperty = false; +}; + +class AttachedObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(InnerObject *attached READ attached CONSTANT) + +public: + explicit AttachedObject(QObject *parent = nullptr) : + QObject(parent), + m_attached(new InnerObject(this)) + {} + + InnerObject *attached() const { return m_attached; } + +private: + InnerObject *m_attached; +}; + +class OuterObject : public QObject +{ + Q_OBJECT +public: + explicit OuterObject(QObject *parent = nullptr) : QObject(parent) {} +}; + +AttachedObject *InnerObject::qmlAttachedProperties(QObject *object) +{ + return new AttachedObject(object); +} + +QML_DECLARE_TYPE(InnerObject) +QML_DECLARE_TYPEINFO(InnerObject, QML_HAS_ATTACHED_PROPERTIES) + +void tst_qqmllanguage::revisionedPropertyOfAttachedObjectProperty() +{ + qmlRegisterAnonymousType<AttachedObject>("foo", 2); + qmlRegisterType<InnerObject>("foo", 2, 0, "InnerObject"); + qmlRegisterType<InnerObject, 2>("foo", 2, 2, "InnerObject"); + qmlRegisterType<OuterObject>("foo", 2, 2, "OuterObject"); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import foo 2.2\n" + "OuterObject {\n" + " InnerObject.attached.revisionedProperty: true\n" + "}", QUrl()); + + QVERIFY(component.isReady()); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); +} + void tst_qqmllanguage::inlineComponent() { QFETCH(QUrl, componentUrl); @@ -5450,6 +5650,9 @@ void tst_qqmllanguage::inlineComponent_data() QTest::newRow("Non-toplevel IC is found") << testFileUrl("inlineComponentUser5.qml") << QColorConstants::Svg::red << 24; QTest::newRow("Resolved in correct order") << testFileUrl("inlineComponentOrder.qml") << QColorConstants::Blue << 200; + + QTest::newRow("ID resolves correctly") << testFileUrl("inlineComponentWithId.qml") << QColorConstants::Svg::red << 42; + QTest::newRow("Alias resolves correctly") << testFileUrl("inlineComponentWithAlias.qml") << QColorConstants::Svg::lime << 42; } void tst_qqmllanguage::inlineComponentReferenceCycle_data() @@ -5540,6 +5743,60 @@ void tst_qqmllanguage::nonExistingInlineComponent() QCOMPARE(error.column(), column); } +class TestItem : public QObject +{ + Q_OBJECT + Q_PROPERTY( QVector<QPointF> positions MEMBER m_points ) + +public: + TestItem() = default; + QVector< QPointF > m_points; +}; + + +Q_DECLARE_METATYPE(QVector<QPointF>); +void tst_qqmllanguage::arrayToContainer() +{ + QQmlEngine engine; + qmlRegisterType<TestItem>("qt.test", 1, 0, "TestItem"); + QVector<QPointF> points { QPointF (2.0, 3.0) }; + engine.rootContext()->setContextProperty("test", QVariant::fromValue(points)); + QQmlComponent component(&engine, testFileUrl("arrayToContainer.qml")); + VERIFY_ERRORS(0); + QScopedPointer<TestItem> root(qobject_cast<TestItem *>(component.createWithInitialProperties( {{"vector", QVariant::fromValue(points)}} ))); + QVERIFY(root); + QCOMPARE(root->m_points.at(0), QPointF (2.0, 3.0) ); +} + +class EnumTester : public QObject +{ + Q_OBJECT +public: + enum Types + { + FIRST = 0, + SECOND, + THIRD + }; + Q_ENUM(Types) +}; + +void tst_qqmllanguage::qualifiedScopeInCustomParser() +{ + qmlRegisterUncreatableType<EnumTester>("scoped.custom.test", 1, 0, "EnumTester", + "Object only creatable in C++"); + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import QtQml.Models 2.12\n" + "import scoped.custom.test 1.0 as BACKEND\n" + "ListModel {\n" + " ListElement { text: \"a\"; type: BACKEND.EnumTester.FIRST }\n" + "}\n", QUrl()); + QVERIFY(component.isReady()); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" |