aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2022-11-22 11:35:25 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2022-12-02 16:55:21 +0100
commit3f4856dbca0114b8f354df482fec437dc6b04d23 (patch)
tree7f3b6542f20c2c331a21e395a3937db30b507a8d
parent90da0220e77cb6d71df460bd0e30358d734346d1 (diff)
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 <ulf.hermann@qt.io>
-rw-r--r--src/qml/qml/qqmlapplicationengine.cpp77
-rw-r--r--src/qml/qml/qqmlapplicationengine.h2
-rw-r--r--src/qml/qml/qqmlapplicationengine_p.h3
-rw-r--r--src/qml/qml/qqmlfileselector.cpp5
-rw-r--r--tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp10
5 files changed, 81 insertions, 16 deletions
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
@@ -249,6 +272,18 @@ QQmlApplicationEngine::QQmlApplicationEngine(const QUrl &url, QObject *parent)
}
/*!
+ 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
given then it will be interpreted as relative to the working directory of the
@@ -302,6 +337,30 @@ void QQmlApplicationEngine::load(const QString &filePath)
}
/*!
+ 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.
diff --git a/src/qml/qml/qqmlapplicationengine.h b/src/qml/qml/qqmlapplicationengine.h
index 828629602e..afbb76dd06 100644
--- a/src/qml/qml/qqmlapplicationengine.h
+++ b/src/qml/qml/qqmlapplicationengine.h
@@ -19,6 +19,7 @@ class Q_QML_EXPORT QQmlApplicationEngine : public QQmlEngine
public:
QQmlApplicationEngine(QObject *parent = nullptr);
QQmlApplicationEngine(const QUrl &url, QObject *parent = nullptr);
+ QQmlApplicationEngine(QAnyStringView uri, QAnyStringView typeName, QObject *parent = nullptr);
QQmlApplicationEngine(const QString &filePath, QObject *parent = nullptr);
~QQmlApplicationEngine() override;
@@ -27,6 +28,7 @@ public:
public Q_SLOTS:
void load(const QUrl &url);
void load(const QString &filePath);
+ void loadFromModule(QAnyStringView uri, QAnyStringView typeName);
void setInitialProperties(const QVariantMap &initialProperties);
void setExtraFileSelectors(const QStringList &extraFileSelectors);
void loadData(const QByteArray &data, const QUrl &url = QUrl());
diff --git a/src/qml/qml/qqmlapplicationengine_p.h b/src/qml/qml/qqmlapplicationengine_p.h
index 7ff7a954b1..4cf21bba6d 100644
--- a/src/qml/qml/qqmlapplicationengine_p.h
+++ b/src/qml/qml/qqmlapplicationengine_p.h
@@ -30,12 +30,15 @@ class Q_QML_PRIVATE_EXPORT QQmlApplicationEnginePrivate : public QQmlEnginePriva
public:
QQmlApplicationEnginePrivate(QQmlEngine *e);
~QQmlApplicationEnginePrivate();
+ void ensureInitialized();
void init();
void cleanUp();
void startLoad(const QUrl &url, const QByteArray &data = QByteArray(), bool dataFlag = false);
+ void startLoad(QAnyStringView uri, QAnyStringView type);
void _q_loadTranslations();
void finishLoad(QQmlComponent *component);
+ void ensureLoadingFinishes(QQmlComponent *component);
QList<QObject *> objects;
QVariantMap initialProperties;
QStringList extraFileSelectors;
diff --git a/src/qml/qml/qqmlfileselector.cpp b/src/qml/qml/qqmlfileselector.cpp
index e13dbba819..1704e2d994 100644
--- a/src/qml/qml/qqmlfileselector.cpp
+++ b/src/qml/qml/qqmlfileselector.cpp
@@ -163,10 +163,7 @@ QQmlFileSelector* QQmlFileSelector::get(QQmlEngine* engine)
if (qobject_cast<QQmlApplicationEngine *>(engine)) {
auto *appEnginePrivate = static_cast<QQmlApplicationEnginePrivate *>(enginePrivate);
- if (!appEnginePrivate->isInitialized) {
- appEnginePrivate->init();
- appEnginePrivate->isInitialized = true;
- }
+ appEnginePrivate->ensureInitialized();
}
const QUrl nonEmptyInvalid(QLatin1String(":"));
diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
index d0f580cf5f..5774b68c32 100644
--- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
@@ -50,12 +50,12 @@ void tst_qqmlapplicationengine::basicLoading()
{
int size = 0;
- QQmlApplicationEngine *test = new QQmlApplicationEngine(testFileUrl("basicTest.qml"));
+ auto test = std::make_unique<QQmlApplicationEngine>(testFileUrl("basicTest.qml"));
QCOMPARE(test->rootObjects().size(), ++size);
QVERIFY(test->rootObjects()[size -1]);
QVERIFY(test->rootObjects()[size -1]->property("success").toBool());
- QSignalSpy objectCreated(test, SIGNAL(objectCreated(QObject*,QUrl)));
+ QSignalSpy objectCreated(test.get(), &QQmlApplicationEngine::objectCreated);
test->load(testFileUrl("basicTest.qml"));
QCOMPARE(objectCreated.size(), size);//one less than rootObjects().size() because we missed the first one
QCOMPARE(test->rootObjects().size(), ++size);
@@ -69,7 +69,11 @@ void tst_qqmlapplicationengine::basicLoading()
QVERIFY(test->rootObjects()[size -1]);
QVERIFY(test->rootObjects()[size -1]->property("success").toBool());
- delete test;
+ test->loadFromModule("QtQuick", "Rectangle");
+ QCOMPARE(objectCreated.size(), size);
+ QCOMPARE(test->rootObjects().size(), ++size);
+ QVERIFY(test->rootObjects()[size -1]);
+ QCOMPARE(test->rootObjects()[size -1]->metaObject()->className(), "QQuickRectangle");
}
// make sure we resolve a relative URL to an absolute one, otherwise things