diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2022-10-28 15:28:47 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2022-11-10 15:00:11 +0100 |
commit | 00af995d5c8d288f8add068eb1a9562d96f11fa9 (patch) | |
tree | 04f4e3807c55eba1d8a557f04cb7d983baa8bfba /src | |
parent | 826d4eb5ac97f8f35b242eb2096cc36ade6ee236 (diff) |
QQmlComponent::loadFomModule: handle required properties
Add support for handling required properties in types created via
QQmlComponent::loadFomModule which are backed only by C++. We check all
properties in the QQmlPropertyCache for their requiredness; we could
also attempt this via the QMetaObject, but the assumption here is that
for a QML object we want the property cache anyway in the near future.
Reducing the size of the ConstructionState which now stores the
RequiredProperties is left as an exercise for another commit.
Change-Id: I2e6f67f809ac2cbddbe2b28614ed98cee066fc61
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 41 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent_p.h | 9 |
2 files changed, 31 insertions, 19 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 5a674b5c49..598b45e6ca 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -308,8 +308,7 @@ void QQmlComponentPrivate::fromTypeData(const QQmlRefPointer<QQmlTypeData> &data RequiredProperties &QQmlComponentPrivate::requiredProperties() { - Q_ASSERT(state.hasCreator()); - return state.creator()->requiredProperties(); + return state.requiredProperties(); } bool QQmlComponentPrivate::hadTopLevelRequiredProperties() const @@ -916,9 +915,7 @@ QObject *QQmlComponentPrivate::createWithProperties(QObject *parent, const QVari q->setInitialProperties(rv, properties); q->completeCreate(); - // TODO: remove loadedType check; change requiredProperties to return - // something sensible - if (!loadedType.isValid() && !requiredProperties().empty()) { + if (!requiredProperties().empty()) { if (behavior == CreateWarnAboutRequiredProperties) { const RequiredProperties &unsetRequiredProperties = requiredProperties(); for (const auto &unsetRequiredProperty : unsetRequiredProperties) { @@ -1036,6 +1033,14 @@ QObject *QQmlComponentPrivate::beginCreate(QQmlRefPointer<QQmlContextData> conte enginePriv->dereferenceScarceResources(); } else { rv = loadedType.createWithQQmlData(); + QQmlPropertyCache::ConstPtr propertyCache = QQmlData::ensurePropertyCache(rv); + for (int i = 0, propertyCount = propertyCache->propertyCount(); i < propertyCount; ++i) { + if (const QQmlPropertyData *propertyData = propertyCache->property(i); propertyData->isRequired()) { + RequiredPropertyInfo info; + info.propertyName = propertyData->name(rv); + state.requiredProperties().insert(propertyData, info); + } + } } if (rv) { @@ -1174,26 +1179,24 @@ void QQmlComponent::completeCreate() void QQmlComponentPrivate::completeCreate() { - if (!loadedType.isValid()) { - const RequiredProperties& unsetRequiredProperties = requiredProperties(); - for (const auto& unsetRequiredProperty: unsetRequiredProperties) { - QQmlError error = unsetRequiredPropertyToQQmlError(unsetRequiredProperty); - state.errors.push_back(QQmlComponentPrivate::AnnotatedQmlError { error, true }); - } - if (state.completePending) { - ++creationDepth; - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); - complete(ep, &state); - --creationDepth; - } - } else { - /* TODO: we need a way to track required properties + const RequiredProperties& unsetRequiredProperties = requiredProperties(); + for (const auto& unsetRequiredProperty: unsetRequiredProperties) { + QQmlError error = unsetRequiredPropertyToQQmlError(unsetRequiredProperty); + state.errors.push_back(QQmlComponentPrivate::AnnotatedQmlError { error, true }); + } + if (loadedType.isValid()) { + /* We can directly set completePending to false, as finalize is only concerned with setting up pending bindings, but that cannot happen here, as we're dealing with a pure C++ type, which cannot have pending bindings */ state.completePending = false; QQmlEnginePrivate::get(engine)->inProgressCreations--; + } else if (state.completePending) { + ++creationDepth; + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + complete(ep, &state); + --creationDepth; } } diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index f614b7e8a2..ea926577f4 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -96,6 +96,14 @@ public: QList<AnnotatedQmlError> errors; bool completePending = false; + RequiredProperties &requiredProperties() { + if (hasCreator()) + return m_creator->requiredProperties(); + else + return m_requiredProperties; + } + + void appendErrors(const QList<QQmlError> &qmlErrors) { for (const QQmlError &e : qmlErrors) @@ -132,6 +140,7 @@ public: } private: + RequiredProperties m_requiredProperties; // todo: union with another member std::unique_ptr<QQmlObjectCreator> m_creator; }; ConstructionState state; |