summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml')
-rw-r--r--src/declarative/qml/parser/qdeclarativejs.g2
-rw-r--r--src/declarative/qml/parser/qdeclarativejsgrammar.cpp2
-rw-r--r--src/declarative/qml/parser/qdeclarativejsgrammar_p.h4
-rw-r--r--src/declarative/qml/parser/qdeclarativejsparser.cpp2
-rw-r--r--src/declarative/qml/qdeclarativebinding_p.h7
-rw-r--r--src/declarative/qml/qdeclarativeboundsignal.cpp4
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp315
-rw-r--r--src/declarative/qml/qdeclarativecompiler_p.h8
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp9
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp9
-rw-r--r--src/declarative/qml/qdeclarativecontextscriptclass.cpp35
-rw-r--r--src/declarative/qml/qdeclarativecontextscriptclass_p.h1
-rw-r--r--src/declarative/qml/qdeclarativedeclarativedata_p.h10
-rw-r--r--src/declarative/qml/qdeclarativedom.cpp20
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp139
-rw-r--r--src/declarative/qml/qdeclarativeengine_p.h8
-rw-r--r--src/declarative/qml/qdeclarativeenginedebug.cpp4
-rw-r--r--src/declarative/qml/qdeclarativeenginedebug_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp46
-rw-r--r--src/declarative/qml/qdeclarativeexpression_p.h5
-rw-r--r--src/declarative/qml/qdeclarativeglobal_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeglobalscriptclass.cpp15
-rw-r--r--src/declarative/qml/qdeclarativeglobalscriptclass_p.h7
-rw-r--r--src/declarative/qml/qdeclarativeinstruction_p.h320
-rw-r--r--src/declarative/qml/qdeclarativelist.h2
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp9
-rw-r--r--src/declarative/qml/qdeclarativemetatype_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp83
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass_p.h12
-rw-r--r--src/declarative/qml/qdeclarativeparser.cpp13
-rw-r--r--src/declarative/qml/qdeclarativeparser_p.h10
-rw-r--r--src/declarative/qml/qdeclarativeproperty.cpp17
-rw-r--r--src/declarative/qml/qdeclarativeproperty_p.h2
-rw-r--r--src/declarative/qml/qdeclarativepropertycache.cpp4
-rw-r--r--src/declarative/qml/qdeclarativescript.cpp1
-rw-r--r--src/declarative/qml/qdeclarativescriptparser.cpp70
-rw-r--r--src/declarative/qml/qdeclarativevaluetype.cpp75
-rw-r--r--src/declarative/qml/qdeclarativevaluetype_p.h11
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp10
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript.cpp220
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript_p.h11
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest.cpp19
42 files changed, 1129 insertions, 418 deletions
diff --git a/src/declarative/qml/parser/qdeclarativejs.g b/src/declarative/qml/parser/qdeclarativejs.g
index 7cf81b2..493ad25 100644
--- a/src/declarative/qml/parser/qdeclarativejs.g
+++ b/src/declarative/qml/parser/qdeclarativejs.g
@@ -1020,7 +1020,7 @@ case $rule_number: {
JsIdentifier: T_ON ;
/.
case $rule_number: {
- QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_READONLY]);
+ QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_ON]);
sym(1).sval = driver->intern(s.constData(), s.length());
break;
}
diff --git a/src/declarative/qml/parser/qdeclarativejsgrammar.cpp b/src/declarative/qml/parser/qdeclarativejsgrammar.cpp
index 0677bc5..89493ff 100644
--- a/src/declarative/qml/parser/qdeclarativejsgrammar.cpp
+++ b/src/declarative/qml/parser/qdeclarativejsgrammar.cpp
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
+** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/declarative/qml/parser/qdeclarativejsgrammar_p.h b/src/declarative/qml/parser/qdeclarativejsgrammar_p.h
index 2b2e3d1..32bb12b 100644
--- a/src/declarative/qml/parser/qdeclarativejsgrammar_p.h
+++ b/src/declarative/qml/parser/qdeclarativejsgrammar_p.h
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
+** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
class QDeclarativeJSGrammar
{
public:
- enum {
+ enum VariousConstants {
EOF_SYMBOL = 0,
REDUCE_HERE = 100,
SHIFT_THERE = 99,
diff --git a/src/declarative/qml/parser/qdeclarativejsparser.cpp b/src/declarative/qml/parser/qdeclarativejsparser.cpp
index fd9e690..c86e047 100644
--- a/src/declarative/qml/parser/qdeclarativejsparser.cpp
+++ b/src/declarative/qml/parser/qdeclarativejsparser.cpp
@@ -516,7 +516,7 @@ case 66: {
}
case 67: {
- QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_READONLY]);
+ QString s = QLatin1String(QDeclarativeJSGrammar::spell[T_ON]);
sym(1).sval = driver->intern(s.constData(), s.length());
break;
}
diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h
index f66b9c7..1a714f0 100644
--- a/src/declarative/qml/qdeclarativebinding_p.h
+++ b/src/declarative/qml/qdeclarativebinding_p.h
@@ -64,7 +64,7 @@
QT_BEGIN_NAMESPACE
-class Q_AUTOTEST_EXPORT QDeclarativeAbstractBinding
+class Q_DECLARATIVE_EXPORT QDeclarativeAbstractBinding
{
public:
QDeclarativeAbstractBinding();
@@ -101,7 +101,7 @@ private:
class QDeclarativeContext;
class QDeclarativeBindingPrivate;
-class Q_AUTOTEST_EXPORT QDeclarativeBinding : public QDeclarativeExpression, public QDeclarativeAbstractBinding
+class Q_DECLARATIVE_EXPORT QDeclarativeBinding : public QDeclarativeExpression, public QDeclarativeAbstractBinding
{
Q_OBJECT
public:
@@ -130,8 +130,9 @@ protected:
private:
Q_DECLARE_PRIVATE(QDeclarativeBinding)
};
-Q_DECLARE_METATYPE(QDeclarativeBinding*);
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QDeclarativeBinding*);
+
#endif // QDECLARATIVEBINDING_P_H
diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp
index ce396fd..6a5a102 100644
--- a/src/declarative/qml/qdeclarativeboundsignal.cpp
+++ b/src/declarative/qml/qdeclarativeboundsignal.cpp
@@ -104,7 +104,7 @@ QDeclarativeBoundSignal::QDeclarativeBoundSignal(QObject *scope, const QMetaMeth
// is that they both do the work to figure it out. Boo hoo.
if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
- QDeclarativeGraphics_setParent_noEvent(this, parent);
+ QDeclarative_setParent_noEvent(this, parent);
QMetaObject::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
}
@@ -120,7 +120,7 @@ QDeclarativeBoundSignal::QDeclarativeBoundSignal(QDeclarativeContext *ctxt, cons
// is that they both do the work to figure it out. Boo hoo.
if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
- QDeclarativeGraphics_setParent_noEvent(this, parent);
+ QDeclarative_setParent_noEvent(this, parent);
QMetaObject::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
m_expression = new QDeclarativeExpression(ctxt, val, scope);
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 5da207d..ef1032b 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -65,6 +65,7 @@
#include "qdeclarativescriptparser_p.h"
#include "qdeclarativebinding_p.h"
#include "qdeclarativecompiledbindings_p.h"
+#include "qdeclarativeglobalscriptclass_p.h"
#include <qfxperf_p_p.h>
@@ -113,32 +114,6 @@ QList<QDeclarativeError> QDeclarativeCompiler::errors() const
}
/*!
- Returns true if \a val is a legal object id, false otherwise.
-
- Legal ids must start with a lower-case letter or underscore, and contain only
- letters, numbers and underscores.
-*/
-bool QDeclarativeCompiler::isValidId(const QString &val)
-{
- if (val.isEmpty())
- return false;
-
- if (val.at(0).isLetter() && !val.at(0).isLower()) {
- qWarning().nospace() << "id " << val << " is invalid: ids cannot start with uppercase letters";
- return false;
- }
-
- QChar u(QLatin1Char('_'));
- for (int ii = 0; ii < val.count(); ++ii)
- if (val.at(ii) != u &&
- ((ii == 0 && !val.at(ii).isLetter()) ||
- (ii != 0 && !val.at(ii).isLetterOrNumber())) )
- return false;
-
- return true;
-}
-
-/*!
Returns true if \a name refers to an attached property, false otherwise.
Attached property names are those that start with a capital letter.
@@ -586,9 +561,11 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
QDeclarativeCompositeTypeData::TypeReference &tref = unit->types[ii];
QDeclarativeCompiledData::TypeReference ref;
QDeclarativeScriptParser::TypeReference *parserRef = unit->data.referencedTypes().at(ii);
- if (tref.type)
+ if (tref.type) {
ref.type = tref.type;
- else if (tref.unit) {
+ if (!ref.type->isCreatable())
+ COMPILE_EXCEPTION(parserRef->refObjects.first(), QCoreApplication::translate("QDeclarativeCompiler", "Element is not creatable."));
+ } else if (tref.unit) {
ref.component = tref.unit->toComponent(engine);
if (ref.component->isError()) {
@@ -718,6 +695,7 @@ bool QDeclarativeCompiler::buildObject(Object *obj, const BindingContext &ctxt)
BindingContext objCtxt(obj);
// Create the synthesized meta object, ignoring aliases
+ COMPILE_CHECK(checkDynamicMeta(obj));
COMPILE_CHECK(mergeDynamicMetaProperties(obj));
COMPILE_CHECK(buildDynamicMeta(obj, IgnoreAliases));
@@ -1007,12 +985,15 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj)
} else if (v->type == Value::SignalExpression) {
+ BindingContext ctxt = compileState.signalExpressions.value(v);
+
QDeclarativeInstruction store;
store.type = QDeclarativeInstruction::StoreSignal;
store.line = v->location.start.line;
store.storeSignal.signalIndex = prop->index;
store.storeSignal.value =
output->indexForString(v->value.asScript().trimmed());
+ store.storeSignal.context = ctxt.stack;
output->bytecode << store;
}
@@ -1139,10 +1120,11 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj,
if (obj->properties.count())
idProp = *obj->properties.begin();
- if (idProp && (idProp->value || idProp->values.count() > 1 || !isValidId(idProp->values.first()->primitive())))
- COMPILE_EXCEPTION(idProp, QCoreApplication::translate("QDeclarativeCompiler","Invalid component id specification"));
-
if (idProp) {
+ if (idProp->value || idProp->values.count() > 1 || idProp->values.at(0)->object)
+ COMPILE_EXCEPTION(idProp, QCoreApplication::translate("QDeclarativeCompiler","Invalid component id specification"));
+ COMPILE_CHECK(checkValidId(idProp->values.first(), idProp->values.first()->primitive()));
+
QString idVal = idProp->values.first()->primitive();
if (compileState.ids.contains(idVal))
@@ -1344,7 +1326,7 @@ QMetaMethod QDeclarativeCompiler::findSignalByName(const QMetaObject *mo, const
}
bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj,
- const BindingContext &ctxt)
+ const BindingContext &ctxt)
{
Q_ASSERT(obj->metaObject());
Q_ASSERT(!prop->isEmpty());
@@ -1365,7 +1347,7 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl
} else {
- if (prop->value || prop->values.count() > 1)
+ if (prop->value || prop->values.count() != 1)
COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Incorrectly specified signal"));
prop->index = sigIdx;
@@ -1380,6 +1362,8 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl
QString script = prop->values.at(0)->value.asScript().trimmed();
if (script.isEmpty())
COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Empty signal assignment"));
+
+ compileState.signalExpressions.insert(prop->values.at(0), ctxt);
}
}
@@ -1623,6 +1607,10 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p
for (int ii = 0; ii < prop->values.count(); ++ii) {
QDeclarativeParser::Value *v = prop->values.at(ii);
+ Q_ASSERT(v->type == Value::CreatedObject ||
+ v->type == Value::PropertyBinding ||
+ v->type == Value::Literal);
+
if (v->type == Value::CreatedObject) {
genObject(v->object);
@@ -1652,7 +1640,27 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p
output->bytecode << store;
}
- } else if (v->type == Value::ValueSource) {
+ } else if (v->type == Value::PropertyBinding) {
+
+ genBindingAssignment(v, prop, obj, valueTypeProperty);
+
+ } else if (v->type == Value::Literal) {
+
+ QMetaProperty mp = obj->metaObject()->property(prop->index);
+ genLiteralAssignment(mp, v);
+
+ }
+
+ }
+
+ for (int ii = 0; ii < prop->onValues.count(); ++ii) {
+
+ QDeclarativeParser::Value *v = prop->onValues.at(ii);
+
+ Q_ASSERT(v->type == Value::ValueSource ||
+ v->type == Value::ValueInterceptor);
+
+ if (v->type == Value::ValueSource) {
genObject(v->object);
QDeclarativeInstruction store;
@@ -1685,16 +1693,6 @@ void QDeclarativeCompiler::genPropertyAssignment(QDeclarativeParser::Property *p
QDeclarativeType *valueType = toQmlType(v->object);
store.assignValueInterceptor.castValue = valueType->propertyValueInterceptorCast();
output->bytecode << store;
-
- } else if (v->type == Value::PropertyBinding) {
-
- genBindingAssignment(v, prop, obj, valueTypeProperty);
-
- } else if (v->type == Value::Literal) {
-
- QMetaProperty mp = obj->metaObject()->property(prop->index);
- genLiteralAssignment(mp, v);
-
}
}
@@ -1711,8 +1709,7 @@ bool QDeclarativeCompiler::buildIdProperty(QDeclarativeParser::Property *prop,
QDeclarativeParser::Value *idValue = prop->values.at(0);
QString val = idValue->primitive();
- if (!isValidId(val))
- COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","\"%1\" is not a valid object id").arg(val));
+ COMPILE_CHECK(checkValidId(idValue, val));
// We disallow id's that conflict with import prefixes and types
QDeclarativeEnginePrivate::ImportedNamespace *ns = 0;
@@ -1793,19 +1790,25 @@ bool QDeclarativeCompiler::buildAttachedProperty(QDeclarativeParser::Property *p
// }
// font is a nested property. pointSize and family are not.
bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
- const BindingContext &ctxt)
+ QDeclarativeParser::Object *obj,
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->type != 0);
Q_ASSERT(prop->index != -1);
- if (prop->values.count())
- COMPILE_EXCEPTION(prop->values.first(), QCoreApplication::translate("QDeclarativeCompiler", "Invalid value in grouped property"));
-
- if (prop->type < (int)QVariant::UserType) {
+ if (QDeclarativeValueTypeFactory::isValueType(prop->type)) {
QDeclarativeEnginePrivate *ep =
static_cast<QDeclarativeEnginePrivate *>(QObjectPrivate::get(engine));
if (prop->type >= 0 /* QVariant == -1 */ && ep->valueTypes[prop->type]) {
+
+ if (prop->values.count()) {
+ if (prop->values.at(0)->location < prop->value->location) {
+ COMPILE_EXCEPTION(prop->value, QCoreApplication::translate("QDeclarativeCompiler", "Property has already been assigned a value"));
+ } else {
+ COMPILE_EXCEPTION(prop->values.at(0), QCoreApplication::translate("QDeclarativeCompiler", "Property has already been assigned a value"));
+ }
+ }
+
COMPILE_CHECK(buildValueTypeProperty(ep->valueTypes[prop->type],
prop->value, obj, ctxt.incr()));
obj->addValueTypeProperty(prop);
@@ -1820,6 +1823,9 @@ bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *pr
if (!prop->value->metatype)
COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Invalid grouped property access"));
+ if (prop->values.count())
+ COMPILE_EXCEPTION(prop->values.at(0), QCoreApplication::translate("QDeclarativeCompiler", "Cannot assign a value directly to a grouped property"));
+
obj->addGroupedProperty(prop);
COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
@@ -1829,9 +1835,9 @@ bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *pr
}
bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type,
- QDeclarativeParser::Object *obj,
- QDeclarativeParser::Object *baseObj,
- const BindingContext &ctxt)
+ QDeclarativeParser::Object *obj,
+ QDeclarativeParser::Object *baseObj,
+ const BindingContext &ctxt)
{
if (obj->defaultProperty)
COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Invalid property use"));
@@ -1848,37 +1854,36 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type,
if (prop->value)
COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Property assignment expected"));
- if (prop->values.count() != 1)
+ if (prop->values.count() > 1) {
COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Single property assignment expected"));
+ } else if (prop->values.count()) {
+ Value *value = prop->values.at(0);
- Value *value = prop->values.at(0);
-
- if (value->object) {
- bool isPropertyValue = output->types.at(value->object->type).type->propertyValueSourceCast() != -1;
- bool isPropertyInterceptor = output->types.at(value->object->type).type->propertyValueInterceptorCast() != -1;
- if (!isPropertyValue && !isPropertyInterceptor) {
+ if (value->object) {
COMPILE_EXCEPTION(prop, QCoreApplication::translate("QDeclarativeCompiler","Unexpected object assignment"));
- } else {
- COMPILE_CHECK(buildObject(value->object, ctxt));
-
- if (isPropertyInterceptor && baseObj->synthdata.isEmpty())
- buildDynamicMeta(baseObj, ForceCreation);
- value->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
+ } else if (value->value.isScript()) {
+ // ### Check for writability
+ BindingReference reference;
+ reference.expression = value->value;
+ reference.property = prop;
+ reference.value = value;
+ reference.bindingContext = ctxt;
+ reference.bindingContext.owner++;
+ addBindingReference(reference);
+ value->type = Value::PropertyBinding;
+ } else {
+ COMPILE_CHECK(testLiteralAssignment(p, value));
+ value->type = Value::Literal;
}
- } else if (value->value.isScript()) {
- // ### Check for writability
- BindingReference reference;
- reference.expression = value->value;
- reference.property = prop;
- reference.value = value;
- reference.bindingContext = ctxt;
- reference.bindingContext.owner++;
- addBindingReference(reference);
- value->type = Value::PropertyBinding;
- } else {
- COMPILE_CHECK(testLiteralAssignment(p, value));
- value->type = Value::Literal;
}
+
+ for (int ii = 0; ii < prop->onValues.count(); ++ii) {
+ Value *v = prop->onValues.at(ii);
+ Q_ASSERT(v->object);
+
+ COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, baseObj, v, ctxt));
+ }
+
obj->addValueProperty(prop);
}
@@ -1886,13 +1891,11 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type,
}
// Build assignments to QML lists. QML lists are properties of type
-// QList<T *> * and QDeclarativeList<T *> *.
-//
-// QList<T *> * types can accept a list of objects, or a single binding
-// QDeclarativeList<T *> * types can accept a list of objects
+// QDeclarativeListProperty<T>. List properties can accept a list of
+// objects, or a single binding.
bool QDeclarativeCompiler::buildListProperty(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
- const BindingContext &ctxt)
+ QDeclarativeParser::Object *obj,
+ const BindingContext &ctxt)
{
Q_ASSERT(QDeclarativeEnginePrivate::get(engine)->isList(prop->type));
@@ -1950,20 +1953,6 @@ bool QDeclarativeCompiler::buildScriptStringProperty(QDeclarativeParser::Propert
}
// Compile regular property assignments of the form "property: <value>"
-//
-// ### The following problems exist
-//
-// There is no distinction between how "lists" of values are specified. This
-// Item {
-// children: Item {}
-// children: Item {}
-// }
-// is identical to
-// Item {
-// children: [ Item {}, Item {} ]
-// }
-//
-// We allow assignming multiple values to single value properties
bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeParser::Property *prop,
QDeclarativeParser::Object *obj,
const BindingContext &ctxt)
@@ -1983,14 +1972,21 @@ bool QDeclarativeCompiler::buildPropertyAssignment(QDeclarativeParser::Property
}
}
+ for (int ii = 0; ii < prop->onValues.count(); ++ii) {
+ Value *v = prop->onValues.at(ii);
+
+ Q_ASSERT(v->object);
+ COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, obj, v, ctxt));
+ }
+
return true;
}
// Compile assigning a single object instance to a regular property
bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
- QDeclarativeParser::Value *v,
- const BindingContext &ctxt)
+ QDeclarativeParser::Object *obj,
+ QDeclarativeParser::Value *v,
+ const BindingContext &ctxt)
{
Q_ASSERT(prop->index != -1);
Q_ASSERT(v->object->type != -1);
@@ -2019,15 +2015,6 @@ bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Pro
v->object->metatype = output->types.at(v->object->type).metaObject();
Q_ASSERT(v->object->metaObject());
- // Will be true if the assigned type inherits QDeclarativePropertyValueSource
- bool isPropertyValue = false;
- // Will be true if the assigned type inherits QDeclarativePropertyValueInterceptor
- bool isPropertyInterceptor = false;
- if (QDeclarativeType *valueType = toQmlType(v->object)) {
- 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
// effect the properties on the type, but don't effect assignability
@@ -2063,13 +2050,6 @@ bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Pro
component->getDefaultProperty()->addValue(componentValue);
v->object = component;
COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
- } else if (isPropertyValue || isPropertyInterceptor) {
- // Assign as a property value source
- COMPILE_CHECK(buildObject(v->object, ctxt));
-
- if (isPropertyInterceptor && prop->parent->synthdata.isEmpty())
- buildDynamicMeta(prop->parent, ForceCreation);
- v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
} else {
COMPILE_EXCEPTION(v->object, QCoreApplication::translate("QDeclarativeCompiler","Cannot assign object to property"));
}
@@ -2078,6 +2058,55 @@ bool QDeclarativeCompiler::buildPropertyObjectAssignment(QDeclarativeParser::Pro
return true;
}
+// Compile assigning a single object instance to a regular property using the "on" syntax.
+//
+// For example:
+// Item {
+// NumberAnimation on x { }
+// }
+bool QDeclarativeCompiler::buildPropertyOnAssignment(QDeclarativeParser::Property *prop,
+ QDeclarativeParser::Object *obj,
+ QDeclarativeParser::Object *baseObj,
+ QDeclarativeParser::Value *v,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(prop->index != -1);
+ Q_ASSERT(v->object->type != -1);
+
+ if (!obj->metaObject()->property(prop->index).isWritable())
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name)));
+
+
+ // Normally buildObject() will set this up, but we need the static
+ // meta object earlier to test for assignability. It doesn't matter
+ // that there may still be outstanding synthesized meta object changes
+ // on this type, as they are not relevant for assignability testing
+ v->object->metatype = output->types.at(v->object->type).metaObject();
+ Q_ASSERT(v->object->metaObject());
+
+ // Will be true if the assigned type inherits QDeclarativePropertyValueSource
+ bool isPropertyValue = false;
+ // Will be true if the assigned type inherits QDeclarativePropertyValueInterceptor
+ bool isPropertyInterceptor = false;
+ if (QDeclarativeType *valueType = toQmlType(v->object)) {
+ isPropertyValue = valueType->propertyValueSourceCast() != -1;
+ isPropertyInterceptor = valueType->propertyValueInterceptorCast() != -1;
+ }
+
+ if (isPropertyValue || isPropertyInterceptor) {
+ // Assign as a property value source
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ if (isPropertyInterceptor && prop->parent->synthdata.isEmpty())
+ buildDynamicMeta(baseObj, ForceCreation);
+ v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
+ } else {
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler","\"%1\" cannot operate on \"%2\"").arg(v->object->typeName.constData()).arg(prop->name.constData()));
+ }
+
+ return true;
+}
+
// Compile assigning a literal or binding to a regular property
bool QDeclarativeCompiler::buildPropertyLiteralAssignment(QDeclarativeParser::Property *prop,
QDeclarativeParser::Object *obj,
@@ -2175,6 +2204,8 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
if (propNames.contains(prop.name))
COMPILE_EXCEPTION(&prop, QCoreApplication::translate("QDeclarativeCompiler","Duplicate property name"));
+ if (QString::fromUtf8(prop.name).at(0).isUpper())
+ COMPILE_EXCEPTION(&prop, QCoreApplication::translate("QDeclarativeCompiler","Property names cannot begin with an upper case letter"));
propNames.insert(prop.name);
}
@@ -2182,12 +2213,16 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
QByteArray name = obj->dynamicSignals.at(ii).name;
if (methodNames.contains(name))
COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Duplicate signal name"));
+ if (QString::fromUtf8(name).at(0).isUpper())
+ COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Signal names cannot begin with an upper case letter"));
methodNames.insert(name);
}
for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
QByteArray name = obj->dynamicSlots.at(ii).name;
if (methodNames.contains(name))
COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Duplicate method name"));
+ if (QString::fromUtf8(name).at(0).isUpper())
+ COMPILE_EXCEPTION(obj, QCoreApplication::translate("QDeclarativeCompiler","Method names cannot begin with an upper case letter"));
methodNames.insert(name);
}
@@ -2203,10 +2238,13 @@ bool QDeclarativeCompiler::mergeDynamicMetaProperties(QDeclarativeParser::Object
continue;
Property *property = 0;
- if (p.isDefaultProperty)
+ if (p.isDefaultProperty) {
property = obj->getDefaultProperty();
- else
+ } else {
property = obj->getProperty(p.name);
+ if (!property->values.isEmpty())
+ COMPILE_EXCEPTION(property, QCoreApplication::translate("QDeclarativeCompiler","Property value set multiple times"));
+ }
if (property->value)
COMPILE_EXCEPTION(property, QCoreApplication::translate("QDeclarativeCompiler","Invalid property nesting"));
@@ -2233,8 +2271,6 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn
obj->dynamicSlots.isEmpty())
return true;
- COMPILE_CHECK(checkDynamicMeta(obj));
-
QByteArray dynamicData(sizeof(QDeclarativeVMEMetaData), (char)0);
QByteArray newClassName = obj->metatype->className();
@@ -2437,6 +2473,31 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn
return true;
}
+bool QDeclarativeCompiler::checkValidId(QDeclarativeParser::Value *v, const QString &val)
+{
+ if (val.isEmpty())
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler", "Invalid empty ID"));
+
+ if (val.at(0).isLetter() && !val.at(0).isLower())
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler", "IDs cannot start with an uppercase letter"));
+
+ QChar u(QLatin1Char('_'));
+ for (int ii = 0; ii < val.count(); ++ii) {
+
+ if (ii == 0 && !val.at(ii).isLetter() && val.at(ii) != u) {
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler", "IDs must start with a letter or underscore"));
+ } else if (ii != 0 && !val.at(ii).isLetterOrNumber() && val.at(ii) != u) {
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler", "IDs must contain only letters, numbers, and underscores"));
+ }
+
+ }
+
+ if (QDeclarativeEnginePrivate::get(engine)->globalClass->illegalNames().contains(val))
+ COMPILE_EXCEPTION(v, QCoreApplication::translate("QDeclarativeCompiler", "ID illegally masks global JavaScript property"));
+
+ return true;
+}
+
#include <qdeclarativejsparser_p.h>
static QStringList astNodeToStringList(QDeclarativeJS::AST::Node *node)
@@ -2560,9 +2621,9 @@ bool QDeclarativeCompiler::buildBinding(QDeclarativeParser::Value *value,
}
void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *binding,
- QDeclarativeParser::Property *prop,
- QDeclarativeParser::Object *obj,
- QDeclarativeParser::Property *valueTypeProperty)
+ QDeclarativeParser::Property *prop,
+ QDeclarativeParser::Object *obj,
+ QDeclarativeParser::Property *valueTypeProperty)
{
Q_UNUSED(obj);
Q_ASSERT(compileState.bindings.contains(binding));
diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h
index 2ea3366..cca42e2 100644
--- a/src/declarative/qml/qdeclarativecompiler_p.h
+++ b/src/declarative/qml/qdeclarativecompiler_p.h
@@ -155,7 +155,6 @@ public:
bool isError() const;
QList<QDeclarativeError> errors() const;
- static bool isValidId(const QString &);
static bool isAttachedPropertyName(const QByteArray &);
static bool isSignalPropertyName(const QByteArray &);
@@ -219,6 +218,11 @@ private:
QDeclarativeParser::Object *obj,
QDeclarativeParser::Value *value,
const BindingContext &ctxt);
+ bool buildPropertyOnAssignment(QDeclarativeParser::Property *prop,
+ QDeclarativeParser::Object *obj,
+ QDeclarativeParser::Object *baseObj,
+ QDeclarativeParser::Value *value,
+ const BindingContext &ctxt);
bool buildPropertyLiteralAssignment(QDeclarativeParser::Property *prop,
QDeclarativeParser::Object *obj,
QDeclarativeParser::Value *value,
@@ -242,6 +246,7 @@ private:
QDeclarativeParser::Object *obj,
const QDeclarativeParser::Object::DynamicProperty &);
bool completeComponentBuild();
+ bool checkValidId(QDeclarativeParser::Value *, const QString &);
void genObject(QDeclarativeParser::Object *obj);
@@ -302,6 +307,7 @@ private:
QByteArray compiledBindingData;
QHash<QDeclarativeParser::Value *, BindingReference> bindings;
+ QHash<QDeclarativeParser::Value *, BindingContext> signalExpressions;
QList<QDeclarativeParser::Object *> aliasingObjects;
QDeclarativeParser::Object *root;
};
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp
index fe63ad2..d6bb216 100644
--- a/src/declarative/qml/qdeclarativecomponent.cpp
+++ b/src/declarative/qml/qdeclarativecomponent.cpp
@@ -437,6 +437,13 @@ void QDeclarativeComponent::loadUrl(const QUrl &url)
else
d->url = url;
+ if (url.isEmpty()) {
+ QDeclarativeError error;
+ error.setDescription(tr("Invalid empty URL"));
+ d->state.errors << error;
+ return;
+ }
+
QDeclarativeCompositeTypeData *data =
QDeclarativeEnginePrivate::get(d->engine)->typeManager.get(d->url);
@@ -618,7 +625,7 @@ QDeclarativeComponentPrivate::beginCreate(QDeclarativeContext *context, const QB
QObject *rv = begin(ctxt, ep, cc, start, count, &state, bindings);
if (rv) {
- QDeclarativeGraphics_setParent_noEvent(ctxt, rv);
+ QDeclarative_setParent_noEvent(ctxt, rv);
} else {
delete ctxt;
}
diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp
index b244cd8..f70e143 100644
--- a/src/declarative/qml/qdeclarativecontext.cpp
+++ b/src/declarative/qml/qdeclarativecontext.cpp
@@ -47,6 +47,7 @@
#include "qdeclarativeengine.h"
#include "qdeclarativecompiledbindings_p.h"
#include "qdeclarativeinfo.h"
+#include "qdeclarativeglobalscriptclass_p.h"
#include <qscriptengine.h>
#include <QtCore/qvarlengtharray.h>
@@ -74,10 +75,13 @@ void QDeclarativeContextPrivate::addScript(const QDeclarativeParser::Object::Scr
QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
+
scriptContext->pushScope(enginePriv->contextClass->newContext(q, scopeObject));
+ scriptContext->pushScope(enginePriv->globalClass->globalObject());
QScriptValue scope = scriptEngine->newObject();
scriptContext->setActivationObject(scope);
+ scriptContext->pushScope(scope);
for (int ii = 0; ii < script.codes.count(); ++ii) {
scriptEngine->evaluate(script.codes.at(ii), script.files.at(ii), script.lineNumbers.at(ii));
@@ -480,7 +484,10 @@ QVariant QDeclarativeContext::contextProperty(const QString &name) const
if (!value.isValid() && parentContext())
value = parentContext()->contextProperty(name);
} else {
- value = d->propertyValues[idx];
+ if (idx >= d->propertyValues.count())
+ value = QVariant::fromValue(d->idValues[idx - d->propertyValues.count()].data());
+ else
+ value = d->propertyValues[idx];
}
return value;
diff --git a/src/declarative/qml/qdeclarativecontextscriptclass.cpp b/src/declarative/qml/qdeclarativecontextscriptclass.cpp
index 7deed0b..5fcf4e2 100644
--- a/src/declarative/qml/qdeclarativecontextscriptclass.cpp
+++ b/src/declarative/qml/qdeclarativecontextscriptclass.cpp
@@ -50,10 +50,11 @@
QT_BEGIN_NAMESPACE
struct ContextData : public QScriptDeclarativeClass::Object {
- ContextData() : isSharedContext(true) {}
- ContextData(QDeclarativeContext *c, QObject *o) : context(c), scopeObject(o), isSharedContext(false) {}
+ ContextData() : overrideObject(0), isSharedContext(true) {}
+ ContextData(QDeclarativeContext *c, QObject *o) : context(c), scopeObject(o), overrideObject(0), isSharedContext(false) {}
QDeclarativeGuard<QDeclarativeContext> context;
QDeclarativeGuard<QObject> scopeObject;
+ QObject *overrideObject;
bool isSharedContext;
QDeclarativeContext *getContext(QDeclarativeEngine *engine) {
@@ -110,6 +111,17 @@ QDeclarativeContext *QDeclarativeContextScriptClass::contextFromValue(const QScr
return data->getContext(engine);
}
+QObject *QDeclarativeContextScriptClass::setOverrideObject(QScriptValue &v, QObject *override)
+{
+ if (scriptClass(v) != this)
+ return 0;
+
+ ContextData *data = (ContextData *)object(v);
+ QObject *rv = data->overrideObject;
+ data->overrideObject = override;
+ return rv;
+}
+
QScriptClass::QueryFlags
QDeclarativeContextScriptClass::queryProperty(Object *object, const Identifier &name,
QScriptClass::QueryFlags flags)
@@ -127,6 +139,20 @@ QDeclarativeContextScriptClass::queryProperty(Object *object, const Identifier &
if (!bindContext)
return 0;
+ QObject *overrideObject = ((ContextData *)object)->overrideObject;
+ if (overrideObject) {
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ QScriptClass::QueryFlags rv =
+ ep->objectClass->queryProperty(overrideObject, name, flags, bindContext,
+ QDeclarativeObjectScriptClass::ImplicitObject |
+ QDeclarativeObjectScriptClass::SkipAttachedProperties);
+ if (rv) {
+ lastScopeObject = overrideObject;
+ lastContext = bindContext;
+ return rv;
+ }
+ }
+
bool includeTypes = true;
while (bindContext) {
QScriptClass::QueryFlags rv =
@@ -236,8 +262,9 @@ QDeclarativeContextScriptClass::property(Object *object, const Identifier &name)
}
}
- ep->capturedProperties <<
- QDeclarativeEnginePrivate::CapturedProperty(bindContext, -1, lastPropertyIndex + cp->notifyIndex);
+ if (ep->captureProperties)
+ ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(bindContext, -1, lastPropertyIndex + cp->notifyIndex);
+
return Value(scriptEngine, rv);
} else if(lastDefaultObject != -1) {
diff --git a/src/declarative/qml/qdeclarativecontextscriptclass_p.h b/src/declarative/qml/qdeclarativecontextscriptclass_p.h
index 26086ec..4b0dca0 100644
--- a/src/declarative/qml/qdeclarativecontextscriptclass_p.h
+++ b/src/declarative/qml/qdeclarativecontextscriptclass_p.h
@@ -70,6 +70,7 @@ public:
QScriptValue newSharedContext();
QDeclarativeContext *contextFromValue(const QScriptValue &);
+ QObject *setOverrideObject(QScriptValue &, QObject *);
protected:
virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
diff --git a/src/declarative/qml/qdeclarativedeclarativedata_p.h b/src/declarative/qml/qdeclarativedeclarativedata_p.h
index 2c92419..ae40130 100644
--- a/src/declarative/qml/qdeclarativedeclarativedata_p.h
+++ b/src/declarative/qml/qdeclarativedeclarativedata_p.h
@@ -103,7 +103,10 @@ public:
static QDeclarativeDeclarativeData *get(const QObject *object, bool create = false) {
QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
- if (priv->declarativeData) {
+ if (priv->wasDeleted) {
+ Q_ASSERT(!create);
+ return 0;
+ } else if (priv->declarativeData) {
return static_cast<QDeclarativeDeclarativeData *>(priv->declarativeData);
} else if (create) {
priv->declarativeData = new QDeclarativeDeclarativeData;
@@ -117,6 +120,11 @@ public:
template<class T>
void QDeclarativeGuard<T>::addGuard()
{
+ if (QObjectPrivate::get(o)->wasDeleted) {
+ if (prev) remGuard();
+ return;
+ }
+
QDeclarativeDeclarativeData *data = QDeclarativeDeclarativeData::get(o, true);
next = data->guards;
if (next) reinterpret_cast<QDeclarativeGuard<T> *>(next)->prev = &next;
diff --git a/src/declarative/qml/qdeclarativedom.cpp b/src/declarative/qml/qdeclarativedom.cpp
index 6c81f34..cb56ead 100644
--- a/src/declarative/qml/qdeclarativedom.cpp
+++ b/src/declarative/qml/qdeclarativedom.cpp
@@ -374,7 +374,10 @@ QDeclarativeDomValue QDeclarativeDomProperty::value() const
QDeclarativeDomValue rv;
if (d->property) {
rv.d->property = d->property;
- rv.d->value = d->property->values.at(0);
+ if (d->property->values.count())
+ rv.d->value = d->property->values.at(0);
+ else
+ rv.d->value = d->property->onValues.at(0);
rv.d->property->addref();
rv.d->value->addref();
}
@@ -505,7 +508,7 @@ int QDeclarativeDomDynamicProperty::propertyType() const
QByteArray QDeclarativeDomDynamicProperty::propertyTypeName() const
{
- if (isValid())
+ if (isValid())
return d->property.customType;
return QByteArray();
@@ -1181,7 +1184,7 @@ QDeclarativeDomObject QDeclarativeDomValueValueSource::object() const
\qml
Rectangle {
- x: Behavior { NumberAnimation { duration: 500 } }
+ Behavior on x { NumberAnimation { duration: 500 } }
}
\endqml
*/
@@ -1225,7 +1228,7 @@ QDeclarativeDomValueValueInterceptor &QDeclarativeDomValueValueInterceptor::oper
returned.
\qml
Rectangle {
- x: Behavior { NumberAnimation { duration: 500 } }
+ Behavior on x { NumberAnimation { duration: 500 } }
}
\endqml
*/
@@ -1346,7 +1349,7 @@ QDeclarativeDomValue::Type QDeclarativeDomValue::type() const
{
if (d->property)
if (QDeclarativeMetaType::isList(d->property->type) ||
- (d->property && d->property->values.count() > 1))
+ (d->property && (d->property->values.count() + d->property->onValues.count()) > 1))
return List;
QDeclarativeParser::Value *value = d->value;
@@ -1628,6 +1631,13 @@ QList<QDeclarativeDomValue> QDeclarativeDomList::values() const
rv << v;
}
+ for (int ii = 0; ii < d->property->onValues.count(); ++ii) {
+ QDeclarativeDomValue v;
+ v.d->value = d->property->onValues.at(ii);
+ v.d->value->addref();
+ rv << v;
+ }
+
return rv;
}
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index af75e98..41d55d7 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -167,6 +167,7 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
QDeclarativeItemModule::defineModule();
QDeclarativeUtilModule::defineModule();
QDeclarativeEnginePrivate::defineModule();
+ QDeclarativeValueTypeFactory::registerValueTypes();
}
globalClass = new QDeclarativeGlobalScriptClass(&scriptEngine);
@@ -236,9 +237,13 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr
qtObject.setProperty(QLatin1String("tint"), newFunction(QDeclarativeEnginePrivate::tint, 2));
}
+ //date/time formatting
+ qtObject.setProperty(QLatin1String("formatDate"),newFunction(QDeclarativeEnginePrivate::formatDate, 2));
+ qtObject.setProperty(QLatin1String("formatTime"),newFunction(QDeclarativeEnginePrivate::formatTime, 2));
+ qtObject.setProperty(QLatin1String("formatDateTime"),newFunction(QDeclarativeEnginePrivate::formatDateTime, 2));
+
//misc methods
qtObject.setProperty(QLatin1String("closestAngle"), newFunction(QDeclarativeEnginePrivate::closestAngle, 2));
- qtObject.setProperty(QLatin1String("playSound"), newFunction(QDeclarativeEnginePrivate::playSound, 1));
qtObject.setProperty(QLatin1String("openUrlExternally"),newFunction(QDeclarativeEnginePrivate::desktopOpenUrl, 1));
qtObject.setProperty(QLatin1String("md5"),newFunction(QDeclarativeEnginePrivate::md5, 1));
qtObject.setProperty(QLatin1String("btoa"),newFunction(QDeclarativeEnginePrivate::btoa, 1));
@@ -936,6 +941,66 @@ QScriptValue QDeclarativeEnginePrivate::vector(QScriptContext *ctxt, QScriptEngi
return engine->newVariant(qVariantFromValue(QVector3D(x, y, z)));
}
+QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptEngine*engine)
+{
+ int argCount = ctxt->argumentCount();
+ if(argCount == 0 || argCount > 2)
+ return engine->nullValue();
+
+ QDate date = ctxt->argument(0).toDateTime().date();
+ Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
+ if (argCount == 2) {
+ if (ctxt->argument(1).isString()) {
+ QString format = ctxt->argument(1).toString();
+ return engine->newVariant(qVariantFromValue(date.toString(format)));
+ } else if (ctxt->argument(1).isNumber()) {
+ enumFormat = Qt::DateFormat(ctxt->argument(1).toUInt32());
+ } else
+ return engine->nullValue();
+ }
+ return engine->newVariant(qVariantFromValue(date.toString(enumFormat)));
+}
+
+QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptEngine*engine)
+{
+ int argCount = ctxt->argumentCount();
+ if(argCount == 0 || argCount > 2)
+ return engine->nullValue();
+
+ QTime date = ctxt->argument(0).toDateTime().time();
+ Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
+ if (argCount == 2) {
+ if (ctxt->argument(1).isString()) {
+ QString format = ctxt->argument(1).toString();
+ return engine->newVariant(qVariantFromValue(date.toString(format)));
+ } else if (ctxt->argument(1).isNumber()) {
+ enumFormat = Qt::DateFormat(ctxt->argument(1).toUInt32());
+ } else
+ return engine->nullValue();
+ }
+ return engine->newVariant(qVariantFromValue(date.toString(enumFormat)));
+}
+
+QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScriptEngine*engine)
+{
+ int argCount = ctxt->argumentCount();
+ if(argCount == 0 || argCount > 2)
+ return engine->nullValue();
+
+ QDateTime date = ctxt->argument(0).toDateTime();
+ Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
+ if (argCount == 2) {
+ if (ctxt->argument(1).isString()) {
+ QString format = ctxt->argument(1).toString();
+ return engine->newVariant(qVariantFromValue(date.toString(format)));
+ } else if (ctxt->argument(1).isNumber()) {
+ enumFormat = Qt::DateFormat(ctxt->argument(1).toUInt32());
+ } else
+ return engine->nullValue();
+ }
+ return engine->newVariant(qVariantFromValue(date.toString(enumFormat)));
+}
+
QScriptValue QDeclarativeEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine *engine)
{
int argCount = ctxt->argumentCount();
@@ -1040,30 +1105,6 @@ QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngi
return qScriptValueFromValue(engine, qVariantFromValue(color));
}
-QScriptValue QDeclarativeEnginePrivate::playSound(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if (ctxt->argumentCount() != 1)
- return engine->undefinedValue();
-
- QUrl url(ctxt->argument(0).toString());
-
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
- if (url.isRelative()) {
- QDeclarativeContext *context = enginePriv->getContext(ctxt);
- if (!context)
- return engine->undefinedValue();
-
- url = context->resolvedUrl(url);
- }
-
- if (url.scheme() == QLatin1String("file")) {
-
- QSound::play(url.toLocalFile());
-
- }
- return engine->undefinedValue();
-}
-
QScriptValue QDeclarativeEnginePrivate::desktopOpenUrl(QScriptContext *ctxt, QScriptEngine *e)
{
if(ctxt->argumentCount() < 1)
@@ -1193,17 +1234,13 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine
else if (a == 0x00)
finalColor = color;
else {
- uint src = tintColor.rgba();
- uint dest = color.rgba();
+ qreal a = tintColor.alphaF();
+ qreal inv_a = 1.0 - a;
- uint res = (((a * (src & 0xFF00FF)) +
- ((0xFF - a) * (dest & 0xFF00FF))) >> 8) & 0xFF00FF;
- res |= (((a * ((src >> 8) & 0xFF00FF)) +
- ((0xFF - a) * ((dest >> 8) & 0xFF00FF)))) & 0xFF00FF00;
- if ((src & 0xFF000000) == 0xFF000000)
- res |= 0xFF000000;
-
- finalColor = QColor::fromRgba(res);
+ finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a,
+ tintColor.greenF() * a + color.greenF() * inv_a,
+ tintColor.blueF() * a + color.blueF() * inv_a,
+ a + inv_a * color.alphaF());
}
return qScriptValueFromValue(engine, qVariantFromValue(finalColor));
@@ -1383,7 +1420,11 @@ public:
paths += QFileInfo(base.toLocalFile()).path();
paths += importPath;
paths += QDeclarativeEnginePrivate::get(engine)->environmentImportPath;
+#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0))
QString builtinPath = QLibraryInfo::location(QLibraryInfo::ImportsPath);
+#else
+ QString builtinPath;
+#endif
if (!builtinPath.isEmpty())
paths += builtinPath;
@@ -1687,6 +1728,7 @@ QString QDeclarativeEngine::offlineStoragePath() const
\internal
Returns the result of the merge of \a baseName with \a dir, \a suffixes, and \a prefix.
+ The \a prefix must contain the dot.
*/
QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString &baseName,
const QStringList &suffixes,
@@ -1696,7 +1738,6 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString
QString pluginFileName = prefix;
pluginFileName += baseName;
- pluginFileName += QLatin1Char('.');
pluginFileName += suffix;
QFileInfo fileInfo(dir, pluginFileName);
@@ -1728,14 +1769,26 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString
QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString &baseName)
{
#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
- return resolvePlugin(dir, baseName, QStringList(QLatin1String("dll")));
+ return resolvePlugin(dir, baseName,
+ QStringList()
+# ifdef QT_DEBUG
+ << QLatin1String("d.dll") // try a qmake-style debug build first
+# endif
+ << QLatin1String(".dll"));
#elif defined(Q_OS_SYMBIAN)
- return resolvePlugin(dir, baseName, QStringList() << QLatin1String("dll") << QLatin1String("qtplugin"));
+ return resolvePlugin(dir, baseName,
+ QStringList()
+ << QLatin1String(".dll")
+ << QLatin1String(".qtplugin"));
#else
# if defined(Q_OS_DARWIN)
- return resolvePlugin(dir, baseName, QStringList() << QLatin1String("dylib") << QLatin1String("so") << QLatin1String("bundle"),
+ return resolvePlugin(dir, baseName,
+ QStringList()
+ << QLatin1String(".dylib")
+ << QLatin1String(".so")
+ << QLatin1String(".bundle"),
QLatin1String("lib"));
# else // Generic Unix
QStringList validSuffixList;
@@ -1746,14 +1799,14 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString
"In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
*/
- validSuffixList << QLatin1String("sl");
+ validSuffixList << QLatin1String(".sl");
# if defined __ia64
- validSuffixList << QLatin1String("so");
+ validSuffixList << QLatin1String(".so");
# endif
# elif defined(Q_OS_AIX)
- validSuffixList << QLatin1String("a") << QLatin1String("so");
+ validSuffixList << QLatin1String(".a") << QLatin1String(".so");
# elif defined(Q_OS_UNIX)
- validSuffixList << QLatin1String("so");
+ validSuffixList << QLatin1String(".so");
# endif
// Examples of valid library names:
diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h
index 0359f98..459a325 100644
--- a/src/declarative/qml/qdeclarativeengine_p.h
+++ b/src/declarative/qml/qdeclarativeengine_p.h
@@ -238,7 +238,8 @@ public:
QHash<const QMetaObject *, QDeclarativePropertyCache *> propertyCache;
QDeclarativePropertyCache *cache(QObject *obj) {
Q_Q(QDeclarativeEngine);
- if (!obj || QObjectPrivate::get(obj)->metaObject) return 0;
+ if (!obj || QObjectPrivate::get(obj)->metaObject ||
+ QObjectPrivate::get(obj)->wasDeleted) return 0;
const QMetaObject *mo = obj->metaObject();
QDeclarativePropertyCache *rv = propertyCache.value(mo);
if (!rv) {
@@ -318,7 +319,6 @@ public:
static QScriptValue tint(QScriptContext*, QScriptEngine*);
static QScriptValue closestAngle(QScriptContext*, QScriptEngine*);
- static QScriptValue playSound(QScriptContext*, QScriptEngine*);
static QScriptValue desktopOpenUrl(QScriptContext*, QScriptEngine*);
static QScriptValue md5(QScriptContext*, QScriptEngine*);
static QScriptValue btoa(QScriptContext*, QScriptEngine*);
@@ -326,6 +326,10 @@ public:
static QScriptValue consoleLog(QScriptContext*, QScriptEngine*);
static QScriptValue quit(QScriptContext*, QScriptEngine*);
+ static QScriptValue formatDate(QScriptContext*, QScriptEngine*);
+ static QScriptValue formatTime(QScriptContext*, QScriptEngine*);
+ static QScriptValue formatDateTime(QScriptContext*, QScriptEngine*);
+
static QScriptEngine *getScriptEngine(QDeclarativeEngine *e) { return &e->d_func()->scriptEngine; }
static QDeclarativeEngine *getEngine(QScriptEngine *e) { return static_cast<QDeclarativeScriptEngine*>(e)->p->q_func(); }
static QDeclarativeEnginePrivate *get(QDeclarativeEngine *e) { return e->d_func(); }
diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp
index 09882cb..3e4acbe 100644
--- a/src/declarative/qml/qdeclarativeenginedebug.cpp
+++ b/src/declarative/qml/qdeclarativeenginedebug.cpp
@@ -117,7 +117,7 @@ QDeclarativeEngineDebugServer::propertyData(QObject *obj, int propIdx)
QVariant value = prop.read(obj);
rv.value = valueContents(value);
- if (QVariant::Type(prop.userType()) < QVariant::UserType) {
+ if (QDeclarativeValueTypeFactory::isValueType(prop.userType())) {
rv.type = QDeclarativeObjectProperty::Basic;
} else if (QDeclarativeMetaType::isQObject(prop.userType())) {
rv.type = QDeclarativeObjectProperty::Object;
@@ -131,7 +131,7 @@ QDeclarativeEngineDebugServer::propertyData(QObject *obj, int propIdx)
QVariant QDeclarativeEngineDebugServer::valueContents(const QVariant &value) const
{
int userType = value.userType();
- if (QVariant::Type(userType) < QVariant::UserType)
+ if (QDeclarativeValueTypeFactory::isValueType(userType))
return value;
/*
diff --git a/src/declarative/qml/qdeclarativeenginedebug_p.h b/src/declarative/qml/qdeclarativeenginedebug_p.h
index 89da399..a95449b 100644
--- a/src/declarative/qml/qdeclarativeenginedebug_p.h
+++ b/src/declarative/qml/qdeclarativeenginedebug_p.h
@@ -53,7 +53,7 @@
// We mean it.
//
-#include "../debugger/qdeclarativedebugservice_p.h"
+#include <private/qdeclarativedebugservice_p.h>
#include <QtCore/qurl.h>
#include <QtCore/qvariant.h>
diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp
index ae1e790..e528e9e 100644
--- a/src/declarative/qml/qdeclarativeexpression.cpp
+++ b/src/declarative/qml/qdeclarativeexpression.cpp
@@ -46,6 +46,7 @@
#include "qdeclarativecontext_p.h"
#include "qdeclarativerewrite_p.h"
#include "qdeclarativecompiler_p.h"
+#include "qdeclarativeglobalscriptclass_p.h"
#include <QtCore/qdebug.h>
#include <QtScript/qscriptprogram.h>
@@ -135,6 +136,7 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContext *ctxt, void *expr,
if (!dd->cachedClosures.at(progIdx)) {
QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
scriptContext->pushScope(ep->contextClass->newSharedContext());
+ scriptContext->pushScope(ep->globalClass->globalObject());
dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(data->expression, data->url, data->line));
scriptEngine->popContext();
}
@@ -151,9 +153,11 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContext *ctxt, void *expr,
new QScriptProgram(data->expression, data->url, data->line);
}
- data->expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx));
+ data->expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx),
+ &data->expressionContext);
#else
- data->expressionFunction = evalInObjectScope(ctxt, me, data->expression);
+ data->expressionFunction = evalInObjectScope(ctxt, me, data->expression,
+ &data->expressionContext);
#endif
data->expressionFunctionValid = true;
@@ -164,22 +168,34 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContext *ctxt, void *expr,
}
QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContext *context, QObject *object,
- const QString &program)
+ const QString &program, QScriptValue *contextObject)
{
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine());
QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine);
- scriptContext->pushScope(ep->contextClass->newContext(context, object));
+ if (contextObject) {
+ *contextObject = ep->contextClass->newContext(context, object);
+ scriptContext->pushScope(*contextObject);
+ } else {
+ scriptContext->pushScope(ep->contextClass->newContext(context, object));
+ }
+ scriptContext->pushScope(ep->globalClass->globalObject());
QScriptValue rv = ep->scriptEngine.evaluate(program);
ep->scriptEngine.popContext();
return rv;
}
QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContext *context, QObject *object,
- const QScriptProgram &program)
+ const QScriptProgram &program, QScriptValue *contextObject)
{
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine());
QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine);
- scriptContext->pushScope(ep->contextClass->newContext(context, object));
+ if (contextObject) {
+ *contextObject = ep->contextClass->newContext(context, object);
+ scriptContext->pushScope(*contextObject);
+ } else {
+ scriptContext->pushScope(ep->contextClass->newContext(context, object));
+ }
+ scriptContext->pushScope(ep->globalClass->globalObject());
QScriptValue rv = ep->scriptEngine.evaluate(program);
ep->scriptEngine.popContext();
return rv;
@@ -326,15 +342,14 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo
QDeclarativeEngine *engine = data->context()->engine();
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- if (secondaryScope)
- ctxtPriv->defaultObjects.append(secondaryScope);
-
QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
if (!data->expressionFunctionValid) {
QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
- scriptContext->pushScope(ep->contextClass->newContext(data->context(), data->me));
+ data->expressionContext = ep->contextClass->newContext(data->context(), data->me);
+ scriptContext->pushScope(data->expressionContext);
+ scriptContext->pushScope(ep->globalClass->globalObject());
if (data->expressionRewritten) {
data->expressionFunction = scriptEngine->evaluate(data->expression,
@@ -357,11 +372,14 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo
QDeclarativeContext *oldSharedContext = 0;
QObject *oldSharedScope = 0;
+ QObject *oldOverride = 0;
if (data->isShared) {
oldSharedContext = ep->sharedContext;
oldSharedScope = ep->sharedScope;
ep->sharedContext = data->context();
ep->sharedScope = data->me;
+ } else {
+ oldOverride = ep->contextClass->setOverrideObject(data->expressionContext, secondaryScope);
}
QScriptValue svalue = data->expressionFunction.call();
@@ -369,6 +387,8 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo
if (data->isShared) {
ep->sharedContext = oldSharedContext;
ep->sharedScope = oldSharedScope;
+ } else {
+ ep->contextClass->setOverrideObject(data->expressionContext, oldOverride);
}
if (isUndefined)
@@ -383,12 +403,6 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo
data->error = QDeclarativeError();
}
- if (secondaryScope) {
- QObject *last = ctxtPriv->defaultObjects.takeLast();
- Q_ASSERT(last == secondaryScope);
- Q_UNUSED(last);
- }
-
QVariant rv;
if (svalue.isArray()) {
diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h
index 91ac4c0..cd1729d 100644
--- a/src/declarative/qml/qdeclarativeexpression_p.h
+++ b/src/declarative/qml/qdeclarativeexpression_p.h
@@ -119,6 +119,7 @@ public:
bool expressionFunctionValid:1;
bool expressionRewritten:1;
QScriptValue expressionFunction;
+ QScriptValue expressionContext;
QObject *me;
bool trackChange;
@@ -180,8 +181,8 @@ public:
virtual void emitValueChanged();
static void exceptionToError(QScriptEngine *, QDeclarativeError &);
- static QScriptValue evalInObjectScope(QDeclarativeContext *, QObject *, const QString &);
- static QScriptValue evalInObjectScope(QDeclarativeContext *, QObject *, const QScriptProgram &);
+ static QScriptValue evalInObjectScope(QDeclarativeContext *, QObject *, const QString &, QScriptValue * = 0);
+ static QScriptValue evalInObjectScope(QDeclarativeContext *, QObject *, const QScriptProgram &, QScriptValue * = 0);
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeglobal_p.h b/src/declarative/qml/qdeclarativeglobal_p.h
index bbdc91c..1041992 100644
--- a/src/declarative/qml/qdeclarativeglobal_p.h
+++ b/src/declarative/qml/qdeclarativeglobal_p.h
@@ -79,7 +79,7 @@ struct QDeclarativeGraphics_DerivedObject : public QObject
neither \a parent nor the object's previous parent (if it had one) will
receive ChildRemoved or ChildAdded events.
*/
-inline void QDeclarativeGraphics_setParent_noEvent(QObject *object, QObject *parent)
+inline void QDeclarative_setParent_noEvent(QObject *object, QObject *parent)
{
static_cast<QDeclarativeGraphics_DerivedObject *>(object)->setParent_noEvent(parent);
}
diff --git a/src/declarative/qml/qdeclarativeglobalscriptclass.cpp b/src/declarative/qml/qdeclarativeglobalscriptclass.cpp
index 5b06b42..9ee2fe5 100644
--- a/src/declarative/qml/qdeclarativeglobalscriptclass.cpp
+++ b/src/declarative/qml/qdeclarativeglobalscriptclass.cpp
@@ -53,15 +53,17 @@ QT_BEGIN_NAMESPACE
QDeclarativeGlobalScriptClass::QDeclarativeGlobalScriptClass(QScriptEngine *engine)
: QScriptClass(engine)
{
- QScriptValue v = engine->newObject();
- globalObject = engine->globalObject();
+ QScriptValue globalObject = engine->globalObject();
+ m_globalObject = engine->newObject();
QScriptValueIterator iter(globalObject);
while (iter.hasNext()) {
iter.next();
- v.setProperty(iter.scriptName(), iter.value());
+ m_globalObject.setProperty(iter.scriptName(), iter.value());
+ m_illegalNames.insert(iter.name());
}
+ QScriptValue v = engine->newObject();
v.setScriptClass(this);
engine->setGlobalObject(v);
}
@@ -101,12 +103,14 @@ void QDeclarativeGlobalScriptClass::setProperty(QScriptValue &object,
engine()->currentContext()->throwError(error);
}
+/* This method is for the use of tst_qdeclarativeecmascript::callQtInvokables() only */
void QDeclarativeGlobalScriptClass::explicitSetProperty(const QString &name, const QScriptValue &value)
{
+ QScriptValue globalObject = engine()->globalObject();
+
QScriptValue v = engine()->newObject();
- globalObject = engine()->globalObject();
- QScriptValueIterator iter(globalObject);
+ QScriptValueIterator iter(v);
while (iter.hasNext()) {
iter.next();
v.setProperty(iter.scriptName(), iter.value());
@@ -114,6 +118,7 @@ void QDeclarativeGlobalScriptClass::explicitSetProperty(const QString &name, con
v.setProperty(name, value);
v.setScriptClass(this);
+
engine()->setGlobalObject(v);
}
diff --git a/src/declarative/qml/qdeclarativeglobalscriptclass_p.h b/src/declarative/qml/qdeclarativeglobalscriptclass_p.h
index a33cf5e..1b34aee 100644
--- a/src/declarative/qml/qdeclarativeglobalscriptclass_p.h
+++ b/src/declarative/qml/qdeclarativeglobalscriptclass_p.h
@@ -54,6 +54,7 @@
//
#include <QtScript/qscriptclass.h>
+#include <QtCore/qset.h>
QT_BEGIN_NAMESPACE
@@ -74,8 +75,12 @@ public:
void explicitSetProperty(const QString &, const QScriptValue &);
+ const QScriptValue &globalObject() const { return m_globalObject; }
+ const QSet<QString> &illegalNames() const { return m_illegalNames; }
+
private:
- QScriptValue globalObject;
+ QSet<QString> m_illegalNames;
+ QScriptValue m_globalObject;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h
index d8af6a7..ec32b35 100644
--- a/src/declarative/qml/qdeclarativeinstruction_p.h
+++ b/src/declarative/qml/qdeclarativeinstruction_p.h
@@ -161,154 +161,180 @@ public:
Type type;
unsigned short line;
+
+ struct InitInstruction {
+ int bindingsSize;
+ int parserStatusSize;
+ int contextCache;
+ int compiledBinding;
+ };
+ struct CreateInstruction {
+ int type;
+ int data;
+ int bindingBits;
+ ushort column;
+ };
+ struct StoreMetaInstruction {
+ int data;
+ int aliasData;
+ int propertyCache;
+ };
+ struct SetIdInstruction {
+ int value;
+ int index;
+ };
+ struct AssignValueSourceInstruction {
+ int property;
+ int owner;
+ int castValue;
+ };
+ struct AssignValueInterceptorInstruction {
+ int property;
+ int owner;
+ int castValue;
+ };
+ struct AssignBindingInstruction {
+ unsigned int property;
+ int value;
+ short context;
+ short owner;
+ };
+ struct FetchInstruction {
+ int property;
+ };
+ struct FetchValueInstruction {
+ int property;
+ int type;
+ };
+ struct FetchQmlListInstruction {
+ int property;
+ int type;
+ };
+ struct BeginInstruction {
+ int castValue;
+ };
+ struct StoreFloatInstruction {
+ int propertyIndex;
+ float value;
+ };
+ struct StoreDoubleInstruction {
+ int propertyIndex;
+ double value;
+ };
+ struct StoreIntegerInstruction {
+ int propertyIndex;
+ int value;
+ };
+ struct StoreBoolInstruction {
+ int propertyIndex;
+ bool value;
+ };
+ struct StoreStringInstruction {
+ int propertyIndex;
+ int value;
+ };
+ struct StoreScriptStringInstruction {
+ int propertyIndex;
+ int value;
+ int scope;
+ };
+ struct StoreScriptInstruction {
+ int value;
+ };
+ struct StoreUrlInstruction {
+ int propertyIndex;
+ int value;
+ };
+ struct StoreColorInstruction {
+ int propertyIndex;
+ unsigned int value;
+ };
+ struct StoreDateInstruction {
+ int propertyIndex;
+ int value;
+ };
+ struct StoreTimeInstruction {
+ int propertyIndex;
+ int valueIndex;
+ };
+ struct StoreDateTimeInstruction {
+ int propertyIndex;
+ int valueIndex;
+ };
+ struct StoreRealPairInstruction {
+ int propertyIndex;
+ int valueIndex;
+ };
+ struct StoreRectInstruction {
+ int propertyIndex;
+ int valueIndex;
+ };
+ struct StoreVector3DInstruction {
+ int propertyIndex;
+ int valueIndex;
+ };
+ struct StoreObjectInstruction {
+ int propertyIndex;
+ };
+ struct AssignCustomTypeInstruction {
+ int propertyIndex;
+ int valueIndex;
+ };
+ struct StoreSignalInstruction {
+ int signalIndex;
+ int value;
+ int context;
+ };
+ struct AssignSignalObjectInstruction {
+ int signal;
+ };
+ struct CreateComponentInstruction {
+ int count;
+ ushort column;
+ int endLine;
+ int metaObject;
+ };
+ struct FetchAttachedInstruction {
+ int id;
+ };
+ struct DeferInstruction {
+ int deferCount;
+ };
+
union {
- struct {
- int bindingsSize;
- int parserStatusSize;
- int contextCache;
- int compiledBinding;
- } init;
- struct {
- int type;
- int data;
- int bindingBits;
- ushort column;
- } create;
- struct {
- int data;
- int aliasData;
- int propertyCache;
- } storeMeta;
- struct {
- int value;
- int index;
- } setId;
- struct {
- int property;
- int owner;
- int castValue;
- } assignValueSource;
- struct {
- int property;
- int owner;
- int castValue;
- } assignValueInterceptor;
- struct {
- unsigned int property;
- int value;
- short context;
- short owner;
- } assignBinding;
- struct {
- int property;
- int id;
- } assignIdOptBinding;
- struct {
- int property;
- int contextIdx;
- short context;
- short notifyIdx;
- } assignObjPropBinding;
- struct {
- int property;
- } fetch;
- struct {
- int property;
- int type;
- } fetchValue;
- struct {
- int property;
- int type;
- } fetchQmlList;
- struct {
- int castValue;
- } begin;
- struct {
- int propertyIndex;
- float value;
- } storeFloat;
- struct {
- int propertyIndex;
- double value;
- } storeDouble;
- struct {
- int propertyIndex;
- int value;
- } storeInteger;
- struct {
- int propertyIndex;
- bool value;
- } storeBool;
- struct {
- int propertyIndex;
- int value;
- } storeString;
- struct {
- int propertyIndex;
- int value;
- int scope;
- } storeScriptString;
- struct {
- int value;
- } storeScript;
- struct {
- int propertyIndex;
- int value;
- } storeUrl;
- struct {
- int propertyIndex;
- unsigned int value;
- } storeColor;
- struct {
- int propertyIndex;
- int value;
- } storeDate;
- struct {
- int propertyIndex;
- int valueIndex;
- } storeTime;
- struct {
- int propertyIndex;
- int valueIndex;
- } storeDateTime;
- struct {
- int propertyIndex;
- int valueIndex;
- } storeRealPair;
- struct {
- int propertyIndex;
- int valueIndex;
- } storeRect;
- struct {
- int propertyIndex;
- int valueIndex;
- } storeVector3D;
- struct {
- int propertyIndex;
- } storeObject;
- struct {
- int propertyIndex;
- int valueIndex;
- } assignCustomType;
- struct {
- int signalIndex;
- int value;
- } storeSignal;
- struct {
- int signal;
- } assignSignalObject;
- struct {
- int count;
- ushort column;
- int endLine;
- int metaObject;
- } createComponent;
- struct {
- int id;
- } fetchAttached;
- struct {
- int deferCount;
- } defer;
+ InitInstruction init;
+ CreateInstruction create;
+ StoreMetaInstruction storeMeta;
+ SetIdInstruction setId;
+ AssignValueSourceInstruction assignValueSource;
+ AssignValueInterceptorInstruction assignValueInterceptor;
+ AssignBindingInstruction assignBinding;
+ FetchInstruction fetch;
+ FetchValueInstruction fetchValue;
+ FetchQmlListInstruction fetchQmlList;
+ BeginInstruction begin;
+ StoreFloatInstruction storeFloat;
+ StoreDoubleInstruction storeDouble;
+ StoreIntegerInstruction storeInteger;
+ StoreBoolInstruction storeBool;
+ StoreStringInstruction storeString;
+ StoreScriptStringInstruction storeScriptString;
+ StoreScriptInstruction storeScript;
+ StoreUrlInstruction storeUrl;
+ StoreColorInstruction storeColor;
+ StoreDateInstruction storeDate;
+ StoreTimeInstruction storeTime;
+ StoreDateTimeInstruction storeDateTime;
+ StoreRealPairInstruction storeRealPair;
+ StoreRectInstruction storeRect;
+ StoreVector3DInstruction storeVector3D;
+ StoreObjectInstruction storeObject;
+ AssignCustomTypeInstruction assignCustomType;
+ StoreSignalInstruction storeSignal;
+ AssignSignalObjectInstruction assignSignalObject;
+ CreateComponentInstruction createComponent;
+ FetchAttachedInstruction fetchAttached;
+ DeferInstruction defer;
};
void dump(QDeclarativeCompiledData *);
diff --git a/src/declarative/qml/qdeclarativelist.h b/src/declarative/qml/qdeclarativelist.h
index 8d59384..eac4967 100644
--- a/src/declarative/qml/qdeclarativelist.h
+++ b/src/declarative/qml/qdeclarativelist.h
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QObject;
-class QMetaObject;
+struct QMetaObject;
template<typename T>
struct QDeclarativeListProperty {
typedef void (*AppendFunction)(QDeclarativeListProperty<T> *, T*);
diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp
index abbb9d6..50ab56b 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -286,6 +286,11 @@ QDeclarativeCustomParser *QDeclarativeType::customParser() const
return d->m_customParser;
}
+bool QDeclarativeType::isCreatable() const
+{
+ return d->m_newFunc != 0;
+}
+
bool QDeclarativeType::isInterface() const
{
return d->m_isInterface;
@@ -402,7 +407,7 @@ int QDeclarativePrivate::registerType(const QDeclarativePrivate::RegisterType &t
data->types.append(dtype);
data->idToType.insert(dtype->typeId(), dtype);
- data->idToType.insert(dtype->qListTypeId(), dtype);
+ if (dtype->qListTypeId()) data->idToType.insert(dtype->qListTypeId(), dtype);
if (!dtype->qmlTypeName().isEmpty())
data->nameToType.insertMulti(dtype->qmlTypeName(), dtype);
@@ -414,7 +419,7 @@ int QDeclarativePrivate::registerType(const QDeclarativePrivate::RegisterType &t
if (data->lists.size() <= type.listId)
data->lists.resize(type.listId + 16);
data->objects.setBit(type.typeId, true);
- data->lists.setBit(type.listId, true);
+ if (type.listId) data->lists.setBit(type.listId, true);
return index;
}
diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h
index ec5c045..cf8946d 100644
--- a/src/declarative/qml/qdeclarativemetatype_p.h
+++ b/src/declarative/qml/qdeclarativemetatype_p.h
@@ -114,6 +114,8 @@ public:
QDeclarativeCustomParser *customParser() const;
+ bool isCreatable() const;
+
bool isInterface() const;
int typeId() const;
int qListTypeId() const;
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
index 542f417..e6f6e5f 100644
--- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
+++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
@@ -232,7 +232,7 @@ QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name)
QDeclarativeEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex);
}
- if ((uint)lastData->propType < QVariant::UserType) {
+ if (QDeclarativeValueTypeFactory::isValueType((uint)lastData->propType)) {
QDeclarativeValueType *valueType = enginePriv->valueTypes[lastData->propType];
if (valueType)
return Value(scriptEngine, enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType));
@@ -442,6 +442,13 @@ QDeclarativeObjectMethodScriptClass::QDeclarativeObjectMethodScriptClass(QDeclar
engine(bindEngine)
{
setSupportsCall(true);
+
+ QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
+
+ m_connect = scriptEngine->newFunction(connect);
+ m_connectId = createPersistentIdentifier(QLatin1String("connect"));
+ m_disconnect = scriptEngine->newFunction(disconnect);
+ m_disconnectId = createPersistentIdentifier(QLatin1String("disconnect"));
}
QDeclarativeObjectMethodScriptClass::~QDeclarativeObjectMethodScriptClass()
@@ -455,6 +462,80 @@ QScriptValue QDeclarativeObjectMethodScriptClass::newMethod(QObject *object, con
return newObject(scriptEngine, this, new MethodData(object, *method));
}
+QScriptValue QDeclarativeObjectMethodScriptClass::connect(QScriptContext *context, QScriptEngine *engine)
+{
+ QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
+
+ QScriptValue that = context->thisObject();
+ if (&p->objectClass->methods != scriptClass(that))
+ return engine->undefinedValue();
+
+ MethodData *data = (MethodData *)object(that);
+
+ if (!data->object || context->argumentCount() == 0)
+ return engine->undefinedValue();
+
+ QByteArray signal("2");
+ signal.append(data->object->metaObject()->method(data->data.coreIndex).signature());
+
+ if (context->argumentCount() == 1) {
+ qScriptConnect(data->object, signal.constData(), QScriptValue(), context->argument(0));
+ } else {
+ qScriptConnect(data->object, signal.constData(), context->argument(0), context->argument(1));
+ }
+
+ return engine->undefinedValue();
+}
+
+QScriptValue QDeclarativeObjectMethodScriptClass::disconnect(QScriptContext *context, QScriptEngine *engine)
+{
+ QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
+
+ QScriptValue that = context->thisObject();
+ if (&p->objectClass->methods != scriptClass(that))
+ return engine->undefinedValue();
+
+ MethodData *data = (MethodData *)object(that);
+
+ if (!data->object || context->argumentCount() == 0)
+ return engine->undefinedValue();
+
+ QByteArray signal("2");
+ signal.append(data->object->metaObject()->method(data->data.coreIndex).signature());
+
+ if (context->argumentCount() == 1) {
+ qScriptDisconnect(data->object, signal.constData(), QScriptValue(), context->argument(0));
+ } else {
+ qScriptDisconnect(data->object, signal.constData(), context->argument(0), context->argument(1));
+ }
+
+ return engine->undefinedValue();
+}
+
+QScriptClass::QueryFlags
+QDeclarativeObjectMethodScriptClass::queryProperty(Object *, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ if (name == m_connectId.identifier || name == m_disconnectId.identifier)
+ return QScriptClass::HandlesReadAccess;
+ else
+ return 0;
+
+}
+
+QDeclarativeObjectScriptClass::ScriptValue
+QDeclarativeObjectMethodScriptClass::property(Object *, const Identifier &name)
+{
+ QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
+
+ if (name == m_connectId.identifier)
+ return Value(scriptEngine, m_connect);
+ else if (name == m_disconnectId.identifier)
+ return Value(scriptEngine, m_disconnect);
+ else
+ return Value();
+}
+
namespace {
struct MetaCallArgument {
inline MetaCallArgument();
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h
index 8023756..04e760f 100644
--- a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h
+++ b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h
@@ -73,10 +73,21 @@ public:
~QDeclarativeObjectMethodScriptClass();
QScriptValue newMethod(QObject *, const QDeclarativePropertyCache::Data *);
+
protected:
virtual Value call(Object *, QScriptContext *);
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags);
+ virtual Value property(Object *, const Identifier &);
private:
+ PersistentIdentifier m_connectId;
+ PersistentIdentifier m_disconnectId;
+ QScriptValue m_connect;
+ QScriptValue m_disconnect;
+
+ static QScriptValue connect(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue disconnect(QScriptContext *context, QScriptEngine *engine);
+
QDeclarativeEngine *engine;
};
#endif
@@ -119,6 +130,7 @@ protected:
private:
#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
+ friend class QDeclarativeObjectMethodScriptClass;
QDeclarativeObjectMethodScriptClass methods;
#endif
diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp
index 5ac49d5..b0599ad 100644
--- a/src/declarative/qml/qdeclarativeparser.cpp
+++ b/src/declarative/qml/qdeclarativeparser.cpp
@@ -221,12 +221,14 @@ QDeclarativeParser::Property::~Property()
{
foreach(Value *value, values)
value->release();
+ foreach(Value *value, onValues)
+ value->release();
if (value) value->release();
}
-Object *QDeclarativeParser::Property::getValue()
+Object *QDeclarativeParser::Property::getValue(const LocationSpan &l)
{
- if (!value) value = new Object;
+ if (!value) { value = new Object; value->location = l; }
return value;
}
@@ -235,9 +237,14 @@ void QDeclarativeParser::Property::addValue(Value *v)
values << v;
}
+void QDeclarativeParser::Property::addOnValue(Value *v)
+{
+ onValues << v;
+}
+
bool QDeclarativeParser::Property::isEmpty() const
{
- return !value && values.isEmpty();
+ return !value && values.isEmpty() && onValues.isEmpty();
}
QDeclarativeParser::Value::Value()
diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h
index aae507e..5bf4b68 100644
--- a/src/declarative/qml/qdeclarativeparser_p.h
+++ b/src/declarative/qml/qdeclarativeparser_p.h
@@ -104,6 +104,11 @@ namespace QDeclarativeParser
Location start;
Location end;
LocationRange range;
+
+ bool operator<(LocationSpan &o) const {
+ return (start.line < o.start.line) ||
+ (start.line == o.start.line && start.column < o.start.column);
+ }
};
class Property;
@@ -318,8 +323,9 @@ namespace QDeclarativeParser
// The Object to which this property is attached
Object *parent;
- Object *getValue();
+ Object *getValue(const LocationSpan &);
void addValue(Value *v);
+ void addOnValue(Value *v);
// The QVariant::Type of the property, or 0 (QVariant::Invalid) if
// unknown.
@@ -333,6 +339,8 @@ namespace QDeclarativeParser
// The list of values assigned to this property. Content in values
// and value are mutually exclusive
QList<Value *> values;
+ // The list of values assigned to this property using the "on" syntax
+ QList<Value *> onValues;
// The accessed property. This is used to represent dot properties.
// Content in value and values are mutually exclusive.
Object *value;
diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp
index e1ec2cd..4f73b89 100644
--- a/src/declarative/qml/qdeclarativeproperty.cpp
+++ b/src/declarative/qml/qdeclarativeproperty.cpp
@@ -238,10 +238,10 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name
if (property->flags & QDeclarativePropertyCache::Data::IsFunction)
return; // Not an object property
- if (ii == (path.count() - 2) && property->propType < (int)QVariant::UserType) {
+ if (ii == (path.count() - 2) && QDeclarativeValueTypeFactory::isValueType(property->propType)) {
// We're now at a value type property. We can use a global valuetypes array as we
// never actually use the objects, just look up their properties.
- QObject *typeObject = qmlValueTypes()->valueTypes[property->propType];
+ QObject *typeObject = (*qmlValueTypes())[property->propType];
if (!typeObject) return; // Not a value type
int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData());
@@ -346,7 +346,7 @@ QDeclarativePropertyPrivate::propertyTypeCategory() const
int type = propertyType();
if (type == QVariant::Invalid)
return QDeclarativeProperty::InvalidCategory;
- else if ((uint)type < QVariant::UserType)
+ else if (QDeclarativeValueTypeFactory::isValueType((uint)type))
return QDeclarativeProperty::Normal;
else if (core.flags & QDeclarativePropertyCache::Data::IsQObjectDerived)
return QDeclarativeProperty::Object;
@@ -793,7 +793,7 @@ QVariant QDeclarativeProperty::read(QObject *object, const QString &name, QDecla
QVariant QDeclarativePropertyPrivate::readValueProperty()
{
- if(isValueType()) {
+ if (isValueType()) {
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context);
QDeclarativeValueType *valueType = 0;
@@ -809,13 +809,20 @@ QVariant QDeclarativePropertyPrivate::readValueProperty()
if (!ep) delete valueType;
return rv;
- } else if(core.flags & QDeclarativePropertyCache::Data::IsQList) {
+ } else if (core.flags & QDeclarativePropertyCache::Data::IsQList) {
QDeclarativeListProperty<QObject> prop;
void *args[] = { &prop, 0 };
QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args);
return QVariant::fromValue(QDeclarativeListReferencePrivate::init(prop, core.propType, engine));
+ } else if (core.flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
+
+ QObject *rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args);
+ return QVariant::fromValue(rv);
+
} else {
return object->metaObject()->property(core.coreIndex).read(object.data());
diff --git a/src/declarative/qml/qdeclarativeproperty_p.h b/src/declarative/qml/qdeclarativeproperty_p.h
index 1fda7f4..c31e2d3 100644
--- a/src/declarative/qml/qdeclarativeproperty_p.h
+++ b/src/declarative/qml/qdeclarativeproperty_p.h
@@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
class QDeclarativeContext;
class QDeclarativeEnginePrivate;
class QDeclarativeExpression;
-class Q_AUTOTEST_EXPORT QDeclarativePropertyPrivate
+class Q_DECLARATIVE_EXPORT QDeclarativePropertyPrivate
{
public:
enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02 };
diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp
index 08b47b7..fea59e5 100644
--- a/src/declarative/qml/qdeclarativepropertycache.cpp
+++ b/src/declarative/qml/qdeclarativepropertycache.cpp
@@ -155,9 +155,9 @@ QDeclarativePropertyCache::Data QDeclarativePropertyCache::create(const QMetaObj
int parenIdx = methodName.indexOf(QLatin1Char('('));
Q_ASSERT(parenIdx != -1);
- methodName = methodName.left(parenIdx);
+ QStringRef methodNameRef = methodName.leftRef(parenIdx);
- if (methodName == property) {
+ if (methodNameRef == property) {
rv.load(m);
return rv;
}
diff --git a/src/declarative/qml/qdeclarativescript.cpp b/src/declarative/qml/qdeclarativescript.cpp
index acfb9e1..ac4b2c1 100644
--- a/src/declarative/qml/qdeclarativescript.cpp
+++ b/src/declarative/qml/qdeclarativescript.cpp
@@ -43,6 +43,7 @@
/*!
\qmlclass Script QDeclarativeScript
+ \since 4.7
\brief The Script element provides a way to add JavaScript code snippets in QML.
\ingroup group_utility
diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp
index f4c9cdd..fe516c5 100644
--- a/src/declarative/qml/qdeclarativescriptparser.cpp
+++ b/src/declarative/qml/qdeclarativescriptparser.cpp
@@ -85,8 +85,8 @@ class ProcessAST: protected AST::Visitor
{
const State &state = top();
if (state.property) {
- State s(state.property->getValue(),
- state.property->getValue()->getProperty(name.toUtf8()));
+ State s(state.property->getValue(location),
+ state.property->getValue(location)->getProperty(name.toUtf8()));
s.property->location = location;
push(s);
} else {
@@ -106,12 +106,12 @@ public:
void operator()(const QString &code, AST::Node *node);
protected:
- Object *defineObjectBinding(AST::UiQualifiedId *propertyName,
+ Object *defineObjectBinding(AST::UiQualifiedId *propertyName, bool onAssignment,
AST::UiQualifiedId *objectTypeName,
LocationSpan location,
AST::UiObjectInitializer *initializer = 0);
- Object *defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
+ Object *defineObjectBinding_helper(AST::UiQualifiedId *propertyName, bool onAssignment,
const QString &objectType,
AST::SourceLocation typeLocation,
LocationSpan location,
@@ -243,6 +243,7 @@ QString ProcessAST::asString(AST::UiQualifiedId *node) const
Object *
ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
+ bool onAssignment,
const QString &objectType,
AST::SourceLocation typeLocation,
LocationSpan location,
@@ -254,10 +255,19 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
(lastTypeDot >= 0 && objectType.at(lastTypeDot+1).isUpper()));
int propertyCount = 0;
- for (; propertyName; propertyName = propertyName->next){
+ for (AST::UiQualifiedId *name = propertyName; name; name = name->next){
++propertyCount;
- _stateStack.pushProperty(propertyName->name->asString(),
- this->location(propertyName));
+ _stateStack.pushProperty(name->name->asString(),
+ this->location(name));
+ }
+
+ if (!onAssignment && propertyCount && currentProperty() && currentProperty()->values.count()) {
+ QDeclarativeError error;
+ error.setDescription(QCoreApplication::translate("QDeclarativeParser","Property value set multiple times"));
+ error.setLine(this->location(propertyName).start.line);
+ error.setColumn(this->location(propertyName).start.column);
+ _parser->_errors << error;
+ return 0;
}
if (!isType) {
@@ -327,7 +337,10 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
Value *v = new Value;
v->object = obj;
v->location = obj->location;
- prop->addValue(v);
+ if (onAssignment)
+ prop->addOnValue(v);
+ else
+ prop->addValue(v);
while (propertyCount--)
_stateStack.pop();
@@ -363,7 +376,7 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
}
}
-Object *ProcessAST::defineObjectBinding(AST::UiQualifiedId *qualifiedId,
+Object *ProcessAST::defineObjectBinding(AST::UiQualifiedId *qualifiedId, bool onAssignment,
AST::UiQualifiedId *objectTypeName,
LocationSpan location,
AST::UiObjectInitializer *initializer)
@@ -395,7 +408,7 @@ Object *ProcessAST::defineObjectBinding(AST::UiQualifiedId *qualifiedId,
}
- return defineObjectBinding_helper(qualifiedId, objectType, typeLocation, location, initializer);
+ return defineObjectBinding_helper(qualifiedId, onAssignment, objectType, typeLocation, location, initializer);
}
LocationSpan ProcessAST::location(AST::UiQualifiedId *id)
@@ -623,7 +636,7 @@ bool ProcessAST::visit(AST::UiObjectDefinition *node)
LocationSpan l = location(node->firstSourceLocation(),
node->lastSourceLocation());
- defineObjectBinding(/*propertyName = */ 0,
+ defineObjectBinding(/*propertyName = */ 0, false,
node->qualifiedTypeNameId,
l,
node->initializer);
@@ -638,7 +651,7 @@ bool ProcessAST::visit(AST::UiObjectBinding *node)
LocationSpan l = location(node->qualifiedTypeNameId->identifierToken,
node->initializer->rbraceToken);
- defineObjectBinding(node->qualifiedId,
+ defineObjectBinding(node->qualifiedId, node->hasOnToken,
node->qualifiedTypeNameId,
l,
node->initializer);
@@ -674,14 +687,23 @@ bool ProcessAST::visit(AST::UiScriptBinding *node)
{
int propertyCount = 0;
AST::UiQualifiedId *propertyName = node->qualifiedId;
- for (; propertyName; propertyName = propertyName->next){
+ for (AST::UiQualifiedId *name = propertyName; name; name = name->next){
++propertyCount;
- _stateStack.pushProperty(propertyName->name->asString(),
- location(propertyName));
+ _stateStack.pushProperty(name->name->asString(),
+ location(name));
}
Property *prop = currentProperty();
+ if (prop->values.count()) {
+ QDeclarativeError error;
+ error.setDescription(QCoreApplication::translate("QDeclarativeParser","Property value set multiple times"));
+ error.setLine(this->location(propertyName).start.line);
+ error.setColumn(this->location(propertyName).start.column);
+ _parser->_errors << error;
+ return 0;
+ }
+
QDeclarativeParser::Variant primitive;
if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(node->statement)) {
@@ -724,16 +746,26 @@ bool ProcessAST::visit(AST::UiArrayBinding *node)
{
int propertyCount = 0;
AST::UiQualifiedId *propertyName = node->qualifiedId;
- for (; propertyName; propertyName = propertyName->next){
+ for (AST::UiQualifiedId *name = propertyName; name; name = name->next){
++propertyCount;
- _stateStack.pushProperty(propertyName->name->asString(),
- location(propertyName));
+ _stateStack.pushProperty(name->name->asString(),
+ location(name));
+ }
+
+ Property* prop = currentProperty();
+
+ if (prop->values.count()) {
+ QDeclarativeError error;
+ error.setDescription(QCoreApplication::translate("QDeclarativeParser","Property value set multiple times"));
+ error.setLine(this->location(propertyName).start.line);
+ error.setColumn(this->location(propertyName).start.column);
+ _parser->_errors << error;
+ return 0;
}
accept(node->members);
// For the DOM, store the position of the T_LBRACKET upto the T_RBRACKET as the range:
- Property* prop = currentProperty();
prop->listValueRange.offset = node->lbracketToken.offset;
prop->listValueRange.length = node->rbracketToken.offset + node->rbracketToken.length - node->lbracketToken.offset;
diff --git a/src/declarative/qml/qdeclarativevaluetype.cpp b/src/declarative/qml/qdeclarativevaluetype.cpp
index 01fa214..c070123 100644
--- a/src/declarative/qml/qdeclarativevaluetype.cpp
+++ b/src/declarative/qml/qdeclarativevaluetype.cpp
@@ -41,23 +41,88 @@
#include "qdeclarativevaluetype_p.h"
+#include "qdeclarativemetatype_p.h"
+
#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
+#if (QT_VERSION < QT_VERSION_CHECK(4,7,0))
+Q_DECLARE_METATYPE(QEasingCurve);
+#endif
+
+template<typename T>
+int qmlRegisterValueTypeEnums(const char *qmlName)
+{
+ QByteArray name(T::staticMetaObject.className());
+
+ QByteArray pointerName(name + '*');
+
+ QDeclarativePrivate::RegisterType type = {
+ 0,
+
+ qRegisterMetaType<T *>(pointerName.constData()), 0, 0,
+
+ "Qt", 4, 6, qmlName, &T::staticMetaObject,
+
+ 0, 0,
+
+ 0, 0, 0,
+
+ 0, 0,
+
+ 0
+ };
+
+ return QDeclarativePrivate::registerType(type);
+}
+
QDeclarativeValueTypeFactory::QDeclarativeValueTypeFactory()
{
// ### Optimize
for (unsigned int ii = 0; ii < (QVariant::UserType - 1); ++ii)
valueTypes[ii] = valueType(ii);
+#if (QT_VERSION < QT_VERSION_CHECK(4,7,0))
+ easingType = qMetaTypeId<QEasingCurve>();
+ easingValueType = valueType(easingType);
+#endif
}
QDeclarativeValueTypeFactory::~QDeclarativeValueTypeFactory()
{
for (unsigned int ii = 0; ii < (QVariant::UserType - 1); ++ii)
delete valueTypes[ii];
+#if (QT_VERSION < QT_VERSION_CHECK(4,7,0))
+ delete easingValueType;
+#endif
+}
+
+bool QDeclarativeValueTypeFactory::isValueType(int idx)
+{
+ if ((uint)idx < QVariant::UserType)
+ return true;
+#if (QT_VERSION < QT_VERSION_CHECK(4,7,0))
+ if (idx == qMetaTypeId<QEasingCurve>())
+ return true;
+#endif
+ return false;
+}
+
+void QDeclarativeValueTypeFactory::registerValueTypes()
+{
+ qmlRegisterValueTypeEnums<QDeclarativeEasingValueType>("Easing");
+ qmlRegisterValueTypeEnums<QDeclarativeFontValueType>("Font");
+}
+
+QDeclarativeValueType *QDeclarativeValueTypeFactory::operator[](int idx) const
+{
+#if (QT_VERSION < QT_VERSION_CHECK(4,7,0))
+ if (idx == easingType) return easingValueType;
+#endif
+ return valueTypes[idx];
}
+
QDeclarativeValueType *QDeclarativeValueTypeFactory::valueType(int t)
{
switch (t) {
@@ -75,11 +140,17 @@ QDeclarativeValueType *QDeclarativeValueTypeFactory::valueType(int t)
return new QDeclarativeRectFValueType;
case QVariant::Vector3D:
return new QDeclarativeVector3DValueType;
+#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0))
case QVariant::EasingCurve:
return new QDeclarativeEasingValueType;
+#endif
case QVariant::Font:
return new QDeclarativeFontValueType;
default:
+#if (QT_VERSION < QT_VERSION_CHECK(4,7,0))
+ if (t == qMetaTypeId<QEasingCurve>())
+ return new QDeclarativeEasingValueType;
+#endif
return 0;
}
}
@@ -495,7 +566,11 @@ void QDeclarativeEasingValueType::write(QObject *obj, int idx, QDeclarativePrope
QVariant QDeclarativeEasingValueType::value()
{
+#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0))
return QVariant(easing);
+#else
+ return QVariant::fromValue<QEasingCurve>(easing);
+#endif
}
void QDeclarativeEasingValueType::setValue(QVariant value)
diff --git a/src/declarative/qml/qdeclarativevaluetype_p.h b/src/declarative/qml/qdeclarativevaluetype_p.h
index cb153be..ad2f6c4 100644
--- a/src/declarative/qml/qdeclarativevaluetype_p.h
+++ b/src/declarative/qml/qdeclarativevaluetype_p.h
@@ -81,10 +81,19 @@ class Q_DECLARATIVE_EXPORT QDeclarativeValueTypeFactory
public:
QDeclarativeValueTypeFactory();
~QDeclarativeValueTypeFactory();
+ static bool isValueType(int);
static QDeclarativeValueType *valueType(int);
+ static void registerValueTypes();
+
+ QDeclarativeValueType *operator[](int idx) const;
+
+private:
QDeclarativeValueType *valueTypes[QVariant::UserType - 1];
- QDeclarativeValueType *operator[](int idx) const { return valueTypes[idx]; }
+#if (QT_VERSION < QT_VERSION_CHECK(4,7,0))
+ int easingType;
+ QDeclarativeValueType *easingValueType;
+#endif
};
class Q_AUTOTEST_EXPORT QDeclarativePointFValueType : public QDeclarativeValueType
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index 720b496..6a08674 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -217,7 +217,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati
// TODO: parent might be a layout
}
} else {
- QDeclarativeGraphics_setParent_noEvent(o, parent);
+ QDeclarative_setParent_noEvent(o, parent);
// o->setParent(parent);
}
}
@@ -538,13 +538,13 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarati
case QDeclarativeInstruction::StoreSignal:
{
QObject *target = stack.top();
- // XXX scope
- QMetaMethod signal =
- target->metaObject()->method(instr.storeSignal.signalIndex);
+ QObject *context = stack.at(stack.count() - 1 - instr.assignBinding.context);
+
+ QMetaMethod signal = target->metaObject()->method(instr.storeSignal.signalIndex);
QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
QDeclarativeExpression *expr =
- new QDeclarativeExpression(ctxt, primitives.at(instr.storeSignal.value), target);
+ new QDeclarativeExpression(ctxt, primitives.at(instr.storeSignal.value), context);
expr->setSourceLocation(comp->name, instr.line);
bs->setExpression(expr);
}
diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp
index 03151e4..784353a 100644
--- a/src/declarative/qml/qdeclarativeworkerscript.cpp
+++ b/src/declarative/qml/qdeclarativeworkerscript.cpp
@@ -365,6 +365,8 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
workerEngine->evaluate(script);
workerEngine->popContext();
+ } else {
+ qWarning().nospace() << "WorkerScript: Cannot find source file " << url.toString();
}
}
@@ -382,7 +384,7 @@ QVariant QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(const QScri
quint32 length = (quint32)value.property(QLatin1String("length")).toNumber();
for (quint32 ii = 0; ii < length; ++ii) {
- QVariant v = scriptValueToVariant(ii);
+ QVariant v = scriptValueToVariant(value.property(ii));
list << v;
}
@@ -561,6 +563,65 @@ void QDeclarativeWorkerScriptEngine::run()
delete d->workerEngine; d->workerEngine = 0;
}
+
+/*!
+ \qmlclass WorkerScript QDeclarativeWorkerScript
+ \brief The WorkerScript element enables the use of threads in QML.
+
+ Use WorkerScript to run operations in a new thread.
+ This is useful for running operations in the background so
+ that the main GUI thread is not blocked.
+
+ Messages can be passed between the new thread and the parent thread
+ using sendMessage() and the onMessage() handler.
+
+ Here is an example:
+
+ \qml
+ import Qt 4.6
+
+ Rectangle {
+ width: 300
+ height: 300
+
+ Text {
+ id: myText
+ text: 'Click anywhere'
+ }
+
+ WorkerScript {
+ id: myWorker
+ source: "script.js"
+
+ onMessage: {
+ myText.text = messageObject.reply
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: myWorker.sendMessage( {'x': mouse.x, 'y': mouse.y} );
+ }
+ }
+ \endqml
+
+ The above worker script specifies a javascript file, "script.js", that handles
+ the operations to be performed in the new thread:
+
+ \qml
+ WorkerScript.onMessage = function(message) {
+ // ... long-running operations and calculations are done here
+ WorkerScript.sendMessage( {'reply': 'Mouse is at ' + message.x + ',' + message.y} );
+ }
+ \endqml
+
+ When the user clicks anywhere within the rectangle, \c sendMessage() is
+ called, triggering the \tt WorkerScript.onMessage() handler in
+ \tt source.js. This in turn sends a reply message that is then received
+ by the \tt onMessage() handler of \tt myWorker.
+
+ \sa WorkerListModel
+*/
QDeclarativeWorkerScript::QDeclarativeWorkerScript(QObject *parent)
: QObject(parent), m_engine(0), m_scriptId(-1)
{
@@ -571,6 +632,12 @@ QDeclarativeWorkerScript::~QDeclarativeWorkerScript()
if (m_scriptId != -1) m_engine->removeWorkerScript(m_scriptId);
}
+/*!
+ \qmlproperty url WorkerScript::source
+
+ This holds the url of the javascript file that implements the
+ \tt WorkerScript.onMessage() handler for threaded operations.
+*/
QUrl QDeclarativeWorkerScript::source() const
{
return m_source;
@@ -589,6 +656,13 @@ void QDeclarativeWorkerScript::setSource(const QUrl &source)
emit sourceChanged();
}
+/*
+ \qmlmethod WorkerScript::sendMessage(jsobject message)
+
+ Sends the given \a message to a worker script handler in another
+ thread. The other worker script handler can receive this message
+ through the onMessage() handler.
+*/
void QDeclarativeWorkerScript::sendMessage(const QScriptValue &message)
{
if (!m_engine) {
@@ -616,6 +690,13 @@ void QDeclarativeWorkerScript::componentComplete()
}
}
+/*!
+ \qmlsignal WorkerScript::onMessage(jsobject msg)
+
+ This handler is called when a message \a msg is received from a worker
+ script in another thread through a call to sendMessage().
+*/
+
bool QDeclarativeWorkerScript::event(QEvent *event)
{
if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
@@ -841,6 +922,41 @@ bool QDeclarativeWorkerListModelAgent::event(QEvent *e)
return QObject::event(e);
}
+/*!
+ \qmlclass WorkerListModel QDeclarativeWorkerListModel
+ \brief The WorkerListModel element provides a threaded list model.
+
+ Use WorkerListModel together with WorkerScript to define a list model
+ that is controlled by a separate thread. This is useful if list modification
+ operations are synchronous and take some time: using WorkerListModel
+ moves these operations to a different thread and avoids blocking of the
+ main GUI thread.
+
+ The thread that creates the WorkerListModel can modify the model for any
+ initial set-up requirements. However, once the model has been modified by
+ the associated WorkerScript, the model can only be modified by that worker
+ script and becomes read-only to all other threads.
+
+ Here is an example application that uses WorkerScript to append the
+ current time to a WorkerListModel:
+
+ \snippet examples/declarative/workerlistmodel/timedisplay.qml 0
+
+ The included file, \tt dataloader.js, looks like this:
+
+ \snippet examples/declarative/workerlistmodel/dataloader.js 0
+
+ The application's \tt Timer object periodically sends a message to the
+ worker script by calling \tt WorkerScript::sendMessage(). When this message
+ is received, \tt WorkerScript.onMessage() is invoked in
+ \tt dataloader.js, which appends the current time to the worker list
+ model.
+
+ Note that unlike ListModel, WorkerListModel does not have \tt move() and
+ \tt setProperty() methods.
+
+ \sa WorkerScript, ListModel
+*/
QDeclarativeWorkerListModel::QDeclarativeWorkerListModel(QObject *parent)
: QListModelInterface(parent), m_agent(0)
{
@@ -854,6 +970,14 @@ QDeclarativeWorkerListModel::~QDeclarativeWorkerListModel()
}
}
+/*!
+ \qmlmethod WorkerListModel::clear()
+
+ Deletes all content from the model. The properties are cleared such that
+ different properties may be set on subsequent additions.
+
+ \sa append() remove()
+*/
void QDeclarativeWorkerListModel::clear()
{
if (m_agent) {
@@ -869,6 +993,13 @@ void QDeclarativeWorkerListModel::clear()
}
}
+/*!
+ \qmlmethod WorkerListModel::remove(int index)
+
+ Deletes the content at \a index from the model.
+
+ \sa clear()
+*/
void QDeclarativeWorkerListModel::remove(int index)
{
if (m_agent) {
@@ -884,6 +1015,18 @@ void QDeclarativeWorkerListModel::remove(int index)
emit countChanged();
}
+/*!
+ \qmlmethod WorkerListModel::append(jsobject dict)
+
+ Adds a new item to the end of the list model, with the
+ values in \a dict.
+
+ \code
+ FruitModel.append({"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ \sa set() remove()
+*/
void QDeclarativeWorkerListModel::append(const QScriptValue &value)
{
if (m_agent) {
@@ -914,6 +1057,21 @@ void QDeclarativeWorkerListModel::append(const QScriptValue &value)
emit countChanged();
}
+/*!
+ \qmlmethod WorkerListModel::insert(int index, jsobject dict)
+
+ Adds a new item to the list model at position \a index, with the
+ values in \a dict.
+
+ \code
+ FruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ The \a index must be to an existing item in the list, or one past
+ the end of the list (equivalent to append).
+
+ \sa set() append()
+*/
void QDeclarativeWorkerListModel::insert(int index, const QScriptValue &value)
{
if (m_agent) {
@@ -946,6 +1104,30 @@ void QDeclarativeWorkerListModel::insert(int index, const QScriptValue &value)
emit countChanged();
}
+/*!
+ \qmlmethod object ListModel::get(int index)
+
+ Returns the item at \a index in the list model.
+
+ \code
+ FruitModel.append({"cost": 5.95, "name":"Jackfruit"})
+ FruitModel.get(0).cost
+ \endcode
+
+ The \a index must be an element in the list.
+
+ Note that properties of the returned object that are themselves objects
+ will also be models, and this get() method is used to access elements:
+
+ \code
+ FruitModel.append(..., "attributes":
+ [{"name":"spikes","value":"7mm"},
+ {"name":"color","value":"green"}]);
+ FruitModel.get(0).attributes.get(1).value; // == "green"
+ \endcode
+
+ \sa append()
+*/
QScriptValue QDeclarativeWorkerListModel::get(int index) const
{
QDeclarativeEngine *engine = qmlEngine(this);
@@ -962,6 +1144,21 @@ QScriptValue QDeclarativeWorkerListModel::get(int index) const
return rv;
}
+/*!
+ \qmlmethod WorkerListModel::set(int index, jsobject dict)
+
+ Changes the item at \a index in the list model with the
+ values in \a dict. Properties not appearing in \a valuemap
+ are left unchanged.
+
+ \code
+ FruitModel.set(3, {"cost": 5.95, "name":"Pizza"})
+ \endcode
+
+ The \a index must be an element in the list.
+
+ \sa append()
+*/
void QDeclarativeWorkerListModel::set(int index, const QScriptValue &value)
{
if (m_agent) {
@@ -995,6 +1192,22 @@ void QDeclarativeWorkerListModel::set(int index, const QScriptValue &value)
}
}
+/*!
+ \qmlmethod WorkerListModel::sync()
+
+ Writes any unsaved changes to the list model. This must be called after
+ changes have been made to the list model in the worker script.
+
+ Note that this method can only be called from the associated worker script.
+*/
+void QDeclarativeWorkerListModel::sync()
+{
+ // This is really a dummy method to make it look like sync() exists in
+ // WorkerListModel (and not QDeclarativeWorkerListModelAgent) and to let
+ // us document sync().
+ qmlInfo(this) << "sync() can only be called from a WorkerScript";
+}
+
QDeclarativeWorkerListModelAgent *QDeclarativeWorkerListModel::agent()
{
if (!m_agent)
@@ -1013,6 +1226,10 @@ QString QDeclarativeWorkerListModel::toString(int role) const
return m_roles.value(role);
}
+/*!
+ \qmlproperty int ListModel::count
+ The number of data entries in the model.
+*/
int QDeclarativeWorkerListModel::count() const
{
return m_values.count();
@@ -1038,4 +1255,3 @@ QT_END_NAMESPACE
#include "qdeclarativeworkerscript.moc"
-
diff --git a/src/declarative/qml/qdeclarativeworkerscript_p.h b/src/declarative/qml/qdeclarativeworkerscript_p.h
index 8ebd2c1..912eac9 100644
--- a/src/declarative/qml/qdeclarativeworkerscript_p.h
+++ b/src/declarative/qml/qdeclarativeworkerscript_p.h
@@ -61,8 +61,12 @@
#include <QtScript/qscriptvalue.h>
#include <QtCore/qurl.h>
+QT_BEGIN_HEADER
+
QT_BEGIN_NAMESPACE
+QT_MODULE(Declarative)
+
class QDeclarativeWorkerScript;
class QDeclarativeWorkerScriptEnginePrivate;
class QDeclarativeWorkerScriptEngine : public QThread
@@ -84,7 +88,7 @@ private:
QDeclarativeWorkerScriptEnginePrivate *d;
};
-class QDeclarativeWorkerScript : public QObject, public QDeclarativeParserStatus
+class Q_DECLARATIVE_EXPORT QDeclarativeWorkerScript : public QObject, public QDeclarativeParserStatus
{
Q_OBJECT
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
@@ -115,7 +119,7 @@ private:
};
class QDeclarativeWorkerListModelAgent;
-class QDeclarativeWorkerListModel : public QListModelInterface
+class Q_DECLARATIVE_EXPORT QDeclarativeWorkerListModel : public QListModelInterface
{
Q_OBJECT
Q_PROPERTY(int count READ count NOTIFY countChanged)
@@ -130,6 +134,7 @@ public:
Q_INVOKABLE void insert(int index, const QScriptValue&);
Q_INVOKABLE QScriptValue get(int index) const;
Q_INVOKABLE void set(int index, const QScriptValue &);
+ Q_INVOKABLE void sync();
QDeclarativeWorkerListModelAgent *agent();
@@ -157,4 +162,6 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QDeclarativeWorkerScript);
QML_DECLARE_TYPE(QDeclarativeWorkerListModel);
+QT_END_HEADER
+
#endif // QDECLARATIVEWORKERSCRIPT_P_H
diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
index 3ba53f0..87cab85 100644
--- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp
+++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
@@ -52,6 +52,7 @@
#include <QtScript/qscriptcontext.h>
#include <QtScript/qscriptengine.h>
#include <QtNetwork/qnetworkreply.h>
+#include <QtCore/qtextcodec.h>
#include <QtCore/qxmlstream.h>
#include <QtCore/qstack.h>
#include <QtCore/qdebug.h>
@@ -312,7 +313,7 @@ public:
// C++ API
static QScriptValue prototype(QScriptEngine *);
- static QScriptValue load(QScriptEngine *engine, const QString &data);
+ static QScriptValue load(QScriptEngine *engine, const QByteArray &data);
};
QT_END_NAMESPACE
@@ -619,7 +620,7 @@ QScriptValue Document::prototype(QScriptEngine *engine)
return proto;
}
-QScriptValue Document::load(QScriptEngine *engine, const QString &data)
+QScriptValue Document::load(QScriptEngine *engine, const QByteArray &data)
{
Q_ASSERT(engine);
@@ -960,6 +961,7 @@ public:
QScriptValue abort(QScriptValue *me);
QString responseBody() const;
+ const QByteArray & rawResponseBody() const;
private slots:
void downloadProgress(qint64);
void error(QNetworkReply::NetworkError);
@@ -1279,9 +1281,20 @@ void QDeclarativeXMLHttpRequest::finished()
QString QDeclarativeXMLHttpRequest::responseBody() const
{
+ QXmlStreamReader reader(m_responseEntityBody);
+ reader.readNext();
+ QTextCodec *codec = QTextCodec::codecForName(reader.documentEncoding().toString().toUtf8());
+ if (codec)
+ return codec->toUnicode(m_responseEntityBody);
+
return QString::fromUtf8(m_responseEntityBody);
}
+const QByteArray &QDeclarativeXMLHttpRequest::rawResponseBody() const
+{
+ return m_responseEntityBody;
+}
+
QScriptValue QDeclarativeXMLHttpRequest::dispatchCallback(QScriptValue *me)
{
QScriptValue v = me->property(QLatin1String("callback"));
@@ -1538,7 +1551,7 @@ static QScriptValue qmlxmlhttprequest_responseXML(QScriptContext *context, QScri
request->readyState() != QDeclarativeXMLHttpRequest::Done)
return engine->nullValue();
else
- return Document::load(engine, request->responseBody());
+ return Document::load(engine, request->rawResponseBody());
}
static QScriptValue qmlxmlhttprequest_onreadystatechange(QScriptContext *context, QScriptEngine *engine)