aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/types/qqmlbind.cpp
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2023-08-15 11:40:32 +0200
committerUlf Hermann <ulf.hermann@qt.io>2023-08-22 09:12:56 +0200
commit603fb28d1d1500752782d5d138c262fccb50f0f9 (patch)
tree8cee39c7ee196ac673158fbf58a6c5cb2d16dd2f /src/qml/types/qqmlbind.cpp
parent139d45c062ce6061b96f7ffe206babde4b596a98 (diff)
QQmlBind: handle top-level attached properties
While top-level attached properties are formally deferred in QQmlBind, QQmlBind is not really interested in them. Top-level attached properties cannot be generalized grouped properties, after all. Therefore, populate the attached objects the usual way when encountering them. Pick-to: 6.6 6.5 Fixes: QTBUG-116049 Change-Id: I18e8759ea52fd91fadf80b2cc69b5054f7cea23a Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Semih Yavuz <semih.yavuz@qt.io>
Diffstat (limited to 'src/qml/types/qqmlbind.cpp')
-rw-r--r--src/qml/types/qqmlbind.cpp101
1 files changed, 76 insertions, 25 deletions
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index 8bfe9d4c4e..cdca6e89d4 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -3,28 +3,29 @@
#include "qqmlbind_p.h"
-#include <private/qqmlnullablevalue_p.h>
-#include <private/qqmlproperty_p.h>
+#include <private/qqmlanybinding_p.h>
#include <private/qqmlbinding_p.h>
+#include <private/qqmlcomponent_p.h>
#include <private/qqmlmetatype_p.h>
+#include <private/qqmlnullablevalue_p.h>
+#include <private/qqmlproperty_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qv4persistent_p.h>
+#include <private/qv4qmlcontext_p.h>
+#include <private/qv4resolvedtypereference_p.h>
-#include <qqmlengine.h>
-#include <qqmlcontext.h>
-#include <qqmlproperty.h>
-#include <qqmlpropertymap.h>
-#include <qqmlinfo.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlinfo.h>
+#include <QtQml/qqmlproperty.h>
+#include <QtQml/qqmlpropertymap.h>
+
+#include <QtCore/private/qobject_p.h>
-#include <QtCore/qfile.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qtimer.h>
+#include <QtCore/qfile.h>
#include <QtCore/qloggingcategory.h>
-#include <private/qqmlanybinding_p.h>
-#include <private/qv4qmlcontext_p.h>
-#include <private/qqmlcomponent_p.h>
-
-#include <private/qobject_p.h>
+#include <QtCore/qtimer.h>
QT_BEGIN_NAMESPACE
@@ -736,6 +737,20 @@ static QQmlAnyBinding createBinding(
return QQmlAnyBinding();
}
+static void initCreator(
+ QQmlData::DeferredData *deferredData,
+ const QQmlRefPointer<QQmlContextData> &contextData,
+ QQmlComponentPrivate::ConstructionState *immediateState)
+{
+ if (!immediateState->hasCreator()) {
+ immediateState->setCompletePending(true);
+ immediateState->initCreator(
+ deferredData->context->parent(), deferredData->compilationUnit,
+ contextData);
+ immediateState->creator()->beginPopulateDeferred(deferredData->context);
+ }
+}
+
void QQmlBindPrivate::decodeBinding(
QQmlBind *q, const QString &propertyPrefix,
QQmlData::DeferredData *deferredData,
@@ -744,12 +759,54 @@ void QQmlBindPrivate::decodeBinding(
{
const QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit
= deferredData->compilationUnit;
- const QString propertyName = propertyPrefix
- + compilationUnit->stringAt(binding->propertyNameIndex);
+ const QString propertySuffix = compilationUnit->stringAt(binding->propertyNameIndex);
+ const QString propertyName = propertyPrefix + propertySuffix;
switch (binding->type()) {
- case QV4::CompiledData::Binding::Type_GroupProperty:
- case QV4::CompiledData::Binding::Type_AttachedProperty: {
+ case QV4::CompiledData::Binding::Type_AttachedProperty:
+ if (propertyPrefix.isEmpty()) {
+ // Top-level attached properties cannot be generalized grouped properties.
+ // Treat them as regular properties.
+ // ... unless we're not supposed to handle regular properties. Then ignore them.
+ if (!immediateState)
+ return;
+
+ Q_ASSERT(compilationUnit->stringAt(compilationUnit->objectAt(binding->value.objectIndex)
+ ->inheritedTypeNameIndex).isEmpty());
+
+ const QV4::ResolvedTypeReference *typeReference
+ = compilationUnit->resolvedType(binding->propertyNameIndex);
+ Q_ASSERT(typeReference);
+ QQmlType attachedType = typeReference->type();
+ if (!attachedType.isValid()) {
+ const QQmlTypeNameCache::Result result
+ = deferredData->context->imports()->query(propertySuffix);
+ if (!result.isValid()) {
+ qmlWarning(q).nospace()
+ << "Unknown name " << propertySuffix << ". The binding is ignored.";
+ return;
+ }
+ attachedType = result.type;
+ }
+
+ QQmlContext *context = qmlContext(q);
+ QObject *attachedObject = qmlAttachedPropertiesObject(
+ q, attachedType.attachedPropertiesFunction(
+ QQmlEnginePrivate::get(context->engine())));
+ if (!attachedObject) {
+ qmlWarning(q).nospace() <<"Could not create attached properties object '"
+ << attachedType.typeName() << "'";
+ return;
+ }
+
+ initCreator(deferredData, QQmlContextData::get(context), immediateState);
+ immediateState->creator()->populateDeferredInstance(
+ q, deferredData->deferredIdx, binding->value.objectIndex, attachedObject,
+ attachedObject, /*value type property*/ nullptr, binding);
+ return;
+ }
+ Q_FALLTHROUGH();
+ case QV4::CompiledData::Binding::Type_GroupProperty: {
const QString pre = propertyName + u'.';
const QV4::CompiledData::Object *subObj
= compilationUnit->objectAt(binding->value.objectIndex);
@@ -776,13 +833,7 @@ void QQmlBindPrivate::decodeBinding(
QQmlProperty property = QQmlPropertyPrivate::create(
q, propertyName, contextData, QQmlPropertyPrivate::InitFlag::AllowSignal);
if (property.isValid()) {
- if (!immediateState->hasCreator()) {
- immediateState->setCompletePending(true);
- immediateState->initCreator(
- deferredData->context->parent(), deferredData->compilationUnit,
- contextData);
- immediateState->creator()->beginPopulateDeferred(deferredData->context);
- }
+ initCreator(deferredData, contextData, immediateState);
immediateState->creator()->populateDeferredBinding(
property, deferredData->deferredIdx, binding);
} else {