diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2019-08-05 16:03:58 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2019-08-19 11:38:24 +0000 |
commit | 1c59558b03715c6be46650489547c5f9d60d3464 (patch) | |
tree | ed259466b692e52fd102cc0cbf2320361d3c9169 /src | |
parent | 06f5b386e69a9e8c8ad3dfbdea44d18d912c23ea (diff) |
Introduce functions to set properties during creation
Change-Id: Idd4c8ab9e34b9bc3e00f21d7cf1e4f1a70586e7f
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlapplicationengine.cpp | 18 | ||||
-rw-r--r-- | src/qml/qml/qqmlapplicationengine.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlapplicationengine_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 74 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent_p.h | 3 | ||||
-rw-r--r-- | src/quick/items/qquickview.cpp | 18 | ||||
-rw-r--r-- | src/quick/items/qquickview.h | 1 | ||||
-rw-r--r-- | src/quick/items/qquickview_p.h | 2 |
9 files changed, 109 insertions, 11 deletions
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp index e93cfcadb9..d04a89b514 100644 --- a/src/qml/qml/qqmlapplicationengine.cpp +++ b/src/qml/qml/qqmlapplicationengine.cpp @@ -131,7 +131,7 @@ void QQmlApplicationEnginePrivate::finishLoad(QQmlComponent *c) q->objectCreated(nullptr, c->url()); break; case QQmlComponent::Ready: { - auto newObj = c->create(); + auto newObj = initialProperties.empty() ? c->create() : c->createWithInitialProperties(initialProperties); objects << newObj; QObject::connect(newObj, &QObject::destroyed, q, [&](QObject *obj) { objects.removeAll(obj); }); q->objectCreated(objects.constLast(), c->url()); @@ -279,6 +279,22 @@ void QQmlApplicationEngine::load(const QString &filePath) } /*! + Sets the initial properties with which the QML component gets initialized after + it gets loaded. + + + \sa QQmlComponent::setInitialProperties + \sa QQmlApplicationEngine::load + \sa QQmlApplicationEngine::loadData + \since 5.14 +*/ +void QQmlApplicationEngine::setInitialProperties(const QVariantMap &initialProperties) +{ + Q_D(QQmlApplicationEngine); + d->initialProperties = initialProperties; +} + +/*! Loads the QML given in \a data. The object tree defined by \a data is instantiated immediately. diff --git a/src/qml/qml/qqmlapplicationengine.h b/src/qml/qml/qqmlapplicationengine.h index bb5d6b5d68..2b4de91154 100644 --- a/src/qml/qml/qqmlapplicationengine.h +++ b/src/qml/qml/qqmlapplicationengine.h @@ -66,6 +66,7 @@ public: public Q_SLOTS: void load(const QUrl &url); void load(const QString &filePath); + void setInitialProperties(const QVariantMap &initialProperties); void loadData(const QByteArray &data, const QUrl &url = QUrl()); Q_SIGNALS: diff --git a/src/qml/qml/qqmlapplicationengine_p.h b/src/qml/qml/qqmlapplicationengine_p.h index 7a341847bd..1279e400e8 100644 --- a/src/qml/qml/qqmlapplicationengine_p.h +++ b/src/qml/qml/qqmlapplicationengine_p.h @@ -73,6 +73,7 @@ public: void loadTranslations(const QUrl &rootFile); void finishLoad(QQmlComponent *component); QList<QObject *> objects; + QVariantMap initialProperties; }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index fefe2bc685..ed8c41a582 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -350,6 +350,32 @@ void QQmlComponentPrivate::clear() compilationUnit = nullptr; } +QObject *QQmlComponentPrivate::doBeginCreate(QQmlComponent *q, QQmlContext *context) +{ + if (!engine) { + // ###Qt6: In Qt 6, it should be impossible for users to create a QQmlComponent without an engine, and we can remove this check + qWarning("QQmlComponent: Must provide an engine before calling create"); + return nullptr; + } + if (!context) + context = engine->rootContext(); + return q->beginCreate(context); +} + +bool QQmlComponentPrivate::setInitialProperty(QObject *component, const QString& name, const QVariant &value) +{ + QQmlProperty prop(component, name); + auto privProp = QQmlPropertyPrivate::get(prop); + if (!prop.isValid() || !privProp->writeValueProperty(value, nullptr)) { + QQmlError error{}; + error.setUrl(url); + error.setDescription(QLatin1String("Could not set property %1").arg(name)); + state.errors.push_back(error); + return false; + } else + return true; +} + /*! \internal */ @@ -780,18 +806,28 @@ QObject *QQmlComponent::create(QQmlContext *context) { Q_D(QQmlComponent); - if (!d->engine) { - // ###Qt6: In Qt 6, it should be impossible for users to create a QQmlComponent without an engine, and we can remove this check - qWarning("QQmlComponent: Must provide an engine before calling create"); - return nullptr; - } + QObject *rv = d->doBeginCreate(this, context); + if (rv) + completeCreate(); + return rv; +} - if (!context) - context = d->engine->rootContext(); +/*! + Create an object instance of this component, and initialize its toplevel properties according to initalPropertyValues. - QObject *rv = beginCreate(context); - if (rv) + + \sa QQmlComponent::create + \since 5.14 +*/ +QObject *QQmlComponent::createWithInitialProperties(const QVariantMap& initialProperties, QQmlContext *context) +{ + Q_D(QQmlComponent); + + QObject *rv = d->doBeginCreate(this, context); + if (rv) { + setInitialProperties(rv, initialProperties); completeCreate(); + } return rv; } @@ -1067,6 +1103,26 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context, enginePriv->incubate(incubator, forContextData); } +/*! + Set toplevel properties of the component. + + + This method provides advanced control over component instance creation. + In general, programmers should use + \l QQmlComponent::createWithInitialProperties to create a component. + + Use this method after beginCreate and before completeCreate has been called. + If a provided property does not exist, a warning is issued. + + \since 5.14 +*/ +void QQmlComponent::setInitialProperties(QObject *component, const QVariantMap &properties) +{ + Q_D(QQmlComponent); + for (auto it = properties.constBegin(); it != properties.constEnd(); ++it) + d->setInitialProperty(component, it.key(), it.value()); +} + /* This is essentially a copy of QQmlComponent::create(); except it takes the QQmlContextData arguments instead of QQmlContext which means we don't have to construct the rather weighty diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h index 39b6d4526f..f259c99b08 100644 --- a/src/qml/qml/qqmlcomponent.h +++ b/src/qml/qml/qqmlcomponent.h @@ -100,6 +100,8 @@ public: QUrl url() const; virtual QObject *create(QQmlContext *context = nullptr); + QObject *createWithInitialProperties(const QVariantMap& initialProperties, QQmlContext *context = nullptr); + void setInitialProperties(QObject *component, const QVariantMap &properties); virtual QObject *beginCreate(QQmlContext *); virtual void completeCreate(); diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index 9a967501c9..2170646b89 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -143,6 +143,9 @@ public: static QQmlComponentPrivate *get(QQmlComponent *c) { return static_cast<QQmlComponentPrivate *>(QObjectPrivate::get(c)); } + + QObject *doBeginCreate(QQmlComponent *q, QQmlContext *context); + bool setInitialProperty(QObject *component, const QString &name, const QVariant& value); }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp index 61477360bf..17fc16d44b 100644 --- a/src/quick/items/qquickview.cpp +++ b/src/quick/items/qquickview.cpp @@ -240,6 +240,22 @@ void QQuickView::setSource(const QUrl& url) } /*! + Sets the initial properties with which the QML component gets initialized after + calling \l QQuickView::setSource. + + + Note that you can only use this function to initialize toplevel properties. + + \sa QQmlComponent::createWithInitialProperties + \since 5.14 +*/ +void QQuickView::setInitialProperties(const QVariantMap &initialProperties) +{ + Q_D(QQuickView); + d->initialProperties = initialProperties; +} + +/*! \internal Set the source \a url, \a component and content \a item (root of the QML object hierarchy) directly. @@ -471,7 +487,7 @@ void QQuickView::continueExecute() return; } - QObject *obj = d->component->create(); + QObject *obj = d->initialProperties.empty() ? d->component->create() : d->component->createWithInitialProperties(d->initialProperties); if (d->component->isError()) { const QList<QQmlError> errorList = d->component->errors(); diff --git a/src/quick/items/qquickview.h b/src/quick/items/qquickview.h index ecae25e90b..4122fcac79 100644 --- a/src/quick/items/qquickview.h +++ b/src/quick/items/qquickview.h @@ -88,6 +88,7 @@ public: public Q_SLOTS: void setSource(const QUrl&); + void setInitialProperties(const QVariantMap &initialProperties); void setContent(const QUrl& url, QQmlComponent *component, QObject *item); Q_SIGNALS: diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h index 3f284c0519..b1ab8d8e8c 100644 --- a/src/quick/items/qquickview_p.h +++ b/src/quick/items/qquickview_p.h @@ -108,6 +108,8 @@ public: QQuickView::ResizeMode resizeMode; QSize initialSize; QElapsedTimer frameTimer; + + QVariantMap initialProperties; }; QT_END_NAMESPACE |