diff options
author | Martin Jones <martin.jones@nokia.com> | 2009-10-12 06:56:50 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2009-10-12 06:56:50 (GMT) |
commit | 7421702dd3202c21f3871171792476f0d2d50abe (patch) | |
tree | 5a45e20fd74e23cf0a4ad2aa1a80bd073fa51413 /src/declarative/qml | |
parent | 9094a6588de3a7264ec4647a24b94253a7609823 (diff) | |
parent | 949e21cdafeec0c0e4ac632ebbf21767479f04e5 (diff) | |
download | Qt-7421702dd3202c21f3871171792476f0d2d50abe.zip Qt-7421702dd3202c21f3871171792476f0d2d50abe.tar.gz Qt-7421702dd3202c21f3871171792476f0d2d50abe.tar.bz2 |
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Conflicts:
src/declarative/qml/qmlcompiler.cpp
Diffstat (limited to 'src/declarative/qml')
44 files changed, 704 insertions, 338 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/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index f3f9289..a0d749f 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE +DEFINE_BOOL_CONFIG_OPTION(qmlBasicScriptDump, QML_BASICSCRIPT_DUMP); + using namespace QmlJS; struct ScriptInstruction { @@ -367,7 +369,7 @@ bool QmlBasicScript::compile(const Expression &expression) { if (!expression.expression.asAST()) return false; - QByteArray expr = expression.expression.asScript().toLatin1(); + QByteArray expr = expression.expression.asScript().toUtf8(); const char *src = expr.constData(); QmlBasicScriptCompiler bsc; @@ -400,6 +402,8 @@ bool QmlBasicScript::compile(const Expression &expression) ::memcpy((char *)d->data(), bsc.data.constData(), bsc.data.count()); } + if (d && qmlBasicScriptDump()) + dump(); return d != 0; } @@ -649,7 +653,7 @@ QVariant QmlBasicScript::run(QmlContext *context, QObject *me) case ScriptInstruction::FetchRootConstant: { - QObject *obj = contextPrivate->defaultObjects.at(0); + QObject *obj = contextPrivate->defaultObjects.last(); stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); if (obj && instr.constant.notify != 0) diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 3a34f46..2435c40 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -67,8 +67,8 @@ QmlBindingPrivate::QmlBindingPrivate() { } -QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent) -: QmlExpression(ctxt, data, rc, obj, *new QmlBindingPrivate) +QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, const QUrl &url, int lineNumber, QObject *parent) +: QmlExpression(ctxt, data, rc, obj, url, lineNumber, *new QmlBindingPrivate) { setParent(parent); } @@ -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 e3a297c..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(); @@ -90,7 +93,8 @@ class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression, Q_OBJECT public: QmlBinding(const QString &, QObject *, QmlContext *, QObject *parent=0); - QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, QObject *parent); + QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, const QUrl &, int, + QObject *parent); ~QmlBinding(); void setTarget(const QmlMetaProperty &); @@ -99,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/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp index 8c3c355..7032a3b 100644 --- a/src/declarative/qml/qmlcompileddata.cpp +++ b/src/declarative/qml/qmlcompileddata.cpp @@ -150,7 +150,7 @@ int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l) } QmlCompiledData::QmlCompiledData() -: importCache(0) +: importCache(0), root(0) { } @@ -189,7 +189,7 @@ const QMetaObject *QmlCompiledData::TypeReference::metaObject() const return type->metaObject(); } else { Q_ASSERT(component); - return &static_cast<QmlComponentPrivate *>(QObjectPrivate::get(component))->cc->root; + return static_cast<QmlComponentPrivate *>(QObjectPrivate::get(component))->cc->root; } } diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 670e442..431f9f6 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -195,14 +195,14 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, QString string = v->value.asScript(); if (!prop.isWritable()) - COMPILE_EXCEPTION(v, "Invalid property assignment:" << QLatin1String(prop.name()) << "is a read-only property"); + COMPILE_EXCEPTION(v, "Invalid property assignment:" << QString::fromUtf8(prop.name()) << "is a read-only property"); if (prop.isEnumType()) { int value; if (prop.isFlagType()) { - value = prop.enumerator().keysToValue(string.toLatin1().constData()); + value = prop.enumerator().keysToValue(string.toUtf8().constData()); } else - value = prop.enumerator().keyToValue(string.toLatin1().constData()); + value = prop.enumerator().keyToValue(string.toUtf8().constData()); if (value == -1) COMPILE_EXCEPTION(v, "Invalid property assignment: unknown enumeration"); return true; @@ -336,9 +336,9 @@ void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop, if (prop.isEnumType()) { int value; if (prop.isFlagType()) { - value = prop.enumerator().keysToValue(string.toLatin1().constData()); + value = prop.enumerator().keysToValue(string.toUtf8().constData()); } else - value = prop.enumerator().keyToValue(string.toLatin1().constData()); + value = prop.enumerator().keyToValue(string.toUtf8().constData()); instr.type = QmlInstruction::StoreInteger; instr.storeInteger.propertyIndex = prop.propertyIndex(); @@ -595,7 +595,7 @@ bool QmlCompiler::compile(QmlEngine *engine, ref.ref = tref.unit; ref.ref->addref(); } - ref.className = parserRef->name.toLatin1(); + ref.className = parserRef->name.toUtf8(); out->types << ref; } @@ -647,7 +647,13 @@ void QmlCompiler::compileTree(Object *tree) output->importCache = output->imports.cache(engine); Q_ASSERT(tree->metatype); - static_cast<QMetaObject &>(output->root) = *tree->metaObject(); + + if (tree->metadata.isEmpty()) { + output->root = tree->metatype; + } else { + static_cast<QMetaObject &>(output->rootData) = *tree->metaObject(); + output->root = &output->rootData; + } if (!tree->metadata.isEmpty()) QmlEnginePrivate::get(engine)->registerCompositeType(output); } @@ -666,7 +672,7 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) obj->className = tr.className; // This object is a "Component" element - if (obj->metatype == &QmlComponent::staticMetaObject) { + if (tr.type && obj->metatype == &QmlComponent::staticMetaObject) { COMPILE_CHECK(buildComponent(obj, ctxt)); return true; } @@ -780,7 +786,9 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) void QmlCompiler::genObject(QmlParser::Object *obj) { - if (obj->metatype == &QmlComponent::staticMetaObject) { + const QmlCompiledData::TypeReference &tr = + output->types.at(obj->type); + if (tr.type && obj->metatype == &QmlComponent::staticMetaObject) { genComponent(obj); return; } @@ -833,6 +841,8 @@ void QmlCompiler::genObject(QmlParser::Object *obj) QmlInstruction script; script.type = QmlInstruction::StoreScript; script.line = 0; // ### + script.storeScript.fileName = output->indexForString(obj->scriptBlocksFile.at(ii)); + script.storeScript.lineNumber = obj->scriptBlocksLineNumber.at(ii); script.storeScript.value = output->indexForString(obj->scriptBlocks.at(ii)); output->bytecode << script; } @@ -1054,6 +1064,8 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj, bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) { QString scriptCode; + QString sourceUrl; + int lineNumber = 1; if (script->properties.count() == 1 && script->properties.begin().key() == QByteArray("source")) { @@ -1066,8 +1078,7 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) source->values.at(0)->object || !source->values.at(0)->value.isString()) COMPILE_EXCEPTION(source, "Invalid Script source value"); - QString sourceUrl = - output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString(); + sourceUrl = output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString(); for (int ii = 0; ii < unit->resources.count(); ++ii) { if (unit->resources.at(ii)->url == sourceUrl) { @@ -1079,10 +1090,14 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) } else if (!script->properties.isEmpty()) { COMPILE_EXCEPTION(*script->properties.begin(), "Properties cannot be set on Script block"); } else if (script->defaultProperty) { + sourceUrl = output->url.toString(); + QmlParser::Location currentLocation; for (int ii = 0; ii < script->defaultProperty->values.count(); ++ii) { Value *v = script->defaultProperty->values.at(ii); + if (lineNumber == 1) + lineNumber = v->location.start.line; if (v->object || !v->value.isString()) COMPILE_EXCEPTION(v, "Invalid Script block"); @@ -1105,8 +1120,11 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) } } - if (!scriptCode.isEmpty()) + if (!scriptCode.isEmpty()) { obj->scriptBlocks.append(scriptCode); + obj->scriptBlocksFile.append(sourceUrl); + obj->scriptBlocksLineNumber.append(lineNumber); + } return true; } @@ -1521,6 +1539,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); @@ -1625,7 +1661,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) @@ -1638,7 +1674,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"); @@ -1662,6 +1698,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, bool QmlCompiler::buildValueTypeProperty(QObject *type, QmlParser::Object *obj, + QmlParser::Object *baseObj, const BindingContext &ctxt) { if (obj->defaultProperty) @@ -1683,13 +1720,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; @@ -1854,8 +1894,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 @@ -1869,7 +1913,7 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, if (propertyMetaObject) { const QMetaObject *c = v->object->metatype; while(c) { - isAssignable |= (c == propertyMetaObject); + isAssignable |= (QmlMetaPropertyPrivate::equal(c, propertyMetaObject)); c = c->superClass(); } } @@ -1892,11 +1936,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"); } @@ -2002,7 +2048,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; @@ -2062,7 +2109,7 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) Q_ASSERT(tdata->status == QmlCompositeTypeData::Complete); QmlCompiledData *data = tdata->toCompiledComponent(engine); - customTypeName = data->root.className(); + customTypeName = data->root->className(); } else { customTypeName = qmltype->typeName(); } @@ -2226,28 +2273,44 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder, QStringList alias = astNodeToStringList(node); - if (alias.count() != 2) + if (alias.count() != 1 && alias.count() != 2) COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); if (!compileState.ids.contains(alias.at(0))) COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); Object *idObject = compileState.ids[alias.at(0)]; - int propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); - if (-1 == propIdx) - COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); + QByteArray typeName; + + int propIdx = -1; + bool writable = false; + if (alias.count() == 2) { + propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); + + if (-1 == propIdx) + COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); + + QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); + writable = aliasProperty.isWritable(); - QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); + if (aliasProperty.isEnumType()) + typeName = "int"; // Avoid introducing a dependency on the aliased metaobject + else + typeName = aliasProperty.typeName(); + } else { + typeName = idObject->metaObject()->className(); + typeName += "*"; + } data.append((const char *)&idObject->idIndex, sizeof(idObject->idIndex)); data.append((const char *)&propIdx, sizeof(propIdx)); builder.addSignal(prop.name + "Changed()"); QMetaPropertyBuilder propBuilder = - builder.addProperty(prop.name, aliasProperty.typeName(), - builder.methodCount() - 1); + builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1); propBuilder.setScriptable(true); + propBuilder.setWritable(writable); return true; } @@ -2322,7 +2385,7 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; store.assignBinding.owner = ref.bindingContext.owner; - store.line = prop->location.end.line; + store.line = binding->location.start.line; Q_ASSERT(ref.bindingContext.owner == 0 || (ref.bindingContext.owner != 0 && valueTypeProperty)); @@ -2418,7 +2481,7 @@ bool QmlCompiler::canCoerce(int to, QmlParser::Object *from) const QMetaObject *fromMo = from->metaObject(); while (fromMo) { - if (fromMo == toMo) + if (QmlMetaPropertyPrivate::equal(fromMo, toMo)) return true; fromMo = fromMo->superClass(); } @@ -2437,7 +2500,7 @@ bool QmlCompiler::canCoerce(int to, int from) QmlEnginePrivate::get(engine)->rawMetaObjectForType(from); while (fromMo) { - if (fromMo == toMo) + if (QmlMetaPropertyPrivate::equal(fromMo, toMo)) return true; fromMo = fromMo->superClass(); } @@ -2465,7 +2528,7 @@ QStringList QmlCompiler::deferredProperties(QmlParser::Object *obj) return QStringList(); QMetaClassInfo classInfo = mo->classInfo(idx); - QStringList rv = QString(QLatin1String(classInfo.value())).split(QLatin1Char(',')); + QStringList rv = QString::fromUtf8(classInfo.value()).split(QLatin1Char(',')); return rv; } diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 1d27342..ecf3344 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -104,7 +104,8 @@ public: int type; }; - QAbstractDynamicMetaObject root; + const QMetaObject *root; + QAbstractDynamicMetaObject rootData; QList<QString> primitives; QList<float> floatData; QList<int> intData; @@ -191,6 +192,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 +211,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/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp index 71b4ef0..13bd02c 100644 --- a/src/declarative/qml/qmlcompositetypemanager.cpp +++ b/src/declarative/qml/qmlcompositetypemanager.cpp @@ -119,7 +119,7 @@ QmlCompositeTypeData::toCompiledComponent(QmlEngine *engine) compiledComponent = new QmlCompiledData; compiledComponent->url = imports.baseUrl(); - compiledComponent->name = compiledComponent->url.toString().toLatin1(); // ### + compiledComponent->name = compiledComponent->url.toString().toUtf8(); QmlCompiler compiler; if (!compiler.compile(engine, this, compiledComponent)) { @@ -443,7 +443,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) int waiting = 0; for (int ii = 0; ii < types.count(); ++ii) { QmlScriptParser::TypeReference *parserRef = types.at(ii); - QByteArray typeName = parserRef->name.toLatin1(); + QByteArray typeName = parserRef->name.toUtf8(); QmlCompositeTypeData::TypeReference ref; @@ -458,7 +458,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) if (typeNamespace) { QmlError error; error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Namespace %1 cannot be used as a type").arg(QLatin1String(typeName))); + error.setDescription(tr("Namespace %1 cannot be used as a type").arg(QString::fromUtf8(typeName))); if (!parserRef->refObjects.isEmpty()) { QmlParser::Object *obj = parserRef->refObjects.first(); error.setLine(obj->location.start.line); @@ -500,7 +500,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) { QmlError error; error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Type %1 unavailable").arg(QLatin1String(typeName))); + error.setDescription(tr("Type %1 unavailable").arg(QString::fromUtf8(typeName))); if (!parserRef->refObjects.isEmpty()) { QmlParser::Object *obj = parserRef->refObjects.first(); error.setLine(obj->location.start.line); diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index f6795aa..43a4741 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -61,8 +61,11 @@ QmlContextPrivate::QmlContextPrivate() { } -void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject) +void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject, + const QString &fileName, int lineNumber) { + Q_Q(QmlContext); + if (!engine) return; @@ -70,29 +73,15 @@ void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject) QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(scriptValue); + scriptContext->pushScope(enginePriv->contextClass->newContext(q, scopeObject)); - if (scopeObject) - scriptContext->pushScope(enginePriv->objectClass->newQObject(scopeObject)); - QScriptValue scope = scriptEngine->newObject(); scriptContext->setActivationObject(scope); - QScriptValue val = scriptEngine->evaluate(script); + QScriptValue val = scriptEngine->evaluate(script, fileName, lineNumber); - if (scriptEngine->hasUncaughtException()) { - if (scriptEngine->uncaughtException().isError()){ - QScriptValue exception = scriptEngine->uncaughtException(); - if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){ - qWarning() << exception.property(QLatin1String("fileName")).toString() - << scriptEngine->uncaughtExceptionLineNumber() - << exception.toString(); - - } else { - qmlInfo(scopeObject) << exception.toString(); - } - } - } + if (scriptEngine->hasUncaughtException()) + QmlExpressionPrivate::printException(scriptEngine); scriptEngine->popContext(); @@ -139,10 +128,6 @@ void QmlContextPrivate::init() if (parent) parent->d_func()->childContexts.insert(q); - - //set scope chain - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - scriptValue = QmlEnginePrivate::get(engine)->contextClass->newContext(q); } void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index d18bfda..9a77e94 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -91,10 +91,9 @@ public: QObjectList defaultObjects; int highPriorityCount; - QScriptValue scriptValue; - QList<QScriptValue> scripts; - void addScript(const QString &script, QObject *scope); + void addScript(const QString &script, QObject *scope, + const QString &fileName = QString(), int lineNumber = 1); QUrl url; diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index 6d2c58c..939d008 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -47,8 +47,9 @@ QT_BEGIN_NAMESPACE struct ContextData : public QScriptDeclarativeClass::Object { - ContextData(QmlContext *c) : context(c) {} + ContextData(QmlContext *c, QObject *o) : context(c), scopeObject(o) {} QGuard<QmlContext> context; + QGuard<QObject> scopeObject; }; /* @@ -57,7 +58,7 @@ struct ContextData : public QScriptDeclarativeClass::Object { */ QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine) : QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), - lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) + lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) { } @@ -65,11 +66,11 @@ QmlContextScriptClass::~QmlContextScriptClass() { } -QScriptValue QmlContextScriptClass::newContext(QmlContext *context) +QScriptValue QmlContextScriptClass::newContext(QmlContext *context, QObject *scopeObject) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return newObject(scriptEngine, this, new ContextData(context)); + return newObject(scriptEngine, this, new ContextData(context, scopeObject)); } QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v) @@ -81,24 +82,27 @@ QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v) return data->context; } -#include <QDebug> QScriptClass::QueryFlags QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags flags) { Q_UNUSED(flags); + lastScopeObject = 0; lastContext = 0; lastData = 0; lastPropertyIndex = -1; lastDefaultObject = -1; QmlContext *bindContext = ((ContextData *)object)->context.data(); + QObject *scopeObject = ((ContextData *)object)->scopeObject.data(); if (!bindContext) return 0; while (bindContext) { - QScriptClass::QueryFlags rv = queryProperty(bindContext, name, flags); + QScriptClass::QueryFlags rv = + queryProperty(bindContext, scopeObject, name, flags); + scopeObject = 0; // Only applies to the first context if (rv) return rv; bindContext = bindContext->parentContext(); } @@ -107,7 +111,8 @@ QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, } QScriptClass::QueryFlags -QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &name, +QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObject, + const Identifier &name, QScriptClass::QueryFlags flags) { QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); @@ -129,6 +134,24 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier & } } + for (int ii = 0; ii < cp->scripts.count(); ++ii) { + lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); + if (lastFunction.isValid()) { + lastContext = bindContext; + return QScriptClass::HandlesReadAccess; + } + } + + if (scopeObject) { + QScriptClass::QueryFlags rv = + ep->objectClass->queryProperty(scopeObject, name, flags, 0); + if (rv) { + lastScopeObject = scopeObject; + lastContext = bindContext; + return rv; + } + } + for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) { QScriptClass::QueryFlags rv = ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, 0); @@ -140,13 +163,6 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier & } } - for (int ii = 0; ii < cp->scripts.count(); ++ii) { - lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); - if (lastFunction.isValid()) { - lastContext = bindContext; - return QScriptClass::HandlesReadAccess; - } - } return 0; } @@ -160,8 +176,11 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); + if (lastScopeObject) { - if (lastData) { + return ep->objectClass->property(lastScopeObject, name); + + } else if (lastData) { if (lastData->type) return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type); @@ -197,7 +216,7 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, const QScriptValue &value) { - Q_ASSERT(lastDefaultObject != -1); + Q_ASSERT(lastScopeObject || lastDefaultObject != -1); QmlContext *bindContext = lastContext; Q_ASSERT(bindContext); @@ -205,7 +224,11 @@ void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); - ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value); + if (lastScopeObject) { + ep->objectClass->setProperty(lastScopeObject, name, value); + } else { + ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value); + } } QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h index 761a115..126c8fe 100644 --- a/src/declarative/qml/qmlcontextscriptclass_p.h +++ b/src/declarative/qml/qmlcontextscriptclass_p.h @@ -67,7 +67,7 @@ public: QmlContextScriptClass(QmlEngine *); ~QmlContextScriptClass(); - QScriptValue newContext(QmlContext *); + QScriptValue newContext(QmlContext *, QObject * = 0); QmlContext *contextFromValue(const QScriptValue &); @@ -78,11 +78,13 @@ protected: virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: - QScriptClass::QueryFlags queryProperty(QmlContext *, const Identifier &, + QScriptClass::QueryFlags queryProperty(QmlContext *, QObject *scopeObject, + const Identifier &, QScriptClass::QueryFlags flags); QmlEngine *engine; + QObject *lastScopeObject; QmlContext *lastContext; QmlTypeNameCache::Data *lastData; int lastPropertyIndex; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index ccdf6cf..245ddc0 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -970,7 +970,7 @@ struct QmlEnginePrivate::ImportedNamespace { int vmin = minversions.at(i); if (isBuiltin.at(i)) { - QByteArray qt = urls.at(i).toLatin1(); + QByteArray qt = urls.at(i).toUtf8(); qt += "/"; qt += type; QmlType *t = QmlMetaType::qmlType(qt,vmaj,vmin); @@ -982,7 +982,7 @@ struct QmlEnginePrivate::ImportedNamespace { return true; } } else { - QUrl url = QUrl(urls.at(i) + QLatin1String("/" + type + ".qml")); + QUrl url = QUrl(urls.at(i) + QLatin1String("/") + QString::fromUtf8(type) + QLatin1String(".qml")); if (vmaj || vmin) { // Check version file - XXX cache these in QmlEngine! QFile qmldir(QUrl(urls.at(i)+QLatin1String("/qmldir")).toLocalFile()); @@ -1101,7 +1101,7 @@ public: if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return)) return true; if (s->urls.count() == 1 && !s->isBuiltin[0] && !s->isLibrary[0] && url_return) { - *url_return = QUrl(s->urls[0]+QLatin1String("/")).resolved(QUrl(QLatin1String(unqualifiedtype + ".qml"))); + *url_return = QUrl(s->urls[0]+QLatin1String("/")).resolved(QUrl(QString::fromUtf8(unqualifiedtype) + QLatin1String(".qml"))); return true; } } @@ -1323,7 +1323,7 @@ bool QmlEnginePrivate::addToImport(Imports* imports, const QString& uri, const Q */ bool QmlEnginePrivate::resolveType(const Imports& imports, const QByteArray& type, QmlType** type_return, QUrl* url_return, int *vmaj, int *vmin, ImportedNamespace** ns_return) const { - ImportedNamespace* ns = imports.d->findNamespace(QLatin1String(type)); + ImportedNamespace* ns = imports.d->findNamespace(QString::fromUtf8(type)); if (ns) { if (qmlImportTrace()) qDebug() << "QmlEngine::resolveType" << type << "is namespace for" << ns->urls; @@ -1379,7 +1379,7 @@ static void *voidptr_constructor(const void *v) void QmlEnginePrivate::registerCompositeType(QmlCompiledData *data) { - QByteArray name = data->root.className(); + QByteArray name = data->root->className(); QByteArray ptr = name + "*"; QByteArray lst = "QmlList<" + ptr + ">*"; @@ -1417,7 +1417,7 @@ const QMetaObject *QmlEnginePrivate::rawMetaObjectForType(int t) const { QHash<int, QmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t); if (iter != m_compositeTypes.end()) { - return &(*iter)->root; + return (*iter)->root; } else { return QmlMetaType::rawMetaObjectForType(t); } @@ -1427,7 +1427,7 @@ const QMetaObject *QmlEnginePrivate::metaObjectForType(int t) const { QHash<int, QmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t); if (iter != m_compositeTypes.end()) { - return &(*iter)->root; + return (*iter)->root; } else { return QmlMetaType::metaObjectForType(t); } diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp index 16129ee..e20616a 100644 --- a/src/declarative/qml/qmlenginedebug.cpp +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -325,8 +325,8 @@ void QmlEngineDebugServer::propertyChanged(int id, int objectId, const QByteArra QString objectName = o->objectName(); if (objectName.isEmpty()) objectName = QLatin1String("<unnamed>"); - v = QLatin1String(o->metaObject()->className()) + - QLatin1String(": ") + objectName; + v = QString::fromUtf8(o->metaObject()->className()) + + QLatin1String(": ") + objectName; } if (v.isNull()) v = value.toString(); diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 23e1700..76ca2c1 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -89,8 +89,11 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr, } void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, - QObject *me) + QObject *me, const QUrl &url, int lineNumber) { + data->fileName = url.toString(); + data->line = lineNumber; + quint32 *exprData = (quint32 *)expr; Q_ASSERT(*exprData == BasicScriptEngineData || *exprData == PreTransformedQtScriptData); @@ -107,14 +110,12 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); if (!dd->programs.at(progIdx)) { - dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(data->expression)); + dd->programs[progIdx] = + new QScriptProgram(scriptEngine->compile(data->expression, data->fileName, data->line)); } - QmlContextPrivate *ctxtPriv = ctxt->d_func(); QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(ctxtPriv->scriptValue); - if (me) - scriptContext->pushScope(ep->objectClass->newQObject(me)); + scriptContext->pushScope(ep->contextClass->newContext(ctxt, me)); data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]); @@ -145,11 +146,12 @@ QmlExpression::QmlExpression() /*! \internal */ QmlExpression::QmlExpression(QmlContext *ctxt, void *expr, QmlRefCount *rc, QObject *me, + const QUrl &url, int lineNumber, QmlExpressionPrivate &dd) : QObject(dd, 0) { Q_D(QmlExpression); - d->init(ctxt, expr, rc, me); + d->init(ctxt, expr, rc, me, url, lineNumber); } /*! @@ -210,7 +212,7 @@ QString QmlExpression::expression() const { Q_D(const QmlExpression); if (d->data->sse.isValid()) - return QLatin1String(d->data->sse.expression()); + return QString::fromUtf8(d->data->sse.expression()); else return d->data->expression; } @@ -251,6 +253,28 @@ QVariant QmlExpressionPrivate::evalSSE() return rv; } +void QmlExpressionPrivate::printException(QScriptEngine *scriptEngine) +{ + if (scriptEngine->hasUncaughtException() && + scriptEngine->uncaughtException().isError()) { + + QString fileName; + int lineNumber = scriptEngine->uncaughtExceptionLineNumber(); + + QScriptValue exception = scriptEngine->uncaughtException(); + QLatin1String fileNameProp("fileName"); + + if (!exception.property(fileNameProp).toString().isEmpty()){ + fileName = exception.property(fileNameProp).toString(); + } else { + fileName = QLatin1String("<Unknown File>"); + } + + qWarning().nospace() << qPrintable(fileName) << ":" << lineNumber << ": " + << qPrintable(exception.toString()); + } +} + QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) { #ifdef Q_ENABLE_PERFORMANCE_LOG @@ -270,10 +294,7 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) if (!data->expressionFunctionValid) { QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(ctxtPriv->scriptValue); - - if (data->me) - scriptContext->pushScope(ep->objectClass->newQObject(data->me)); + scriptContext->pushScope(ep->contextClass->newContext(data->context(), data->me)); if (data->expressionRewritten) { data->expressionFunction = scriptEngine->evaluate(data->expression, @@ -291,19 +312,8 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) QScriptValue svalue = data->expressionFunction.call(); - if (scriptEngine->hasUncaughtException()) { - if (scriptEngine->uncaughtException().isError()){ - QScriptValue exception = scriptEngine->uncaughtException(); - QLatin1String fileNameProp("fileName"); - if (!exception.property(fileNameProp).toString().isEmpty()){ - qWarning() << exception.property(fileNameProp).toString() - << scriptEngine->uncaughtExceptionLineNumber() - << exception.toString(); - } else { - qWarning() << exception.toString(); - } - } - } + if (scriptEngine->hasUncaughtException()) + printException(scriptEngine); if (secondaryScope) ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount); diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h index c295a1c..b85e0a7 100644 --- a/src/declarative/qml/qmlexpression.h +++ b/src/declarative/qml/qmlexpression.h @@ -89,8 +89,8 @@ Q_SIGNALS: protected: QmlExpression(QmlContext *, const QString &, QObject *, QmlExpressionPrivate &dd); - QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, - QmlExpressionPrivate &dd); + QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, const QUrl &, + int, QmlExpressionPrivate &dd); private Q_SLOTS: void __q_notify(); diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index 33016e6..d9bb27b 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -136,7 +136,7 @@ public: }; void init(QmlContext *, const QString &, QObject *); - void init(QmlContext *, void *, QmlRefCount *, QObject *); + void init(QmlContext *, void *, QmlRefCount *, QObject *, const QUrl &, int); QmlExpressionData *data; @@ -150,6 +150,8 @@ public: static QmlExpressionPrivate *get(QmlExpression *expr) { return static_cast<QmlExpressionPrivate *>(QObjectPrivate::get(expr)); } + + static void printException(QScriptEngine *); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp index bae1682..e3c0225 100644 --- a/src/declarative/qml/qmlinfo.cpp +++ b/src/declarative/qml/qmlinfo.cpp @@ -95,7 +95,7 @@ QmlInfo::QmlInfo(QObject *object) location += QLatin1String(":"); location += QString::number(ddata->columnNumber); location += QLatin1String(")"); - *this << location.toLatin1().constData(); + *this << qPrintable(location); } else { *this << "(unknown location):"; } 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 1dcdace..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; @@ -240,6 +246,8 @@ public: } storeString; struct { int value; + int fileName; + int lineNumber; } storeScript; struct { int propertyIndex; diff --git a/src/declarative/qml/qmlintegercache.cpp b/src/declarative/qml/qmlintegercache.cpp index 564faaa..89a18a1 100644 --- a/src/declarative/qml/qmlintegercache.cpp +++ b/src/declarative/qml/qmlintegercache.cpp @@ -87,7 +87,7 @@ QmlIntegerCache *QmlIntegerCache::createForEnums(QmlType *type, QmlEngine *engin QMetaEnum enumerator = mo->enumerator(ii); for (int jj = 0; jj < enumerator.keyCount(); ++jj) { - QString name = QLatin1String(enumerator.key(jj)); + QString name = QString::fromUtf8(enumerator.key(jj)); int value = enumerator.value(jj); if (!name.at(0).isUpper()) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 302ce8c..79022e7 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -174,7 +174,7 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) if (typeData) { QmlType *t = 0; - enginePrivate->resolveType(typeData->imports, name.toLatin1(), &t, 0, 0, 0, 0); + enginePrivate->resolveType(typeData->imports, name.toUtf8(), &t, 0, 0, 0, 0); if (t && t->attachedPropertiesFunction()) { attachedFunc = t->index(); } @@ -467,7 +467,7 @@ QStringList QmlMetaProperty::properties(QObject *obj) const QMetaObject *mo = obj->metaObject(); for (int ii = 0; ii < mo->propertyCount(); ++ii) { QMetaProperty prop = mo->property(ii); - rv << QLatin1String(prop.name()); + rv << QString::fromUtf8(prop.name()); } return rv; @@ -487,7 +487,7 @@ QString QmlMetaProperty::name() const else valueType = QmlValueTypeFactory::valueType(d->core.propType); Q_ASSERT(valueType); - rv += QLatin1String(valueType->metaObject()->property(d->valueTypeCoreIdx).name()); + rv += QString::fromUtf8(valueType->metaObject()->property(d->valueTypeCoreIdx).name()); if (!ep) delete valueType; @@ -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; } @@ -654,7 +654,7 @@ QMetaMethod QmlMetaPropertyPrivate::findSignal(QObject *obj, const QString &name int methods = mo->methodCount(); for (int ii = methods - 1; ii >= 0; --ii) { QMetaMethod method = mo->method(ii); - QString methodName = QLatin1String(method.signature()); + QString methodName = QString::fromUtf8(method.signature()); int idx = methodName.indexOf(QLatin1Char('(')); methodName = methodName.left(idx); @@ -698,30 +698,6 @@ QVariant QmlMetaProperty::read() const return QVariant(); } -void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value) -{ - QString expr = value.toString(); - const QObjectList &children = object->children(); - - for (int ii = 0; ii < children.count(); ++ii) { - QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii)); - if (sig && sig->index() == core.coreIndex) { - if (expr.isEmpty()) { - sig->disconnect(); - sig->deleteLater(); - } else { - sig->expression()->setExpression(expr); - } - return; - } - } - - if (!expr.isEmpty()) { - // XXX scope - (void *)new QmlBoundSignal(qmlContext(object), expr, object, q->method(), object); - } -} - QVariant QmlMetaPropertyPrivate::readValueProperty() { uint type = q->type(); @@ -752,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(); @@ -776,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); @@ -803,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; } @@ -819,7 +837,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data u = value.toUrl(); found = true; } else if (vt == QVariant::ByteArray) { - u = QUrl(QLatin1String(value.toByteArray())); + u = QUrl(QString::fromUtf8(value.toByteArray())); found = true; } else if (vt == QVariant::String) { u = QUrl(value.toString()); @@ -829,21 +847,19 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data if (found) { if (context && u.isRelative() && !u.isEmpty()) u = context->baseUrl().resolved(u); - void *a[1]; - a[0] = &u; - QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); + int status = -1; + void *argv[] = { &u, 0, &status, &flags }; + QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv); } } 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) { @@ -858,7 +874,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data const QMetaObject *propMo = QmlMetaType::rawMetaObjectForType(t); while (valMo) { - if (valMo == propMo) + if (equal(valMo, propMo)) break; valMo = valMo->superClass(); } @@ -867,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); @@ -912,7 +928,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data const QMetaObject *objMo = obj->metaObject(); bool found = false; while(!found && objMo) { - if (objMo == mo) + if (equal(objMo, mo)) found = true; else objMo = objMo->superClass(); @@ -933,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); } } @@ -955,21 +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() & SignalProperty) { - - d->writeSignalProperty(value); + if (type() & Property && d->core.isValid()) { - } else if (d->core.isValid()) { - - d->writeValueProperty(value, source); + d->writeValueProperty(value, flags); } } @@ -1201,4 +1211,13 @@ QmlMetaProperty QmlMetaProperty::createProperty(QObject *obj, return prop; } +/*! + Returns true if lhs and rhs refer to the same metaobject data +*/ +bool QmlMetaPropertyPrivate::equal(const QMetaObject *lhs, const QMetaObject *rhs) +{ + return lhs == rhs || (1 && lhs && rhs && lhs->d.stringdata == rhs->d.stringdata); +} + + QT_END_NAMESPACE 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 00b9c3a..7288266 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -96,15 +96,18 @@ public: int propertyType() const; QmlMetaProperty::PropertyCategory propertyCategory() const; - void writeSignalProperty(const QVariant &); - 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); + + static bool equal(const QMetaObject *, const QMetaObject *); }; QT_END_NAMESPACE 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/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 41573a2..80f2786 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -267,7 +267,7 @@ QScriptValue QmlObjectScriptClass::tostring(QScriptContext *context, QScriptEngi if(obj){ QString objectName = obj->objectName(); - ret += QLatin1String(obj->metaObject()->className()); + ret += QString::fromUtf8(obj->metaObject()->className()); ret += QLatin1String("(0x"); ret += QString::number((quintptr)obj,16); 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 16862eb..88d7d77 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -168,6 +168,8 @@ namespace QmlParser // Script blocks that were nested under this object QStringList scriptBlocks; + QStringList scriptBlocksFile; + QList<int> scriptBlocksLineNumber; // The bytes to cast instances by to get to the QmlParserStatus // interface. -1 indicates the type doesn't support this interface. @@ -273,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.cpp b/src/declarative/qml/qmlpropertycache.cpp index 63ce00c..e00126f 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -52,7 +52,7 @@ void QmlPropertyCache::Data::load(const QMetaProperty &p) propType = qMetaTypeId<QVariant>(); coreIndex = p.propertyIndex(); notifyIndex = p.notifySignalIndex(); - name = QLatin1String(p.name()); + name = QString::fromUtf8(p.name()); if (p.isConstant()) flags |= Data::IsConstant; @@ -76,7 +76,7 @@ void QmlPropertyCache::Data::load(const QMetaProperty &p) void QmlPropertyCache::Data::load(const QMetaMethod &m) { - name = QLatin1String(m.signature()); + name = QString::fromUtf8(m.signature()); int parenIdx = name.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); name = name.left(parenIdx); @@ -120,7 +120,7 @@ QmlPropertyCache::Data QmlPropertyCache::create(const QMetaObject *metaObject, int methodCount = metaObject->methodCount(); for (int ii = methodCount - 1; ii >= 0; --ii) { QMetaMethod m = metaObject->method(ii); - QString methodName = QLatin1String(m.signature()); + QString methodName = QString::fromUtf8(m.signature()); int parenIdx = methodName.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); @@ -151,7 +151,7 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject cache->indexCache.resize(propCount); for (int ii = propCount - 1; ii >= 0; --ii) { QMetaProperty p = metaObject->property(ii); - QString propName = QLatin1String(p.name()); + QString propName = QString::fromUtf8(p.name()); RData *data = new RData; data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName); @@ -172,7 +172,7 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject int methodCount = metaObject->methodCount(); for (int ii = methodCount - 1; ii >= 0; --ii) { QMetaMethod m = metaObject->method(ii); - QString methodName = QLatin1String(m.signature()); + QString methodName = QString::fromUtf8(m.signature()); int parenIdx = methodName.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); 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/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index 1c7bf83..57e40b6 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -87,12 +87,12 @@ class ProcessAST: protected AST::Visitor const State &state = top(); if (state.property) { State s(state.property->getValue(), - state.property->getValue()->getProperty(name.toLatin1())); + state.property->getValue()->getProperty(name.toUtf8())); s.property->location = location; push(s); } else { State s(state.object, - state.object->getProperty(name.toLatin1())); + state.object->getProperty(name.toUtf8())); s.property->location = location; push(s); @@ -312,7 +312,7 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName, // XXX this doesn't do anything (_scope never builds up) _scope.append(resolvableObjectType); - obj->typeName = qualifiedNameId().toLatin1(); + obj->typeName = qualifiedNameId().toUtf8(); _scope.removeLast(); obj->location = location; 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 e4eef64..675f5ae 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); } @@ -533,7 +515,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, int sigIdx = instr.assignSignalObject.signal; const QByteArray &pr = datas.at(sigIdx); - QmlMetaProperty prop(target, QLatin1String(pr)); + QmlMetaProperty prop(target, QString::fromUtf8(pr)); if (prop.type() & QmlMetaProperty::SignalProperty) { QMetaMethod method = QmlMetaType::defaultMethod(assign); @@ -567,7 +549,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreScript: { QObject *target = stack.top(); - cp->addScript(primitives.at(instr.storeScript.value), target); + cp->addScript(primitives.at(instr.storeScript.value), target, + primitives.at(instr.storeScript.fileName), + instr.storeScript.lineNumber); } break; @@ -597,12 +581,11 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, if (stack.count() == 1 && bindingSkipList.testBit(coreIndex)) break; - QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, 0); + QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->url, instr.line, 0); bindValues.append(bind); bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->setTarget(mp); bind->addToObject(target); - bind->setSourceLocation(comp->url, instr.line); } break; @@ -654,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(); @@ -705,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); } @@ -725,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); @@ -848,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 f473743..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; @@ -181,20 +199,32 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) (QmlContextPrivate *)QObjectPrivate::get(ctxt); QObject *target = ctxtPriv->idValues[d->contextIdx].data(); - if (!target) return -1; + if (!target) { + if (d->propertyIdx == -1) + *reinterpret_cast<QObject **>(a[0]) = target; + return -1; + } if (c == QMetaObject::ReadProperty && !aConnected.testBit(id)) { int sigIdx = methodOffset + id + metaData->propertyCount; QMetaObject::connect(ctxt, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx); - QMetaProperty prop = - target->metaObject()->property(d->propertyIdx); - if (prop.hasNotifySignal()) - QMetaObject::connect(target, prop.notifySignalIndex(), - object, sigIdx); + if (d->propertyIdx != -1) { + QMetaProperty prop = + target->metaObject()->property(d->propertyIdx); + if (prop.hasNotifySignal()) + QMetaObject::connect(target, prop.notifySignalIndex(), + object, sigIdx); + } aConnected.setBit(id); } - return QMetaObject::metacall(target, c, d->propertyIdx, a); + + if (d->propertyIdx == -1) { + *reinterpret_cast<QObject **>(a[0]) = target; + return -1; + } else { + return QMetaObject::metacall(target, c, d->propertyIdx, a); + } } return -1; @@ -253,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; diff --git a/src/declarative/qml/qmlxmlhttprequest.cpp b/src/declarative/qml/qmlxmlhttprequest.cpp index 0bc927c..5117a00 100644 --- a/src/declarative/qml/qmlxmlhttprequest.cpp +++ b/src/declarative/qml/qmlxmlhttprequest.cpp @@ -1105,7 +1105,7 @@ void QmlXMLHttpRequest::downloadProgress(qint64 bytes) m_status = m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); m_statusText = - QLatin1String(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); + QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); // ### We assume if this is called the headers are now available if (m_state < HeadersReceived) { @@ -1127,7 +1127,7 @@ void QmlXMLHttpRequest::error(QNetworkReply::NetworkError error) m_status = m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); m_statusText = - QLatin1String(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); + QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); m_responseEntityBody = QByteArray(); m_errorFlag = true; @@ -1146,7 +1146,7 @@ void QmlXMLHttpRequest::finished() m_status = m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); m_statusText = - QLatin1String(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); + QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); if (m_state < HeadersReceived) { m_state = HeadersReceived; |