aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-10-01 14:43:37 +0200
committerUlf Hermann <ulf.hermann@qt.io>2019-10-14 10:42:29 +0200
commitee62b2824fe91e95a3f8218b93ba55a2ef6660d0 (patch)
treeff403362ee4b73c9d90c640d29bf22a0aba94c23 /src/qml
parent8cb08ca42157bb43b523103a6d1be94534be0597 (diff)
Add support for semi-automatic QML type registrations
We can use the new moc JSON output to collect all meta-objects at build time and, for those that include QML element registration meta-data, generate code that automatically registers these types with QML. This eliminates the need to call qmlRegisterType manually. For now this generates free-standing functions (per module) that need to be called manually. This is intended as an intermediate step. Task-number: QTBUG-68796 Change-Id: Ib414eef9757344feee488ebc7388f957b975347f Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/qml/qml.pri2
-rw-r--r--src/qml/qml/qqmlengine.cpp2
-rw-r--r--src/qml/qml/qqmlextensioninterface.h11
-rw-r--r--src/qml/qml/qqmlextensionplugin.cpp56
-rw-r--r--src/qml/qml/qqmlextensionplugin.h13
-rw-r--r--src/qml/qml/qqmlimport.cpp51
-rw-r--r--src/qml/qml/qqmlimport_p.h1
-rw-r--r--src/qml/qml/qqmlmetatype.cpp74
-rw-r--r--src/qml/qml/qqmlmetatype_p.h4
-rw-r--r--src/qml/qml/qqmlmetatypedata.cpp7
-rw-r--r--src/qml/qml/qqmlmetatypedata_p.h4
-rw-r--r--src/qml/qml/qqmlmoduleregistration.cpp54
-rw-r--r--src/qml/qml/qqmlmoduleregistration.h58
-rw-r--r--src/qml/qml/qqmltypeloader.cpp24
-rw-r--r--src/qml/qml/qqmltypeloader_p.h2
-rw-r--r--src/qml/qml/qqmltypeloaderthread.cpp17
-rw-r--r--src/qml/qml/qqmltypeloaderthread_p.h5
17 files changed, 309 insertions, 76 deletions
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index 2e9c6f3de6..a16f3d4167 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -3,6 +3,7 @@ SOURCES += \
$$PWD/qqmldatablob.cpp \
$$PWD/qqmldirdata.cpp \
$$PWD/qqmlerror.cpp \
+ $$PWD/qqmlmoduleregistration.cpp \
$$PWD/qqmlopenmetaobject.cpp \
$$PWD/qqmlscriptblob.cpp \
$$PWD/qqmlscriptdata.cpp \
@@ -71,6 +72,7 @@ HEADERS += \
$$PWD/qqmldatablob_p.h \
$$PWD/qqmldirdata_p.h \
$$PWD/qqmlglobal_p.h \
+ $$PWD/qqmlmoduleregistration.h \
$$PWD/qqmlopenmetaobject_p.h \
$$PWD/qqmlscriptblob_p.h \
$$PWD/qqmlscriptdata_p.h \
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index af44d737a2..7edb8b3110 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -2262,7 +2262,7 @@ void QQmlEngine::setPluginPathList(const QStringList &paths)
On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
- The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
+ The plugin has to be a Qt plugin which implements the QQmlEngineExtensionPlugin interface.
*/
bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
{
diff --git a/src/qml/qml/qqmlextensioninterface.h b/src/qml/qml/qqmlextensioninterface.h
index d2eb79c5c9..1490bc512e 100644
--- a/src/qml/qml/qqmlextensioninterface.h
+++ b/src/qml/qml/qqmlextensioninterface.h
@@ -62,8 +62,14 @@ public:
virtual void initializeEngine(QQmlEngine *engine, const char *uri) = 0;
};
-#define QQmlTypesExtensionInterface_iid "org.qt-project.Qt.QQmlTypesExtensionInterface"
+class Q_QML_EXPORT QQmlEngineExtensionInterface
+{
+public:
+ virtual ~QQmlEngineExtensionInterface() = default;
+ virtual void initializeEngine(QQmlEngine *engine, const char *uri) = 0;
+};
+#define QQmlTypesExtensionInterface_iid "org.qt-project.Qt.QQmlTypesExtensionInterface"
Q_DECLARE_INTERFACE(QQmlTypesExtensionInterface, "org.qt-project.Qt.QQmlTypesExtensionInterface/1.0")
// NOTE: When changing this to a new version and deciding to add backup code to
@@ -73,6 +79,9 @@ Q_DECLARE_INTERFACE(QQmlTypesExtensionInterface, "org.qt-project.Qt.QQmlTypesExt
Q_DECLARE_INTERFACE(QQmlExtensionInterface, QQmlExtensionInterface_iid)
+#define QQmlEngineExtensionInterface_iid "org.qt-project.Qt.QQmlEngineExtensionInterface"
+Q_DECLARE_INTERFACE(QQmlEngineExtensionInterface, QQmlEngineExtensionInterface_iid)
+
QT_END_NAMESPACE
#endif // QQMLEXTENSIONINTERFACE_H
diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp
index c1c971f0a9..26364661a8 100644
--- a/src/qml/qml/qqmlextensionplugin.cpp
+++ b/src/qml/qml/qqmlextensionplugin.cpp
@@ -43,10 +43,11 @@
QT_BEGIN_NAMESPACE
/*!
- \since 5.0
+ \since 5.14
\inmodule QtQml
- \class QQmlExtensionPlugin
- \brief The QQmlExtensionPlugin class provides an abstract base for custom QML extension plugins.
+ \class QQmlEngineExtensionPlugin
+ \brief The QQmlEngineExtensionPlugin class provides an abstract base for custom QML extension
+ plugins.
\ingroup plugins
@@ -60,6 +61,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn void QQmlExtensionPlugin::registerTypes(const char *uri)
+ \internal
Registers the QML types in the given \a uri. Subclasses should implement
this to call qmlRegisterType() for all types which are provided by the extension
@@ -70,26 +72,39 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \internal
+*/
+QQmlExtensionPlugin::QQmlExtensionPlugin(QObject *parent)
+ : QObject(*(new QQmlExtensionPluginPrivate), parent)
+{
+}
+
+/*!
Constructs a QML extension plugin with the given \a parent.
Note that this constructor is invoked automatically by the
Q_PLUGIN_METADATA() macro, so there is no need for calling it
explicitly.
-*/
-QQmlExtensionPlugin::QQmlExtensionPlugin(QObject *parent)
- : QObject(*(new QQmlExtensionPluginPrivate), parent)
+ */
+QQmlEngineExtensionPlugin::QQmlEngineExtensionPlugin(QObject *parent)
+ : QObject(parent)
{
}
+
/*!
\internal
*/
-QQmlExtensionPlugin::~QQmlExtensionPlugin()
-{
-}
+QQmlExtensionPlugin::~QQmlExtensionPlugin() = default;
+
+/*!
+ \internal
+ */
+QQmlEngineExtensionPlugin::~QQmlEngineExtensionPlugin() = default;
/*!
\since 5.1
+ \internal
\brief Returns the URL of the directory from which the extension is loaded.
This is useful when the plugin also needs to load QML files or other
@@ -102,14 +117,23 @@ QUrl QQmlExtensionPlugin::baseUrl() const
}
/*!
- \fn void QQmlExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
+ \internal
+*/
+
+void QQmlExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
+{
+ Q_UNUSED(engine);
+ Q_UNUSED(uri);
+}
+
+/*!
+ \fn void QQmlEngineExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
Initializes the extension from the \a uri using the \a engine. Here an application
plugin might, for example, expose some data or objects to QML,
as context properties on the engine's root context.
-*/
-
-void QQmlExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
+ */
+void QQmlEngineExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
{
Q_UNUSED(engine);
Q_UNUSED(uri);
@@ -127,6 +151,12 @@ void QQmlExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
\inmodule QtQml
*/
+/*!
+ \class QQmlEngineExtensionInterface
+ \internal
+ \inmodule QtQml
+*/
+
QT_END_NAMESPACE
#include "moc_qqmlextensionplugin.cpp"
diff --git a/src/qml/qml/qqmlextensionplugin.h b/src/qml/qml/qqmlextensionplugin.h
index 55e9b89dae..ef7ff422cd 100644
--- a/src/qml/qml/qqmlextensionplugin.h
+++ b/src/qml/qml/qqmlextensionplugin.h
@@ -70,6 +70,19 @@ private:
Q_DISABLE_COPY(QQmlExtensionPlugin)
};
+class Q_QML_EXPORT QQmlEngineExtensionPlugin
+ : public QObject
+ , public QQmlEngineExtensionInterface
+{
+ Q_OBJECT
+ Q_DISABLE_COPY_MOVE(QQmlEngineExtensionPlugin)
+ Q_INTERFACES(QQmlEngineExtensionInterface)
+public:
+ explicit QQmlEngineExtensionPlugin(QObject *parent = nullptr);
+ ~QQmlEngineExtensionPlugin() override;
+ void initializeEngine(QQmlEngine *engine, const char *uri) override;
+};
+
QT_END_NAMESPACE
#endif // QQMLEXTENSIONPLUGIN_H
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index d69c2ac903..79e3585202 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -990,7 +990,9 @@ static QVector<QStaticPlugin> makePlugins()
const auto staticPlugins = QPluginLoader::staticPlugins();
for (const QStaticPlugin &plugin : staticPlugins) {
const QString iid = plugin.metaData().value(QLatin1String("IID")).toString();
- if (iid == QLatin1String(QQmlExtensionInterface_iid) || iid == QLatin1String(QQmlExtensionInterface_iid_old)) {
+ if (iid == QLatin1String(QQmlEngineExtensionInterface_iid)
+ || iid == QLatin1String(QQmlExtensionInterface_iid)
+ || iid == QLatin1String(QQmlExtensionInterface_iid_old)) {
plugins.append(plugin);
}
}
@@ -1008,7 +1010,9 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res
static const QVector<QStaticPlugin> plugins = makePlugins();
for (const QStaticPlugin &plugin : plugins) {
// Since a module can list more than one plugin, we keep iterating even after we found a match.
- if (QQmlExtensionPlugin *instance = qobject_cast<QQmlExtensionPlugin *>(plugin.instance())) {
+ QObject *instance = plugin.instance();
+ if (qobject_cast<QQmlEngineExtensionPlugin *>(instance)
+ || qobject_cast<QQmlExtensionPlugin *>(instance)) {
const QJsonArray metaTagsUriList = plugin.metaData().value(QLatin1String("uri")).toArray();
if (metaTagsUriList.isEmpty()) {
if (errors) {
@@ -2055,17 +2059,8 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
// other QML loader threads and thus not process the initializeEngine call).
}
- // The plugin's per-engine initialization does not need lock protection, as this function is
- // only called from the engine specific loader thread and importDynamicPlugin as well as
- // importStaticPlugin are the only places of access.
- if (!initializedPlugins.contains(uniquePluginID)) {
- initializedPlugins.insert(uniquePluginID);
-
- if (QQmlExtensionInterface *eiface = qobject_cast<QQmlExtensionInterface *>(instance)) {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
- ep->typeLoader.initializeEngine(eiface, uri.toUtf8().constData());
- }
- }
+ if (!initializedPlugins.contains(uniquePluginID))
+ finalizePlugin(instance, uniquePluginID, uri);
return true;
}
@@ -2140,18 +2135,8 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr
// other QML loader threads and thus not process the initializeEngine call).
}
-
- if (!engineInitialized) {
- // The plugin's per-engine initialization does not need lock protection, as this function is
- // only called from the engine specific loader thread and importDynamicPlugin as well as
- // importStaticPlugin are the only places of access.
- initializedPlugins.insert(absoluteFilePath);
-
- if (QQmlExtensionInterface *eiface = qobject_cast<QQmlExtensionInterface *>(instance)) {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
- ep->typeLoader.initializeEngine(eiface, uri.toUtf8().constData());
- }
- }
+ if (!engineInitialized)
+ finalizePlugin(instance, absoluteFilePath, uri);
return true;
}
@@ -2174,4 +2159,20 @@ void QQmlImportDatabase::clearDirCache()
qmldirCache.clear();
}
+void QQmlImportDatabase::finalizePlugin(QObject *instance, const QString &path, const QString &uri)
+{
+ // The plugin's per-engine initialization does not need lock protection, as this function is
+ // only called from the engine specific loader thread and importDynamicPlugin as well as
+ // importStaticPlugin are the only places of access.
+
+ initializedPlugins.insert(path);
+ if (auto *extensionIface = qobject_cast<QQmlExtensionInterface *>(instance)) {
+ QQmlEnginePrivate::get(engine)->typeLoader.initializeEngine(
+ extensionIface, uri.toUtf8().constData());
+ } else if (auto *engineIface = qobject_cast<QQmlEngineExtensionInterface *>(instance)) {
+ QQmlEnginePrivate::get(engine)->typeLoader.initializeEngine(
+ engineIface, uri.toUtf8().constData());
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index e24b3c447c..7f781d2eb7 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -236,6 +236,7 @@ private:
bool importStaticPlugin(QObject *instance, const QString &basePath, const QString &uri,
const QString &typeNamespace, int vmaj, QList<QQmlError> *errors);
void clearDirCache();
+ void finalizePlugin(QObject *instance, const QString &path, const QString &uri);
struct QmldirCache {
int versionMajor;
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 1a5affb0ad..c21247bb95 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -267,6 +267,23 @@ void QQmlMetaType::clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
}
}
+void QQmlMetaType::qmlInsertModuleRegistration(const QString &uri, int majorVersion,
+ void (*registerFunction)())
+{
+ const QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion);
+ QQmlMetaTypeDataPtr data;
+ if (data->moduleTypeRegistrationFunctions.contains(versionedUri))
+ qFatal("Canot add multiple registrations for %s %d", qPrintable(uri), majorVersion);
+ else
+ data->moduleTypeRegistrationFunctions.insert(versionedUri, registerFunction);
+}
+
+void QQmlMetaType::qmlRegisterModuleTypes(const QString &uri, int majorVersion)
+{
+ QQmlMetaTypeDataPtr data;
+ data->registerModuleTypes(QQmlMetaTypeData::VersionedUri(uri, majorVersion));
+}
+
void QQmlMetaType::clearTypeRegistrations()
{
//Only cleans global static, assumed no running engine
@@ -633,17 +650,6 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat
const QString &uri, const QString &typeNamespace, int vmaj,
QList<QQmlError> *errors)
{
- QQmlTypesExtensionInterface *iface = qobject_cast<QQmlTypesExtensionInterface *>(instance);
- if (!iface) {
- if (errors) {
- QQmlError error;
- error.setDescription(QStringLiteral("Module loaded for URI '%1' does not implement "
- "QQmlTypesExtensionInterface").arg(typeNamespace));
- errors->prepend(error);
- }
- return false;
- }
-
if (!typeNamespace.isEmpty() && typeNamespace != uri) {
// This is an 'identified' module
// The namespace for type registrations must match the URI for locating the module
@@ -681,26 +687,42 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat
"it cannot be protected from external registrations.").arg(uri));
}
- if (auto *plugin = qobject_cast<QQmlExtensionPlugin *>(instance)) {
- // basepath should point to the directory of the module, not the plugin file itself:
- QQmlExtensionPluginPrivate::get(plugin)->baseUrl
- = QQmlImports::urlFromLocalFileOrQrcOrUrl(basePath);
+ if (!qobject_cast<QQmlEngineExtensionInterface *>(instance)) {
+ QQmlTypesExtensionInterface *iface = qobject_cast<QQmlTypesExtensionInterface *>(instance);
+ if (!iface) {
+ if (errors) {
+ QQmlError error;
+ // Also does not implement QQmlTypesExtensionInterface, but we want to discourage that.
+ error.setDescription(QStringLiteral("Module loaded for URI '%1' does not implement "
+ "QQmlEngineExtensionInterface").arg(typeNamespace));
+ errors->prepend(error);
+ }
+ return false;
+ }
+
+ if (auto *plugin = qobject_cast<QQmlExtensionPlugin *>(instance)) {
+ // basepath should point to the directory of the module, not the plugin file itself:
+ QQmlExtensionPluginPrivate::get(plugin)->baseUrl
+ = QQmlImports::urlFromLocalFileOrQrcOrUrl(basePath);
+ }
+
+ const QByteArray bytes = uri.toUtf8();
+ const char *moduleId = bytes.constData();
+ iface->registerTypes(moduleId);
}
- const QByteArray bytes = uri.toUtf8();
- const char *moduleId = bytes.constData();
- iface->registerTypes(moduleId);
- }
+ data->registerModuleTypes(QQmlMetaTypeData::VersionedUri(uri, vmaj));
- if (!failures.isEmpty()) {
- if (errors) {
- for (const QString &failure : qAsConst(failures)) {
- QQmlError error;
- error.setDescription(failure);
- errors->prepend(error);
+ if (!failures.isEmpty()) {
+ if (errors) {
+ for (const QString &failure : qAsConst(failures)) {
+ QQmlError error;
+ error.setDescription(failure);
+ errors->prepend(error);
+ }
}
+ return false;
}
- return false;
}
return true;
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 35d5386e1f..13ba4d809b 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -188,6 +188,10 @@ public:
static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd);
+
+ static void qmlInsertModuleRegistration(const QString &uri, int majorVersion,
+ void (*registerFunction)());
+ static void qmlRegisterModuleTypes(const QString &uri, int majorVersion);
};
Q_DECLARE_TYPEINFO(QQmlMetaType, Q_MOVABLE_TYPE);
diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp
index 775bc8bdb4..c2150225c3 100644
--- a/src/qml/qml/qqmlmetatypedata.cpp
+++ b/src/qml/qml/qqmlmetatypedata.cpp
@@ -78,6 +78,13 @@ void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv)
priv->release();
}
+void QQmlMetaTypeData::registerModuleTypes(const QQmlMetaTypeData::VersionedUri &versionedUri)
+{
+ auto function = moduleTypeRegistrationFunctions.constFind(versionedUri);
+ if (function != moduleTypeRegistrationFunctions.constEnd())
+ (*function)();
+}
+
QQmlPropertyCache *QQmlMetaTypeData::propertyCacheForMinorVersion(int index, int minorVersion) const
{
return (index < typePropertyCaches.length())
diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h
index ea796ee7c6..755a51a16e 100644
--- a/src/qml/qml/qqmlmetatypedata_p.h
+++ b/src/qml/qml/qqmlmetatypedata_p.h
@@ -96,9 +96,13 @@ struct QQmlMetaTypeData
QHashedString uri;
int majorVersion;
};
+
typedef QHash<VersionedUri, QQmlTypeModule *> TypeModules;
TypeModules uriToModule;
+ QHash<VersionedUri, void (*)()> moduleTypeRegistrationFunctions;
+ void registerModuleTypes(const VersionedUri &versionedUri);
+
QBitArray objects;
QBitArray interfaces;
QBitArray lists;
diff --git a/src/qml/qml/qqmlmoduleregistration.cpp b/src/qml/qml/qqmlmoduleregistration.cpp
new file mode 100644
index 0000000000..bb82ec1d95
--- /dev/null
+++ b/src/qml/qml/qqmlmoduleregistration.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtQml/private/qqmlmetatype_p.h>
+#include <QtQml/qqmlmoduleregistration.h>
+#include <QtCore/qglobalstatic.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlModuleRegistration::QQmlModuleRegistration(
+ const char *uri, int majorVersion,
+ void (*registerFunction)())
+{
+ QQmlMetaType::qmlInsertModuleRegistration(QString::fromUtf8(uri), majorVersion,
+ registerFunction);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmoduleregistration.h b/src/qml/qml/qqmlmoduleregistration.h
new file mode 100644
index 0000000000..8924724b48
--- /dev/null
+++ b/src/qml/qml/qqmlmoduleregistration.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLMODULEREGISTRATION_H
+#define QQMLMODULEREGISTRATION_H
+
+#include <QtQml/qtqmlglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QML_EXPORT QQmlModuleRegistration
+{
+ Q_DISABLE_COPY_MOVE(QQmlModuleRegistration)
+
+public:
+ QQmlModuleRegistration(const char *uri, int majorVersion, void (*registerFunction)());
+ ~QQmlModuleRegistration() = default;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLMODULEREGISTRATION_H
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index c62f760ee3..54f94d6a11 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -395,19 +395,29 @@ QQmlEngine *QQmlTypeLoader::engine() const
Call the initializeEngine() method on \a iface. Used by QQmlImportDatabase to ensure it
gets called in the correct thread.
*/
-void QQmlTypeLoader::initializeEngine(QQmlExtensionInterface *iface,
- const char *uri)
+template<class Interface>
+void doInitializeEngine(Interface *iface, QQmlTypeLoaderThread *thread, QQmlEngine *engine,
+ const char *uri)
{
- Q_ASSERT(m_thread->isThisThread() || engine()->thread() == QThread::currentThread());
+ Q_ASSERT(thread->isThisThread() || engine->thread() == QThread::currentThread());
- if (m_thread->isThisThread()) {
- m_thread->initializeEngine(iface, uri);
+ if (thread->isThisThread()) {
+ thread->initializeEngine(iface, uri);
} else {
- Q_ASSERT(engine()->thread() == QThread::currentThread());
- iface->initializeEngine(engine(), uri);
+ Q_ASSERT(engine->thread() == QThread::currentThread());
+ iface->initializeEngine(engine, uri);
}
}
+void QQmlTypeLoader::initializeEngine(QQmlEngineExtensionInterface *iface, const char *uri)
+{
+ doInitializeEngine(iface, m_thread, engine(), uri);
+}
+
+void QQmlTypeLoader::initializeEngine(QQmlExtensionInterface *iface, const char *uri)
+{
+ doInitializeEngine(iface, m_thread, engine(), uri);
+}
void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QByteArray &data)
{
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 612d6777ed..d45f0e095c 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -68,6 +68,7 @@ QT_BEGIN_NAMESPACE
class QQmlScriptBlob;
class QQmlQmldirData;
class QQmlTypeData;
+class QQmlEngineExtensionInterface;
class QQmlExtensionInterface;
class QQmlProfiler;
class QQmlTypeLoaderThread;
@@ -172,6 +173,7 @@ public:
void loadWithCachedUnit(QQmlDataBlob *blob, const QV4::CompiledData::Unit *unit, Mode mode = PreferSynchronous);
QQmlEngine *engine() const;
+ void initializeEngine(QQmlEngineExtensionInterface *, const char *);
void initializeEngine(QQmlExtensionInterface *, const char *);
void invalidate();
diff --git a/src/qml/qml/qqmltypeloaderthread.cpp b/src/qml/qml/qqmltypeloaderthread.cpp
index 0e1cecd1e5..618bb09039 100644
--- a/src/qml/qml/qqmltypeloaderthread.cpp
+++ b/src/qml/qml/qqmltypeloaderthread.cpp
@@ -138,7 +138,13 @@ void QQmlTypeLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p)
void QQmlTypeLoaderThread::initializeEngine(QQmlExtensionInterface *iface,
const char *uri)
{
- callMethodInMain(&This::initializeEngineMain, iface, uri);
+ callMethodInMain(&This::initializeExtensionMain, iface, uri);
+}
+
+void QQmlTypeLoaderThread::initializeEngine(QQmlEngineExtensionInterface *iface,
+ const char *uri)
+{
+ callMethodInMain(&This::initializeEngineExtensionMain, iface, uri);
}
void QQmlTypeLoaderThread::shutdownThread()
@@ -188,7 +194,14 @@ void QQmlTypeLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qrea
b->release();
}
-void QQmlTypeLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface,
+void QQmlTypeLoaderThread::initializeExtensionMain(QQmlExtensionInterface *iface,
+ const char *uri)
+{
+ Q_ASSERT(m_loader->engine()->thread() == QThread::currentThread());
+ iface->initializeEngine(m_loader->engine(), uri);
+}
+
+void QQmlTypeLoaderThread::initializeEngineExtensionMain(QQmlEngineExtensionInterface *iface,
const char *uri)
{
Q_ASSERT(m_loader->engine()->thread() == QThread::currentThread());
diff --git a/src/qml/qml/qqmltypeloaderthread_p.h b/src/qml/qml/qqmltypeloaderthread_p.h
index 67e47e86de..9fb441e6e2 100644
--- a/src/qml/qml/qqmltypeloaderthread_p.h
+++ b/src/qml/qml/qqmltypeloaderthread_p.h
@@ -65,6 +65,7 @@ QT_BEGIN_NAMESPACE
class QQmlDataBlob;
class QQmlTypeLoader;
+class QQmlEngineExtensionInterface;
class QQmlExtensionInterface;
class QQmlTypeLoaderThread : public QQmlThread
@@ -86,6 +87,7 @@ public:
void callCompleted(QQmlDataBlob *b);
void callDownloadProgressChanged(QQmlDataBlob *b, qreal p);
void initializeEngine(QQmlExtensionInterface *, const char *);
+ void initializeEngine(QQmlEngineExtensionInterface *, const char *);
protected:
void shutdownThread() override;
@@ -96,7 +98,8 @@ private:
void loadWithCachedUnitThread(QQmlDataBlob *b, const QV4::CompiledData::Unit *unit);
void callCompletedMain(QQmlDataBlob *b);
void callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p);
- void initializeEngineMain(QQmlExtensionInterface *iface, const char *uri);
+ void initializeExtensionMain(QQmlExtensionInterface *iface, const char *uri);
+ void initializeEngineExtensionMain(QQmlEngineExtensionInterface *iface, const char *uri);
QQmlTypeLoader *m_loader;
#if QT_CONFIG(qml_network)