diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-05-20 15:26:47 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-05-24 15:44:16 +0200 |
commit | dc77f7c71c532a1c51f7618765559937fd5d2eb3 (patch) | |
tree | f1d633a5033b0a4cc30c52aac9b3b0a5be05385d /src/qml/qml/qqmlabstractbinding.cpp | |
parent | 3d8702378ba7f8252862aac8d71995d61f4f2b69 (diff) |
Replace synthetic AOT functions with property-to-property bindings
Those should be more efficient and make your feet attract fewer
projectiles.
Fixes: QTBUG-103588
Change-Id: I8b25b9edb1edf5e112dbcba5bba898646d29ae2b
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlabstractbinding.cpp')
-rw-r--r-- | src/qml/qml/qqmlabstractbinding.cpp | 96 |
1 files changed, 95 insertions, 1 deletions
diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp index 8c28c525f2..a84607d035 100644 --- a/src/qml/qml/qqmlabstractbinding.cpp +++ b/src/qml/qml/qqmlabstractbinding.cpp @@ -42,6 +42,7 @@ #include <QtQml/qqmlinfo.h> #include <private/qqmlbinding_p.h> #include <private/qqmlvaluetypeproxybinding_p.h> +#include <private/qqmlvmemetaobject_p.h> QT_BEGIN_NAMESPACE @@ -190,11 +191,104 @@ void QQmlAbstractBinding::removeFromObject() data->clearBindingBit(coreIndex); } -void QQmlAbstractBinding::printBindingLoopError(QQmlProperty &prop) +void QQmlAbstractBinding::printBindingLoopError(const QQmlProperty &prop) { qmlWarning(prop.object()) << QString(QLatin1String("Binding loop detected for property \"%1\"")).arg(prop.name()); } +void QQmlAbstractBinding::getPropertyData( + const QQmlPropertyData **propertyData, QQmlPropertyData *valueTypeData) const +{ + Q_ASSERT(propertyData); + + QQmlData *data = QQmlData::get(m_target.data(), false); + Q_ASSERT(data); + + if (Q_UNLIKELY(!data->propertyCache)) + data->propertyCache = QQmlMetaType::propertyCache(m_target->metaObject()); + + *propertyData = data->propertyCache->property(m_targetIndex.coreIndex()); + Q_ASSERT(*propertyData); + + if (Q_UNLIKELY(m_targetIndex.hasValueTypeIndex() && valueTypeData)) { + const QMetaObject *valueTypeMetaObject + = QQmlMetaType::metaObjectForValueType((*propertyData)->propType()); + Q_ASSERT(valueTypeMetaObject); + QMetaProperty vtProp = valueTypeMetaObject->property(m_targetIndex.valueTypeIndex()); + valueTypeData->setFlags(QQmlPropertyData::flagsForProperty(vtProp)); + valueTypeData->setPropType(vtProp.metaType()); + valueTypeData->setCoreIndex(m_targetIndex.valueTypeIndex()); + } +} + +void QQmlAbstractBinding::updateCanUseAccessor() +{ + setCanUseAccessor(true); // Always use accessors, except when: + if (auto interceptorMetaObject = QQmlInterceptorMetaObject::get(targetObject())) { + if (!m_targetIndex.isValid() || interceptorMetaObject->intercepts(m_targetIndex)) + setCanUseAccessor(false); + } +} + +void QQmlAbstractBinding::setTarget(const QQmlProperty &prop) +{ + auto pd = QQmlPropertyPrivate::get(prop); + setTarget(prop.object(), pd->core, &pd->valueTypeData); +} + +bool QQmlAbstractBinding::setTarget( + QObject *object, const QQmlPropertyData &core, const QQmlPropertyData *valueType) +{ + return setTarget(object, core.coreIndex(), core.isAlias(), + valueType ? valueType->coreIndex() : -1); +} + +bool QQmlAbstractBinding::setTarget( + QObject *object, int coreIndex, bool coreIsAlias, int valueTypeIndex) +{ + m_target = object; + + if (!object) { + m_targetIndex = QQmlPropertyIndex(); + return false; + } + + for (bool isAlias = coreIsAlias; isAlias;) { + QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex); + + int aValueTypeIndex; + if (!vme->aliasTarget(coreIndex, &object, &coreIndex, &aValueTypeIndex)) { + // can't resolve id (yet) + m_target = nullptr; + m_targetIndex = QQmlPropertyIndex(); + return false; + } + 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 = data->propertyCache->property(coreIndex); + Q_ASSERT(propertyData); + + m_target = object; + isAlias = propertyData->isAlias(); + coreIndex = propertyData->coreIndex(); + } + m_targetIndex = QQmlPropertyIndex(coreIndex, valueTypeIndex); + + QQmlData *data = QQmlData::get(m_target.data(), true); + if (!data->propertyCache) + data->propertyCache = QQmlMetaType::propertyCache(m_target->metaObject()); + + return true; +} + + QString QQmlAbstractBinding::expression() const { return QLatin1String("<Unknown>"); |