From 1534dd6d97c49f5c7e0392df9c95198311b5b817 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 22 Jul 2016 10:08:17 +0200 Subject: QML: Introduce QQmlPropertyIndex This helps in making it clear when an index is a plain old number and when it consists of an encoded value type index. Change-Id: Ic50d95caf244ed0ee2d62bdba53910a371cfee04 Reviewed-by: Simon Hausmann --- src/qml/qml/qml.pri | 1 + src/qml/qml/qqmlabstractbinding.cpp | 19 ++-- src/qml/qml/qqmlabstractbinding_p.h | 4 +- src/qml/qml/qqmlbinding.cpp | 31 ++----- src/qml/qml/qqmlbinding_p.h | 1 - src/qml/qml/qqmldata_p.h | 18 ++-- src/qml/qml/qqmlengine.cpp | 18 +++- src/qml/qml/qqmlobjectcreator.cpp | 18 ++-- src/qml/qml/qqmlproperty.cpp | 52 ++++++----- src/qml/qml/qqmlproperty_p.h | 8 +- src/qml/qml/qqmlpropertycache_p.h | 14 +-- src/qml/qml/qqmlpropertyindex_p.h | 133 +++++++++++++++++++++++++++ src/qml/qml/qqmlpropertyvalueinterceptor_p.h | 4 +- src/qml/qml/qqmlvaluetypeproxybinding.cpp | 6 +- src/qml/qml/qqmlvaluetypeproxybinding_p.h | 4 +- src/qml/qml/qqmlvaluetypewrapper.cpp | 2 +- src/qml/qml/qqmlvmemetaobject.cpp | 26 +++--- src/qml/qml/qqmlvmemetaobject_p.h | 6 +- 18 files changed, 249 insertions(+), 116 deletions(-) create mode 100644 src/qml/qml/qqmlpropertyindex_p.h (limited to 'src/qml/qml') diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri index cc394b78cb..87be140cbb 100644 --- a/src/qml/qml/qml.pri +++ b/src/qml/qml/qml.pri @@ -90,6 +90,7 @@ HEADERS += \ $$PWD/qqmlxmlhttprequest_p.h \ $$PWD/qqmlcleanup_p.h \ $$PWD/qqmlpropertycache_p.h \ + $$PWD/qqmlpropertyindex_p.h \ $$PWD/qqmlnotifier_p.h \ $$PWD/qqmltypenotavailable_p.h \ $$PWD/qqmltypenamecache_p.h \ diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp index abaf95fa11..39d609454f 100644 --- a/src/qml/qml/qqmlabstractbinding.cpp +++ b/src/qml/qml/qqmlabstractbinding.cpp @@ -78,24 +78,26 @@ void QQmlAbstractBinding::addToObject() QQmlData *data = QQmlData::get(obj, true); - int coreIndex; - if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) { + int coreIndex = targetPropertyIndex().coreIndex(); + if (targetPropertyIndex().hasValueTypeIndex()) { // Value type // Find the value type proxy (if there is one) QQmlValueTypeProxyBinding *proxy = 0; if (data->hasBindingBit(coreIndex)) { QQmlAbstractBinding *b = data->bindings; - while (b && b->targetPropertyIndex() != coreIndex) + while (b && (b->targetPropertyIndex().coreIndex() != coreIndex || + b->targetPropertyIndex().hasValueTypeIndex())) b = b->nextBinding(); Q_ASSERT(b && b->isValueTypeProxy()); proxy = static_cast(b); } if (!proxy) { - proxy = new QQmlValueTypeProxyBinding(obj, coreIndex); + proxy = new QQmlValueTypeProxyBinding(obj, QQmlPropertyIndex(coreIndex)); - Q_ASSERT(proxy->targetPropertyIndex() == coreIndex); + Q_ASSERT(proxy->targetPropertyIndex().coreIndex() == coreIndex); + Q_ASSERT(!proxy->targetPropertyIndex().hasValueTypeIndex()); Q_ASSERT(proxy->targetObject() == obj); proxy->addToObject(); @@ -137,12 +139,13 @@ void QQmlAbstractBinding::removeFromObject() next = nextBinding(); setNextBinding(0); - int coreIndex; - if (QQmlPropertyData::decodeValueTypePropertyIndex(targetPropertyIndex(), &coreIndex) != -1) { + int coreIndex = targetPropertyIndex().coreIndex(); + if (targetPropertyIndex().hasValueTypeIndex()) { // Find the value type binding QQmlAbstractBinding *vtbinding = data->bindings; - while (vtbinding->targetPropertyIndex() != coreIndex) { + while (vtbinding && (vtbinding->targetPropertyIndex().coreIndex() != coreIndex || + vtbinding->targetPropertyIndex().hasValueTypeIndex())) { vtbinding = vtbinding->nextBinding(); Q_ASSERT(vtbinding); } diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h index 0ccfae4610..bea2d253e4 100644 --- a/src/qml/qml/qqmlabstractbinding_p.h +++ b/src/qml/qml/qqmlabstractbinding_p.h @@ -76,7 +76,7 @@ public: // Should return the encoded property index for the binding. Should return this value // even if the binding is not enabled or added to an object. // Encoding is: coreIndex | (valueTypeIndex << 16) - int targetPropertyIndex() const { return m_targetIndex; } + QQmlPropertyIndex targetPropertyIndex() const { return m_targetIndex; } // Should return the object for the binding. Should return this object even if the // binding is not enabled or added to the object. @@ -113,7 +113,7 @@ protected: inline void setNextBinding(QQmlAbstractBinding *); - int m_targetIndex; + QQmlPropertyIndex m_targetIndex; // Pointer is the target object to which the binding binds // flag1 is the updating flag diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index ffe1b4287d..c96e5b661d 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -465,8 +465,7 @@ void QQmlBinding::setEnabled(bool e, QQmlPropertyData::WriteFlags flags) m_nextBinding.setFlag2(); // Always use accessors, only not when: if (auto interceptorMetaObject = QQmlInterceptorMetaObject::get(targetObject())) { - int coreIndex = getPropertyCoreIndex(); - if (coreIndex == -1 || interceptorMetaObject->intercepts(coreIndex)) + if (!m_targetIndex.isValid() || interceptorMetaObject->intercepts(m_targetIndex)) m_nextBinding.clearFlag2(); } @@ -491,7 +490,7 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core) m_target = object; if (!object) { - m_targetIndex = -1; + m_targetIndex = QQmlPropertyIndex(); return; } @@ -505,7 +504,7 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core) int aValueTypeIndex; if (!vme->aliasTarget(coreIndex, &object, &coreIndex, &aValueTypeIndex)) { m_target = 0; - m_targetIndex = -1; + m_targetIndex = QQmlPropertyIndex(); return; } if (valueTypeIndex == -1) @@ -514,7 +513,7 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core) QQmlData *data = QQmlData::get(object, false); if (!data || !data->propertyCache) { m_target = 0; - m_targetIndex = -1; + m_targetIndex = QQmlPropertyIndex(); return; } QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex); @@ -543,39 +542,25 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core) QQmlPropertyData QQmlBinding::getPropertyData() const { - int coreIndex; - int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(m_targetIndex, &coreIndex); - QQmlData *data = QQmlData::get(*m_target, false); Q_ASSERT(data && data->propertyCache); - QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex); + QQmlPropertyData *propertyData = data->propertyCache->property(m_targetIndex.coreIndex()); Q_ASSERT(propertyData); QQmlPropertyData d = *propertyData; - if (Q_UNLIKELY(valueTypeIndex != -1)) { + if (Q_UNLIKELY(m_targetIndex.hasValueTypeIndex())) { const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d.propType); Q_ASSERT(valueTypeMetaObject); - QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex); + QMetaProperty vtProp = valueTypeMetaObject->property(m_targetIndex.valueTypeIndex()); d.setFlags(d.getFlags() | QQmlPropertyData::IsValueTypeVirtual); d.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp); d.valueTypePropType = vtProp.userType(); - d.valueTypeCoreIndex = valueTypeIndex; + d.valueTypeCoreIndex = m_targetIndex.valueTypeIndex(); } return d; } -Q_ALWAYS_INLINE int QQmlBinding::getPropertyCoreIndex() const -{ - int coreIndex; - int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(m_targetIndex, &coreIndex); - if (valueTypeIndex != -1) { - return -1; - } else { - return coreIndex; - } -} - class QObjectPointerBinding: public QQmlNonbindingBinding { QQmlMetaObject targetMetaObject; diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h index 67fbeb693e..94fc0ccfc0 100644 --- a/src/qml/qml/qqmlbinding_p.h +++ b/src/qml/qml/qqmlbinding_p.h @@ -107,7 +107,6 @@ protected: const QV4::ScopedFunctionObject &f) = 0; QQmlPropertyData getPropertyData() const; - int getPropertyCoreIndex() const; int getPropertyType() const; bool slowWrite(const QQmlPropertyData &core, const QV4::Value &result, bool isUndefined, diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index a9f2acdb06..d9a69a9ca3 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -53,7 +53,7 @@ #include #include - +#include #include #include #include @@ -174,7 +174,7 @@ public: void clearBindingBit(int); void setBindingBit(QObject *obj, int); - inline bool hasPendingBindingBit(int) const; + inline bool hasPendingBindingBit(int index) const; void setPendingBindingBit(QObject *obj, int); void clearPendingBindingBit(int); @@ -227,7 +227,7 @@ public: static void markAsDeleted(QObject *); static void setQueuedForDeletion(QObject *); - static inline void flushPendingBinding(QObject *, int coreIndex); + static inline void flushPendingBinding(QObject *, QQmlPropertyIndex propertyIndex); static QQmlPropertyCache *ensurePropertyCache(QJSEngine *engine, QObject *object); @@ -235,7 +235,7 @@ private: // For attachedProperties mutable QQmlDataExtended *extendedData; - void flushPendingBindingImpl(int coreIndex); + void flushPendingBindingImpl(QQmlPropertyIndex index); }; bool QQmlData::wasDeleted(QObject *object) @@ -288,20 +288,20 @@ bool QQmlData::hasBindingBit(int coreIndex) const (bindingBits[bit / 32] & (1 << (bit % 32)))); } -bool QQmlData::hasPendingBindingBit(int coreIndex) const +bool QQmlData::hasPendingBindingBit(int index) const { - int bit = coreIndex * 2 + 1; + int bit = index * 2 + 1; return bindingBitsSize > bit && ((bindingBitsSize == 32) ? (bindingBitsValue & (1 << bit)) : (bindingBits[bit / 32] & (1 << (bit % 32)))); } -void QQmlData::flushPendingBinding(QObject *o, int coreIndex) +void QQmlData::flushPendingBinding(QObject *o, QQmlPropertyIndex propertyIndex) { QQmlData *data = QQmlData::get(o, false); - if (data && data->hasPendingBindingBit(coreIndex)) - data->flushPendingBindingImpl(coreIndex); + if (data && data->hasPendingBindingBit(propertyIndex.coreIndex())) + data->flushPendingBindingImpl(propertyIndex); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 5cfb546718..48832f3b07 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -837,16 +837,18 @@ void QQmlData::setQueuedForDeletion(QObject *object) } } -void QQmlData::flushPendingBindingImpl(int coreIndex) +void QQmlData::flushPendingBindingImpl(QQmlPropertyIndex index) { - clearPendingBindingBit(coreIndex); + clearPendingBindingBit(index.coreIndex()); // Find the binding QQmlAbstractBinding *b = bindings; - while (b && b->targetPropertyIndex() != coreIndex) + while (b && (b->targetPropertyIndex().coreIndex() != index.coreIndex() || + b->targetPropertyIndex().hasValueTypeIndex())) b = b->nextBinding(); - if (b && b->targetPropertyIndex() == coreIndex) + if (b && b->targetPropertyIndex().coreIndex() == index.coreIndex() && + !b->targetPropertyIndex().hasValueTypeIndex()) b->setEnabled(true, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding); } @@ -1788,21 +1790,29 @@ static void QQmlData_clearBit(QQmlData *data, int bit) void QQmlData::clearBindingBit(int coreIndex) { + Q_ASSERT(coreIndex >= 0); + Q_ASSERT(coreIndex <= 0xffff); QQmlData_clearBit(this, coreIndex * 2); } void QQmlData::setBindingBit(QObject *obj, int coreIndex) { + Q_ASSERT(coreIndex >= 0); + Q_ASSERT(coreIndex <= 0xffff); QQmlData_setBit(this, obj, coreIndex * 2); } void QQmlData::clearPendingBindingBit(int coreIndex) { + Q_ASSERT(coreIndex >= 0); + Q_ASSERT(coreIndex <= 0xffff); QQmlData_clearBit(this, coreIndex * 2 + 1); } void QQmlData::setPendingBindingBit(QObject *obj, int coreIndex) { + Q_ASSERT(coreIndex >= 0); + Q_ASSERT(coreIndex <= 0xffff); QQmlData_setBit(this, obj, coreIndex * 2 + 1); } diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index b354104b6e..1e1c238b19 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -636,10 +636,10 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings) // ### this is best done through type-compile-time binding skip lists. if (_valueTypeProperty) { - QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, _valueTypeProperty->coreIndex); + QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex)); if (binding && !binding->isValueTypeProxy()) { - QQmlPropertyPrivate::removeBinding(_bindingTarget, _valueTypeProperty->coreIndex); + QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex)); } else if (binding) { QQmlValueTypeProxyBinding *proxy = static_cast(binding); @@ -788,7 +788,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment) && !_valueTypeProperty) - QQmlPropertyPrivate::removeBinding(_bindingTarget, property->coreIndex); + QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(property->coreIndex)); if (binding->type == QV4::CompiledData::Binding::Type_Script) { QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]; @@ -857,14 +857,16 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con QObject *target = createdSubObject->parent(); if (targetCorePropertyData.isAlias()) { - int propIndex; - QQmlPropertyPrivate::findAliasTarget(target, targetCorePropertyData.coreIndex, &target, &propIndex); + QQmlPropertyIndex propIndex; + QQmlPropertyPrivate::findAliasTarget(target, QQmlPropertyIndex(targetCorePropertyData.coreIndex), &target, &propIndex); QQmlData *data = QQmlData::get(target); if (!data || !data->propertyCache) { qWarning() << "can't resolve property alias for 'on' assignment"; return false; } - targetCorePropertyData = *data->propertyCache->property(propIndex); + + // we can't have aliasses on subproperties of value types, so: + targetCorePropertyData = *data->propertyCache->property(propIndex.coreIndex()); } QQmlProperty prop = @@ -874,7 +876,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con QQmlInterceptorMetaObject *mo = QQmlInterceptorMetaObject::get(target); if (!mo) mo = new QQmlInterceptorMetaObject(target, QQmlData::get(target)->propertyCache); - mo->registerInterceptor(prop.index(), QQmlPropertyPrivate::valueTypeCoreIndex(prop), vi); + mo->registerInterceptor(QQmlPropertyPrivate::propertyIndex(prop), vi); return true; } return false; @@ -1191,7 +1193,7 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru continue; QQmlData *data = QQmlData::get(b->targetObject()); Q_ASSERT(data); - data->clearPendingBindingBit(b->targetPropertyIndex()); + data->clearPendingBindingBit(b->targetPropertyIndex().coreIndex()); b->setEnabled(true, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding); diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index b3eb0a5619..260cf9deaa 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -741,10 +741,10 @@ QQmlPropertyPrivate::setBinding(const QQmlProperty &that, QQmlAbstractBinding *n setBinding(newBinding); } -static void removeOldBinding(QObject *object, int index, QQmlPropertyPrivate::BindingFlags flags = QQmlPropertyPrivate::None) +static void removeOldBinding(QObject *object, QQmlPropertyIndex index, QQmlPropertyPrivate::BindingFlags flags = QQmlPropertyPrivate::None) { - int coreIndex; - int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex); + int coreIndex = index.coreIndex(); + int valueTypeIndex = index.valueTypeIndex(); QQmlData *data = QQmlData::get(object, false); @@ -754,7 +754,8 @@ static void removeOldBinding(QObject *object, int index, QQmlPropertyPrivate::Bi QQmlAbstractBinding::Ptr oldBinding; oldBinding = data->bindings; - while (oldBinding && oldBinding->targetPropertyIndex() != coreIndex) + while (oldBinding && (oldBinding->targetPropertyIndex().coreIndex() != coreIndex || + oldBinding->targetPropertyIndex().hasValueTypeIndex())) oldBinding = oldBinding->nextBinding(); if (!oldBinding) @@ -776,12 +777,12 @@ void QQmlPropertyPrivate::removeBinding(QQmlAbstractBinding *b) removeBinding(b->targetObject(), b->targetPropertyIndex()); } -void QQmlPropertyPrivate::removeBinding(QObject *o, int index) +void QQmlPropertyPrivate::removeBinding(QObject *o, QQmlPropertyIndex index) { Q_ASSERT(o); QObject *target; - int targetIndex; + QQmlPropertyIndex targetIndex; findAliasTarget(o, index, &target, &targetIndex); removeOldBinding(target, targetIndex); } @@ -795,7 +796,7 @@ void QQmlPropertyPrivate::removeBinding(const QQmlProperty &that) } QQmlAbstractBinding * -QQmlPropertyPrivate::binding(QObject *object, int index) +QQmlPropertyPrivate::binding(QObject *object, QQmlPropertyIndex index) { QQmlData *data = QQmlData::get(object); if (!data) @@ -803,19 +804,19 @@ QQmlPropertyPrivate::binding(QObject *object, int index) findAliasTarget(object, index, &object, &index); - int coreIndex; - int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex); + const int coreIndex = index.coreIndex(); + const int valueTypeIndex = index.valueTypeIndex(); if (!data->hasBindingBit(coreIndex)) return 0; QQmlAbstractBinding *binding = data->bindings; - while (binding && binding->targetPropertyIndex() != coreIndex) + while (binding && (binding->targetPropertyIndex().coreIndex() != coreIndex || + binding->targetPropertyIndex().hasValueTypeIndex())) binding = binding->nextBinding(); if (binding && valueTypeIndex != -1) { if (binding->isValueTypeProxy()) { - int index = QQmlPropertyData::encodeValueTypePropertyIndex(coreIndex, valueTypeIndex); binding = static_cast(binding)->binding(index); } } @@ -823,13 +824,14 @@ QQmlPropertyPrivate::binding(QObject *object, int index) return binding; } -void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex, - QObject **targetObject, int *targetBindingIndex) +void QQmlPropertyPrivate::findAliasTarget(QObject *object, QQmlPropertyIndex bindingIndex, + QObject **targetObject, + QQmlPropertyIndex *targetBindingIndex) { QQmlData *data = QQmlData::get(object, false); if (data) { - int coreIndex; - int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(bindingIndex, &coreIndex); + int coreIndex = bindingIndex.coreIndex(); + int valueTypeIndex = bindingIndex.valueTypeIndex(); QQmlPropertyData *propertyData = data->propertyCache?data->propertyCache->property(coreIndex):0; @@ -841,11 +843,12 @@ void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex, // This will either be a value type sub-reference or an alias to a value-type sub-reference not both Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); - int aBindingIndex = aCoreIndex; - if (aValueTypeIndex != -1) - aBindingIndex = QQmlPropertyData::encodeValueTypePropertyIndex(aBindingIndex, aValueTypeIndex); - else if (valueTypeIndex != -1) - aBindingIndex = QQmlPropertyData::encodeValueTypePropertyIndex(aBindingIndex, valueTypeIndex); + QQmlPropertyIndex aBindingIndex(aCoreIndex); + if (aValueTypeIndex != -1) { + aBindingIndex = QQmlPropertyIndex(aCoreIndex, aValueTypeIndex); + } else if (valueTypeIndex != -1) { + aBindingIndex = QQmlPropertyIndex(aCoreIndex, valueTypeIndex); + } findAliasTarget(aObject, aBindingIndex, targetObject, targetBindingIndex); return; @@ -863,11 +866,10 @@ void QQmlPropertyPrivate::setBinding(QQmlAbstractBinding *binding, BindingFlags Q_ASSERT(binding); QObject *object = binding->targetObject(); - int index = binding->targetPropertyIndex(); + const QQmlPropertyIndex index = binding->targetPropertyIndex(); #ifndef QT_NO_DEBUG - int coreIndex; - QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex); + int coreIndex = index.coreIndex(); QQmlData *data = QQmlData::get(object, true); if (data->propertyCache) { QQmlPropertyData *propertyData = data->propertyCache->property(coreIndex); @@ -1600,9 +1602,9 @@ int QQmlProperty::index() const return d ? d->core.coreIndex : -1; } -int QQmlPropertyPrivate::valueTypeCoreIndex(const QQmlProperty &that) +QQmlPropertyIndex QQmlPropertyPrivate::propertyIndex(const QQmlProperty &that) { - return that.d ? that.d->core.getValueTypeCoreIndex() : -1; + return that.d ? that.d->core.encodedIndex() : QQmlPropertyIndex(); } /*! diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h index 9398c74621..f23426f45c 100644 --- a/src/qml/qml/qqmlproperty_p.h +++ b/src/qml/qml/qqmlproperty_p.h @@ -101,7 +101,7 @@ public: QQmlPropertyData::WriteFlags flags = 0); static bool write(QObject *, const QQmlPropertyData &, const QVariant &, QQmlContextData *, QQmlPropertyData::WriteFlags flags = 0); - static void findAliasTarget(QObject *, int, QObject **, int *); + static void findAliasTarget(QObject *, QQmlPropertyIndex, QObject **, QQmlPropertyIndex *); enum BindingFlag { None = 0, @@ -112,9 +112,9 @@ public: static void setBinding(QQmlAbstractBinding *binding, BindingFlags flags = None, QQmlPropertyData::WriteFlags writeFlags = QQmlPropertyData::DontRemoveBinding); static void removeBinding(const QQmlProperty &that); - static void removeBinding(QObject *o, int index); + static void removeBinding(QObject *o, QQmlPropertyIndex index); static void removeBinding(QQmlAbstractBinding *b); - static QQmlAbstractBinding *binding(QObject *, int index); + static QQmlAbstractBinding *binding(QObject *, QQmlPropertyIndex index); static QQmlPropertyData saveValueType(const QQmlPropertyData &, const QMetaObject *, int, @@ -138,7 +138,7 @@ public: static void takeSignalExpression(const QQmlProperty &that, QQmlBoundSignalExpression *); static bool write(const QQmlProperty &that, const QVariant &, QQmlPropertyData::WriteFlags); - static int valueTypeCoreIndex(const QQmlProperty &that); + static QQmlPropertyIndex propertyIndex(const QQmlProperty &that); static int bindingIndex(const QQmlProperty &that); static int bindingIndex(const QQmlPropertyData &that); static QMetaMethod findSignalByName(const QMetaObject *mo, const QByteArray &); diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 750537e707..52e0fdc3bd 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -55,6 +55,7 @@ #include #include "qqmlcleanup_p.h" #include "qqmlnotifier_p.h" +#include #include #include @@ -174,13 +175,7 @@ public: // Returns the "encoded" index for use with bindings. Encoding is: // coreIndex | ((valueTypeCoreIndex + 1) << 16) - inline int encodedIndex() const; - static int encodeValueTypePropertyIndex(int coreIndex, int valueTypeCoreIndex) - { return coreIndex | ((valueTypeCoreIndex + 1) << 16); } - static int decodeValueTypePropertyIndex(int index, int *coreIndex = 0) { - if (coreIndex) *coreIndex = index & 0xffff; - return (index >> 16) - 1; - } + inline QQmlPropertyIndex encodedIndex() const; union { int propType; // When !NotFullyResolved @@ -557,9 +552,10 @@ int QQmlPropertyRawData::getValueTypeCoreIndex() const return isValueTypeVirtual()?valueTypeCoreIndex:-1; } -int QQmlPropertyRawData::encodedIndex() const +QQmlPropertyIndex QQmlPropertyRawData::encodedIndex() const { - return isValueTypeVirtual()?QQmlPropertyData::encodeValueTypePropertyIndex(coreIndex, valueTypeCoreIndex):coreIndex; + return isValueTypeVirtual() ? QQmlPropertyIndex(coreIndex, valueTypeCoreIndex) + : QQmlPropertyIndex(coreIndex); } inline QQmlPropertyData *QQmlPropertyCache::ensureResolved(QQmlPropertyData *p) const diff --git a/src/qml/qml/qqmlpropertyindex_p.h b/src/qml/qml/qqmlpropertyindex_p.h new file mode 100644 index 0000000000..ebc1828efb --- /dev/null +++ b/src/qml/qml/qqmlpropertyindex_p.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLPROPERTYINDEX_P_H +#define QQMLPROPERTYINDEX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_NAMESPACE + +class QQmlPropertyIndex +{ + qint32 index; + +public: + QQmlPropertyIndex() + { index = -1; } + + static QQmlPropertyIndex fromEncoded(qint32 encodedIndex) + { + QQmlPropertyIndex idx; + idx.index = encodedIndex; + return idx; + } + + explicit QQmlPropertyIndex(int coreIndex) + { index = encode(coreIndex, -1); } + + explicit QQmlPropertyIndex(int coreIndex, int valueTypeIndex) + : index(encode(coreIndex, valueTypeIndex)) + {} + + bool isValid() const + { return index != -1; } + + int coreIndex() const + { + if (index == -1) + return -1; + return index & 0xffff; + } + + int valueTypeIndex() const + { + if (index == -1) + return -1; + return (index >> 16) - 1; + } + + bool hasValueTypeIndex() const + { + if (index == -1) + return false; + return index >> 16; + } + + qint32 toEncoded() const + { return index; } + + int intValue() const + { return index; } + + bool operator==(const QQmlPropertyIndex &other) const + { return index == other.index; } + + bool operator!=(const QQmlPropertyIndex &other) const + { return !operator==(other); } + +private: + static qint32 encode(int coreIndex, int valueTypeIndex) + { + Q_ASSERT(coreIndex >= -1); + Q_ASSERT(coreIndex <= 0xffff); + Q_ASSERT(valueTypeIndex >= -1); + Q_ASSERT(valueTypeIndex < 0xffff); + + if (coreIndex == -1) + return -1; + else + return coreIndex | ((valueTypeIndex + 1) << 16); + } +}; + +QT_END_NAMESPACE + +#endif // QQMLPROPERTYINDEX_P_H diff --git a/src/qml/qml/qqmlpropertyvalueinterceptor_p.h b/src/qml/qml/qqmlpropertyvalueinterceptor_p.h index 0c10d13aea..a3d6b0c8c7 100644 --- a/src/qml/qml/qqmlpropertyvalueinterceptor_p.h +++ b/src/qml/qml/qqmlpropertyvalueinterceptor_p.h @@ -52,6 +52,7 @@ // #include +#include #include QT_BEGIN_NAMESPACE @@ -68,8 +69,7 @@ public: private: friend class QQmlInterceptorMetaObject; - int m_coreIndex; - int m_valueTypeCoreIndex; + QQmlPropertyIndex m_propertyIndex; QQmlPropertyValueInterceptor *m_next; }; diff --git a/src/qml/qml/qqmlvaluetypeproxybinding.cpp b/src/qml/qml/qqmlvaluetypeproxybinding.cpp index 595cd01d05..56f073121e 100644 --- a/src/qml/qml/qqmlvaluetypeproxybinding.cpp +++ b/src/qml/qml/qqmlvaluetypeproxybinding.cpp @@ -41,7 +41,7 @@ QT_BEGIN_NAMESPACE -QQmlValueTypeProxyBinding::QQmlValueTypeProxyBinding(QObject *o, int index) +QQmlValueTypeProxyBinding::QQmlValueTypeProxyBinding(QObject *o, QQmlPropertyIndex index) : QQmlAbstractBinding(), m_bindings(0) { @@ -72,7 +72,7 @@ bool QQmlValueTypeProxyBinding::isValueTypeProxy() const return true; } -QQmlAbstractBinding *QQmlValueTypeProxyBinding::binding(int propertyIndex) +QQmlAbstractBinding *QQmlValueTypeProxyBinding::binding(QQmlPropertyIndex propertyIndex) { QQmlAbstractBinding *binding = m_bindings.data(); @@ -91,7 +91,7 @@ void QQmlValueTypeProxyBinding::removeBindings(quint32 mask) QQmlAbstractBinding *lastBinding = 0; while (binding) { - int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(binding->targetPropertyIndex()); + const int valueTypeIndex = binding->targetPropertyIndex().valueTypeIndex(); if (valueTypeIndex != -1 && (mask & (1 << valueTypeIndex))) { QQmlAbstractBinding *remove = binding; remove->setAddedToObject(false); diff --git a/src/qml/qml/qqmlvaluetypeproxybinding_p.h b/src/qml/qml/qqmlvaluetypeproxybinding_p.h index 6e297bb3ea..9a487d6992 100644 --- a/src/qml/qml/qqmlvaluetypeproxybinding_p.h +++ b/src/qml/qml/qqmlvaluetypeproxybinding_p.h @@ -58,9 +58,9 @@ QT_BEGIN_NAMESPACE class QQmlValueTypeProxyBinding : public QQmlAbstractBinding { public: - QQmlValueTypeProxyBinding(QObject *o, int coreIndex); + QQmlValueTypeProxyBinding(QObject *o, QQmlPropertyIndex coreIndex); - QQmlAbstractBinding *binding(int targetPropertyIndex); + QQmlAbstractBinding *binding(QQmlPropertyIndex targetPropertyIndex); void removeBindings(quint32 mask); virtual void setEnabled(bool, QQmlPropertyData::WriteFlags); diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index b69eea61c5..e39acaf168 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -464,7 +464,7 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) QQmlPropertyPrivate::setBinding(newBinding); return; } else { - QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyData::encodeValueTypePropertyIndex(reference->d()->property, pd->coreIndex)); + QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyIndex(reference->d()->property, pd->coreIndex)); } } diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index d5001674ad..81bc6846e6 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -159,8 +159,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect() QQmlData *targetDData = QQmlData::get(target, /*create*/false); if (!targetDData) return; - int coreIndex; - QQmlPropertyData::decodeValueTypePropertyIndex(aliasData->encodedMetaPropertyIndex, &coreIndex); + int coreIndex = QQmlPropertyIndex::fromEncoded(aliasData->encodedMetaPropertyIndex).coreIndex(); const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex); if (!pd) return; @@ -199,10 +198,9 @@ QQmlInterceptorMetaObject::~QQmlInterceptorMetaObject() } -void QQmlInterceptorMetaObject::registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor) +void QQmlInterceptorMetaObject::registerInterceptor(QQmlPropertyIndex index, QQmlPropertyValueInterceptor *interceptor) { - interceptor->m_coreIndex = index; - interceptor->m_valueTypeCoreIndex = valueIndex; + interceptor->m_propertyIndex = index; interceptor->m_next = interceptors; interceptors = interceptor; } @@ -223,10 +221,10 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a) !(*reinterpret_cast(a[3]) & QQmlPropertyData::BypassInterceptor)) { for (QQmlPropertyValueInterceptor *vi = interceptors; vi; vi = vi->m_next) { - if (vi->m_coreIndex != id) + if (vi->m_propertyIndex.coreIndex() != id) continue; - int valueIndex = vi->m_valueTypeCoreIndex; + const int valueIndex = vi->m_propertyIndex.valueTypeIndex(); int type = QQmlData::get(object)->propertyCache->property(id)->propType; if (type != QVariant::Invalid) { @@ -866,8 +864,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * if (!targetDData) return -1; - int coreIndex; - const int valueTypePropertyIndex = QQmlPropertyData::decodeValueTypePropertyIndex(aliasData->encodedMetaPropertyIndex, &coreIndex); + QQmlPropertyIndex encodedIndex = QQmlPropertyIndex::fromEncoded(aliasData->encodedMetaPropertyIndex); + int coreIndex = encodedIndex.coreIndex(); + const int valueTypePropertyIndex = encodedIndex.valueTypeIndex(); // Remove binding (if any) on write if(c == QMetaObject::WriteProperty) { @@ -875,7 +874,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * if (flags & QQmlPropertyData::RemoveBindingOnAliasWrite) { QQmlData *targetData = QQmlData::get(target); if (targetData && targetData->hasBindingBit(coreIndex)) - QQmlPropertyPrivate::removeBinding(target, aliasData->encodedMetaPropertyIndex); + QQmlPropertyPrivate::removeBinding(target, encodedIndex); } } @@ -1189,8 +1188,11 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, if (!*target) return false; - if (!aliasData->isObjectAlias()) - *valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(aliasData->encodedMetaPropertyIndex, coreIndex); + if (!aliasData->isObjectAlias()) { + QQmlPropertyIndex encodedIndex = QQmlPropertyIndex::fromEncoded(aliasData->encodedMetaPropertyIndex); + *coreIndex = encodedIndex.coreIndex(); + *valueTypeIndex = encodedIndex.valueTypeIndex(); + } return true; } diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 4a81fc50d2..031bfdfb9b 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -97,7 +97,7 @@ public: QQmlInterceptorMetaObject(QObject *obj, QQmlPropertyCache *cache); ~QQmlInterceptorMetaObject(); - void registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor); + void registerInterceptor(QQmlPropertyIndex index, QQmlPropertyValueInterceptor *interceptor); static QQmlInterceptorMetaObject *get(QObject *obj); @@ -106,10 +106,10 @@ public: // Used by auto-tests for inspection QQmlPropertyCache *propertyCache() const { return cache; } - bool intercepts(int coreIndex) const + bool intercepts(QQmlPropertyIndex propertyIndex) const { for (auto it = interceptors; it; it = it->m_next) { - if (it->m_coreIndex == coreIndex) + if (it->m_propertyIndex == propertyIndex) return true; } return false; -- cgit v1.2.3