diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2016-08-03 16:17:19 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2016-08-09 08:06:16 +0000 |
commit | 107a52b8a7019b66b4cb3279e7bf070d5b57c2e0 (patch) | |
tree | c633860d4345d6629fa066d56b99fe9335dba474 /src | |
parent | c3cbbf362c769b065fd0586b0510d043cbae92a4 (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.cpp | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmlbinding.cpp | 117 | ||||
-rw-r--r-- | src/qml/qml/qqmlbinding_p.h | 8 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 52 | ||||
-rw-r--r-- | src/qml/qml/qqmlproperty.cpp | 90 | ||||
-rw-r--r-- | src/qml/qml/qqmlproperty_p.h | 18 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 48 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper.cpp | 10 |
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()); |