From 3f4856dbca0114b8f354df482fec437dc6b04d23 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Tue, 22 Nov 2022 11:35:25 +0100 Subject: Introduce QQmlApplicationEngine::loadFromModule This allow instantiating QML types via their module and typename. It simply exposes the underlying functionality of QQmlComponent::loadFromModule. Also add the corresponding convenience constructor. This commit also does some minor refactoring so that functionality can be shared between load and loadFromModule. [ChangeLog][QtQml][QQmlApplicationEngine] It is now possible to load QML types via their module and type name. Fixes: QTBUG-97156 Change-Id: Iee812db269d27e4db4b10117ed2570272a7cc40c Reviewed-by: Ulf Hermann --- src/qml/qml/qqmlapplicationengine.cpp | 77 +++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 9 deletions(-) (limited to 'src/qml/qml/qqmlapplicationengine.cpp') diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp index 08564e1cc2..45f7043336 100644 --- a/src/qml/qml/qqmlapplicationengine.cpp +++ b/src/qml/qml/qqmlapplicationengine.cpp @@ -23,6 +23,14 @@ QQmlApplicationEnginePrivate::~QQmlApplicationEnginePrivate() { } +void QQmlApplicationEnginePrivate::ensureInitialized() +{ + if (!isInitialized) { + init(); + isInitialized = true; + } +} + void QQmlApplicationEnginePrivate::cleanUp() { Q_Q(QQmlApplicationEngine); @@ -81,10 +89,7 @@ void QQmlApplicationEnginePrivate::startLoad(const QUrl &url, const QByteArray & { Q_Q(QQmlApplicationEngine); - if (!isInitialized) { - init(); - isInitialized = true; - } + ensureInitialized(); if (url.scheme() == QLatin1String("file") || url.scheme() == QLatin1String("qrc")) { QFileInfo fi(QQmlFile::urlToLocalFileOrQrc(url)); @@ -101,11 +106,19 @@ void QQmlApplicationEnginePrivate::startLoad(const QUrl &url, const QByteArray & else c->loadUrl(url); - if (!c->isLoading()) { - finishLoad(c); - return; - } - QObject::connect(c, &QQmlComponent::statusChanged, q, [this, c] { this->finishLoad(c); }); + ensureLoadingFinishes(c); +} + +void QQmlApplicationEnginePrivate::startLoad(QAnyStringView uri, QAnyStringView type) +{ + Q_Q(QQmlApplicationEngine); + + _q_loadTranslations(); //Translations must be loaded before the QML file is + QQmlComponent *c = new QQmlComponent(q, q); + + ensureInitialized(); + c->loadFromModule(uri, type); + ensureLoadingFinishes(c); } void QQmlApplicationEnginePrivate::finishLoad(QQmlComponent *c) @@ -142,6 +155,16 @@ void QQmlApplicationEnginePrivate::finishLoad(QQmlComponent *c) c->deleteLater(); } +void QQmlApplicationEnginePrivate::ensureLoadingFinishes(QQmlComponent *c) +{ + Q_Q(QQmlApplicationEngine); + if (!c->isLoading()) { + finishLoad(c); + return; + } + QObject::connect(c, &QQmlComponent::statusChanged, q, [this, c] { this->finishLoad(c); }); +} + /*! \class QQmlApplicationEngine \since 5.1 @@ -248,6 +271,18 @@ QQmlApplicationEngine::QQmlApplicationEngine(const QUrl &url, QObject *parent) load(url); } +/*! + Create a new QQmlApplicationEngine and loads the QML type specified by + \a uri and \a typeName + This is provided as a convenience, and is the same as using the empty constructor and calling + loadFromModule afterwards. +*/ +QQmlApplicationEngine::QQmlApplicationEngine(QAnyStringView uri, QAnyStringView typeName, QObject *parent) + : QQmlApplicationEngine(parent) +{ + loadFromModule(uri, typeName); +} + /*! Create a new QQmlApplicationEngine and loads the QML file at the given \a filePath, which must be a local file path. If a relative path is @@ -301,6 +336,30 @@ void QQmlApplicationEngine::load(const QString &filePath) d->startLoad(QUrl::fromUserInput(filePath, QLatin1String("."), QUrl::AssumeLocalFile)); } +/*! + Loads the QML type \a typeName from the module specified by \a uri. + If the type originates from a QML file located at a remote url, + the type will be loaded asynchronously. + Listen to the \l {QQmlApplicationEngine::objectCreated()}{objectCreated} + signal to determine when the object tree is ready. + + If an error occurs, the \l {QQmlApplicationEngine::objectCreated()}{objectCreated} + signal is emitted with a null pointer as parameter and error messages are printed + with qWarning. + + \code + QQmlApplicationEngine engine; + engine.loadFromModule("QtQuick", "Rectangle"); + \endcode + + \sa QQmlComponent::loadFromModule + */ +void QQmlApplicationEngine::loadFromModule(QAnyStringView uri, QAnyStringView typeName) +{ + Q_D(QQmlApplicationEngine); + d->startLoad(uri, typeName); +} + /*! Sets the \a initialProperties with which the QML component gets initialized after it gets loaded. -- cgit v1.2.3