aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2016-08-03 16:17:19 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2016-08-09 08:06:16 +0000
commit107a52b8a7019b66b4cb3279e7bf070d5b57c2e0 (patch)
treec633860d4345d6629fa066d56b99fe9335dba474 /src
parentc3cbbf362c769b065fd0586b0510d043cbae92a4 (diff)
QML: Split off value type information from property data
Change-Id: I2ae2fb0f18af9b866cc9482fd4f42d9d4269f8cb Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp9
-rw-r--r--src/qml/qml/qqmlbinding.cpp117
-rw-r--r--src/qml/qml/qqmlbinding_p.h8
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp52
-rw-r--r--src/qml/qml/qqmlproperty.cpp90
-rw-r--r--src/qml/qml/qqmlproperty_p.h18
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h48
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp10
8 files changed, 143 insertions, 209 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 9cfc5dcb1f..8fef45891a 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -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->encodedIndex());
+ QQmlData::flushPendingBinding(object, QQmlPropertyIndex(property->coreIndex));
if (property->isFunction() && !property->isVarProperty()) {
if (property->isVMEFunction()) {
@@ -466,14 +466,14 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
bindingFunction->initBindingLocation();
newBinding = QQmlBinding::create(property, value, object, callingQmlContext);
- newBinding->setTarget(object, *property);
+ newBinding->setTarget(object, *property, nullptr);
}
}
if (newBinding)
QQmlPropertyPrivate::setBinding(newBinding);
else
- QQmlPropertyPrivate::removeBinding(object, property->encodedIndex());
+ QQmlPropertyPrivate::removeBinding(object, QQmlPropertyIndex(property->coreIndex));
if (!newBinding && property->isVarProperty()) {
// allow assignment of "special" values (null, undefined, function) to var properties
@@ -648,6 +648,9 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, con
void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value)
{
+ Q_ASSERT(propertyIndex < 0xffff);
+ Q_ASSERT(propertyIndex >= 0);
+
if (QQmlData::wasDeleted(object))
return;
QQmlData *ddata = QQmlData::get(object, /*create*/false);
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 5c9b14ba74..72c7347a68 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -170,7 +170,11 @@ void QQmlBinding::update(QQmlPropertyData::WriteFlags flags)
// Check for a binding update loop
if (Q_UNLIKELY(updatingFlag())) {
- QQmlProperty p = QQmlPropertyPrivate::restore(targetObject(), getPropertyData(), 0);
+ QQmlPropertyData *d = nullptr;
+ QQmlPropertyData vtd;
+ getPropertyData(&d, &vtd);
+ Q_ASSERT(d);
+ QQmlProperty p = QQmlPropertyPrivate::restore(targetObject(), *d, &vtd, 0);
QQmlAbstractBinding::printBindingLoopError(p);
return;
}
@@ -205,8 +209,10 @@ protected:
QQmlPropertyData::WriteFlags flags, QV4::Scope &,
const QV4::ScopedFunctionObject &) Q_DECL_OVERRIDE Q_DECL_FINAL
{
- QQmlPropertyData pd = getPropertyData();
- pd.writeProperty(*m_target, &binding, flags);
+ Q_ASSERT(!m_targetIndex.hasValueTypeIndex());
+ QQmlPropertyData *pd = nullptr;
+ getPropertyData(&pd, nullptr);
+ pd->writeProperty(*m_target, &binding, flags);
}
};
@@ -260,13 +266,18 @@ protected:
Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL
{
- QQmlPropertyData pd = getPropertyData();
+ Q_ASSERT(targetObject());
+
+ QQmlPropertyData *pd;
+ QQmlPropertyData vpd;
+ getPropertyData(&pd, &vpd);
+ Q_ASSERT(pd);
+
int propertyType = StaticPropType; // If the binding is specialized to a type, the if and switch below will be constant-folded.
if (propertyType == QMetaType::UnknownType)
- propertyType = pd.propType;
- Q_ASSERT(targetObject());
+ propertyType = pd->propType;
- if (Q_LIKELY(!isUndefined && !pd.isValueTypeVirtual())) {
+ if (Q_LIKELY(!isUndefined && !vpd.isValid())) {
switch (propertyType) {
case QMetaType::Bool:
if (result.isBoolean())
@@ -293,32 +304,34 @@ protected:
break;
default:
if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
- if (vtw->d()->valueType->typeId == pd.propType) {
- return vtw->write(m_target.data(), pd.coreIndex);
+ if (vtw->d()->valueType->typeId == pd->propType) {
+ return vtw->write(m_target.data(), pd->coreIndex);
}
}
break;
}
}
- return slowWrite(pd, result, isUndefined, flags);
+ return slowWrite(*pd, vpd, result, isUndefined, flags);
}
template <typename T>
- Q_ALWAYS_INLINE bool doStore(T value, const QQmlPropertyData &pd, QQmlPropertyData::WriteFlags flags) const
+ Q_ALWAYS_INLINE bool doStore(T value, const QQmlPropertyData *pd, QQmlPropertyData::WriteFlags flags) const
{
void *o = &value;
- return pd.writeProperty(targetObject(), o, flags);
+ return pd->writeProperty(targetObject(), o, flags);
}
};
-Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core, const QV4::Value &result,
+Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
+ const QQmlPropertyData &valueTypeData,
+ const QV4::Value &result,
bool isUndefined, QQmlPropertyData::WriteFlags flags)
{
QQmlEngine *engine = context()->engine;
QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
- int type = core.isValueTypeVirtual() ? core.valueTypePropType : core.propType;
+ int type = valueTypeData.isValid() ? valueTypeData.propType : core.propType;
QQmlJavaScriptExpression::DeleteWatcher watcher(this);
@@ -354,14 +367,14 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core, const Q
void *args[] = { 0 };
QMetaObject::metacall(m_target.data(), QMetaObject::ResetProperty, core.coreIndex, args);
} else if (isUndefined && type == qMetaTypeId<QVariant>()) {
- QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant(), context(), flags);
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, valueTypeData, QVariant(), context(), flags);
} else if (type == qMetaTypeId<QJSValue>()) {
const QV4::FunctionObject *f = result.as<QV4::FunctionObject>();
if (f && f->isBinding()) {
delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
return false;
}
- QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant::fromValue(
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, valueTypeData, QVariant::fromValue(
QJSValue(QV8Engine::getV4(v8engine), result.asReturnedValue())),
context(), flags);
} else if (isUndefined) {
@@ -378,7 +391,7 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core, const Q
else
delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
return false;
- } else if (!QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, value, context(), flags)) {
+ } else if (!QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, valueTypeData, value, context(), flags)) {
if (watcher.wasDeleted())
return true;
@@ -483,10 +496,11 @@ QString QQmlBinding::expression() const
void QQmlBinding::setTarget(const QQmlProperty &prop)
{
- setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core);
+ auto pd = QQmlPropertyPrivate::get(prop);
+ setTarget(prop.object(), pd->core, &pd->valueTypeData);
}
-void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
+void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core, const QQmlPropertyData *valueType)
{
m_target = object;
@@ -495,11 +509,9 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
return;
}
- QQmlPropertyData pd = core;
-
- while (pd.isAlias()) {
- int coreIndex = pd.coreIndex;
- int valueTypeIndex = pd.getValueTypeCoreIndex();
+ int coreIndex = core.coreIndex;
+ int valueTypeIndex = valueType ? valueType->coreIndex : -1;
+ for (bool isAlias = core.isAlias(); isAlias; ) {
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
int aValueTypeIndex;
@@ -521,18 +533,10 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
Q_ASSERT(propertyData);
m_target = object;
- pd = *propertyData;
- if (valueTypeIndex != -1) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(pd.propType);
- Q_ASSERT(valueTypeMetaObject);
- QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex);
- pd.setAsValueTypeVirtual();
- pd.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
- pd.valueTypePropType = vtProp.userType();
- pd.valueTypeCoreIndex = valueTypeIndex;
- }
+ isAlias = propertyData->isAlias();
+ coreIndex = propertyData->coreIndex;
}
- m_targetIndex = pd.encodedIndex();
+ m_targetIndex = QQmlPropertyIndex(coreIndex, valueTypeIndex);
QQmlData *data = QQmlData::get(*m_target, true);
if (!data->propertyCache) {
@@ -541,25 +545,24 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
}
}
-QQmlPropertyData QQmlBinding::getPropertyData() const
+void QQmlBinding::getPropertyData(QQmlPropertyData **propertyData, QQmlPropertyData *valueTypeData) const
{
+ Q_ASSERT(propertyData);
+
QQmlData *data = QQmlData::get(*m_target, false);
Q_ASSERT(data && data->propertyCache);
- QQmlPropertyData *propertyData = data->propertyCache->property(m_targetIndex.coreIndex());
- Q_ASSERT(propertyData);
+ *propertyData = data->propertyCache->property(m_targetIndex.coreIndex());
+ Q_ASSERT(*propertyData);
- QQmlPropertyData d = *propertyData;
- if (Q_UNLIKELY(m_targetIndex.hasValueTypeIndex())) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d.propType);
+ if (Q_UNLIKELY(m_targetIndex.hasValueTypeIndex() && valueTypeData)) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType((*propertyData)->propType);
Q_ASSERT(valueTypeMetaObject);
QMetaProperty vtProp = valueTypeMetaObject->property(m_targetIndex.valueTypeIndex());
- d.setAsValueTypeVirtual();
- d.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
- d.valueTypePropType = vtProp.userType();
- d.valueTypeCoreIndex = m_targetIndex.valueTypeIndex();
+ valueTypeData->setFlags(QQmlPropertyData::flagsForProperty(vtProp));
+ valueTypeData->propType = vtProp.userType();
+ valueTypeData->coreIndex = m_targetIndex.valueTypeIndex();
}
- return d;
}
class QObjectPointerBinding: public QQmlNonbindingBinding
@@ -575,20 +578,22 @@ protected:
Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL
{
- QQmlPropertyData pd = getPropertyData();
- if (Q_UNLIKELY(isUndefined || pd.isValueTypeVirtual()))
- return slowWrite(pd, result, isUndefined, flags);
+ QQmlPropertyData *pd;
+ QQmlPropertyData vtpd;
+ getPropertyData(&pd, &vtpd);
+ if (Q_UNLIKELY(isUndefined || vtpd.isValid()))
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
// Check if the result is a QObject:
QObject *resultObject = nullptr;
QQmlMetaObject resultMo;
if (result.isNull()) {
// Special case: we can always write a nullptr. Don't bother checking anything else.
- return pd.writeProperty(targetObject(), &resultObject, flags);
+ return pd->writeProperty(targetObject(), &resultObject, flags);
} else if (auto wrapper = result.as<QV4::QObjectWrapper>()) {
resultObject = wrapper->object();
if (!resultObject)
- return pd.writeProperty(targetObject(), &resultObject, flags);
+ return pd->writeProperty(targetObject(), &resultObject, flags);
if (QQmlData *ddata = QQmlData::get(resultObject, false))
resultMo = ddata->propertyCache;
if (resultMo.isNull()) {
@@ -599,22 +604,22 @@ protected:
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context());
resultMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, value.userType());
if (resultMo.isNull())
- return slowWrite(pd, result, isUndefined, flags);
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
resultObject = *static_cast<QObject *const *>(value.constData());
} else {
- return slowWrite(pd, result, isUndefined, flags);
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
}
// Compare & set:
if (QQmlMetaObject::canConvert(resultMo, targetMetaObject)) {
- return pd.writeProperty(targetObject(), &resultObject, flags);
+ return pd->writeProperty(targetObject(), &resultObject, flags);
} else if (!resultObject && QQmlMetaObject::canConvert(targetMetaObject, resultMo)) {
// In the case of a null QObject, we assign the null if there is
// any change that the null variant type could be up or down cast to
// the property type.
- return pd.writeProperty(targetObject(), &resultObject, flags);
+ return pd->writeProperty(targetObject(), &resultObject, flags);
} else {
- return slowWrite(pd, result, isUndefined, flags);
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
}
}
};
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 94fc0ccfc0..1801c3040c 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -81,7 +81,7 @@ public:
~QQmlBinding();
void setTarget(const QQmlProperty &);
- void setTarget(QObject *, const QQmlPropertyData &);
+ void setTarget(QObject *, const QQmlPropertyData &, const QQmlPropertyData *valueType);
void setNotifyOnValueChanged(bool);
@@ -106,11 +106,11 @@ protected:
QQmlPropertyData::WriteFlags flags, QV4::Scope &scope,
const QV4::ScopedFunctionObject &f) = 0;
- QQmlPropertyData getPropertyData() const;
+ void getPropertyData(QQmlPropertyData **propertyData, QQmlPropertyData *valueTypeData) const;
int getPropertyType() const;
- bool slowWrite(const QQmlPropertyData &core, const QV4::Value &result, bool isUndefined,
- QQmlPropertyData::WriteFlags flags);
+ bool slowWrite(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData,
+ const QV4::Value &result, bool isUndefined, QQmlPropertyData::WriteFlags flags);
private:
inline bool updatingFlag() const;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 1e1c238b19..993331b0a0 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -810,16 +810,18 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
// the point property (_qobjectForBindings) and after evaluating the expression,
// the result is written to a value type virtual property, that contains the sub-index
// of the "x" property.
- QQmlPropertyData targetCorePropertyData = *property;
- if (_valueTypeProperty)
- targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
+ QQmlBinding *qmlBinding;
+ if (_valueTypeProperty) {
+ qmlBinding = QQmlBinding::create(_valueTypeProperty, function, _scopeObject, context);
+ qmlBinding->setTarget(_bindingTarget, *_valueTypeProperty, property);
+ } else {
+ qmlBinding = QQmlBinding::create(property, function, _scopeObject, context);
+ qmlBinding->setTarget(_bindingTarget, *property, nullptr);
+ }
- QQmlBinding *qmlBinding = QQmlBinding::create(&targetCorePropertyData, function, _scopeObject, context);
sharedState->allCreatedBindings.push(QQmlAbstractBinding::Ptr(qmlBinding));
- qmlBinding->setTarget(_bindingTarget, targetCorePropertyData);
-
- if (targetCorePropertyData.isAlias()) {
+ if (property->isAlias()) {
QQmlPropertyPrivate::setBinding(qmlBinding, QQmlPropertyPrivate::DontEnable);
} else {
qmlBinding->addToObject();
@@ -840,15 +842,16 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
QQmlType *type = qmlTypeForObject(createdSubObject);
Q_ASSERT(type);
- QQmlPropertyData targetCorePropertyData = *property;
- if (_valueTypeProperty)
- targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
-
int valueSourceCast = type->propertyValueSourceCast();
if (valueSourceCast != -1) {
QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast);
QObject *target = createdSubObject->parent();
- vs->setTarget(QQmlPropertyPrivate::restore(target, targetCorePropertyData, context));
+ QQmlProperty prop;
+ if (_valueTypeProperty)
+ prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, property, context);
+ else
+ prop = QQmlPropertyPrivate::restore(target, *property, nullptr, context);
+ vs->setTarget(prop);
return true;
}
int valueInterceptorCast = type->propertyValueInterceptorCast();
@@ -856,9 +859,11 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(createdSubObject) + valueInterceptorCast);
QObject *target = createdSubObject->parent();
- if (targetCorePropertyData.isAlias()) {
+ QQmlPropertyIndex propertyIndex;
+ if (property->isAlias()) {
+ QQmlPropertyIndex originalIndex(property->coreIndex, _valueTypeProperty ? _valueTypeProperty->coreIndex : -1);
QQmlPropertyIndex propIndex;
- QQmlPropertyPrivate::findAliasTarget(target, QQmlPropertyIndex(targetCorePropertyData.coreIndex), &target, &propIndex);
+ QQmlPropertyPrivate::findAliasTarget(target, originalIndex, &target, &propIndex);
QQmlData *data = QQmlData::get(target);
if (!data || !data->propertyCache) {
qWarning() << "can't resolve property alias for 'on' assignment";
@@ -866,17 +871,24 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
}
// we can't have aliasses on subproperties of value types, so:
- targetCorePropertyData = *data->propertyCache->property(propIndex.coreIndex());
+ QQmlPropertyData targetPropertyData = *data->propertyCache->property(propIndex.coreIndex());
+ auto prop = QQmlPropertyPrivate::restore(target, targetPropertyData, nullptr, context);
+ vi->setTarget(prop);
+ propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
+ } else {
+ QQmlProperty prop;
+ if (_valueTypeProperty)
+ prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, property, context);
+ else
+ prop = QQmlPropertyPrivate::restore(target, *property, nullptr, context);
+ vi->setTarget(prop);
+ propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
}
- QQmlProperty prop =
- QQmlPropertyPrivate::restore(target, targetCorePropertyData, context);
-
- vi->setTarget(prop);
QQmlInterceptorMetaObject *mo = QQmlInterceptorMetaObject::get(target);
if (!mo)
mo = new QQmlInterceptorMetaObject(target, QQmlData::get(target)->propertyCache);
- mo->registerInterceptor(QQmlPropertyPrivate::propertyIndex(prop), vi);
+ mo->registerInterceptor(propertyIndex, vi);
return true;
}
return false;
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 33f3b96389..ffa9bfa3a7 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -306,10 +306,9 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
object = currentObject;
core = *property;
- core.setAsValueTypeVirtual();
- core.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
- core.valueTypePropType = vtProp.userType();
- core.valueTypeCoreIndex = idx;
+ valueTypeData.setFlags(QQmlPropertyData::flagsForProperty(vtProp));
+ valueTypeData.propType = vtProp.userType();
+ valueTypeData.coreIndex = idx;
return;
} else {
@@ -473,7 +472,7 @@ const char *QQmlProperty::propertyTypeName() const
if (d->isValueType()) {
const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType);
Q_ASSERT(valueTypeMetaObject);
- return valueTypeMetaObject->property(d->core.valueTypeCoreIndex).typeName();
+ return valueTypeMetaObject->property(d->valueTypeData.coreIndex).typeName();
} else if (d->object && type() & Property && d->core.isValid()) {
return d->object->metaObject()->property(d->core.coreIndex).typeName();
} else {
@@ -493,10 +492,7 @@ bool QQmlProperty::operator==(const QQmlProperty &other) const
// from the other members
return d->object == other.d->object &&
d->core.coreIndex == other.d->core.coreIndex &&
- d->core.isValueTypeVirtual() == other.d->core.isValueTypeVirtual() &&
- (!d->core.isValueTypeVirtual() ||
- (d->core.valueTypeCoreIndex == other.d->core.valueTypeCoreIndex &&
- d->core.valueTypePropType == other.d->core.valueTypePropType));
+ d->valueTypeData.coreIndex == other.d->valueTypeData.coreIndex;
}
/*!
@@ -510,14 +506,14 @@ int QQmlProperty::propertyType() const
bool QQmlPropertyPrivate::isValueType() const
{
- return core.isValueTypeVirtual();
+ return valueTypeData.isValid();
}
int QQmlPropertyPrivate::propertyType() const
{
uint type = this->type();
if (isValueType()) {
- return core.valueTypePropType;
+ return valueTypeData.propType;
} else if (type & QQmlProperty::Property) {
return core.propType;
} else {
@@ -653,7 +649,7 @@ QString QQmlProperty::name() const
const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType);
Q_ASSERT(valueTypeMetaObject);
- const char *vtName = valueTypeMetaObject->property(d->core.valueTypeCoreIndex).name();
+ const char *vtName = valueTypeMetaObject->property(d->valueTypeData.coreIndex).name();
rv += QString::fromUtf8(vtName);
d->nameCache = rv;
@@ -708,7 +704,8 @@ QQmlPropertyPrivate::binding(const QQmlProperty &that)
if (!that.d || !that.isProperty() || !that.d->object)
return 0;
- return binding(that.d->object, that.d->core.encodedIndex());
+ QQmlPropertyIndex thatIndex(that.d->core.coreIndex, that.d->valueTypeData.coreIndex);
+ return binding(that.d->object, thatIndex);
}
/*!
@@ -791,7 +788,7 @@ void QQmlPropertyPrivate::removeBinding(const QQmlProperty &that)
if (!that.d || !that.isProperty() || !that.d->object)
return;
- removeBinding(that.d->object, that.d->core.encodedIndex());
+ removeBinding(that.d->object, that.d->encodedIndex());
}
QQmlAbstractBinding *
@@ -1030,7 +1027,7 @@ QVariant QQmlPropertyPrivate::readValueProperty()
QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType);
Q_ASSERT(valueType);
valueType->read(object, core.coreIndex);
- return valueType->metaObject()->property(core.valueTypeCoreIndex).read(valueType);
+ return valueType->metaObject()->property(valueTypeData.coreIndex).read(valueType);
} else if (core.isQList()) {
@@ -1148,38 +1145,28 @@ bool QQmlPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx,
bool QQmlPropertyPrivate::writeValueProperty(const QVariant &value, QQmlPropertyData::WriteFlags flags)
{
- return writeValueProperty(object, core, value, effectiveContext(), flags);
+ return writeValueProperty(object, core, valueTypeData, value, effectiveContext(), flags);
}
bool
QQmlPropertyPrivate::writeValueProperty(QObject *object,
const QQmlPropertyData &core,
+ const QQmlPropertyData &valueTypeData,
const QVariant &value,
QQmlContextData *context,QQmlPropertyData::WriteFlags flags)
{
// Remove any existing bindings on this property
if (!(flags & QQmlPropertyData::DontRemoveBinding) && object)
- removeBinding(object, core.encodedIndex());
+ removeBinding(object, encodedIndex(core, valueTypeData));
bool rv = false;
- if (core.isValueTypeVirtual()) {
-
+ if (valueTypeData.isValid()) {
QQmlValueType *writeBack = QQmlValueTypeFactory::valueType(core.propType);
writeBack->read(object, core.coreIndex);
-
- QQmlPropertyData data = core;
- data.setFlags(core.valueTypeFlags);
- data.coreIndex = core.valueTypeCoreIndex;
- data.propType = core.valueTypePropType;
-
- rv = write(writeBack, data, value, context, flags);
-
+ rv = write(writeBack, valueTypeData, value, context, flags);
writeBack->write(object, core.coreIndex, flags);
-
} else {
-
rv = write(object, core, value, context, flags);
-
}
return rv;
@@ -1603,56 +1590,23 @@ int QQmlProperty::index() const
QQmlPropertyIndex QQmlPropertyPrivate::propertyIndex(const QQmlProperty &that)
{
- return that.d ? that.d->core.encodedIndex() : QQmlPropertyIndex();
-}
-
-/*!
- Returns the "property index" for use in bindings. The top 16 bits are the value type
- offset, and 0 otherwise. The bottom 16 bits are the regular property index.
-*/
-int QQmlPropertyPrivate::bindingIndex(const QQmlProperty &that)
-{
- if (!that.d)
- return -1;
- return bindingIndex(that.d->core);
-}
-
-int QQmlPropertyPrivate::bindingIndex(const QQmlPropertyData &that)
-{
- int rv = that.coreIndex;
- if (rv != -1 && that.isValueTypeVirtual())
- rv = rv | (that.valueTypeCoreIndex << 16);
- return rv;
-}
-
-QQmlPropertyData
-QQmlPropertyPrivate::saveValueType(const QQmlPropertyData &base,
- const QMetaObject *subObject, int subIndex,
- QQmlEngine *)
-{
- QMetaProperty subProp = subObject->property(subIndex);
-
- QQmlPropertyData core = base;
- core.setAsValueTypeVirtual();
- core.valueTypeFlags = QQmlPropertyData::flagsForProperty(subProp);
- core.valueTypeCoreIndex = subIndex;
- core.valueTypePropType = subProp.userType();
-
- return core;
+ return that.d ? that.d->encodedIndex() : QQmlPropertyIndex();
}
QQmlProperty
QQmlPropertyPrivate::restore(QObject *object, const QQmlPropertyData &data,
- QQmlContextData *ctxt)
+ const QQmlPropertyData *valueTypeData, QQmlContextData *ctxt)
{
QQmlProperty prop;
prop.d = new QQmlPropertyPrivate;
prop.d->object = object;
prop.d->context = ctxt;
- prop.d->engine = ctxt?ctxt->engine:0;
+ prop.d->engine = ctxt ? ctxt->engine : nullptr;
prop.d->core = data;
+ if (valueTypeData)
+ prop.d->valueTypeData = *valueTypeData;
return prop;
}
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index f23426f45c..16d2bfef64 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -73,12 +73,18 @@ public:
QPointer<QObject> object;
QQmlPropertyData core;
+ QQmlPropertyData valueTypeData;
bool isNameCached:1;
QString nameCache;
QQmlPropertyPrivate();
+ QQmlPropertyIndex encodedIndex() const
+ { return encodedIndex(core, valueTypeData); }
+ static QQmlPropertyIndex encodedIndex(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData)
+ { return QQmlPropertyIndex(core.coreIndex, valueTypeData.coreIndex); }
+
inline QQmlContextData *effectiveContext() const;
void initProperty(QObject *obj, const QString &name);
@@ -96,7 +102,7 @@ public:
static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object,
const QVariant &value, int flags);
static bool writeValueProperty(QObject *,
- const QQmlPropertyData &,
+ const QQmlPropertyData &, const QQmlPropertyData &valueTypeData,
const QVariant &, QQmlContextData *,
QQmlPropertyData::WriteFlags flags = 0);
static bool write(QObject *, const QQmlPropertyData &, const QVariant &,
@@ -116,12 +122,8 @@ public:
static void removeBinding(QQmlAbstractBinding *b);
static QQmlAbstractBinding *binding(QObject *, QQmlPropertyIndex index);
- static QQmlPropertyData saveValueType(const QQmlPropertyData &,
- const QMetaObject *, int,
- QQmlEngine *);
- static QQmlProperty restore(QObject *,
- const QQmlPropertyData &,
- QQmlContextData *);
+ static QQmlProperty restore(QObject *, const QQmlPropertyData &, const QQmlPropertyData *,
+ QQmlContextData *);
int signalIndex() const;
@@ -139,8 +141,6 @@ public:
QQmlBoundSignalExpression *);
static bool write(const QQmlProperty &that, const QVariant &, QQmlPropertyData::WriteFlags);
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 &);
static bool connect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index,
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index dfe0d02dcd..cc3ad62706 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -95,8 +95,7 @@ public:
QJSValueType = 6, // Property type is a QScriptValue
V4HandleType = 7, // Property type is a QQmlV4Handle
VarPropertyType = 8, // Property type is a "var" property of VMEMO
- ValueTypeVirtualType = 9, // Property is a value type "virtual" property
- QVariantType = 10 // Property is a QVariant
+ QVariantType = 9 // Property is a QVariant
};
// Can apply to all properties, except IsFunction
@@ -154,8 +153,6 @@ public:
bool isQJSValue() const { return flags.type == Flags::QJSValueType; }
bool isV4Handle() const { return flags.type == Flags::V4HandleType; }
bool isVarProperty() const { return flags.type == Flags::VarPropertyType; }
- bool isValueTypeVirtual() const { return flags.type == Flags::ValueTypeVirtualType; }
- void setAsValueTypeVirtual() { flags.type = Flags::ValueTypeVirtualType; }
bool isQVariant() const { return flags.type == Flags::QVariantType; }
bool isVMEFunction() const { return flags.isVMEFunction; }
bool hasArguments() const { return flags.hasArguments; }
@@ -168,20 +165,12 @@ public:
bool isCloned() const { return flags.isCloned; }
bool isConstructor() const { return flags.isConstructor; }
- bool hasOverride() const { return flags.type != Flags::ValueTypeVirtualType &&
- !(flags.hasAccessors) &&
+ bool hasOverride() const { return !(flags.hasAccessors) &&
overrideIndex >= 0; }
bool hasRevision() const { return !(flags.hasAccessors) && revision != 0; }
bool isFullyResolved() const { return !flags.notFullyResolved; }
- // Returns -1 if not a value type virtual property
- inline int getValueTypeCoreIndex() const;
-
- // Returns the "encoded" index for use with bindings. Encoding is:
- // coreIndex | ((valueTypeCoreIndex + 1) << 16)
- inline QQmlPropertyIndex encodedIndex() const;
-
union {
int propType; // When !NotFullyResolved
const char *propTypeName; // When NotFullyResolved
@@ -198,18 +187,9 @@ public:
qint16 revision;
qint16 metaObjectOffset;
- union {
- struct { // When IsValueTypeVirtual
- quint16 valueTypePropType; // The QVariant::Type of access property on the value
- // type proxy object
- quint16 valueTypeCoreIndex; // The prop index of the access property on the value
- // type proxy object
- };
-
- struct { // When !IsValueTypeVirtual
- uint overrideIndexIsProperty : 1;
- signed int overrideIndex : 31;
- };
+ struct { // When !IsValueTypeVirtual
+ uint overrideIndexIsProperty : 1;
+ signed int overrideIndex : 31;
};
};
struct { // When HasAccessors
@@ -218,8 +198,6 @@ public:
};
int coreIndex;
- Flags valueTypeFlags; // flags of the access property on the value type proxy
- // object
private:
friend class QQmlPropertyData;
friend class QQmlPropertyCache;
@@ -619,21 +597,7 @@ bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
propType == other.propType &&
coreIndex == other.coreIndex &&
notifyIndex == other.notifyIndex &&
- revision == other.revision &&
- (!isValueTypeVirtual() ||
- (valueTypeCoreIndex == other.valueTypeCoreIndex &&
- valueTypePropType == other.valueTypePropType));
-}
-
-int QQmlPropertyRawData::getValueTypeCoreIndex() const
-{
- return isValueTypeVirtual()?valueTypeCoreIndex:-1;
-}
-
-QQmlPropertyIndex QQmlPropertyRawData::encodedIndex() const
-{
- return isValueTypeVirtual() ? QQmlPropertyIndex(coreIndex, valueTypeCoreIndex)
- : QQmlPropertyIndex(coreIndex);
+ revision == other.revision;
}
inline QQmlPropertyData *QQmlPropertyCache::ensureResolved(QQmlPropertyData *p) const
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index a1bf692f19..3ad53aa3fc 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -431,8 +431,6 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
const QQmlPropertyData *pd = r->d()->propertyCache->property(name, 0, 0);
if (!pd)
return;
- QMetaProperty property = metaObject->property(pd->coreIndex);
- Q_ASSERT(property.isValid());
if (reference) {
QV4::ScopedFunctionObject f(scope, value);
@@ -449,25 +447,23 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
QQmlPropertyData cacheData;
cacheData.setWritable(true);
- cacheData.setAsValueTypeVirtual();
cacheData.propType = writeBackPropertyType;
cacheData.coreIndex = reference->d()->property;
- cacheData.valueTypeCoreIndex = pd->coreIndex;
- cacheData.valueTypePropType = property.userType();
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
bindingFunction->initBindingLocation();
QQmlBinding *newBinding = QQmlBinding::create(&cacheData, value, reference->d()->object, context);
- newBinding->setTarget(reference->d()->object, cacheData);
+ newBinding->setTarget(reference->d()->object, cacheData, pd);
QQmlPropertyPrivate::setBinding(newBinding);
return;
} else {
QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyIndex(reference->d()->property, pd->coreIndex));
-
}
}
+ QMetaProperty property = metaObject->property(pd->coreIndex);
+ Q_ASSERT(property.isValid());
QVariant v = v4->toVariant(value, property.userType());