diff options
author | Martin Jones <martin.jones@nokia.com> | 2010-04-08 00:52:14 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2010-04-08 00:52:14 (GMT) |
commit | 979ad950e257c0c90463ab6c2db7fea4aece3331 (patch) | |
tree | 9bd14fb2e786d5a84ae3b5685c46e6e7a5594b59 /src/declarative | |
parent | fac110fd9313972f001bf8b52b0254cc2d67ef66 (diff) | |
parent | 9d9161446bfad883c298d54a122e822c5e273a9c (diff) | |
download | Qt-979ad950e257c0c90463ab6c2db7fea4aece3331.zip Qt-979ad950e257c0c90463ab6c2db7fea4aece3331.tar.gz Qt-979ad950e257c0c90463ab6c2db7fea4aece3331.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-qml into 4.7
Diffstat (limited to 'src/declarative')
-rw-r--r-- | src/declarative/graphicsitems/qdeclarativerepeater.cpp | 19 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativebinding.cpp | 24 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeengine.cpp | 34 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeengine_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeexpression.cpp | 66 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeexpression_p.h | 4 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeobjectscriptclass.cpp | 22 | ||||
-rw-r--r-- | src/declarative/qml/qdeclarativeproperty.cpp | 15 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativelistaccessor.cpp | 6 | ||||
-rw-r--r-- | src/declarative/util/qdeclarativelistaccessor_p.h | 2 |
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: |