aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlabstractbinding.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-12-15 16:47:27 +0100
committerUlf Hermann <ulf.hermann@qt.io>2022-12-17 02:45:33 +0100
commite9b7eaaf6e627c84cf77dc0ea76c9cb40d705711 (patch)
treeb0fc412c1311efdf6539c21ce251bbb810956dc5 /src/qml/qml/qqmlabstractbinding.cpp
parent9ea0b225372f6b9104ff330364a81aee2855e3f2 (diff)
QML: Consider deep aliases when finding binding targets
If we have a deep alias we need to bind to the inner object rather than the outer one. Fixes: QTBUG-109417 Pick-to: 6.5 6.2 Change-Id: Iefe8641026cfbbf9199b2bb8d9fa2f5fba591f17 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlabstractbinding.cpp')
-rw-r--r--src/qml/qml/qqmlabstractbinding.cpp60
1 files changed, 43 insertions, 17 deletions
diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp
index 0904d1af46..78d1d68f55 100644
--- a/src/qml/qml/qqmlabstractbinding.cpp
+++ b/src/qml/qml/qqmlabstractbinding.cpp
@@ -207,15 +207,36 @@ bool QQmlAbstractBinding::setTarget(
valueType ? valueType->coreIndex() : -1);
}
+static const QQmlPropertyData *getObjectPropertyData(QObject *object, int coreIndex)
+{
+ QQmlData *data = QQmlData::get(object, true);
+ if (!data)
+ return nullptr;
+
+ if (!data->propertyCache) {
+ data->propertyCache = QQmlMetaType::propertyCache(object);
+ if (!data->propertyCache)
+ return nullptr;
+ }
+
+ const QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
+ Q_ASSERT(propertyData);
+ return propertyData;
+}
+
bool QQmlAbstractBinding::setTarget(
QObject *object, int coreIndex, bool coreIsAlias, int valueTypeIndex)
{
- m_target = object;
-
- if (!object) {
+ auto invalidate = [this]() {
+ m_target = nullptr;
m_targetIndex = QQmlPropertyIndex();
return false;
- }
+ };
+
+ if (!object)
+ return invalidate();
+
+ m_target = object;
for (bool isAlias = coreIsAlias; isAlias;) {
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
@@ -223,21 +244,26 @@ bool QQmlAbstractBinding::setTarget(
int aValueTypeIndex;
if (!vme->aliasTarget(coreIndex, &object, &coreIndex, &aValueTypeIndex)) {
// can't resolve id (yet)
- m_target = nullptr;
- m_targetIndex = QQmlPropertyIndex();
- return false;
+ return invalidate();
}
- if (valueTypeIndex == -1)
- valueTypeIndex = aValueTypeIndex;
-
- QQmlData *data = QQmlData::get(object, false);
- if (!data || !data->propertyCache) {
- m_target = nullptr;
- m_targetIndex = QQmlPropertyIndex();
- return false;
+
+ const QQmlPropertyData *propertyData = getObjectPropertyData(object, coreIndex);
+ if (!propertyData)
+ return invalidate();
+
+ if (aValueTypeIndex != -1) {
+ if (propertyData->propType().flags().testFlag(QMetaType::PointerToQObject)) {
+ // deep alias
+ propertyData->readProperty(object, &object);
+ coreIndex = aValueTypeIndex;
+ valueTypeIndex = -1;
+ propertyData = getObjectPropertyData(object, coreIndex);
+ if (!propertyData)
+ return invalidate();
+ } else {
+ valueTypeIndex = aValueTypeIndex;
+ }
}
- const QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex);
- Q_ASSERT(propertyData);
m_target = object;
isAlias = propertyData->isAlias();