From 11ff5c314682258b6eb26e90847210662eb0f533 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 12 Feb 2020 17:49:31 +0100 Subject: Provide a way to statically register namespaces Previously, qmltyperegistrar would stumble over any QML_* macros in namespaces, as the namespaces could not be used as template arguments. However, namespaces are intended to be usable by QML as uncreatable "types". Now, qmltyperegistrar checks the namespace flag that moc records in the JSON output, and if that is given, registers an uncreatable metaobject instead of a type. Therefore you can use QML_ELEMENT and friends to register namespaces, just like you would register classes (except that they're implicitly uncreatable, of course). Task-number: QTBUG-68796 Change-Id: I186d7e9425471c32fb1a1f29c0c0b946afb2a9d2 Reviewed-by: Fabian Kosmale --- src/qml/qml/qqml.h | 32 ++++++++++++++++++++++++++ src/qmltyperegistrar/qmltyperegistrar.cpp | 38 ++++++++++++++++++++++++------- 2 files changed, 62 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index ef7fdd1945..a3e3f1c584 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -848,6 +848,38 @@ void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor) template<> inline void qmlRegisterTypesAndRevisions<>(const char *, int) {} +inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject, + const char *uri, int versionMajor) +{ + QQmlPrivate::RegisterTypeAndRevisions type = { + 0, + 0, + 0, + 0, + nullptr, + + uri, + versionMajor, + + metaObject, + metaObject, + + nullptr, + nullptr, + + -1, + -1, + -1, + + nullptr, + nullptr, + + &qmlCreateCustomParser + }; + + qmlregister(QQmlPrivate::TypeAndRevisionsRegistration, &type); +} + int Q_QML_EXPORT qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName); QT_END_NAMESPACE diff --git a/src/qmltyperegistrar/qmltyperegistrar.cpp b/src/qmltyperegistrar/qmltyperegistrar.cpp index 49c9fccb66..6fe5a20092 100644 --- a/src/qmltyperegistrar/qmltyperegistrar.cpp +++ b/src/qmltyperegistrar/qmltyperegistrar.cpp @@ -47,14 +47,23 @@ struct ScopedPointerFileCloser static inline void cleanup(FILE *handle) { if (handle) fclose(handle); } }; -static bool acceptClassForQmlTypeRegistration(const QJsonObject &classDef) +enum RegistrationMode { + NoRegistration, + ClassRegistration, + NamespaceRegistration +}; + +static RegistrationMode qmlTypeRegistrationMode(const QJsonObject &classDef) { const QJsonArray classInfos = classDef[QLatin1String("classInfos")].toArray(); for (const QJsonValue &info: classInfos) { - if (info[QLatin1String("name")].toString() == QLatin1String("QML.Element")) - return true; + const QString name = info[QLatin1String("name")].toString(); + if (name == QLatin1String("QML.Element")) { + return classDef[QLatin1String("namespace")].toBool() ? NamespaceRegistration + : ClassRegistration; + } } - return false; + return NoRegistration; } static QVector foreignRelatedTypes(const QVector &types, @@ -284,7 +293,11 @@ int main(int argc, char **argv) const QJsonArray classes = metaObject[QLatin1String("classes")].toArray(); for (const auto &cls : classes) { QJsonObject classDef = cls.toObject(); - if (acceptClassForQmlTypeRegistration(classDef)) { + switch (qmlTypeRegistrationMode(classDef)) { + case NamespaceRegistration: + classDef.insert(QLatin1String("namespace"), true); + Q_FALLTHROUGH(); + case ClassRegistration: { const QString include = metaObject[QLatin1String("inputFile")].toString(); const bool declaredInHeader = include.endsWith(QLatin1String(".h")); if (declaredInHeader) { @@ -297,8 +310,11 @@ int main(int argc, char **argv) .toString())); } types.append(classDef); - } else { + break; + } + case NoRegistration: foreignTypes.append(classDef); + break; } } }; @@ -360,8 +376,14 @@ int main(int argc, char **argv) continue; const QString className = classDef[QLatin1String("qualifiedClassName")].toString(); - fprintf(output, "\n qmlRegisterTypesAndRevisions<%s>(\"%s\", %s);", qPrintable(className), - qPrintable(module), qPrintable(majorVersion)); + + if (classDef.value(QLatin1String("namespace")).toBool()) { + fprintf(output, "\n qmlRegisterNamespaceAndRevisions(&%s::staticMetaObject, \"%s\", %s);", + qPrintable(className), qPrintable(module), qPrintable(majorVersion)); + } else { + fprintf(output, "\n qmlRegisterTypesAndRevisions<%s>(\"%s\", %s);", + qPrintable(className), qPrintable(module), qPrintable(majorVersion)); + } } fprintf(output, "\n qmlRegisterModule(\"%s\", %s, %s);", -- cgit v1.2.3