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 <simon.hausmann@qt.io>
This commit is contained in:
Erik Verbruggen 2016-07-22 10:08:17 +02:00
parent fdc3dcd43f
commit 1534dd6d97
22 changed files with 283 additions and 138 deletions

View File

@ -576,8 +576,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertie
const QQmlPropertyCache *targetCache = propertyCaches->at(targetObjectIndex);
Q_ASSERT(targetCache);
int coreIndex;
QQmlPropertyData::decodeValueTypePropertyIndex(alias->encodedMetaPropertyIndex, &coreIndex);
int coreIndex = QQmlPropertyIndex::fromEncoded(alias->encodedMetaPropertyIndex).coreIndex();
QQmlPropertyData *targetProperty = targetCache->property(coreIndex);
if (!targetProperty)
return false;
@ -655,8 +654,8 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias
*propertyFlags |= QQmlPropertyData::IsQObjectDerived;
} else {
int coreIndex;
int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(alias.encodedMetaPropertyIndex, &coreIndex);
int coreIndex = QQmlPropertyIndex::fromEncoded(alias.encodedMetaPropertyIndex).coreIndex();
int valueTypeIndex = QQmlPropertyIndex::fromEncoded(alias.encodedMetaPropertyIndex).valueTypeIndex();
QQmlPropertyCache *targetCache = propertyCaches->at(targetObjectIndex);
Q_ASSERT(targetCache);

View File

@ -1078,7 +1078,7 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv
} else
property = QStringRef(&aliasPropertyValue, 0, aliasPropertyValue.length());
int propIdx = -1;
QQmlPropertyIndex propIdx;
if (property.isEmpty()) {
alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
@ -1121,7 +1121,7 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv
break;
}
propIdx = targetProperty->coreIndex;
propIdx = QQmlPropertyIndex(targetProperty->coreIndex);
if (!subProperty.isEmpty()) {
const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(targetProperty->propType);
@ -1138,14 +1138,14 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv
}
Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
propIdx = QQmlPropertyData::encodeValueTypePropertyIndex(propIdx, valueTypeIndex);
propIdx = QQmlPropertyIndex(propIdx.coreIndex(), valueTypeIndex);
} else {
if (targetProperty->isQObject())
alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
}
}
alias->encodedMetaPropertyIndex = propIdx;
alias->encodedMetaPropertyIndex = propIdx.toEncoded();
alias->flags |= QV4::CompiledData::Alias::Resolved;
numResolvedAliases++;
}

View File

@ -328,7 +328,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired)
{
QQmlData::flushPendingBinding(object, property->coreIndex);
QQmlData::flushPendingBinding(object, property->encodedIndex());
if (property->isFunction() && !property->isVarProperty()) {
if (property->isVMEFunction()) {

View File

@ -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 \

View File

@ -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<QQmlValueTypeProxyBinding *>(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);
}

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -53,7 +53,7 @@
#include <private/qtqmlglobal_p.h>
#include <private/qobject_p.h>
#include <private/qqmlpropertyindex_p.h>
#include <private/qv4value_p.h>
#include <private/qv4persistent_p.h>
#include <qjsengine.h>
@ -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

View File

@ -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);
}

View File

@ -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<QQmlValueTypeProxyBinding *>(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);

View File

@ -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<QQmlValueTypeProxyBinding *>(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();
}
/*!

View File

@ -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 &);

View File

@ -55,6 +55,7 @@
#include <private/qflagpointer_p.h>
#include "qqmlcleanup_p.h"
#include "qqmlnotifier_p.h"
#include <private/qqmlpropertyindex_p.h>
#include <private/qhashedstring_p.h>
#include <QtCore/qvarlengtharray.h>
@ -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

View File

@ -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 <private/qglobal_p.h>
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

View File

@ -52,6 +52,7 @@
//
#include <private/qtqmlglobal_p.h>
#include <private/qqmlpropertyindex_p.h>
#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
@ -68,8 +69,7 @@ public:
private:
friend class QQmlInterceptorMetaObject;
int m_coreIndex;
int m_valueTypeCoreIndex;
QQmlPropertyIndex m_propertyIndex;
QQmlPropertyValueInterceptor *m_next;
};

View File

@ -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);

View File

@ -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);

View File

@ -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));
}
}

View File

@ -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<int*>(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;
}

View File

@ -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;

View File

@ -194,7 +194,8 @@ void tst_qqmlproperty::qmlmetaproperty()
QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -445,7 +446,8 @@ void tst_qqmlproperty::qmlmetaproperty_object()
QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -495,7 +497,8 @@ void tst_qqmlproperty::qmlmetaproperty_object()
QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -548,7 +551,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -598,7 +602,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -647,7 +652,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QVERIFY(!sigExprWatcher.wasDeleted());
QCOMPARE(QQmlPropertyPrivate::signalExpression(prop), sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -696,7 +702,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QVERIFY(!sigExprWatcher.wasDeleted());
QCOMPARE(QQmlPropertyPrivate::signalExpression(prop), sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -749,7 +756,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -799,7 +807,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -852,7 +861,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -902,7 +912,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QQmlPropertyPrivate::takeSignalExpression(prop, sigExpr);
QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -951,7 +962,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QVERIFY(!sigExprWatcher.wasDeleted());
QCOMPARE(QQmlPropertyPrivate::signalExpression(prop), sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}
@ -1000,7 +1012,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QVERIFY(!sigExprWatcher.wasDeleted());
QCOMPARE(QQmlPropertyPrivate::signalExpression(prop), sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
QCOMPARE(QQmlPropertyPrivate::propertyIndex(prop).valueTypeIndex(), -1);
QVERIFY(!QQmlPropertyPrivate::propertyIndex(prop).hasValueTypeIndex());
delete obj;
}