diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-01-25 13:56:24 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-01-25 16:53:32 +0100 |
commit | 79ac5a2053c09246860d61a9d5124d89d0b30abd (patch) | |
tree | ea67dc128b323c6147b866877a10b296968f58fa /src | |
parent | be26ca6bcaaf0ddd7337cb8ff856a2e97866278a (diff) |
qmltyperegistrar: Make sure we have metatypes for all QML types
We need to be able to resolve any QML type from its C++ name using
QMetaType::fromName(). qmltyperegistrar can generate the missing
metatypes, either by creating synthetic ones (for namespaces), or by
making sure the existing ones are registered (for others).
Change-Id: If775af56d891f2c2a5bb94589b3cb05a199c7c35
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 24 | ||||
-rw-r--r-- | src/qmltyperegistrar/qmltyperegistrar.cpp | 54 |
2 files changed, 65 insertions, 13 deletions
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 1b994b88e1..608a0f0188 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -904,6 +904,30 @@ namespace QQmlPrivate const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject, QVector<int> *qmlTypeIds, const QMetaObject *); + constexpr QtPrivate::QMetaTypeInterface metaTypeForNamespace( + const QtPrivate::QMetaTypeInterface::MetaObjectFn &metaObjectFunction, const char *name) + { + return { + /*.revision=*/ 0, + /*.alignment=*/ 0, + /*.size=*/ 0, + /*.flags=*/ 0, + /*.typeId=*/ {}, + /*.metaObject=*/ metaObjectFunction, + /*.name=*/ name, + /*.defaultCtr=*/ nullptr, + /*.copyCtr=*/ nullptr, + /*.moveCtr=*/ nullptr, + /*.dtor=*/ nullptr, + /*.equals*/ nullptr, + /*.lessThan*/ nullptr, + /*.debugStream=*/ nullptr, + /*.dataStreamOut=*/ nullptr, + /*.dataStreamIn=*/ nullptr, + /*.legacyRegisterOp=*/ nullptr + }; + } + } // namespace QQmlPrivate QT_END_NAMESPACE diff --git a/src/qmltyperegistrar/qmltyperegistrar.cpp b/src/qmltyperegistrar/qmltyperegistrar.cpp index a3fe58dbcf..75e849c5e5 100644 --- a/src/qmltyperegistrar/qmltyperegistrar.cpp +++ b/src/qmltyperegistrar/qmltyperegistrar.cpp @@ -181,6 +181,11 @@ int main(int argc, char **argv) processor.postProcessTypes(); + if (parser.isSet(foreignTypesOption)) + processor.processForeignTypes(parser.value(foreignTypesOption).split(QLatin1Char(','))); + + processor.postProcessForeignTypes(); + const QStringList includes = processor.includes(); for (const QString &include : includes) fprintf(output, "\n#include <%s>", qPrintable(include)); @@ -211,17 +216,45 @@ int main(int argc, char **argv) for (const QJsonObject &classDef : types) { const QString className = classDef[QLatin1String("qualifiedClassName")].toString(); + QString targetName = className; + bool seenQmlElement = false; + const QJsonArray classInfos = classDef.value(QLatin1String("classInfos")).toArray(); + for (const QJsonValue &v : classInfos) { + const QString name = v[QStringLiteral("name")].toString(); + if (name == QStringLiteral("QML.Element")) + seenQmlElement = true; + else if (name == QStringLiteral("QML.Foreign")) + targetName = v[QLatin1String("value")].toString(); + } + + // We want all related metatypes to be registered by name, so that we can look them up + // without including the C++ headers. That's the reason for the QMetaType(foo).id() calls. + if (classDef.value(QLatin1String("namespace")).toBool()) { - QString targetName = className; - for (const QJsonValue &v : classDef.value(QLatin1String("classInfos")).toArray()) { - if (v[QLatin1String("name")].toString() == QLatin1String("QML.Foreign")) - targetName = v[QLatin1String("value")].toString(); + fprintf(output, "\n {"); + fprintf(output, "\n static const auto metaType " + "= QQmlPrivate::metaTypeForNamespace(" + "[](const QtPrivate::QMetaTypeInterface *) { " + "return &%s::staticMetaObject; " + "}, \"%s\");", + qPrintable(targetName), qPrintable(targetName)); + fprintf(output, "\n QMetaType(&metaType).id();"); + fprintf(output, "\n }"); + 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::staticMetaObject, \"%s\", %s, nullptr, &%s::staticMetaObject);", - qPrintable(targetName), qPrintable(module), qPrintable(majorVersion), qPrintable(className)); } else { - fprintf(output, "\n qmlRegisterTypesAndRevisions<%s>(\"%s\", %s);", - qPrintable(className), qPrintable(module), qPrintable(majorVersion)); + if (seenQmlElement) { + fprintf(output, "\n qmlRegisterTypesAndRevisions<%s>(\"%s\", %s);", + qPrintable(className), qPrintable(module), qPrintable(majorVersion)); + } else { + fprintf(output, "\n QMetaType::fromType<%s%s>().id();", + qPrintable(className), + classDef.value(QLatin1String("object")).toBool() ? " *" : ""); + } } } @@ -234,11 +267,6 @@ int main(int argc, char **argv) if (!parser.isSet(pluginTypesOption)) return EXIT_SUCCESS; - if (parser.isSet(foreignTypesOption)) - processor.processForeignTypes(parser.value(foreignTypesOption).split(QLatin1Char(','))); - - processor.postProcessForeignTypes(); - QmlTypesCreator creator; creator.setOwnTypes(processor.types()); creator.setForeignTypes(processor.foreignTypes()); |