aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2022-10-28 15:28:47 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2022-11-10 15:00:11 +0100
commit00af995d5c8d288f8add068eb1a9562d96f11fa9 (patch)
tree04f4e3807c55eba1d8a557f04cb7d983baa8bfba /src
parent826d4eb5ac97f8f35b242eb2096cc36ade6ee236 (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.cpp41
-rw-r--r--src/qml/qml/qqmlcomponent_p.h9
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;