From 1b93a1d86549347566e1a7645c0501e5c9f6aa0a Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 2 Feb 2021 14:11:24 +0100 Subject: qmltyperegistrar: Fix handling of default properties Default properties are always local. There is no way to declare a default property for a foreign type as the default property is queried directly from the classinfo at runtime. Change-Id: I30efb6fba190957ac2a4ad86da437f209cd1f3ad Reviewed-by: Fabian Kosmale --- .../qml/qmltyperegistrar/tst_qmltyperegistrar.cpp | 34 +++++++++++++++ .../qml/qmltyperegistrar/tst_qmltyperegistrar.h | 51 ++++++++++++++++++++++ 2 files changed, 85 insertions(+) (limited to 'tests/auto/qml/qmltyperegistrar') diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp index cd3596e142..34d8007ede 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp @@ -171,4 +171,38 @@ void tst_qmltyperegistrar::multiExtensions() QVERIFY(qmltypesData.contains("interfaces: [\"Interface3\"]")); } +void tst_qmltyperegistrar::localDefault() +{ + QQmlEngine engine; + { + QQmlComponent c(&engine); + c.setData("import QmlTypeRegistrarTest\n" + "import QtQml\n" + "ForeignWithoutDefault { QtObject {} }", QUrl()); + QVERIFY(c.isError()); + QVERIFY(c.errorString().contains( + QStringLiteral("Cannot assign to non-existent default property"))); + } + { + QQmlComponent c(&engine); + c.setData("import QmlTypeRegistrarTest\n" + "import QtQml\n" + "Local { QtObject {} }", QUrl()); + QVERIFY(c.isReady()); + } + + QCOMPARE(qmltypesData.count("name: \"LocalWithDefault\""), 1); + QCOMPARE(qmltypesData.count("name: \"ForeignWithoutDefault\""), 1); + QCOMPARE(qmltypesData.count("defaultProperty: \"d\""), 1); + + const int local = qmltypesData.indexOf("name: \"LocalWithDefault\""); + const int foreign = qmltypesData.indexOf("name: \"ForeignWithoutDefault\""); + const int defaultProp = qmltypesData.indexOf("defaultProperty: \"d\""); + + // We assume that name is emitted before defaultProperty. + // Then this proves that the default property does not belong to ForeignWithoutDefault. + QVERIFY(local < defaultProp); + QVERIFY(foreign > defaultProp || foreign < local); +} + QTEST_MAIN(tst_qmltyperegistrar) diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h index 40569879ec..eb3b680e82 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h @@ -116,11 +116,61 @@ public: void setWidth(int width) { v.setWidth(width); } }; +class ForeignWithoutDefault : public QObject +{ + Q_OBJECT + Q_PROPERTY(QObject *d READ d WRITE setD NOTIFY dChanged) +public: + QObject *d() const { return m_d; } + + void setD(QObject *d) + { + if (m_d != d) { + m_d = d; + emit dChanged(); + } + } + +signals: + void dChanged(); + +private: + QObject *m_d = nullptr; +}; + +class LocalWithDefault : public QObject +{ + Q_OBJECT + Q_PROPERTY(QObject *d READ d WRITE setD NOTIFY dChanged) + QML_NAMED_ELEMENT(ForeignWithoutDefault) + QML_FOREIGN(ForeignWithoutDefault) + Q_CLASSINFO("DefaultProperty", "d") + +public: + LocalWithDefault(QObject *parent = nullptr) : QObject(parent) {} + QObject *d() const { return m_d; } + + void setD(QObject *d) + { + if (m_d != d) { + m_d = d; + emit dChanged(); + } + } + +signals: + void dChanged(); + +private: + QObject *m_d = nullptr; +}; + class Local : public Foreign { Q_OBJECT QML_ELEMENT Q_PROPERTY(int someProperty MEMBER someProperty BINDABLE bindableSomeProperty) + QML_EXTENDED(LocalWithDefault) public: enum Flag { Flag1 = 0x1, @@ -216,6 +266,7 @@ private slots: void derivedFromForeign(); void metaTypesRegistered(); void multiExtensions(); + void localDefault(); private: QByteArray qmltypesData; -- cgit v1.2.3