diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-03-02 02:08:17 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-03-02 02:08:17 (GMT) |
commit | 5b2d90a57c3722aa48edeaa58be2d55ae967a99d (patch) | |
tree | c0602cea4552854b38169a519ee3222e047839fb /src | |
parent | b2b9dc03fc01a8387e74591642fa15b272845e2b (diff) | |
parent | b3c94b923200dd9c98b66f4233c62e63a3ee79d4 (diff) | |
download | Qt-5b2d90a57c3722aa48edeaa58be2d55ae967a99d.zip Qt-5b2d90a57c3722aa48edeaa58be2d55ae967a99d.tar.gz Qt-5b2d90a57c3722aa48edeaa58be2d55ae967a99d.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-qml into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/qt-qml:
Add docs and tests for WorkerListModel.
Add accessor operations to VisualItemModel::children
Make "on" syntax mandatory for value sources and interceptors
Fix warning.
Minor optimization.
Test GridView.onAdd & GridView.onRemove. Reduce wait()s
Replace remaining QGuard usage with QDeclarativeGuard.
Reapply "Some animation cleanup/refactoring."
Setting the same source again causes reload.
Expand documention of status property with examples
Document TextEdit::textMargin
use ParentAnimation
Diffstat (limited to 'src')
20 files changed, 436 insertions, 134 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index b43b30b..8d778f8 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -45,6 +45,7 @@ #include "qdeclarativeflickable_p_p.h" #include <qdeclarativeeasefollow_p.h> +#include <qdeclarativeguard_p.h> #include <qlistmodelinterface_p.h> #include <QKeyEvent> @@ -251,7 +252,7 @@ public: } } - QGuard<QDeclarativeVisualModel> model; + QDeclarativeGuard<QDeclarativeVisualModel> model; QVariant modelVariant; QList<FxGridItem*> visibleItems; QHash<QDeclarativeItem*,int> unrequestedItems; diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index 99ab053..2739ab8 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -232,6 +232,16 @@ qreal QDeclarativeImage::paintedHeight() const \o Error - an error occurred while loading the image \endlist + Note that a change in the status property does not cause anything to happen + (although it reflects what has happened with the image internally). If you wish + to react to the change in status you need to do it yourself, for example in one + of the following ways: + \list + \o Create a state, so that a state change occurs, e.g. State{name: 'loaded'; when: image.status = Image.Ready;} + \o Do something inside the onStatusChanged signal handler, e.g. Image{id: image; onStatusChanged: if(image.status == Image.Ready) console.log('Loaded');} + \o Bind to the status variable somewhere, e.g. Text{text: if(image.status!=Image.Ready){'Not Loaded';}else{'Loaded';}} + \endlist + \sa progress */ diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 03303a0..02a8493 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -47,6 +47,7 @@ #include <qdeclarativeeasefollow_p.h> #include <qdeclarativeexpression.h> #include <qdeclarativeengine.h> +#include <qdeclarativeguard_p.h> #include <qlistmodelinterface_p.h> #include <QKeyEvent> @@ -429,7 +430,7 @@ public: virtual void flickX(qreal velocity); virtual void flickY(qreal velocity); - QGuard<QDeclarativeVisualModel> model; + QDeclarativeGuard<QDeclarativeVisualModel> model; QVariant modelVariant; QList<FxListItem*> visibleItems; QHash<QDeclarativeItem*,int> unrequestedItems; diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp index bd89321..b0499d7 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader.cpp +++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp @@ -320,6 +320,15 @@ void QDeclarativeLoaderPrivate::_q_sourceLoaded() \o Error - an error occurred while loading the QML source \endlist + Note that a change in the status property does not cause anything to happen + (although it reflects what has happened to the loader internally). If you wish + to react to the change in status you need to do it yourself, for example in one + of the following ways: + \list + \o Create a state, so that a state change occurs, e.g. State{name: 'loaded'; when: loader.status = Loader.Ready;} + \o Do something inside the onStatusChanged signal handler, e.g. Loader{id: loader; onStatusChanged: if(loader.status == Loader.Ready) console.log('Loaded');} + \o Bind to the status variable somewhere, e.g. Text{text: if(loader.status!=Loader.Ready){'Not Loaded';}else{'Loaded';}} + \endlist \sa progress */ diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h index ca50910..6344a8a 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h @@ -60,6 +60,7 @@ #include <qdeclarative.h> #include <qdeclarativeanimation_p_p.h> +#include <qdeclarativeguard_p.h> #include <qdatetime.h> @@ -132,7 +133,7 @@ public: int pathOffset; int requestedIndex; QList<QDeclarativeItem *> items; - QGuard<QDeclarativeVisualModel> model; + QDeclarativeGuard<QDeclarativeVisualModel> model; QVariant modelVariant; enum MovementReason { Other, Key, Mouse }; MovementReason moveReason; diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 8e44b26..be73b39 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -613,6 +613,11 @@ void QDeclarativeTextEdit::setPersistentSelection(bool on) emit persistentSelectionChanged(d->persistentSelection); } +/* + \qmlproperty number TextEdit::textMargin + + The margin, in pixels, around the text in the TextEdit. +*/ qreal QDeclarativeTextEdit::textMargin() const { Q_D(const QDeclarativeTextEdit); diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index cd72ef9..a0aed46 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -53,6 +53,7 @@ #include <qdeclarativedeclarativedata_p.h> #include <qdeclarativepropertycache_p.h> #include <qdeclarativeguard_p.h> +#include <qdeclarativeglobal_p.h> #include <qlistmodelinterface_p.h> #include <qhash.h> @@ -80,6 +81,14 @@ public: static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->emitChildrenChanged(); } + static int children_count(QDeclarativeListProperty<QDeclarativeItem> *prop) { + return static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->children.count(); + } + + static QDeclarativeItem *children_at(QDeclarativeListProperty<QDeclarativeItem> *prop, int index) { + return static_cast<QDeclarativeVisualItemModelPrivate *>(prop->data)->children.at(index); + } + void itemAppended() { Q_Q(QDeclarativeVisualItemModel); QDeclarativeVisualItemModelAttached *attached = QDeclarativeVisualItemModelAttached::properties(children.last()); @@ -135,7 +144,8 @@ QDeclarativeVisualItemModel::QDeclarativeVisualItemModel() QDeclarativeListProperty<QDeclarativeItem> QDeclarativeVisualItemModel::children() { Q_D(QDeclarativeVisualItemModel); - return QDeclarativeListProperty<QDeclarativeItem>(this, d, QDeclarativeVisualItemModelPrivate::children_append); + return QDeclarativeListProperty<QDeclarativeItem>(this, d, d->children_append, + d->children_count, d->children_at); } /*! @@ -984,8 +994,8 @@ QDeclarativeItem *QDeclarativeVisualDataModel::item(int index, const QByteArray if (complete) d->m_delegate->completeCreate(); if (nobj) { - ctxt->setParent(nobj); - data->setParent(nobj); + QDeclarative_setParent_noEvent(ctxt, nobj); + QDeclarative_setParent_noEvent(data, nobj); d->m_cache.insertItem(index, nobj); if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj)) emit createdPackage(index, package); @@ -1268,7 +1278,6 @@ void QDeclarativeVisualDataModel::_q_dataChanged(const QModelIndex &begin, const void QDeclarativeVisualDataModel::_q_modelReset() { - Q_D(QDeclarativeVisualDataModel); emit modelReset(); } diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 5da207d..a9809c0 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -718,6 +718,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)); @@ -1623,6 +1624,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 +1657,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 +1710,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); - } } @@ -1793,8 +1808,8 @@ 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); @@ -1829,9 +1844,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 +1863,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 +1900,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 +1962,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 +1981,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 +2024,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 +2059,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 +2067,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, @@ -2203,10 +2241,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 +2274,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(); diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 2ea3366..93a3f83 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -219,6 +219,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, diff --git a/src/declarative/qml/qdeclarativedom.cpp b/src/declarative/qml/qdeclarativedom.cpp index 6c81f34..5b43109 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(); } @@ -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/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp index 5ac49d5..0e3d856 100644 --- a/src/declarative/qml/qdeclarativeparser.cpp +++ b/src/declarative/qml/qdeclarativeparser.cpp @@ -221,6 +221,8 @@ QDeclarativeParser::Property::~Property() { foreach(Value *value, values) value->release(); + foreach(Value *value, onValues) + value->release(); if (value) value->release(); } @@ -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..d0d7de1 100644 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ b/src/declarative/qml/qdeclarativeparser_p.h @@ -320,6 +320,7 @@ namespace QDeclarativeParser Object *getValue(); void addValue(Value *v); + void addOnValue(Value *v); // The QVariant::Type of the property, or 0 (QVariant::Invalid) if // unknown. @@ -333,6 +334,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/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index f4c9cdd..a4b3668 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -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/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index 03151e4..c1d090e 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -841,6 +841,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 +889,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 +912,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 +934,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 +976,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 +1023,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 +1063,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 +1111,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 +1145,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 +1174,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..01cc72a 100644 --- a/src/declarative/qml/qdeclarativeworkerscript_p.h +++ b/src/declarative/qml/qdeclarativeworkerscript_p.h @@ -61,6 +61,8 @@ #include <QtScript/qscriptvalue.h> #include <QtCore/qurl.h> +QT_BEGIN_HEADER + QT_BEGIN_NAMESPACE class QDeclarativeWorkerScript; @@ -84,7 +86,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 +117,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 +132,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 +160,6 @@ QT_END_NAMESPACE QML_DECLARE_TYPE(QDeclarativeWorkerScript); QML_DECLARE_TYPE(QDeclarativeWorkerListModel); +QT_END_HEADER + #endif // QDECLARATIVEWORKERSCRIPT_P_H diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index 10230d3..ebf1a20 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -1573,7 +1573,8 @@ QDeclarativeSequentialAnimation::QDeclarativeSequentialAnimation(QObject *parent QDeclarativeAnimationGroup(parent) { Q_D(QDeclarativeAnimationGroup); - d->ag = new QSequentialAnimationGroup(this); + d->ag = new QSequentialAnimationGroup; + QDeclarative_setParent_noEvent(d->ag, this); } QDeclarativeSequentialAnimation::~QDeclarativeSequentialAnimation() @@ -1638,7 +1639,8 @@ QDeclarativeParallelAnimation::QDeclarativeParallelAnimation(QObject *parent) : QDeclarativeAnimationGroup(parent) { Q_D(QDeclarativeAnimationGroup); - d->ag = new QParallelAnimationGroup(this); + d->ag = new QParallelAnimationGroup; + QDeclarative_setParent_noEvent(d->ag, this); } QDeclarativeParallelAnimation::~QDeclarativeParallelAnimation() @@ -1797,7 +1799,7 @@ QDeclarativePropertyAnimation::~QDeclarativePropertyAnimation() void QDeclarativePropertyAnimationPrivate::init() { Q_Q(QDeclarativePropertyAnimation); - va = new QDeclarativeTimeLineValueAnimator; + va = new QDeclarativeBulkValueAnimator; QDeclarative_setParent_noEvent(va, q); } @@ -2213,7 +2215,7 @@ QAbstractAnimation *QDeclarativePropertyAnimation::qtAnimation() return d->va; } -struct PropertyUpdater : public QDeclarativeTimeLineValue +struct PropertyUpdater : public QDeclarativeBulkValueUpdater { QDeclarativeStateActions actions; int interpolatorType; //for Number/ColorAnimation @@ -2231,7 +2233,6 @@ struct PropertyUpdater : public QDeclarativeTimeLineValue wasDeleted = &deleted; if (reverse) //QVariantAnimation sends us 1->0 when reversed, but we are expecting 0->1 v = 1 - v; - QDeclarativeTimeLineValue::setValue(v); for (int ii = 0; ii < actions.count(); ++ii) { QDeclarativeAction &action = actions[ii]; diff --git a/src/declarative/util/qdeclarativeanimation_p_p.h b/src/declarative/util/qdeclarativeanimation_p_p.h index e582066..ae82a90 100644 --- a/src/declarative/util/qdeclarativeanimation_p_p.h +++ b/src/declarative/util/qdeclarativeanimation_p_p.h @@ -149,14 +149,21 @@ private: bool running; }; -//animates QDeclarativeTimeLineValue (assumes start and end values will be reals or compatible) -class QDeclarativeTimeLineValueAnimator : public QVariantAnimation +class QDeclarativeBulkValueUpdater +{ +public: + virtual ~QDeclarativeBulkValueUpdater() {} + virtual void setValue(qreal value) = 0; +}; + +//animates QDeclarativeBulkValueUpdater (assumes start and end values will be reals or compatible) +class QDeclarativeBulkValueAnimator : public QVariantAnimation { Q_OBJECT public: - QDeclarativeTimeLineValueAnimator(QObject *parent = 0) : QVariantAnimation(parent), animValue(0), fromSourced(0), policy(KeepWhenStopped) {} - ~QDeclarativeTimeLineValueAnimator() { if (policy == DeleteWhenStopped) { delete animValue; animValue = 0; } } - void setAnimValue(QDeclarativeTimeLineValue *value, DeletionPolicy p) + QDeclarativeBulkValueAnimator(QObject *parent = 0) : QVariantAnimation(parent), animValue(0), fromSourced(0), policy(KeepWhenStopped) {} + ~QDeclarativeBulkValueAnimator() { if (policy == DeleteWhenStopped) { delete animValue; animValue = 0; } } + void setAnimValue(QDeclarativeBulkValueUpdater *value, DeletionPolicy p) { if (state() == Running) stop(); @@ -193,7 +200,7 @@ protected: } private: - QDeclarativeTimeLineValue *animValue; + QDeclarativeBulkValueUpdater *animValue; bool *fromSourced; DeletionPolicy policy; }; @@ -352,7 +359,7 @@ public: int interpolatorType; QVariantAnimation::Interpolator interpolator; - QDeclarativeTimeLineValueAnimator *va; + QDeclarativeBulkValueAnimator *va; static QVariant interpolateVariant(const QVariant &from, const QVariant &to, qreal progress); static void convertVariant(QVariant &variant, int type); diff --git a/src/declarative/util/qdeclarativefontloader.cpp b/src/declarative/util/qdeclarativefontloader.cpp index 4d12ae1..8f5f537 100644 --- a/src/declarative/util/qdeclarativefontloader.cpp +++ b/src/declarative/util/qdeclarativefontloader.cpp @@ -189,6 +189,16 @@ void QDeclarativeFontLoader::setName(const QString &name) \o Loading - the font is currently being loaded \o Error - an error occurred while loading the font \endlist + + Note that a change in the status property does not cause anything to happen + (although it reflects what has happened to the font loader internally). If you wish + to react to the change in status you need to do it yourself, for example in one + of the following ways: + \list + \o Create a state, so that a state change occurs, e.g. State{name: 'loaded'; when: loader.status = FontLoader.Ready;} + \o Do something inside the onStatusChanged signal handler, e.g. FontLoader{id: loader; onStatusChanged: if(loader.status == FontLoader.Ready) console.log('Loaded');} + \o Bind to the status variable somewhere, e.g. Text{text: if(loader.status!=FontLoader.Ready){'Not Loaded';}else{'Loaded';}} + \endlist */ QDeclarativeFontLoader::Status QDeclarativeFontLoader::status() const { diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp index 6fe5bf3..f08e634 100644 --- a/src/declarative/util/qdeclarativeview.cpp +++ b/src/declarative/util/qdeclarativeview.cpp @@ -51,6 +51,7 @@ #include <qdeclarativedebug_p.h> #include <qdeclarativedebugservice_p.h> #include <qdeclarativeglobal_p.h> +#include <qdeclarativeguard_p.h> #include <qscriptvalueiterator.h> #include <qdebug.h> @@ -136,8 +137,8 @@ public: QDeclarativeView *q; - QGuard<QGraphicsObject> root; - QGuard<QDeclarativeItem> qmlRoot; + QDeclarativeGuard<QGraphicsObject> root; + QDeclarativeGuard<QDeclarativeItem> qmlRoot; QUrl source; @@ -282,13 +283,14 @@ QDeclarativeView::~QDeclarativeView() /*! Sets the source to the \a url, loads the QML component and instantiates it. + + Calling this methods multiple times with the same url will result + in the QML being reloaded. */ void QDeclarativeView::setSource(const QUrl& url) { - if (url != d->source) { - d->source = url; - d->execute(); - } + d->source = url; + d->execute(); } /*! diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index 162a669..d260ada 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -647,11 +647,21 @@ void QDeclarativeXmlListModel::setNamespaceDeclarations(const QString &declarati This property holds the status of data source loading. It can be one of: \list \o Null - no data source has been set - \o Ready - nthe data source has been loaded + \o Ready - the data source has been loaded \o Loading - the data source is currently being loaded \o Error - an error occurred while loading the data source \endlist + Note that a change in the status property does not cause anything to happen + (although it reflects what has happened to the XmlListModel internally). If you wish + to react to the change in status you need to do it yourself, for example in one + of the following ways: + \list + \o Create a state, so that a state change occurs, e.g. State{name: 'loaded'; when: xmlListModel.status = XmlListModel.Ready;} + \o Do something inside the onStatusChanged signal handler, e.g. XmlListModel{id: xmlListModel; onStatusChanged: if(xmlListModel.status == XmlListModel.Ready) console.log('Loaded');} + \o Bind to the status variable somewhere, e.g. Text{text: if(xmlListModel.status!=XmlListModel.Ready){'Not Loaded';}else{'Loaded';}} + \endlist + \sa progress */ |