summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/graphicsitems/qdeclarativerepeater.cpp19
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp24
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp34
-rw-r--r--src/declarative/qml/qdeclarativeengine_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp66
-rw-r--r--src/declarative/qml/qdeclarativeexpression_p.h4
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp22
-rw-r--r--src/declarative/qml/qdeclarativeproperty.cpp15
-rw-r--r--src/declarative/util/qdeclarativelistaccessor.cpp6
-rw-r--r--src/declarative/util/qdeclarativelistaccessor_p.h2
10 files changed, 119 insertions, 75 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativerepeater.cpp b/src/declarative/graphicsitems/qdeclarativerepeater.cpp
index e836788..95f6276 100644
--- a/src/declarative/graphicsitems/qdeclarativerepeater.cpp
+++ b/src/declarative/graphicsitems/qdeclarativerepeater.cpp
@@ -62,10 +62,10 @@ QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate()
/*!
\qmlclass Repeater QDeclarativeRepeater
- \since 4.7
+ \since 4.7
\inherits Item
- \brief The Repeater item allows you to repeat a component based on a model.
+ \brief The Repeater item allows you to repeat an Item-based component using a model.
The Repeater item is used when you want to create a large number of
similar items. For each entry in the model, an item is instantiated
@@ -102,15 +102,24 @@ QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate()
The repeater instance continues to own all items it instantiates, even
if they are otherwise manipulated. It is illegal to manually remove an item
created by the Repeater.
+
+ \note Repeater is Item-based, and cannot be used to repeat non-Item-derived objects.
+ For example, it cannot be used to repeat QtObjects.
+ \badcode
+ Item {
+ //XXX illegal. Can't repeat QtObject as it doesn't derive from Item.
+ Repeater {
+ model: 10
+ QtObject {}
+ }
+ }
+ \endcode
*/
/*!
\internal
\class QDeclarativeRepeater
\qmlclass Repeater
-
- XXX Repeater is very conservative in how it instatiates/deletes items. Also
- new model entries will not be created and old ones will not be removed.
*/
/*!
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp
index 71cf3cb..bed1956 100644
--- a/src/declarative/qml/qdeclarativebinding.cpp
+++ b/src/declarative/qml/qdeclarativebinding.cpp
@@ -148,8 +148,26 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
idx, a);
} else {
+ QDeclarativeEnginePrivate *ep = (data->context() && data->context()->engine)?
+ QDeclarativeEnginePrivate::get(data->context()->engine):0;
+
bool isUndefined = false;
- QVariant value = this->value(&isUndefined);
+ QVariant value;
+
+ if (data->property.propertyTypeCategory() == QDeclarativeProperty::List) {
+ QScriptValue scriptValue = d->scriptValue(0, &isUndefined);
+ value = ep->scriptValueToVariant(scriptValue, qMetaTypeId<QList<QObject *> >());
+ } else {
+ QScriptValue scriptValue = d->scriptValue(0, &isUndefined);
+ value = ep->scriptValueToVariant(scriptValue);
+ if (value.userType() == QMetaType::QObjectStar && !qvariant_cast<QObject*>(value)) {
+ // If the object is null, we extract the predicted type. While this isn't
+ // 100% reliable, in many cases it gives us better error messages if we
+ // assign this null-object to an incompatible property
+ int type = ep->objectClass->objectType(scriptValue);
+ value = QVariant(type, (void *)0);
+ }
+ }
if (isUndefined && !data->error.isValid() && data->property.isResettable()) {
@@ -187,9 +205,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
}
if (data->error.isValid()) {
- QDeclarativeEnginePrivate *p = (data->context() && data->context()->engine)?
- QDeclarativeEnginePrivate::get(data->context()->engine):0;
- if (!data->addError(p))
+ if (!data->addError(ep))
qWarning().nospace() << qPrintable(this->error().toString());
} else {
data->removeError();
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index e8b6913..3c66efb 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -1324,7 +1324,6 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine
return qScriptValueFromValue(engine, qVariantFromValue(finalColor));
}
-
QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val)
{
if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) {
@@ -1335,6 +1334,14 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v
} else {
return scriptEngine.nullValue();
}
+ } else if (val.userType() == qMetaTypeId<QList<QObject *> >()) {
+ const QList<QObject *> &list = *(QList<QObject *>*)val.constData();
+ QScriptValue rv = scriptEngine.newArray(list.count());
+ for (int ii = 0; ii < list.count(); ++ii) {
+ QObject *object = list.at(ii);
+ rv.setProperty(ii, objectClass->newQObject(object));
+ }
+ return rv;
}
bool objOk;
@@ -1346,22 +1353,31 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v
}
}
-QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val)
+QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val, int hint)
{
QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
if (dc == objectClass)
return QVariant::fromValue(objectClass->toQObject(val));
+ else if (dc == valueTypeClass)
+ return valueTypeClass->toVariant(val);
else if (dc == contextClass)
return QVariant();
- QScriptDeclarativeClass *sc = QScriptDeclarativeClass::scriptClass(val);
- if (!sc) {
- return val.toVariant();
- } else if (sc == valueTypeClass) {
- return valueTypeClass->toVariant(val);
- } else {
- return QVariant();
+ // Convert to a QList<QObject*> if val is an array and we were explicitly hinted, or
+ // if the first element is a QObject*
+ if ((hint == qMetaTypeId<QList<QObject *> >() && val.isArray()) ||
+ (val.isArray() && QScriptDeclarativeClass::scriptClass(val.property(0)) == objectClass)) {
+ QList<QObject *> list;
+ int length = val.property(QLatin1String("length")).toInt32();
+ for (int ii = 0; ii < length; ++ii) {
+ QScriptValue arrayItem = val.property(ii);
+ QObject *d = arrayItem.toQObject();
+ list << d;
+ }
+ return QVariant::fromValue(list);
}
+
+ return val.toVariant();
}
// XXX this beyonds in QUrl::toLocalFile()
diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h
index 45089d0..3f22d61 100644
--- a/src/declarative/qml/qdeclarativeengine_p.h
+++ b/src/declarative/qml/qdeclarativeengine_p.h
@@ -308,7 +308,7 @@ public:
QHash<QString, QScriptValue> m_sharedScriptImports;
QScriptValue scriptValueFromVariant(const QVariant &);
- QVariant scriptValueToVariant(const QScriptValue &);
+ QVariant scriptValueToVariant(const QScriptValue &, int hint = QVariant::Invalid);
void sendQuit ();
diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp
index a250f21..e0aee52 100644
--- a/src/declarative/qml/qdeclarativeexpression.cpp
+++ b/src/declarative/qml/qdeclarativeexpression.cpp
@@ -351,7 +351,7 @@ void QDeclarativeExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine
}
}
-QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUndefined)
+QScriptValue QDeclarativeExpressionPrivate::eval(QObject *secondaryScope, bool *isUndefined)
{
QDeclarativeExpressionData *data = this->data;
QDeclarativeEngine *engine = data->context()->engine;
@@ -376,7 +376,7 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo
const QString code = rewriteBinding(data->expression, &ok);
if (!ok) {
scriptEngine->popContext();
- return QVariant();
+ return QScriptValue();
}
data->expressionFunction = scriptEngine->evaluate(code, data->url, data->line);
}
@@ -413,54 +413,20 @@ QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bo
if (scriptEngine->hasUncaughtException()) {
exceptionToError(scriptEngine, data->error);
scriptEngine->clearExceptions();
- return QVariant();
+ return QScriptValue();
} else {
data->error = QDeclarativeError();
+ return svalue;
}
-
- QVariant rv;
-
- if (svalue.isArray()) {
- int length = svalue.property(QLatin1String("length")).toInt32();
- if (length && svalue.property(0).isObject()) {
- QList<QObject *> list;
- for (int ii = 0; ii < length; ++ii) {
- QScriptValue arrayItem = svalue.property(ii);
- QObject *d = arrayItem.toQObject();
- list << d;
- }
- rv = QVariant::fromValue(list);
- }
- } else if (svalue.isObject() &&
- ep->objectClass->scriptClass(svalue) == ep->objectClass) {
- QObject *o = svalue.toQObject();
- int type = QMetaType::QObjectStar;
- // If the object is null, we extract the predicted type. While this isn't
- // 100% reliable, in many cases it gives us better error messages if we
- // assign this null-object to an incompatible property
- if (!o) type = ep->objectClass->objectType(svalue);
-
- return QVariant(type, &o);
- }
-
- if (rv.isNull())
- rv = svalue.toVariant();
-
- return rv;
}
-QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
+QScriptValue QDeclarativeExpressionPrivate::scriptValue(QObject *secondaryScope, bool *isUndefined)
{
Q_Q(QDeclarativeExpression);
-
- QVariant rv;
- if (!q->engine()) {
- qWarning("QDeclarativeExpression: Attempted to evaluate an expression in an invalid context");
- return rv;
- }
+ Q_ASSERT(q->engine());
if (data->expression.isEmpty())
- return rv;
+ return QScriptValue();
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine());
@@ -476,7 +442,7 @@ QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isU
QDeclarativeExpressionData *localData = data;
localData->addref();
- rv = evalQtScript(secondaryScope, isUndefined);
+ QScriptValue value = eval(secondaryScope, isUndefined);
ep->currentExpression = lastCurrentExpression;
ep->captureProperties = lastCaptureProperties;
@@ -494,7 +460,21 @@ QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isU
lastCapturedProperties.copyAndClear(ep->capturedProperties);
- return rv;
+ return value;
+}
+
+QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
+{
+ Q_Q(QDeclarativeExpression);
+
+ if (!q->engine()) {
+ qWarning("QDeclarativeExpression: Attempted to evaluate an expression in an invalid context");
+ return QVariant();
+ }
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine());
+
+ return ep->scriptValueToVariant(scriptValue(secondaryScope, isUndefined));
}
/*!
diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h
index 9a90fb6..1a0e4dd 100644
--- a/src/declarative/qml/qdeclarativeexpression_p.h
+++ b/src/declarative/qml/qdeclarativeexpression_p.h
@@ -150,7 +150,9 @@ public:
QDeclarativeExpressionData *data;
QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0);
- QVariant evalQtScript(QObject *secondaryScope, bool *isUndefined = 0);
+ QScriptValue scriptValue(QObject *secondaryScope = 0, bool *isUndefined = 0);
+
+ QScriptValue eval(QObject *secondaryScope, bool *isUndefined = 0);
void updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties);
void clearGuards();
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
index 10b9fab..0e230e8 100644
--- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
+++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
@@ -222,15 +222,10 @@ QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name)
if (lastData->flags & QDeclarativePropertyCache::Data::IsVMEFunction) {
return Value(scriptEngine, ((QDeclarativeVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex));
} else {
-#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
// Uncomment to use QtScript method call logic
// QScriptValue sobj = scriptEngine->newQObject(obj);
// return Value(scriptEngine, sobj.property(toString(name)));
return Value(scriptEngine, methods.newMethod(obj, lastData));
-#else
- QScriptValue sobj = scriptEngine->newQObject(obj);
- return Value(scriptEngine, sobj.property(toString(name)));
-#endif
}
} else {
if (enginePriv->captureProperties && !(lastData->flags & QDeclarativePropertyCache::Data::IsConstant)) {
@@ -295,7 +290,6 @@ QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name)
QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj);
return Value(scriptEngine, enginePriv->scriptValueFromVariant(var));
}
-
}
}
@@ -456,8 +450,6 @@ bool QDeclarativeObjectScriptClass::compare(Object *o1, Object *o2)
return d1 == d2 || d1->object == d2->object;
}
-#if (QT_VERSION > QT_VERSION_CHECK(4, 6, 2)) || defined(QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE)
-
struct MethodData : public QScriptDeclarativeClass::Object {
MethodData(QObject *o, const QDeclarativePropertyCache::Data &d) : object(o), data(d) {}
@@ -687,7 +679,17 @@ void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine,
new (&data) QVariant(QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value));
type = callType;
} else if (callType == qMetaTypeId<QList<QObject*> >()) {
- new (&data) QList<QObject *>(); // We don't support passing in QList<QObject*>
+ QList<QObject *> *list = new (&data) QList<QObject *>();
+ if (value.isArray()) {
+ int length = value.property(QLatin1String("length")).toInt32();
+ for (int ii = 0; ii < length; ++ii) {
+ QScriptValue arrayItem = value.property(ii);
+ QObject *d = arrayItem.toQObject();
+ list->append(d);
+ }
+ } else if (QObject *d = value.toQObject()) {
+ list->append(d);
+ }
type = callType;
} else {
new (&data) QVariant();
@@ -800,7 +802,5 @@ QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::
return Value();
}
-#endif
-
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp
index affb6b9..d33f29e 100644
--- a/src/declarative/qml/qdeclarativeproperty.cpp
+++ b/src/declarative/qml/qdeclarativeproperty.cpp
@@ -1045,6 +1045,21 @@ bool QDeclarativePropertyPrivate::write(QObject *object, const QDeclarativePrope
prop.append(&prop, (void *)o);
}
+ } else if (propertyType == qMetaTypeId<QList<QObject *> >()) {
+
+ QList<QObject *> list;
+
+ if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
+ list = qvariant_cast<QList<QObject *> >(value);
+ } else {
+ QObject *o = enginePriv?enginePriv->toQObject(value):QDeclarativeMetaType::toQObject(value);
+ if (o)
+ list.append(o);
+ }
+
+ void *args[] = { &list, 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args);
+
} else {
Q_ASSERT(variantType != propertyType);
diff --git a/src/declarative/util/qdeclarativelistaccessor.cpp b/src/declarative/util/qdeclarativelistaccessor.cpp
index 4ac587f..f91b2fb 100644
--- a/src/declarative/util/qdeclarativelistaccessor.cpp
+++ b/src/declarative/util/qdeclarativelistaccessor.cpp
@@ -84,6 +84,8 @@ void QDeclarativeListAccessor::setList(const QVariant &v, QDeclarativeEngine *en
QObject *data = enginePrivate?enginePrivate->toQObject(v):QDeclarativeMetaType::toQObject(v);
d = QVariant::fromValue(data);
m_type = Instance;
+ } else if (d.userType() == qMetaTypeId<QList<QObject *> >()) {
+ m_type = ObjectList;
} else if (d.userType() == qMetaTypeId<QDeclarativeListReference>()) {
m_type = ListProperty;
} else {
@@ -98,6 +100,8 @@ int QDeclarativeListAccessor::count() const
return qvariant_cast<QStringList>(d).count();
case VariantList:
return qvariant_cast<QVariantList>(d).count();
+ case ObjectList:
+ return qvariant_cast<QList<QObject*> >(d).count();
case ListProperty:
return ((QDeclarativeListReference *)d.constData())->count();
case Instance:
@@ -118,6 +122,8 @@ QVariant QDeclarativeListAccessor::at(int idx) const
return QVariant::fromValue(qvariant_cast<QStringList>(d).at(idx));
case VariantList:
return qvariant_cast<QVariantList>(d).at(idx);
+ case ObjectList:
+ return QVariant::fromValue(qvariant_cast<QList<QObject*> >(d).at(idx));
case ListProperty:
return QVariant::fromValue(((QDeclarativeListReference *)d.constData())->at(idx));
case Instance:
diff --git a/src/declarative/util/qdeclarativelistaccessor_p.h b/src/declarative/util/qdeclarativelistaccessor_p.h
index d8bb8af..10d944a 100644
--- a/src/declarative/util/qdeclarativelistaccessor_p.h
+++ b/src/declarative/util/qdeclarativelistaccessor_p.h
@@ -65,7 +65,7 @@ public:
int count() const;
QVariant at(int) const;
- enum Type { Invalid, StringList, VariantList, ListProperty, Instance, Integer };
+ enum Type { Invalid, StringList, VariantList, ObjectList, ListProperty, Instance, Integer };
Type type() const { return m_type; }
private: