diff options
Diffstat (limited to 'src/qml/qml/qqmlincubator.cpp')
-rw-r--r-- | src/qml/qml/qqmlincubator.cpp | 93 |
1 files changed, 85 insertions, 8 deletions
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index bc06226cbf..0ad013e90b 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -43,6 +43,7 @@ #include "qqmlexpression_p.h" #include "qqmlobjectcreator_p.h" +#include <private/qqmlcomponent_p.h> void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext) { @@ -60,7 +61,7 @@ void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext) QExplicitlySharedDataPointer<QQmlIncubatorPrivate> parentIncubator; QQmlContextData *cctxt = forContext; while (cctxt) { - if (cctxt->incubator) { + if (!cctxt->hasExtraObject && cctxt->incubator) { parentIncubator = cctxt->incubator; break; } @@ -148,7 +149,8 @@ void QQmlIncubatorPrivate::clear() } enginePriv = nullptr; if (!rootContext.isNull()) { - rootContext->incubator = nullptr; + if (!rootContext->hasExtraObject) + rootContext->incubator = nullptr; rootContext = nullptr; } @@ -296,6 +298,20 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i) tresult = creator->create(subComponentToCreate, /*parent*/nullptr, &i); if (!tresult) errors = creator->errors; + else { + RequiredProperties& requiredProperties = creator->requiredProperties(); + for (auto it = initialProperties.cbegin(); it != initialProperties.cend(); ++it) { + auto component = tresult; + auto name = it.key(); + QQmlProperty prop = QQmlComponentPrivate::removePropertyFromRequired(component, name, requiredProperties); + if (!prop.isValid() || !prop.write(it.value())) { + QQmlError error{}; + error.setUrl(compilationUnit->url()); + error.setDescription(QLatin1String("Could not set property %1").arg(name)); + errors.push_back(error); + } + } + } enginePriv->dereferenceScarceResources(); if (watcher.hasRecursed()) @@ -312,8 +328,14 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i) ddata->indestructible = true; ddata->explicitIndestructibleSet = true; ddata->rootObjectInCreation = false; - if (q) + if (q) { q->setInitialState(result); + if (!creator->requiredProperties().empty()) { + const auto& unsetRequiredProperties = creator->requiredProperties(); + for (const auto& unsetRequiredProperty: unsetRequiredProperties) + errors << QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(unsetRequiredProperty); + } + } } if (watcher.hasRecursed()) @@ -381,26 +403,51 @@ void QQmlIncubationController::incubateFor(int msecs) if (!d || !d->incubatorCount) return; - QQmlInstantiationInterrupt i(msecs * 1000000); + QQmlInstantiationInterrupt i(msecs * Q_INT64_C(1000000)); i.reset(); do { static_cast<QQmlIncubatorPrivate*>(d->incubatorList.first())->incubate(i); } while (d && d->incubatorCount != 0 && !i.shouldInterrupt()); } +#if QT_DEPRECATED_SINCE(5, 15) /*! -Incubate objects while the bool pointed to by \a flag is true, or until there are no -more objects to incubate, or up to \a msecs if \a msecs is not zero. +\obsolete + +\warning Do not use this function. +Use the overload taking a \c{std::atomic<bool>} instead. +*/ +void QQmlIncubationController::incubateWhile(volatile bool *flag, int msecs) +{ + if (!d || !d->incubatorCount) + return; + + QQmlInstantiationInterrupt i(flag, msecs * Q_INT64_C(1000000)); + i.reset(); + do { + static_cast<QQmlIncubatorPrivate*>(d->incubatorList.first())->incubate(i); + } while (d && d->incubatorCount != 0 && !i.shouldInterrupt()); +} +#endif + +/*! +\since 5.15 + +Incubate objects while the atomic bool pointed to by \a flag is true, +or until there are no more objects to incubate, or up to \a msecs if \a +msecs is not zero. Generally this method is used in conjunction with a thread or a UNIX signal that sets the bool pointed to by \a flag to false when it wants incubation to be interrupted. + +\note \a flag is read using acquire memory ordering. */ -void QQmlIncubationController::incubateWhile(volatile bool *flag, int msecs) +void QQmlIncubationController::incubateWhile(std::atomic<bool> *flag, int msecs) { if (!d || !d->incubatorCount) return; - QQmlInstantiationInterrupt i(flag, msecs * 1000000); + QQmlInstantiationInterrupt i(flag, msecs * Q_INT64_C(1000000)); i.reset(); do { static_cast<QQmlIncubatorPrivate*>(d->incubatorList.first())->incubate(i); @@ -657,6 +704,36 @@ QObject *QQmlIncubator::object() const } /*! +Return a list of properties which are required but haven't been set yet. +This list can be modified, so that subclasses which implement special logic +setInitialProperties can mark properties set there as no longer required. + +\sa QQmlIncubator::setInitialProperties +\since 5.15 +*/ +RequiredProperties &QQmlIncubatorPrivate::requiredProperties() +{ + return creator->requiredProperties(); +} + +bool QQmlIncubatorPrivate::hadRequiredProperties() const +{ + return creator->componentHadRequiredProperties(); +} + +/*! +Stores a mapping from property names to initial values, contained in +\a initialProperties, with which the incubated component will be initialized. + +\sa QQmlComponent::setInitialProperties +\since 5.15 +*/ +void QQmlIncubator::setInitialProperties(const QVariantMap &initialProperties) +{ + d->initialProperties = initialProperties; +} + +/*! Called when the status of the incubator changes. \a status is the new status. The default implementation does nothing. |