diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-06-18 12:23:30 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-06-21 14:31:02 +0200 |
commit | 71085008cecc25b9f635ed3c811f296a15ec0c0d (patch) | |
tree | e739d5d1732079bc5ff6cd19245d15a68b1a2fce | |
parent | 21c13ab37426f96ab7717cc7b2764b702b382343 (diff) |
Allow extending namespaces with other namespaces
Previously you could only extend types.
Change-Id: I5d0bcea58403a87b9ff878c255ff590f162f8b24
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/qml/doc/src/cppintegration/definetypes.qdoc | 6 | ||||
-rw-r--r-- | src/qml/qml/qqml.h | 16 | ||||
-rw-r--r-- | src/qml/qml/qqmlregistration.h | 3 | ||||
-rw-r--r-- | src/qmltyperegistrar/qmltyperegistrar.cpp | 17 | ||||
-rw-r--r-- | tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp | 18 | ||||
-rw-r--r-- | tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h | 29 |
6 files changed, 80 insertions, 9 deletions
diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc index 969bf4f7c0..f4b0f51180 100644 --- a/src/qml/doc/src/cppintegration/definetypes.qdoc +++ b/src/qml/doc/src/cppintegration/definetypes.qdoc @@ -345,11 +345,13 @@ merged with the original target class when used from within QML. For example: The \c leftMargin property is a new property added to an existing C++ type, \l QLineEdit, without modifying its source code. -The QML_EXTENDED(extended) macro is for registering extended types. The +The QML_EXTENDED(extension) macro is for registering extended types. The argument is the name of another class to be used as extension. You can also use QML_EXTENDED_NAMESPACE(namespace) to register a namespace, and -especially the enumerations declared within, as an extension to a type. +especially the enumerations declared within, as an extension to a type. If the +type you are extending is itself a namespace, you need to use +QML_NAMESPACE_EXTENDED(namespace) instead. An extension class is a regular QObject, with a constructor that takes a QObject pointer. However, the extension class creation is delayed until the first diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index d82567d26e..b635c2289e 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -790,8 +790,9 @@ inline void qmlRegisterTypesAndRevisions<>(const char *, int, QList<int> *) inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject, const char *uri, int versionMajor, - QList<int> *qmlTypeIds = nullptr, - const QMetaObject *classInfoMetaObject = nullptr) + QList<int> *qmlTypeIds, + const QMetaObject *classInfoMetaObject, + const QMetaObject *extensionMetaObject) { QQmlPrivate::RegisterTypeAndRevisions type = { 0, @@ -816,7 +817,7 @@ inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject, -1, nullptr, - nullptr, + extensionMetaObject, &qmlCreateCustomParser<void>, qmlTypeIds @@ -825,6 +826,15 @@ inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject, qmlregister(QQmlPrivate::TypeAndRevisionsRegistration, &type); } +inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject, + const char *uri, int versionMajor, + QList<int> *qmlTypeIds = nullptr, + const QMetaObject *classInfoMetaObject = nullptr) +{ + qmlRegisterNamespaceAndRevisions(metaObject, uri, versionMajor, qmlTypeIds, + classInfoMetaObject, nullptr); +} + int Q_QML_EXPORT qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName); QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlregistration.h b/src/qml/qml/qqmlregistration.h index d2e4b17248..c07cab660a 100644 --- a/src/qml/qml/qqmlregistration.h +++ b/src/qml/qml/qqmlregistration.h @@ -118,6 +118,9 @@ QT_BEGIN_NAMESPACE template<typename T, typename... Args> \ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *); +#define QML_NAMESPACE_EXTENDED(EXTENDED_NAMESPACE) \ + Q_CLASSINFO("QML.Extended", #EXTENDED_NAMESPACE) + #define QML_FOREIGN(FOREIGN_TYPE) \ Q_CLASSINFO("QML.Foreign", #FOREIGN_TYPE) \ using QmlForeignType = FOREIGN_TYPE; \ diff --git a/src/qmltyperegistrar/qmltyperegistrar.cpp b/src/qmltyperegistrar/qmltyperegistrar.cpp index 914781e737..a74f676a0b 100644 --- a/src/qmltyperegistrar/qmltyperegistrar.cpp +++ b/src/qmltyperegistrar/qmltyperegistrar.cpp @@ -220,6 +220,7 @@ int main(int argc, char **argv) const QString className = classDef[QLatin1String("qualifiedClassName")].toString(); QString targetName = className; + QString extendedName; bool seenQmlElement = false; const QJsonArray classInfos = classDef.value(QLatin1String("classInfos")).toArray(); for (const QJsonValue v : classInfos) { @@ -228,6 +229,8 @@ int main(int argc, char **argv) seenQmlElement = true; else if (name == QStringLiteral("QML.Foreign")) targetName = v[QLatin1String("value")].toString(); + else if (name == QStringLiteral("QML.Extended")) + extendedName = v[QStringLiteral("value")].toString(); } // We want all related metatypes to be registered by name, so that we can look them up @@ -273,11 +276,17 @@ int main(int argc, char **argv) qPrintable(targetTypeName)); } + auto metaObjectPointer = [](const QString &name) -> QString { + return u'&' + name + QStringLiteral("::staticMetaObject"); + }; + if (seenQmlElement) { - fprintf(output, "\n qmlRegisterNamespaceAndRevisions(&%s::staticMetaObject, " - "\"%s\", %s, nullptr, &%s::staticMetaObject);", - qPrintable(targetName), qPrintable(module), qPrintable(majorVersion), - qPrintable(className)); + fprintf(output, "\n qmlRegisterNamespaceAndRevisions(%s, " + "\"%s\", %s, nullptr, %s, %s);", + qPrintable(metaObjectPointer(targetName)), qPrintable(module), + qPrintable(majorVersion), qPrintable(metaObjectPointer(className)), + extendedName.isEmpty() ? "nullptr" + : qPrintable(metaObjectPointer(extendedName))); } } else { if (seenQmlElement) { diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp index f11f5d6404..1271090c56 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp @@ -288,4 +288,22 @@ void tst_qmltyperegistrar::namespacesAndValueTypes() check(QMetaType::fromName("ValueTypeWithEnum2"), QMetaType::fromType<ValueTypeWithEnum2>()); } +void tst_qmltyperegistrar::namespaceExtendedNamespace() +{ + QQmlEngine engine; + QQmlComponent c(&engine); + c.setData("import QtQml\n" + "import QmlTypeRegistrarTest\n" + "QtObject {\n" + " property int b: ForeignNamespace.B\n" + " property int f: ForeignNamespace.F\n" + "}", QUrl()); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer o(c.create()); + QVERIFY(!o.isNull()); + + QCOMPARE(o->property("b").toInt(), int(ExtensionValueType::B)); + QCOMPARE(o->property("f").toInt(), int(BaseNamespace::F)); +} + QTEST_MAIN(tst_qmltyperegistrar) diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h index 2a8423c682..d0f3f4d27b 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h @@ -382,6 +382,34 @@ struct BValueTypeWithEnumForeign2 QML_NAMED_ELEMENT(valueTypeWithEnum2) }; + +namespace BaseNamespace +{ +Q_NAMESPACE +enum BBB { + D, E, F +}; +Q_ENUM_NS(BBB) +} + +struct ExtensionValueType +{ + Q_GADGET +public: + enum EEE { + A, B, C + }; + Q_ENUM(EEE) +}; + +namespace ForeignNamespace +{ +Q_NAMESPACE +QML_FOREIGN_NAMESPACE(BaseNamespace) +QML_NAMESPACE_EXTENDED(ExtensionValueType) +QML_ELEMENT +} + class tst_qmltyperegistrar : public QObject { Q_OBJECT @@ -411,6 +439,7 @@ private slots: void finalProperty(); void parentProperty(); void namespacesAndValueTypes(); + void namespaceExtendedNamespace(); private: QByteArray qmltypesData; |