diff options
8 files changed, 253 insertions, 16 deletions
diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index afc6735..fbd957c 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -45,9 +45,11 @@ #include <private/qmlcustomparser_p.h> #include <private/qmlparser_p.h> #include "qmlopenmetaobject_p.h" +#include <private/qmlengine_p.h> #include <qmlcontext.h> #include "qmllistmodel_p.h" #include <QtScript/qscriptvalueiterator.h> +#include "qmlinfo.h" Q_DECLARE_METATYPE(QListModelInterface *) @@ -264,6 +266,7 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(ModelNode *) QT_BEGIN_NAMESPACE + void ModelNode::setObjectValue(const QScriptValue& valuemap) { QScriptValueIterator it(valuemap); while (it.hasNext()) { @@ -451,14 +454,17 @@ void QmlListModel::clear() */ void QmlListModel::remove(int index) { - if (_root) { - ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); - _root->values.removeAt(index); - if (node) - delete node; - emit itemsRemoved(index,1); - emit countChanged(_root->values.count()); + if (!_root || index < 0 || index >= _root->values.count()) { + qmlInfo(tr("remove: index %1 out of range").arg(index),this); + return; } + + ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); + _root->values.removeAt(index); + if (node) + delete node; + emit itemsRemoved(index,1); + emit countChanged(_root->values.count()); } /*! @@ -480,9 +486,11 @@ void QmlListModel::insert(int index, const QScriptValue& valuemap) { if (!_root) _root = new ModelNode; - if (index >= _root->values.count()) { + if (index >= _root->values.count() || index<0) { if (index == _root->values.count()) append(valuemap); + else + qmlInfo(tr("insert: index %1 out of range").arg(index),this); return; } ModelNode *mn = new ModelNode; @@ -508,8 +516,10 @@ void QmlListModel::insert(int index, const QScriptValue& valuemap) */ void QmlListModel::move(int from, int to, int n) { - if (from+n > count() || to+n > count() || n==0 || from==to || from < 0 || to < 0) + if (n==0 || from==to) return; + if (from+n > count() || to+n > count() || from < 0 || to < 0) + qmlInfo(tr("move: out of range"),this); int origfrom=from; // preserve actual move, so any animations are correct int origto=to; int orign=n; @@ -556,7 +566,7 @@ void QmlListModel::move(int from, int to, int n) void QmlListModel::append(const QScriptValue& valuemap) { if (!valuemap.isObject()) { - qWarning("ListModel::append: value is not an object"); + qmlInfo(tr("append: value is not an object"),this); return; } if (!_root) @@ -569,10 +579,43 @@ void QmlListModel::append(const QScriptValue& valuemap) } /*! + \qmlmethod dict ListModel::get(index) + + Returns the item at \a index in the list model. + + \code + FruitModel.append({"cost": 5.95, "name":"Pizza"}) + FruitModel.get(0).cost + \endcode + + The \a index must be an element in the list. + + \sa append() +*/ +QScriptValue QmlListModel::get(int index) const +{ + if (index >= count()) { + qmlInfo(tr("get: index %1 out of range").arg(index),this); + return 0; + } + + ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); + if (!node) + return 0; + QmlEngine *eng = qmlEngine(this); + if (!eng) { + qWarning("Cannot call QmlListModel::get() without a QmlEngine"); + return 0; + } + return QmlEnginePrivate::qmlScriptObject(node->object(), eng); +} + +/*! \qmlmethod ListModel::set(index,dict) - Changes the item at \a index in the list model to the - values in \a 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"}) @@ -586,8 +629,8 @@ void QmlListModel::set(int index, const QScriptValue& valuemap) { if (!_root) _root = new ModelNode; - if ( index >= _root->values.count()) { - qWarning() << "ListModel::set index out of range:" << index; + if ( index > _root->values.count()) { + qmlInfo(tr("set: index %1 out of range").arg(index),this); return; } if (index == _root->values.count()) @@ -628,7 +671,7 @@ void QmlListModel::set(int index, const QString& property, const QVariant& value if (!_root) _root = new ModelNode; if ( index >= _root->values.count()) { - qWarning() << "ListModel::set index out of range:" << index; + qmlInfo(tr("set: index %1 out of range").arg(index),this); return; } ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); diff --git a/src/declarative/util/qmllistmodel_p.h b/src/declarative/util/qmllistmodel_p.h index 31365d1..34b1562 100644 --- a/src/declarative/util/qmllistmodel_p.h +++ b/src/declarative/util/qmllistmodel_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) struct ModelNode; -class QmlListModel : public QListModelInterface +class Q_DECLARATIVE_EXPORT QmlListModel : public QListModelInterface { Q_OBJECT Q_PROPERTY(int count READ count NOTIFY countChanged) @@ -77,6 +77,7 @@ public: Q_INVOKABLE void remove(int index); Q_INVOKABLE void append(const QScriptValue&); 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 set(int index, const QString& property, const QVariant& value); Q_INVOKABLE void move(int from, int to, int count); diff --git a/tests/auto/declarative/qmlgraphicswebview/data/javaScript.qml b/tests/auto/declarative/qmlgraphicswebview/data/javaScript.qml new file mode 100644 index 0000000..75d0cea --- /dev/null +++ b/tests/auto/declarative/qmlgraphicswebview/data/javaScript.qml @@ -0,0 +1,5 @@ +import Qt 4.6 + +WebView { + url: "javaScript.html" +} diff --git a/tests/auto/declarative/qmllistmodel/qmllistmodel.pro b/tests/auto/declarative/qmllistmodel/qmllistmodel.pro new file mode 100644 index 0000000..60b0c4b --- /dev/null +++ b/tests/auto/declarative/qmllistmodel/qmllistmodel.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative +QT += script +macx:CONFIG -= app_bundle + +SOURCES += tst_qmllistmodel.cpp diff --git a/tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp b/tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp new file mode 100644 index 0000000..9ce1a7c --- /dev/null +++ b/tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <qtest.h> +#include <QtDeclarative/private/qmllistmodel_p.h> +#include <QtDeclarative/private/qmlexpression_p.h> +#include <QDebug> + +class tst_QmlListModel : public QObject +{ + Q_OBJECT +public: + tst_QmlListModel() {} + +private slots: + void dynamic_data(); + void dynamic(); +}; + +void tst_QmlListModel::dynamic_data() +{ + QTest::addColumn<QString>("script"); + QTest::addColumn<int>("result"); + QTest::addColumn<QString>("warning"); + + // Simple flat model + + QTest::newRow("count") << "count" << 0 << ""; + + QTest::newRow("append1") << "{append({'foo':123});count}" << 1 << ""; + QTest::newRow("append2") << "{append({'foo':123,'bar':456});count}" << 1 << ""; + QTest::newRow("append3a") << "{append({'foo':123});append({'foo':456});get(0).foo}" << 123 << ""; + QTest::newRow("append3b") << "{append({'foo':123});append({'foo':456});get(1).foo}" << 456 << ""; + + QTest::newRow("clear1") << "{append({'foo':456});clear();count}" << 0 << ""; + QTest::newRow("clear2") << "{append({'foo':123});append({'foo':456});clear();count}" << 0 << ""; + QTest::newRow("clear2") << "{append({'foo':123});clear();get(0).foo}" << 0 << "QML QmlListModel (unknown location) get: index 0 out of range"; + + QTest::newRow("remove1") << "{append({'foo':123});remove(0);count}" << 0 << ""; + QTest::newRow("remove2a") << "{append({'foo':123});append({'foo':456});remove(0);count}" << 1 << ""; + QTest::newRow("remove2b") << "{append({'foo':123});append({'foo':456});remove(0);get(0).foo}" << 456 << ""; + QTest::newRow("remove2c") << "{append({'foo':123});append({'foo':456});remove(1);get(0).foo}" << 123 << ""; + QTest::newRow("remove3") << "{append({'foo':123});remove(0);get(0).foo}" << 0 << "QML QmlListModel (unknown location) get: index 0 out of range"; + + QTest::newRow("insert1") << "{insert(0,{'foo':123});count}" << 1 << ""; + QTest::newRow("insert2") << "{insert(1,{'foo':123});count}" << 0 << "QML QmlListModel (unknown location) insert: index 1 out of range"; + QTest::newRow("insert3a") << "{append({'foo':123});insert(1,{'foo':456});count}" << 2 << ""; + QTest::newRow("insert3b") << "{append({'foo':123});insert(1,{'foo':456});get(0).foo}" << 123 << ""; + QTest::newRow("insert3c") << "{append({'foo':123});insert(1,{'foo':456});get(1).foo}" << 456 << ""; + QTest::newRow("insert3d") << "{append({'foo':123});insert(0,{'foo':456});get(0).foo}" << 456 << ""; + QTest::newRow("insert3e") << "{append({'foo':123});insert(0,{'foo':456});get(1).foo}" << 123 << ""; + QTest::newRow("insert4") << "{append({'foo':123});insert(-1,{'foo':456})}" << 0 << "QML QmlListModel (unknown location) insert: index -1 out of range"; + + QTest::newRow("set1") << "{append({'foo':123});set(0,{'foo':456});count}" << 1 << ""; + QTest::newRow("set2") << "{append({'foo':123});set(0,{'foo':456});get(0).foo}" << 456 << ""; + QTest::newRow("set3a") << "{append({'foo':123,'bar':456});set(0,{'foo':999});get(0).foo}" << 999 << ""; + QTest::newRow("set3b") << "{append({'foo':123,'bar':456});set(0,{'foo':999});get(0).bar}" << 456 << ""; + + QTest::newRow("setprop1") << "{append({'foo':123});set(0,'foo',456);count}" << 1 << ""; + QTest::newRow("setprop2") << "{append({'foo':123});set(0,'foo',456);get(0).foo}" << 456 << ""; + QTest::newRow("setprop3a") << "{append({'foo':123,'bar':456});set(0,'foo',999);get(0).foo}" << 999 << ""; + QTest::newRow("setprop3b") << "{append({'foo':123,'bar':456});set(0,'foo',999);get(0).bar}" << 456 << ""; + + QTest::newRow("move1a") << "{append({'foo':123});append({'foo':456});move(0,1,1);count}" << 2 << ""; + QTest::newRow("move1b") << "{append({'foo':123});append({'foo':456});move(0,1,1);get(0).foo}" << 456 << ""; + QTest::newRow("move1c") << "{append({'foo':123});append({'foo':456});move(0,1,1);get(1).foo}" << 123 << ""; + QTest::newRow("move1d") << "{append({'foo':123});append({'foo':456});move(1,0,1);get(0).foo}" << 456 << ""; + QTest::newRow("move1e") << "{append({'foo':123});append({'foo':456});move(1,0,1);get(1).foo}" << 123 << ""; + QTest::newRow("move2a") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(0,1,2);count}" << 3 << ""; + QTest::newRow("move2b") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(0,1,2);get(0).foo}" << 789 << ""; + QTest::newRow("move2c") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(0,1,2);get(1).foo}" << 123 << ""; + QTest::newRow("move2d") << "{append({'foo':123});append({'foo':456});append({'foo':789});move(0,1,2);get(2).foo}" << 456 << ""; + + // Structured model + + // XXX todo +} + +void tst_QmlListModel::dynamic() +{ + QFETCH(QString, script); + QFETCH(int, result); + QFETCH(QString, warning); + + QmlEngine engine; + QmlListModel model; + QmlEngine::setContextForObject(&model,engine.rootContext()); + engine.rootContext()->addDefaultObject(&model); + QmlExpression e(engine.rootContext(), script, &model); + if (!warning.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1()); + int actual = e.value().toInt(); + if (e.hasError()) + qDebug() << e.error(); // errors not expected + QVERIFY(!e.hasError()); + QCOMPARE(actual,result); +} + +QTEST_MAIN(tst_QmlListModel) + +#include "tst_qmllistmodel.moc" diff --git a/tests/auto/declarative/visual/webview/embedding/egg.qml b/tests/auto/declarative/visual/webview/embedding/egg.qml new file mode 100644 index 0000000..a9019d1 --- /dev/null +++ b/tests/auto/declarative/visual/webview/embedding/egg.qml @@ -0,0 +1,27 @@ +import Qt 4.6 + +Item { + property var period : 250 + property var color : "black" + id: root + + Item { + x: root.width/2 + y: root.height/2 + Rectangle { + radius: width/2 + color: root.color + x: -width/2 + y: -height/2 + width: root.width*1.5 + height: root.height*1.5 + } + rotation: NumberAnimation { + from: 0 + to: 360 + repeat: true + running: true + duration: root.period + } + } +} diff --git a/tests/auto/declarative/visual/webview/embedding/nesting.html b/tests/auto/declarative/visual/webview/embedding/nesting.html new file mode 100644 index 0000000..6e81689 --- /dev/null +++ b/tests/auto/declarative/visual/webview/embedding/nesting.html @@ -0,0 +1,9 @@ +<html> +<head><title>Nesting</title> +<link rel="icon" sizes="48x48" href="basic.png"> +</head> +<body bgcolor="green"> +<h1>Nesting</h1> +This is a test... +<OBJECT data=egg.qml TYPE=application/x-qt-plugin width=50 height=70 period=2000 color=white></OBJECT> +... with a spinning QML egg nested in it. diff --git a/tests/auto/declarative/visual/webview/embedding/nesting.qml b/tests/auto/declarative/visual/webview/embedding/nesting.qml new file mode 100644 index 0000000..0d76579 --- /dev/null +++ b/tests/auto/declarative/visual/webview/embedding/nesting.qml @@ -0,0 +1,8 @@ +import Qt 4.6 + +WebView { + width: 300 + height: 200 + url: "nesting.html" + settings.pluginsEnabled: true +} |