aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2022-10-31 14:51:13 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2022-11-10 15:00:11 +0100
commit7b67d4061974de01eb5387199fe18e67a400545f (patch)
tree66231ec93d5d9a08b90c86313724c04c44c04e31 /src
parentf086d452503a9e3703484921939593f7ff35cd47 (diff)
Required properties: Use pointers instead of references
This allows for a more natural handling of the case where there are no required properties, and will enable further refactoring of ConstructionState. Unfortunately, we lack a way to mark pointers as always non-null in Qt, else we could mark all required property pointers originating from QQmlObjectCreatorSharedState as such. Change-Id: Icaccb27654130fb57daf924bb44a70a5cf114fed Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/qml/qqmlcomponent.cpp28
-rw-r--r--src/qml/qml/qqmlcomponent_p.h19
-rw-r--r--src/qml/qml/qqmlincubator.cpp13
-rw-r--r--src/qml/qml/qqmlincubator_p.h2
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h2
-rw-r--r--src/qmlmodels/qqmldelegatemodel.cpp4
-rw-r--r--src/qmlmodels/qqmltableinstancemodel.cpp6
-rw-r--r--src/quicktemplates2/qquickstackelement.cpp11
-rw-r--r--src/quicktemplates2/qquickstackelement_p_p.h4
9 files changed, 45 insertions, 44 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 0ca3836181..56df62e50e 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -916,8 +916,7 @@ QObject *QQmlComponentPrivate::createWithProperties(QObject *parent, const QVari
if (state.hasUnsetRequiredProperties()) {
if (behavior == CreateWarnAboutRequiredProperties) {
- const RequiredProperties &unsetRequiredProperties = state.requiredProperties();
- for (const auto &unsetRequiredProperty : unsetRequiredProperties) {
+ for (const auto &unsetRequiredProperty : std::as_const(*state.requiredProperties())) {
const QQmlError error = unsetRequiredPropertyToQQmlError(unsetRequiredProperty);
qmlWarning(rv, error);
}
@@ -1110,6 +1109,7 @@ void QQmlComponentPrivate::complete(QQmlEnginePrivate *enginePriv, ConstructionS
Finds the matching top-level property with name \a name of the component \a createdComponent.
If it was a required property or an alias to a required property contained in \a
requiredProperties, it is removed from it.
+ \a requiredProperties must be non-null.
If wasInRequiredProperties is non-null, the referenced boolean is set to true iff the property
was found in requiredProperties.
@@ -1122,9 +1122,10 @@ void QQmlComponentPrivate::complete(QQmlEnginePrivate *enginePriv, ConstructionS
setInitialProperties.
*/
QQmlProperty QQmlComponentPrivate::removePropertyFromRequired(
- QObject *createdComponent, const QString &name, RequiredProperties &requiredProperties,
+ QObject *createdComponent, const QString &name, RequiredProperties *requiredProperties,
QQmlEngine *engine, bool *wasInRequiredProperties)
{
+ Q_ASSERT(requiredProperties);
QQmlProperty prop(createdComponent, name, engine);
auto privProp = QQmlPropertyPrivate::get(prop);
if (prop.isValid()) {
@@ -1145,11 +1146,11 @@ QQmlProperty QQmlComponentPrivate::removePropertyFromRequired(
Q_ASSERT(data && data->propertyCache);
targetProp = data->propertyCache->property(targetProp->coreIndex());
}
- auto it = requiredProperties.find(targetProp);
- if (it != requiredProperties.end()) {
+ auto it = requiredProperties->find(targetProp);
+ if (it != requiredProperties->end()) {
if (wasInRequiredProperties)
*wasInRequiredProperties = true;
- requiredProperties.erase(it);
+ requiredProperties->erase(it);
} else {
if (wasInRequiredProperties)
*wasInRequiredProperties = false;
@@ -1178,8 +1179,7 @@ void QQmlComponent::completeCreate()
void QQmlComponentPrivate::completeCreate()
{
if (state.hasUnsetRequiredProperties()) {
- const RequiredProperties& unsetRequiredProperties = state.requiredProperties();
- for (const auto& unsetRequiredProperty: unsetRequiredProperties) {
+ for (const auto& unsetRequiredProperty: std::as_const(*state.requiredProperties())) {
QQmlError error = unsetRequiredPropertyToQQmlError(unsetRequiredProperty);
state.errors.push_back(QQmlComponentPrivate::AnnotatedQmlError { error, true });
}
@@ -1484,7 +1484,7 @@ struct QmlIncubatorObject : public QV4::Object
static ReturnedValue method_forceCompletion(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
void statusChanged(QQmlIncubator::Status);
- void setInitialState(QObject *, RequiredProperties &requiredProperties);
+ void setInitialState(QObject *, RequiredProperties *requiredProperties);
};
}
@@ -1582,7 +1582,7 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
*/
-void QQmlComponentPrivate::setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v, RequiredProperties &requiredProperties, QObject *createdComponent)
+void QQmlComponentPrivate::setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v, RequiredProperties *requiredProperties, QObject *createdComponent)
{
QV4::Scope scope(engine);
QV4::ScopedObject object(scope);
@@ -1627,7 +1627,7 @@ void QQmlComponentPrivate::setInitialProperties(QV4::ExecutionEngine *engine, QV
if (engine->hasException) {
qmlWarning(createdComponent, engine->catchExceptionAsQmlError());
continue;
- } else if (isTopLevelProperty) {
+ } else if (isTopLevelProperty && requiredProperties) {
auto prop = removePropertyFromRequired(createdComponent, name->toQString(),
requiredProperties, engine->qmlEngine());
}
@@ -1721,7 +1721,7 @@ void QQmlComponent::createObject(QQmlV4Function *args)
}
if (d->state.hasUnsetRequiredProperties()) {
QList<QQmlError> errors;
- for (const auto &requiredProperty: d->state.requiredProperties()) {
+ for (const auto &requiredProperty: std::as_const(*d->state.requiredProperties())) {
errors.push_back(QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(requiredProperty));
}
qmlWarning(rv, errors);
@@ -1878,7 +1878,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
}
// XXX used by QSGLoader
-void QQmlComponentPrivate::initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate, RequiredProperties &requiredProperties)
+void QQmlComponentPrivate::initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate, RequiredProperties *requiredProperties)
{
QV4::ExecutionEngine *v4engine = engine->handle();
QV4::Scope scope(v4engine);
@@ -1977,7 +1977,7 @@ void QV4::Heap::QmlIncubatorObject::destroy() {
Object::destroy();
}
-void QV4::QmlIncubatorObject::setInitialState(QObject *o, RequiredProperties &requiredProperties)
+void QV4::QmlIncubatorObject::setInitialState(QObject *o, RequiredProperties *requiredProperties)
{
QQmlComponent_setQmlParent(o, d()->parent);
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index e61fd1ca69..064b609b19 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -47,8 +47,8 @@ public:
QObject *beginCreate(QQmlRefPointer<QQmlContextData>);
void completeCreate();
- void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate, RequiredProperties &requiredProperties);
- static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v, RequiredProperties &requiredProperties, QObject *createdComponent);
+ void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate, RequiredProperties *requiredProperties);
+ static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v, RequiredProperties *requiredProperties, QObject *createdComponent);
static QQmlError unsetRequiredPropertyToQQmlError(const RequiredPropertyInfo &unsetRequiredProperty);
virtual void incubateObject(
@@ -99,25 +99,27 @@ public:
\internal A list of pending required properties that need
to be set in order for object construction to be successful.
*/
- RequiredProperties &requiredProperties() {
+ RequiredProperties *requiredProperties() {
if (hasCreator())
return m_creator->requiredProperties();
else
- return m_requiredProperties;
+ return &m_requiredProperties;
}
void addPendingRequiredProperty(const QQmlPropertyData *propData, const RequiredPropertyInfo &info)
{
- requiredProperties().insert(propData, info);
+ Q_ASSERT(requiredProperties());
+ requiredProperties()->insert(propData, info);
}
bool hasUnsetRequiredProperties() const {
- return !const_cast<ConstructionState *>(this)->requiredProperties().isEmpty();
+ return !const_cast<ConstructionState *>(this)->requiredProperties()->isEmpty();
}
void clearRequiredProperties()
{
- requiredProperties().clear();
+ if (auto reqProps = requiredProperties())
+ reqProps->clear();
}
@@ -167,8 +169,7 @@ public:
static void completeDeferred(QQmlEnginePrivate *enginePriv, DeferredState *deferredState);
static void complete(QQmlEnginePrivate *enginePriv, ConstructionState *state);
- static QQmlProperty removePropertyFromRequired(
- QObject *createdComponent, const QString &name, RequiredProperties &requiredProperties,
+ static QQmlProperty removePropertyFromRequired(QObject *createdComponent, const QString &name, RequiredProperties *requiredProperties,
QQmlEngine *engine, bool *wasInRequiredProperties = nullptr);
QQmlEngine *engine;
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index afd265516a..3c0a9dff36 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -263,7 +263,7 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
if (!tresult)
errors = creator->errors;
else {
- RequiredProperties& requiredProperties = creator->requiredProperties();
+ RequiredProperties* requiredProperties = creator->requiredProperties();
for (auto it = initialProperties.cbegin(); it != initialProperties.cend(); ++it) {
auto component = tresult;
auto name = it.key();
@@ -295,9 +295,9 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
ddata->rootObjectInCreation = false;
if (q) {
q->setInitialState(result);
- if (creator && !creator->requiredProperties().empty()) {
- const auto& unsetRequiredProperties = creator->requiredProperties();
- for (const auto& unsetRequiredProperty: unsetRequiredProperties)
+ if (creator && !creator->requiredProperties()->empty()) {
+ const RequiredProperties *unsetRequiredProperties = creator->requiredProperties();
+ for (const auto& unsetRequiredProperty: *unsetRequiredProperties)
errors << QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(unsetRequiredProperty);
}
}
@@ -647,14 +647,15 @@ QObject *QQmlIncubator::object() const
}
/*!
-Return a list of properties which are required but haven't been set yet.
+Return a pointer to 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()
+RequiredProperties *QQmlIncubatorPrivate::requiredProperties()
{
return creator->requiredProperties();
}
diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h
index 00954737f0..a582fbf3ff 100644
--- a/src/qml/qml/qqmlincubator_p.h
+++ b/src/qml/qml/qqmlincubator_p.h
@@ -70,7 +70,7 @@ public:
void forceCompletion(QQmlInstantiationInterrupt &i);
void incubate(QQmlInstantiationInterrupt &i);
- RequiredProperties &requiredProperties();
+ RequiredProperties *requiredProperties();
bool hadTopLevelRequiredProperties() const;
};
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 844a4ee73b..2371facc0a 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -113,7 +113,7 @@ public:
}
QFiniteStack<QQmlGuard<QObject> > &allCreatedObjects() { return sharedState->allCreatedObjects; }
- RequiredProperties &requiredProperties() {return sharedState->requiredProperties;}
+ RequiredProperties *requiredProperties() {return &sharedState->requiredProperties;}
bool componentHadTopLevelRequiredProperties() const {return sharedState->hadTopLevelRequiredProperties;}
static QQmlComponent *createComponent(QQmlEngine *engine,
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
index 00072636d1..fcbcec15a1 100644
--- a/src/qmlmodels/qqmldelegatemodel.cpp
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
@@ -931,9 +931,9 @@ void QQDMIncubationTask::initializeRequiredProperties(QQmlDelegateModelItem *mod
proxyContext->setContextObject(nullptr);
}
- if (incubatorPriv->requiredProperties().empty())
+ if (incubatorPriv->requiredProperties()->empty())
return;
- RequiredProperties &requiredProperties = incubatorPriv->requiredProperties();
+ RequiredProperties *requiredProperties = incubatorPriv->requiredProperties();
auto qmlMetaObject = modelItemToIncubate->metaObject();
// if a required property was not in the model, it might still be a static property of the
diff --git a/src/qmlmodels/qqmltableinstancemodel.cpp b/src/qmlmodels/qqmltableinstancemodel.cpp
index 1c14427b90..e4fcae2a44 100644
--- a/src/qmlmodels/qqmltableinstancemodel.cpp
+++ b/src/qmlmodels/qqmltableinstancemodel.cpp
@@ -397,8 +397,8 @@ bool QQmlTableInstanceModel::setRequiredProperty(int index, const QString &name,
bool wasInRequired = false;
const auto task = QQmlIncubatorPrivate::get(modelItem->incubationTask);
- RequiredProperties &props = task->requiredProperties();
- if (props.empty())
+ RequiredProperties *props = task->requiredProperties();
+ if (props->empty())
return false;
QQmlProperty componentProp = QQmlComponentPrivate::removePropertyFromRequired(
@@ -492,7 +492,7 @@ void QQmlTableInstanceModelIncubationTask::setInitialState(QObject *object)
modelItemToIncubate->object = object;
emit tableInstanceModel->initItem(modelItemToIncubate->index, object);
- if (!QQmlIncubatorPrivate::get(this)->requiredProperties().empty()) {
+ if (!QQmlIncubatorPrivate::get(this)->requiredProperties()->empty()) {
modelItemToIncubate->object = nullptr;
object->deleteLater();
}
diff --git a/src/quicktemplates2/qquickstackelement.cpp b/src/quicktemplates2/qquickstackelement.cpp
index e165a780bb..f8001a2980 100644
--- a/src/quicktemplates2/qquickstackelement.cpp
+++ b/src/quicktemplates2/qquickstackelement.cpp
@@ -141,13 +141,12 @@ bool QQuickStackElement::load(QQuickStackView *parent)
if (component->isError())
QQuickStackViewPrivate::get(parent)->warn(component->errorString().trimmed());
} else {
- RequiredProperties noRequiredProperties {};
- initialize(noRequiredProperties);
+ initialize(/*required properties=*/nullptr);
}
return item;
}
-void QQuickStackElement::incubate(QObject *object, RequiredProperties &requiredProperties)
+void QQuickStackElement::incubate(QObject *object, RequiredProperties *requiredProperties)
{
item = qmlobject_cast<QQuickItem *>(object);
if (item) {
@@ -157,7 +156,7 @@ void QQuickStackElement::incubate(QObject *object, RequiredProperties &requiredP
}
}
-void QQuickStackElement::initialize(RequiredProperties &requiredProperties)
+void QQuickStackElement::initialize(RequiredProperties *requiredProperties)
{
if (!item || init)
return;
@@ -182,9 +181,9 @@ void QQuickStackElement::initialize(RequiredProperties &requiredProperties)
properties.clear();
}
- if (!requiredProperties.empty()) {
+ if (requiredProperties && !requiredProperties->empty()) {
QString error;
- for (const auto &property: requiredProperties) {
+ for (const auto &property: *requiredProperties) {
error += QLatin1String("Property %1 was marked as required but not set.\n")
.arg(property.propertyName);
}
diff --git a/src/quicktemplates2/qquickstackelement_p_p.h b/src/quicktemplates2/qquickstackelement_p_p.h
index f591e8fd5d..00b150805d 100644
--- a/src/quicktemplates2/qquickstackelement_p_p.h
+++ b/src/quicktemplates2/qquickstackelement_p_p.h
@@ -39,8 +39,8 @@ public:
static QQuickStackElement *fromObject(QObject *object, QQuickStackView *view, QString *error);
bool load(QQuickStackView *parent);
- void incubate(QObject *object, RequiredProperties &requiredProperties);
- void initialize(RequiredProperties &requiredProperties);
+ void incubate(QObject *object, RequiredProperties *requiredProperties);
+ void initialize(RequiredProperties *requiredProperties);
void setIndex(int index);
void setView(QQuickStackView *view);