diff options
Diffstat (limited to 'src/declarative/qml')
26 files changed, 460 insertions, 153 deletions
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index a2e2050..2e62a3b 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -10,6 +10,7 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlcontext.cpp \ qml/qmlcustomparser.cpp \ qml/qmlpropertyvaluesource.cpp \ + qml/qmlpropertyvalueinterceptor.cpp \ qml/qmlproxymetaobject.cpp \ qml/qmlvme.cpp \ qml/qmlcompiler.cpp \ @@ -59,6 +60,7 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlcustomparser_p.h \ qml/qmlcustomparser_p_p.h \ qml/qmlpropertyvaluesource.h \ + qml/qmlpropertyvalueinterceptor.h \ qml/qmlboundsignal_p.h \ qml/qmlparserstatus.h \ qml/qmlproxymetaobject_p.h \ diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 58ce02c..2435c40 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -97,7 +97,7 @@ QmlMetaProperty QmlBinding::property() const return d->bindingData()->property; } -void QmlBinding::update() +void QmlBinding::update(QmlMetaProperty::WriteFlags flags) { Q_D(QmlBinding); @@ -119,17 +119,17 @@ void QmlBinding::update() int idx = data->property.coreIndex(); Q_ASSERT(idx != -1); - void *a[1]; + QmlBinding *t = this; - a[0] = (void *)&t; - QMetaObject::metacall(data->property.object(), + int status = -1; + void *a[] = { &t, 0, &status, &flags }; + QMetaObject::metacall(data->property.object(), QMetaObject::WriteProperty, idx, a); } else { - QVariant value = this->value(); - data->property.write(value, QmlMetaProperty::Binding); + data->property.write(value, flags); } data->updating = false; @@ -146,17 +146,17 @@ void QmlBinding::valueChanged() update(); } -void QmlBinding::setEnabled(bool e) +void QmlBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) { Q_D(QmlBinding); d->bindingData()->enabled = e; setTrackChange(e); - QmlAbstractBinding::setEnabled(e); + QmlAbstractBinding::setEnabled(e, flags); if (e) { addToObject(d->bindingData()->property.object()); - update(); + update(flags); } else { removeFromObject(); } @@ -231,7 +231,7 @@ QString QmlAbstractBinding::expression() const return QLatin1String("<Unknown>"); } -void QmlAbstractBinding::setEnabled(bool e) +void QmlAbstractBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags) { if (e) m_mePtr = 0; } diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h index 1c0ccf1..6a3e92a 100644 --- a/src/declarative/qml/qmlbinding.h +++ b/src/declarative/qml/qmlbinding.h @@ -47,6 +47,7 @@ #include <QtDeclarative/qml.h> #include <QtDeclarative/qmlpropertyvaluesource.h> #include <QtDeclarative/qmlexpression.h> +#include <QtCore/QMetaProperty> QT_BEGIN_HEADER @@ -62,10 +63,12 @@ public: virtual QString expression() const; - virtual void setEnabled(bool) = 0; + void setEnabled(bool e) { setEnabled(e, QmlMetaProperty::DontRemoveBinding); } + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags) = 0; virtual int propertyIndex() = 0; - virtual void update() = 0; + void update() { update(QmlMetaProperty::DontRemoveBinding); } + virtual void update(QmlMetaProperty::WriteFlags) = 0; void addToObject(QObject *); void removeFromObject(); @@ -100,12 +103,13 @@ public: bool enabled() const; // Inherited from QmlAbstractBinding - virtual void setEnabled(bool); + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); virtual int propertyIndex(); + virtual void update(QmlMetaProperty::WriteFlags flags); virtual QString expression() const; public Q_SLOTS: - void update(); + void update() { update(QmlMetaProperty::DontRemoveBinding); } protected: virtual void valueChanged(); diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp index e4ca358..6dc221e 100644 --- a/src/declarative/qml/qmlbindingoptimizations.cpp +++ b/src/declarative/qml/qmlbindingoptimizations.cpp @@ -69,16 +69,16 @@ QmlBinding_Id::~QmlBinding_Id() removeFromContext(); } -void QmlBinding_Id::setEnabled(bool e) +void QmlBinding_Id::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) { if (e) { addToObject(m_object); - update(); + update(flags); } else { removeFromObject(); } - QmlAbstractBinding::setEnabled(e); + QmlAbstractBinding::setEnabled(e, flags); } int QmlBinding_Id::propertyIndex() @@ -86,7 +86,7 @@ int QmlBinding_Id::propertyIndex() return m_propertyIdx; } -void QmlBinding_Id::update() +void QmlBinding_Id::update(QmlMetaProperty::WriteFlags flags) { QmlContextPrivate *ctxtPriv = static_cast<QmlContextPrivate *>(QObjectPrivate::get(context())); @@ -102,7 +102,8 @@ void QmlBinding_Id::update() } QObject *o = ctxtPriv->idValues[m_id].data(); - void *a[] = { &o, 0 }; + int status = -1; + void *a[] = { &o, 0, &status, &flags }; QMetaObject::metacall(m_object, QMetaObject::WriteProperty, m_propertyIdx, a); } @@ -123,7 +124,9 @@ void QmlBinding_Id::reset() removeFromContext(); QObject *o = 0; - void *a[] = { &o, 0 }; + int status = -1; + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding; + void *a[] = { &o, 0, &status, &flags }; QMetaObject::metacall(m_object, QMetaObject::WriteProperty, m_propertyIdx, a); } @@ -150,17 +153,17 @@ QmlBinding_ObjProperty::QmlBinding_ObjProperty(QObject *object, int propertyIdx, { } -void QmlBinding_ObjProperty::setEnabled(bool e) +void QmlBinding_ObjProperty::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) { m_enabled = e; if (e) { addToObject(m_object); - update(); + update(flags); } else { removeFromObject(); } - QmlAbstractBinding::setEnabled(e); + QmlAbstractBinding::setEnabled(e, flags); } int QmlBinding_ObjProperty::propertyIndex() @@ -168,21 +171,24 @@ int QmlBinding_ObjProperty::propertyIndex() return m_propertyIdx; } -void QmlBinding_ObjProperty::update() +void QmlBinding_ObjProperty::update(QmlMetaProperty::WriteFlags flags) { if (!m_enabled) return; QObject *value = 0; - void *a[] = { &value, 0 }; + int status = -1; + void *ra[] = { &value, 0, &status }; // Read QMetaObject::metacall(m_context, QMetaObject::ReadProperty, - m_contextIdx, a); + m_contextIdx, ra); + + void *wa[] = { &value, 0, &status, &flags }; // Write QMetaObject::metacall(m_object, QMetaObject::WriteProperty, - m_propertyIdx, a); + m_propertyIdx, wa); // Connect notify if needed. Only need to connect once, so we set // m_notifyIdx back to -1 afterwards diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h index 4862007..d0a4df4 100644 --- a/src/declarative/qml/qmlbindingoptimizations_p.h +++ b/src/declarative/qml/qmlbindingoptimizations_p.h @@ -69,9 +69,9 @@ public: virtual ~QmlBinding_Id(); // Inherited from QmlAbstractBinding - virtual void setEnabled(bool); + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); virtual int propertyIndex(); - virtual void update(); + virtual void update(QmlMetaProperty::WriteFlags flags); void reset(); @@ -96,11 +96,12 @@ public: QObject *context, int contextIdx, int notifyIdx); // Inherited from QmlAbstractBinding - virtual void setEnabled(bool); + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); virtual int propertyIndex(); + virtual void update(QmlMetaProperty::WriteFlags flags); private Q_SLOTS: - virtual void update(); + void update() { update(QmlMetaProperty::DontRemoveBinding); } private: bool m_enabled; diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index d36b1c9..f33731c 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1531,6 +1531,24 @@ void QmlCompiler::genPropertyAssignment(QmlParser::Property *prop, store.assignValueSource.castValue = valueType->propertyValueSourceCast(); output->bytecode << store; + } else if (v->type == Value::ValueInterceptor) { + genObject(v->object); + + QmlInstruction store; + store.type = QmlInstruction::StoreValueInterceptor; + store.line = v->object->location.start.line; + if (valueTypeProperty) { + store.assignValueInterceptor.property = QmlMetaPropertyPrivate::saveValueType(valueTypeProperty->index, prop->index); + store.assignValueInterceptor.owner = 1; + } else { + store.assignValueInterceptor.property = + QmlMetaPropertyPrivate::saveProperty(prop->index); + store.assignValueInterceptor.owner = 0; + } + QmlType *valueType = QmlMetaType::qmlType(v->object->metatype); + store.assignValueInterceptor.castValue = valueType->propertyValueInterceptorCast(); + output->bytecode << store; + } else if (v->type == Value::PropertyBinding) { genBindingAssignment(v, prop, obj, valueTypeProperty); @@ -1635,7 +1653,7 @@ bool QmlCompiler::buildAttachedProperty(QmlParser::Property *prop, // font.pointSize: 12 // font.family: "Helvetica" // } -// font is a nested property. size and family are not. +// font is a nested property. pointSize and family are not. bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, QmlParser::Object *obj, const BindingContext &ctxt) @@ -1648,7 +1666,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine)); if (ep->valueTypes[prop->type]) { COMPILE_CHECK(buildValueTypeProperty(ep->valueTypes[prop->type], - prop->value, ctxt.incr())); + prop->value, obj, ctxt.incr())); obj->addValueTypeProperty(prop); } else { COMPILE_EXCEPTION(prop, "Invalid property access"); @@ -1672,6 +1690,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, bool QmlCompiler::buildValueTypeProperty(QObject *type, QmlParser::Object *obj, + QmlParser::Object *baseObj, const BindingContext &ctxt) { if (obj->defaultProperty) @@ -1693,13 +1712,16 @@ bool QmlCompiler::buildValueTypeProperty(QObject *type, if (value->object) { bool isPropertyValue = output->types.at(value->object->type).type->propertyValueSourceCast() != -1; - if (!isPropertyValue) { + bool isPropertyInterceptor = output->types.at(value->object->type).type->propertyValueInterceptorCast() != -1; + if (!isPropertyValue && !isPropertyInterceptor) { COMPILE_EXCEPTION(prop, "Invalid property use"); } else { COMPILE_CHECK(buildObject(value->object, ctxt)); - value->type = Value::ValueSource; - } + if (isPropertyInterceptor && prop->parent->synthdata.isEmpty()) + buildDynamicMeta(baseObj, ForceCreation); + value->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor; + } } else if (value->value.isScript()) { // ### Check for writability BindingReference reference; @@ -1864,8 +1886,12 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, // Will be true if the assigned type inherits QmlPropertyValueSource bool isPropertyValue = false; - if (QmlType *valueType = QmlMetaType::qmlType(v->object->metatype)) + // Will be true if the assigned type inherits QmlPropertyValueInterceptor + bool isPropertyInterceptor = false; + if (QmlType *valueType = QmlMetaType::qmlType(v->object->metatype)) { isPropertyValue = valueType->propertyValueSourceCast() != -1; + isPropertyInterceptor = valueType->propertyValueInterceptorCast() != -1; + } // We want to raw metaObject here as the raw metaobject is the // actual property type before we applied any extensions that might @@ -1902,11 +1928,13 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, component->getDefaultProperty()->addValue(componentValue); v->object = component; COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt)); - } else if (isPropertyValue) { + } else if (isPropertyValue || isPropertyInterceptor) { // Assign as a property value source COMPILE_CHECK(buildObject(v->object, ctxt)); - v->type = Value::ValueSource; + if (isPropertyInterceptor && prop->parent->synthdata.isEmpty()) + buildDynamicMeta(prop->parent, ForceCreation); + v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor; } else { COMPILE_EXCEPTION(v->object, "Cannot assign object to property"); } @@ -2012,7 +2040,8 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) Q_ASSERT(obj); Q_ASSERT(obj->metatype); - if (obj->dynamicProperties.isEmpty() && + if (mode != ForceCreation && + obj->dynamicProperties.isEmpty() && obj->dynamicSignals.isEmpty() && obj->dynamicSlots.isEmpty()) return true; diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 1d27342..3a35d58 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -191,6 +191,7 @@ private: const BindingContext &ctxt); bool buildValueTypeProperty(QObject *type, QmlParser::Object *obj, + QmlParser::Object *baseObj, const BindingContext &ctxt); bool buildListProperty(QmlParser::Property *prop, QmlParser::Object *obj, @@ -209,7 +210,7 @@ private: bool doesPropertyExist(QmlParser::Property *prop, QmlParser::Object *obj); bool testLiteralAssignment(const QMetaProperty &prop, QmlParser::Value *value); - enum DynamicMetaMode { IgnoreAliases, ResolveAliases }; + enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation }; bool mergeDynamicMetaProperties(QmlParser::Object *obj); bool buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode); bool checkDynamicMeta(QmlParser::Object *obj); diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index 5b1cbeb..9a761b2 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -573,7 +573,7 @@ void QmlComponentPrivate::completeCreate() bindValues.at(ii); for (int jj = 0; jj < bv.count; ++jj) { if(bv.at(jj)) - bv.at(jj)->setEnabled(true); + bv.at(jj)->setEnabled(true, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } QmlEnginePrivate::clear(bv); } diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index 18439f4..a465445 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -149,6 +149,9 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx) case QmlInstruction::StoreValueSource: qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t" << instr->assignValueSource.castValue; break; + case QmlInstruction::StoreValueInterceptor: + qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_INTERCEPTOR\t" << instr->assignValueInterceptor.property << "\t" << instr->assignValueInterceptor.castValue; + break; case QmlInstruction::BeginObject: qWarning() << idx << "\t" << line << "\t" << "BEGIN\t\t\t" << instr->begin.castValue; break; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 0da40c3..5265d42 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -130,6 +130,7 @@ public: StoreIdOptBinding, /* assignIdOptBinding */ StoreObjPropBinding, /* assignObjPropBinding */ StoreValueSource, /* assignValueSource */ + StoreValueInterceptor, /* assignValueInterceptor */ BeginObject, /* begin */ @@ -190,6 +191,11 @@ public: } assignValueSource; struct { int property; + int owner; + int castValue; + } assignValueInterceptor; //### merge with above + struct { + int property; int value; short context; short owner; diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index a43f6c3..8643301 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -559,17 +559,17 @@ QmlAbstractBinding *QmlMetaProperty::binding() const is assumed by the caller. */ QmlAbstractBinding * -QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const +QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags) const { if (!isProperty() || (type() & Attached) || !d->object) return 0; - return d->setBinding(d->object, d->core, newBinding); + return d->setBinding(d->object, d->core, newBinding, flags); } QmlAbstractBinding * QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data &core, - QmlAbstractBinding *newBinding) + QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags) { QmlDeclarativeData *data = QmlDeclarativeData::get(object, 0 != newBinding); @@ -581,7 +581,7 @@ QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data binding->setEnabled(false); if (newBinding) - newBinding->setEnabled(true); + newBinding->setEnabled(true, flags); return binding; // ### QmlAbstractBinding; } @@ -591,7 +591,7 @@ QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data } if (newBinding) - newBinding->setEnabled(true); + newBinding->setEnabled(true, flags); return 0; } @@ -728,11 +728,52 @@ QVariant QmlMetaPropertyPrivate::readValueProperty() } } +//### +//writeEnumProperty MIRRORS the relelvant bit of QMetaProperty::write AND MUST BE KEPT IN SYNC! +//### +bool QmlMetaPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags) +{ + if (!object || !prop.isWritable()) + return false; + + QVariant v = value; + uint t = QVariant::Invalid; + if (prop.isEnumType()) { + QMetaEnum menum = prop.enumerator(); + if (v.type() == QVariant::String +#ifdef QT3_SUPPORT + || v.type() == QVariant::CString +#endif + ) { + if (prop.isFlagType()) + v = QVariant(menum.keysToValue(value.toByteArray())); + else + v = QVariant(menum.keyToValue(value.toByteArray())); + } else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) { + int enumMetaTypeId = QMetaType::type(QByteArray(menum.scope()) + "::" + menum.name()); + if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData()) + return false; + v = QVariant(*reinterpret_cast<const int *>(v.constData())); + } + v.convert(QVariant::Int); + } + + // the status variable is changed by qt_metacall to indicate what it did + // this feature is currently only used by QtDBus and should not be depended + // upon. Don't change it without looking into QDBusAbstractInterface first + // -1 (unchanged): normal qt_metacall, result stored in argv[0] + // changed: result stored directly in value, return the value of status + int status = -1; + void *argv[] = { v.data(), &v, &status, &flags }; + QMetaObject::metacall(object, QMetaObject::WriteProperty, idx, argv); + return status; +} + void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, - QmlMetaProperty::WriteSource source) + QmlMetaProperty::WriteFlags flags) { // Remove any existing bindings on this property - if (source != QmlMetaProperty::Binding) + if (!(flags & QmlMetaProperty::DontRemoveBinding)) delete q->setBinding(0); uint type = q->type(); @@ -752,22 +793,23 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, QmlPropertyCache::Data data = core; data.coreIndex = valueTypeCoreIdx; data.propType = valueTypePropType; - write(writeBack, data, value, context); + write(writeBack, data, value, context, flags); - writeBack->write(object, core.coreIndex); + writeBack->write(object, core.coreIndex, flags); if (!ep) delete writeBack; } else { - write(object, core, value, context); + write(object, core, value, context, flags); } } void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data &property, - const QVariant &value, QmlContext *context) + const QVariant &value, QmlContext *context, QmlMetaProperty::WriteFlags flags) { int coreIdx = property.coreIndex; + int status = -1; //for dbus if (property.flags & QmlPropertyCache::Data::IsEnumType) { QMetaProperty prop = object->metaObject()->property(property.coreIndex); @@ -779,7 +821,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data if (qFuzzyCompare(fractional, (double)0.0)) v.convert(QVariant::Int); } - prop.write(object, v); + writeEnumProperty(prop, coreIdx, object, v, flags); return; } @@ -812,14 +854,12 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data } else if (vt == t) { - void *a[1]; - a[0] = (void *)value.constData(); + void *a[] = { (void *)value.constData(), 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if (qMetaTypeId<QVariant>() == t) { - void *a[1]; - a[0] = (void *)&value; + void *a[] = { (void *)&value, 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if (property.flags & QmlPropertyCache::Data::IsQObjectDerived) { @@ -843,7 +883,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data if (valMo || !o) { - void *args[] = { &o, 0 }; + void *args[] = { &o, 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args); @@ -909,16 +949,14 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data QVariant v = value; if (v.convert((QVariant::Type)t)) { - void *a[1]; - a[0] = (void *)v.constData(); + void *a[] = { (void *)v.constData(), 0, &status, &flags}; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if ((uint)t >= QVariant::UserType && vt == QVariant::String) { QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t); if (con) { QVariant v = con(value.toString()); if (v.userType() == t) { - void *a[1]; - a[0] = (void *)v.constData(); + void *a[] = { (void *)v.constData(), 0, &status, &flags}; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } } @@ -931,17 +969,17 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data */ void QmlMetaProperty::write(const QVariant &value) const { - write(value, Other); + write(value, 0); } -void QmlMetaProperty::write(const QVariant &value, WriteSource source) const +void QmlMetaProperty::write(const QVariant &value, QmlMetaProperty::WriteFlags flags) const { if (!d->object) return; if (type() & Property && d->core.isValid()) { - d->writeValueProperty(value, source); + d->writeValueProperty(value, flags); } } diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h index 8c34ece..b0ae28c 100644 --- a/src/declarative/qml/qmlmetaproperty.h +++ b/src/declarative/qml/qmlmetaproperty.h @@ -88,8 +88,9 @@ public: QVariant read() const; void write(const QVariant &) const; - enum WriteSource { Animation, Binding, Other }; - void write(const QVariant &, WriteSource) const; + enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02 }; + Q_DECLARE_FLAGS(WriteFlags, WriteFlag) + void write(const QVariant &, QmlMetaProperty::WriteFlags) const; bool hasChangedNotifier() const; bool needsChangedNotifier() const; @@ -126,7 +127,8 @@ public: QMetaProperty property() const; QmlAbstractBinding *binding() const; - QmlAbstractBinding *setBinding(QmlAbstractBinding *) const; + QmlAbstractBinding *setBinding(QmlAbstractBinding *, + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding) const; QmlExpression *signalExpression() const; QmlExpression *setSignalExpression(QmlExpression *) const; @@ -139,6 +141,7 @@ private: QmlMetaPropertyPrivate *d; }; typedef QList<QmlMetaProperty> QmlMetaProperties; + Q_DECLARE_OPERATORS_FOR_FLAGS(QmlMetaProperty::WriteFlags) QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 4576b71..b74aa2d 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -97,9 +97,12 @@ public: QmlMetaProperty::PropertyCategory propertyCategory() const; QVariant readValueProperty(); - void writeValueProperty(const QVariant &, QmlMetaProperty::WriteSource); - static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *); - static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *); + void writeValueProperty(const QVariant &, QmlMetaProperty::WriteFlags); + static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags); + static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *, + QmlMetaProperty::WriteFlags flags = 0); + static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *, + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding); static quint32 saveValueType(int, int); static quint32 saveProperty(int); diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index c40232f..5198f9f 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -128,6 +128,7 @@ public: const QMetaObject *m_attachedPropertiesType; int m_parserStatusCast; int m_propertyValueSourceCast; + int m_propertyValueInterceptorCast; QmlPrivate::CreateFunc m_extFunc; const QMetaObject *m_extMetaObject; int m_index; @@ -140,8 +141,8 @@ public: QmlTypePrivate::QmlTypePrivate() : m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_qmlListId(0), m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), - m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_extFunc(0), m_extMetaObject(0), - m_index(-1), m_customParser(0), m_isSetup(false) + m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1), + m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false) { } @@ -169,7 +170,8 @@ QmlType::QmlType(int type, int listType, int qmlListType, const QMetaObject *metaObject, QmlAttachedPropertiesFunc attachedPropertiesFunc, const QMetaObject *attachedType, - int parserStatusCast, int propertyValueSourceCast, QmlPrivate::CreateFunc extFunc, + int parserStatusCast, int propertyValueSourceCast, int propertyValueInterceptorCast, + QmlPrivate::CreateFunc extFunc, const QMetaObject *extMetaObject, int index, QmlCustomParser *customParser) : d(new QmlTypePrivate) @@ -187,6 +189,7 @@ QmlType::QmlType(int type, int listType, int qmlListType, d->m_attachedPropertiesType = attachedType; d->m_parserStatusCast = parserStatusCast; d->m_propertyValueSourceCast = propertyValueSourceCast; + d->m_propertyValueInterceptorCast = propertyValueInterceptorCast; d->m_extFunc = extFunc; d->m_index = index; d->m_customParser = customParser; @@ -412,6 +415,11 @@ int QmlType::propertyValueSourceCast() const return d->m_propertyValueSourceCast; } +int QmlType::propertyValueInterceptorCast() const +{ + return d->m_propertyValueInterceptorCast; +} + QVariant QmlType::fromObject(QObject *obj) const { QVariant rv; @@ -467,7 +475,7 @@ int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id, int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func, const char *uri, int version_maj, int version_min_from, int version_min_to, const char *cname, const QMetaObject *mo, QmlAttachedPropertiesFunc attach, const QMetaObject *attachMo, - int pStatus, int object, int valueSource, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser) + int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser) { Q_UNUSED(object); @@ -492,7 +500,7 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId, func, name, version_maj, version_min_from, version_min_to, mo, attach, attachMo, pStatus, - valueSource, extFunc, extmo, index, parser); + valueSource, valueInterceptor, extFunc, extmo, index, parser); data->types.append(type); data->idToType.insert(type->typeId(), type); @@ -539,6 +547,17 @@ int QmlMetaType::qmlPropertyValueSourceCast(int userType) return -1; } +int QmlMetaType::qmlPropertyValueInterceptorCast(int userType) +{ + QReadLocker lock(metaTypeDataLock()); + QmlMetaTypeData *data = metaTypeData(); + QmlType *type = data->idToType.value(userType); + if (type && type->typeId() == userType) + return type->propertyValueInterceptorCast(); + else + return -1; +} + QObject *QmlMetaType::toQObject(const QVariant &v) { if (!isObject(v.userType())) diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h index 02c817d..42c278c 100644 --- a/src/declarative/qml/qmlmetatype.h +++ b/src/declarative/qml/qmlmetatype.h @@ -48,6 +48,7 @@ #include <QtDeclarative/qmlprivate.h> #include <QtDeclarative/qmlparserstatus.h> #include <QtDeclarative/qmlpropertyvaluesource.h> +#include <QtDeclarative/qmlpropertyvalueinterceptor.h> QT_BEGIN_HEADER @@ -60,7 +61,7 @@ class QmlCustomParser; class Q_DECLARATIVE_EXPORT QmlMetaType { public: - static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin_from, int vmin_to, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); + static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin_from, int vmin_to, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *); static bool copy(int type, void *data, const void *copy = 0); @@ -80,6 +81,7 @@ public: static QObject *toQObject(const QVariant &); static int qmlParserStatusCast(int); static int qmlPropertyValueSourceCast(int); + static int qmlPropertyValueInterceptorCast(int); static int listType(int); static bool clear(const QVariant &); static bool append(const QVariant &, const QVariant &); @@ -146,6 +148,7 @@ public: QVariant fromObject(QObject *) const; const char *interfaceIId() const; int propertyValueSourceCast() const; + int propertyValueInterceptorCast() const; int index() const; private: @@ -153,7 +156,7 @@ private: friend class QmlTypePrivate; friend class QmlMetaTypeData; QmlType(int, int, int, QmlPrivate::Func, const char *, int); - QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); + QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); ~QmlType(); QmlTypePrivate *d; @@ -176,6 +179,7 @@ int qmlRegisterType(const char *typeName) QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(), QmlPrivate::StaticCastSelector<T,QObject>::cast(), QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(), 0, 0, 0); } @@ -196,7 +200,8 @@ int qmlRegisterType(const char *uri, int version_maj, int version_min_from, int QmlPrivate::attachedPropertiesMetaObject<T>(), QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(), QmlPrivate::StaticCastSelector<T,QObject>::cast(), - QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(), 0, 0, 0); } @@ -224,6 +229,7 @@ int qmlRegisterExtendedType(const char *typeName) QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(), QmlPrivate::StaticCastSelector<T,QObject>::cast(), QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(), &QmlPrivate::CreateParent<E>::create, &E::staticMetaObject, 0); } @@ -253,6 +259,7 @@ int qmlRegisterExtendedType(const char *uri, int version_maj, int version_min_fr QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(), QmlPrivate::StaticCastSelector<T,QObject>::cast(), QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(), &QmlPrivate::CreateParent<E>::create, &E::staticMetaObject, 0); } @@ -290,6 +297,7 @@ int qmlRegisterCustomType(const char *uri, int version_maj, int version_min_from QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(), QmlPrivate::StaticCastSelector<T,QObject>::cast(), QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(), 0, 0, parser); } diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 8c46939..bae263a 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -282,6 +282,9 @@ void QmlParser::Value::dump(int indent) const case Value::ValueSource: type = "ValueSource"; break; + case Value::ValueInterceptor: + type = "ValueInterceptor"; + break; case Value::CreatedObject: type = "CreatedObject"; break; diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index d05cc73..88d7d77 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -275,6 +275,8 @@ namespace QmlParser PropertyBinding, // This is used as a QmlPropertyValueSource assignment ValueSource, + // This is used as a QmlPropertyValueInterceptor assignment + ValueInterceptor, // This is used as a property QObject assignment CreatedObject, // This is used as a signal object assignment diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index f1b1219..91b0c53 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -132,7 +132,7 @@ QmlPropertyCache::Data::Data() { } -bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data::Data &other) +bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data &other) { return flags == other.flags && propType == other.propType && diff --git a/src/declarative/qml/qmlpropertyvalueinterceptor.cpp b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp new file mode 100644 index 0000000..86905e6 --- /dev/null +++ b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlpropertyvalueinterceptor.h" +#include "qml.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QmlPropertyValueInterceptor + \brief The QmlPropertyValueInterceptor class is inherited by property interceptors such as Behavior. + + This class intercepts property writes, allowing for custom handling. For example, Behavior uses this + interception to provide a default animation for all changes to a property's value. + */ + +/*! + Constructs a QmlPropertyValueInterceptor. +*/ +QmlPropertyValueInterceptor::QmlPropertyValueInterceptor() +{ +} + +QmlPropertyValueInterceptor::~QmlPropertyValueInterceptor() +{ +} + +/*! + \fn void QmlPropertyValueInterceptor::setTarget(const QmlMetaProperty &property) + Set the target \a property for the value interceptor. This method will + be called by the QML engine when assigning a value interceptor. +*/ + +/*! + \fn void QmlPropertyValueInterceptor::write(const QVariant &value) + This method will be called when a new \a value is assigned to the property being intercepted. +*/ + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlpropertyvalueinterceptor.h b/src/declarative/qml/qmlpropertyvalueinterceptor.h new file mode 100644 index 0000000..678c12c --- /dev/null +++ b/src/declarative/qml/qmlpropertyvalueinterceptor.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLPROPERTYVALUEINTERCEPTOR_H +#define QMLPROPERTYVALUEINTERCEPTOR_H + +#include <QtCore/qobject.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QmlMetaProperty; +class Q_DECLARATIVE_EXPORT QmlPropertyValueInterceptor +{ +public: + QmlPropertyValueInterceptor(); + virtual ~QmlPropertyValueInterceptor(); + virtual void setTarget(const QmlMetaProperty &property) = 0; + virtual void write(const QVariant &value) = 0; +}; +Q_DECLARE_INTERFACE(QmlPropertyValueInterceptor, "com.trolltech.qml.QmlPropertyValueInterceptor") + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMLPROPERTYVALUEINTERCEPTOR_H diff --git a/src/declarative/qml/qmlvaluetype.cpp b/src/declarative/qml/qmlvaluetype.cpp index 4ae2070..84c9ecb 100644 --- a/src/declarative/qml/qmlvaluetype.cpp +++ b/src/declarative/qml/qmlvaluetype.cpp @@ -97,9 +97,10 @@ void QmlPointFValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlPointFValueType::write(QObject *obj, int idx) +void QmlPointFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &point, 0 }; + int status = -1; + void *a[] = { &point, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -144,9 +145,10 @@ void QmlPointValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlPointValueType::write(QObject *obj, int idx) +void QmlPointValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &point, 0 }; + int status = -1; + void *a[] = { &point, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -191,9 +193,10 @@ void QmlSizeFValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlSizeFValueType::write(QObject *obj, int idx) +void QmlSizeFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &size, 0 }; + int status = -1; + void *a[] = { &size, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -238,9 +241,10 @@ void QmlSizeValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlSizeValueType::write(QObject *obj, int idx) +void QmlSizeValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &size, 0 }; + int status = -1; + void *a[] = { &size, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -285,9 +289,10 @@ void QmlRectFValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlRectFValueType::write(QObject *obj, int idx) +void QmlRectFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &rect, 0 }; + int status = -1; + void *a[] = { &rect, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -352,9 +357,10 @@ void QmlRectValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlRectValueType::write(QObject *obj, int idx) +void QmlRectValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &rect, 0 }; + int status = -1; + void *a[] = { &rect, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -419,9 +425,10 @@ void QmlVector3DValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlVector3DValueType::write(QObject *obj, int idx) +void QmlVector3DValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &vector, 0 }; + int status = -1; + void *a[] = { &vector, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -476,9 +483,10 @@ void QmlFontValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlFontValueType::write(QObject *obj, int idx) +void QmlFontValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &font, 0 }; + int status = -1; + void *a[] = { &font, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } diff --git a/src/declarative/qml/qmlvaluetype_p.h b/src/declarative/qml/qmlvaluetype_p.h index da5e972..d3adf1e 100644 --- a/src/declarative/qml/qmlvaluetype_p.h +++ b/src/declarative/qml/qmlvaluetype_p.h @@ -58,6 +58,7 @@ #include <QtCore/qvariant.h> #include <QtGui/qvector3d.h> #include <QtGui/qfont.h> +#include <QmlMetaProperty> QT_BEGIN_NAMESPACE @@ -67,7 +68,7 @@ class QmlValueType : public QObject public: QmlValueType(QObject *parent = 0); virtual void read(QObject *, int) = 0; - virtual void write(QObject *, int) = 0; + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags flags) = 0; virtual QVariant value() = 0; virtual void setValue(QVariant) = 0; }; @@ -92,7 +93,7 @@ public: QmlPointFValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -114,7 +115,7 @@ public: QmlPointValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -136,7 +137,7 @@ public: QmlSizeFValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -158,7 +159,7 @@ public: QmlSizeValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -182,7 +183,7 @@ public: QmlRectFValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -211,7 +212,7 @@ public: QmlRectValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -239,7 +240,7 @@ public: QmlVector3DValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -267,7 +268,7 @@ public: QmlFontValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp index 6fd674a..6a7bdeb 100644 --- a/src/declarative/qml/qmlvaluetypescriptclass.cpp +++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp @@ -132,7 +132,7 @@ void QmlValueTypeScriptClass::setProperty(QScriptValue &object, ref.type->read(ref.object, ref.property); QMetaProperty p = ref.type->metaObject()->property(id); p.write(ref.type, v); - ref.type->write(ref.object, ref.property); + ref.type->write(ref.object, ref.property, 0); } QVariant QmlValueTypeScriptClass::toVariant(const QScriptValue &val) diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index a057f11..d4921b6 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -155,6 +155,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlEnginePrivate *ep = QmlEnginePrivate::get(ctxt->engine()); QmlContextPrivate *cp = (QmlContextPrivate *)QObjectPrivate::get(ctxt); + int status = -1; //for dbus + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::BypassInterceptor; + for (int ii = start; !isError() && ii < (start + count); ++ii) { QmlInstruction &instr = comp->bytecode[ii]; @@ -275,10 +278,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreVariant: { QObject *target = stack.top(); - void *a[1]; // XXX - can be more efficient QVariant v = QmlStringConverters::variantFromString(primitives.at(instr.storeString.value)); - a[0] = (void *)&v; + void *a[] = { &v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeString.propertyIndex, a); } @@ -287,8 +289,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreString: { QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&primitives.at(instr.storeString.value); + void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeString.propertyIndex, a); } @@ -297,9 +298,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreUrl: { QObject *target = stack.top(); - void *a[1]; QUrl u(primitives.at(instr.storeUrl.value)); - a[0] = (void *)&u; + void *a[] = { &u, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeUrl.propertyIndex, a); } @@ -309,8 +309,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, { QObject *target = stack.top(); float f = instr.storeFloat.value; - void *a[1]; - a[0] = &f; + void *a[] = { &f, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeFloat.propertyIndex, a); } @@ -320,8 +319,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, { QObject *target = stack.top(); double d = instr.storeDouble.value; - void *a[1]; - a[0] = &d; + void *a[] = { &d, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDouble.propertyIndex, a); } @@ -330,8 +328,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreBool: { QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&instr.storeBool.value; + void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeBool.propertyIndex, a); } @@ -340,8 +337,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreInteger: { QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&instr.storeInteger.value; + void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeInteger.propertyIndex, a); } @@ -350,9 +346,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreColor: { QObject *target = stack.top(); - void *a[1]; QColor c = QColor::fromRgba(instr.storeColor.value); - a[0] = (void *)&c; + void *a[] = { &c, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeColor.propertyIndex, a); } @@ -361,9 +356,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreDate: { QObject *target = stack.top(); - void *a[1]; QDate d = QDate::fromJulianDay(instr.storeDate.value); - a[0] = (void *)&d; + void *a[] = { &d, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDate.propertyIndex, a); } @@ -372,13 +366,12 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreTime: { QObject *target = stack.top(); - void *a[1]; QTime t; t.setHMS(intData.at(instr.storeTime.valueIndex), intData.at(instr.storeTime.valueIndex+1), intData.at(instr.storeTime.valueIndex+2), intData.at(instr.storeTime.valueIndex+3)); - a[0] = (void *)&t; + void *a[] = { &t, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeTime.propertyIndex, a); } @@ -387,14 +380,13 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreDateTime: { QObject *target = stack.top(); - void *a[1]; QTime t; t.setHMS(intData.at(instr.storeDateTime.valueIndex+1), intData.at(instr.storeDateTime.valueIndex+2), intData.at(instr.storeDateTime.valueIndex+3), intData.at(instr.storeDateTime.valueIndex+4)); QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t); - a[0] = (void *)&dt; + void *a[] = { &dt, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDateTime.propertyIndex, a); } @@ -403,10 +395,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StorePoint: { QObject *target = stack.top(); - void *a[1]; QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)).toPoint(); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -415,10 +406,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StorePointF: { QObject *target = stack.top(); - void *a[1]; QPointF p(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -427,10 +417,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreSize: { QObject *target = stack.top(); - void *a[1]; QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)).toSize(); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -439,10 +428,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreSizeF: { QObject *target = stack.top(); - void *a[1]; QSizeF s(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)); - a[0] = (void *)&s; + void *a[] = { &s, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -451,12 +439,11 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreRect: { QObject *target = stack.top(); - void *a[1]; QRect r = QRectF(floatData.at(instr.storeRect.valueIndex), floatData.at(instr.storeRect.valueIndex+1), floatData.at(instr.storeRect.valueIndex+2), floatData.at(instr.storeRect.valueIndex+3)).toRect(); - a[0] = (void *)&r; + void *a[] = { &r, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRect.propertyIndex, a); } @@ -465,12 +452,11 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreRectF: { QObject *target = stack.top(); - void *a[1]; QRectF r(floatData.at(instr.storeRect.valueIndex), floatData.at(instr.storeRect.valueIndex+1), floatData.at(instr.storeRect.valueIndex+2), floatData.at(instr.storeRect.valueIndex+3)); - a[0] = (void *)&r; + void *a[] = { &r, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRect.propertyIndex, a); } @@ -479,11 +465,10 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreVector3D: { QObject *target = stack.top(); - void *a[1]; QVector3D p(floatData.at(instr.storeVector3D.valueIndex), floatData.at(instr.storeVector3D.valueIndex+1), floatData.at(instr.storeVector3D.valueIndex+2)); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeVector3D.propertyIndex, a); } @@ -494,9 +479,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QObject *assignObj = stack.pop(); QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&assignObj; - + void *a[] = { (void *)&assignObj, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeObject.propertyIndex, a); } @@ -506,7 +489,6 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::AssignCustomType: { QObject *target = stack.top(); - void *a[1]; QmlCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex); const QString &primitive = primitives.at(data.index); QmlMetaType::StringConverter converter = @@ -518,7 +500,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) VME_EXCEPTION("Cannot assign value" << primitive << "to property" << prop.name()); - a[0] = (void *)v.data(); + void *a[] = { (void *)v.data(), 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.assignCustomType.propertyIndex, a); } @@ -655,6 +637,20 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, } break; + case QmlInstruction::StoreValueInterceptor: + { + QObject *obj = stack.pop(); + QmlPropertyValueInterceptor *vi = reinterpret_cast<QmlPropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.assignValueInterceptor.castValue); + QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner); + QmlMetaProperty prop; + prop.restore(instr.assignValueInterceptor.property, target, ctxt); + obj->setParent(target); + vi->setTarget(prop); + QmlVMEMetaObject *mo = static_cast<QmlVMEMetaObject *>((QMetaObject*)target->metaObject()); + mo->registerInterceptor(prop.coreIndex(), vi); + } + break; + case QmlInstruction::StoreObjectQmlList: { QObject *assign = stack.pop(); @@ -706,8 +702,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QObject *target = stack.top(); QVariant v = QVariant::fromValue(assign); - void *a[1]; - a[0] = (void *)&v; + void *a[] = { &v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeObject.propertyIndex, a); } @@ -726,8 +721,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, if (iid) { void *ptr = assign->qt_metacast(iid); if (ptr) { - void *a[1]; - a[0] = &ptr; + void *a[] = { &ptr, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIdx, a); @@ -849,7 +843,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlValueType *valueHandler = static_cast<QmlValueType *>(stack.pop()); QObject *target = stack.top(); - valueHandler->write(target, instr.fetchValue.property); + valueHandler->write(target, instr.fetchValue.property, QmlMetaProperty::BypassInterceptor); } break; diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp index a324795..e5acc51 100644 --- a/src/declarative/qml/qmlvmemetaobject.cpp +++ b/src/declarative/qml/qmlvmemetaobject.cpp @@ -100,6 +100,24 @@ QmlVMEMetaObject::~QmlVMEMetaObject() int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) { int id = _id; + if(c == QMetaObject::WriteProperty) { + int flags = *reinterpret_cast<int*>(a[3]); + if (!(flags & QmlMetaProperty::BypassInterceptor) + && !aInterceptors.isEmpty() + && aInterceptors.testBit(id)) { + QmlPropertyValueInterceptor *vi = interceptors.value(id); + if (id >= propOffset) { + id -= propOffset; + if (id < metaData->propertyCount) { + vi->write(QVariant(data[id].type(), a[0])); + return -1; + } + } else { + vi->write(QVariant(property(id).type(), a[0])); + return -1; + } + } + } if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) { if (id >= propOffset) { id -= propOffset; @@ -265,4 +283,13 @@ void QmlVMEMetaObject::listChanged(int id) activate(object, methodOffset + id, 0); } +void QmlVMEMetaObject::registerInterceptor(int index, QmlPropertyValueInterceptor *interceptor) +{ + if (aInterceptors.isEmpty()) + aInterceptors.resize(propertyCount() + metaData->propertyCount); + aInterceptors.setBit(index); + interceptors.insert(index, interceptor); +} + + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h index 1c26241..d376f4c 100644 --- a/src/declarative/qml/qmlvmemetaobject_p.h +++ b/src/declarative/qml/qmlvmemetaobject_p.h @@ -104,6 +104,8 @@ public: QmlRefCount * = 0); ~QmlVMEMetaObject(); + void registerInterceptor(int index, QmlPropertyValueInterceptor *interceptor); + protected: virtual int metaCall(QMetaObject::Call _c, int _id, void **_a); @@ -117,6 +119,8 @@ private: QVariant *data; QBitArray aConnected; + QBitArray aInterceptors; + QHash<int, QmlPropertyValueInterceptor*> interceptors; QAbstractDynamicMetaObject *parent; |