aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-01-25 13:56:24 +0100
committerUlf Hermann <ulf.hermann@qt.io>2021-01-25 16:53:32 +0100
commit79ac5a2053c09246860d61a9d5124d89d0b30abd (patch)
treeea67dc128b323c6147b866877a10b296968f58fa /src
parentbe26ca6bcaaf0ddd7337cb8ff856a2e97866278a (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.h24
-rw-r--r--src/qmltyperegistrar/qmltyperegistrar.cpp54
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());