From 2c40b2faac1d9bd941310c0c0e1e0d0fa0033ab5 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 8 Apr 2010 09:48:43 +1000 Subject: Update Repeater docs. --- .../graphicsitems/qdeclarativerepeater.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 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. */ /*! -- cgit v0.12 From 9d9161446bfad883c298d54a122e822c5e273a9c Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 8 Apr 2010 10:21:46 +1000 Subject: Support QList properties We already supported returning QList from methods, but there wasn't really much that could be done with the return value. This closes the loop on QList support by allowing them to be properties, and used as models. --- src/declarative/qml/qdeclarativebinding.cpp | 24 +++++-- src/declarative/qml/qdeclarativeengine.cpp | 34 +++++++--- src/declarative/qml/qdeclarativeengine_p.h | 2 +- src/declarative/qml/qdeclarativeexpression.cpp | 66 +++++++------------ src/declarative/qml/qdeclarativeexpression_p.h | 4 +- .../qml/qdeclarativeobjectscriptclass.cpp | 22 +++---- src/declarative/qml/qdeclarativeproperty.cpp | 15 +++++ src/declarative/util/qdeclarativelistaccessor.cpp | 6 ++ src/declarative/util/qdeclarativelistaccessor_p.h | 2 +- .../data/qlistOfQObjects.1.qml | 16 +++++ .../data/qlistOfQObjects.2.qml | 17 +++++ .../data/qlistOfQObjects.3.qml | 21 ++++++ .../data/qlistOfQObjects.4.qml | 22 +++++++ .../data/qlistOfQObjects.5.qml | 35 ++++++++++ .../declarative/qdeclarativeecmascript/testtypes.h | 6 ++ .../tst_qdeclarativeecmascript.cpp | 75 ++++++++++++++++++++++ 16 files changed, 297 insertions(+), 70 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.1.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.2.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.3.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.4.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.5.qml 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 >()); + } else { + QScriptValue scriptValue = d->scriptValue(0, &isUndefined); + value = ep->scriptValueToVariant(scriptValue); + if (value.userType() == QMetaType::QObjectStar && !qvariant_cast(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()) { @@ -1335,6 +1334,14 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v } else { return scriptEngine.nullValue(); } + } else if (val.userType() == qMetaTypeId >()) { + const QList &list = *(QList*)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 if val is an array and we were explicitly hinted, or + // if the first element is a QObject* + if ((hint == qMetaTypeId >() && val.isArray()) || + (val.isArray() && QScriptDeclarativeClass::scriptClass(val.property(0)) == objectClass)) { + QList 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 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 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 &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 >()) { - new (&data) QList(); // We don't support passing in QList + QList *list = new (&data) QList(); + 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 list; + + if (value.userType() == qMetaTypeId >()) { + list = qvariant_cast >(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 >()) { + m_type = ObjectList; } else if (d.userType() == qMetaTypeId()) { m_type = ListProperty; } else { @@ -98,6 +100,8 @@ int QDeclarativeListAccessor::count() const return qvariant_cast(d).count(); case VariantList: return qvariant_cast(d).count(); + case ObjectList: + return qvariant_cast >(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(d).at(idx)); case VariantList: return qvariant_cast(d).at(idx); + case ObjectList: + return QVariant::fromValue(qvariant_cast >(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: diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.1.qml new file mode 100644 index 0000000..9c289be --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.1.qml @@ -0,0 +1,16 @@ +import Qt.test 1.0 +import Qt 4.6 + +MyQmlObject { + id: root + + property bool test1 + property bool test2 + + qlistProperty: root + + Component.onCompleted: { + test1 = (qlistProperty.length == 1) + test2 = (qlistProperty[0] == root) + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.2.qml new file mode 100644 index 0000000..8041f5c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.2.qml @@ -0,0 +1,17 @@ +import Qt.test 1.0 +import Qt 4.6 + +MyQmlObject { + id: root + + property bool test1 + property bool test2 + + Component.onCompleted: { + qlistProperty = root + + test1 = (qlistProperty.length == 1) + test2 = (qlistProperty[0] == root) + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.3.qml new file mode 100644 index 0000000..df44e48 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.3.qml @@ -0,0 +1,21 @@ +import Qt.test 1.0 +import Qt 4.6 + +MyQmlObject { + id: root + + property bool test1 + property bool test2 + property bool test3 + property bool test4 + + objectProperty: QtObject { id: obj } + qlistProperty: [ root, obj ] + + Component.onCompleted: { + test1 = (qlistProperty.length == 2) + test2 = (qlistProperty[0] == root) + test3 = (qlistProperty[1] == obj) + test4 = (qlistProperty[2] == null) + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.4.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.4.qml new file mode 100644 index 0000000..33c3576 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.4.qml @@ -0,0 +1,22 @@ +import Qt.test 1.0 +import Qt 4.6 + +MyQmlObject { + id: root + + property bool test1 + property bool test2 + property bool test3 + property bool test4 + + objectProperty: QtObject { id: obj } + + Component.onCompleted: { + qlistProperty = [ root, obj ] + + test1 = (qlistProperty.length == 2) + test2 = (qlistProperty[0] == root) + test3 = (qlistProperty[1] == obj) + test4 = (qlistProperty[2] == null) + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.5.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.5.qml new file mode 100644 index 0000000..3fd497c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qlistOfQObjects.5.qml @@ -0,0 +1,35 @@ +import Qt.test 1.0 +import Qt 4.6 + +MyQmlObject { + id: root + + property bool test1 + property bool test2 + property bool test3 + property bool test4 + property bool test5 + property bool test6 + property bool test7 + property bool test8 + + objectProperty: QtObject { id: obj } + + Component.onCompleted: { + qlistProperty = [ root, obj ] + + test1 = (qlistProperty.length == 2) + test2 = (qlistProperty[0] == root) + test3 = (qlistProperty[1] == obj) + test4 = (qlistProperty[2] == null) + + var a = qlistProperty; + a.reverse(); + qlistProperty = a + + test5 = (qlistProperty.length == 2) + test7 = (qlistProperty[0] == obj) + test6 = (qlistProperty[1] == root) + test8 = (qlistProperty[2] == null) + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h index faad8b7..d8ec452 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -91,6 +91,7 @@ class MyQmlObject : public QObject Q_PROPERTY(QDeclarativeListProperty objectListProperty READ objectListProperty CONSTANT) Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty) Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp) + Q_PROPERTY(QList qlistProperty READ qlistProperty WRITE setQListProperty) public: MyQmlObject(): m_methodCalled(false), m_methodIntCalled(false), m_object(0), m_value(0), m_resetProperty(13) {} @@ -142,6 +143,9 @@ public: QRegExp regExp() { return m_regExp; } void setRegExp(const QRegExp ®Exp) { m_regExp = regExp; } + QList qlistProperty() const { return m_objectQList2; } + void setQListProperty(const QList &v) { m_objectQList2 = v; } + signals: void basicSignal(); void argumentSignal(int a, QString b, qreal c); @@ -167,6 +171,8 @@ private: int m_value; int m_resetProperty; QRegExp m_regExp; + + QList m_objectQList2; }; QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES) diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 77dd4b8..a2625da 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -130,6 +130,7 @@ private slots: void qlistqobjectMethods(); void strictlyEquals(); void compiled(); + void qlistOfQObjects(); void bug1(); void dynamicCreationCrash(); @@ -2065,6 +2066,80 @@ void tst_qdeclarativeecmascript::compiled() delete object; } +// Test manipulating QList properties +void tst_qdeclarativeecmascript::qlistOfQObjects() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("qlistOfQObjects.1.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("qlistOfQObjects.2.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("qlistOfQObjects.3.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), true); + QCOMPARE(object->property("test3").toBool(), true); + QCOMPARE(object->property("test4").toBool(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("qlistOfQObjects.4.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), true); + QCOMPARE(object->property("test3").toBool(), true); + QCOMPARE(object->property("test4").toBool(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("qlistOfQObjects.5.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), true); + QCOMPARE(object->property("test3").toBool(), true); + QCOMPARE(object->property("test4").toBool(), true); + QCOMPARE(object->property("test5").toBool(), true); + QCOMPARE(object->property("test6").toBool(), true); + QCOMPARE(object->property("test7").toBool(), true); + QCOMPARE(object->property("test8").toBool(), true); + + delete object; + } +} + QTEST_MAIN(tst_qdeclarativeecmascript) #include "tst_qdeclarativeecmascript.moc" -- cgit v0.12