diff options
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 24 | ||||
-rw-r--r-- | src/qmltyperegistrar/qmltyperegistrar.cpp | 54 | ||||
-rw-r--r-- | tests/auto/qml/qmltyperegistrar/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/qml/qmltyperegistrar/foo.cpp | 35 | ||||
-rw-r--r-- | tests/auto/qml/qmltyperegistrar/foo.h | 73 | ||||
-rw-r--r-- | tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp | 29 | ||||
-rw-r--r-- | tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h | 12 |
7 files changed, 215 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()); diff --git a/tests/auto/qml/qmltyperegistrar/CMakeLists.txt b/tests/auto/qml/qmltyperegistrar/CMakeLists.txt index c12ef77ebb..0839f56c4f 100644 --- a/tests/auto/qml/qmltyperegistrar/CMakeLists.txt +++ b/tests/auto/qml/qmltyperegistrar/CMakeLists.txt @@ -10,6 +10,7 @@ qt_internal_add_test(tst_qmltyperegistrar hppheader.hpp # noextheader special case tst_qmltyperegistrar.cpp tst_qmltyperegistrar.h + foo.cpp foo.h INCLUDE_DIRECTORIES foreign PUBLIC_LIBRARIES diff --git a/tests/auto/qml/qmltyperegistrar/foo.cpp b/tests/auto/qml/qmltyperegistrar/foo.cpp new file mode 100644 index 0000000000..25aed2d8f0 --- /dev/null +++ b/tests/auto/qml/qmltyperegistrar/foo.cpp @@ -0,0 +1,35 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "foo.h" +#include <QDebug> + +void Ooo::blah() +{ + qDebug() << "blah"; +} diff --git a/tests/auto/qml/qmltyperegistrar/foo.h b/tests/auto/qml/qmltyperegistrar/foo.h new file mode 100644 index 0000000000..2da5b92fc5 --- /dev/null +++ b/tests/auto/qml/qmltyperegistrar/foo.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FOO_H +#define FOO_H + +#include <QtCore/qobject.h> +#include <qqml.h> + +class Bbb : public QObject +{ + Q_OBJECT +public: + Bbb(QObject *parent = nullptr) : QObject(parent) {} +}; + +class Ccc : public QObject +{ + Q_OBJECT +public: + Ccc(QObject *parent) : QObject(parent) {} +}; + +class Ooo : public QObject +{ + Q_OBJECT + QML_ELEMENT + QML_EXTENDED(Bbb) + QML_ATTACHED(Ccc); +public: + Q_INVOKABLE void blah(); + + static Ccc *qmlAttachedProperties(QObject *o) { return new Ccc(o); } +}; + +namespace Foo { +Q_NAMESPACE +QML_ELEMENT + +enum Bar { + A, B, C +}; + +Q_ENUM_NS(Bar); +} + + +#endif // FOO_H diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp index 7b82be20f7..b5efefba9a 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp @@ -126,4 +126,33 @@ void tst_qmltyperegistrar::namespacedElement() QVERIFY2(!c.isError(), qPrintable(c.errorString())); } +void tst_qmltyperegistrar::derivedFromForeign() +{ + QVERIFY(qmltypesData.contains("name: \"DerivedFromForeign\"")); + QVERIFY(qmltypesData.contains("prototype: \"QTimeLine\"")); + QVERIFY(qmltypesData.contains("name: \"QTimeLine\"")); +} + +void tst_qmltyperegistrar::metaTypesRegistered() +{ + QQmlEngine engine; + QQmlComponent c(&engine); + c.setData("import QmlTypeRegistrarTest\nOoo {}", QUrl()); + QVERIFY(c.isReady()); + QScopedPointer<QObject> obj(c.create()); + + auto verifyMetaType = [](const char *name, const char *className) { + const auto foundMetaType = QMetaType::fromName(name); + QVERIFY(foundMetaType.isValid()); + QCOMPARE(foundMetaType.name(), name); + QVERIFY(foundMetaType.metaObject()); + QCOMPARE(foundMetaType.metaObject()->className(), className); + }; + + verifyMetaType("Foo", "Foo"); + verifyMetaType("Ooo*", "Ooo"); + verifyMetaType("Bbb*", "Bbb"); + verifyMetaType("Ccc*", "Ccc"); +} + QTEST_MAIN(tst_qmltyperegistrar) diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h index 509816f62c..486009ea59 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h @@ -33,6 +33,7 @@ #include <QtQml/qqml.h> #include <QtCore/qproperty.h> +#include <QtCore/qtimeline.h> class Interface {}; class Interface2 {}; @@ -141,6 +142,14 @@ namespace Namespace { }; } +class DerivedFromForeign : public QTimeLine +{ + Q_OBJECT + QML_ELEMENT +public: + DerivedFromForeign(QObject *parent) : QTimeLine(1000, parent) {} +}; + class tst_qmltyperegistrar : public QObject { Q_OBJECT @@ -158,6 +167,9 @@ private slots: void pastMajorVersions(); void implementsInterfaces(); void namespacedElement(); + void derivedFromForeign(); + void metaTypesRegistered(); + private: QByteArray qmltypesData; }; |