diff options
20 files changed, 426 insertions, 77 deletions
diff --git a/doc/src/declarative/qmldocument.qdoc b/doc/src/declarative/qmldocument.qdoc index 84e7926..2775ea6 100644 --- a/doc/src/declarative/qmldocument.qdoc +++ b/doc/src/declarative/qmldocument.qdoc @@ -71,6 +71,8 @@ Rectangle { } \endcode +QML documents are always encoded in UTF-8 format. + A QML document always begins with one or more import statements. To prevent elements introduced in later versions from affecting existing QML programs, the element types available within a document are controlled by the imported QML \l {Modules}. That is, diff --git a/doc/src/declarative/binding.qdoc b/doc/src/declarative/qtbinding.qdoc index 94465a1..94465a1 100644 --- a/doc/src/declarative/binding.qdoc +++ b/doc/src/declarative/qtbinding.qdoc diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index 6324724..903fad7 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -1483,8 +1483,8 @@ void QFxItemPrivate::resources_removeAt(int) int QFxItemPrivate::resources_count() const { - // ### - return 0; + Q_Q(const QFxItem); + return q->children().count(); } void QFxItemPrivate::resources_append(QObject *o) @@ -1498,10 +1498,14 @@ void QFxItemPrivate::resources_insert(int, QObject *) // ### } -QObject *QFxItemPrivate::resources_at(int) const +QObject *QFxItemPrivate::resources_at(int idx) const { - // ### - return 0; + Q_Q(const QFxItem); + QObjectList children = q->children(); + if (idx < children.count()) + return children.at(idx); + else + return 0; } void QFxItemPrivate::resources_clear() @@ -1516,8 +1520,8 @@ void QFxItemPrivate::children_removeAt(int) int QFxItemPrivate::children_count() const { - // ### - return 0; + Q_Q(const QFxItem); + return q->childItems().count(); } void QFxItemPrivate::children_append(QFxItem *i) @@ -1531,10 +1535,14 @@ void QFxItemPrivate::children_insert(int, QFxItem *) // ### } -QFxItem *QFxItemPrivate::children_at(int) const +QFxItem *QFxItemPrivate::children_at(int idx) const { - // ### - return 0; + Q_Q(const QFxItem); + QList<QGraphicsItem *> children = q->childItems(); + if (idx < children.count()) + return qobject_cast<QFxItem *>(children.at(idx)); + else + return 0; } void QFxItemPrivate::children_clear() diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 2e62a3b..58a18a2 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -44,7 +44,8 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlcontextscriptclass.cpp \ qml/qmlglobalscriptclass.cpp \ qml/qmlvaluetypescriptclass.cpp \ - qml/qmltypenamescriptclass.cpp + qml/qmltypenamescriptclass.cpp \ + qml/qmllistscriptclass.cpp HEADERS += qml/qmlparser_p.h \ qml/qmlinstruction_p.h \ @@ -105,7 +106,8 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlcontextscriptclass_p.h \ qml/qmlglobalscriptclass_p.h \ qml/qmlvaluetypescriptclass_p.h \ - qml/qmltypenamescriptclass_p.h + qml/qmltypenamescriptclass_p.h \ + qml/qmllistscriptclass_p.h # for qtscript debugger contains(QT_CONFIG, scripttools):QT += scripttools diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index d5f64c2..f0ecf1d 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -86,6 +86,7 @@ #include <private/qmlxmlhttprequest_p.h> #include <private/qmlsqldatabase_p.h> #include <private/qmltypenamescriptclass_p.h> +#include <private/qmllistscriptclass_p.h> #ifdef Q_OS_WIN // for %APPDATA% #include "qt_windows.h" @@ -173,6 +174,8 @@ QmlEnginePrivate::~QmlEnginePrivate() valueTypeClass = 0; delete typeNameClass; typeNameClass = 0; + delete listClass; + listClass = 0; delete networkAccessManager; networkAccessManager = 0; delete nodeListClass; @@ -218,6 +221,7 @@ void QmlEnginePrivate::init() objectClass = new QmlObjectScriptClass(q); valueTypeClass = new QmlValueTypeScriptClass(q); typeNameClass = new QmlTypeNameScriptClass(q); + listClass = new QmlListScriptClass(q); rootContext = new QmlContext(q,true); #ifdef QT_SCRIPTTOOLS_LIB if (qmlDebugger()){ diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 4c90a80..a85ac55 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -96,6 +96,7 @@ class QScriptDeclarativeClass; class QmlTypeNameScriptClass; class QmlTypeNameCache; class QmlComponentAttached; +class QmlListScriptClass; class QmlEnginePrivate : public QObjectPrivate { @@ -129,6 +130,7 @@ public: QmlObjectScriptClass *objectClass; QmlValueTypeScriptClass *valueTypeClass; QmlTypeNameScriptClass *typeNameClass; + QmlListScriptClass *listClass; // Global script class QScriptClass *globalClass; // Used by DOM Core 3 API diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp index 862d6ba..119641f 100644 --- a/src/declarative/qml/qmlinfo.cpp +++ b/src/declarative/qml/qmlinfo.cpp @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE For example, \code - qmlInfo(object, tr("component property is a write-once property")); + qmlInfo(tr("component property is a write-once property"), object); \endcode prints @@ -77,7 +77,7 @@ void qmlInfo(const QString& msg, QObject* object) { QString pos = QLatin1String("QML"); if (object) { - pos += " "; + pos += QLatin1Char(' '); pos += QLatin1String(object->metaObject()->className()); } QmlDeclarativeData *ddata = QmlDeclarativeData::get(object); diff --git a/src/declarative/qml/qmllistscriptclass.cpp b/src/declarative/qml/qmllistscriptclass.cpp new file mode 100644 index 0000000..09bde8c --- /dev/null +++ b/src/declarative/qml/qmllistscriptclass.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmllistscriptclass_p.h" +#include <private/qmlengine_p.h> + +QT_BEGIN_NAMESPACE + +struct ListData : public QScriptDeclarativeClass::Object { + QGuard<QObject> object; + int propertyIdx; + QmlListScriptClass::ListType type; +}; + +QmlListScriptClass::QmlListScriptClass(QmlEngine *e) +: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(e)), engine(e) +{ + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + + m_lengthId = createPersistentIdentifier(QLatin1String("length")); +} + +QmlListScriptClass::~QmlListScriptClass() +{ +} + +QScriptValue QmlListScriptClass::newList(QObject *object, int propId, ListType type) +{ + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + + if (!object || propId == -1) + return scriptEngine->nullValue(); + + ListData *data = new ListData; + data->object = object; + data->propertyIdx = propId; + data->type = type; + + return newObject(scriptEngine, this, data); +} + +QScriptClass::QueryFlags +QmlListScriptClass::queryProperty(Object *object, const Identifier &name, + QScriptClass::QueryFlags flags) +{ + if (name == m_lengthId.identifier) + return QScriptClass::HandlesReadAccess; + + bool ok = false; + quint32 idx = toArrayIndex(name, &ok); + + if (ok) { + lastIndex = idx; + return QScriptClass::HandlesReadAccess; + } else { + return 0; + } +} + +QScriptValue QmlListScriptClass::property(Object *obj, const Identifier &name) +{ + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); + + ListData *data = (ListData *)obj; + if (!data->object) + return scriptEngine->undefinedValue(); + + void *list = 0; + void *args[] = { &list, 0 }; + QMetaObject::metacall(data->object, QMetaObject::ReadProperty, + data->propertyIdx, args); + + if (!list) + return scriptEngine->undefinedValue(); + + if (data->type == QListPtr) { + const QList<QObject *> &qlist = *((QList<QObject *>*)list); + + if (name == m_lengthId.identifier) + return qlist.count(); + else if (lastIndex < qlist.count()) + return enginePriv->objectClass->newQObject(qlist.at(lastIndex)); + else + return scriptEngine->undefinedValue(); + + } else { + Q_ASSERT(data->type == QmlListPtr); + const QmlList<QObject *> &qmllist = *((QmlList<QObject *>*)list); + + int count = qmllist.count(); + + if (name == m_lengthId.identifier) + return count; + else if (lastIndex < count) + return enginePriv->objectClass->newQObject(qmllist.at(lastIndex)); + else + return scriptEngine->undefinedValue(); + } +} + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/qmllistscriptclass_p.h b/src/declarative/qml/qmllistscriptclass_p.h new file mode 100644 index 0000000..7592098 --- /dev/null +++ b/src/declarative/qml/qmllistscriptclass_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLLISTSCRIPTCLASS_P_H +#define QMLLISTSCRIPTCLASS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qscriptdeclarativeclass_p.h> + +QT_BEGIN_NAMESPACE + +class QmlEngine; +class QmlListScriptClass : public QScriptDeclarativeClass +{ +public: + QmlListScriptClass(QmlEngine *); + ~QmlListScriptClass(); + + enum ListType { QListPtr, QmlListPtr }; + QScriptValue newList(QObject *, int, ListType); + +protected: + virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, + QScriptClass::QueryFlags flags); + virtual QScriptValue property(Object *, const Identifier &); + +private: + PersistentIdentifier m_lengthId; + QmlEngine *engine; + + quint32 lastIndex; +}; + +QT_END_NAMESPACE + +#endif // QMLLISTSCRIPTCLASS_P_H + diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 80f2786..122db51 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -45,6 +45,7 @@ #include <private/qmlcontext_p.h> #include <private/qmldeclarativedata_p.h> #include <private/qmltypenamescriptclass_p.h> +#include <private/qmllistscriptclass_p.h> #include <QtDeclarative/qmlbinding.h> #include <QtCore/qtimer.h> @@ -64,8 +65,7 @@ QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine) : QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), lastData(0), engine(bindEngine) { - engine = bindEngine; - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine); + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); m_destroy = scriptEngine->newFunction(destroy); m_destroyId = createPersistentIdentifier(QLatin1String("destroy")); @@ -214,7 +214,13 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name return enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType); } - if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) { + if (lastData->flags & QmlPropertyCache::Data::IsQList) { + return enginePriv->listClass->newList(obj, lastData->coreIndex, + QmlListScriptClass::QListPtr); + } else if (lastData->flags & QmlPropertyCache::Data::IsQmlList) { + return enginePriv->listClass->newList(obj, lastData->coreIndex, + QmlListScriptClass::QmlListPtr); + } if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) { QObject *rv = 0; void *args[] = { &rv, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args); diff --git a/src/declarative/qml/qmlrewrite.cpp b/src/declarative/qml/qmlrewrite.cpp index 5166c96..a41b571 100644 --- a/src/declarative/qml/qmlrewrite.cpp +++ b/src/declarative/qml/qmlrewrite.cpp @@ -40,9 +40,13 @@ ****************************************************************************/ #include "qmlrewrite_p.h" +#include <QtDeclarative/qfxglobal.h> +#include <QtCore/qdebug.h> QT_BEGIN_NAMESPACE +DEFINE_BOOL_CONFIG_OPTION(rewriteDump, QML_REWRITE_DUMP); + namespace QmlRewrite { QString RewriteBinding::operator()(const QString &code) @@ -76,8 +80,20 @@ QString RewriteBinding::rewrite(QString code, unsigned position, _writer->replace(startOfStatement, 0, QLatin1String("(function() { ")); _writer->replace(endOfStatement, 0, QLatin1String(" })")); + if (rewriteDump()) { + qWarning() << "============================================================="; + qWarning() << "Rewrote:"; + qWarning() << qPrintable(code); + } + w.write(&code); + if (rewriteDump()) { + qWarning() << "To:"; + qWarning() << qPrintable(code); + qWarning() << "============================================================="; + } + return code; } diff --git a/src/declarative/util/qmlstateoperations.cpp b/src/declarative/util/qmlstateoperations.cpp index 716cec4..60fd421 100644 --- a/src/declarative/util/qmlstateoperations.cpp +++ b/src/declarative/util/qmlstateoperations.cpp @@ -48,11 +48,14 @@ #include <QtDeclarative/qmlinfo.h> #include <private/qfxanchors_p.h> #include <private/qfxitem_p.h> +#include <QtGui/qgraphicsitem.h> +#include <QtCore/qmath.h> QT_BEGIN_NAMESPACE class QmlParentChangePrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QmlParentChange) public: QmlParentChangePrivate() : target(0), parent(0), origParent(0), origStackBefore(0) {} @@ -67,53 +70,37 @@ public: void QmlParentChangePrivate::doChange(QFxItem *targetParent, QFxItem *stackBefore) { if (targetParent && target && target->parentItem()) { - QPointF me = target->parentItem()->mapToScene(QPointF(0,0)); - QPointF them = targetParent->mapToScene(QPointF(0,0)); - - QPointF themx = targetParent->mapToScene(QPointF(1,0)); - QPointF themy = targetParent->mapToScene(QPointF(0,1)); - - themx -= them; - themy -= them; - - target->setParentItem(targetParent); - - // XXX - this is silly and will only work in a few cases - - /* - xDiff = rx * themx_x + ry * themy_x - yDiff = rx * themx_y + ry * themy_y - */ - - qreal rx = 0; - qreal ry = 0; - qreal xDiff = them.x() - me.x(); - qreal yDiff = them.y() - me.y(); - - - if (themx.x() == 0.) { - ry = xDiff / themy.x(); - rx = (yDiff - ry * themy.y()) / themx.y(); - } else if (themy.x() == 0.) { - rx = xDiff / themx.x(); - ry = (yDiff - rx * themx.y()) / themy.y(); - } else if (themx.y() == 0.) { - ry = yDiff / themy.y(); - rx = (xDiff - ry * themy.x()) / themx.x(); - } else if (themy.y() == 0.) { - rx = yDiff / themx.y(); - ry = (xDiff - rx * themx.x()) / themy.x(); - } else { - qreal div = (themy.x() * themx.y() - themy.y() * themx.x()); - - if (div != 0.) - rx = (themx.y() * xDiff - themx.x() * yDiff) / div; - - if (themy.y() != 0.) ry = (yDiff - rx * themx.y()) / themy.y(); + //### for backwards direction, we can just restore original x, y, scale, rotation + Q_Q(QmlParentChange); + const QTransform &transform = target->itemTransform(targetParent); + if (transform.type() >= QTransform::TxShear) { + qmlInfo(QObject::tr("Unable to preserve appearance under complex transform"), q); } - target->setX(target->x() - rx); - target->setY(target->y() - ry); + qreal scale = 1; + qreal rotation = 0; + if (transform.type() != QTransform::TxRotate) { + if (transform.m11() == transform.m22()) + scale = transform.m11(); + else + qmlInfo(QObject::tr("Unable to preserve appearance under non-uniform scale"), q); + } else if (transform.type() == QTransform::TxRotate) { + if (transform.m11() == transform.m22()) + scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12()); + else + qmlInfo(QObject::tr("Unable to preserve appearance under non-uniform scale"), q); + + if (scale != 0) + rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI; + else + qmlInfo(QObject::tr("Unable to preserve appearance under scale of 0"), q); + } + target->setParentItem(targetParent); + //qDebug() << transform.dx() << transform.dy() << rotation << scale; + target->setX(transform.dx()); + target->setY(transform.dy()); + target->setRotation(rotation); + target->setScale(scale); } else if (target) { target->setParentItem(targetParent); } @@ -127,7 +114,16 @@ void QmlParentChangePrivate::doChange(QFxItem *targetParent, QFxItem *stackBefor /*! \preliminary \qmlclass ParentChange - \brief The ParentChange element allows you to reparent an object in a state. + \brief The ParentChange element allows you to reparent an Item in a state change. + + ParentChange reparents an Item while preserving its visual appearance (position, rotation, + and scale) on screen. You can then specify a transition to move/rotate/scale the Item to + its final intended appearance. + + ParentChange can only preserve visual appearance if no complex transforms are involved. + More specifically, it will not work if the transform property has been set for any + Items involved in the reparenting (defined as any Items in the common ancestor tree + for the original and new parent). */ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,ParentChange,QmlParentChange) diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index d019839..1e59f66 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -258,6 +258,13 @@ QString QScriptDeclarativeClass::toString(const Identifier &identifier) return QString((QChar *)r->data(), r->size()); } +quint32 QScriptDeclarativeClass::toArrayIndex(const Identifier &identifier, bool *ok) +{ + JSC::UString::Rep *r = (JSC::UString::Rep *)identifier; + JSC::UString s(r); + return s.toArrayIndex(ok); +} + QScriptClass::QueryFlags QScriptDeclarativeClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags flags) diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index b28209a..559e842 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -103,6 +103,7 @@ public: PersistentIdentifier createPersistentIdentifier(const Identifier &); QString toString(const Identifier &); + quint32 toArrayIndex(const Identifier &, bool *ok); virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); diff --git a/tests/auto/declarative/qmlecmascript/data/listProperties.qml b/tests/auto/declarative/qmlecmascript/data/listProperties.qml new file mode 100644 index 0000000..73a1d6f --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/listProperties.qml @@ -0,0 +1,44 @@ +import Qt.test 1.0 +import Qt 4.6 + +MyQmlObject { + id: root + + objectListProperty: [ + Object { property int a: 10 }, + Object { property int a: 11 } + ] + + objectQmlListProperty: [ + Object { property int a: 10 }, + Object { property int a: 1 }, + Object { property int a: 39 } + ] + + Script { + function calcTest1() { + var rv = 0; + for (var ii = 0; ii < root.objectListProperty.length; ++ii) { + rv += root.objectListProperty[ii].a; + } + return rv; + } + + function calcTest2() { + var rv = 0; + for (var ii = 0; ii < root.objectQmlListProperty.length; ++ii) { + rv += root.objectQmlListProperty[ii].a; + } + return rv; + } + } + + property int test1: calcTest1(); + property int test2: root.objectListProperty.length + property int test3: calcTest2(); + property int test4: root.objectQmlListProperty.length + property bool test5: root.objectQmlListProperty[1] != undefined + property bool test6: root.objectQmlListProperty[100] == undefined + property bool test7: root.objectListProperty[1] != undefined + property bool test8: root.objectListProperty[100] == undefined +} diff --git a/tests/auto/declarative/qmlecmascript/testtypes.h b/tests/auto/declarative/qmlecmascript/testtypes.h index e6c2c20..ae3a954 100644 --- a/tests/auto/declarative/qmlecmascript/testtypes.h +++ b/tests/auto/declarative/qmlecmascript/testtypes.h @@ -6,6 +6,7 @@ #include <QtDeclarative/qmlexpression.h> #include <QtCore/qpoint.h> #include <QtCore/qsize.h> +#include <QtDeclarative/qmllist.h> #include <QtCore/qrect.h> class MyQmlAttachedObject : public QObject @@ -23,11 +24,14 @@ class MyQmlObject : public QObject Q_OBJECT Q_ENUMS(MyEnum) Q_ENUMS(MyEnum2) - Q_PROPERTY(int deleteOnSet READ deleteOnSet WRITE setDeleteOnSet); + Q_PROPERTY(int deleteOnSet READ deleteOnSet WRITE setDeleteOnSet) Q_PROPERTY(bool trueProperty READ trueProperty CONSTANT) Q_PROPERTY(bool falseProperty READ falseProperty CONSTANT) Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringChanged) - Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty NOTIFY objectChanged); + Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty NOTIFY objectChanged) + Q_PROPERTY(QmlList<QObject *> *objectQmlListProperty READ objectQmlListProperty CONSTANT) + Q_PROPERTY(QList<QObject *> *objectListProperty READ objectListProperty CONSTANT) + public: MyQmlObject(): m_methodCalled(false), m_methodIntCalled(false), m_object(0) {} @@ -54,6 +58,9 @@ public: emit objectChanged(); } + QmlList<QObject *> *objectQmlListProperty() { return &m_objectQmlList; } + QList<QObject *> *objectListProperty() { return &m_objectQList; } + bool methodCalled() const { return m_methodCalled; } bool methodIntCalled() const { return m_methodIntCalled; } @@ -84,6 +91,8 @@ private: QObject *m_object; QString m_string; + QmlConcreteList<QObject *> m_objectQmlList; + QList<QObject *> m_objectQList; }; QML_DECLARE_TYPE(MyQmlObject); diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 7fb1703..f24882a 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -63,6 +63,7 @@ private slots: void extendedObjectPropertyLookup(); void scriptErrors(); void signalTriggeredBindings(); + void listProperties(); private: QmlEngine engine; @@ -787,6 +788,25 @@ void tst_qmlecmascript::signalTriggeredBindings() QCOMPARE(object->property("test2").toReal(), 400.); } +/* +Test that list properties can be iterated from ECMAScript +*/ +void tst_qmlecmascript::listProperties() +{ + QmlComponent component(&engine, TEST_FILE("listProperties.qml")); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toInt(), 21); + QCOMPARE(object->property("test2").toInt(), 2); + QCOMPARE(object->property("test3").toInt(), 50); + QCOMPARE(object->property("test4").toInt(), 3); + QCOMPARE(object->property("test5").toBool(), true); + QCOMPARE(object->property("test6").toBool(), true); + QCOMPARE(object->property("test7").toBool(), true); + QCOMPARE(object->property("test8").toBool(), true); +} + QTEST_MAIN(tst_qmlecmascript) #include "tst_qmlecmascript.moc" diff --git a/tools/qmldebugger/objectpropertiesview.cpp b/tools/qmldebugger/objectpropertiesview.cpp index 2237fbb..f725194 100644 --- a/tools/qmldebugger/objectpropertiesview.cpp +++ b/tools/qmldebugger/objectpropertiesview.cpp @@ -1,3 +1,5 @@ +#include <QtCore/qdebug.h> + #include <QtGui/qtreewidget.h> #include <QtGui/qlayout.h> @@ -53,6 +55,9 @@ ObjectPropertiesView::ObjectPropertiesView(QmlEngineDebug *client, QWidget *pare void ObjectPropertiesView::reload(const QmlDebugObjectReference &obj) { + if (m_query) + delete m_query; + m_query = m_client->queryObjectRecursive(obj, this); if (!m_query->isWaiting()) queryFinished(); @@ -63,16 +68,20 @@ void ObjectPropertiesView::reload(const QmlDebugObjectReference &obj) void ObjectPropertiesView::queryFinished() { - if (m_watch) { - m_client->removeWatch(m_watch); - delete m_watch; - m_watch = 0; - } + if (!m_query) + return; QmlDebugObjectReference obj = m_query->object(); QmlDebugWatch *watch = m_client->addWatch(obj, this); - if (watch->state() != QmlDebugWatch::Dead) { + if (watch->state() == QmlDebugWatch::Dead) { + delete watch; + watch = 0; + } else { + if (m_watch) { + m_client->removeWatch(m_watch); + delete m_watch; + } m_watch = watch; QObject::connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), this, SLOT(valueChanged(QByteArray,QVariant))); @@ -89,6 +98,7 @@ void ObjectPropertiesView::setObject(const QmlDebugObjectReference &object) m_object = object; m_tree->clear(); + QList<QmlDebugPropertyReference> properties = object.properties(); for (int i=0; i<properties.count(); i++) { const QmlDebugPropertyReference &p = properties[i]; diff --git a/tools/qmldebugger/objecttree.cpp b/tools/qmldebugger/objecttree.cpp index f398987..f68e7f1 100644 --- a/tools/qmldebugger/objecttree.cpp +++ b/tools/qmldebugger/objecttree.cpp @@ -75,10 +75,10 @@ void ObjectTree::buildTree(const QmlDebugObjectReference &obj, QTreeWidgetItem * QTreeWidgetItem *item = parent ? new QTreeWidgetItem(parent) : new QTreeWidgetItem(this); item->setText(0, obj.className()); item->setData(0, Qt::UserRole, qVariantFromValue(obj)); - item->setData(0, ObjectTree::ContextIdRole, obj.contextDebugId()); if (parent && obj.contextDebugId() >= 0 - && obj.contextDebugId() != parent->data(0, ObjectTree::ContextIdRole).toInt()) { + && obj.contextDebugId() != parent->data(0, Qt::UserRole + ).value<QmlDebugObjectReference>().contextDebugId()) { QmlDebugFileReference source = obj.source(); if (!source.url().isEmpty()) { QString toolTipString = QLatin1String("URL: ") + source.url().toString(); diff --git a/tools/qmldebugger/objecttree.h b/tools/qmldebugger/objecttree.h index a924ec5..bba6c08 100644 --- a/tools/qmldebugger/objecttree.h +++ b/tools/qmldebugger/objecttree.h @@ -17,10 +17,6 @@ class ObjectTree : public QTreeWidget { Q_OBJECT public: - enum AdditionalRoles { - ContextIdRole = Qt::UserRole + 1 - }; - ObjectTree(QmlEngineDebug *client, QWidget *parent = 0); signals: |