diff options
author | axis <qt-info@nokia.com> | 2011-02-24 16:07:22 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2011-02-24 16:07:22 (GMT) |
commit | 2b768ad7d4de4862584762a7d106d9cfcc3416df (patch) | |
tree | 0ddfe84f345d7e61ce71daa51fbbfb373c3e3106 /tests | |
parent | bb7d9bcc8e0c617091e91f7a40f3d33f8c1cdec1 (diff) | |
parent | ca7be48b7a150952a9657d1000941fb986e5bb2b (diff) | |
download | Qt-2b768ad7d4de4862584762a7d106d9cfcc3416df.zip Qt-2b768ad7d4de4862584762a7d106d9cfcc3416df.tar.gz Qt-2b768ad7d4de4862584762a7d106d9cfcc3416df.tar.bz2 |
Merge branch 'master' of scm.dev.nokia.troll.no:qt/qt into earth-master
Conflicts:
src/network/access/qnetworkreplyimpl.cpp
tests/auto/moc/tst_moc.cpp
Diffstat (limited to 'tests')
277 files changed, 18831 insertions, 972 deletions
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index c0004f7..c677249 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -19,4 +19,5 @@ contains(QT_CONFIG, multimedia): SUBDIRS += multimedia.pro contains(QT_CONFIG, phonon): SUBDIRS += phonon.pro contains(QT_CONFIG, svg): SUBDIRS += svg.pro contains(QT_CONFIG, declarative): SUBDIRS += declarative.pro +!symbian SUBDIRS += help.pro diff --git a/tests/auto/bic/tst_bic.cpp b/tests/auto/bic/tst_bic.cpp index fcf6deb..9ef2be1 100644 --- a/tests/auto/bic/tst_bic.cpp +++ b/tests/auto/bic/tst_bic.cpp @@ -135,6 +135,9 @@ tst_Bic::tst_Bic() /* This structure is semi-private and should never shrink */ bic.addBlacklistedClass(QLatin1String("QVFbHeader")); + + /* This structure has a version field that allows extension */ + bic.addBlacklistedClass(QLatin1String("QDeclarativePrivate::RegisterType")); } void tst_Bic::initTestCase_data() diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro index 499c155..08f0b9e 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -31,6 +31,7 @@ contains(QT_CONFIG, private_tests) { qdeclarativeanchors \ qdeclarativeanimatedimage \ qdeclarativeanimations \ + qdeclarativeapplication \ qdeclarativebehaviors \ qdeclarativebinding \ qdeclarativeborderimage \ @@ -55,6 +56,7 @@ contains(QT_CONFIG, private_tests) { qdeclarativeloader \ qdeclarativemousearea \ qdeclarativepathview \ + qdeclarativepincharea \ qdeclarativepositioners \ qdeclarativeproperty \ qdeclarativepropertymap \ diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.gif b/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.gif Binary files differnew file mode 100644 index 0000000..cfb55f2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.gif diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.qml b/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.qml new file mode 100644 index 0000000..8729dd2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.qml @@ -0,0 +1,6 @@ +import QtQuick 1.0 + +AnimatedImage { + source: "hearts.gif" + playing: false +} diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/data/qtbug-16520.qml b/tests/auto/declarative/qdeclarativeanimatedimage/data/qtbug-16520.qml new file mode 100644 index 0000000..cf5b601 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimatedimage/data/qtbug-16520.qml @@ -0,0 +1,17 @@ +import QtQuick 1.0 + +Rectangle { + width: 500 + height: 500 + + AnimatedImage { + objectName: "anim" + anchors.centerIn: parent + asynchronous: true + opacity: status == AnimatedImage.Ready ? 1 : 0 + + Behavior on opacity { + NumberAnimation { duration: 1000 } + } + } +} diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp b/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp index 1790e92..104ee15 100644 --- a/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp +++ b/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp @@ -45,6 +45,7 @@ #include <private/qdeclarativerectangle_p.h> #include <private/qdeclarativeimage_p.h> #include <private/qdeclarativeanimatedimage_p.h> +#include <QSignalSpy> #include "../shared/testhttpserver.h" #include "../../../shared/util.h" @@ -66,13 +67,29 @@ private slots: void stopped(); void setFrame(); void frameCount(); + void mirror_running(); + void mirror_notRunning(); + void mirror_notRunning_data(); void remote(); void remote_data(); void sourceSize(); void sourceSizeReadOnly(); void invalidSource(); + void qtbug_16520(); + +private: + QPixmap grabScene(QGraphicsScene *scene, int width, int height); }; +QPixmap tst_qdeclarativeanimatedimage::grabScene(QGraphicsScene *scene, int width, int height) +{ + QPixmap screenshot(width, height); + screenshot.fill(); + QPainter p_screenshot(&screenshot); + scene->render(&p_screenshot, QRect(0, 0, width, height), QRect(0, 0, width, height)); + return screenshot; +} + void tst_qdeclarativeanimatedimage::play() { QDeclarativeEngine engine; @@ -132,6 +149,93 @@ void tst_qdeclarativeanimatedimage::frameCount() delete anim; } +void tst_qdeclarativeanimatedimage::mirror_running() +{ + // test where mirror is set to true after animation has started + + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/hearts.qml")); + QDeclarativeAnimatedImage *anim = qobject_cast<QDeclarativeAnimatedImage *>(component.create()); + QVERIFY(anim); + + QGraphicsScene scene; + int width = anim->property("width").toInt(); + int height = anim->property("height").toInt(); + scene.addItem(qobject_cast<QGraphicsObject *>(anim)); + + QCOMPARE(anim->currentFrame(), 0); + QPixmap frame0 = grabScene(&scene, width, height); + anim->setCurrentFrame(1); + QPixmap frame1 = grabScene(&scene, width, height); + + anim->setCurrentFrame(0); + + QSignalSpy spy(anim, SIGNAL(frameChanged())); + anim->setPlaying(true); + + QTRY_VERIFY(spy.count() == 1); spy.clear(); + anim->setProperty("mirror", true); + + QCOMPARE(anim->currentFrame(), 1); + QPixmap frame1_flipped = grabScene(&scene, width, height); + + QTRY_VERIFY(spy.count() == 1); spy.clear(); + QCOMPARE(anim->currentFrame(), 0); // animation only has 2 frames, should cycle back to first + QPixmap frame0_flipped = grabScene(&scene, width, height); + + QTransform transform; + transform.translate(width, 0).scale(-1, 1.0); + QPixmap frame0_expected = frame0.transformed(transform); + QPixmap frame1_expected = frame1.transformed(transform); + + QCOMPARE(frame0_flipped, frame0_expected); + QCOMPARE(frame1_flipped, frame1_expected); +} + +void tst_qdeclarativeanimatedimage::mirror_notRunning() +{ + QFETCH(QUrl, fileUrl); + + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, fileUrl); + QDeclarativeAnimatedImage *anim = qobject_cast<QDeclarativeAnimatedImage *>(component.create()); + QVERIFY(anim); + + QGraphicsScene scene; + int width = anim->property("width").toInt(); + int height = anim->property("height").toInt(); + scene.addItem(qobject_cast<QGraphicsObject *>(anim)); + QPixmap screenshot = grabScene(&scene, width, height); + + QTransform transform; + transform.translate(width, 0).scale(-1, 1.0); + QPixmap expected = screenshot.transformed(transform); + + int frame = anim->currentFrame(); + bool playing = anim->isPlaying(); + bool paused = anim->isPlaying(); + + anim->setProperty("mirror", true); + screenshot = grabScene(&scene, width, height); + + QCOMPARE(screenshot, expected); + + // mirroring should not change the current frame or playing status + QCOMPARE(anim->currentFrame(), frame); + QCOMPARE(anim->isPlaying(), playing); + QCOMPARE(anim->isPaused(), paused); + + delete anim; +} + +void tst_qdeclarativeanimatedimage::mirror_notRunning_data() +{ + QTest::addColumn<QUrl>("fileUrl"); + + QTest::newRow("paused") << QUrl::fromLocalFile(SRCDIR "/data/stickmanpause.qml"); + QTest::newRow("stopped") << QUrl::fromLocalFile(SRCDIR "/data/stickmanstopped.qml"); +} + void tst_qdeclarativeanimatedimage::remote() { QFETCH(QString, fileName); @@ -204,6 +308,29 @@ void tst_qdeclarativeanimatedimage::invalidSource() QVERIFY(!anim->isPaused()); QCOMPARE(anim->currentFrame(), 0); QCOMPARE(anim->frameCount(), 0); + QTRY_VERIFY(anim->status() == 3); +} + +void tst_qdeclarativeanimatedimage::qtbug_16520() +{ + TestHTTPServer server(14449); + QVERIFY(server.isValid()); + server.serveDirectory(SRCDIR "/data"); + + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/qtbug-16520.qml")); + QTRY_VERIFY(component.isReady()); + + QDeclarativeRectangle *root = qobject_cast<QDeclarativeRectangle *>(component.create()); + QVERIFY(root); + QDeclarativeAnimatedImage *anim = root->findChild<QDeclarativeAnimatedImage*>("anim"); + + anim->setProperty("source", "http://127.0.0.1:14449/stickman.gif"); + + QTRY_VERIFY(anim->opacity() == 0); + QTRY_VERIFY(anim->opacity() == 1); + + delete anim; } QTEST_MAIN(tst_qdeclarativeanimatedimage) diff --git a/tests/auto/declarative/qdeclarativeapplication/qdeclarativeapplication.pro b/tests/auto/declarative/qdeclarativeapplication/qdeclarativeapplication.pro new file mode 100644 index 0000000..91e5468 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeapplication/qdeclarativeapplication.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative gui +macx:CONFIG -= app_bundle + +SOURCES += tst_qdeclarativeapplication.cpp diff --git a/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp b/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp new file mode 100644 index 0000000..64f327b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "../../../shared/util.h" +#include <QtDeclarative/qdeclarativecomponent.h> +#include <QtDeclarative/qdeclarativeengine.h> +#include <QtDeclarative/qdeclarativeitem.h> +#include <QtGui/qgraphicsview.h> +#include <QtGui/qgraphicsscene.h> + +class tst_qdeclarativeapplication : public QObject +{ + Q_OBJECT +public: + tst_qdeclarativeapplication(); + +private slots: + void active(); + void layoutDirection(); + +private: + QDeclarativeEngine engine; +}; + +tst_qdeclarativeapplication::tst_qdeclarativeapplication() +{ +} + +void tst_qdeclarativeapplication::active() +{ + QDeclarativeComponent component(&engine); + component.setData("import QtQuick 1.0; Item { property bool active: Qt.application.active }", QUrl::fromLocalFile("")); + QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create()); + QVERIFY(item); + QGraphicsScene scene; + QGraphicsView view(&scene); + scene.addItem(item); + + // not active + QVERIFY(!item->property("active").toBool()); + QCOMPARE(item->property("active").toBool(), QApplication::activeWindow() != 0); + + // active + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + QCOMPARE(item->property("active").toBool(), QApplication::activeWindow() != 0); + + // not active again + // on mac, setActiveWindow(0) on mac does not deactivate the current application + // (you have to switch to a different app or hide the current app to trigger this) +#if !defined(Q_WS_MAC) + QApplication::setActiveWindow(0); + QVERIFY(!item->property("active").toBool()); + QCOMPARE(item->property("active").toBool(), QApplication::activeWindow() != 0); +#endif +} + +void tst_qdeclarativeapplication::layoutDirection() +{ + QDeclarativeComponent component(&engine); + component.setData("import QtQuick 1.0; Item { property bool layoutDirection: Qt.application.layoutDirection }", QUrl::fromLocalFile("")); + QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create()); + QVERIFY(item); + QGraphicsScene scene; + QGraphicsView view(&scene); + scene.addItem(item); + + // not mirrored + QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::LeftToRight); + + // mirrored + QApplication::setLayoutDirection(Qt::RightToLeft); + QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::RightToLeft); + + // not mirrored again + QApplication::setLayoutDirection(Qt::LeftToRight); + QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::LeftToRight); +} + +QTEST_MAIN(tst_qdeclarativeapplication) + +#include "tst_qdeclarativeapplication.moc" diff --git a/tests/auto/declarative/qdeclarativeborderimage/data/heart200.png b/tests/auto/declarative/qdeclarativeborderimage/data/heart200.png Binary files differnew file mode 100644 index 0000000..5a31ae8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeborderimage/data/heart200.png diff --git a/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp b/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp index bc2f170..d85b92a 100644 --- a/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp +++ b/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp @@ -43,6 +43,8 @@ #include <QTcpServer> #include <QTcpSocket> #include <QDir> +#include <QGraphicsScene> +#include <QPainter> #include <QtDeclarative/qdeclarativeengine.h> #include <QtDeclarative/qdeclarativecomponent.h> @@ -77,12 +79,15 @@ private slots: void clearSource(); void resized(); void smooth(); + void mirror(); void tileModes(); void sciSource(); void sciSource_data(); void invalidSciFile(); void pendingRemoteRequest(); void pendingRemoteRequest_data(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QDeclarativeEngine engine; @@ -153,6 +158,8 @@ void tst_qdeclarativeborderimage::imageSource() QTRY_VERIFY(obj->status() == QDeclarativeBorderImage::Ready); QCOMPARE(obj->width(), 120.); QCOMPARE(obj->height(), 120.); + QCOMPARE(obj->sourceSize().width(), 120); + QCOMPARE(obj->sourceSize().height(), 120); QCOMPARE(obj->horizontalTileMode(), QDeclarativeBorderImage::Stretch); QCOMPARE(obj->verticalTileMode(), QDeclarativeBorderImage::Stretch); } else { @@ -192,6 +199,8 @@ void tst_qdeclarativeborderimage::resized() QVERIFY(obj != 0); QCOMPARE(obj->width(), 300.); QCOMPARE(obj->height(), 300.); + QCOMPARE(obj->sourceSize().width(), 120); + QCOMPARE(obj->sourceSize().height(), 120); QCOMPARE(obj->horizontalTileMode(), QDeclarativeBorderImage::Stretch); QCOMPARE(obj->verticalTileMode(), QDeclarativeBorderImage::Stretch); @@ -214,6 +223,37 @@ void tst_qdeclarativeborderimage::smooth() delete obj; } +void tst_qdeclarativeborderimage::mirror() +{ + QString componentStr = "import QtQuick 1.0\nBorderImage { source: \"" SRCDIR "/data/heart200.png\"; smooth: true; width: 300; height: 300; border { top: 50; right: 50; bottom: 50; left: 50 } }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeBorderImage *obj = qobject_cast<QDeclarativeBorderImage*>(component.create()); + QVERIFY(obj != 0); + + int width = obj->property("width").toInt(); + int height = obj->property("height").toInt(); + + QGraphicsScene scene; + scene.addItem(qobject_cast<QGraphicsObject *>(obj)); + QPixmap screenshot(width, height); + screenshot.fill(); + QPainter p_screenshot(&screenshot); + scene.render(&p_screenshot, QRect(0, 0, width, height), QRect(0, 0, width, height)); + + QTransform transform; + transform.translate(width, 0).scale(-1, 1.0); + QPixmap expected = screenshot.transformed(transform); + + obj->setProperty("mirror", true); + p_screenshot.fillRect(QRect(0, 0, width, height), Qt::white); + scene.render(&p_screenshot, QRect(0, 0, width, height), QRect(0, 0, width, height)); + + QCOMPARE(screenshot, expected); + + delete obj; +} + void tst_qdeclarativeborderimage::tileModes() { { @@ -342,6 +382,45 @@ void tst_qdeclarativeborderimage::pendingRemoteRequest_data() QTest::newRow("sci file") << "http://localhost/none.sci"; } +void tst_qdeclarativeborderimage::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; BorderImage { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; BorderImage { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_qdeclarativeborderimage::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("mirror") << "mirror: true" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"BorderImage.mirror\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("cache") << "cache: true" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"BorderImage.cache\" is not available in QtQuick 1.0.\n"; +} + QTEST_MAIN(tst_qdeclarativeborderimage) #include "tst_qdeclarativeborderimage.moc" diff --git a/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml new file mode 100644 index 0000000..0da3bda --- /dev/null +++ b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml @@ -0,0 +1,43 @@ +import QtQuick 1.0 + +Item{ + id: root + property QtObject declarativerectangle : null + property QtObject declarativeitem : null + + property QtObject bindingTestObject : null + property QtObject bindingThisTestObject : null + + Component{ + id: a + Rectangle { + property Rectangle innerRect: Rectangle { border.width: 20 } + } + } + Component{ + id: b + Item{ + property bool testBool: false + property int testInt: null + property QtObject testObject: null + } + } + + // test passing in bindings + width: 100 + Component { + id: c + Item { + property int testValue + width: 300 + } + } + + Component.onCompleted: { + root.declarativerectangle = a.createObject(root, {"x":17,"y":17, "color":"white", "border.width":3, "innerRect.border.width": 20}); + root.declarativeitem = b.createObject(root, {"x":17,"y":17,"testBool":true,"testInt":17,"testObject":root}); + + root.bindingTestObject = c.createObject(root, {'testValue': (function(){return width * 3}) }) // use root.width + root.bindingThisTestObject = c.createObject(root, {'testValue': (function(){return this.width * 3}) }) // use width of Item within 'c' + } +} diff --git a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp index 4db538e..4340fce 100644 --- a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp +++ b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp @@ -44,6 +44,9 @@ #include <QtGui/qgraphicsitem.h> #include <QtDeclarative/qdeclarativeengine.h> #include <QtDeclarative/qdeclarativecomponent.h> +#include <QtDeclarative/qdeclarativeitem.h> +#include <QtDeclarative/qdeclarativeproperty.h> +#include <qcolor.h> #ifdef Q_OS_SYMBIAN // In Symbian OS test data is located in applications private dir @@ -60,6 +63,7 @@ private slots: void null(); void loadEmptyUrl(); void qmlCreateObject(); + void qmlCreateObjectWithProperties(); private: QDeclarativeEngine engine; @@ -118,6 +122,52 @@ void tst_qdeclarativecomponent::qmlCreateObject() QCOMPARE(testObject3->metaObject()->className(), "QDeclarativeGraphicsWidget"); } +void tst_qdeclarativecomponent::qmlCreateObjectWithProperties() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/createObjectWithScript.qml")); + QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8()); + QObject *object = component.create(); + QVERIFY(object != 0); + + QObject *testObject1 = object->property("declarativerectangle").value<QObject*>(); + QVERIFY(testObject1); + QVERIFY(testObject1->parent() == object); + QCOMPARE(testObject1->property("x").value<int>(), 17); + QCOMPARE(testObject1->property("y").value<int>(), 17); + QCOMPARE(testObject1->property("color").value<QColor>(), QColor(255,255,255)); + QCOMPARE(QDeclarativeProperty::read(testObject1,"border.width").toInt(), 3); + QCOMPARE(QDeclarativeProperty::read(testObject1,"innerRect.border.width").toInt(), 20); + delete testObject1; + + QObject *testObject2 = object->property("declarativeitem").value<QObject*>(); + QVERIFY(testObject2); + QVERIFY(testObject2->parent() == object); + //QCOMPARE(testObject2->metaObject()->className(), "QDeclarativeItem_QML_2"); + QCOMPARE(testObject2->property("x").value<int>(), 17); + QCOMPARE(testObject2->property("y").value<int>(), 17); + QCOMPARE(testObject2->property("testBool").value<bool>(), true); + QCOMPARE(testObject2->property("testInt").value<int>(), 17); + QCOMPARE(testObject2->property("testObject").value<QObject*>(), object); + delete testObject2; + + QObject *testBindingObj = object->property("bindingTestObject").value<QObject*>(); + QVERIFY(testBindingObj); + QCOMPARE(testBindingObj->parent(), object); + QCOMPARE(testBindingObj->property("testValue").value<int>(), 300); + object->setProperty("width", 150); + QCOMPARE(testBindingObj->property("testValue").value<int>(), 150 * 3); + delete testBindingObj; + + QObject *testBindingThisObj = object->property("bindingThisTestObject").value<QObject*>(); + QVERIFY(testBindingThisObj); + QCOMPARE(testBindingThisObj->parent(), object); + QCOMPARE(testBindingThisObj->property("testValue").value<int>(), 900); + testBindingThisObj->setProperty("width", 200); + QCOMPARE(testBindingThisObj->property("testValue").value<int>(), 200 * 3); + delete testBindingThisObj; +} + QTEST_MAIN(tst_qdeclarativecomponent) #include "tst_qdeclarativecomponent.moc" diff --git a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp index a807f35..9a15575 100644 --- a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp +++ b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp @@ -72,7 +72,7 @@ class tst_QDeclarativeDebug : public QObject Q_OBJECT private: - QDeclarativeDebugObjectReference findRootObject(int context = 0); + QDeclarativeDebugObjectReference findRootObject(int context = 0, bool recursive = false); QDeclarativeDebugPropertyReference findProperty(const QList<QDeclarativeDebugPropertyReference> &props, const QString &name) const; void waitForQuery(QDeclarativeDebugQuery *query); @@ -115,9 +115,11 @@ private slots: void setBindingForObject(); void setMethodBody(); + void queryObjectTree(); + void setBindingInStates(); }; -QDeclarativeDebugObjectReference tst_QDeclarativeDebug::findRootObject(int context) +QDeclarativeDebugObjectReference tst_QDeclarativeDebug::findRootObject(int context, bool recursive) { QDeclarativeDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); waitForQuery(q_engines); @@ -129,7 +131,9 @@ QDeclarativeDebugObjectReference tst_QDeclarativeDebug::findRootObject(int conte if (q_context->rootContext().objects().count() == 0) return QDeclarativeDebugObjectReference(); - QDeclarativeDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[context], this); + QDeclarativeDebugObjectQuery *q_obj = recursive ? + m_dbg->queryObjectRecursive(q_context->rootContext().objects()[context], this) : + m_dbg->queryObject(q_context->rootContext().objects()[context], this); waitForQuery(q_obj); QDeclarativeDebugObjectReference result = q_obj->object(); @@ -309,6 +313,34 @@ void tst_QDeclarativeDebug::initTestCase() "function myMethodIndirect() { myMethod(3); }\n" "}"; + // and a fourth to test states + qml << "import QtQuick 1.0\n" + "Rectangle {\n" + "id:rootRect\n" + "width:100\n" + "states: [\n" + "State {\n" + "name:\"state1\"\n" + "PropertyChanges {\n" + "target:rootRect\n" + "width:200\n" + "}\n" + "}\n" + "]\n" + "transitions: [\n" + "Transition {\n" + "from:\"*\"\n" + "to:\"state1\"\n" + "PropertyAnimation {\n" + "target:rootRect\n" + "property:\"width\"\n" + "duration:100\n" + "}\n" + "}\n" + "]\n" + "}\n" + ; + for (int i=0; i<qml.count(); i++) { QDeclarativeComponent component(m_engine); component.setData(qml[i], QUrl::fromLocalFile("")); @@ -636,14 +668,14 @@ void tst_QDeclarativeDebug::queryRootContexts() QCOMPARE(context.debugId(), QDeclarativeDebugService::idForObject(actualContext)); QCOMPARE(context.name(), actualContext->objectName()); - QCOMPARE(context.objects().count(), 3); // 3 qml component objects created for context in main() + QCOMPARE(context.objects().count(), 4); // 4 qml component objects created for context in main() // root context query sends only root object data - it doesn't fill in // the children or property info QCOMPARE(context.objects()[0].properties().count(), 0); QCOMPARE(context.objects()[0].children().count(), 0); - QCOMPARE(context.contexts().count(), 4); + QCOMPARE(context.contexts().count(), 5); QVERIFY(context.contexts()[0].debugId() >= 0); QCOMPARE(context.contexts()[0].name(), QString("tst_QDeclarativeDebug_childContext")); @@ -898,7 +930,6 @@ void tst_QDeclarativeDebug::tst_QDeclarativeDebugPropertyReference() compareProperties(r, ref); } - void tst_QDeclarativeDebug::setBindingForObject() { QDeclarativeDebugObjectReference rootObject = findRootObject(); @@ -970,6 +1001,162 @@ void tst_QDeclarativeDebug::setBindingForObject() QCOMPARE(onEnteredRef.value(), QVariant("{console.log('hello, world') }")); } +void tst_QDeclarativeDebug::setBindingInStates() +{ + // Check if changing bindings of propertychanges works + + const int sourceIndex = 3; + + QDeclarativeDebugObjectReference obj = findRootObject(sourceIndex); + + QVERIFY(obj.debugId() != -1); + QVERIFY(obj.children().count() >= 2); + + // We are going to switch state a couple of times, we need to get rid of the transition before + QDeclarativeDebugExpressionQuery *q_deleteTransition = m_dbg->queryExpressionResult(obj.debugId(),QString("transitions = []"),this); + waitForQuery(q_deleteTransition); + delete q_deleteTransition; + + + // check initial value of the property that is changing + QDeclarativeDebugExpressionQuery *q_setState; + q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this); + waitForQuery(q_setState); + delete q_setState; + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),200); + + + q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"\""),this); + waitForQuery(q_setState); + delete q_setState; + + + obj = findRootObject(sourceIndex, true); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),100); + + + // change the binding + QDeclarativeDebugObjectReference state = obj.children()[0]; + QCOMPARE(state.className(), QString("State")); + QVERIFY(state.children().count() > 0); + + QDeclarativeDebugObjectReference propertyChange = state.children()[0]; + QVERIFY(propertyChange.debugId() != -1); + + QVERIFY( m_dbg->setBindingForObject(propertyChange.debugId(), "width",QVariant(300),true) ); + + // check properties changed in state + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),100); + + + q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this); + waitForQuery(q_setState); + delete q_setState; + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),300); + + // check changing properties of base state from within a state + QVERIFY(m_dbg->setBindingForObject(obj.debugId(),"width","height*2",false)); + QVERIFY(m_dbg->setBindingForObject(obj.debugId(),"height","200",true)); + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),300); + + q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"\""),this); + waitForQuery(q_setState); + delete q_setState; + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 400); + + // reset binding while in a state + q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this); + waitForQuery(q_setState); + delete q_setState; + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 300); + + m_dbg->resetBindingForObject(propertyChange.debugId(), "width"); + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 400); + + // re-add binding + m_dbg->setBindingForObject(propertyChange.debugId(), "width", "300", true); + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 300); +} + +void tst_QDeclarativeDebug::queryObjectTree() +{ + const int sourceIndex = 3; + + // Check if states/transitions are initialized when fetching root item + QDeclarativeDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + waitForQuery(q_engines); + + QDeclarativeDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); + waitForQuery(q_context); + + QVERIFY(q_context->rootContext().objects().count() > sourceIndex); + QDeclarativeDebugObjectReference rootObject = q_context->rootContext().objects()[sourceIndex]; + + QDeclarativeDebugObjectQuery *q_obj = m_dbg->queryObjectRecursive(rootObject, this); + waitForQuery(q_obj); + + QDeclarativeDebugObjectReference obj = q_obj->object(); + + delete q_engines; + delete q_context; + delete q_obj; + + QVERIFY(obj.debugId() != -1); + QVERIFY(obj.children().count() >= 2); + + + + // check state + QDeclarativeDebugObjectReference state = obj.children()[0]; + QCOMPARE(state.className(), QString("State")); + QVERIFY(state.children().count() > 0); + + QDeclarativeDebugObjectReference propertyChange = state.children()[0]; + QVERIFY(propertyChange.debugId() != -1); + + QDeclarativeDebugPropertyReference propertyChangeTarget = findProperty(propertyChange.properties(),"target"); + QCOMPARE(propertyChangeTarget.objectDebugId(), propertyChange.debugId()); + + QDeclarativeDebugObjectReference targetReference = qvariant_cast<QDeclarativeDebugObjectReference>(propertyChangeTarget.value()); + QVERIFY(targetReference.debugId() != -1); + + + + // check transition + QDeclarativeDebugObjectReference transition = obj.children()[1]; + QCOMPARE(transition.className(), QString("Transition")); + QCOMPARE(findProperty(transition.properties(),"from").value().toString(), QString("*")); + QCOMPARE(findProperty(transition.properties(),"to").value(), findProperty(state.properties(),"name").value()); + QVERIFY(transition.children().count() > 0); + + QDeclarativeDebugObjectReference animation = transition.children()[0]; + QVERIFY(animation.debugId() != -1); + + QDeclarativeDebugPropertyReference animationTarget = findProperty(animation.properties(),"target"); + QCOMPARE(animationTarget.objectDebugId(), animation.debugId()); + + targetReference = qvariant_cast<QDeclarativeDebugObjectReference>(animationTarget.value()); + QVERIFY(targetReference.debugId() != -1); + + QCOMPARE(findProperty(animation.properties(),"property").value().toString(), QString("width")); + QCOMPARE(findProperty(animation.properties(),"duration").value().toInt(), 100); +} + int main(int argc, char *argv[]) { int _argc = argc + 1; diff --git a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp index e3f0349..c182893 100644 --- a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp +++ b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp @@ -76,7 +76,7 @@ void tst_QDeclarativeDebugClient::initTestCase() QTest::ignoreMessage(QtWarningMsg, "Qml debugging is enabled. Only use this in a safe environment!"); QDeclarativeDebugHelper::enableDebugging(); - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 3770..."); + QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 13770..."); new QDeclarativeEngine(this); m_conn = new QDeclarativeDebugConnection(this); @@ -84,7 +84,7 @@ void tst_QDeclarativeDebugClient::initTestCase() QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::handshake()", m_conn); QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::handshake()"); - m_conn->connectToHost("127.0.0.1", 3770); + m_conn->connectToHost("127.0.0.1", 13770); QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established"); bool ok = m_conn->waitForConnected(); @@ -149,7 +149,7 @@ int main(int argc, char *argv[]) char **_argv = new char*[_argc]; for (int i = 0; i < argc; ++i) _argv[i] = argv[i]; - _argv[_argc - 1] = "-qmljsdebugger=port:3770"; + _argv[_argc - 1] = "-qmljsdebugger=port:13770"; QApplication app(_argc, _argv); tst_QDeclarativeDebugClient tc; diff --git a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp index aacdea5..0911a83 100644 --- a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp +++ b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp @@ -79,11 +79,11 @@ void tst_QDeclarativeDebugService::initTestCase() QTest::ignoreMessage(QtWarningMsg, "Qml debugging is enabled. Only use this in a safe environment!"); QDeclarativeDebugHelper::enableDebugging(); - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 3769..."); + QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 13769..."); new QDeclarativeEngine(this); m_conn = new QDeclarativeDebugConnection(this); - m_conn->connectToHost("127.0.0.1", 3769); + m_conn->connectToHost("127.0.0.1", 13769); QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established"); bool ok = m_conn->waitForConnected(); @@ -133,6 +133,10 @@ void tst_QDeclarativeDebugService::sendMessage() client.sendMessage(msg); QByteArray resp = client.waitForResponse(); QCOMPARE(resp, msg); + + QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugService: Conflicting plugin name \"tst_QDeclarativeDebugService::sendMessage()\" "); + QDeclarativeDebugService duplicate("tst_QDeclarativeDebugService::sendMessage()"); + duplicate.sendMessage("msg"); } void tst_QDeclarativeDebugService::idForObject() @@ -189,7 +193,7 @@ int main(int argc, char *argv[]) char **_argv = new char*[_argc]; for (int i = 0; i < argc; ++i) _argv[i] = argv[i]; - _argv[_argc - 1] = "-qmljsdebugger=port:3769"; + _argv[_argc - 1] = "-qmljsdebugger=port:13769"; QApplication app(_argc, _argv); tst_QDeclarativeDebugService tc; diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml index 948b39c..c8c926a 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml @@ -1,13 +1,73 @@ import Qt.test 1.0 +import QtQuick 1.0 + +import "functionAssignment.js" as Script MyQmlObject { property variant a - property bool runTest: false - onRunTestChanged: { + property int aNumber: 10 + + property bool assignToProperty: false + property bool assignToPropertyFromJsFile: false + + property bool assignWithThis: false + property bool assignWithThisFromJsFile: false + + property bool assignToValueType: false + + property bool assignFuncWithoutReturn: false + property bool assignWrongType: false + property bool assignWrongTypeToValueType: false + + + onAssignToPropertyChanged: { + function myFunction() { + return aNumber * 10; + } + a = myFunction; + } + + property QtObject obj: QtObject { + property int aNumber: 4212 + function myFunction() { + return this.aNumber * 10; // should use the aNumber from root, not this object + } + } + onAssignWithThisChanged: { + a = obj.myFunction; + } + + onAssignToPropertyFromJsFileChanged: { + Script.bindPropertyWithThis() + } + + onAssignWithThisFromJsFileChanged: { + Script.bindProperty() + } + + property Text text: Text { } + onAssignToValueTypeChanged: { + text.font.pixelSize = (function() { return aNumber * 10; }) + a = (function() { return text.font.pixelSize; }) + } + + + // detecting errors: + + onAssignFuncWithoutReturnChanged: { function myFunction() { - console.log("hello world"); } a = myFunction; } + onAssignWrongTypeChanged: { + function myFunction() { + return 'a string'; + } + aNumber = myFunction; + } + + onAssignWrongTypeToValueTypeChanged: { + text.font.pixelSize = (function() { return 'a string'; }) + } } diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.js b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.js new file mode 100644 index 0000000..14daa76 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.js @@ -0,0 +1,17 @@ +function bindProperty() +{ + a = (function(){ return aNumber * 10 }) +} + + +function TestObject() { } +TestObject.prototype.aNumber = 928349 +TestObject.prototype.bindFunction = function() { + return this.aNumber * 10 // this should not use the TestObject's aNumber +} +var testObj = new TestObject() + +function bindPropertyWithThis() +{ + a = testObj.bindFunction +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision.qml new file mode 100644 index 0000000..77accd8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision.qml @@ -0,0 +1,7 @@ +import Qt.test 1.1 + +MyRevisionedClass +{ + prop1: prop2 + onSignal1: method2() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision2.qml new file mode 100644 index 0000000..36057cb --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision2.qml @@ -0,0 +1,9 @@ +import Qt.test 1.1 + +MyRevisionedSubclass +{ + prop1: prop3 + onSignal1: method2() + prop3: prop4 + onSignal3: method4() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision3.qml new file mode 100644 index 0000000..81769e9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision3.qml @@ -0,0 +1,8 @@ +import Qt.test 1.0 + +MyRevisionedSubclass +{ + prop1: prop3 + onSignal1: method1() + onSignal3: method3() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision4.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision4.qml new file mode 100644 index 0000000..81ea536 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision4.qml @@ -0,0 +1,14 @@ +import Qt.test 1.1 +import QtQuick 1.0 + +QtObject { + property variant a + property real test + + a: MyRevisionedClass { + prop2: 11 + + Component.onCompleted: test = prop2 + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors.qml new file mode 100644 index 0000000..44d421e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors.qml @@ -0,0 +1,14 @@ +import QtQuick 1.0 +import Qt.test 1.0 + +MyRevisionedClass +{ + // Will not hit optimizer + property real p1: prop1 % 3 + property real p2: prop2 % 3 + + // Should hit optimizer + property real p3: prop2 + + Component.onCompleted: method2() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors2.qml new file mode 100644 index 0000000..121642e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors2.qml @@ -0,0 +1,24 @@ +import QtQuick 1.0 +import Qt.test 1.0 + +MyRevisionedSubclass +{ + // Will not hit optimizer + property real p1: prop1 % 3 + property real p2: prop2 % 3 + property real p3: prop3 % 3 + property real p4: prop4 % 3 + + // Should hit optimizer + property real p5: prop1 + property real p6: prop2 + property real p7: prop3 + property real p8: prop4 + + Component.onCompleted: { + method1() + method2() + method3() + method4() + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors3.qml new file mode 100644 index 0000000..123650e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors3.qml @@ -0,0 +1,36 @@ +import QtQuick 1.0 +import Qt.test 1.1 + +MyRevisionedSubclass +{ + // Will not hit optimizer + property real pA: propA % 3 + property real pB: propB % 3 + property real pC: propC % 3 + property real pD: propD % 3 + property real p1: prop1 % 3 + property real p2: prop2 % 3 + property real p3: prop3 % 3 + property real p4: prop4 % 3 + + // Should hit optimizer + property real pE: propA + property real pF: propB + property real pG: propC + property real pH: propD + property real p5: prop1 + property real p6: prop2 + property real p7: prop3 + property real p8: prop4 + + Component.onCompleted: { + methodA() + methodB() + methodC() + methodD() + method1() + method2() + method3() + method4() + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/nonExistantAttachedObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/nonExistentAttachedObject.qml index f9585db..f9585db 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/nonExistantAttachedObject.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/nonExistentAttachedObject.qml diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/signalWithUnknownTypes.qml b/tests/auto/declarative/qdeclarativeecmascript/data/signalWithUnknownTypes.qml new file mode 100644 index 0000000..49293ed --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/signalWithUnknownTypes.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyQmlObject { + onSignalWithUnknownType: variantMethod(arg); +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp index 1257da6..7e63bd5 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp @@ -113,9 +113,20 @@ void registerTypes() qmlRegisterType<NumberAssignment>("Qt.test", 1,0, "NumberAssignment"); qmlRegisterExtendedType<DefaultPropertyExtendedObject, DefaultPropertyExtensionObject>("Qt.test", 1,0, "DefaultPropertyExtendedObject"); qmlRegisterType<OverrideDefaultPropertyObject>("Qt.test", 1,0, "OverrideDefaultPropertyObject"); + qmlRegisterType<MyRevisionedClass>("Qt.test",1,0,"MyRevisionedClass"); + qmlRegisterType<MyRevisionedClass,1>("Qt.test",1,1,"MyRevisionedClass"); + + // Register the uncreatable base class + qmlRegisterRevision<MyRevisionedBaseClassRegistered,1>("Qt.test",1,1); + // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0 + qmlRegisterType<MyRevisionedSubclass>("Qt.test",1,0,"MyRevisionedSubclass"); + // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1 + qmlRegisterType<MyRevisionedSubclass,1>("Qt.test",1,1,"MyRevisionedSubclass"); qmlRegisterExtendedType<QWidget,QWidgetDeclarativeUI>("Qt.test",1,0,"QWidget"); qmlRegisterType<QPlainTextEdit>("Qt.test",1,0,"QPlainTextEdit"); + + qRegisterMetaType<MyQmlObject::MyType>("MyQmlObject::MyType"); } #include "testtypes.moc" diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h index 6c6ad1f..081cc4c 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -152,6 +152,11 @@ public: MyQmlObject *myinvokableObject; Q_INVOKABLE MyQmlObject *returnme() { return this; } + struct MyType { + int value; + }; + QVariant variant() const { return m_variant; } + signals: void basicSignal(); void argumentSignal(int a, QString b, qreal c); @@ -159,6 +164,7 @@ signals: void objectChanged(); void anotherBasicSignal(); void thirdBasicSignal(); + void signalWithUnknownType(const MyQmlObject::MyType &arg); public slots: void deleteMe() { delete this; } @@ -166,6 +172,7 @@ public slots: void method(int a) { if(a == 163) m_methodIntCalled = true; } void setString(const QString &s) { m_string = s; } void myinvokable(MyQmlObject *o) { myinvokableObject = o; } + void variantMethod(const QVariant &v) { m_variant = v; } private: friend class tst_qdeclarativeecmascript; @@ -178,6 +185,7 @@ private: int m_value; int m_resetProperty; QRegExp m_regExp; + QVariant m_variant; }; QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES) @@ -738,6 +746,168 @@ public: OverrideDefaultPropertyObject() {} }; +class MyRevisionedBaseClassRegistered : public QObject +{ +Q_OBJECT + Q_PROPERTY(qreal propA READ propA WRITE setPropA NOTIFY propAChanged) + Q_PROPERTY(qreal propB READ propB WRITE setPropB NOTIFY propBChanged REVISION 1) + +public: + MyRevisionedBaseClassRegistered() : m_pa(1), m_pb(2) {} + + qreal propA() const { return m_pa; } + void setPropA(qreal p) { + if (p != m_pa) { + m_pa = p; + emit propAChanged(); + } + } + qreal propB() const { return m_pb; } + void setPropB(qreal p) { + if (p != m_pb) { + m_pb = p; + emit propBChanged(); + } + } + + Q_INVOKABLE void methodA() { } + Q_INVOKABLE Q_REVISION(1) void methodB() { } + +signals: + void propAChanged(); + void propBChanged(); + + void signalA(); + Q_REVISION(1) void signalB(); + +protected: + qreal m_pa; + qreal m_pb; +}; + +class MyRevisionedBaseClassUnregistered : public MyRevisionedBaseClassRegistered +{ +Q_OBJECT + Q_PROPERTY(qreal propC READ propC WRITE setPropC NOTIFY propCChanged) + Q_PROPERTY(qreal propD READ propD WRITE setPropD NOTIFY propDChanged REVISION 1) + +public: + MyRevisionedBaseClassUnregistered() : m_pc(1), m_pd(2) {} + + qreal propC() const { return m_pc; } + void setPropC(qreal p) { + if (p != m_pc) { + m_pc = p; + emit propCChanged(); + } + } + qreal propD() const { return m_pd; } + void setPropD(qreal p) { + if (p != m_pd) { + m_pd = p; + emit propDChanged(); + } + } + + Q_INVOKABLE void methodC() { } + Q_INVOKABLE Q_REVISION(1) void methodD() { } + +signals: + void propCChanged(); + void propDChanged(); + + void signalC(); + Q_REVISION(1) void signalD(); + +protected: + qreal m_pc; + qreal m_pd; +}; + +class MyRevisionedClass : public MyRevisionedBaseClassUnregistered +{ + Q_OBJECT + Q_PROPERTY(qreal prop1 READ prop1 WRITE setProp1 NOTIFY prop1Changed) + Q_PROPERTY(qreal prop2 READ prop2 WRITE setProp2 NOTIFY prop2Changed REVISION 1) + +public: + MyRevisionedClass() {} + + qreal prop1() const { return m_p1; } + void setProp1(qreal p) { + if (p != m_p1) { + m_p1 = p; + emit prop1Changed(); + } + } + qreal prop2() const { return m_p2; } + void setProp2(qreal p) { + if (p != m_p2) { + m_p2 = p; + emit prop2Changed(); + } + } + + Q_INVOKABLE void method1() { } + Q_INVOKABLE Q_REVISION(1) void method2() { } + +signals: + void prop1Changed(); + void prop2Changed(); + + void signal1(); + Q_REVISION(1) void signal2(); + +protected: + qreal m_p1; + qreal m_p2; +}; + +class MyRevisionedSubclass : public MyRevisionedClass +{ + Q_OBJECT + Q_PROPERTY(qreal prop3 READ prop3 WRITE setProp3 NOTIFY prop3Changed) + Q_PROPERTY(qreal prop4 READ prop4 WRITE setProp4 NOTIFY prop4Changed REVISION 1) + +public: + MyRevisionedSubclass() : m_p3(3), m_p4(4) {} + + qreal prop3() const { return m_p3; } + void setProp3(qreal p) { + if (p != m_p3) { + m_p3 = p; + emit prop3Changed(); + } + } + qreal prop4() const { return m_p4; } + void setProp4(qreal p) { + if (p != m_p4) { + m_p4 = p; + emit prop4Changed(); + } + } + + Q_INVOKABLE void method3() { } + Q_INVOKABLE Q_REVISION(1) void method4() { } + +signals: + void prop3Changed(); + void prop4Changed(); + + void signal3(); + Q_REVISION(1) void signal4(); + +protected: + qreal m_p3; + qreal m_p4; +}; + +QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered) +QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered) +QML_DECLARE_TYPE(MyRevisionedClass) +QML_DECLARE_TYPE(MyRevisionedSubclass) +Q_DECLARE_METATYPE(MyQmlObject::MyType) + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 034adf7..40b0e1b 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -50,6 +50,7 @@ #include <QtCore/qnumeric.h> #include <private/qdeclarativeengine_p.h> #include <private/qdeclarativeglobalscriptclass_p.h> +#include <private/qscriptdeclarativeclass_p.h> #include "testtypes.h" #include "testhttpserver.h" #include "../../../shared/util.h" @@ -105,7 +106,7 @@ private slots: void constantsOverrideBindings(); void outerBindingOverridesInnerBinding(); void aliasPropertyAndBinding(); - void nonExistantAttachedObject(); + void nonExistentAttachedObject(); void scope(); void signalParameterTypes(); void objectsCompareAsEqual(); @@ -142,6 +143,7 @@ private slots: void compiled(); void numberAssignment(); void propertySplicing(); + void signalWithUnknownTypes(); void bug1(); void bug2(); @@ -155,7 +157,10 @@ private slots: void qtcreatorbug_1289(); void noSpuriousWarningsAtShutdown(); void canAssignNullToQObject(); - void functionAssignment(); + void functionAssignment_fromBinding(); + void functionAssignment_fromJS(); + void functionAssignment_fromJS_data(); + void functionAssignmentfromJS_invalid(); void eval(); void function(); void qtbug_10696(); @@ -170,12 +175,16 @@ private slots: void aliasBindingsAssignCorrectly(); void aliasBindingsOverrideTarget(); void aliasWritesOverrideBindings(); + void pushCleanContext(); void include(); void callQtInvokables(); void invokableObjectArg(); void invokableObjectRet(); + + void revisionErrors(); + void revision(); private: QDeclarativeEngine engine; }; @@ -643,7 +652,7 @@ void tst_qdeclarativeecmascript::attachedProperties() void tst_qdeclarativeecmascript::enums() { - // Existant enums + // Existent enums { QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml")); QObject *object = component.create(); @@ -785,9 +794,9 @@ Access a non-existent attached object. Tests for a regression where this used to crash. */ -void tst_qdeclarativeecmascript::nonExistantAttachedObject() +void tst_qdeclarativeecmascript::nonExistentAttachedObject() { - QDeclarativeComponent component(&engine, TEST_FILE("nonExistantAttachedObject.qml")); + QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml")); QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty"; QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); @@ -2334,6 +2343,26 @@ void tst_qdeclarativeecmascript::propertySplicing() delete object; } +// QTBUG-16683 +void tst_qdeclarativeecmascript::signalWithUnknownTypes() +{ + QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml")); + + MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(object != 0); + + MyQmlObject::MyType type; + type.value = 0x8971123; + emit object->signalWithUnknownType(type); + + MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant()); + + QCOMPARE(result.value, type.value); + + + delete object; +} + // Test that assigning a null object works // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4 void tst_qdeclarativeecmascript::nullObjectBinding() @@ -2511,9 +2540,8 @@ void tst_qdeclarativeecmascript::canAssignNullToQObject() } } -void tst_qdeclarativeecmascript::functionAssignment() +void tst_qdeclarativeecmascript::functionAssignment_fromBinding() { - { QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml")); QString url = component.url().toString(); @@ -2526,26 +2554,64 @@ void tst_qdeclarativeecmascript::functionAssignment() QVERIFY(!o->property("a").isValid()); delete o; - } +} + +void tst_qdeclarativeecmascript::functionAssignment_fromJS() +{ + QFETCH(QString, triggerProperty); - { QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml")); + QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString())); MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create()); QVERIFY(o != 0); + QVERIFY(!o->property("a").isValid()); + + o->setProperty("aNumber", QVariant(5)); + o->setProperty(triggerProperty.toUtf8().constData(), true); + QCOMPARE(o->property("a"), QVariant(50)); + o->setProperty("aNumber", QVariant(10)); + QCOMPARE(o->property("a"), QVariant(100)); + + delete o; +} + +void tst_qdeclarativeecmascript::functionAssignment_fromJS_data() +{ + QTest::addColumn<QString>("triggerProperty"); + + QTest::newRow("assign to property") << "assignToProperty"; + QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile"; + + QTest::newRow("assign to value type") << "assignToValueType"; + + QTest::newRow("use 'this'") << "assignWithThis"; + QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile"; +} + +void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid() +{ + QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml")); + QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString())); + + MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create()); + QVERIFY(o != 0); QVERIFY(!o->property("a").isValid()); - + + o->setProperty("assignFuncWithoutReturn", true); + QVERIFY(!o->property("a").isValid()); + QString url = component.url().toString(); - QString warning = url + ":10: Error: Cannot assign a function to a property."; + QString warning = url + ":63: Unable to assign QString to int"; QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); - - o->setProperty("runTest", true); - - QVERIFY(!o->property("a").isValid()); + o->setProperty("assignWrongType", true); + + warning = url + ":70: Unable to assign QString to int"; + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + o->setProperty("assignWrongTypeToValueType", true); delete o; - } } void tst_qdeclarativeecmascript::eval() @@ -2863,6 +2929,132 @@ void tst_qdeclarativeecmascript::aliasWritesOverrideBindings() } } +void tst_qdeclarativeecmascript::revisionErrors() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml")); + QString url = component.url().toString(); + + QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2"; + QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2"; + QString warning3 = url + ":13: ReferenceError: Can't find variable: method2"; + + QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData()); + MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create()); + QVERIFY(object != 0); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml")); + QString url = component.url().toString(); + + // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0 + // method2, prop2 from MyRevisionedClass not available + // method4, prop4 from MyRevisionedSubclass not available + QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2"; + QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2"; + QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4"; + QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4"; + QString warning5 = url + ":20: ReferenceError: Can't find variable: method2"; + + QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData()); + MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create()); + QVERIFY(object != 0); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml")); + QString url = component.url().toString(); + + // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1 + // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1 + QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD"; + QString warning2 = url + ":10: ReferenceError: Can't find variable: propD"; + QString warning3 = url + ":20: ReferenceError: Can't find variable: propD"; + QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData()); + MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create()); + QVERIFY(object != 0); + } +} + +void tst_qdeclarativeecmascript::revision() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml")); + QString url = component.url().toString(); + + MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create()); + QVERIFY(object != 0); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml")); + QString url = component.url().toString(); + + MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create()); + QVERIFY(object != 0); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml")); + QString url = component.url().toString(); + + MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create()); + QVERIFY(object != 0); + } + // Test that non-root classes can resolve revisioned methods + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("test").toReal(), 11.); + delete object; + } +} + +// Test for QScriptDeclarativeClass::pushCleanContext() +void tst_qdeclarativeecmascript::pushCleanContext() +{ + QScriptEngine engine; + engine.globalObject().setProperty("a", 6); + QCOMPARE(engine.evaluate("a").toInt32(), 6); + + // First confirm pushContext() behaves as we expect + QScriptValue object = engine.newObject(); + object.setProperty("a", 15); + QScriptContext *context1 = engine.pushContext(); + context1->pushScope(object); + QCOMPARE(engine.evaluate("a").toInt32(), 15); + + QScriptContext *context2 = engine.pushContext(); + Q_UNUSED(context2); + QCOMPARE(engine.evaluate("a").toInt32(), 15); + QScriptValue func1 = engine.evaluate("(function() { return a; })"); + + // Now check that pushCleanContext() works + QScriptDeclarativeClass::pushCleanContext(&engine); + QCOMPARE(engine.evaluate("a").toInt32(), 6); + QScriptValue func2 = engine.evaluate("(function() { return a; })"); + + engine.popContext(); + QCOMPARE(engine.evaluate("a").toInt32(), 15); + + engine.popContext(); + QCOMPARE(engine.evaluate("a").toInt32(), 15); + + engine.popContext(); + QCOMPARE(engine.evaluate("a").toInt32(), 6); + + // Check that function objects created in these contexts work + QCOMPARE(func1.call().toInt32(), 15); + QCOMPARE(func2.call().toInt32(), 6); +} + QTEST_MAIN(tst_qdeclarativeecmascript) #include "tst_qdeclarativeecmascript.moc" diff --git a/tests/auto/declarative/qdeclarativeflickable/data/resize.qml b/tests/auto/declarative/qdeclarativeflickable/data/resize.qml new file mode 100644 index 0000000..e2abb99 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeflickable/data/resize.qml @@ -0,0 +1,27 @@ +import QtQuick 1.1 + +Rectangle { + function resizeContent() { + flick.resizeContent(600, 600, Qt.point(100, 100)) + } + function returnToBounds() { + flick.returnToBounds() + } + width: 400 + height: 360 + color: "gray" + + Flickable { + id: flick + objectName: "flick" + anchors.fill: parent + contentWidth: 300 + contentHeight: 300 + + Rectangle { + width: flick.contentWidth + height: flick.contentHeight + color: "red" + } + } +} diff --git a/tests/auto/declarative/qdeclarativeflickable/data/wheel.qml b/tests/auto/declarative/qdeclarativeflickable/data/wheel.qml new file mode 100644 index 0000000..6ea81b2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeflickable/data/wheel.qml @@ -0,0 +1,21 @@ +import QtQuick 1.1 + +Rectangle { + width: 400 + height: 400 + color: "gray" + + Flickable { + id: flick + objectName: "flick" + anchors.fill: parent + contentWidth: 800 + contentHeight: 800 + + Rectangle { + width: flick.contentWidth + height: flick.contentHeight + color: "red" + } + } +} diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index 1bf93ee..f4bec8f 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -42,10 +42,12 @@ #include <QtTest/QSignalSpy> #include <QtDeclarative/qdeclarativeengine.h> #include <QtDeclarative/qdeclarativecomponent.h> +#include <QtDeclarative/qdeclarativeview.h> #include <private/qdeclarativeflickable_p.h> #include <private/qdeclarativevaluetype_p.h> #include <QtGui/qgraphicswidget.h> #include <math.h> +#include "../../../shared/util.h" #ifdef Q_OS_SYMBIAN // In Symbian OS test data is located in applications private dir @@ -69,6 +71,11 @@ private slots: void pressDelay(); void flickableDirection(); void qgraphicswidget(); + void resizeContent(); + void returnToBounds(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); + void wheel(); private: QDeclarativeEngine engine; @@ -277,6 +284,135 @@ void tst_qdeclarativeflickable::qgraphicswidget() QVERIFY(widget); } +// QtQuick 1.1 +void tst_qdeclarativeflickable::resizeContent() +{ + QDeclarativeEngine engine; + QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/resize.qml")); + QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(c.create()); + QDeclarativeFlickable *obj = findItem<QDeclarativeFlickable>(root, "flick"); + + QVERIFY(obj != 0); + QCOMPARE(obj->contentX(), 0.); + QCOMPARE(obj->contentY(), 0.); + QCOMPARE(obj->contentWidth(), 300.); + QCOMPARE(obj->contentHeight(), 300.); + + QMetaObject::invokeMethod(root, "resizeContent"); + + QCOMPARE(obj->contentX(), 100.); + QCOMPARE(obj->contentY(), 100.); + QCOMPARE(obj->contentWidth(), 600.); + QCOMPARE(obj->contentHeight(), 600.); + + delete root; +} + +// QtQuick 1.1 +void tst_qdeclarativeflickable::returnToBounds() +{ + QDeclarativeEngine engine; + QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/resize.qml")); + QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(c.create()); + QDeclarativeFlickable *obj = findItem<QDeclarativeFlickable>(root, "flick"); + + QVERIFY(obj != 0); + QCOMPARE(obj->contentX(), 0.); + QCOMPARE(obj->contentY(), 0.); + QCOMPARE(obj->contentWidth(), 300.); + QCOMPARE(obj->contentHeight(), 300.); + + obj->setContentX(100); + obj->setContentY(400); + QTRY_COMPARE(obj->contentX(), 100.); + QTRY_COMPARE(obj->contentY(), 400.); + + QMetaObject::invokeMethod(root, "returnToBounds"); + + QTRY_COMPARE(obj->contentX(), 0.); + QTRY_COMPARE(obj->contentY(), 0.); + + delete root; +} + +void tst_qdeclarativeflickable::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; Flickable { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; Flickable { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; +} + +void tst_qdeclarativeflickable::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("resizeContent") << "Component.onCompleted: resizeContent(100,100,Qt.point(50,50))" + << "<Unknown File>:1: ReferenceError: Can't find variable: resizeContent" + << ""; + + QTest::newRow("returnToBounds") << "Component.onCompleted: returnToBounds()" + << "<Unknown File>:1: ReferenceError: Can't find variable: returnToBounds" + << ""; + +} + +void tst_qdeclarativeflickable::wheel() +{ + QDeclarativeView *canvas = new QDeclarativeView; + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/wheel.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeFlickable *flick = canvas->rootObject()->findChild<QDeclarativeFlickable*>("flick"); + QVERIFY(flick != 0); + + QGraphicsScene *scene = canvas->scene(); + QGraphicsSceneWheelEvent event(QEvent::GraphicsSceneWheel); + event.setScenePos(QPointF(200, 200)); + event.setDelta(-120); + event.setOrientation(Qt::Vertical); + event.setAccepted(false); + QApplication::sendEvent(scene, &event); + + QTRY_VERIFY(flick->contentY() > 0); + QVERIFY(flick->contentX() == 0); + + flick->setContentY(0); + QVERIFY(flick->contentY() == 0); + + event.setScenePos(QPointF(200, 200)); + event.setDelta(-120); + event.setOrientation(Qt::Horizontal); + event.setAccepted(false); + QApplication::sendEvent(scene, &event); + + QTRY_VERIFY(flick->contentX() > 0); + QVERIFY(flick->contentY() == 0); + + delete canvas; +} + + template<typename T> T *tst_qdeclarativeflickable::findItem(QGraphicsObject *parent, const QString &objectName) { diff --git a/tests/auto/declarative/qdeclarativegridview/data/attachedSignals.qml b/tests/auto/declarative/qdeclarativegridview/data/attachedSignals.qml new file mode 100644 index 0000000..d527e9d --- /dev/null +++ b/tests/auto/declarative/qdeclarativegridview/data/attachedSignals.qml @@ -0,0 +1,27 @@ +import QtQuick 1.0 + +GridView { + id: view + width: 240; height: 320 + + property variant addedDelegates: [] + property int removedDelegateCount + + model: testModel + + cellWidth: delegateWidth; cellHeight: delegateHeight + + delegate: Rectangle { + width: delegateWidth; height: delegateHeight + border.width: 1 + GridView.onAdd: { + var obj = GridView.view.addedDelegates + obj.push(model.name) + GridView.view.addedDelegates = obj + } + GridView.onRemove: { + view.removedDelegateCount += 1 + } + } +} + diff --git a/tests/auto/declarative/qdeclarativegridview/data/footer.qml b/tests/auto/declarative/qdeclarativegridview/data/footer.qml index ad69a25..b41e2ac 100644 --- a/tests/auto/declarative/qdeclarativegridview/data/footer.qml +++ b/tests/auto/declarative/qdeclarativegridview/data/footer.qml @@ -1,6 +1,9 @@ import QtQuick 1.0 Rectangle { + function changeFooter() { + grid.footer = footer2 + } width: 240 height: 320 color: "#ffffff" @@ -29,4 +32,9 @@ Rectangle { delegate: myDelegate footer: Text { objectName: "footer"; text: "Footer"; height: 30 } } + + Component { + id: footer2 + Text { objectName: "footer2"; text: "Footer 2"; height: 20 } + } } diff --git a/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml b/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml index 77c94ba..e4e699c 100644 --- a/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml +++ b/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml @@ -2,6 +2,8 @@ import QtQuick 1.0 Rectangle { id: root + property bool showHeader: false + property bool showFooter: false property int added: -1 property variant removed @@ -40,6 +42,10 @@ Rectangle { GridView.onAdd: root.added = index GridView.onRemove: root.removed = name } + }, + Component { + id: headerFooter + Rectangle { width: 30; height: 320; color: "blue" } } ] GridView { @@ -52,5 +58,7 @@ Rectangle { flow: (testTopToBottom == false) ? "LeftToRight" : "TopToBottom" model: testModel delegate: myDelegate + header: root.showHeader ? headerFooter : null + footer: root.showFooter ? headerFooter : null } } diff --git a/tests/auto/declarative/qdeclarativegridview/data/header.qml b/tests/auto/declarative/qdeclarativegridview/data/header.qml index 99baacd..f39da55 100644 --- a/tests/auto/declarative/qdeclarativegridview/data/header.qml +++ b/tests/auto/declarative/qdeclarativegridview/data/header.qml @@ -1,6 +1,9 @@ import QtQuick 1.0 Rectangle { + function changeHeader() { + grid.header = header2 + } width: 240 height: 320 color: "#ffffff" @@ -29,4 +32,9 @@ Rectangle { delegate: myDelegate header: Text { objectName: "header"; text: "Header"; height: 30 } } + + Component { + id: header2 + Text { objectName: "header2"; text: "Header 2"; height: 20 } + } } diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp index 0fac0fc..79189a7 100644 --- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp +++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp @@ -78,6 +78,7 @@ private slots: void componentChanges(); void modelChanges(); void positionViewAtIndex(); + void snapping(); void resetModel(); void enforceRange(); void QTBUG_8456(); @@ -85,6 +86,12 @@ private slots: void footer(); void header(); void indexAt(); + void onAdd(); + void onAdd_data(); + void onRemove(); + void onRemove_data(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QDeclarativeView *createView(); @@ -128,6 +135,13 @@ public: emit endInsertRows(); } + void addItems(const QList<QPair<QString, QString> > &items) { + emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1); + for (int i=0; i<items.count(); i++) + list.append(QPair<QString,QString>(items[i].first, items[i].second)); + emit endInsertRows(); + } + void insertItem(int index, const QString &name, const QString &number) { emit beginInsertRows(QModelIndex(), index, index); list.insert(index, QPair<QString,QString>(name, number)); @@ -140,6 +154,13 @@ public: emit endRemoveRows(); } + void removeItems(int index, int count) { + emit beginRemoveRows(QModelIndex(), index, index+count-1); + while (count--) + list.removeAt(index); + emit endRemoveRows(); + } + void moveItem(int from, int to) { emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); list.move(from, to); @@ -994,6 +1015,7 @@ void tst_QDeclarativeGridView::positionViewAtIndex() // Position on a currently visible item gridview->positionViewAtIndex(4, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->indexAt(120, 90), 4); QTRY_COMPARE(gridview->contentY(), 60.); // Confirm items positioned correctly @@ -1008,6 +1030,7 @@ void tst_QDeclarativeGridView::positionViewAtIndex() // Position on an item beyond the visible items gridview->positionViewAtIndex(21, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->indexAt(40, 450), 21); QTRY_COMPARE(gridview->contentY(), 420.); // Confirm items positioned correctly @@ -1022,6 +1045,7 @@ void tst_QDeclarativeGridView::positionViewAtIndex() // Position on an item that would leave empty space if positioned at the top gridview->positionViewAtIndex(31, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->indexAt(120, 630), 31); QTRY_COMPARE(gridview->contentY(), 520.); // Confirm items positioned correctly @@ -1036,6 +1060,9 @@ void tst_QDeclarativeGridView::positionViewAtIndex() // Position at the beginning again gridview->positionViewAtIndex(0, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->indexAt(0, 0), 0); + QTRY_COMPARE(gridview->indexAt(40, 30), 0); + QTRY_COMPARE(gridview->indexAt(80, 60), 4); QTRY_COMPARE(gridview->contentY(), 0.); // Confirm items positioned correctly @@ -1089,6 +1116,100 @@ void tst_QDeclarativeGridView::positionViewAtIndex() gridview->positionViewAtIndex(20, QDeclarativeGridView::Contain); QTRY_COMPARE(gridview->contentY(), 100.); + // Test for Top To Bottom layout + ctxt->setContextProperty("testTopToBottom", QVariant(true)); + + // Confirm items positioned correctly + itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount-1; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_COMPARE(item->x(), (i/5)*80.); + QTRY_COMPARE(item->y(), (i%5)*60.); + } + + // Position at End + gridview->positionViewAtIndex(30, QDeclarativeGridView::End); + QTRY_COMPARE(gridview->contentX(), 320.); + QTRY_COMPARE(gridview->contentY(), 0.); + + // Position in Center + gridview->positionViewAtIndex(15, QDeclarativeGridView::Center); + QTRY_COMPARE(gridview->contentX(), 160.); + + // Ensure at least partially visible + gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible); + QTRY_COMPARE(gridview->contentX(), 160.); + + gridview->setContentX(170); + gridview->positionViewAtIndex(25, QDeclarativeGridView::Visible); + QTRY_COMPARE(gridview->contentX(), 170.); + + gridview->positionViewAtIndex(30, QDeclarativeGridView::Visible); + QTRY_COMPARE(gridview->contentX(), 320.); + + gridview->setContentX(170); + gridview->positionViewAtIndex(25, QDeclarativeGridView::Contain); + QTRY_COMPARE(gridview->contentX(), 240.); + + // positionViewAtBeginning + gridview->positionViewAtBeginning(); + QTRY_COMPARE(gridview->contentX(), 0.); + + gridview->setContentX(80); + canvas->rootObject()->setProperty("showHeader", true); + gridview->positionViewAtBeginning(); + QTRY_COMPARE(gridview->contentX(), -30.); + + // positionViewAtEnd + gridview->positionViewAtEnd(); + QTRY_COMPARE(gridview->contentX(), 430.); + + gridview->setContentX(80); + canvas->rootObject()->setProperty("showFooter", true); + gridview->positionViewAtEnd(); + QTRY_COMPARE(gridview->contentX(), 460.); + + delete canvas; +} + +void tst_QDeclarativeGridView::snapping() +{ + QDeclarativeView *canvas = createView(); + + TestModel model; + for (int i = 0; i < 40; i++) + model.addItem("Item" + QString::number(i), ""); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testTopToBottom", QVariant(false)); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); + qApp->processEvents(); + + QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid"); + QTRY_VERIFY(gridview != 0); + + gridview->setHeight(220); + QCOMPARE(gridview->height(), 220.); + + gridview->positionViewAtIndex(12, QDeclarativeGridView::Visible); + QCOMPARE(gridview->contentY(), 80.); + + gridview->setContentY(0); + QCOMPARE(gridview->contentY(), 0.); + + gridview->setSnapMode(QDeclarativeGridView::SnapToRow); + QCOMPARE(gridview->snapMode(), QDeclarativeGridView::SnapToRow); + + gridview->positionViewAtIndex(12, QDeclarativeGridView::Visible); + QCOMPARE(gridview->contentY(), 60.); + + gridview->positionViewAtIndex(15, QDeclarativeGridView::End); + QCOMPARE(gridview->contentY(), 120.); + delete canvas; } @@ -1232,6 +1353,15 @@ void tst_QDeclarativeGridView::manualHighlight() QTRY_COMPARE(gridview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 2)); QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y()); QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x()); + + gridview->setFlow(QDeclarativeGridView::TopToBottom); + QTRY_COMPARE(gridview->flow(), QDeclarativeGridView::TopToBottom); + + gridview->setCurrentIndex(0); + QTRY_COMPARE(gridview->currentIndex(), 0); + QTRY_COMPARE(gridview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 0)); + QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y()); + QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x()); } void tst_QDeclarativeGridView::footer() @@ -1258,12 +1388,27 @@ void tst_QDeclarativeGridView::footer() QVERIFY(footer); QCOMPARE(footer->y(), 180.0); + QCOMPARE(footer->height(), 30.0); model.removeItem(2); QTRY_COMPARE(footer->y(), 120.0); model.clear(); QTRY_COMPARE(footer->y(), 0.0); + + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter"); + + footer = findItem<QDeclarativeText>(contentItem, "footer"); + QVERIFY(!footer); + footer = findItem<QDeclarativeText>(contentItem, "footer2"); + QVERIFY(footer); + + QCOMPARE(footer->y(), 600.0); + QCOMPARE(footer->height(), 20.0); + QCOMPARE(gridview->contentY(), 0.0); } void tst_QDeclarativeGridView::header() @@ -1290,6 +1435,7 @@ void tst_QDeclarativeGridView::header() QVERIFY(header); QCOMPARE(header->y(), 0.0); + QCOMPARE(header->height(), 30.0); QCOMPARE(gridview->contentY(), 0.0); QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", 0); @@ -1298,6 +1444,20 @@ void tst_QDeclarativeGridView::header() model.clear(); QTRY_COMPARE(header->y(), 0.0); + + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader"); + + header = findItem<QDeclarativeText>(contentItem, "header"); + QVERIFY(!header); + header = findItem<QDeclarativeText>(contentItem, "header2"); + QVERIFY(header); + + QCOMPARE(header->y(), 10.0); + QCOMPARE(header->height(), 20.0); + QCOMPARE(gridview->contentY(), 10.0); } void tst_QDeclarativeGridView::indexAt() @@ -1337,6 +1497,156 @@ void tst_QDeclarativeGridView::indexAt() delete canvas; } +void tst_QDeclarativeGridView::onAdd() +{ + QFETCH(int, initialItemCount); + QFETCH(int, itemsToAdd); + + const int delegateWidth = 50; + const int delegateHeight = 100; + TestModel model; + QDeclarativeView *canvas = createView(); + canvas->setFixedSize(5 * delegateWidth, 5 * delegateHeight); // just ensure all items fit + + // these initial items should not trigger GridView.onAdd + for (int i=0; i<initialItemCount; i++) + model.addItem("dummy value", "dummy value"); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("delegateWidth", delegateWidth); + ctxt->setContextProperty("delegateHeight", delegateHeight); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml")); + + QObject *object = canvas->rootObject(); + object->setProperty("width", canvas->width()); + object->setProperty("height", canvas->height()); + qApp->processEvents(); + + QList<QPair<QString, QString> > items; + for (int i=0; i<itemsToAdd; i++) + items << qMakePair(QString("value %1").arg(i), QString::number(i)); + model.addItems(items); + + qApp->processEvents(); + + QVariantList result = object->property("addedDelegates").toList(); + QCOMPARE(result.count(), items.count()); + for (int i=0; i<items.count(); i++) + QCOMPARE(result[i].toString(), items[i].first); + + delete canvas; +} + +void tst_QDeclarativeGridView::onAdd_data() +{ + QTest::addColumn<int>("initialItemCount"); + QTest::addColumn<int>("itemsToAdd"); + + QTest::newRow("0, add 1") << 0 << 1; + QTest::newRow("0, add 2") << 0 << 2; + QTest::newRow("0, add 10") << 0 << 10; + + QTest::newRow("1, add 1") << 1 << 1; + QTest::newRow("1, add 2") << 1 << 2; + QTest::newRow("1, add 10") << 1 << 10; + + QTest::newRow("5, add 1") << 5 << 1; + QTest::newRow("5, add 2") << 5 << 2; + QTest::newRow("5, add 10") << 5 << 10; +} + +void tst_QDeclarativeGridView::onRemove() +{ + QFETCH(int, initialItemCount); + QFETCH(int, indexToRemove); + QFETCH(int, removeCount); + + const int delegateWidth = 50; + const int delegateHeight = 100; + TestModel model; + for (int i=0; i<initialItemCount; i++) + model.addItem(QString("value %1").arg(i), "dummy value"); + + QDeclarativeView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("delegateWidth", delegateWidth); + ctxt->setContextProperty("delegateHeight", delegateHeight); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml")); + QObject *object = canvas->rootObject(); + + qApp->processEvents(); + + model.removeItems(indexToRemove, removeCount); + qApp->processEvents(); + QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount)); + + delete canvas; +} + +void tst_QDeclarativeGridView::onRemove_data() +{ + QTest::addColumn<int>("initialItemCount"); + QTest::addColumn<int>("indexToRemove"); + QTest::addColumn<int>("removeCount"); + + QTest::newRow("remove first") << 1 << 0 << 1; + QTest::newRow("two items, remove first") << 2 << 0 << 1; + QTest::newRow("two items, remove last") << 2 << 1 << 1; + QTest::newRow("two items, remove all") << 2 << 0 << 2; + + QTest::newRow("four items, remove first") << 4 << 0 << 1; + QTest::newRow("four items, remove 0-2") << 4 << 0 << 2; + QTest::newRow("four items, remove 1-3") << 4 << 1 << 2; + QTest::newRow("four items, remove 2-4") << 4 << 2 << 2; + QTest::newRow("four items, remove last") << 4 << 3 << 1; + QTest::newRow("four items, remove all") << 4 << 0 << 4; + + QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8; + QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5; + QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6; +} + +void tst_QDeclarativeGridView::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; GridView { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; GridView { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_QDeclarativeGridView::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("positionViewAtBeginning") << "Component.onCompleted: positionViewAtBeginning()" + << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtBeginning" + << ""; + + QTest::newRow("positionViewAtEnd") << "Component.onCompleted: positionViewAtEnd()" + << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtEnd" + << ""; +} + QDeclarativeView *tst_QDeclarativeGridView::createView() { QDeclarativeView *canvas = new QDeclarativeView(0); diff --git a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp index ddecf7e..f1fe2bd 100644 --- a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp +++ b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp @@ -79,6 +79,8 @@ private slots: void resized(); void preserveAspectRatio(); void smooth(); + void mirror(); + void mirror_data(); void svg(); void geometry(); void geometry_data(); @@ -88,6 +90,8 @@ private slots: void paintedWidthHeight(); void sourceSize_QTBUG_14303(); void nullPixmapPaint(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: template<typename T> @@ -124,19 +128,21 @@ void tst_qdeclarativeimage::imageSource_data() QTest::addColumn<double>("height"); QTest::addColumn<bool>("remote"); QTest::addColumn<bool>("async"); + QTest::addColumn<bool>("cache"); QTest::addColumn<QString>("error"); - QTest::newRow("local") << QUrl::fromLocalFile(SRCDIR "/data/colors.png").toString() << 120.0 << 120.0 << false << false << ""; - QTest::newRow("local async") << QUrl::fromLocalFile(SRCDIR "/data/colors1.png").toString() << 120.0 << 120.0 << false << true << ""; + QTest::newRow("local") << QUrl::fromLocalFile(SRCDIR "/data/colors.png").toString() << 120.0 << 120.0 << false << false << true << ""; + QTest::newRow("local no cache") << QUrl::fromLocalFile(SRCDIR "/data/colors.png").toString() << 120.0 << 120.0 << false << false << false << ""; + QTest::newRow("local async") << QUrl::fromLocalFile(SRCDIR "/data/colors1.png").toString() << 120.0 << 120.0 << false << true << true << ""; QTest::newRow("local not found") << QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString() << 0.0 << 0.0 << false - << false << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString(); + << false << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString(); QTest::newRow("local async not found") << QUrl::fromLocalFile(SRCDIR "/data/no-such-file-1.png").toString() << 0.0 << 0.0 << false - << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/no-such-file-1.png").toString(); - QTest::newRow("remote") << SERVER_ADDR "/colors.png" << 120.0 << 120.0 << true << false << ""; - QTest::newRow("remote redirected") << SERVER_ADDR "/oldcolors.png" << 120.0 << 120.0 << true << false << ""; - QTest::newRow("remote svg") << SERVER_ADDR "/heart.svg" << 550.0 << 500.0 << true << false << ""; + << true << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/no-such-file-1.png").toString(); + QTest::newRow("remote") << SERVER_ADDR "/colors.png" << 120.0 << 120.0 << true << false << true << ""; + QTest::newRow("remote redirected") << SERVER_ADDR "/oldcolors.png" << 120.0 << 120.0 << true << false << false << ""; + QTest::newRow("remote svg") << SERVER_ADDR "/heart.svg" << 550.0 << 500.0 << true << false << false << ""; QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << 0.0 << 0.0 << true - << false << "file::2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found"; + << false << true << "file::2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found"; } @@ -147,6 +153,7 @@ void tst_qdeclarativeimage::imageSource() QFETCH(double, height); QFETCH(bool, remote); QFETCH(bool, async); + QFETCH(bool, cache); QFETCH(QString, error); TestHTTPServer server(SERVER_PORT); @@ -159,8 +166,9 @@ void tst_qdeclarativeimage::imageSource() if (!error.isEmpty()) QTest::ignoreMessage(QtWarningMsg, error.toUtf8()); - QString componentStr = "import QtQuick 1.0\nImage { source: \"" + source + "\"; asynchronous: " - + (async ? QLatin1String("true") : QLatin1String("false")) + " }"; + QString componentStr = "import QtQuick 1.1\nImage { source: \"" + source + "\"; asynchronous: " + + (async ? QLatin1String("true") : QLatin1String("false")) + "; cache: " + + (cache ? QLatin1String("true") : QLatin1String("false")) + " }"; QDeclarativeComponent component(&engine); component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QDeclarativeImage *obj = qobject_cast<QDeclarativeImage*>(component.create()); @@ -168,6 +176,13 @@ void tst_qdeclarativeimage::imageSource() if (async) QVERIFY(obj->asynchronous() == true); + else + QVERIFY(obj->asynchronous() == false); + + if (cache) + QVERIFY(obj->cache() == true); + else + QVERIFY(obj->cache() == false); if (remote || async) QTRY_VERIFY(obj->status() == QDeclarativeImage::Loading); @@ -259,6 +274,90 @@ void tst_qdeclarativeimage::smooth() delete obj; } +void tst_qdeclarativeimage::mirror() +{ + QFETCH(int, fillMode); + + qreal width = 300; + qreal height = 250; + + QString src = QUrl::fromLocalFile(SRCDIR "/data/heart200.png").toString(); + QString componentStr = "import QtQuick 1.1\nImage { source: \"" + src + "\"; }"; + + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeImage *obj = qobject_cast<QDeclarativeImage*>(component.create()); + QVERIFY(obj != 0); + + obj->setProperty("width", width); + obj->setProperty("height", height); + obj->setFillMode((QDeclarativeImage::FillMode)fillMode); + obj->setProperty("mirror", true); + + QGraphicsScene scene; + scene.addItem(qobject_cast<QGraphicsObject *>(obj)); + QPixmap screenshot(width, height); + screenshot.fill(); + QPainter p_screenshot(&screenshot); + scene.render(&p_screenshot, QRect(0, 0, width, height), QRect(0, 0, width, height)); + + QPixmap srcPixmap; + QVERIFY(srcPixmap.load(SRCDIR "/data/heart200.png")); + + QPixmap expected(width, height); + expected.fill(); + QPainter p_e(&expected); + QTransform transform; + transform.translate(width, 0).scale(-1, 1.0); + p_e.setTransform(transform); + + switch (fillMode) { + case QDeclarativeImage::Stretch: + p_e.drawPixmap(QRect(0, 0, width, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height())); + break; + case QDeclarativeImage::PreserveAspectFit: + p_e.drawPixmap(QRect(25, 0, width / (width/height), height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height())); + break; + case QDeclarativeImage::PreserveAspectCrop: + { + qreal ratio = width/srcPixmap.width(); // width is the longer side + QRect rect(0, 0, srcPixmap.width()*ratio, srcPixmap.height()*ratio); + rect.moveCenter(QRect(0, 0, width, height).center()); + p_e.drawPixmap(rect, srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height())); + break; + } + case QDeclarativeImage::Tile: + p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap); + break; + case QDeclarativeImage::TileVertically: + transform.scale(width / srcPixmap.width(), 1.0); + p_e.setTransform(transform); + p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap); + break; + case QDeclarativeImage::TileHorizontally: + transform.scale(1.0, height / srcPixmap.height()); + p_e.setTransform(transform); + p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap); + break; + } + + QCOMPARE(screenshot, expected); + + delete obj; +} + +void tst_qdeclarativeimage::mirror_data() +{ + QTest::addColumn<int>("fillMode"); + + QTest::newRow("Stretch") << int(QDeclarativeImage::Stretch); + QTest::newRow("PreserveAspectFit") << int(QDeclarativeImage::PreserveAspectFit); + QTest::newRow("PreserveAspectCrop") << int(QDeclarativeImage::PreserveAspectCrop); + QTest::newRow("Tile") << int(QDeclarativeImage::Tile); + QTest::newRow("TileVertically") << int(QDeclarativeImage::TileVertically); + QTest::newRow("TileHorizontally") << int(QDeclarativeImage::TileHorizontally); +} + void tst_qdeclarativeimage::svg() { QString src = QUrl::fromLocalFile(SRCDIR "/data/heart.svg").toString(); @@ -570,6 +669,45 @@ void tst_qdeclarativeimage::nullPixmapPaint() delete image; } +void tst_qdeclarativeimage::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; Image { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; Image { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_qdeclarativeimage::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("mirror") << "mirror: true" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Image.mirror\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("cache") << "cache: true" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Image.cache\" is not available in QtQuick 1.0.\n"; +} + /* Find an item with the specified objectName. If index is supplied then the item must also evaluate the {index} expression equal to index diff --git a/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp b/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp index 5b214e6..6d35332 100644 --- a/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp +++ b/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp @@ -180,6 +180,10 @@ void tst_qdeclarativeimageprovider::fillRequestTestsData(const QString &id) << "image://test/" + fileName << fileName << "" << QSize(100,100) << ""; fileName = newImageFileName(); + QTest::newRow(QTest::toString(id + " simple test with capitalization"))//As it's a URL, should make no difference + << "image://Test/" + fileName << fileName << "" << QSize(100,100) << ""; + + fileName = newImageFileName(); QTest::newRow(QTest::toString(id + " url with no id")) << "image://test/" + fileName << "" + fileName << "" << QSize(100,100) << ""; diff --git a/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp b/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp index 9ac6137..b5edec8 100644 --- a/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp +++ b/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp @@ -512,7 +512,7 @@ void tst_qdeclarativeinstruction::dump() { QDeclarativeInstruction i; i.line = 50; - i.type = (QDeclarativeInstruction::Type)(1234); // Non-existant + i.type = (QDeclarativeInstruction::Type)(1234); // Non-existent data->bytecode << i; } diff --git a/tests/auto/declarative/qdeclarativeitem/data/implicitsize.qml b/tests/auto/declarative/qdeclarativeitem/data/implicitsize.qml new file mode 100644 index 0000000..869c0fc --- /dev/null +++ b/tests/auto/declarative/qdeclarativeitem/data/implicitsize.qml @@ -0,0 +1,19 @@ +import QtQuick 1.1 + +Item { + implicitWidth: 200 + implicitHeight: 100 + + width: 80 + height: 60 + + function resetSize() { + width = undefined + height = undefined + } + + function changeImplicit() { + implicitWidth = 150 + implicitHeight = 80 + } +} diff --git a/tests/auto/declarative/qdeclarativeitem/data/qtbug_16871.qml b/tests/auto/declarative/qdeclarativeitem/data/qtbug_16871.qml new file mode 100644 index 0000000..8102df1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeitem/data/qtbug_16871.qml @@ -0,0 +1,5 @@ +import QtQuick 1.0 + +Item { + children: [ 10 ] +} diff --git a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp index 57f7a95..137522d 100644 --- a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp +++ b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp @@ -65,6 +65,7 @@ private slots: void keys(); void keysProcessingOrder(); void keyNavigation(); + void keyNavigation_skipNotVisible(); void smooth(); void clip(); void mapCoordinates(); @@ -82,6 +83,10 @@ private slots: void mouseFocus(); void transformCrash(); + void implicitSize(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); + void qtbug_16871(); private: template<typename T> @@ -455,6 +460,84 @@ void tst_QDeclarativeItem::keyNavigation() delete canvas; } +void tst_QDeclarativeItem::keyNavigation_skipNotVisible() +{ + QDeclarativeView *canvas = new QDeclarativeView(0); + canvas->setFixedSize(240,320); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/keynavigationtest.qml")); + canvas->show(); + qApp->processEvents(); + + QEvent wa(QEvent::WindowActivate); + QApplication::sendEvent(canvas, &wa); + QFocusEvent fe(QEvent::FocusIn); + QApplication::sendEvent(canvas, &fe); + + QDeclarativeItem *item = findItem<QDeclarativeItem>(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // Set item 2 to not visible + item = findItem<QDeclarativeItem>(canvas->rootObject(), "item2"); + QVERIFY(item); + item->setVisible(false); + QVERIFY(!item->isVisible()); + + // right + QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem<QDeclarativeItem>(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // tab + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem<QDeclarativeItem>(canvas->rootObject(), "item3"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // backtab + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem<QDeclarativeItem>(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + //Set item 3 to not visible + item = findItem<QDeclarativeItem>(canvas->rootObject(), "item3"); + QVERIFY(item); + item->setVisible(false); + QVERIFY(!item->isVisible()); + + // tab + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem<QDeclarativeItem>(canvas->rootObject(), "item4"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // backtab + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem<QDeclarativeItem>(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + delete canvas; +} + void tst_QDeclarativeItem::smooth() { QDeclarativeComponent component(&engine); @@ -836,6 +919,91 @@ void tst_QDeclarativeItem::transformCrash() delete canvas; } +void tst_QDeclarativeItem::implicitSize() +{ + QDeclarativeView *canvas = new QDeclarativeView(0); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/implicitsize.qml")); + canvas->show(); + + QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(canvas->rootObject()); + QVERIFY(item); + QCOMPARE(item->width(), qreal(80)); + QCOMPARE(item->height(), qreal(60)); + + QCOMPARE(item->implicitWidth(), qreal(200)); + QCOMPARE(item->implicitHeight(), qreal(100)); + + QMetaObject::invokeMethod(item, "resetSize"); + + QCOMPARE(item->width(), qreal(200)); + QCOMPARE(item->height(), qreal(100)); + + QMetaObject::invokeMethod(item, "changeImplicit"); + + QCOMPARE(item->implicitWidth(), qreal(150)); + QCOMPARE(item->implicitHeight(), qreal(80)); + QCOMPARE(item->width(), qreal(150)); + QCOMPARE(item->height(), qreal(80)); + + delete canvas; +} + +void tst_QDeclarativeItem::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; Item { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; Item { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_QDeclarativeItem::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("implicitWidth") << "implicitWidth: 100" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Item.implicitWidth\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("implicitHeight") << "implicitHeight: 100" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Item.implicitHeight\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("onImplicitWidthChanged") << "onImplicitWidthChanged: x" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Item.onImplicitWidthChanged\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("onImplicitHeightChanged") << "onImplicitHeightChanged: x" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Item.onImplicitHeightChanged\" is not available in QtQuick 1.0.\n"; +} + +void tst_QDeclarativeItem::qtbug_16871() +{ + QDeclarativeComponent component(&engine, SRCDIR "/data/qtbug_16871.qml"); + QObject *o = component.create(); + QVERIFY(o != 0); + delete o; +} + + template<typename T> T *tst_QDeclarativeItem::findItem(QGraphicsObject *parent, const QString &objectName) { diff --git a/tests/auto/declarative/qdeclarativelanguage/data/allowedRevisionOverloads.qml b/tests/auto/declarative/qdeclarativelanguage/data/allowedRevisionOverloads.qml new file mode 100644 index 0000000..64acbd1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/allowedRevisionOverloads.qml @@ -0,0 +1,6 @@ +import Test 1.0 + +MyRevisionedLegalOverload +{ +} + diff --git a/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.errors.txt new file mode 100644 index 0000000..e9b449d --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.errors.txt @@ -0,0 +1 @@ +3:1:Type Test/MyRevisionedIllegalOverload 1.0 contains an illegal property "propA". This is an error in the type's implementation. diff --git a/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.qml b/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.qml new file mode 100644 index 0000000..612bcfe --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.qml @@ -0,0 +1,7 @@ +import Test 1.0 + +MyRevisionedIllegalOverload +{ +} + + diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.errors.txt new file mode 100644 index 0000000..29342dc --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.errors.txt @@ -0,0 +1 @@ +8:5:"MyRevisionedClass.prop2" is not available in Test 1.0. diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.qml b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.qml new file mode 100644 index 0000000..4b37ed3 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.qml @@ -0,0 +1,9 @@ +// Check that a property in a later revision (prop2) cannot be assigned +import QtQuick 1.0 +import Test 1.0 + +MyRevisionedClass +{ + prop1: 1 + prop2: 2 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.errors.txt new file mode 100644 index 0000000..57b5764 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.errors.txt @@ -0,0 +1 @@ +6:5:"MyRevisionedClass.onSignal2" is not available in Test 1.0. diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.qml b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.qml new file mode 100644 index 0000000..8da7a25 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.qml @@ -0,0 +1,7 @@ +import Test 1.0 + +MyRevisionedClass +{ + onSignal1: prop1 = 2 + onSignal2: prop1 = 3 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.errors.txt new file mode 100644 index 0000000..45364a0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.errors.txt @@ -0,0 +1 @@ +9:5:"MyRevisionedClass.propD" is not available in Test 1.1. diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.qml b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.qml new file mode 100644 index 0000000..195be21 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.qml @@ -0,0 +1,10 @@ +import Test 1.1 + +MyRevisionedClass +{ + propA: 10 + propB: 10 + propC: 10 + // propD is in rev 1 of MyRevisionedClassUnregistered, but not registered in 1.1 + propD: 10 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/revisions11.qml b/tests/auto/declarative/qdeclarativelanguage/data/revisions11.qml new file mode 100644 index 0000000..4d3d7d2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/revisions11.qml @@ -0,0 +1,10 @@ +import QtQuick 1.0 +import Test 1.1 + +MyRevisionedClass +{ + prop1: 1 + prop2: 10 + + onSignal2: prop2 = 3 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/revisionsbasesub11.qml b/tests/auto/declarative/qdeclarativelanguage/data/revisionsbasesub11.qml new file mode 100644 index 0000000..57d76b1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/revisionsbasesub11.qml @@ -0,0 +1,16 @@ +import QtQuick 1.0 +import Test 1.1 + +MyRevisionedSubclass +{ + propA: 10 + propB: 10 + propC: 10 + // propD is not registered in 1.1 + prop1: 10 + prop2: 10 + prop3: 10 + prop4: 10 + + onSignal4: prop4 = 2 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/revisionssub11.qml b/tests/auto/declarative/qdeclarativelanguage/data/revisionssub11.qml new file mode 100644 index 0000000..f107356 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/revisionssub11.qml @@ -0,0 +1,12 @@ +import QtQuick 1.0 +import Test 1.1 + +MyRevisionedSubclass +{ + prop1: 10 + prop2: 10 + prop3: 10 + prop4: 10 + + onSignal4: prop4 = 2 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/versionedbase.qml b/tests/auto/declarative/qdeclarativelanguage/data/versionedbase.qml new file mode 100644 index 0000000..8c74715 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/versionedbase.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 +import Test 1.1 + +MySubclass +{ + prop1: 10 + prop2: 10 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp b/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp index e312e31..69cba76 100644 --- a/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp @@ -52,6 +52,20 @@ void registerTypes() qmlRegisterType<MyNamespace::MySecondNamespacedType>("Test",1,0,"MySecondNamespacedType"); qmlRegisterType<MyParserStatus>("Test",1,0,"MyParserStatus"); qmlRegisterType<MyGroupedObject>(); + qmlRegisterType<MyRevisionedClass>("Test",1,0,"MyRevisionedClass"); + qmlRegisterType<MyRevisionedClass,1>("Test",1,1,"MyRevisionedClass"); + qmlRegisterType<MyRevisionedIllegalOverload>("Test",1,0,"MyRevisionedIllegalOverload"); + qmlRegisterType<MyRevisionedLegalOverload>("Test",1,0,"MyRevisionedLegalOverload"); + + // Register the uncreatable base class + qmlRegisterRevision<MyRevisionedBaseClassRegistered,1>("Test",1,1); + // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0 + qmlRegisterType<MyRevisionedSubclass>("Test",1,0,"MyRevisionedSubclass"); + // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1 + qmlRegisterType<MyRevisionedSubclass,1>("Test",1,1,"MyRevisionedSubclass"); + + // Only version 1.0, but its super class is registered in version 1.1 also + qmlRegisterType<MySubclass>("Test",1,0,"MySubclass"); qmlRegisterCustomType<MyCustomParserType>("Test", 1, 0, "MyCustomParserType", new MyCustomParserTypeParser); diff --git a/tests/auto/declarative/qdeclarativelanguage/testtypes.h b/tests/auto/declarative/qdeclarativelanguage/testtypes.h index 2cdf580..12424d0 100644 --- a/tests/auto/declarative/qdeclarativelanguage/testtypes.h +++ b/tests/auto/declarative/qdeclarativelanguage/testtypes.h @@ -601,6 +601,207 @@ private: int m_ccc; }; +class MyRevisionedBaseClassRegistered : public QObject +{ + Q_OBJECT + Q_PROPERTY(qreal propA READ propA WRITE setPropA NOTIFY propAChanged) + Q_PROPERTY(qreal propB READ propB WRITE setPropB NOTIFY propBChanged REVISION 1) + +public: + MyRevisionedBaseClassRegistered() : m_pa(1), m_pb(2) {} + + qreal propA() const { return m_pa; } + void setPropA(qreal p) { + if (p != m_pa) { + m_pa = p; + emit propAChanged(); + } + } + qreal propB() const { return m_pb; } + void setPropB(qreal p) { + if (p != m_pb) { + m_pb = p; + emit propBChanged(); + } + } + + Q_INVOKABLE void methodA() { } + Q_INVOKABLE Q_REVISION(1) void methodB() { } + +signals: + void propAChanged(); + void propBChanged(); + + void signalA(); + Q_REVISION(1) void signalB(); + +protected: + qreal m_pa; + qreal m_pb; +}; + +class MyRevisionedIllegalOverload : public MyRevisionedBaseClassRegistered +{ + Q_OBJECT + Q_PROPERTY(qreal propA READ propA WRITE setPropA REVISION 1); +}; + +class MyRevisionedLegalOverload : public MyRevisionedBaseClassRegistered +{ + Q_OBJECT + Q_PROPERTY(qreal propB READ propB WRITE setPropB REVISION 1); +}; + +class MyRevisionedBaseClassUnregistered : public MyRevisionedBaseClassRegistered +{ + Q_OBJECT + Q_PROPERTY(qreal propC READ propC WRITE setPropC NOTIFY propCChanged) + Q_PROPERTY(qreal propD READ propD WRITE setPropD NOTIFY propDChanged REVISION 1) + +public: + MyRevisionedBaseClassUnregistered() : m_pc(1), m_pd(2) {} + + qreal propC() const { return m_pc; } + void setPropC(qreal p) { + if (p != m_pc) { + m_pc = p; + emit propCChanged(); + } + } + qreal propD() const { return m_pd; } + void setPropD(qreal p) { + if (p != m_pd) { + m_pd = p; + emit propDChanged(); + } + } + + Q_INVOKABLE void methodC() { } + Q_INVOKABLE Q_REVISION(1) void methodD() { } + +signals: + void propCChanged(); + void propDChanged(); + + void signalC(); + Q_REVISION(1) void signalD(); + +protected: + qreal m_pc; + qreal m_pd; +}; + +class MyRevisionedClass : public MyRevisionedBaseClassUnregistered +{ + Q_OBJECT + Q_PROPERTY(qreal prop1 READ prop1 WRITE setProp1 NOTIFY prop1Changed) + Q_PROPERTY(qreal prop2 READ prop2 WRITE setProp2 NOTIFY prop2Changed REVISION 1) + +public: + MyRevisionedClass() : m_p1(1), m_p2(2) {} + + qreal prop1() const { return m_p1; } + void setProp1(qreal p) { + if (p != m_p1) { + m_p1 = p; + emit prop1Changed(); + } + } + qreal prop2() const { return m_p2; } + void setProp2(qreal p) { + if (p != m_p2) { + m_p2 = p; + emit prop2Changed(); + } + } + + Q_INVOKABLE void method1() { } + Q_INVOKABLE Q_REVISION(1) void method2() { } + +signals: + void prop1Changed(); + void prop2Changed(); + + void signal1(); + Q_REVISION(1) void signal2(); + +protected: + qreal m_p1; + qreal m_p2; +}; + +class MyRevisionedSubclass : public MyRevisionedClass +{ + Q_OBJECT + Q_PROPERTY(qreal prop3 READ prop3 WRITE setProp3 NOTIFY prop3Changed) + Q_PROPERTY(qreal prop4 READ prop4 WRITE setProp4 NOTIFY prop4Changed REVISION 1) + +public: + MyRevisionedSubclass() : m_p3(3), m_p4(4) {} + + qreal prop3() const { return m_p3; } + void setProp3(qreal p) { + if (p != m_p3) { + m_p3 = p; + emit prop3Changed(); + } + } + qreal prop4() const { return m_p4; } + void setProp4(qreal p) { + if (p != m_p4) { + m_p4 = p; + emit prop4Changed(); + } + } + + Q_INVOKABLE void method3() { } + Q_INVOKABLE Q_REVISION(1) void method4() { } + +signals: + void prop3Changed(); + void prop4Changed(); + + void signal3(); + Q_REVISION(1) void signal4(); + +protected: + qreal m_p3; + qreal m_p4; +}; + +class MySubclass : public MyRevisionedClass +{ + Q_OBJECT + Q_PROPERTY(qreal prop5 READ prop5 WRITE setProp5 NOTIFY prop5Changed) + +public: + MySubclass() : m_p5(5) {} + + qreal prop5() const { return m_p5; } + void setProp5(qreal p) { + if (p != m_p5) { + m_p5 = p; + emit prop5Changed(); + } + } + + Q_INVOKABLE void method5() { } + +signals: + void prop5Changed(); + +protected: + qreal m_p5; +}; + +QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered) +QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered) +QML_DECLARE_TYPE(MyRevisionedClass) +QML_DECLARE_TYPE(MyRevisionedSubclass) +QML_DECLARE_TYPE(MySubclass) + + + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index a3e8ce6..f3f41a9 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -153,6 +153,9 @@ private slots: void customOnProperty(); void variantNotify(); + void revisions(); + void revisionOverloads(); + // regression tests for crashes void crash1(); void crash2(); @@ -421,6 +424,10 @@ void tst_qdeclarativelanguage::errors_data() << "incorrectCase.errors.sensitive.txt" #endif << false; + + QTest::newRow("metaobjectRevision.1") << "metaobjectRevision.1.qml" << "metaobjectRevision.1.errors.txt" << false; + QTest::newRow("metaobjectRevision.2") << "metaobjectRevision.2.qml" << "metaobjectRevision.2.errors.txt" << false; + QTest::newRow("metaobjectRevision.3") << "metaobjectRevision.3.qml" << "metaobjectRevision.3.errors.txt" << false; } @@ -947,7 +954,7 @@ void tst_qdeclarativelanguage::aliasProperties() object->setProperty("value", QVariant(13)); QCOMPARE(object->property("valueAlias").toInt(), 13); - // Write throught alias + // Write through alias object->setProperty("valueAlias", QVariant(19)); QCOMPARE(object->property("valueAlias").toInt(), 19); QCOMPARE(object->property("value").toInt(), 19); @@ -1109,7 +1116,7 @@ void tst_qdeclarativelanguage::aliasProperties() object->setProperty("rectProperty", QVariant(QRect(33, 12, 99, 100))); QCOMPARE(object->property("valueAlias").toRect(), QRect(33, 12, 99, 100)); - // Write throught alias + // Write through alias object->setProperty("valueAlias", QVariant(QRect(3, 3, 4, 9))); QCOMPARE(object->property("valueAlias").toRect(), QRect(3, 3, 4, 9)); QCOMPARE(object->property("rectProperty").toRect(), QRect(3, 3, 4, 9)); @@ -1129,7 +1136,7 @@ void tst_qdeclarativelanguage::aliasProperties() object->setProperty("rectProperty", QVariant(QRect(33, 8, 102, 111))); QCOMPARE(object->property("aliasProperty").toInt(), 33); - // Write throught alias + // Write through alias object->setProperty("aliasProperty", QVariant(4)); QCOMPARE(object->property("aliasProperty").toInt(), 4); QCOMPARE(object->property("rectProperty").toRect(), QRect(4, 8, 102, 111)); @@ -1888,6 +1895,61 @@ void tst_qdeclarativelanguage::variantNotify() delete object; } +void tst_qdeclarativelanguage::revisions() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("revisions11.qml")); + + VERIFY_ERRORS(0); + MyRevisionedClass *object = qobject_cast<MyRevisionedClass*>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->prop2(), 10.0); + + delete object; + } + { + QDeclarativeEngine myEngine; + QDeclarativeComponent component(&myEngine, TEST_FILE("revisionssub11.qml")); + + VERIFY_ERRORS(0); + MyRevisionedSubclass *object = qobject_cast<MyRevisionedSubclass*>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->prop1(), 10.0); + QCOMPARE(object->prop2(), 10.0); + QCOMPARE(object->prop3(), 10.0); + QCOMPARE(object->prop4(), 10.0); + + delete object; + } + { + QDeclarativeComponent component(&engine, TEST_FILE("versionedbase.qml")); + VERIFY_ERRORS(0); + MySubclass *object = qobject_cast<MySubclass*>(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->prop1(), 10.0); + QCOMPARE(object->prop2(), 10.0); + + delete object; + } +} + +void tst_qdeclarativelanguage::revisionOverloads() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("allowedRevisionOverloads.qml")); + VERIFY_ERRORS(0); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("disallowedRevisionOverloads.qml")); + QEXPECT_FAIL("", "QTBUG-13849", Abort); + QVERIFY(0); + VERIFY_ERRORS("disallowedRevisionOverloads.errors.txt"); + } +} + void tst_qdeclarativelanguage::initTestCase() { registerTypes(); diff --git a/tests/auto/declarative/qdeclarativelistmodel/data/setmodelcachelist.qml b/tests/auto/declarative/qdeclarativelistmodel/data/setmodelcachelist.qml new file mode 100644 index 0000000..ffe417a --- /dev/null +++ b/tests/auto/declarative/qdeclarativelistmodel/data/setmodelcachelist.qml @@ -0,0 +1,20 @@ +import QtQuick 1.0 + +ListModel { + id: model + property bool ok : false + + Component.onCompleted: { + model.append({"attrs": []}) + model.get(0) + model.set(0, {"attrs": [{'abc': 123, 'def': 456}] } ) + ok = ( model.get(0).attrs.get(0).abc == 123 + && model.get(0).attrs.get(0).def == 456 ) + + model.set(0, {"attrs": [{'abc': 789, 'def': 101}] } ) + ok = ( model.get(0).attrs.get(0).abc == 789 + && model.get(0).attrs.get(0).def == 101 ) + + } +} + diff --git a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp index 5a88dd1..45072f3 100644 --- a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp +++ b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp @@ -59,6 +59,7 @@ #endif Q_DECLARE_METATYPE(QList<int>) +Q_DECLARE_METATYPE(QList<QVariantHash>) class tst_qdeclarativelistmodel : public QObject { @@ -100,6 +101,11 @@ private slots: void get_nested(); void get_nested_data(); void crash_model_with_multiple_roles(); + void set_model_cache(); + void property_changes(); + void property_changes_data(); + void property_changes_worker(); + void property_changes_worker_data(); }; int tst_qdeclarativelistmodel::roleFromName(const QDeclarativeListModel *model, const QString &roleName) { @@ -297,13 +303,10 @@ void tst_qdeclarativelistmodel::dynamic_data() QTest::newRow("nested-append3") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]});get(0).bars.append({'a':4});get(0).bars.get(3).a}" << 4 << ""; QTest::newRow("nested-insert") << "{append({'foo':123});insert(0,{'bars':[{'a':1},{'b':2},{'c':3}]});get(0).bars.get(0).a}" << 1 << ""; - QTest::newRow("nested-set") << "{append({'foo':123});set(0,{'foo':[{'x':123}]});get(0).foo.get(0).x}" << 123 << ""; + QTest::newRow("nested-set") << "{append({'foo':[{'x':1}]});set(0,{'foo':[{'x':123}]});get(0).foo.get(0).x}" << 123 << ""; QTest::newRow("nested-count") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]}); get(0).bars.count}" << 3 << ""; QTest::newRow("nested-clear") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]}); get(0).bars.clear(); get(0).bars.count}" << 0 << ""; - - // XXX - //QTest::newRow("nested-setprop") << "{append({'foo':123});setProperty(0,'foo',[{'x':123}]);get(0).foo.get(0).x}" << 123 << ""; } void tst_qdeclarativelistmodel::dynamic() @@ -420,6 +423,9 @@ void tst_qdeclarativelistmodel::dynamic_worker_sync() if (QByteArray(QTest::currentDataTag()).startsWith("nested")) QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML ListModel: Cannot add list-type data when modifying or after modification from a worker script"); + if (QByteArray(QTest::currentDataTag()).startsWith("nested-set")) + QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML ListModel: Cannot add list-type data when modifying or after modification from a worker script"); + QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker", Q_ARG(QVariant, operations.mid(0, operations.length()-1)))); waitForWorker(item); @@ -928,6 +934,163 @@ void tst_qdeclarativelistmodel::crash_model_with_multiple_roles() model->setProperty(0, "black", true); } +//QTBUG-15190 +void tst_qdeclarativelistmodel::set_model_cache() +{ + QDeclarativeEngine eng; + QDeclarativeComponent component(&eng, QUrl::fromLocalFile(SRCDIR "/data/setmodelcachelist.qml")); + QObject *model = component.create(); + QVERIFY2(component.errorString().isEmpty(), QTest::toString(component.errorString())); + QVERIFY(model != 0); + QVERIFY(model->property("ok").toBool()); +} + +void tst_qdeclarativelistmodel::property_changes() +{ + QFETCH(QString, script_setup); + QFETCH(QString, script_change); + QFETCH(QString, roleName); + QFETCH(int, listIndex); + QFETCH(bool, itemsChanged); + QFETCH(QString, testExpression); + + QDeclarativeEngine engine; + QDeclarativeListModel model; + QDeclarativeEngine::setContextForObject(&model, engine.rootContext()); + engine.rootContext()->setContextObject(&model); + + QDeclarativeExpression expr(engine.rootContext(), &model, script_setup); + expr.evaluate(); + QVERIFY2(!expr.hasError(), QTest::toString(expr.error().toString())); + + QString signalHandler = "on" + QString(roleName[0].toUpper()) + roleName.mid(1, roleName.length()) + "Changed:"; + QString qml = "import QtQuick 1.0\n" + "Connections {\n" + "property bool gotSignal: false\n" + "target: model.get(0)\n" + + signalHandler + " gotSignal = true\n" + "}\n"; + QDeclarativeComponent component(&engine); + component.setData(qml.toUtf8(), QUrl::fromLocalFile("")); + engine.rootContext()->setContextProperty("model", &model); + QObject *connectionsObject = component.create(); + QVERIFY2(component.errorString().isEmpty(), QTest::toString(component.errorString())); + + QSignalSpy spyItemsChanged(&model, SIGNAL(itemsChanged(int, int, QList<int>))); + + expr.setExpression(script_change); + expr.evaluate(); + QVERIFY2(!expr.hasError(), QTest::toString(expr.error())); + + // test the object returned by get() emits the correct signals + QCOMPARE(connectionsObject->property("gotSignal").toBool(), itemsChanged); + + // test itemsChanged() is emitted correctly + if (itemsChanged) { + QCOMPARE(spyItemsChanged.count(), 1); + QCOMPARE(spyItemsChanged.at(0).at(0).toInt(), listIndex); + QCOMPARE(spyItemsChanged.at(0).at(1).toInt(), 1); + } else { + QCOMPARE(spyItemsChanged.count(), 0); + } + + expr.setExpression(testExpression); + QCOMPARE(expr.evaluate().toBool(), true); + + delete connectionsObject; +} + +void tst_qdeclarativelistmodel::property_changes_data() +{ + QTest::addColumn<QString>("script_setup"); + QTest::addColumn<QString>("script_change"); + QTest::addColumn<QString>("roleName"); + QTest::addColumn<int>("listIndex"); + QTest::addColumn<bool>("itemsChanged"); + QTest::addColumn<QString>("testExpression"); + + QTest::newRow("set: plain") << "append({'a':123, 'b':456, 'c':789});" << "set(0,{'b':123});" + << "b" << 0 << true << "get(0).b == 123"; + QTest::newRow("setProperty: plain") << "append({'a':123, 'b':456, 'c':789});" << "setProperty(0, 'b', 123);" + << "b" << 0 << true << "get(0).b == 123"; + + QTest::newRow("set: plain, no changes") << "append({'a':123, 'b':456, 'c':789});" << "set(0,{'b':456});" + << "b" << 0 << false << "get(0).b == 456"; + QTest::newRow("setProperty: plain, no changes") << "append({'a':123, 'b':456, 'c':789});" << "setProperty(0, 'b', 456);" + << "b" << 0 << false << "get(0).b == 456"; + + // Following tests only call set() since setProperty() only allows plain + // values, not lists, as the argument. + // Note that when a list is changed, itemsChanged() is currently always + // emitted regardless of whether it actually changed or not. + + QTest::newRow("nested-set: list, new size") << "append({'a':123, 'b':[{'a':1},{'a':2},{'a':3}], 'c':789});" << "set(0,{'b':[{'a':1},{'a':2}]});" + << "b" << 0 << true << "get(0).b.get(0).a == 1 && get(0).b.get(1).a == 2"; + + QTest::newRow("nested-set: list, empty -> non-empty") << "append({'a':123, 'b':[], 'c':789});" << "set(0,{'b':[{'a':1},{'a':2},{'a':3}]});" + << "b" << 0 << true << "get(0).b.get(0).a == 1 && get(0).b.get(1).a == 2 && get(0).b.get(2).a == 3"; + + QTest::newRow("nested-set: list, non-empty -> empty") << "append({'a':123, 'b':[{'a':1},{'a':2},{'a':3}], 'c':789});" << "set(0,{'b':[]});" + << "b" << 0 << true << "get(0).b.count == 0"; + + QTest::newRow("nested-set: list, same size, different values") << "append({'a':123, 'b':[{'a':1},{'a':2},{'a':3}], 'c':789});" << "set(0,{'b':[{'a':1},{'a':222},{'a':3}]});" + << "b" << 0 << true << "get(0).b.get(0).a == 1 && get(0).b.get(1).a == 222 && get(0).b.get(2).a == 3"; + + QTest::newRow("nested-set: list, no changes") << "append({'a':123, 'b':[{'a':1},{'a':2},{'a':3}], 'c':789});" << "set(0,{'b':[{'a':1},{'a':2},{'a':3}]});" + << "b" << 0 << true << "get(0).b.get(0).a == 1 && get(0).b.get(1).a == 2 && get(0).b.get(2).a == 3"; + + QTest::newRow("nested-set: list, no changes, empty") << "append({'a':123, 'b':[], 'c':789});" << "set(0,{'b':[]});" + << "b" << 0 << true << "get(0).b.count == 0"; +} + + +void tst_qdeclarativelistmodel::property_changes_worker() +{ + // nested models are not supported when WorkerScript is involved + if (QByteArray(QTest::currentDataTag()).startsWith("nested-")) + return; + + QFETCH(QString, script_setup); + QFETCH(QString, script_change); + QFETCH(QString, roleName); + QFETCH(int, listIndex); + QFETCH(bool, itemsChanged); + + QDeclarativeListModel model; + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/model.qml")); + QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8()); + QDeclarativeItem *item = createWorkerTest(&engine, &component, &model); + QVERIFY(item != 0); + + QDeclarativeExpression expr(engine.rootContext(), &model, script_setup); + expr.evaluate(); + QVERIFY2(!expr.hasError(), QTest::toString(expr.error().toString())); + + QSignalSpy spyItemsChanged(&model, SIGNAL(itemsChanged(int, int, QList<int>))); + + QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker", + Q_ARG(QVariant, QStringList(script_change)))); + waitForWorker(item); + + // test itemsChanged() is emitted correctly + if (itemsChanged) { + QCOMPARE(spyItemsChanged.count(), 1); + QCOMPARE(spyItemsChanged.at(0).at(0).toInt(), listIndex); + QCOMPARE(spyItemsChanged.at(0).at(1).toInt(), 1); + } else { + QCOMPARE(spyItemsChanged.count(), 0); + } + + delete item; + qApp->processEvents(); +} + +void tst_qdeclarativelistmodel::property_changes_worker_data() +{ + property_changes_data(); +} + QTEST_MAIN(tst_qdeclarativelistmodel) #include "tst_qdeclarativelistmodel.moc" diff --git a/tests/auto/declarative/qdeclarativelistview/data/attachedSignals.qml b/tests/auto/declarative/qdeclarativelistview/data/attachedSignals.qml new file mode 100644 index 0000000..5ca1a45 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelistview/data/attachedSignals.qml @@ -0,0 +1,24 @@ +import QtQuick 1.0 + +ListView { + id: view + width: 240; height: 320 + + property variant addedDelegates: [] + property int removedDelegateCount + + model: testModel + + delegate: Rectangle { + width: 200; height: delegateHeight + border.width: 1 + ListView.onAdd: { + var obj = ListView.view.addedDelegates + obj.push(model.name) + ListView.view.addedDelegates = obj + } + ListView.onRemove: { + view.removedDelegateCount += 1 + } + } +} diff --git a/tests/auto/declarative/qdeclarativelistview/data/footer.qml b/tests/auto/declarative/qdeclarativelistview/data/footer.qml index 4cbd33b..33e04f1 100644 --- a/tests/auto/declarative/qdeclarativelistview/data/footer.qml +++ b/tests/auto/declarative/qdeclarativelistview/data/footer.qml @@ -1,6 +1,9 @@ import QtQuick 1.0 Rectangle { + function changeFooter() { + list.footer = footer2 + } width: 240 height: 320 color: "#ffffff" @@ -27,4 +30,9 @@ Rectangle { delegate: myDelegate footer: Text { objectName: "footer"; text: "Footer"; height: 30 } } + + Component { + id: footer2 + Text { objectName: "footer2"; text: "Footer 2"; height: 20 } + } } diff --git a/tests/auto/declarative/qdeclarativelistview/data/header.qml b/tests/auto/declarative/qdeclarativelistview/data/header.qml index 6da996e..38cdd6e 100644 --- a/tests/auto/declarative/qdeclarativelistview/data/header.qml +++ b/tests/auto/declarative/qdeclarativelistview/data/header.qml @@ -1,6 +1,9 @@ import QtQuick 1.0 Rectangle { + function changeHeader() { + list.header = header2 + } width: 240 height: 320 color: "#ffffff" @@ -26,6 +29,10 @@ Rectangle { snapMode: ListView.SnapToItem model: testModel delegate: myDelegate - header: Text { objectName: "header"; text: "Header"; height: 10 } + header: Text { objectName: "header"; text: "Header"; height: 20 } + } + Component { + id: header2 + Text { objectName: "header2"; text: "Header 2"; height: 10 } } } diff --git a/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml b/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml new file mode 100644 index 0000000..35a398b --- /dev/null +++ b/tests/auto/declarative/qdeclarativelistview/data/listview-sections_delegate.qml @@ -0,0 +1,63 @@ +import QtQuick 1.0 + +Rectangle { + width: 240 + height: 320 + color: "#ffffff" + resources: [ + Component { + id: myDelegate + Item { + id: wrapper + objectName: "wrapper" + height: 20; + width: 240 + Rectangle { + height: 20 + width: parent.width + color: wrapper.ListView.isCurrentItem ? "lightsteelblue" : "white" + Text { + text: index + } + Text { + x: 30 + id: textName + objectName: "textName" + text: name + } + Text { + x: 100 + id: textNumber + objectName: "textNumber" + text: number + } + Text { + objectName: "nextSection" + x: 150 + text: wrapper.ListView.nextSection + } + Text { + x: 200 + text: wrapper.y + } + } + } + } + ] + ListView { + id: list + objectName: "list" + width: 240 + height: 320 + model: testModel + delegate: myDelegate + section.property: "number" + section.delegate: Rectangle { + objectName: "sect_" + section + color: "#99bb99" + height: 20 + width: list.width + Text { text: section } + } + } +} diff --git a/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml b/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml index 534540f..3cd6f42 100644 --- a/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml +++ b/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml @@ -1,10 +1,13 @@ import QtQuick 1.0 Rectangle { + id: root width: 240 height: 320 color: "#ffffff" + property bool showHeader: false + property bool showFooter: false property real hr: list.visibleArea.heightRatio function heightRatio() { return list.visibleArea.heightRatio @@ -105,6 +108,10 @@ Rectangle { Component { id: invalidHl SmoothedAnimation {} + }, + Component { + id: headerFooter + Rectangle { height: 30; width: 240; color: "blue" } } ] ListView { @@ -119,5 +126,7 @@ Rectangle { highlightMoveSpeed: 1000 highlightResizeSpeed: 1000 cacheBuffer: testObject.cacheBuffer + header: root.showHeader ? headerFooter : null + footer: root.showFooter ? headerFooter : null } } diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp index 9b6f04c..f358625 100644 --- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp +++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp @@ -90,6 +90,7 @@ private slots: void enforceRange(); void spacing(); void sections(); + void sectionsDelegate(); void cacheBuffer(); void positionViewAtIndex(); void resetModel(); @@ -108,6 +109,12 @@ private slots: void QTBUG_16037(); void indexAt(); void incrementalModel(); + void onAdd(); + void onAdd_data(); + void onRemove(); + void onRemove_data(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: template <class T> void items(); @@ -294,6 +301,13 @@ public: emit endInsertRows(); } + void addItems(const QList<QPair<QString, QString> > &items) { + emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1); + for (int i=0; i<items.count(); i++) + list.append(QPair<QString,QString>(items[i].first, items[i].second)); + emit endInsertRows(); + } + void insertItem(int index, const QString &name, const QString &number) { emit beginInsertRows(QModelIndex(), index, index); list.insert(index, QPair<QString,QString>(name, number)); @@ -1015,6 +1029,58 @@ void tst_QDeclarativeListView::sections() delete canvas; } +void tst_QDeclarativeListView::sectionsDelegate() +{ + QDeclarativeView *canvas = createView(); + + TestModel model; + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), QString::number(i/5)); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listview-sections_delegate.qml")); + qApp->processEvents(); + + QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + + QDeclarativeItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + // Confirm items positioned correctly + int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + QTRY_VERIFY(item); + QTRY_COMPARE(item->y(), qreal(i*20 + ((i+5)/5) * 20)); + QDeclarativeText *next = findItem<QDeclarativeText>(item, "nextSection"); + QCOMPARE(next->text().toInt(), (i+1)/5); + } + + for (int i = 0; i < 3; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "sect_" + QString::number(i)); + QVERIFY(item); + QTRY_COMPARE(item->y(), qreal(i*20*6)); + } + + model.modifyItem(0, "One", "aaa"); + model.modifyItem(1, "Two", "aaa"); + model.modifyItem(2, "Three", "aaa"); + model.modifyItem(3, "Four", "aaa"); + model.modifyItem(4, "Five", "aaa"); + + for (int i = 0; i < 3; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, + "sect_" + (i == 0 ? QString("aaa") : QString::number(i))); + QVERIFY(item); + QTRY_COMPARE(item->y(), qreal(i*20*6)); + } + + delete canvas; +} + void tst_QDeclarativeListView::currentIndex() { TestModel model; @@ -1383,6 +1449,24 @@ void tst_QDeclarativeListView::positionViewAtIndex() listview->positionViewAtIndex(20, QDeclarativeListView::Contain); QTRY_COMPARE(listview->contentY(), 100.); + // positionAtBeginnging + listview->positionViewAtBeginning(); + QTRY_COMPARE(listview->contentY(), 0.); + + listview->setContentY(80); + canvas->rootObject()->setProperty("showHeader", true); + listview->positionViewAtBeginning(); + QTRY_COMPARE(listview->contentY(), -30.); + + // positionAtEnd + listview->positionViewAtEnd(); + QTRY_COMPARE(listview->contentY(), 480.); // 40*20 - 320 + + listview->setContentY(80); + canvas->rootObject()->setProperty("showFooter", true); + listview->positionViewAtEnd(); + QTRY_COMPARE(listview->contentY(), 510.); + delete canvas; } @@ -1592,7 +1676,7 @@ void tst_QDeclarativeListView::QTBUG_9791() // Confirm items positioned correctly int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); - QVERIFY(itemCount == 3); + QCOMPARE(itemCount, 3); for (int i = 0; i < itemCount; ++i) { QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); @@ -1716,12 +1800,27 @@ void tst_QDeclarativeListView::header() QDeclarativeText *header = findItem<QDeclarativeText>(contentItem, "header"); QVERIFY(header); QCOMPARE(header->y(), 0.0); + QCOMPARE(header->height(), 20.0); QCOMPARE(listview->contentY(), 0.0); model.clear(); QTRY_COMPARE(header->y(), 0.0); + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader"); + + header = findItem<QDeclarativeText>(contentItem, "header"); + QVERIFY(!header); + header = findItem<QDeclarativeText>(contentItem, "header2"); + QVERIFY(header); + + QCOMPARE(header->y(), 10.0); + QCOMPARE(header->height(), 10.0); + QCOMPARE(listview->contentY(), 10.0); + delete canvas; } { @@ -1776,6 +1875,7 @@ void tst_QDeclarativeListView::footer() QDeclarativeText *footer = findItem<QDeclarativeText>(contentItem, "footer"); QVERIFY(footer); QCOMPARE(footer->y(), 60.0); + QCOMPARE(footer->height(), 30.0); model.removeItem(1); QTRY_COMPARE(footer->y(), 40.0); @@ -1783,6 +1883,20 @@ void tst_QDeclarativeListView::footer() model.clear(); QTRY_COMPARE(footer->y(), 0.0); + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter"); + + footer = findItem<QDeclarativeText>(contentItem, "footer"); + QVERIFY(!footer); + footer = findItem<QDeclarativeText>(contentItem, "footer2"); + QVERIFY(footer); + + QCOMPARE(footer->y(), 600.0); + QCOMPARE(footer->height(), 20.0); + QCOMPARE(listview->contentY(), 0.0); + delete canvas; } @@ -2039,6 +2153,152 @@ void tst_QDeclarativeListView::incrementalModel() delete canvas; } +void tst_QDeclarativeListView::onAdd() +{ + QFETCH(int, initialItemCount); + QFETCH(int, itemsToAdd); + + const int delegateHeight = 10; + TestModel2 model; + + // these initial items should not trigger ListView.onAdd + for (int i=0; i<initialItemCount; i++) + model.addItem("dummy value", "dummy value"); + + QDeclarativeView *canvas = createView(); + canvas->setFixedSize(200, delegateHeight * (initialItemCount + itemsToAdd)); + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("delegateHeight", delegateHeight); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml")); + + QObject *object = canvas->rootObject(); + object->setProperty("width", canvas->width()); + object->setProperty("height", canvas->height()); + qApp->processEvents(); + + QList<QPair<QString, QString> > items; + for (int i=0; i<itemsToAdd; i++) + items << qMakePair(QString("value %1").arg(i), QString::number(i)); + model.addItems(items); + + qApp->processEvents(); + + QVariantList result = object->property("addedDelegates").toList(); + QCOMPARE(result.count(), items.count()); + for (int i=0; i<items.count(); i++) + QCOMPARE(result[i].toString(), items[i].first); + + delete canvas; +} + +void tst_QDeclarativeListView::onAdd_data() +{ + QTest::addColumn<int>("initialItemCount"); + QTest::addColumn<int>("itemsToAdd"); + + QTest::newRow("0, add 1") << 0 << 1; + QTest::newRow("0, add 2") << 0 << 2; + QTest::newRow("0, add 10") << 0 << 10; + + QTest::newRow("1, add 1") << 1 << 1; + QTest::newRow("1, add 2") << 1 << 2; + QTest::newRow("1, add 10") << 1 << 10; + + QTest::newRow("5, add 1") << 5 << 1; + QTest::newRow("5, add 2") << 5 << 2; + QTest::newRow("5, add 10") << 5 << 10; +} + +void tst_QDeclarativeListView::onRemove() +{ + QFETCH(int, initialItemCount); + QFETCH(int, indexToRemove); + QFETCH(int, removeCount); + + const int delegateHeight = 10; + TestModel2 model; + for (int i=0; i<initialItemCount; i++) + model.addItem(QString("value %1").arg(i), "dummy value"); + + QDeclarativeView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("delegateHeight", delegateHeight); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml")); + QObject *object = canvas->rootObject(); + + qApp->processEvents(); + + model.removeItems(indexToRemove, removeCount); + qApp->processEvents(); + QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount)); + + delete canvas; +} + +void tst_QDeclarativeListView::onRemove_data() +{ + QTest::addColumn<int>("initialItemCount"); + QTest::addColumn<int>("indexToRemove"); + QTest::addColumn<int>("removeCount"); + + QTest::newRow("remove first") << 1 << 0 << 1; + QTest::newRow("two items, remove first") << 2 << 0 << 1; + QTest::newRow("two items, remove last") << 2 << 1 << 1; + QTest::newRow("two items, remove all") << 2 << 0 << 2; + + QTest::newRow("four items, remove first") << 4 << 0 << 1; + QTest::newRow("four items, remove 0-2") << 4 << 0 << 2; + QTest::newRow("four items, remove 1-3") << 4 << 1 << 2; + QTest::newRow("four items, remove 2-4") << 4 << 2 << 2; + QTest::newRow("four items, remove last") << 4 << 3 << 1; + QTest::newRow("four items, remove all") << 4 << 0 << 4; + + QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8; + QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5; + QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6; +} + +void tst_QDeclarativeListView::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; ListView { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; ListView { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_QDeclarativeListView::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("positionViewAtBeginning") << "Component.onCompleted: positionViewAtBeginning()" + << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtBeginning" + << ""; + + QTest::newRow("positionViewAtEnd") << "Component.onCompleted: positionViewAtEnd()" + << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtEnd" + << ""; +} + void tst_QDeclarativeListView::qListModelInterface_items() { items<TestModel>(); diff --git a/tests/auto/declarative/qdeclarativeloader/data/QTBUG_16928.qml b/tests/auto/declarative/qdeclarativeloader/data/QTBUG_16928.qml new file mode 100644 index 0000000..9949e34 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeloader/data/QTBUG_16928.qml @@ -0,0 +1,23 @@ +import QtQuick 1.1 + +Rectangle { + color: "green" + width: loader.implicitWidth+50 + height: loader.implicitHeight+50 + + Loader { + id: loader + sourceComponent: Item { + anchors.centerIn: parent + + implicitWidth: 200 + implicitHeight: 200 + Rectangle { + color: "red" + anchors.fill: parent + } + } + anchors.fill: parent + anchors.margins: 15 + } +} diff --git a/tests/auto/declarative/qdeclarativeloader/data/QTBUG_17114.qml b/tests/auto/declarative/qdeclarativeloader/data/QTBUG_17114.qml new file mode 100644 index 0000000..8a49733 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeloader/data/QTBUG_17114.qml @@ -0,0 +1,18 @@ +import QtQuick 1.1 + +Rectangle { + property real loaderWidth: loader.width + property real loaderHeight: loader.height + width: 200 + height: 200 + + Loader { + id: loader + sourceComponent: Item { + property real iwidth: 32 + property real iheight: 32 + width: iwidth + height: iheight + } + } +} diff --git a/tests/auto/declarative/qdeclarativeloader/data/implicitSize.qml b/tests/auto/declarative/qdeclarativeloader/data/implicitSize.qml new file mode 100644 index 0000000..53aad97 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeloader/data/implicitSize.qml @@ -0,0 +1,28 @@ +import QtQuick 1.1 + +Rectangle { + property real implWidth: 0 + property real implHeight: 0 + color: "green" + width: loader.implicitWidth+50 + height: loader.implicitHeight+50 + + Loader { + id: loader + sourceComponent: Item { + anchors.centerIn: parent + + implicitWidth: 100 + implicitHeight: 100 + Rectangle { + color: "red" + anchors.fill: parent + } + } + + anchors.fill: parent + anchors.margins: 50 + onImplicitWidthChanged: implWidth = implicitWidth + onImplicitHeightChanged: implHeight = loader.implicitHeight + } +} diff --git a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp index bfa81ed..f5218c7 100644 --- a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp +++ b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp @@ -69,9 +69,8 @@ public: tst_QDeclarativeLoader(); private slots: - void url(); - void invalidUrl(); - void component(); + void sourceOrComponent(); + void sourceOrComponent_data(); void clear(); void urlToComponent(); void componentToUrl(); @@ -90,6 +89,9 @@ private slots: void nonItem(); void vmeErrors(); void creationContext(); + void QTBUG_16928(); + void implicitSize(); + void QTBUG_17114(); private: QDeclarativeEngine engine; @@ -100,56 +102,71 @@ tst_QDeclarativeLoader::tst_QDeclarativeLoader() { } -void tst_QDeclarativeLoader::url() +void tst_QDeclarativeLoader::sourceOrComponent() { + QFETCH(QString, sourceDefinition); + QFETCH(QUrl, sourceUrl); + QFETCH(QString, errorString); + + bool error = !errorString.isEmpty(); + if (error) + QTest::ignoreMessage(QtWarningMsg, errorString.toUtf8().constData()); + QDeclarativeComponent component(&engine); - component.setData(QByteArray("import QtQuick 1.0\nLoader { property int did_load: 0; onLoaded: did_load=123; source: \"Rect120x60.qml\" }"), TEST_FILE("")); + component.setData(QByteArray( + "import QtQuick 1.0\n" + "Loader {\n" + " property int onItemChangedCount: 0\n" + " property int onSourceChangedCount: 0\n" + " property int onStatusChangedCount: 0\n" + " property int onProgressChangedCount: 0\n" + " property int onLoadedCount: 0\n") + + sourceDefinition.toUtf8() + + QByteArray( + " onItemChanged: onItemChangedCount += 1\n" + " onSourceChanged: onSourceChangedCount += 1\n" + " onStatusChanged: onStatusChangedCount += 1\n" + " onProgressChanged: onProgressChangedCount += 1\n" + " onLoaded: onLoadedCount += 1\n" + "}") + , TEST_FILE("")); + QDeclarativeLoader *loader = qobject_cast<QDeclarativeLoader*>(component.create()); QVERIFY(loader != 0); - QVERIFY(loader->item()); - QVERIFY(loader->source() == QUrl::fromLocalFile(SRCDIR "/data/Rect120x60.qml")); + QCOMPARE(loader->item() == 0, error); + QCOMPARE(loader->source(), sourceUrl); QCOMPARE(loader->progress(), 1.0); - QCOMPARE(loader->status(), QDeclarativeLoader::Ready); - QCOMPARE(loader->property("did_load").toInt(), 123); - QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1); - delete loader; -} + QCOMPARE(loader->status(), error ? QDeclarativeLoader::Error : QDeclarativeLoader::Ready); + QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), error ? 0: 1); -void tst_QDeclarativeLoader::component() -{ - QDeclarativeComponent component(&engine, TEST_FILE("/SetSourceComponent.qml")); - QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(component.create()); - QVERIFY(item); + if (!error) { + QDeclarativeComponent *c = qobject_cast<QDeclarativeComponent*>(loader->QGraphicsObject::children().at(0)); + QVERIFY(c); + QCOMPARE(loader->sourceComponent(), c); + } - QDeclarativeLoader *loader = qobject_cast<QDeclarativeLoader*>(item->QGraphicsObject::children().at(1)); - QVERIFY(loader); - QVERIFY(loader->item()); - QCOMPARE(loader->progress(), 1.0); - QCOMPARE(loader->status(), QDeclarativeLoader::Ready); - QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1); + QCOMPARE(loader->property("onSourceChangedCount").toInt(), 1); + QCOMPARE(loader->property("onStatusChangedCount").toInt(), 1); + QCOMPARE(loader->property("onProgressChangedCount").toInt(), 1); - QDeclarativeComponent *c = qobject_cast<QDeclarativeComponent*>(item->QGraphicsObject::children().at(0)); - QVERIFY(c); - QCOMPARE(loader->sourceComponent(), c); + QCOMPARE(loader->property("onItemChangedCount").toInt(), error ? 0 : 1); + QCOMPARE(loader->property("onLoadedCount").toInt(), error ? 0 : 1); - delete item; + delete loader; } -void tst_QDeclarativeLoader::invalidUrl() +void tst_QDeclarativeLoader::sourceOrComponent_data() { - QTest::ignoreMessage(QtWarningMsg, QString(QUrl::fromLocalFile(SRCDIR "/data/IDontExist.qml").toString() + ": File not found").toUtf8().constData()); + QTest::addColumn<QString>("sourceDefinition"); + QTest::addColumn<QUrl>("sourceUrl"); + QTest::addColumn<QString>("errorString"); - QDeclarativeComponent component(&engine); - component.setData(QByteArray("import QtQuick 1.0\nLoader { source: \"IDontExist.qml\" }"), TEST_FILE("")); - QDeclarativeLoader *loader = qobject_cast<QDeclarativeLoader*>(component.create()); - QVERIFY(loader != 0); - QVERIFY(loader->item() == 0); - QCOMPARE(loader->progress(), 1.0); - QCOMPARE(loader->status(), QDeclarativeLoader::Error); - QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 0); + QTest::newRow("source") << "source: 'Rect120x60.qml'\n" << QUrl::fromLocalFile(SRCDIR "/data/Rect120x60.qml") << ""; + QTest::newRow("sourceComponent") << "Component { id: comp; Rectangle { width: 100; height: 50 } }\n sourceComponent: comp\n" << QUrl() << ""; - delete loader; + QTest::newRow("invalid source") << "source: 'IDontExist.qml'\n" << QUrl::fromLocalFile(SRCDIR "/data/IDontExist.qml") + << QString(QUrl::fromLocalFile(SRCDIR "/data/IDontExist.qml").toString() + ": File not found"); } void tst_QDeclarativeLoader::clear() @@ -446,7 +463,7 @@ void tst_QDeclarativeLoader::networkRequestUrl() server.serveDirectory(SRCDIR "/data"); QDeclarativeComponent component(&engine); - component.setData(QByteArray("import QtQuick 1.0\nLoader { property int did_load : 0; source: \"http://127.0.0.1:14450/Rect120x60.qml\"; onLoaded: did_load=123 }"), QUrl::fromLocalFile(SRCDIR "/dummy.qml")); + component.setData(QByteArray("import QtQuick 1.0\nLoader { property int signalCount : 0; source: \"http://127.0.0.1:14450/Rect120x60.qml\"; onLoaded: signalCount += 1 }"), QUrl::fromLocalFile(SRCDIR "/dummy.qml")); if (component.isError()) qDebug() << component.errors(); QDeclarativeLoader *loader = qobject_cast<QDeclarativeLoader*>(component.create()); @@ -456,7 +473,7 @@ void tst_QDeclarativeLoader::networkRequestUrl() QVERIFY(loader->item()); QCOMPARE(loader->progress(), 1.0); - QCOMPARE(loader->property("did_load").toInt(), 123); + QCOMPARE(loader->property("signalCount").toInt(), 1); QCOMPARE(static_cast<QGraphicsItem*>(loader)->children().count(), 1); delete loader; @@ -576,6 +593,45 @@ void tst_QDeclarativeLoader::creationContext() delete o; } +void tst_QDeclarativeLoader::QTBUG_16928() +{ + QDeclarativeComponent component(&engine, TEST_FILE("QTBUG_16928.qml")); + QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(component.create()); + QVERIFY(item); + + QCOMPARE(item->width(), 250.); + QCOMPARE(item->height(), 250.); + + delete item; +} + +void tst_QDeclarativeLoader::implicitSize() +{ + QDeclarativeComponent component(&engine, TEST_FILE("implicitSize.qml")); + QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(component.create()); + QVERIFY(item); + + QCOMPARE(item->width(), 150.); + QCOMPARE(item->height(), 150.); + + QCOMPARE(item->property("implHeight").toReal(), 100.); + QCOMPARE(item->property("implWidth").toReal(), 100.); + + delete item; +} + +void tst_QDeclarativeLoader::QTBUG_17114() +{ + QDeclarativeComponent component(&engine, TEST_FILE("QTBUG_17114.qml")); + QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(component.create()); + QVERIFY(item); + + QCOMPARE(item->property("loaderWidth").toReal(), 32.); + QCOMPARE(item->property("loaderHeight").toReal(), 32.); + + delete item; +} + QTEST_MAIN(tst_QDeclarativeLoader) #include "tst_qdeclarativeloader.moc" diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.2.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.2.qml new file mode 100644 index 0000000..70b2bfd --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.2.qml @@ -0,0 +1,21 @@ +import com.nokia.AutoTestQmlMixedPluginType 1.5 +import QtQuick 1.0 + +Item { + property bool test: false + property bool test2: false + + Bar { + id: bar + } + + Foo { + id: foo + } + + Component.onCompleted: { + test = (bar.value == 16); + test2 = (foo.value == 89); + } +} + diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.qml new file mode 100644 index 0000000..da6ff46 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/importsMixedQmlCppPlugin.qml @@ -0,0 +1,13 @@ +import com.nokia.AutoTestQmlMixedPluginType 1.0 +import QtQuick 1.0 + +Item { + property bool test: false + Bar { + id: bar + } + + Component.onCompleted: { + test = (bar.value == 16); + } +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/pluginWithQmlFile.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/pluginWithQmlFile.qml new file mode 100644 index 0000000..a9e28e5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/pluginWithQmlFile.qml @@ -0,0 +1,3 @@ +import com.nokia.AutoTestPluginWithQmlFile 1.0 + +MyQmlFile {} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.errors.txt b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.errors.txt new file mode 100644 index 0000000..a40c1c8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.errors.txt @@ -0,0 +1 @@ +1:1:module "com.nokia.AutoTestQmlVersionPluginType" version 1.9 is not installed diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.qml new file mode 100644 index 0000000..59fd084 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.2.qml @@ -0,0 +1,5 @@ +import com.nokia.AutoTestQmlVersionPluginType 1.9 +import QtQuick 1.0 + +QtObject { +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.errors.txt b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.errors.txt new file mode 100644 index 0000000..2634223 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.errors.txt @@ -0,0 +1 @@ +1:1:module "com.nokia.AutoTestQmlVersionPluginType" version 1.1 is not installed diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.qml new file mode 100644 index 0000000..2065c07 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/versionNotInstalled.qml @@ -0,0 +1,6 @@ +import com.nokia.AutoTestQmlVersionPluginType 1.1 +import QtQuick 1.0 + +QtObject { +} + diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/works2.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/works2.qml new file mode 100644 index 0000000..cc322bf --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/works2.qml @@ -0,0 +1,3 @@ +import com.nokia.AutoTestQmlPluginType 2.0 + +MyPluginType { valueOnlyIn2: 123 } diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/data/works21.qml b/tests/auto/declarative/qdeclarativemoduleplugin/data/works21.qml new file mode 100644 index 0000000..c08160a --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/data/works21.qml @@ -0,0 +1,3 @@ +import com.nokia.AutoTestQmlPluginType 2.1 + +MyPluginType { valueOnlyIn2: 123 } diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/MyQmlFile.qml b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/MyQmlFile.qml new file mode 100644 index 0000000..18dcd26 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/MyQmlFile.qml @@ -0,0 +1,3 @@ +import QtQuick 1.0 + +Item {}
\ No newline at end of file diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/qmldir new file mode 100644 index 0000000..858ba14 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestPluginWithQmlFile/qmldir @@ -0,0 +1,3 @@ +MyQmlFile 1.0 MyQmlFile.qml +plugin pluginWithQmlFile + diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/Foo.qml b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/Foo.qml new file mode 100644 index 0000000..ce51cbd --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/Foo.qml @@ -0,0 +1,5 @@ +import QtQuick 1.0 + +Item { + property int value: 89 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/qmldir new file mode 100644 index 0000000..065dc3b --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlMixedPluginType/qmldir @@ -0,0 +1,2 @@ +plugin pluginMixed +Foo 1.5 Foo.qml diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2.1/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2.1/qmldir new file mode 100644 index 0000000..0a8b5d4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2.1/qmldir @@ -0,0 +1 @@ +plugin plugin diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2/qmldir new file mode 100644 index 0000000..0a8b5d4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlPluginType.2/qmldir @@ -0,0 +1 @@ +plugin plugin diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlVersionPluginType/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlVersionPluginType/qmldir new file mode 100644 index 0000000..640967f --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/AutoTestQmlVersionPluginType/qmldir @@ -0,0 +1 @@ +plugin pluginVersion diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentA.qml b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentA.qml new file mode 100644 index 0000000..49613aa --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentA.qml @@ -0,0 +1,3 @@ +import QtQuick 1.0 + +Item {} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentB.qml b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentB.qml new file mode 100644 index 0000000..f19a336 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/ComponentB.qml @@ -0,0 +1,4 @@ +import QtQuick 1.0 + +Item {} + diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/qmldir b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/qmldir new file mode 100644 index 0000000..167bb10 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/imports/com/nokia/PureQmlModule/qmldir @@ -0,0 +1,3 @@ +ComponentA 1.0 ComponentA.qml +ComponentB 1.0 ComponentB.qml + diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.2.1.pro b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.2.1.pro new file mode 100644 index 0000000..661675a --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.2.1.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core declarative +DESTDIR = ../imports/com/nokia/AutoTestQmlPluginType.2.1 + +symbian: { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.cpp new file mode 100644 index 0000000..1ae2bd4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2.1/plugin.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 <QStringList> +#include <QtDeclarative/qdeclarativeextensionplugin.h> +#include <QtDeclarative/qdeclarative.h> +#include <QDebug> + +class MyPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue) + Q_PROPERTY(int valueOnlyIn2 READ value WRITE setValue) + +public: + MyPluginType(QObject *parent=0) : QObject(parent) + { + qWarning("import2.1 worked"); + } + + int value() const { return v; } + void setValue(int i) { v = i; } + +private: + int v; +}; + + +class MyPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + MyPlugin() + { + qWarning("plugin2.1 created"); + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlPluginType"); + qmlRegisterType<MyPluginType>(uri, 2, 1, "MyPluginType"); + } +}; + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(plugin, MyPlugin); diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.2.pro b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.2.pro new file mode 100644 index 0000000..d254642 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.2.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core declarative +DESTDIR = ../imports/com/nokia/AutoTestQmlPluginType.2 + +symbian: { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.cpp new file mode 100644 index 0000000..6bd8542 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/plugin.2/plugin.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 <QStringList> +#include <QtDeclarative/qdeclarativeextensionplugin.h> +#include <QtDeclarative/qdeclarative.h> +#include <QDebug> + +class MyPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue) + Q_PROPERTY(int valueOnlyIn2 READ value WRITE setValue) + +public: + MyPluginType(QObject *parent=0) : QObject(parent) + { + qWarning("import2 worked"); + } + + int value() const { return v; } + void setValue(int i) { v = i; } + +private: + int v; +}; + + +class MyPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + MyPlugin() + { + qWarning("plugin2 created"); + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlPluginType"); + qmlRegisterType<MyPluginType>(uri, 2, 0, "MyPluginType"); + } +}; + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(plugin, MyPlugin); diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/plugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/plugin.cpp new file mode 100644 index 0000000..c7796e2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/plugin.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 <QStringList> +#include <QtDeclarative/qdeclarativeextensionplugin.h> +#include <QtDeclarative/qdeclarative.h> +#include <QDebug> + +class BarPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value); + +public: + int value() const { return 16; } +}; + + +class MyMixedPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + MyMixedPlugin() + { + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlMixedPluginType"); + qmlRegisterType<BarPluginType>(uri, 1, 0, "Bar"); + } +}; + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(plugin, MyMixedPlugin); diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/pluginMixed.pro b/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/pluginMixed.pro new file mode 100644 index 0000000..9766003 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginMixed/pluginMixed.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core declarative +DESTDIR = ../imports/com/nokia/AutoTestQmlMixedPluginType + +symbian: { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/plugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/plugin.cpp new file mode 100644 index 0000000..27a6341 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/plugin.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 <QStringList> +#include <QtDeclarative/qdeclarativeextensionplugin.h> +#include <QtDeclarative/qdeclarative.h> +#include <QDebug> + +class FloorPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value); + +public: + int value() const { return 16; } +}; + + +class MyMixedPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + MyMixedPlugin() + { + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlVersionPluginType"); + qmlRegisterType<FloorPluginType>(uri, 1, 4, "Floor"); + } +}; + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(plugin, MyMixedPlugin); diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/pluginVersion.pro b/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/pluginVersion.pro new file mode 100644 index 0000000..70a38b9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginVersion/pluginVersion.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core declarative +DESTDIR = ../imports/com/nokia/AutoTestQmlVersionPluginType + +symbian: { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/plugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/plugin.cpp new file mode 100644 index 0000000..20e2d80 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/plugin.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 <QStringList> +#include <QtDeclarative/qdeclarativeextensionplugin.h> +#include <QtDeclarative/qdeclarative.h> +#include <QDebug> + +class MyPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT +public: + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestPluginWithQmlFile"); + } +}; + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(plugin, MyPlugin); diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/pluginWithQmlFile.pro b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/pluginWithQmlFile.pro new file mode 100644 index 0000000..aa9c95c --- /dev/null +++ b/tests/auto/declarative/qdeclarativemoduleplugin/pluginWithQmlFile/pluginWithQmlFile.pro @@ -0,0 +1,9 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core declarative +DESTDIR = ../imports/com/nokia/AutoTestPluginWithQmlFile + +symbian: { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro b/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro index 221e465..6e72d98 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro +++ b/tests/auto/declarative/qdeclarativemoduleplugin/qdeclarativemoduleplugin.pro @@ -1,6 +1,6 @@ QT = core TEMPLATE = subdirs -SUBDIRS = plugin pluginWrongCase +SUBDIRS = plugin plugin.2 plugin.2.1 pluginWrongCase pluginWithQmlFile pluginMixed pluginVersion tst_qdeclarativemoduleplugin_pro.depends += plugin SUBDIRS += tst_qdeclarativemoduleplugin.pro diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp index 96ec21b..dc104e2 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.cpp @@ -44,6 +44,13 @@ #include <QtDeclarative/qdeclarativecomponent.h> #include <QDebug> +#include "../shared/testhttpserver.h" +#include "../../../shared/util.h" + +#define SERVER_ADDR "http://127.0.0.1:14450" +#define SERVER_PORT 14450 + + class tst_qdeclarativemoduleplugin : public QObject { Q_OBJECT @@ -54,7 +61,15 @@ public: private slots: void importsPlugin(); + void importsPlugin2(); + void importsPlugin21(); + void importsMixedQmlCppPlugin(); void incorrectPluginCase(); + void importPluginWithQmlFile(); + void remoteImportWithQuotedUrl(); + void remoteImportWithUnquotedUri(); + void versionNotInstalled(); + void versionNotInstalled_data(); }; #ifdef Q_OS_SYMBIAN @@ -121,6 +136,38 @@ void tst_qdeclarativemoduleplugin::importsPlugin() delete object; } +void tst_qdeclarativemoduleplugin::importsPlugin2() +{ + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + QTest::ignoreMessage(QtWarningMsg, "plugin2 created"); + QTest::ignoreMessage(QtWarningMsg, "import2 worked"); + QDeclarativeComponent component(&engine, TEST_FILE("data/works2.qml")); + foreach (QDeclarativeError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("value").toInt(),123); + delete object; +} + +void tst_qdeclarativemoduleplugin::importsPlugin21() +{ + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + QTest::ignoreMessage(QtWarningMsg, "plugin2.1 created"); + QTest::ignoreMessage(QtWarningMsg, "import2.1 worked"); + QDeclarativeComponent component(&engine, TEST_FILE("data/works21.qml")); + foreach (QDeclarativeError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("value").toInt(),123); + delete object; +} + void tst_qdeclarativemoduleplugin::incorrectPluginCase() { QDeclarativeEngine engine; @@ -145,6 +192,122 @@ void tst_qdeclarativemoduleplugin::incorrectPluginCase() QCOMPARE(errors.at(0).description(), expectedError); } +void tst_qdeclarativemoduleplugin::importPluginWithQmlFile() +{ + QString path = QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports"); + + // QTBUG-16885: adding an import path with a lower-case "c:" causes assert failure + // (this only happens if the plugin includes pure QML files) + #ifdef Q_OS_WIN + QVERIFY(path.at(0).isUpper() && path.at(1) == QLatin1Char(':')); + path = path.at(0).toLower() + path.mid(1); + #endif + + QDeclarativeEngine engine; + engine.addImportPath(path); + + QDeclarativeComponent component(&engine, TEST_FILE("data/pluginWithQmlFile.qml")); + foreach (QDeclarativeError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + delete object; +} + +void tst_qdeclarativemoduleplugin::remoteImportWithQuotedUrl() +{ + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + server.serveDirectory(SRCDIR "/imports"); + + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine); + component.setData("import \"http://127.0.0.1:14450/com/nokia/PureQmlModule\" \nComponentA { width: 300; ComponentB{} }", QUrl()); + + QTRY_COMPARE(component.status(), QDeclarativeComponent::Ready); + QObject *object = component.create(); + QCOMPARE(object->property("width").toInt(), 300); + QVERIFY(object != 0); + delete object; + + foreach (QDeclarativeError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); +} + +void tst_qdeclarativemoduleplugin::remoteImportWithUnquotedUri() +{ + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + server.serveDirectory(SRCDIR "/imports"); + + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + QDeclarativeComponent component(&engine); + component.setData("import com.nokia.PureQmlModule 1.0 \nComponentA { width: 300; ComponentB{} }", QUrl()); + + + QTRY_COMPARE(component.status(), QDeclarativeComponent::Ready); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("width").toInt(), 300); + delete object; + + foreach (QDeclarativeError err, component.errors()) + qWarning() << err; + VERIFY_ERRORS(0); +} + +// QTBUG-17324 +void tst_qdeclarativemoduleplugin::importsMixedQmlCppPlugin() +{ + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + + { + QDeclarativeComponent component(&engine, TEST_FILE("data/importsMixedQmlCppPlugin.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + QCOMPARE(o->property("test").toBool(), true); + delete o; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("data/importsMixedQmlCppPlugin.2.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + QCOMPARE(o->property("test").toBool(), true); + QCOMPARE(o->property("test2").toBool(), true); + delete o; + } + + +} + +void tst_qdeclarativemoduleplugin::versionNotInstalled_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("errorFile"); + + QTest::newRow("versionNotInstalled") << "data/versionNotInstalled.qml" << "versionNotInstalled.errors.txt"; + QTest::newRow("versionNotInstalled") << "data/versionNotInstalled.2.qml" << "versionNotInstalled.2.errors.txt"; +} + +void tst_qdeclarativemoduleplugin::versionNotInstalled() +{ + QFETCH(QString, file); + QFETCH(QString, errorFile); + + QDeclarativeEngine engine; + engine.addImportPath(QLatin1String(SRCDIR) + QDir::separator() + QLatin1String("imports")); + + QDeclarativeComponent component(&engine, TEST_FILE(file)); + VERIFY_ERRORS(errorFile.toLatin1().constData()); +} + QTEST_MAIN(tst_qdeclarativemoduleplugin) #include "tst_qdeclarativemoduleplugin.moc" diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro index 2e8aa75..98cd472 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro @@ -1,6 +1,9 @@ load(qttest_p4) -SOURCES = tst_qdeclarativemoduleplugin.cpp -QT += declarative + +HEADERS = ../shared/testhttpserver.h +SOURCES = tst_qdeclarativemoduleplugin.cpp \ + ../shared/testhttpserver.cpp +QT += declarative network CONFIG -= app_bundle symbian: { diff --git a/tests/auto/declarative/qdeclarativemousearea/data/pressedOrdering.qml b/tests/auto/declarative/qdeclarativemousearea/data/pressedOrdering.qml new file mode 100644 index 0000000..4a80e83 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemousearea/data/pressedOrdering.qml @@ -0,0 +1,28 @@ +import QtQuick 1.0 + +Item { + id: root + property string value: "base" + + MouseArea { + id: mouseArea + width: 200; height: 200 + onClicked: toggleState.state = "toggled" + } + + StateGroup { + states: State { + name: "pressed" + when: mouseArea.pressed + PropertyChanges { target: root; value: "pressed" } + } + } + + StateGroup { + id: toggleState + states: State { + name: "toggled" + PropertyChanges { target: root; value: "toggled" } + } + } +} diff --git a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp index 9d7cc05..845d6bb 100644 --- a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp +++ b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp @@ -64,6 +64,7 @@ private slots: void onMousePressRejected(); void doubleClick(); void clickTwice(); + void pressedOrdering(); private: QDeclarativeView *createView(); @@ -477,6 +478,40 @@ void tst_QDeclarativeMouseArea::clickTwice() QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 2); } +void tst_QDeclarativeMouseArea::pressedOrdering() +{ + QDeclarativeView *canvas = createView(); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pressedOrdering.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("base")); + + QGraphicsScene *scene = canvas->scene(); + QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress); + pressEvent.setScenePos(QPointF(100, 100)); + pressEvent.setButton(Qt::LeftButton); + pressEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &pressEvent); + + QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed")); + + QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease); + releaseEvent.setScenePos(QPointF(100, 100)); + releaseEvent.setButton(Qt::LeftButton); + releaseEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &releaseEvent); + + QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("toggled")); + + QApplication::sendEvent(scene, &pressEvent); + + QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed")); + + delete canvas; +} + QTEST_MAIN(tst_QDeclarativeMouseArea) #include "tst_qdeclarativemousearea.moc" diff --git a/tests/auto/declarative/qdeclarativepathview/data/dragpath.qml b/tests/auto/declarative/qdeclarativepathview/data/dragpath.qml new file mode 100644 index 0000000..a361bdc --- /dev/null +++ b/tests/auto/declarative/qdeclarativepathview/data/dragpath.qml @@ -0,0 +1,19 @@ +import QtQuick 1.0 + +PathView { + width: 400 + height: 200 + model: 100 + pathItemCount: 20 + path: Path { + startX: 0; startY: 100 + PathLine { x: 400; y: 100 } + } + delegate: Rectangle { height: 100; width: 1; color: PathView.isCurrentItem?"red" : "black" } + dragMargin: 100 + preferredHighlightBegin: 0.5 + preferredHighlightEnd: 0.5 + Text { + text: "current index: " + parent.currentIndex + } +} diff --git a/tests/auto/declarative/qdeclarativepathview/data/treemodel.qml b/tests/auto/declarative/qdeclarativepathview/data/treemodel.qml new file mode 100644 index 0000000..56f7ae4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativepathview/data/treemodel.qml @@ -0,0 +1,19 @@ +import QtQuick 1.0 + +PathView { + width: 320 + height: 240 + function setRoot(index) { + vdm.rootIndex = vdm.modelIndex(index); + } + model: VisualDataModel { + id: vdm + model: myModel + delegate: Text { objectName: "wrapper"; text: display } + } + + path: Path { + startX: 0; startY: 120 + PathLine { x: 320; y: 120 } + } +} diff --git a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp index 23ae907..ebb5f98 100644 --- a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp +++ b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp @@ -53,6 +53,7 @@ #include <QtDeclarative/private/qdeclarativevaluetype_p.h> #include <QAbstractListModel> #include <QStringListModel> +#include <QStandardItemModel> #include <QFile> #include "../../../shared/util.h" @@ -62,6 +63,25 @@ #define SRCDIR "." #endif +static void initStandardTreeModel(QStandardItemModel *model) +{ + QStandardItem *item; + item = new QStandardItem(QLatin1String("Row 1 Item")); + model->insertRow(0, item); + + item = new QStandardItem(QLatin1String("Row 2 Item")); + item->setCheckable(true); + model->insertRow(1, item); + + QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item")); + item->setChild(0, childItem); + + item = new QStandardItem(QLatin1String("Row 3 Item")); + item->setIcon(QIcon()); + model->insertRow(2, item); +} + + class tst_QDeclarativePathView : public QObject { Q_OBJECT @@ -89,6 +109,8 @@ private slots: void pathUpdate(); void visualDataModel(); void undefinedPath(); + void mouseDrag(); + void treeModel(); private: QDeclarativeView *createView(); @@ -867,6 +889,65 @@ void tst_QDeclarativePathView::undefinedPath() delete obj; } +void tst_QDeclarativePathView::mouseDrag() +{ + QDeclarativeView *canvas = createView(); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/dragpath.qml")); + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject()); + QVERIFY(pathview != 0); + + int current = pathview->currentIndex(); + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(10,100))); + + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(30,100)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(90,100)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + + QVERIFY(pathview->currentIndex() != current); + + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(40,100))); + + delete canvas; +} + +void tst_QDeclarativePathView::treeModel() +{ + QDeclarativeView *canvas = createView(); + + QStandardItemModel model; + initStandardTreeModel(&model); + canvas->engine()->rootContext()->setContextProperty("myModel", &model); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/treemodel.qml")); + + QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject()); + QVERIFY(pathview != 0); + QCOMPARE(pathview->count(), 3); + + QDeclarativeText *item = findItem<QDeclarativeText>(pathview, "wrapper", 0); + QVERIFY(item); + QCOMPARE(item->text(), QLatin1String("Row 1 Item")); + + QVERIFY(QMetaObject::invokeMethod(pathview, "setRoot", Q_ARG(QVariant, 1))); + QCOMPARE(pathview->count(), 1); + + QTRY_VERIFY(item = findItem<QDeclarativeText>(pathview, "wrapper", 0)); + QTRY_COMPARE(item->text(), QLatin1String("Row 2 Child Item")); + + delete canvas; +} + QDeclarativeView *tst_QDeclarativePathView::createView() { QDeclarativeView *canvas = new QDeclarativeView(0); diff --git a/tests/auto/declarative/qdeclarativepincharea/data/pinchproperties.qml b/tests/auto/declarative/qdeclarativepincharea/data/pinchproperties.qml new file mode 100644 index 0000000..0b59d9d --- /dev/null +++ b/tests/auto/declarative/qdeclarativepincharea/data/pinchproperties.qml @@ -0,0 +1,46 @@ +import QtQuick 1.1 +Rectangle { + id: whiteRect + property variant center + property real scale + width: 240; height: 320 + color: "white" + Rectangle { + id: blackRect + objectName: "blackrect" + color: "black" + y: 50 + x: 50 + width: 100 + height: 100 + opacity: (whiteRect.width-blackRect.x+whiteRect.height-blackRect.y-199)/200 + Text { text: blackRect.opacity} + PinchArea { + id: pincharea + objectName: "pincharea" + anchors.fill: parent + pinch.target: blackRect + pinch.dragAxis: Drag.XandYAxis + pinch.minimumX: 0 + pinch.maximumX: whiteRect.width-blackRect.width + pinch.minimumY: 0 + pinch.maximumY: whiteRect.height-blackRect.height + pinch.minimumScale: 1.0 + pinch.maximumScale: 2.0 + pinch.minimumRotation: 0.0 + pinch.maximumRotation: 90.0 + onPinchStarted: { + whiteRect.center = pinch.center + whiteRect.scale = pinch.scale + } + onPinchUpdated: { + whiteRect.center = pinch.center + whiteRect.scale = pinch.scale + } + onPinchFinished: { + whiteRect.center = pinch.center + whiteRect.scale = pinch.scale + } + } + } + } diff --git a/tests/auto/declarative/qdeclarativepincharea/qdeclarativepincharea.pro b/tests/auto/declarative/qdeclarativepincharea/qdeclarativepincharea.pro new file mode 100644 index 0000000..2c13644 --- /dev/null +++ b/tests/auto/declarative/qdeclarativepincharea/qdeclarativepincharea.pro @@ -0,0 +1,16 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative gui +macx:CONFIG -= app_bundle + +SOURCES += tst_qdeclarativepincharea.cpp + +symbian: { + importFiles.sources = data + importFiles.path = . + DEPLOYMENT = importFiles +} else { + DEFINES += SRCDIR=\\\"$$PWD\\\" +} + +CONFIG += parallel_test + diff --git a/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp new file mode 100644 index 0000000..f175033 --- /dev/null +++ b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp @@ -0,0 +1,315 @@ +/**************************************************************************** +** +** 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 <QtTest/QtTest> +#include <QtTest/QSignalSpy> +#include <private/qdeclarativepincharea_p.h> +#include <private/qdeclarativerectangle_p.h> +#include <QtDeclarative/qdeclarativeview.h> +#include <QtDeclarative/qdeclarativecontext.h> + +#ifdef Q_OS_SYMBIAN +// In Symbian OS test data is located in applications private dir +#define SRCDIR "." +#endif + +class tst_QDeclarativePinchArea: public QObject +{ + Q_OBJECT +private slots: + void pinchProperties(); + void scale(); + void pan(); + +private: + QDeclarativeView *createView(); +}; + +void tst_QDeclarativePinchArea::pinchProperties() +{ + QDeclarativeView *canvas = createView(); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pinchproperties.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QDeclarativePinchArea *pinchArea = canvas->rootObject()->findChild<QDeclarativePinchArea*>("pincharea"); + QDeclarativePinch *pinch = pinchArea->pinch(); + QVERIFY(pinchArea != 0); + QVERIFY(pinch != 0); + + // target + QDeclarativeItem *blackRect = canvas->rootObject()->findChild<QDeclarativeItem*>("blackrect"); + QVERIFY(blackRect != 0); + QVERIFY(blackRect == pinch->target()); + QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(canvas->rootObject()); + QVERIFY(rootItem != 0); + QSignalSpy targetSpy(pinch, SIGNAL(targetChanged())); + pinch->setTarget(rootItem); + QCOMPARE(targetSpy.count(),1); + pinch->setTarget(rootItem); + QCOMPARE(targetSpy.count(),1); + + // axis + QCOMPARE(pinch->axis(), QDeclarativePinch::XandYAxis); + QSignalSpy axisSpy(pinch, SIGNAL(dragAxisChanged())); + pinch->setAxis(QDeclarativePinch::XAxis); + QCOMPARE(pinch->axis(), QDeclarativePinch::XAxis); + QCOMPARE(axisSpy.count(),1); + pinch->setAxis(QDeclarativePinch::XAxis); + QCOMPARE(axisSpy.count(),1); + + // minimum and maximum drag properties + QSignalSpy xminSpy(pinch, SIGNAL(minimumXChanged())); + QSignalSpy xmaxSpy(pinch, SIGNAL(maximumXChanged())); + QSignalSpy yminSpy(pinch, SIGNAL(minimumYChanged())); + QSignalSpy ymaxSpy(pinch, SIGNAL(maximumYChanged())); + + QCOMPARE(pinch->xmin(), 0.0); + QCOMPARE(pinch->xmax(), rootItem->width()-blackRect->width()); + QCOMPARE(pinch->ymin(), 0.0); + QCOMPARE(pinch->ymax(), rootItem->height()-blackRect->height()); + + pinch->setXmin(10); + pinch->setXmax(10); + pinch->setYmin(10); + pinch->setYmax(10); + + QCOMPARE(pinch->xmin(), 10.0); + QCOMPARE(pinch->xmax(), 10.0); + QCOMPARE(pinch->ymin(), 10.0); + QCOMPARE(pinch->ymax(), 10.0); + + QCOMPARE(xminSpy.count(),1); + QCOMPARE(xmaxSpy.count(),1); + QCOMPARE(yminSpy.count(),1); + QCOMPARE(ymaxSpy.count(),1); + + pinch->setXmin(10); + pinch->setXmax(10); + pinch->setYmin(10); + pinch->setYmax(10); + + QCOMPARE(xminSpy.count(),1); + QCOMPARE(xmaxSpy.count(),1); + QCOMPARE(yminSpy.count(),1); + QCOMPARE(ymaxSpy.count(),1); + + // minimum and maximum scale properties + QSignalSpy scaleMinSpy(pinch, SIGNAL(minimumScaleChanged())); + QSignalSpy scaleMaxSpy(pinch, SIGNAL(maximumScaleChanged())); + + QCOMPARE(pinch->minimumScale(), 1.0); + QCOMPARE(pinch->maximumScale(), 2.0); + + pinch->setMinimumScale(0.5); + pinch->setMaximumScale(1.5); + + QCOMPARE(pinch->minimumScale(), 0.5); + QCOMPARE(pinch->maximumScale(), 1.5); + + QCOMPARE(scaleMinSpy.count(),1); + QCOMPARE(scaleMaxSpy.count(),1); + + pinch->setMinimumScale(0.5); + pinch->setMaximumScale(1.5); + + QCOMPARE(scaleMinSpy.count(),1); + QCOMPARE(scaleMaxSpy.count(),1); + + // minimum and maximum rotation properties + QSignalSpy rotMinSpy(pinch, SIGNAL(minimumRotationChanged())); + QSignalSpy rotMaxSpy(pinch, SIGNAL(maximumRotationChanged())); + + QCOMPARE(pinch->minimumRotation(), 0.0); + QCOMPARE(pinch->maximumRotation(), 90.0); + + pinch->setMinimumRotation(-90.0); + pinch->setMaximumRotation(45.0); + + QCOMPARE(pinch->minimumRotation(), -90.0); + QCOMPARE(pinch->maximumRotation(), 45.0); + + QCOMPARE(rotMinSpy.count(),1); + QCOMPARE(rotMaxSpy.count(),1); + + pinch->setMinimumRotation(-90.0); + pinch->setMaximumRotation(45.0); + + QCOMPARE(rotMinSpy.count(),1); + QCOMPARE(rotMaxSpy.count(),1); + + delete canvas; +} + +QTouchEvent::TouchPoint makeTouchPoint(int id, QPoint p, QGraphicsView *v, QGraphicsItem *i) +{ + QTouchEvent::TouchPoint touchPoint(id); + touchPoint.setPos(i->mapFromScene(p)); + touchPoint.setScreenPos(v->mapToGlobal(p)); + touchPoint.setScenePos(p); + return touchPoint; +} + +void tst_QDeclarativePinchArea::scale() +{ + QDeclarativeView *canvas = createView(); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pinchproperties.qml")); + canvas->show(); + canvas->setFocus(); + QTest::qWaitForWindowShown(canvas); + QVERIFY(canvas->rootObject() != 0); + qApp->processEvents(); + + QDeclarativePinchArea *pinchArea = canvas->rootObject()->findChild<QDeclarativePinchArea*>("pincharea"); + QDeclarativePinch *pinch = pinchArea->pinch(); + QVERIFY(pinchArea != 0); + QVERIFY(pinch != 0); + + QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(canvas->rootObject()); + QVERIFY(root != 0); + + // target + QDeclarativeItem *blackRect = canvas->rootObject()->findChild<QDeclarativeItem*>("blackrect"); + QVERIFY(blackRect != 0); + + QWidget *vp = canvas->viewport(); + + QPoint p1(80, 80); + QPoint p2(100, 100); + + QTest::touchEvent(vp).press(0, p1); + QTest::touchEvent(vp).stationary(0).press(1, p2); + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(root->property("scale").toReal(), 1.0); + + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(root->property("scale").toReal(), 1.5); + QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50 + QCOMPARE(blackRect->scale(), 1.5); + + // scale beyond bound + p1 -= QPoint(50,50); + p2 += QPoint(50,50); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(blackRect->scale(), 2.0); + + QTest::touchEvent(vp).release(0, p1).release(1, p2); + + delete canvas; +} + +void tst_QDeclarativePinchArea::pan() +{ + QDeclarativeView *canvas = createView(); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pinchproperties.qml")); + canvas->show(); + canvas->setFocus(); + QTest::qWaitForWindowShown(canvas); + QVERIFY(canvas->rootObject() != 0); + qApp->processEvents(); + + QDeclarativePinchArea *pinchArea = canvas->rootObject()->findChild<QDeclarativePinchArea*>("pincharea"); + QDeclarativePinch *pinch = pinchArea->pinch(); + QVERIFY(pinchArea != 0); + QVERIFY(pinch != 0); + + QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(canvas->rootObject()); + QVERIFY(root != 0); + + // target + QDeclarativeItem *blackRect = canvas->rootObject()->findChild<QDeclarativeItem*>("blackrect"); + QVERIFY(blackRect != 0); + + QWidget *vp = canvas->viewport(); + + QPoint p1(80, 80); + QPoint p2(100, 100); + + QTest::touchEvent(vp).press(0, p1); + QTest::touchEvent(vp).stationary(0).press(1, p2); + p1 += QPoint(10,10); + p2 += QPoint(10,10); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(root->property("scale").toReal(), 1.0); + + p1 += QPoint(10,10); + p2 += QPoint(10,10); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(root->property("center").toPointF(), QPointF(60, 60)); // blackrect is at 50,50 + + QCOMPARE(blackRect->x(), 60.0); + QCOMPARE(blackRect->y(), 60.0); + + // pan x beyond bound + p1 += QPoint(100,100); + p2 += QPoint(100,100); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(blackRect->x(), 140.0); + QCOMPARE(blackRect->y(), 160.0); + + QTest::touchEvent(vp).release(0, p1).release(1, p2); + + delete canvas; +} + +QDeclarativeView *tst_QDeclarativePinchArea::createView() +{ + QDeclarativeView *canvas = new QDeclarativeView(0); + canvas->viewport()->setAttribute(Qt::WA_AcceptTouchEvents); + canvas->setFixedSize(240,320); + + return canvas; +} + +QTEST_MAIN(tst_QDeclarativePinchArea) + +#include "tst_qdeclarativepincharea.moc" diff --git a/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp b/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp index 0dafc50..edb182c 100644 --- a/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp +++ b/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp @@ -47,6 +47,11 @@ #include "testhttpserver.h" #include "../../../shared/util.h" +#ifndef QT_NO_CONCURRENT +#include <qtconcurrentrun.h> +#include <qfuture.h> +#endif + // These don't let normal people run tests! //#include "../network-settings.h" @@ -356,6 +361,8 @@ void tst_qdeclarativepixmapcache::shrinkcache() } } +#ifndef QT_NO_CONCURRENT + void createNetworkServer() { QEventLoop eventLoop; @@ -382,6 +389,8 @@ void tst_qdeclarativepixmapcache::networkCrash() } #endif +#endif + QTEST_MAIN(tst_qdeclarativepixmapcache) #include "tst_qdeclarativepixmapcache.moc" diff --git a/tests/auto/declarative/qdeclarativepositioners/data/flow-testimplicitsize.qml b/tests/auto/declarative/qdeclarativepositioners/data/flow-testimplicitsize.qml index 51c8134..ee4e104 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/flow-testimplicitsize.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/flow-testimplicitsize.qml @@ -1,16 +1,19 @@ -import QtQuick 1.0 +import QtQuick 1.1 Rectangle { width: 300; height: 200; - property bool leftToRight: false + property int flowLayout: 1 Flow { objectName: "flow" - flow: leftToRight ? Flow.LeftToRight : Flow.TopToBottom + layoutDirection: (flowLayout == 2) ? Qt.RightToLeft : Qt.LeftToRight + flow: (flowLayout == 1) ? Flow.TopToBottom : Flow.LeftToRight; + spacing: 20 anchors.horizontalCenter: parent.horizontalCenter Rectangle { color: "red"; width: 100; height: 50 } Rectangle { color: "blue"; width: 100; height: 50 } } } + diff --git a/tests/auto/declarative/qdeclarativepositioners/data/flowtest-toptobottom.qml b/tests/auto/declarative/qdeclarativepositioners/data/flowtest-toptobottom.qml new file mode 100644 index 0000000..ec1d666 --- /dev/null +++ b/tests/auto/declarative/qdeclarativepositioners/data/flowtest-toptobottom.qml @@ -0,0 +1,44 @@ +import QtQuick 1.1 + +Item { + height: 90 + width: 480 + property bool testRightToLeft: false + + Flow { + objectName: "flow" + height: parent.height + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight + flow: Flow.TopToBottom + Rectangle { + objectName: "one" + color: "red" + width: 50 + height: 50 + } + Rectangle { + objectName: "two" + color: "green" + width: 20 + height: 50 + } + Rectangle { + objectName: "three" + color: "blue" + width: 50 + height: 20 + } + Rectangle { + objectName: "four" + color: "cyan" + width: 50 + height: 50 + } + Rectangle { + objectName: "five" + color: "magenta" + width: 10 + height: 10 + } + } +} diff --git a/tests/auto/declarative/qdeclarativepositioners/data/flowtest.qml b/tests/auto/declarative/qdeclarativepositioners/data/flowtest.qml index 2810234..7c124a3 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/flowtest.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/flowtest.qml @@ -1,11 +1,14 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 90 height: 480 + property bool testRightToLeft: false + Flow { objectName: "flow" width: parent.width + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight Rectangle { objectName: "one" color: "red" diff --git a/tests/auto/declarative/qdeclarativepositioners/data/grid-animated.qml b/tests/auto/declarative/qdeclarativepositioners/data/grid-animated.qml index e13f078..3dcbed1 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/grid-animated.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/grid-animated.qml @@ -1,11 +1,14 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 640 height: 480 + property bool testRightToLeft: true + Grid { objectName: "grid" columns: 3 + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight add: Transition { NumberAnimation { properties: "x,y"; diff --git a/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml b/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml new file mode 100644 index 0000000..0ec1f37 --- /dev/null +++ b/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml @@ -0,0 +1,41 @@ +import QtQuick 1.1 + +Item { + width: 640 + height: 480 + Grid { + objectName: "grid" + columns: 3 + layoutDirection: Qt.RightToLeft + Rectangle { + objectName: "one" + color: "red" + width: 50 + height: 50 + } + Rectangle { + objectName: "two" + color: "green" + width: 20 + height: 50 + } + Rectangle { + objectName: "three" + color: "blue" + width: 50 + height: 20 + } + Rectangle { + objectName: "four" + color: "cyan" + width: 50 + height: 50 + } + Rectangle { + objectName: "five" + color: "magenta" + width: 10 + height: 10 + } + } +} diff --git a/tests/auto/declarative/qdeclarativepositioners/data/horizontal-animated.qml b/tests/auto/declarative/qdeclarativepositioners/data/horizontal-animated.qml index 5b064cd..3c95f53 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/horizontal-animated.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/horizontal-animated.qml @@ -1,10 +1,13 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 640 height: 480 + property bool testRightToLeft: false + Row { objectName: "row" + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight add: Transition { NumberAnimation { properties: "x"; diff --git a/tests/auto/declarative/qdeclarativepositioners/data/horizontal-spacing.qml b/tests/auto/declarative/qdeclarativepositioners/data/horizontal-spacing.qml index 2b46bca..64bedb0 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/horizontal-spacing.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/horizontal-spacing.qml @@ -1,11 +1,14 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 640 height: 480 + property bool testRightToLeft: false + Row { objectName: "row" spacing: 10 + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight Rectangle { objectName: "one" color: "red" diff --git a/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml b/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml index 919cecc..e1a9652 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml @@ -1,10 +1,13 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 640 height: 480 + property bool testRightToLeft: false + Row { objectName: "row" + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight Rectangle { objectName: "one" color: "red" diff --git a/tests/auto/declarative/qdeclarativepositioners/data/repeatertest.qml b/tests/auto/declarative/qdeclarativepositioners/data/repeatertest.qml index 1cba598..f93ce67 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/repeatertest.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/repeatertest.qml @@ -12,9 +12,27 @@ Item { height: 50 z: {if(index == 0){2;}else if(index == 1){1;} else{3;}} objectName: {if(index == 0){"one";}else if(index == 1){"two";} else{"three";}} - } } } } + + //This crashed once (QTBUG-16959) because the repeater ended up on the end of the list + //If this grid just instantiates without crashing, then it has not regressed. + Grid { + id: grid + rows: 2 + flow: Grid.TopToBottom + + Repeater { + model: 13 + Rectangle { + color: "goldenrod" + width: 100 + height: 100 + radius: 10 + border.width: 1 + } + } + } } diff --git a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp index 93611cc..40e533d 100644 --- a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp +++ b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp @@ -62,23 +62,33 @@ public: private slots: void test_horizontal(); + void test_horizontal_rtl(); void test_horizontal_spacing(); + void test_horizontal_spacing_rightToLeft(); void test_horizontal_animated(); + void test_horizontal_animated_rightToLeft(); void test_vertical(); void test_vertical_spacing(); void test_vertical_animated(); void test_grid(); void test_grid_topToBottom(); + void test_grid_rightToLeft(); void test_grid_spacing(); void test_grid_animated(); + void test_grid_animated_rightToLeft(); void test_grid_zero_columns(); void test_propertychanges(); void test_repeater(); void test_flow(); + void test_flow_rightToLeft(); + void test_flow_topToBottom(); void test_flow_resize(); + void test_flow_resize_rightToLeft(); void test_flow_implicit_resize(); void test_conflictinganchors(); void test_vertical_qgraphicswidget(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QDeclarativeView *createView(const QString &filename); }; @@ -91,6 +101,8 @@ void tst_QDeclarativePositioners::test_horizontal() { QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal.qml"); + canvas->rootObject()->setProperty("testRightToLeft", false); + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); QVERIFY(one != 0); @@ -114,10 +126,41 @@ void tst_QDeclarativePositioners::test_horizontal() delete canvas; } +void tst_QDeclarativePositioners::test_horizontal_rtl() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); + QVERIFY(one != 0); + + QDeclarativeRectangle *two = canvas->rootObject()->findChild<QDeclarativeRectangle*>("two"); + QVERIFY(two != 0); + + QDeclarativeRectangle *three = canvas->rootObject()->findChild<QDeclarativeRectangle*>("three"); + QVERIFY(three != 0); + + QCOMPARE(one->x(), 60.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 40.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 0.0); + QCOMPARE(three->y(), 0.0); + + QDeclarativeItem *row = canvas->rootObject()->findChild<QDeclarativeItem*>("row"); + QCOMPARE(row->width(), 110.0); + QCOMPARE(row->height(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_horizontal_spacing() { QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal-spacing.qml"); + canvas->rootObject()->setProperty("testRightToLeft", false); + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); QVERIFY(one != 0); @@ -141,10 +184,41 @@ void tst_QDeclarativePositioners::test_horizontal_spacing() delete canvas; } +void tst_QDeclarativePositioners::test_horizontal_spacing_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal-spacing.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); + QVERIFY(one != 0); + + QDeclarativeRectangle *two = canvas->rootObject()->findChild<QDeclarativeRectangle*>("two"); + QVERIFY(two != 0); + + QDeclarativeRectangle *three = canvas->rootObject()->findChild<QDeclarativeRectangle*>("three"); + QVERIFY(three != 0); + + QCOMPARE(one->x(), 80.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 00.0); + QCOMPARE(three->y(), 0.0); + + QDeclarativeItem *row = canvas->rootObject()->findChild<QDeclarativeItem*>("row"); + QCOMPARE(row->width(), 130.0); + QCOMPARE(row->height(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_horizontal_animated() { QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal-animated.qml"); + canvas->rootObject()->setProperty("testRightToLeft", false); + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); QVERIFY(one != 0); @@ -193,6 +267,60 @@ void tst_QDeclarativePositioners::test_horizontal_animated() delete canvas; } +void tst_QDeclarativePositioners::test_horizontal_animated_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal-animated.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); + QVERIFY(one != 0); + + QDeclarativeRectangle *two = canvas->rootObject()->findChild<QDeclarativeRectangle*>("two"); + QVERIFY(two != 0); + + QDeclarativeRectangle *three = canvas->rootObject()->findChild<QDeclarativeRectangle*>("three"); + QVERIFY(three != 0); + + //Note that they animate in + QCOMPARE(one->x(), -100.0); + QCOMPARE(two->x(), -100.0); + QCOMPARE(three->x(), -100.0); + + QDeclarativeItem *row = canvas->rootObject()->findChild<QDeclarativeItem*>("row"); + QVERIFY(row); + QCOMPARE(row->width(), 100.0); + QCOMPARE(row->height(), 50.0); + + //QTRY_COMPARE used instead of waiting for the expected time of animation completion + //Note that this means the duration of the animation is NOT tested + + QTRY_COMPARE(one->x(), 50.0); + QTRY_COMPARE(one->y(), 0.0); + QTRY_COMPARE(two->opacity(), 0.0); + QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet + QTRY_COMPARE(two->y(), 0.0); + QTRY_COMPARE(three->x(), 0.0); + QTRY_COMPARE(three->y(), 0.0); + + //Add 'two' + two->setOpacity(1.0); + QCOMPARE(two->opacity(), 1.0); + + // New size should be immediate + QCOMPARE(row->width(), 150.0); + QCOMPARE(row->height(), 50.0); + + QTest::qWait(0);//Let the animation start + QCOMPARE(one->x(), 50.0); + QCOMPARE(two->x(), -100.0); + + QTRY_COMPARE(one->x(), 100.0); + QTRY_COMPARE(two->x(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_vertical() { QDeclarativeView *canvas = createView(SRCDIR "/data/vertical.qml"); @@ -364,6 +492,40 @@ void tst_QDeclarativePositioners::test_grid_topToBottom() delete canvas; } +void tst_QDeclarativePositioners::test_grid_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/grid-righttoleft.qml"); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); + QVERIFY(one != 0); + QDeclarativeRectangle *two = canvas->rootObject()->findChild<QDeclarativeRectangle*>("two"); + QVERIFY(two != 0); + QDeclarativeRectangle *three = canvas->rootObject()->findChild<QDeclarativeRectangle*>("three"); + QVERIFY(three != 0); + QDeclarativeRectangle *four = canvas->rootObject()->findChild<QDeclarativeRectangle*>("four"); + QVERIFY(four != 0); + QDeclarativeRectangle *five = canvas->rootObject()->findChild<QDeclarativeRectangle*>("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 70.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 0.0); + QCOMPARE(three->y(), 0.0); + QCOMPARE(four->x(), 70.0); + QCOMPARE(four->y(), 50.0); + QCOMPARE(five->x(), 60.0); + QCOMPARE(five->y(), 50.0); + + QDeclarativeGrid *grid = canvas->rootObject()->findChild<QDeclarativeGrid*>("grid"); + QCOMPARE(grid->layoutDirection(), Qt::RightToLeft); + QCOMPARE(grid->width(), 120.0); + QCOMPARE(grid->height(), 100.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_grid_spacing() { QDeclarativeView *canvas = createView(SRCDIR "/data/grid-spacing.qml"); @@ -401,6 +563,8 @@ void tst_QDeclarativePositioners::test_grid_animated() { QDeclarativeView *canvas = createView(SRCDIR "/data/grid-animated.qml"); + canvas->rootObject()->setProperty("testRightToLeft", false); + //Note that all animate in QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); QVERIFY(one != 0); @@ -478,6 +642,89 @@ void tst_QDeclarativePositioners::test_grid_animated() delete canvas; } +void tst_QDeclarativePositioners::test_grid_animated_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/grid-animated.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + //Note that all animate in + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); + QVERIFY(one != 0); + QCOMPARE(one->x(), -100.0); + QCOMPARE(one->y(), -100.0); + + QDeclarativeRectangle *two = canvas->rootObject()->findChild<QDeclarativeRectangle*>("two"); + QVERIFY(two != 0); + QCOMPARE(two->x(), -100.0); + QCOMPARE(two->y(), -100.0); + + QDeclarativeRectangle *three = canvas->rootObject()->findChild<QDeclarativeRectangle*>("three"); + QVERIFY(three != 0); + QCOMPARE(three->x(), -100.0); + QCOMPARE(three->y(), -100.0); + + QDeclarativeRectangle *four = canvas->rootObject()->findChild<QDeclarativeRectangle*>("four"); + QVERIFY(four != 0); + QCOMPARE(four->x(), -100.0); + QCOMPARE(four->y(), -100.0); + + QDeclarativeRectangle *five = canvas->rootObject()->findChild<QDeclarativeRectangle*>("five"); + QVERIFY(five != 0); + QCOMPARE(five->x(), -100.0); + QCOMPARE(five->y(), -100.0); + + QDeclarativeItem *grid = canvas->rootObject()->findChild<QDeclarativeItem*>("grid"); + QVERIFY(grid); + QCOMPARE(grid->width(), 150.0); + QCOMPARE(grid->height(), 100.0); + + //QTRY_COMPARE used instead of waiting for the expected time of animation completion + //Note that this means the duration of the animation is NOT tested + + QTRY_COMPARE(one->y(), 0.0); + QTRY_COMPARE(one->x(), 100.0); + QTRY_COMPARE(two->opacity(), 0.0); + QTRY_COMPARE(two->y(), -100.0); + QTRY_COMPARE(two->x(), -100.0); + QTRY_COMPARE(three->y(), 0.0); + QTRY_COMPARE(three->x(), 50.0); + QTRY_COMPARE(four->y(), 0.0); + QTRY_COMPARE(four->x(), 0.0); + QTRY_COMPARE(five->y(), 50.0); + QTRY_COMPARE(five->x(), 100.0); + + //Add 'two' + two->setOpacity(1.0); + QCOMPARE(two->opacity(), 1.0); + QCOMPARE(grid->width(), 150.0); + QCOMPARE(grid->height(), 100.0); + QTest::qWait(0);//Let the animation start + QCOMPARE(two->x(), -100.0); + QCOMPARE(two->y(), -100.0); + QCOMPARE(one->x(), 100.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(three->x(), 50.0); + QCOMPARE(three->y(), 0.0); + QCOMPARE(four->x(), 0.0); + QCOMPARE(four->y(), 0.0); + QCOMPARE(five->x(), 100.0); + QCOMPARE(five->y(), 50.0); + //Let the animation complete + QTRY_COMPARE(two->x(), 50.0); + QTRY_COMPARE(two->y(), 0.0); + QTRY_COMPARE(one->x(), 100.0); + QTRY_COMPARE(one->y(), 0.0); + QTRY_COMPARE(three->x(), 0.0); + QTRY_COMPARE(three->y(), 0.0); + QTRY_COMPARE(four->x(), 100.0); + QTRY_COMPARE(four->y(), 50.0); + QTRY_COMPARE(five->x(), 50.0); + QTRY_COMPARE(five->y(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_grid_zero_columns() { QDeclarativeView *canvas = createView(SRCDIR "/data/gridzerocolumns.qml"); @@ -597,6 +844,8 @@ void tst_QDeclarativePositioners::test_flow() { QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest.qml"); + canvas->rootObject()->setProperty("testRightToLeft", false); + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); QVERIFY(one != 0); QDeclarativeRectangle *two = canvas->rootObject()->findChild<QDeclarativeRectangle*>("two"); @@ -627,6 +876,95 @@ void tst_QDeclarativePositioners::test_flow() delete canvas; } +void tst_QDeclarativePositioners::test_flow_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); + QVERIFY(one != 0); + QDeclarativeRectangle *two = canvas->rootObject()->findChild<QDeclarativeRectangle*>("two"); + QVERIFY(two != 0); + QDeclarativeRectangle *three = canvas->rootObject()->findChild<QDeclarativeRectangle*>("three"); + QVERIFY(three != 0); + QDeclarativeRectangle *four = canvas->rootObject()->findChild<QDeclarativeRectangle*>("four"); + QVERIFY(four != 0); + QDeclarativeRectangle *five = canvas->rootObject()->findChild<QDeclarativeRectangle*>("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 40.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 20.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 40.0); + QCOMPARE(three->y(), 50.0); + QCOMPARE(four->x(), 40.0); + QCOMPARE(four->y(), 70.0); + QCOMPARE(five->x(), 30.0); + QCOMPARE(five->y(), 70.0); + + QDeclarativeItem *flow = canvas->rootObject()->findChild<QDeclarativeItem*>("flow"); + QVERIFY(flow); + QCOMPARE(flow->width(), 90.0); + QCOMPARE(flow->height(), 120.0); + + delete canvas; +} + +void tst_QDeclarativePositioners::test_flow_topToBottom() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest-toptobottom.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", false); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); + QVERIFY(one != 0); + QDeclarativeRectangle *two = canvas->rootObject()->findChild<QDeclarativeRectangle*>("two"); + QVERIFY(two != 0); + QDeclarativeRectangle *three = canvas->rootObject()->findChild<QDeclarativeRectangle*>("three"); + QVERIFY(three != 0); + QDeclarativeRectangle *four = canvas->rootObject()->findChild<QDeclarativeRectangle*>("four"); + QVERIFY(four != 0); + QDeclarativeRectangle *five = canvas->rootObject()->findChild<QDeclarativeRectangle*>("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 0.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 50.0); + QCOMPARE(three->y(), 50.0); + QCOMPARE(four->x(), 100.0); + QCOMPARE(four->y(), 00.0); + QCOMPARE(five->x(), 100.0); + QCOMPARE(five->y(), 50.0); + + QDeclarativeItem *flow = canvas->rootObject()->findChild<QDeclarativeItem*>("flow"); + QVERIFY(flow); + QCOMPARE(flow->height(), 90.0); + QCOMPARE(flow->width(), 150.0); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + QVERIFY(flow); + QCOMPARE(flow->height(), 90.0); + QCOMPARE(flow->width(), 150.0); + + QCOMPARE(one->x(), 100.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 80.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 50.0); + QCOMPARE(three->y(), 50.0); + QCOMPARE(four->x(), 0.0); + QCOMPARE(four->y(), 0.0); + QCOMPARE(five->x(), 40.0); + QCOMPARE(five->y(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_flow_resize() { QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest.qml"); @@ -634,6 +972,7 @@ void tst_QDeclarativePositioners::test_flow_resize() QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(canvas->rootObject()); QVERIFY(root); root->setWidth(125); + root->setProperty("testRightToLeft", false); QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); QVERIFY(one != 0); @@ -660,6 +999,40 @@ void tst_QDeclarativePositioners::test_flow_resize() delete canvas; } +void tst_QDeclarativePositioners::test_flow_resize_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest.qml"); + + QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(canvas->rootObject()); + QVERIFY(root); + root->setWidth(125); + root->setProperty("testRightToLeft", true); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); + QVERIFY(one != 0); + QDeclarativeRectangle *two = canvas->rootObject()->findChild<QDeclarativeRectangle*>("two"); + QVERIFY(two != 0); + QDeclarativeRectangle *three = canvas->rootObject()->findChild<QDeclarativeRectangle*>("three"); + QVERIFY(three != 0); + QDeclarativeRectangle *four = canvas->rootObject()->findChild<QDeclarativeRectangle*>("four"); + QVERIFY(four != 0); + QDeclarativeRectangle *five = canvas->rootObject()->findChild<QDeclarativeRectangle*>("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 75.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 55.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 5.0); + QCOMPARE(three->y(), 0.0); + QCOMPARE(four->x(), 75.0); + QCOMPARE(four->y(), 50.0); + QCOMPARE(five->x(), 65.0); + QCOMPARE(five->y(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_flow_implicit_resize() { QDeclarativeView *canvas = createView(SRCDIR "/data/flow-testimplicitsize.qml"); @@ -671,16 +1044,21 @@ void tst_QDeclarativePositioners::test_flow_implicit_resize() QCOMPARE(flow->width(), 100.0); QCOMPARE(flow->height(), 120.0); - canvas->rootObject()->setProperty("leftToRight", true); + canvas->rootObject()->setProperty("flowLayout", 0); QCOMPARE(flow->flow(), QDeclarativeFlow::LeftToRight); QCOMPARE(flow->width(), 220.0); QCOMPARE(flow->height(), 50.0); - canvas->rootObject()->setProperty("leftToRight", false); + canvas->rootObject()->setProperty("flowLayout", 1); QCOMPARE(flow->flow(), QDeclarativeFlow::TopToBottom); QCOMPARE(flow->width(), 100.0); QCOMPARE(flow->height(), 120.0); + canvas->rootObject()->setProperty("flowLayout", 2); + QCOMPARE(flow->layoutDirection(), Qt::RightToLeft); + QCOMPARE(flow->width(), 220.0); + QCOMPARE(flow->height(), 50.0); + delete canvas; } @@ -694,7 +1072,7 @@ void interceptWarnings(QtMsgType type, const char *msg) void tst_QDeclarativePositioners::test_conflictinganchors() { - qInstallMsgHandler(interceptWarnings); + QtMsgHandler oldMsgHandler = qInstallMsgHandler(interceptWarnings); QDeclarativeEngine engine; QDeclarativeComponent component(&engine); @@ -775,6 +1153,7 @@ void tst_QDeclarativePositioners::test_conflictinganchors() item = qobject_cast<QDeclarativeItem*>(component.create()); QVERIFY(item); QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow")); + qInstallMsgHandler(oldMsgHandler); } void tst_QDeclarativePositioners::test_vertical_qgraphicswidget() @@ -819,6 +1198,49 @@ void tst_QDeclarativePositioners::test_vertical_qgraphicswidget() delete canvas; } +void tst_QDeclarativePositioners::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; " + code.toUtf8(), QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; " + code.toUtf8(), QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_QDeclarativePositioners::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("Flow.layoutDirection") << "Flow { layoutDirection: Qt.LeftToRight }" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Flow.layoutDirection\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("Row.layoutDirection") << "Row { layoutDirection: Qt.LeftToRight }" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Row.layoutDirection\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("Grid.layoutDirection") << "Grid { layoutDirection: Qt.LeftToRight }" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Grid.layoutDirection\" is not available in QtQuick 1.0.\n"; +} + QDeclarativeView *tst_QDeclarativePositioners::createView(const QString &filename) { QDeclarativeView *canvas = new QDeclarativeView(0); diff --git a/tests/auto/declarative/qdeclarativeqt/data/formatting.qml b/tests/auto/declarative/qdeclarativeqt/data/formatting.qml index 35c6a29..f520aeb 100644 --- a/tests/auto/declarative/qdeclarativeqt/data/formatting.qml +++ b/tests/auto/declarative/qdeclarativeqt/data/formatting.qml @@ -1,29 +1,44 @@ import QtQuick 1.0 QtObject { - property date date1: "2008-12-24" - property string test1: Qt.formatDate(date1) - property string test2: Qt.formatDate(date1, Qt.DefaultLocaleLongDate) - property string test3: Qt.formatDate(date1, "ddd MMMM d yy") + property date dateFromString: "2008-12-24" + property variant jsdate: new Date(2008,11,24,14,15,38,200) // months are 0-based - property variant time1: new Date(0,0,0,14,15,38,200) - property string test4: Qt.formatTime(time1) - property string test5: Qt.formatTime(time1, Qt.DefaultLocaleLongDate) - property string test6: Qt.formatTime(time1, "H:m:s a") - property string test7: Qt.formatTime(time1, "hh:mm:ss.zzz") + function formatDate(prop) { + var v = eval(prop) + return [ + Qt.formatDate(v), + Qt.formatDate(v, Qt.DefaultLocaleLongDate), + Qt.formatDate(v, "ddd MMMM d yy") + ] + } - property variant dateTime1: new Date(1978,2,4,9,13,54) - property string test8: Qt.formatDateTime(dateTime1) - property string test9: Qt.formatDateTime(dateTime1, Qt.DefaultLocaleLongDate) - property string test10: Qt.formatDateTime(dateTime1, "M/d/yy H:m:s a") + function formatTime(prop) { + var v = eval(prop) + return [ + Qt.formatTime(v), + Qt.formatTime(v, Qt.DefaultLocaleLongDate), + Qt.formatTime(v, "H:m:s a"), + Qt.formatTime(v, "hh:mm:ss.zzz") + ] + } + + function formatDateTime(prop) { + var v = eval(prop) + return [ + Qt.formatDateTime(v), + Qt.formatDateTime(v, Qt.DefaultLocaleLongDate), + Qt.formatDateTime(v, "M/d/yy H:m:s a") + ] + } // Error cases - property string test11: Qt.formatDate() - property string test12: Qt.formatDate(new Date, new Object) + property string err_date1: Qt.formatDate() + property string err_date2: Qt.formatDate(new Date, new Object) - property string test13: Qt.formatTime() - property string test14: Qt.formatTime(new Date, new Object) + property string err_time1: Qt.formatTime() + property string err_time2: Qt.formatTime(new Date, new Object) - property string test15: Qt.formatDateTime() - property string test16: Qt.formatDateTime(new Date, new Object) + property string err_dateTime1: Qt.formatDateTime() + property string err_dateTime2: Qt.formatDateTime(new Date, new Object) } diff --git a/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro b/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro index 71ff8a8..4b197eb 100644 --- a/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro +++ b/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro @@ -1,5 +1,5 @@ load(qttest_p4) -contains(QT_CONFIG,declarative): QT += declarative +contains(QT_CONFIG,declarative): QT += declarative script SOURCES += tst_qdeclarativeqt.cpp macx:CONFIG -= app_bundle diff --git a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp index bd9d01f..80d9d93 100644 --- a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp +++ b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp @@ -38,6 +38,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include <private/qdeclarativeengine_p.h> #include <qtest.h> #include <QDebug> @@ -81,7 +82,8 @@ private slots: void createComponent_pragmaLibrary(); void createQmlObject(); void consoleLog(); - void formatting(); + void dateTimeFormatting(); + void dateTimeFormatting_data(); void isQtObject(); void btoa(); void atob(); @@ -446,49 +448,88 @@ void tst_qdeclarativeqt::consoleLog() delete object; } -void tst_qdeclarativeqt::formatting() +void tst_qdeclarativeqt::dateTimeFormatting() { - QDeclarativeComponent component(&engine, TEST_FILE("formatting.qml")); + QFETCH(QString, method); + QFETCH(QStringList, inputProperties); + QFETCH(QStringList, expectedResults); - QString warning1 = component.url().toString() + ":22: Error: Qt.formatDate(): Invalid date format"; - QString warning2 = component.url().toString() + ":21: Error: Qt.formatDate(): Invalid arguments"; - QString warning3 = component.url().toString() + ":28: Error: Qt.formatDateTime(): Invalid datetime format"; - QString warning4 = component.url().toString() + ":27: Error: Qt.formatDateTime(): Invalid arguments"; - QString warning5 = component.url().toString() + ":25: Error: Qt.formatTime(): Invalid time format"; - QString warning6 = component.url().toString() + ":24: Error: Qt.formatTime(): Invalid arguments"; + QDate date(2008,12,24); + QTime time(14,15,38,200); + QDateTime dateTime(date, time); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1)); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2)); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning3)); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning4)); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning5)); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning6)); + QDeclarativeEngine eng; + + eng.rootContext()->setContextProperty("qdate", date); + eng.rootContext()->setContextProperty("qtime", time); + eng.rootContext()->setContextProperty("qdatetime", dateTime); + + QDeclarativeComponent component(&eng, TEST_FILE("formatting.qml")); + + QStringList warnings; + warnings << component.url().toString() + ":37: Error: Qt.formatDate(): Invalid date format" + << component.url().toString() + ":36: Error: Qt.formatDate(): Invalid arguments" + << component.url().toString() + ":40: Error: Qt.formatTime(): Invalid time format" + << component.url().toString() + ":39: Error: Qt.formatTime(): Invalid arguments" + << component.url().toString() + ":43: Error: Qt.formatDateTime(): Invalid datetime format" + << component.url().toString() + ":42: Error: Qt.formatDateTime(): Invalid arguments"; + + foreach (const QString &warning, warnings) + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); QObject *object = component.create(); + QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString())); QVERIFY(object != 0); - QDate date1(2008,12,24); - QCOMPARE(object->property("date1").toDate(), date1); - QCOMPARE(object->property("test1").toString(), date1.toString(Qt::DefaultLocaleShortDate)); - QCOMPARE(object->property("test2").toString(), date1.toString(Qt::DefaultLocaleLongDate)); - QCOMPARE(object->property("test3").toString(), date1.toString("ddd MMMM d yy")); - - QTime time1(14,15,38,200); - QCOMPARE(object->property("time1").toTime(), time1); - QCOMPARE(object->property("test4").toString(), time1.toString(Qt::DefaultLocaleShortDate)); - QCOMPARE(object->property("test5").toString(), time1.toString(Qt::DefaultLocaleLongDate)); - QCOMPARE(object->property("test6").toString(), time1.toString("H:m:s a")); - QCOMPARE(object->property("test7").toString(), time1.toString("hh:mm:ss.zzz")); - - QDateTime dateTime1(QDate(1978,03,04),QTime(9,13,54)); - QCOMPARE(object->property("dateTime1").toDateTime(),dateTime1); - QCOMPARE(object->property("test8").toString(), dateTime1.toString(Qt::DefaultLocaleShortDate)); - QCOMPARE(object->property("test9").toString(), dateTime1.toString(Qt::DefaultLocaleLongDate)); - QCOMPARE(object->property("test10").toString(), dateTime1.toString("M/d/yy H:m:s a")); + QVERIFY(inputProperties.count() > 0); + + QVariant result; + foreach(const QString &prop, inputProperties) { + QVERIFY(QMetaObject::invokeMethod(object, method.toUtf8().constData(), + Q_RETURN_ARG(QVariant, result), + Q_ARG(QVariant, prop))); + + QStringList output = result.toStringList(); + for (int i=0; i<output.count(); i++) + QCOMPARE(output[i], expectedResults[i]); + } delete object; } +void tst_qdeclarativeqt::dateTimeFormatting_data() +{ + QTest::addColumn<QString>("method"); + QTest::addColumn<QStringList>("inputProperties"); + QTest::addColumn<QStringList>("expectedResults"); + + QDate date(2008,12,24); + QTime time(14,15,38,200); + QDateTime dateTime(date, time); + + QTest::newRow("formatDate") + << "formatDate" + << (QStringList() << "dateFromString" << "jsdate" << "qdate" << "qdatetime") + << (QStringList() << date.toString(Qt::DefaultLocaleShortDate) + << date.toString(Qt::DefaultLocaleLongDate) + << date.toString("ddd MMMM d yy")); + + QTest::newRow("formatTime") + << "formatTime" + << (QStringList() << "jsdate" << "qtime" << "qdatetime") + << (QStringList() << time.toString(Qt::DefaultLocaleShortDate) + << time.toString(Qt::DefaultLocaleLongDate) + << time.toString("H:m:s a") + << time.toString("hh:mm:ss.zzz")); + + QTest::newRow("formatDateTime") + << "formatDateTime" + << (QStringList() << "jsdate" << "qdatetime") + << (QStringList() << dateTime.toString(Qt::DefaultLocaleShortDate) + << dateTime.toString(Qt::DefaultLocaleLongDate) + << dateTime.toString("M/d/yy H:m:s a")); +} + void tst_qdeclarativeqt::isQtObject() { QDeclarativeComponent component(&engine, TEST_FILE("isQtObject.qml")); diff --git a/tests/auto/declarative/qdeclarativerepeater/data/modelChanged.qml b/tests/auto/declarative/qdeclarativerepeater/data/modelChanged.qml new file mode 100644 index 0000000..0b57d50 --- /dev/null +++ b/tests/auto/declarative/qdeclarativerepeater/data/modelChanged.qml @@ -0,0 +1,26 @@ +import QtQuick 1.1 + +Column { + Repeater { + id: repeater + objectName: "repeater" + + property int itemsCount + property variant itemsFound: [] + + delegate: Rectangle { + color: "red" + width: (index+1)*50 + height: 50 + } + + onModelChanged: { + repeater.itemsCount = repeater.count + var items = [] + for (var i=0; i<repeater.count; i++) + items.push(repeater.itemAt(i)) + repeater.itemsFound = items + } + } +} + diff --git a/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp b/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp index d849d73..ba52987 100644 --- a/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp +++ b/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp @@ -69,9 +69,15 @@ private slots: void numberModel(); void objectList(); void stringList(); - void dataModel(); + void dataModel_adding(); + void dataModel_removing(); + void dataModel_changes(); void itemModel(); + void resetModel(); + void modelChanged(); void properties(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QDeclarativeView *createView(); @@ -186,6 +192,11 @@ void tst_QDeclarativeRepeater::numberModel() QVERIFY(repeater != 0); QCOMPARE(repeater->parentItem()->childItems().count(), 5+1); + QVERIFY(!repeater->itemAt(-1)); + for (int i=0; i<repeater->count(); i++) + QCOMPARE(repeater->itemAt(i), repeater->parentItem()->childItems().at(i)); + QVERIFY(!repeater->itemAt(repeater->count())); + QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties"); QVERIFY(testObject->error() == false); @@ -223,6 +234,17 @@ void tst_QDeclarativeRepeater::objectList() QCOMPARE(repeater->property("errors").toInt(), 0);//If this fails either they are out of order or can't find the object's data QCOMPARE(repeater->property("instantiated").toInt(), 100); + QVERIFY(!repeater->itemAt(-1)); + for (int i=0; i<data.count(); i++) + QCOMPARE(repeater->itemAt(i), repeater->parentItem()->childItems().at(i)); + QVERIFY(!repeater->itemAt(data.count())); + + QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QDeclarativeItem*))); + QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QDeclarativeItem*))); + ctxt->setContextProperty("testData", QVariant::fromValue(data)); + QCOMPARE(addedSpy.count(), data.count()); + QCOMPARE(removedSpy.count(), data.count()); + qDeleteAll(data); delete canvas; } @@ -284,7 +306,69 @@ void tst_QDeclarativeRepeater::stringList() delete canvas; } -void tst_QDeclarativeRepeater::dataModel() +void tst_QDeclarativeRepeater::dataModel_adding() +{ + QDeclarativeView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + TestObject *testObject = new TestObject; + ctxt->setContextProperty("testObject", testObject); + + TestModel testModel; + ctxt->setContextProperty("testData", &testModel); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/repeater2.qml")); + qApp->processEvents(); + + QDeclarativeRepeater *repeater = findItem<QDeclarativeRepeater>(canvas->rootObject(), "repeater"); + QVERIFY(repeater != 0); + QDeclarativeItem *container = findItem<QDeclarativeItem>(canvas->rootObject(), "container"); + QVERIFY(container != 0); + + QVERIFY(!repeater->itemAt(0)); + + QSignalSpy countSpy(repeater, SIGNAL(countChanged())); + QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QDeclarativeItem*))); + + // add to empty model + testModel.addItem("two", "2"); + QCOMPARE(repeater->itemAt(0), container->childItems().at(0)); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(addedSpy.count(), 1); + QCOMPARE(addedSpy.at(0).at(0).toInt(), 0); + QCOMPARE(addedSpy.at(0).at(1).value<QDeclarativeItem*>(), container->childItems().at(0)); + addedSpy.clear(); + + // insert at start + testModel.insertItem(0, "one", "1"); + QCOMPARE(repeater->itemAt(0), container->childItems().at(0)); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(addedSpy.count(), 1); + QCOMPARE(addedSpy.at(0).at(0).toInt(), 0); + QCOMPARE(addedSpy.at(0).at(1).value<QDeclarativeItem*>(), container->childItems().at(0)); + addedSpy.clear(); + + // insert at end + testModel.insertItem(2, "four", "4"); + QCOMPARE(repeater->itemAt(2), container->childItems().at(2)); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(addedSpy.count(), 1); + QCOMPARE(addedSpy.at(0).at(0).toInt(), 2); + QCOMPARE(addedSpy.at(0).at(1).value<QDeclarativeItem*>(), container->childItems().at(2)); + addedSpy.clear(); + + // insert in middle + testModel.insertItem(2, "three", "3"); + QCOMPARE(repeater->itemAt(2), container->childItems().at(2)); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(addedSpy.count(), 1); + QCOMPARE(addedSpy.at(0).at(0).toInt(), 2); + QCOMPARE(addedSpy.at(0).at(1).value<QDeclarativeItem*>(), container->childItems().at(2)); + addedSpy.clear(); + + delete testObject; + delete canvas; +} + +void tst_QDeclarativeRepeater::dataModel_removing() { QDeclarativeView *canvas = createView(); QDeclarativeContext *ctxt = canvas->rootContext(); @@ -295,28 +379,84 @@ void tst_QDeclarativeRepeater::dataModel() testModel.addItem("one", "1"); testModel.addItem("two", "2"); testModel.addItem("three", "3"); + testModel.addItem("four", "4"); + testModel.addItem("five", "5"); ctxt->setContextProperty("testData", &testModel); - canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/repeater2.qml")); qApp->processEvents(); QDeclarativeRepeater *repeater = findItem<QDeclarativeRepeater>(canvas->rootObject(), "repeater"); QVERIFY(repeater != 0); - QDeclarativeItem *container = findItem<QDeclarativeItem>(canvas->rootObject(), "container"); QVERIFY(container != 0); + QCOMPARE(container->childItems().count(), repeater->count()+1); + + QSignalSpy countSpy(repeater, SIGNAL(countChanged())); + QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QDeclarativeItem*))); + + // remove at start + QDeclarativeItem *item = repeater->itemAt(0); + QCOMPARE(item, container->childItems().at(0)); + + testModel.removeItem(0); + QVERIFY(repeater->itemAt(0) != item); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(removedSpy.count(), 1); + QCOMPARE(removedSpy.at(0).at(0).toInt(), 0); + QCOMPARE(removedSpy.at(0).at(1).value<QDeclarativeItem*>(), item); + removedSpy.clear(); + + // remove at end + int lastIndex = testModel.count()-1; + item = repeater->itemAt(lastIndex); + QCOMPARE(item, container->childItems().at(lastIndex)); + + testModel.removeItem(lastIndex); + QVERIFY(repeater->itemAt(lastIndex) != item); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(removedSpy.count(), 1); + QCOMPARE(removedSpy.at(0).at(0).toInt(), lastIndex); + QCOMPARE(removedSpy.at(0).at(1).value<QDeclarativeItem*>(), item); + removedSpy.clear(); + + // remove from middle + item = repeater->itemAt(1); + QCOMPARE(item, container->childItems().at(1)); + + testModel.removeItem(1); + QVERIFY(repeater->itemAt(lastIndex) != item); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(removedSpy.count(), 1); + QCOMPARE(removedSpy.at(0).at(0).toInt(), 1); + QCOMPARE(removedSpy.at(0).at(1).value<QDeclarativeItem*>(), item); + removedSpy.clear(); - QCOMPARE(container->childItems().count(), 4); + delete testObject; + delete canvas; +} - QSignalSpy repeaterSpy(repeater, SIGNAL(countChanged())); - testModel.addItem("four", "4"); - QCOMPARE(container->childItems().count(), 5); - QCOMPARE(repeaterSpy.count(),1); +void tst_QDeclarativeRepeater::dataModel_changes() +{ + QDeclarativeView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + TestObject *testObject = new TestObject; + ctxt->setContextProperty("testObject", testObject); - testModel.removeItem(2); - QCOMPARE(container->childItems().count(), 4); - QCOMPARE(repeaterSpy.count(),2); + TestModel testModel; + testModel.addItem("one", "1"); + testModel.addItem("two", "2"); + testModel.addItem("three", "3"); + + ctxt->setContextProperty("testData", &testModel); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/repeater2.qml")); + qApp->processEvents(); + + QDeclarativeRepeater *repeater = findItem<QDeclarativeRepeater>(canvas->rootObject(), "repeater"); + QVERIFY(repeater != 0); + QDeclarativeItem *container = findItem<QDeclarativeItem>(canvas->rootObject(), "container"); + QVERIFY(container != 0); + QCOMPARE(container->childItems().count(), repeater->count()+1); // Check that model changes are propagated QDeclarativeText *text = findItem<QDeclarativeText>(canvas->rootObject(), "myName", 1); @@ -377,6 +517,93 @@ void tst_QDeclarativeRepeater::itemModel() delete canvas; } +void tst_QDeclarativeRepeater::resetModel() +{ + QDeclarativeView *canvas = createView(); + + QStringList dataA; + for (int i=0; i<10; i++) + dataA << QString::number(i); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testData", dataA); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/repeater1.qml")); + qApp->processEvents(); + QDeclarativeRepeater *repeater = findItem<QDeclarativeRepeater>(canvas->rootObject(), "repeater"); + QVERIFY(repeater != 0); + QDeclarativeItem *container = findItem<QDeclarativeItem>(canvas->rootObject(), "container"); + QVERIFY(container != 0); + + QCOMPARE(repeater->count(), dataA.count()); + for (int i=0; i<repeater->count(); i++) + QCOMPARE(repeater->itemAt(i), container->childItems().at(i+1)); // +1 to skip first Text object + + QSignalSpy modelChangedSpy(repeater, SIGNAL(modelChanged())); + QSignalSpy countSpy(repeater, SIGNAL(countChanged())); + QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QDeclarativeItem*))); + QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QDeclarativeItem*))); + + QStringList dataB; + for (int i=0; i<20; i++) + dataB << QString::number(i); + + // reset context property + ctxt->setContextProperty("testData", dataB); + QCOMPARE(repeater->count(), dataB.count()); + + QCOMPARE(modelChangedSpy.count(), 1); + QCOMPARE(countSpy.count(), 1); + QCOMPARE(removedSpy.count(), dataA.count()); + QCOMPARE(addedSpy.count(), dataB.count()); + for (int i=0; i<dataB.count(); i++) { + QCOMPARE(addedSpy.at(i).at(0).toInt(), i); + QCOMPARE(addedSpy.at(i).at(1).value<QDeclarativeItem*>(), repeater->itemAt(i)); + } + modelChangedSpy.clear(); + countSpy.clear(); + removedSpy.clear(); + addedSpy.clear(); + + // reset via setModel() + repeater->setModel(dataA); + QCOMPARE(repeater->count(), dataA.count()); + + QCOMPARE(modelChangedSpy.count(), 1); + QCOMPARE(countSpy.count(), 1); + QCOMPARE(removedSpy.count(), dataB.count()); + QCOMPARE(addedSpy.count(), dataA.count()); + for (int i=0; i<dataA.count(); i++) { + QCOMPARE(addedSpy.at(i).at(0).toInt(), i); + QCOMPARE(addedSpy.at(i).at(1).value<QDeclarativeItem*>(), repeater->itemAt(i)); + } + + delete canvas; +} + +// QTBUG-17156 +void tst_QDeclarativeRepeater::modelChanged() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, TEST_FILE("/modelChanged.qml")); + + QDeclarativeItem *rootObject = qobject_cast<QDeclarativeItem*>(component.create()); + QVERIFY(rootObject); + QDeclarativeRepeater *repeater = findItem<QDeclarativeRepeater>(rootObject, "repeater"); + QVERIFY(repeater); + + repeater->setModel(4); + QCOMPARE(repeater->count(), 4); + QCOMPARE(repeater->property("itemsCount").toInt(), 4); + QCOMPARE(repeater->property("itemsFound").toList().count(), 4); + + repeater->setModel(10); + QCOMPARE(repeater->count(), 10); + QCOMPARE(repeater->property("itemsCount").toInt(), 10); + QCOMPARE(repeater->property("itemsFound").toList().count(), 10); + + delete rootObject; +} + void tst_QDeclarativeRepeater::properties() { QDeclarativeEngine engine; @@ -407,6 +634,50 @@ void tst_QDeclarativeRepeater::properties() delete rootObject; } +void tst_QDeclarativeRepeater::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; Repeater { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; Repeater { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; +} + +void tst_QDeclarativeRepeater::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("itemAdded") << "onItemAdded: count" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Repeater.onItemAdded\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("itemRemoved") << "onItemRemoved: count" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Repeater.onItemRemoved\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("itemAt") << "Component.onCompleted: itemAt(0)" + << "<Unknown File>:1: ReferenceError: Can't find variable: itemAt" + << ""; +} + + QDeclarativeView *tst_QDeclarativeRepeater::createView() { QDeclarativeView *canvas = new QDeclarativeView(0); diff --git a/tests/auto/declarative/qdeclarativetext/data/horizontalAlignment_RightToLeft.qml b/tests/auto/declarative/qdeclarativetext/data/horizontalAlignment_RightToLeft.qml new file mode 100644 index 0000000..4f58944 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetext/data/horizontalAlignment_RightToLeft.qml @@ -0,0 +1,23 @@ +import QtQuick 1.0 + +Rectangle { + id: top + width: 200; height: 70; + + property alias horizontalAlignment: text.horizontalAlignment + property string text: "اختبا" + + Rectangle { + anchors.centerIn: parent + width: 180 + height: 20 + color: "green" + + Text { + id: text + objectName: "text" + anchors.fill: parent + text: top.text + } + } +} diff --git a/tests/auto/declarative/qdeclarativetext/data/lineCount.qml b/tests/auto/declarative/qdeclarativetext/data/lineCount.qml new file mode 100644 index 0000000..63817f6 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetext/data/lineCount.qml @@ -0,0 +1,15 @@ +import QtQuick 1.1 + +Item { + width: 200 + height: 200 + + Text { + id: myText + objectName: "myText" + width: 200 + wrapMode: Text.WordWrap + maximumLineCount: undefined + text: "Testing that maximumLines, visibleLines, and totalLines works properly in the autotests. The quick brown fox jumped over the lazy anything with the letter 'g'." + } +} diff --git a/tests/auto/declarative/qdeclarativetext/data/lineHeight.qml b/tests/auto/declarative/qdeclarativetext/data/lineHeight.qml new file mode 100644 index 0000000..851d871 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetext/data/lineHeight.qml @@ -0,0 +1,15 @@ +import QtQuick 1.1 + +Item { + width: 200 + height: 200 + + Text { + id: myText + objectName: "myText" + width: 200 + wrapMode: Text.WordWrap + font.pixelSize: 13 + text: "Lorem ipsum sit amet, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum." + } +} diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index 480dba5..a3bba3b 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -43,12 +43,14 @@ #include <QtDeclarative/qdeclarativeengine.h> #include <QtDeclarative/qdeclarativecomponent.h> #include <private/qdeclarativetext_p.h> +#include <private/qdeclarativetext_p_p.h> #include <private/qdeclarativevaluetype_p.h> #include <QFontMetrics> #include <QGraphicsSceneMouseEvent> #include <qmath.h> #include <QDeclarativeView> #include <private/qapplication_p.h> +#include <limits.h> #include "../../../shared/util.h" #include "testhttpserver.h" @@ -78,8 +80,12 @@ private slots: void embeddedImages_data(); void embeddedImages(); + void lineCount(); + void lineHeight(); + // ### these tests may be trivial void horizontalAlignment(); + void horizontalAlignment_RightToLeft(); void verticalAlignment(); void font(); void style(); @@ -98,6 +104,10 @@ private slots: void clickLink(); void QTBUG_12291(); + void implicitSize_data(); + void implicitSize(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QStringList standard; @@ -460,6 +470,8 @@ void tst_qdeclarativetext::alignments() QCOMPARE(actual,expect); } #endif + + delete canvas; } //the alignment tests may be trivial o.oa @@ -495,6 +507,32 @@ void tst_qdeclarativetext::horizontalAlignment() } +void tst_qdeclarativetext::horizontalAlignment_RightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml"); + QDeclarativeText *text = canvas->rootObject()->findChild<QDeclarativeText*>("text"); + QVERIFY(text != 0); + canvas->show(); + + QDeclarativeTextPrivate *textPrivate = QDeclarativeTextPrivate::get(text); + QVERIFY(textPrivate != 0); + + QVERIFY(textPrivate->layout.lineAt(0).x() > canvas->width()/2); + + // "Right" aligned + text->setHAlign(QDeclarativeText::AlignRight); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignRight); + QVERIFY(textPrivate->layout.lineAt(0).x() < canvas->width()/2); + + // Center aligned + text->setHAlign(QDeclarativeText::AlignHCenter); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignHCenter); + QVERIFY(textPrivate->layout.lineAt(0).x() < canvas->width()/2); + QVERIFY(textPrivate->layout.lineAt(0).x() + textPrivate->layout.lineAt(0).width() > canvas->width()/2); + + delete canvas; +} + void tst_qdeclarativetext::verticalAlignment() { //test one align each, and then test if two align fails. @@ -926,6 +964,8 @@ void tst_qdeclarativetext::QTBUG_12291() QDeclarativeText *text = ob->findChild<QDeclarativeText*>("text"); QVERIFY(text); QVERIFY(text->boundingRect().isValid()); + + delete canvas; } class EventSender : public QGraphicsItem @@ -1018,6 +1058,150 @@ void tst_qdeclarativetext::embeddedImages() QCOMPARE(textObject->width(), 16.0); // default size of QTextDocument broken image icon QCOMPARE(textObject->height(), 16.0); } + + delete textObject; +} + +void tst_qdeclarativetext::lineCount() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/lineCount.qml"); + + QDeclarativeText *myText = canvas->rootObject()->findChild<QDeclarativeText*>("myText"); + QVERIFY(myText != 0); + + QVERIFY(myText->lineCount() > 1); + QVERIFY(!myText->truncated()); + QCOMPARE(myText->maximumLineCount(), INT_MAX); + + myText->setMaximumLineCount(2); + QCOMPARE(myText->lineCount(), 2); + QCOMPARE(myText->truncated(), true); + QCOMPARE(myText->maximumLineCount(), 2); + + myText->resetMaximumLineCount(); + QCOMPARE(myText->maximumLineCount(), INT_MAX); + QCOMPARE(myText->truncated(), false); + + myText->setElideMode(QDeclarativeText::ElideRight); + myText->setMaximumLineCount(2); + QCOMPARE(myText->lineCount(), 2); + QCOMPARE(myText->truncated(), true); + QCOMPARE(myText->maximumLineCount(), 2); + + delete canvas; +} + +void tst_qdeclarativetext::lineHeight() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/lineHeight.qml"); + + QDeclarativeText *myText = canvas->rootObject()->findChild<QDeclarativeText*>("myText"); + QVERIFY(myText != 0); + + QVERIFY(myText->lineHeight() == 1); + QVERIFY(myText->lineHeightMode() == QDeclarativeText::ProportionalHeight); + + qreal h = myText->height(); + myText->setLineHeight(1.5); + QVERIFY(myText->height() == h * 1.5); + + myText->setLineHeightMode(QDeclarativeText::FixedHeight); + myText->setLineHeight(20); + QCOMPARE(myText->height(), myText->lineCount() * 20.0); + + myText->setText("Lorem ipsum sit <b>amet</b>, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum."); + myText->setLineHeightMode(QDeclarativeText::ProportionalHeight); + myText->setLineHeight(1.0); + + qreal h2 = myText->height(); + myText->setLineHeight(2.0); + QEXPECT_FAIL("", "QTBUG-17325", Continue); + QVERIFY(myText->height() == h2 * 2.0); + + myText->setLineHeightMode(QDeclarativeText::FixedHeight); + myText->setLineHeight(10); + QEXPECT_FAIL("", "QTBUG-17325", Continue); + QCOMPARE(myText->height(), myText->lineCount() * 10.0); + + delete canvas; +} + +void tst_qdeclarativetext::implicitSize_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<QString>("wrap"); + QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "Text.NoWrap"; + QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "Text.NoWrap"; + QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "Text.Wrap"; + QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "Text.Wrap"; +} + +void tst_qdeclarativetext::implicitSize() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QString componentStr = "import QtQuick 1.1\nText { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeText *textObject = qobject_cast<QDeclarativeText*>(textComponent.create()); + + QVERIFY(textObject->width() < textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); + + textObject->resetWidth(); + QVERIFY(textObject->width() == textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); +} + +void tst_qdeclarativetext::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; Text { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; Text { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_qdeclarativetext::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("maximumLineCount") << "maximumLineCount: 4" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Text.maximumLineCount\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("lineHeight") << "lineHeight: 2" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Text.lineHeight\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("lineHeightMode") << "lineHeightMode: Text.ProportionalHeight" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Text.lineHeightMode\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("lineCount") << "property int foo: lineCount" + << "<Unknown File>:1: ReferenceError: Can't find variable: lineCount" + << ""; + + QTest::newRow("truncated") << "property bool foo: truncated" + << "<Unknown File>:1: ReferenceError: Can't find variable: truncated" + << ""; } QTEST_MAIN(tst_qdeclarativetext) diff --git a/tests/auto/declarative/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml b/tests/auto/declarative/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml new file mode 100644 index 0000000..43ea8d8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml @@ -0,0 +1,23 @@ +import QtQuick 1.0 + +Rectangle { + id: top + width: 200; height: 70; + + property alias horizontalAlignment: text.horizontalAlignment + property string text: "اختبا" + + Rectangle { + anchors.centerIn: parent + width: 200 + height: 20 + color: "green" + + TextEdit { + id: text + objectName: "text" + anchors.fill: parent + text: top.text + } + } +} diff --git a/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_characters.qml b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_characters.qml new file mode 100644 index 0000000..5784e19 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_characters.qml @@ -0,0 +1,8 @@ +import QtQuick 1.1 + +TextEdit { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true + mouseSelectionMode: TextEdit.SelectCharacters +} diff --git a/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_default.qml b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_default.qml new file mode 100644 index 0000000..1e5f4aa --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_default.qml @@ -0,0 +1,7 @@ +import QtQuick 1.1 + +TextEdit { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true +} diff --git a/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_words.qml b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_words.qml new file mode 100644 index 0000000..4b25f2f --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_words.qml @@ -0,0 +1,8 @@ +import QtQuick 1.1 + +TextEdit { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true + mouseSelectionMode: TextEdit.SelectWords +} diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index ba1a95f..7d5101c 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -66,6 +66,8 @@ #define SRCDIR "." #endif +Q_DECLARE_METATYPE(QDeclarativeTextEdit::SelectionMode) + QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual) { // XXX This will be replaced by some clever persistent platform image store. @@ -100,6 +102,7 @@ private slots: // ### these tests may be trivial void hAlign(); + void hAlign_RightToLeft(); void vAlign(); void font(); void color(); @@ -107,8 +110,15 @@ private slots: void persistentSelection(); void focusOnPress(); void selection(); + void moveCursorSelection_data(); + void moveCursorSelection(); + void moveCursorSelectionSequence_data(); + void moveCursorSelectionSequence(); void mouseSelection_data(); void mouseSelection(); + void mouseSelectionMode_data(); + void mouseSelectionMode(); + void dragMouseSelection(); void inputMethodHints(); void cursorDelegate(); @@ -122,6 +132,10 @@ private slots: void openInputPanelOnFocus(); void geometrySignals(); void pastingRichText_QTBUG_14003(); + void implicitSize_data(); + void implicitSize(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: void simulateKey(QDeclarativeView *, int key); @@ -144,7 +158,9 @@ private: tst_qdeclarativetextedit::tst_qdeclarativetextedit() { standard << "the quick brown fox jumped over the lazy dog" - << "the quick brown fox\n jumped over the lazy dog"; + << "the quick brown fox\n jumped over the lazy dog" + << "Hello, world!" + << "!dlrow ,olleH"; richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>" << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>"; @@ -413,6 +429,30 @@ void tst_qdeclarativetextedit::hAlign() } +void tst_qdeclarativetextedit::hAlign_RightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml"); + QDeclarativeTextEdit *textEdit = canvas->rootObject()->findChild<QDeclarativeTextEdit*>("text"); + QVERIFY(textEdit != 0); + canvas->show(); + + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + + // "Right" align + textEdit->setHAlign(QDeclarativeTextEdit::AlignRight); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignRight); + QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2); + + // Center align + // Note that position 0 is on the right-hand side + textEdit->setHAlign(QDeclarativeTextEdit::AlignHCenter); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignHCenter); + QVERIFY(textEdit->positionToRectangle(0).x() - textEdit->width() < canvas->width()/2); + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + + delete canvas; +} + void tst_qdeclarativetextedit::vAlign() { //test one align each, and then test if two align fails. @@ -704,8 +744,351 @@ void tst_qdeclarativetextedit::selection() QVERIFY(textEditObject->selectedText().size() == 10); textEditObject->select(0,100); QVERIFY(textEditObject->selectedText().size() == 10); + + textEditObject->deselect(); + QVERIFY(textEditObject->selectedText().isNull()); + textEditObject->select(0,10); + QVERIFY(textEditObject->selectedText().size() == 10); + textEditObject->deselect(); + QVERIFY(textEditObject->selectedText().isNull()); +} + +void tst_qdeclarativetextedit::moveCursorSelection_data() +{ + QTest::addColumn<QString>("testStr"); + QTest::addColumn<int>("cursorPosition"); + QTest::addColumn<int>("movePosition"); + QTest::addColumn<QDeclarativeTextEdit::SelectionMode>("mode"); + QTest::addColumn<int>("selectionStart"); + QTest::addColumn<int>("selectionEnd"); + QTest::addColumn<bool>("reversible"); + + QTest::newRow("(t)he|characters") + << standard[0] << 0 << 1 << QDeclarativeTextEdit::SelectCharacters << 0 << 1 << true; + QTest::newRow("do(g)|characters") + << standard[0] << 43 << 44 << QDeclarativeTextEdit::SelectCharacters << 43 << 44 << true; + QTest::newRow("jum(p)ed|characters") + << standard[0] << 23 << 24 << QDeclarativeTextEdit::SelectCharacters << 23 << 24 << true; + QTest::newRow("jumped( )over|characters") + << standard[0] << 26 << 27 << QDeclarativeTextEdit::SelectCharacters << 26 << 27 << true; + QTest::newRow("(the )|characters") + << standard[0] << 0 << 4 << QDeclarativeTextEdit::SelectCharacters << 0 << 4 << true; + QTest::newRow("( dog)|characters") + << standard[0] << 40 << 44 << QDeclarativeTextEdit::SelectCharacters << 40 << 44 << true; + QTest::newRow("( jumped )|characters") + << standard[0] << 19 << 27 << QDeclarativeTextEdit::SelectCharacters << 19 << 27 << true; + QTest::newRow("th(e qu)ick|characters") + << standard[0] << 2 << 6 << QDeclarativeTextEdit::SelectCharacters << 2 << 6 << true; + QTest::newRow("la(zy d)og|characters") + << standard[0] << 38 << 42 << QDeclarativeTextEdit::SelectCharacters << 38 << 42 << true; + QTest::newRow("jum(ped ov)er|characters") + << standard[0] << 23 << 29 << QDeclarativeTextEdit::SelectCharacters << 23 << 29 << true; + QTest::newRow("()the|characters") + << standard[0] << 0 << 0 << QDeclarativeTextEdit::SelectCharacters << 0 << 0 << true; + QTest::newRow("dog()|characters") + << standard[0] << 44 << 44 << QDeclarativeTextEdit::SelectCharacters << 44 << 44 << true; + QTest::newRow("jum()ped|characters") + << standard[0] << 23 << 23 << QDeclarativeTextEdit::SelectCharacters << 23 << 23 << true; + + QTest::newRow("<(t)he>|words") + << standard[0] << 0 << 1 << QDeclarativeTextEdit::SelectWords << 0 << 3 << true; + QTest::newRow("<do(g)>|words") + << standard[0] << 43 << 44 << QDeclarativeTextEdit::SelectWords << 41 << 44 << true; + QTest::newRow("<jum(p)ed>|words") + << standard[0] << 23 << 24 << QDeclarativeTextEdit::SelectWords << 20 << 26 << true; + QTest::newRow("<jumped( )>over|words") + << standard[0] << 26 << 27 << QDeclarativeTextEdit::SelectWords << 20 << 27 << false; + QTest::newRow("jumped<( )over>|words,reversed") + << standard[0] << 27 << 26 << QDeclarativeTextEdit::SelectWords << 26 << 31 << false; + QTest::newRow("<(the )>quick|words") + << standard[0] << 0 << 4 << QDeclarativeTextEdit::SelectWords << 0 << 4 << false; + QTest::newRow("<(the )quick>|words,reversed") + << standard[0] << 4 << 0 << QDeclarativeTextEdit::SelectWords << 0 << 9 << false; + QTest::newRow("<lazy( dog)>|words") + << standard[0] << 40 << 44 << QDeclarativeTextEdit::SelectWords << 36 << 44 << false; + QTest::newRow("lazy<( dog)>|words,reversed") + << standard[0] << 44 << 40 << QDeclarativeTextEdit::SelectWords << 40 << 44 << false; + QTest::newRow("<fox( jumped )>over|words") + << standard[0] << 19 << 27 << QDeclarativeTextEdit::SelectWords << 16 << 27 << false; + QTest::newRow("fox<( jumped )over>|words,reversed") + << standard[0] << 27 << 19 << QDeclarativeTextEdit::SelectWords << 19 << 31 << false; + QTest::newRow("<th(e qu)ick>|words") + << standard[0] << 2 << 6 << QDeclarativeTextEdit::SelectWords << 0 << 9 << true; + QTest::newRow("<la(zy d)og|words>") + << standard[0] << 38 << 42 << QDeclarativeTextEdit::SelectWords << 36 << 44 << true; + QTest::newRow("<jum(ped ov)er>|words") + << standard[0] << 23 << 29 << QDeclarativeTextEdit::SelectWords << 20 << 31 << true; + QTest::newRow("<()>the|words") + << standard[0] << 0 << 0 << QDeclarativeTextEdit::SelectWords << 0 << 0 << true; + QTest::newRow("dog<()>|words") + << standard[0] << 44 << 44 << QDeclarativeTextEdit::SelectWords << 44 << 44 << true; + QTest::newRow("jum<()>ped|words") + << standard[0] << 23 << 23 << QDeclarativeTextEdit::SelectWords << 23 << 23 << true; + + QTest::newRow("Hello<(,)> |words") + << standard[2] << 5 << 6 << QDeclarativeTextEdit::SelectWords << 5 << 6 << true; + QTest::newRow("Hello<(, )>world|words") + << standard[2] << 5 << 7 << QDeclarativeTextEdit::SelectWords << 5 << 7 << false; + QTest::newRow("Hello<(, )world>|words,reversed") + << standard[2] << 7 << 5 << QDeclarativeTextEdit::SelectWords << 5 << 12 << false; + QTest::newRow("<Hel(lo, )>world|words") + << standard[2] << 3 << 7 << QDeclarativeTextEdit::SelectWords << 0 << 7 << false; + QTest::newRow("<Hel(lo, )world>|words,reversed") + << standard[2] << 7 << 3 << QDeclarativeTextEdit::SelectWords << 0 << 12 << false; + QTest::newRow("<Hel(lo)>,|words") + << standard[2] << 3 << 5 << QDeclarativeTextEdit::SelectWords << 0 << 5 << true; + QTest::newRow("Hello<()>,|words") + << standard[2] << 5 << 5 << QDeclarativeTextEdit::SelectWords << 5 << 5 << true; + QTest::newRow("Hello,<()>|words") + << standard[2] << 6 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 6 << true; + QTest::newRow("Hello<,( )>world|words") + << standard[2] << 6 << 7 << QDeclarativeTextEdit::SelectWords << 5 << 7 << false; + QTest::newRow("Hello,<( )world>|words,reversed") + << standard[2] << 7 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 12 << false; + QTest::newRow("Hello<,( world)>|words") + << standard[2] << 6 << 12 << QDeclarativeTextEdit::SelectWords << 5 << 12 << false; + QTest::newRow("Hello,<( world)>|words,reversed") + << standard[2] << 12 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 12 << false; + QTest::newRow("Hello<,( world!)>|words") + << standard[2] << 6 << 13 << QDeclarativeTextEdit::SelectWords << 5 << 13 << false; + QTest::newRow("Hello,<( world!)>|words,reversed") + << standard[2] << 13 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 13 << false; + QTest::newRow("Hello<(, world!)>|words") + << standard[2] << 5 << 13 << QDeclarativeTextEdit::SelectWords << 5 << 13 << true; + QTest::newRow("world<(!)>|words") + << standard[2] << 12 << 13 << QDeclarativeTextEdit::SelectWords << 12 << 13 << true; + QTest::newRow("world!<()>)|words") + << standard[2] << 13 << 13 << QDeclarativeTextEdit::SelectWords << 13 << 13 << true; + QTest::newRow("world<()>!)|words") + << standard[2] << 12 << 12 << QDeclarativeTextEdit::SelectWords << 12 << 12 << true; + + QTest::newRow("<(,)>olleH |words") + << standard[3] << 7 << 8 << QDeclarativeTextEdit::SelectWords << 7 << 8 << true; + QTest::newRow("<dlrow( ,)>olleH|words") + << standard[3] << 6 << 8 << QDeclarativeTextEdit::SelectWords << 1 << 8 << false; + QTest::newRow("dlrow<( ,)>olleH|words,reversed") + << standard[3] << 8 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 8 << false; + QTest::newRow("<dlrow( ,ol)leH>|words") + << standard[3] << 6 << 10 << QDeclarativeTextEdit::SelectWords << 1 << 13 << false; + QTest::newRow("dlrow<( ,ol)leH>|words,reversed") + << standard[3] << 10 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 13 << false; + QTest::newRow(",<(ol)leH>,|words") + << standard[3] << 8 << 10 << QDeclarativeTextEdit::SelectWords << 8 << 13 << true; + QTest::newRow(",<()>olleH|words") + << standard[3] << 8 << 8 << QDeclarativeTextEdit::SelectWords << 8 << 8 << true; + QTest::newRow("<()>,olleH|words") + << standard[3] << 7 << 7 << QDeclarativeTextEdit::SelectWords << 7 << 7 << true; + QTest::newRow("<dlrow( )>,olleH|words") + << standard[3] << 6 << 7 << QDeclarativeTextEdit::SelectWords << 1 << 7 << false; + QTest::newRow("dlrow<( ),>olleH|words,reversed") + << standard[3] << 7 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 8 << false; + QTest::newRow("<(dlrow )>,olleH|words") + << standard[3] << 1 << 7 << QDeclarativeTextEdit::SelectWords << 1 << 7 << false; + QTest::newRow("<(dlrow ),>olleH|words,reversed") + << standard[3] << 7 << 1 << QDeclarativeTextEdit::SelectWords << 1 << 8 << false; + QTest::newRow("<(!dlrow )>,olleH|words") + << standard[3] << 0 << 7 << QDeclarativeTextEdit::SelectWords << 0 << 7 << false; + QTest::newRow("<(!dlrow ),>olleH|words,reversed") + << standard[3] << 7 << 0 << QDeclarativeTextEdit::SelectWords << 0 << 8 << false; + QTest::newRow("(!dlrow ,)olleH|words") + << standard[3] << 0 << 8 << QDeclarativeTextEdit::SelectWords << 0 << 8 << true; + QTest::newRow("<(!)>dlrow|words") + << standard[3] << 0 << 1 << QDeclarativeTextEdit::SelectWords << 0 << 1 << true; + QTest::newRow("<()>!dlrow|words") + << standard[3] << 0 << 0 << QDeclarativeTextEdit::SelectWords << 0 << 0 << true; + QTest::newRow("!<()>dlrow|words") + << standard[3] << 1 << 1 << QDeclarativeTextEdit::SelectWords << 1 << 1 << true; +} + +void tst_qdeclarativetextedit::moveCursorSelection() +{ + QFETCH(QString, testStr); + QFETCH(int, cursorPosition); + QFETCH(int, movePosition); + QFETCH(QDeclarativeTextEdit::SelectionMode, mode); + QFETCH(int, selectionStart); + QFETCH(int, selectionEnd); + QFETCH(bool, reversible); + + QString componentStr = "import QtQuick 1.1\nTextEdit { text: \""+ testStr +"\"; }"; + QDeclarativeComponent textinputComponent(&engine); + textinputComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextEdit *texteditObject = qobject_cast<QDeclarativeTextEdit*>(textinputComponent.create()); + QVERIFY(texteditObject != 0); + + texteditObject->setCursorPosition(cursorPosition); + texteditObject->moveCursorSelection(movePosition, mode); + + QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart)); + QCOMPARE(texteditObject->selectionStart(), selectionStart); + QCOMPARE(texteditObject->selectionEnd(), selectionEnd); + + if (reversible) { + texteditObject->setCursorPosition(movePosition); + texteditObject->moveCursorSelection(cursorPosition, mode); + + QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart)); + QCOMPARE(texteditObject->selectionStart(), selectionStart); + QCOMPARE(texteditObject->selectionEnd(), selectionEnd); + } +} + +void tst_qdeclarativetextedit::moveCursorSelectionSequence_data() +{ + QTest::addColumn<QString>("testStr"); + QTest::addColumn<int>("cursorPosition"); + QTest::addColumn<int>("movePosition1"); + QTest::addColumn<int>("movePosition2"); + QTest::addColumn<int>("selection1Start"); + QTest::addColumn<int>("selection1End"); + QTest::addColumn<int>("selection2Start"); + QTest::addColumn<int>("selection2End"); + + QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr") + << standard[0] + << 9 << 13 << 17 + << 4 << 15 + << 4 << 19; + QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl") + << standard[0] + << 13 << 9 << 17 + << 9 << 15 + << 10 << 19; + QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr") + << standard[0] + << 9 << 13 << 16 + << 4 << 15 + << 4 << 16; + QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl") + << standard[0] + << 13 << 9 << 16 + << 9 << 15 + << 10 << 16; + QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr") + << standard[0] + << 9 << 13 << 15 + << 4 << 15 + << 4 << 15; + QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl") + << standard[0] + << 13 << 9 << 15 + << 9 << 15 + << 10 << 15; + QTest::newRow("the {<quick() ^}bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 10 + << 4 << 15 + << 4 << 10; + QTest::newRow("the quick<(^ {^bro)wn>} fox|rtl") + << standard[0] + << 13 << 9 << 10 + << 9 << 15 + << 10 << 15; + QTest::newRow("the {<quick^}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 9 + << 4 << 15 + << 4 << 9; + QTest::newRow("the quick{<(^ bro)wn>} fox|rtl") + << standard[0] + << 13 << 9 << 9 + << 9 << 15 + << 9 << 15; + QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 7 + << 4 << 15 + << 4 << 9; + QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl") + << standard[0] + << 13 << 9 << 7 + << 9 << 15 + << 4 << 15; + QTest::newRow("the {<^quick}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 4 + << 4 << 15 + << 4 << 9; + QTest::newRow("the {<^quick}( bro)wn> fox|rtl") + << standard[0] + << 13 << 9 << 4 + << 9 << 15 + << 4 << 15; + QTest::newRow("the{^ <quick}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 3 + << 4 << 15 + << 3 << 9; + QTest::newRow("the{^ <quick}( bro)wn> fox|rtl") + << standard[0] + << 13 << 9 << 3 + << 9 << 15 + << 3 << 15; + QTest::newRow("{t^he <quick}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 1 + << 4 << 15 + << 0 << 9; + QTest::newRow("{t^he <quick}( bro)wn> fox|rtl") + << standard[0] + << 13 << 9 << 1 + << 9 << 15 + << 0 << 15; + + QTest::newRow("{<He(ll)o>, w^orld}!|ltr") + << standard[2] + << 2 << 4 << 8 + << 0 << 5 + << 0 << 12; + QTest::newRow("{<He(ll)o>, w^orld}!|rtl") + << standard[2] + << 4 << 2 << 8 + << 0 << 5 + << 0 << 12; + + QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr") + << standard[3] + << 9 << 11 << 5 + << 8 << 13 + << 1 << 13; + QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl") + << standard[3] + << 11 << 9 << 5 + << 8 << 13 + << 1 << 13; +} + +void tst_qdeclarativetextedit::moveCursorSelectionSequence() +{ + QFETCH(QString, testStr); + QFETCH(int, cursorPosition); + QFETCH(int, movePosition1); + QFETCH(int, movePosition2); + QFETCH(int, selection1Start); + QFETCH(int, selection1End); + QFETCH(int, selection2Start); + QFETCH(int, selection2End); + + QString componentStr = "import QtQuick 1.1\nTextEdit { text: \""+ testStr +"\"; }"; + QDeclarativeComponent texteditComponent(&engine); + texteditComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextEdit *texteditObject = qobject_cast<QDeclarativeTextEdit*>(texteditComponent.create()); + QVERIFY(texteditObject != 0); + + texteditObject->setCursorPosition(cursorPosition); + + texteditObject->moveCursorSelection(movePosition1, QDeclarativeTextEdit::SelectWords); + QCOMPARE(texteditObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start)); + QCOMPARE(texteditObject->selectionStart(), selection1Start); + QCOMPARE(texteditObject->selectionEnd(), selection1End); + + texteditObject->moveCursorSelection(movePosition2, QDeclarativeTextEdit::SelectWords); + QCOMPARE(texteditObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start)); + QCOMPARE(texteditObject->selectionStart(), selection2Start); + QCOMPARE(texteditObject->selectionEnd(), selection2End); } + void tst_qdeclarativetextedit::mouseSelection_data() { QTest::addColumn<QString>("qmlfile"); @@ -751,6 +1134,100 @@ void tst_qdeclarativetextedit::mouseSelection() delete canvas; } +void tst_qdeclarativetextedit::dragMouseSelection() +{ + QString qmlfile = SRCDIR "/data/mouseselection_true.qml"; + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit *>(canvas->rootObject()); + QVERIFY(textEditObject != 0); + + textEditObject->setAcceptDrops(true); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textEditObject->height()/2; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QString str1 = textEditObject->selectedText(); + QVERIFY(str1.length() > 3); + + // press and drag the current selection. + x1 = 40; + x2 = 100; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QString str2 = textEditObject->selectedText(); + QVERIFY(str2.length() > 3); + + QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved. +} + +void tst_qdeclarativetextedit::mouseSelectionMode_data() +{ + QTest::addColumn<QString>("qmlfile"); + QTest::addColumn<bool>("selectWords"); + + // import installed + QTest::newRow("SelectWords") << SRCDIR "/data/mouseselectionmode_words.qml" << true; + QTest::newRow("SelectCharacters") << SRCDIR "/data/mouseselectionmode_characters.qml" << false; + QTest::newRow("default") << SRCDIR "/data/mouseselectionmode_default.qml" << false; +} + +void tst_qdeclarativetextedit::mouseSelectionMode() +{ + QFETCH(QString, qmlfile); + QFETCH(bool, selectWords); + + QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit *>(canvas->rootObject()); + QVERIFY(textEditObject != 0); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textEditObject->height()/2; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QString str = textEditObject->selectedText(); + if (selectWords) { + QCOMPARE(str, text); + } else { + QVERIFY(str.length() > 3); + QVERIFY(str != text); + } + + delete canvas; +} + void tst_qdeclarativetextedit::inputMethodHints() { QDeclarativeView *canvas = createView(SRCDIR "/data/inputmethodhints.qml"); @@ -906,10 +1383,18 @@ void tst_qdeclarativetextedit::copyAndPaste() { QCOMPARE(textEdit->selectedText(), QString("Hello world!")); QCOMPARE(textEdit->selectedText().length(), 12); textEdit->setCursorPosition(0); + QVERIFY(textEdit->canPaste()); textEdit->paste(); QCOMPARE(textEdit->text(), QString("Hello world!Hello world!")); QCOMPARE(textEdit->text().length(), 24); + // canPaste + QVERIFY(textEdit->canPaste()); + textEdit->setReadOnly(true); + QVERIFY(!textEdit->canPaste()); + textEdit->setReadOnly(false); + QVERIFY(textEdit->canPaste()); + // QTBUG-12339 // test that document and internal text attribute are in sync QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(textEdit); @@ -1191,6 +1676,16 @@ void tst_qdeclarativetextedit::openInputPanelOnFocus() QApplication::processEvents(); QVERIFY(view.inputContext() == 0); QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); + + // input method should not be enabled + // if TextEdit is read only. + edit.setReadOnly(true); + ic.openInputPanelReceived = false; + edit.setFocus(true); + QApplication::processEvents(); + QCOMPARE(ic.openInputPanelReceived, false); + QVERIFY(view.inputContext() == 0); + QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); } void tst_qdeclarativetextedit::geometrySignals() @@ -1224,6 +1719,84 @@ void tst_qdeclarativetextedit::pastingRichText_QTBUG_14003() #endif } +void tst_qdeclarativetextedit::implicitSize_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<QString>("wrap"); + QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap"; + QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap"; + QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap"; + QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap"; +} + +void tst_qdeclarativetextedit::implicitSize() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QString componentStr = "import QtQuick 1.1\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeTextEdit *textObject = qobject_cast<QDeclarativeTextEdit*>(textComponent.create()); + + QVERIFY(textObject->width() < textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); + + textObject->resetWidth(); + QVERIFY(textObject->width() == textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); +} + +void tst_qdeclarativetextedit::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; TextEdit { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; TextEdit { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_qdeclarativetextedit::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("canPaste") << "property bool foo: canPaste" + << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste" + << ""; + + QTest::newRow("lineCount") << "property int foo: lineCount" + << "<Unknown File>:1: ReferenceError: Can't find variable: lineCount" + << ""; + + QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)" + << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection" + << ""; + + QTest::newRow("deselect") << "Component.onCompleted: deselect()" + << "<Unknown File>:1: ReferenceError: Can't find variable: deselect" + << ""; + + QTest::newRow("onLinkActivated") << "onLinkActivated: {}" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"TextEdit.onLinkActivated\" is not available in QtQuick 1.0.\n"; +} + QTEST_MAIN(tst_qdeclarativetextedit) #include "tst_qdeclarativetextedit.moc" diff --git a/tests/auto/declarative/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml b/tests/auto/declarative/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml new file mode 100644 index 0000000..b11535e --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml @@ -0,0 +1,23 @@ +import QtQuick 1.0 + +Rectangle { + id: top + width: 200; height: 70; + + property alias horizontalAlignment: text.horizontalAlignment + property string text: "اختبا" + + Rectangle { + anchors.centerIn: parent + width: 180 + height: 20 + color: "green" + + TextInput { + id: text + objectName: "text" + anchors.fill: parent + text: top.text + } + } +} diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true.qml new file mode 100644 index 0000000..8115ba0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true +} diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_characters.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_characters.qml new file mode 100644 index 0000000..0ffc6ff --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_characters.qml @@ -0,0 +1,8 @@ +import QtQuick 1.1 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true + mouseSelectionMode: TextInput.SelectCharacters +} diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_default.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_default.qml new file mode 100644 index 0000000..87c174b --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_default.qml @@ -0,0 +1,7 @@ +import QtQuick 1.1 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true +} diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_words.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_words.qml new file mode 100644 index 0000000..df69a7d --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_words.qml @@ -0,0 +1,8 @@ +import QtQuick 1.1 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true + mouseSelectionMode: TextInput.SelectWords +} diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 4ad055c..a6d30a5 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -57,6 +57,8 @@ #define SRCDIR "." #endif +Q_DECLARE_METATYPE(QDeclarativeTextInput::SelectionMode) + QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual) { // XXX This will be replaced by some clever persistent platform image store. @@ -87,9 +89,17 @@ private slots: void font(); void color(); void selection(); + void moveCursorSelection_data(); + void moveCursorSelection(); + void moveCursorSelectionSequence_data(); + void moveCursorSelectionSequence(); + void dragMouseSelection(); + void mouseSelectionMode_data(); + void mouseSelectionMode(); void horizontalAlignment_data(); void horizontalAlignment(); + void horizontalAlignment_RightToLeft(); void positionAt(); @@ -111,6 +121,11 @@ private slots: void echoMode(); void geometrySignals(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); + + void preeditAutoScroll(); + private: void simulateKey(QDeclarativeView *, int key); QDeclarativeView *createView(const QString &filename); @@ -124,7 +139,8 @@ tst_qdeclarativetextinput::tst_qdeclarativetextinput() { standard << "the quick brown fox jumped over the lazy dog" << "It's supercalifragisiticexpialidocious!" - << "Hello, world!"; + << "Hello, world!" + << "!dlrow ,olleH"; colorStrings << "aliceblue" << "antiquewhite" @@ -405,9 +421,447 @@ void tst_qdeclarativetextinput::selection() textinputObject->select(0,100); QVERIFY(textinputObject->selectedText().size() == 10); + textinputObject->deselect(); + QVERIFY(textinputObject->selectedText().isNull()); + textinputObject->select(0,10); + QVERIFY(textinputObject->selectedText().size() == 10); + textinputObject->deselect(); + QVERIFY(textinputObject->selectedText().isNull()); + delete textinputObject; } +void tst_qdeclarativetextinput::moveCursorSelection_data() +{ + QTest::addColumn<QString>("testStr"); + QTest::addColumn<int>("cursorPosition"); + QTest::addColumn<int>("movePosition"); + QTest::addColumn<QDeclarativeTextInput::SelectionMode>("mode"); + QTest::addColumn<int>("selectionStart"); + QTest::addColumn<int>("selectionEnd"); + QTest::addColumn<bool>("reversible"); + + QTest::newRow("(t)he|characters") + << standard[0] << 0 << 1 << QDeclarativeTextInput::SelectCharacters << 0 << 1 << true; + QTest::newRow("do(g)|characters") + << standard[0] << 43 << 44 << QDeclarativeTextInput::SelectCharacters << 43 << 44 << true; + QTest::newRow("jum(p)ed|characters") + << standard[0] << 23 << 24 << QDeclarativeTextInput::SelectCharacters << 23 << 24 << true; + QTest::newRow("jumped( )over|characters") + << standard[0] << 26 << 27 << QDeclarativeTextInput::SelectCharacters << 26 << 27 << true; + QTest::newRow("(the )|characters") + << standard[0] << 0 << 4 << QDeclarativeTextInput::SelectCharacters << 0 << 4 << true; + QTest::newRow("( dog)|characters") + << standard[0] << 40 << 44 << QDeclarativeTextInput::SelectCharacters << 40 << 44 << true; + QTest::newRow("( jumped )|characters") + << standard[0] << 19 << 27 << QDeclarativeTextInput::SelectCharacters << 19 << 27 << true; + QTest::newRow("th(e qu)ick|characters") + << standard[0] << 2 << 6 << QDeclarativeTextInput::SelectCharacters << 2 << 6 << true; + QTest::newRow("la(zy d)og|characters") + << standard[0] << 38 << 42 << QDeclarativeTextInput::SelectCharacters << 38 << 42 << true; + QTest::newRow("jum(ped ov)er|characters") + << standard[0] << 23 << 29 << QDeclarativeTextInput::SelectCharacters << 23 << 29 << true; + QTest::newRow("()the|characters") + << standard[0] << 0 << 0 << QDeclarativeTextInput::SelectCharacters << 0 << 0 << true; + QTest::newRow("dog()|characters") + << standard[0] << 44 << 44 << QDeclarativeTextInput::SelectCharacters << 44 << 44 << true; + QTest::newRow("jum()ped|characters") + << standard[0] << 23 << 23 << QDeclarativeTextInput::SelectCharacters << 23 << 23 << true; + + QTest::newRow("<(t)he>|words") + << standard[0] << 0 << 1 << QDeclarativeTextInput::SelectWords << 0 << 3 << true; + QTest::newRow("<do(g)>|words") + << standard[0] << 43 << 44 << QDeclarativeTextInput::SelectWords << 41 << 44 << true; + QTest::newRow("<jum(p)ed>|words") + << standard[0] << 23 << 24 << QDeclarativeTextInput::SelectWords << 20 << 26 << true; + QTest::newRow("<jumped( )>over|words,ltr") + << standard[0] << 26 << 27 << QDeclarativeTextInput::SelectWords << 20 << 27 << false; + QTest::newRow("jumped<( )over>|words,rtl") + << standard[0] << 27 << 26 << QDeclarativeTextInput::SelectWords << 26 << 31 << false; + QTest::newRow("<(the )>quick|words,ltr") + << standard[0] << 0 << 4 << QDeclarativeTextInput::SelectWords << 0 << 4 << false; + QTest::newRow("<(the )quick>|words,rtl") + << standard[0] << 4 << 0 << QDeclarativeTextInput::SelectWords << 0 << 9 << false; + QTest::newRow("<lazy( dog)>|words,ltr") + << standard[0] << 40 << 44 << QDeclarativeTextInput::SelectWords << 36 << 44 << false; + QTest::newRow("lazy<( dog)>|words,rtl") + << standard[0] << 44 << 40 << QDeclarativeTextInput::SelectWords << 40 << 44 << false; + QTest::newRow("<fox( jumped )>over|words,ltr") + << standard[0] << 19 << 27 << QDeclarativeTextInput::SelectWords << 16 << 27 << false; + QTest::newRow("fox<( jumped )over>|words,rtl") + << standard[0] << 27 << 19 << QDeclarativeTextInput::SelectWords << 19 << 31 << false; + QTest::newRow("<th(e qu)ick>|words") + << standard[0] << 2 << 6 << QDeclarativeTextInput::SelectWords << 0 << 9 << true; + QTest::newRow("<la(zy d)og|words>") + << standard[0] << 38 << 42 << QDeclarativeTextInput::SelectWords << 36 << 44 << true; + QTest::newRow("<jum(ped ov)er>|words") + << standard[0] << 23 << 29 << QDeclarativeTextInput::SelectWords << 20 << 31 << true; + QTest::newRow("<()>the|words") + << standard[0] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << true; + QTest::newRow("dog<()>|words") + << standard[0] << 44 << 44 << QDeclarativeTextInput::SelectWords << 44 << 44 << true; + QTest::newRow("jum<()>ped|words") + << standard[0] << 23 << 23 << QDeclarativeTextInput::SelectWords << 23 << 23 << true; + + QTest::newRow("Hello<(,)> |words") + << standard[2] << 5 << 6 << QDeclarativeTextInput::SelectWords << 5 << 6 << true; + QTest::newRow("Hello<(, )>world|words,ltr") + << standard[2] << 5 << 7 << QDeclarativeTextInput::SelectWords << 5 << 7 << false; + QTest::newRow("Hello<(, )world>|words,rtl") + << standard[2] << 7 << 5 << QDeclarativeTextInput::SelectWords << 5 << 12 << false; + QTest::newRow("<Hel(lo, )>world|words,ltr") + << standard[2] << 3 << 7 << QDeclarativeTextInput::SelectWords << 0 << 7 << false; + QTest::newRow("<Hel(lo, )world>|words,rtl") + << standard[2] << 7 << 3 << QDeclarativeTextInput::SelectWords << 0 << 12 << false; + QTest::newRow("<Hel(lo)>,|words") + << standard[2] << 3 << 5 << QDeclarativeTextInput::SelectWords << 0 << 5 << true; + QTest::newRow("Hello<()>,|words") + << standard[2] << 5 << 5 << QDeclarativeTextInput::SelectWords << 5 << 5 << true; + QTest::newRow("Hello,<()>|words") + << standard[2] << 6 << 6 << QDeclarativeTextInput::SelectWords << 6 << 6 << true; + QTest::newRow("Hello<,( )>world|words,ltr") + << standard[2] << 6 << 7 << QDeclarativeTextInput::SelectWords << 5 << 7 << false; + QTest::newRow("Hello,<( )world>|words,rtl") + << standard[2] << 7 << 6 << QDeclarativeTextInput::SelectWords << 6 << 12 << false; + QTest::newRow("Hello<,( world)>|words,ltr") + << standard[2] << 6 << 12 << QDeclarativeTextInput::SelectWords << 5 << 12 << false; + QTest::newRow("Hello,<( world)>|words,rtl") + << standard[2] << 12 << 6 << QDeclarativeTextInput::SelectWords << 6 << 12 << false; + QTest::newRow("Hello<,( world!)>|words,ltr") + << standard[2] << 6 << 13 << QDeclarativeTextInput::SelectWords << 5 << 13 << false; + QTest::newRow("Hello,<( world!)>|words,rtl") + << standard[2] << 13 << 6 << QDeclarativeTextInput::SelectWords << 6 << 13 << false; + QTest::newRow("Hello<(, world!)>|words") + << standard[2] << 5 << 13 << QDeclarativeTextInput::SelectWords << 5 << 13 << true; + // Fails due to an issue with QTextBoundaryFinder and punctuation at the end of strings. + // QTBUG-11365 + // QTest::newRow("world<(!)>|words") + // << standard[2] << 12 << 13 << QDeclarativeTextInput::SelectWords << 12 << 13 << true; + QTest::newRow("world!<()>)|words") + << standard[2] << 13 << 13 << QDeclarativeTextInput::SelectWords << 13 << 13 << true; + QTest::newRow("world<()>!)|words") + << standard[2] << 12 << 12 << QDeclarativeTextInput::SelectWords << 12 << 12 << true; + + QTest::newRow("<(,)>olleH |words") + << standard[3] << 7 << 8 << QDeclarativeTextInput::SelectWords << 7 << 8 << true; + QTest::newRow("<dlrow( ,)>olleH|words,ltr") + << standard[3] << 6 << 8 << QDeclarativeTextInput::SelectWords << 1 << 8 << false; + QTest::newRow("dlrow<( ,)>olleH|words,rtl") + << standard[3] << 8 << 6 << QDeclarativeTextInput::SelectWords << 6 << 8 << false; + QTest::newRow("<dlrow( ,ol)leH>|words,ltr") + << standard[3] << 6 << 10 << QDeclarativeTextInput::SelectWords << 1 << 13 << false; + QTest::newRow("dlrow<( ,ol)leH>|words,rtl") + << standard[3] << 10 << 6 << QDeclarativeTextInput::SelectWords << 6 << 13 << false; + QTest::newRow(",<(ol)leH>,|words") + << standard[3] << 8 << 10 << QDeclarativeTextInput::SelectWords << 8 << 13 << true; + QTest::newRow(",<()>olleH|words") + << standard[3] << 8 << 8 << QDeclarativeTextInput::SelectWords << 8 << 8 << true; + QTest::newRow("<()>,olleH|words") + << standard[3] << 7 << 7 << QDeclarativeTextInput::SelectWords << 7 << 7 << true; + QTest::newRow("<dlrow( )>,olleH|words,ltr") + << standard[3] << 6 << 7 << QDeclarativeTextInput::SelectWords << 1 << 7 << false; + QTest::newRow("dlrow<( ),>olleH|words,rtl") + << standard[3] << 7 << 6 << QDeclarativeTextInput::SelectWords << 6 << 8 << false; + QTest::newRow("<(dlrow )>,olleH|words,ltr") + << standard[3] << 1 << 7 << QDeclarativeTextInput::SelectWords << 1 << 7 << false; + QTest::newRow("<(dlrow ),>olleH|words,rtl") + << standard[3] << 7 << 1 << QDeclarativeTextInput::SelectWords << 1 << 8 << false; + QTest::newRow("<(!dlrow )>,olleH|words,ltr") + << standard[3] << 0 << 7 << QDeclarativeTextInput::SelectWords << 0 << 7 << false; + QTest::newRow("<(!dlrow ),>olleH|words,rtl") + << standard[3] << 7 << 0 << QDeclarativeTextInput::SelectWords << 0 << 8 << false; + QTest::newRow("(!dlrow ,)olleH|words") + << standard[3] << 0 << 8 << QDeclarativeTextInput::SelectWords << 0 << 8 << true; + QTest::newRow("<(!)>dlrow|words") + << standard[3] << 0 << 1 << QDeclarativeTextInput::SelectWords << 0 << 1 << true; + QTest::newRow("<()>!dlrow|words") + << standard[3] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << true; + QTest::newRow("!<()>dlrow|words") + << standard[3] << 1 << 1 << QDeclarativeTextInput::SelectWords << 1 << 1 << true; +} + +void tst_qdeclarativetextinput::moveCursorSelection() +{ + QFETCH(QString, testStr); + QFETCH(int, cursorPosition); + QFETCH(int, movePosition); + QFETCH(QDeclarativeTextInput::SelectionMode, mode); + QFETCH(int, selectionStart); + QFETCH(int, selectionEnd); + QFETCH(bool, reversible); + + QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }"; + QDeclarativeComponent textinputComponent(&engine); + textinputComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextInput *textinputObject = qobject_cast<QDeclarativeTextInput*>(textinputComponent.create()); + QVERIFY(textinputObject != 0); + + textinputObject->setCursorPosition(cursorPosition); + textinputObject->moveCursorSelection(movePosition, mode); + + QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart)); + QCOMPARE(textinputObject->selectionStart(), selectionStart); + QCOMPARE(textinputObject->selectionEnd(), selectionEnd); + + if (reversible) { + textinputObject->setCursorPosition(movePosition); + textinputObject->moveCursorSelection(cursorPosition, mode); + + QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart)); + QCOMPARE(textinputObject->selectionStart(), selectionStart); + QCOMPARE(textinputObject->selectionEnd(), selectionEnd); + } +} + +void tst_qdeclarativetextinput::moveCursorSelectionSequence_data() +{ + QTest::addColumn<QString>("testStr"); + QTest::addColumn<int>("cursorPosition"); + QTest::addColumn<int>("movePosition1"); + QTest::addColumn<int>("movePosition2"); + QTest::addColumn<int>("selection1Start"); + QTest::addColumn<int>("selection1End"); + QTest::addColumn<int>("selection2Start"); + QTest::addColumn<int>("selection2End"); + + QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr") + << standard[0] + << 9 << 13 << 17 + << 4 << 15 + << 4 << 19; + QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl") + << standard[0] + << 13 << 9 << 17 + << 9 << 15 + << 10 << 19; + QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr") + << standard[0] + << 9 << 13 << 16 + << 4 << 15 + << 4 << 16; + QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl") + << standard[0] + << 13 << 9 << 16 + << 9 << 15 + << 10 << 16; + QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr") + << standard[0] + << 9 << 13 << 15 + << 4 << 15 + << 4 << 15; + QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl") + << standard[0] + << 13 << 9 << 15 + << 9 << 15 + << 10 << 15; + QTest::newRow("the {<quick() ^}bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 10 + << 4 << 15 + << 4 << 10; + QTest::newRow("the quick<( {^bro)wn>} fox|rtl") + << standard[0] + << 13 << 9 << 10 + << 9 << 15 + << 10 << 15; + QTest::newRow("the {<quick^}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 9 + << 4 << 15 + << 4 << 9; + QTest::newRow("the quick{<(^ bro)wn>} fox|rtl") + << standard[0] + << 13 << 9 << 9 + << 9 << 15 + << 9 << 15; + QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 7 + << 4 << 15 + << 4 << 9; + QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl") + << standard[0] + << 13 << 9 << 7 + << 9 << 15 + << 4 << 15; + QTest::newRow("the {<^quick}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 4 + << 4 << 15 + << 4 << 9; + QTest::newRow("the {<^quick}( bro)wn> fox|rtl") + << standard[0] + << 13 << 9 << 4 + << 9 << 15 + << 4 << 15; + QTest::newRow("the{^ <quick}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 3 + << 4 << 15 + << 3 << 9; + QTest::newRow("the{^ <quick}( bro)wn> fox|rtl") + << standard[0] + << 13 << 9 << 3 + << 9 << 15 + << 3 << 15; + QTest::newRow("{t^he <quick}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 1 + << 4 << 15 + << 0 << 9; + QTest::newRow("{t^he <quick}( bro)wn> fox|rtl") + << standard[0] + << 13 << 9 << 1 + << 9 << 15 + << 0 << 15; + + QTest::newRow("{<He(ll)o>, w^orld}!|ltr") + << standard[2] + << 2 << 4 << 8 + << 0 << 5 + << 0 << 12; + QTest::newRow("{<He(ll)o>, w^orld}!|rtl") + << standard[2] + << 4 << 2 << 8 + << 0 << 5 + << 0 << 12; + + QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr") + << standard[3] + << 9 << 11 << 5 + << 8 << 13 + << 1 << 13; + QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl") + << standard[3] + << 11 << 9 << 5 + << 8 << 13 + << 1 << 13; +} + +void tst_qdeclarativetextinput::moveCursorSelectionSequence() +{ + QFETCH(QString, testStr); + QFETCH(int, cursorPosition); + QFETCH(int, movePosition1); + QFETCH(int, movePosition2); + QFETCH(int, selection1Start); + QFETCH(int, selection1End); + QFETCH(int, selection2Start); + QFETCH(int, selection2End); + + QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }"; + QDeclarativeComponent textinputComponent(&engine); + textinputComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextInput *textinputObject = qobject_cast<QDeclarativeTextInput*>(textinputComponent.create()); + QVERIFY(textinputObject != 0); + + textinputObject->setCursorPosition(cursorPosition); + + textinputObject->moveCursorSelection(movePosition1, QDeclarativeTextInput::SelectWords); + QCOMPARE(textinputObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start)); + QCOMPARE(textinputObject->selectionStart(), selection1Start); + QCOMPARE(textinputObject->selectionEnd(), selection1End); + + textinputObject->moveCursorSelection(movePosition2, QDeclarativeTextInput::SelectWords); + QCOMPARE(textinputObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start)); + QCOMPARE(textinputObject->selectionStart(), selection2Start); + QCOMPARE(textinputObject->selectionEnd(), selection2End); +} + +void tst_qdeclarativetextinput::dragMouseSelection() +{ + QString qmlfile = SRCDIR "/data/mouseselection_true.qml"; + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextInput *textInputObject = qobject_cast<QDeclarativeTextInput *>(canvas->rootObject()); + QVERIFY(textInputObject != 0); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textInputObject->height()/2; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + + QString str1 = textInputObject->selectedText(); + QVERIFY(str1.length() > 3); + + // press and drag the current selection. + x1 = 40; + x2 = 100; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QString str2 = textInputObject->selectedText(); + QVERIFY(str2.length() > 3); + + QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved. + delete canvas; +} + +void tst_qdeclarativetextinput::mouseSelectionMode_data() +{ + QTest::addColumn<QString>("qmlfile"); + QTest::addColumn<bool>("selectWords"); + + // import installed + QTest::newRow("SelectWords") << SRCDIR "/data/mouseselectionmode_words.qml" << true; + QTest::newRow("SelectCharacters") << SRCDIR "/data/mouseselectionmode_characters.qml" << false; + QTest::newRow("default") << SRCDIR "/data/mouseselectionmode_default.qml" << false; +} + +void tst_qdeclarativetextinput::mouseSelectionMode() +{ + QFETCH(QString, qmlfile); + QFETCH(bool, selectWords); + + QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextInput *textInputObject = qobject_cast<QDeclarativeTextInput *>(canvas->rootObject()); + QVERIFY(textInputObject != 0); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textInputObject->height()/2; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QString str = textInputObject->selectedText(); + if (selectWords) { + QCOMPARE(str, text); + } else { + QVERIFY(str.length() > 3); + QVERIFY(str != text); + } + + delete canvas; +} + void tst_qdeclarativetextinput::horizontalAlignment_data() { QTest::addColumn<int>("hAlign"); @@ -448,6 +902,31 @@ void tst_qdeclarativetextinput::horizontalAlignment() delete canvas; } +void tst_qdeclarativetextinput::horizontalAlignment_RightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml"); + QDeclarativeTextInput *textInput = canvas->rootObject()->findChild<QDeclarativeTextInput*>("text"); + QVERIFY(textInput != 0); + canvas->show(); + + QDeclarativeTextInputPrivate *textInputPrivate = QDeclarativeTextInputPrivate::get(textInput); + QVERIFY(textInputPrivate != 0); + QVERIFY(-textInputPrivate->hscroll > canvas->width()/2); + + // "Right" Align + textInput->setHAlign(QDeclarativeTextInput::AlignRight); + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignRight); + QVERIFY(-textInputPrivate->hscroll < canvas->width()/2); + + // Center Align + textInput->setHAlign(QDeclarativeTextInput::AlignHCenter); + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignHCenter); + QVERIFY(-textInputPrivate->hscroll < canvas->width()/2); + QVERIFY(-textInputPrivate->hscroll + textInputPrivate->width() > canvas->width()/2); + + delete canvas; +} + void tst_qdeclarativetextinput::positionAt() { QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml"); @@ -739,10 +1218,18 @@ void tst_qdeclarativetextinput::copyAndPaste() { QCOMPARE(textInput->selectedText(), QString("Hello world!")); QCOMPARE(textInput->selectedText().length(), 12); textInput->setCursorPosition(0); + QVERIFY(textInput->canPaste()); textInput->paste(); QCOMPARE(textInput->text(), QString("Hello world!Hello world!")); QCOMPARE(textInput->text().length(), 24); + // can paste + QVERIFY(textInput->canPaste()); + textInput->setReadOnly(true); + QVERIFY(!textInput->canPaste()); + textInput->setReadOnly(false); + QVERIFY(textInput->canPaste()); + // select word textInput->setCursorPosition(0); textInput->selectWord(); @@ -760,6 +1247,7 @@ void tst_qdeclarativetextinput::copyAndPaste() { QClipboard *clipboard = QApplication::clipboard(); QVERIFY(clipboard); clipboard->clear(); + QVERIFY(!textInput->canPaste()); // test that copy functionality is disabled // when echo mode is set to hide text/password mode @@ -907,6 +1395,8 @@ void tst_qdeclarativetextinput::echoMode() input->setFocus(false); QVERIFY(input->hasActiveFocus() == false); QCOMPARE(input->displayText(), QLatin1String("Q")); + + delete canvas; } void tst_qdeclarativetextinput::simulateKey(QDeclarativeView *view, int key) @@ -947,6 +1437,17 @@ public: closeInputPanelReceived = true; return QInputContext::filterEvent(event); } + + void sendPreeditText(const QString &text, int cursor) + { + QList<QInputMethodEvent::Attribute> attributes; + attributes.append(QInputMethodEvent::Attribute( + QInputMethodEvent::Cursor, cursor, text.length(), QVariant())); + + QInputMethodEvent event(text, attributes); + sendEvent(event); + } + bool openInputPanelReceived; bool closeInputPanelReceived; }; @@ -1117,6 +1618,16 @@ void tst_qdeclarativetextinput::openInputPanelOnFocus() QApplication::processEvents(); QVERIFY(view.inputContext() == 0); QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); + + // input method should not be enabled + // if TextEdit is read only. + input.setReadOnly(true); + ic.openInputPanelReceived = false; + input.setFocus(true); + QApplication::processEvents(); + QCOMPARE(ic.openInputPanelReceived, false); + QVERIFY(view.inputContext() == 0); + QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); } class MyTextInput : public QDeclarativeTextInput @@ -1183,6 +1694,112 @@ void tst_qdeclarativetextinput::geometrySignals() delete o; } +void tst_qdeclarativetextinput::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; TextInput { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; TextInput { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_qdeclarativetextinput::testQtQuick11Attributes_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("warning"); + QTest::addColumn<QString>("error"); + + QTest::newRow("canPaste") << "property bool foo: canPaste" + << "<Unknown File>:1: ReferenceError: Can't find variable: canPaste" + << ""; + + QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)" + << "<Unknown File>:1: ReferenceError: Can't find variable: moveCursorSelection" + << ""; + + QTest::newRow("deselect") << "Component.onCompleted: deselect()" + << "<Unknown File>:1: ReferenceError: Can't find variable: deselect" + << ""; +} + +void tst_qdeclarativetextinput::preeditAutoScroll() +{ + QString committedText = "super"; + QString preeditText = "califragisiticexpialidocious!"; + + QGraphicsScene scene; + QGraphicsView view(&scene); + MyInputContext ic; + view.setInputContext(&ic); + QDeclarativeTextInput input; + input.setWidth(QFontMetricsF(input.font()).width(committedText)); + input.setText(committedText); + input.setPos(0, 0); + input.setFocus(true); + scene.addItem(&input); + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + + // test the text is scrolled so the preedit is visible. + ic.sendPreeditText(preeditText.mid(0, 3), 1); + QVERIFY(input.positionAt(0) != 0); + QCOMPARE(input.positionAt(input.width()), 8); + + // test the text is scrolled back when the preedit is removed. + ic.sendEvent(QInputMethodEvent()); + QCOMPARE(input.positionAt(0), 0); + QCOMPARE(input.positionAt(input.width()), 5); + + // test if the preedit is larger than the text input that the + // character preceding the cursor is still visible. + for (int i = 0; i < 3; ++i) { + ic.sendPreeditText(preeditText, i + 1); + QCOMPARE(input.positionAt(0), 5 + i); + } + for (int i = 1; i >= 0; --i) { + ic.sendPreeditText(preeditText, i + 1); + QCOMPARE(input.positionAt(0), 5 + i); + } + + // Test incrementing the preedit cursor doesn't cause further + // scrolling when right most text is visible. + ic.sendPreeditText(preeditText, preeditText.length() - 3); + int position = input.positionAt(0); + for (int i = 2; i >= 0; --i) { + ic.sendPreeditText(preeditText, preeditText.length() - i); + QCOMPARE(input.positionAt(0), position); + } + for (int i = 1; i < 3; ++i) { + ic.sendPreeditText(preeditText, preeditText.length() - i); + QCOMPARE(input.positionAt(0), position); + } + + // Test disabling auto scroll. + ic.sendEvent(QInputMethodEvent()); + + input.setAutoScroll(false); + ic.sendPreeditText(preeditText.mid(0, 3), 1); + QCOMPARE(input.positionAt(0), 0); + QCOMPARE(input.positionAt(input.width()), 5); +} + QTEST_MAIN(tst_qdeclarativetextinput) #include "tst_qdeclarativetextinput.moc" diff --git a/tests/auto/declarative/qdeclarativeview/tst_qdeclarativeview.cpp b/tests/auto/declarative/qdeclarativeview/tst_qdeclarativeview.cpp index 46c2a34..8385659 100644 --- a/tests/auto/declarative/qdeclarativeview/tst_qdeclarativeview.cpp +++ b/tests/auto/declarative/qdeclarativeview/tst_qdeclarativeview.cpp @@ -60,6 +60,7 @@ public: tst_QDeclarativeView(); private slots: + void scene(); void resizemodedeclarativeitem(); void resizemodegraphicswidget(); void errors(); @@ -74,6 +75,26 @@ tst_QDeclarativeView::tst_QDeclarativeView() { } +void tst_QDeclarativeView::scene() +{ + // QTBUG-14771 + QGraphicsScene scene; + scene.setItemIndexMethod(QGraphicsScene::NoIndex); + scene.setStickyFocus(true); + + QDeclarativeView *view = new QDeclarativeView(); + QVERIFY(view); + QVERIFY(view->scene()); + view->setScene(&scene); + QCOMPARE(view->scene(), &scene); + + view->setSource(QUrl::fromLocalFile(SRCDIR "/data/resizemodedeclarativeitem.qml")); + QDeclarativeItem* declarativeItem = qobject_cast<QDeclarativeItem*>(view->rootObject()); + QVERIFY(declarativeItem); + QVERIFY(scene.items().count() > 0); + QCOMPARE(scene.items().at(0), declarativeItem); +} + void tst_QDeclarativeView::resizemodedeclarativeitem() { QWidget window; diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onCall.js b/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onCall.js new file mode 100644 index 0000000..f589b0e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onCall.js @@ -0,0 +1,6 @@ +WorkerScript.onMessage = function(msg) { + var a = 123 + var b = 345 + var f = getData() +} + diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onLoad.js b/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onLoad.js new file mode 100644 index 0000000..1d6eab2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/script_error_onLoad.js @@ -0,0 +1,5 @@ +WorkerScript.onMessage = function(msg) { + var a = 123 + aoij awef aljfaow eij +} + diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onCall.qml b/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onCall.qml new file mode 100644 index 0000000..90c4617 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onCall.qml @@ -0,0 +1,6 @@ +import QtQuick 1.0 + +BaseWorker { + source: "script_error_onCall.js" +} + diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onLoad.qml b/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onLoad.qml new file mode 100644 index 0000000..0b9d21d --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/worker_error_onLoad.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +BaseWorker { + source: "script_error_onLoad.js" +} + + diff --git a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp index aaedd82..4b922fb 100644 --- a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp +++ b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp @@ -41,6 +41,8 @@ #include <qtest.h> #include <QtCore/qdebug.h> #include <QtCore/qtimer.h> +#include <QtCore/qdir.h> +#include <QtCore/qfileinfo.h> #include <QtScript/qscriptengine.h> #include <QtDeclarative/qdeclarativecomponent.h> @@ -58,6 +60,13 @@ Q_DECLARE_METATYPE(QScriptValue) #define SRCDIR "." #endif +inline QUrl TEST_FILE(const QString &filename) +{ + QFileInfo fileInfo(__FILE__); + return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath(filename)); +} + + class tst_QDeclarativeWorkerScript : public QObject { Q_OBJECT @@ -70,6 +79,8 @@ private slots: void messaging_sendQObjectList(); void messaging_sendJsObject(); void script_with_pragma(); + void scriptError_onLoad(); + void scriptError_onCall(); private: void waitForEchoMessage(QDeclarativeWorkerScript *worker) { @@ -215,6 +226,47 @@ void tst_QDeclarativeWorkerScript::script_with_pragma() delete worker; } +static QString qdeclarativeworkerscript_lastWarning; +static void qdeclarativeworkerscript_warningsHandler(QtMsgType type, const char *msg) +{ + if (type == QtWarningMsg) + qdeclarativeworkerscript_lastWarning = QString::fromUtf8(msg); +} + +void tst_QDeclarativeWorkerScript::scriptError_onLoad() +{ + QDeclarativeComponent component(&m_engine, SRCDIR "/data/worker_error_onLoad.qml"); + + QtMsgHandler previousMsgHandler = qInstallMsgHandler(qdeclarativeworkerscript_warningsHandler); + QDeclarativeWorkerScript *worker = qobject_cast<QDeclarativeWorkerScript*>(component.create()); + QVERIFY(worker != 0); + + QTRY_COMPARE(qdeclarativeworkerscript_lastWarning, + TEST_FILE("data/script_error_onLoad.js").toString() + QLatin1String(":3: SyntaxError: Parse error")); + + qInstallMsgHandler(previousMsgHandler); + qApp->processEvents(); + delete worker; +} + +void tst_QDeclarativeWorkerScript::scriptError_onCall() +{ + QDeclarativeComponent component(&m_engine, SRCDIR "/data/worker_error_onCall.qml"); + QDeclarativeWorkerScript *worker = qobject_cast<QDeclarativeWorkerScript*>(component.create()); + QVERIFY(worker != 0); + + QtMsgHandler previousMsgHandler = qInstallMsgHandler(qdeclarativeworkerscript_warningsHandler); + QVariant value; + QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value))); + + QTRY_COMPARE(qdeclarativeworkerscript_lastWarning, + TEST_FILE("data/script_error_onCall.js").toString() + QLatin1String(":4: ReferenceError: Can't find variable: getData")); + + qInstallMsgHandler(previousMsgHandler); + qApp->processEvents(); + delete worker; +} + QTEST_MAIN(tst_QDeclarativeWorkerScript) diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml b/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml deleted file mode 100644 index e56aafa..0000000 --- a/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml +++ /dev/null @@ -1,11 +0,0 @@ -import QtQuick 1.0 - -XmlListModel { - source: "model.xml" - query: "/Pets/Pet" - XmlRole { name: "name"; query: "name/string()" } - XmlRole { name: "type"; query: "type/string()" } - XmlRole { name: "age"; query: "age/number()" } - XmlRole { name: "size"; query: "size/string()" } - XmlRole { name: "tricks"; query: "tricks/string()" } -} diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/testtypes.qml b/tests/auto/declarative/qdeclarativexmllistmodel/data/testtypes.qml new file mode 100644 index 0000000..4dbcc02 --- /dev/null +++ b/tests/auto/declarative/qdeclarativexmllistmodel/data/testtypes.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 + +XmlListModel { + query: "/data" + XmlRole { name: "stringValue"; query: "a-string/string()" } + XmlRole { name: "numberValue"; query: "a-number/number()" } +} + diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp index 41807bf..19d7967 100644 --- a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp +++ b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp @@ -40,6 +40,10 @@ ****************************************************************************/ #include <private/qdeclarativeengine_p.h> +#include <QtTest/QtTest> +#include <QtGlobal> +#include <math.h> + #include <qtest.h> #include <QtTest/qsignalspy.h> #include <QtDeclarative/qdeclarativenetworkaccessmanagerfactory.h> @@ -80,7 +84,8 @@ private slots: } void buildModel(); - void missingFields(); + void testTypes(); + void testTypes_data(); void cdata(); void attributes(); void roles(); @@ -202,27 +207,70 @@ void tst_qdeclarativexmllistmodel::buildModel() delete model; } -void tst_qdeclarativexmllistmodel::missingFields() +void tst_qdeclarativexmllistmodel::testTypes() { - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/model2.qml")); + QFETCH(QString, xml); + QFETCH(QString, roleName); + QFETCH(QVariant, expectedValue); + + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/testtypes.qml")); QDeclarativeXmlListModel *model = qobject_cast<QDeclarativeXmlListModel*>(component.create()); QVERIFY(model != 0); - QTRY_COMPARE(model->count(), 9); + model->setXml(xml.toUtf8()); + model->reload(); + QTRY_COMPARE(model->count(), 1); - QList<int> roles; - roles << Qt::UserRole << Qt::UserRole + 1 << Qt::UserRole + 2 << Qt::UserRole + 3 << Qt::UserRole + 4; - QHash<int, QVariant> data = model->data(5, roles); - QVERIFY(data.count() == 5); - QCOMPARE(data.value(Qt::UserRole+3).toString(), QLatin1String("")); - QCOMPARE(data.value(Qt::UserRole+4).toString(), QLatin1String("")); + int role = -1; + foreach (int i, model->roles()) { + if (model->toString(i) == roleName) { + role = i; + break; + } + } + QVERIFY(role >= 0); - data = model->data(7, roles); - QVERIFY(data.count() == 5); - QCOMPARE(data.value(Qt::UserRole+2).toString(), QLatin1String("")); + if (expectedValue.toString() == "nan") + QVERIFY(qIsNaN(model->data(0, role).toDouble())); + else + QCOMPARE(model->data(0, role), expectedValue); delete model; } +void tst_qdeclarativexmllistmodel::testTypes_data() +{ + QTest::addColumn<QString>("xml"); + QTest::addColumn<QString>("roleName"); + QTest::addColumn<QVariant>("expectedValue"); + + QTest::newRow("missing string field") << "<data></data>" + << "stringValue" << QVariant(""); + QTest::newRow("empty string") << "<data><a-string></a-string></data>" + << "stringValue" << QVariant(""); + QTest::newRow("1-char string") << "<data><a-string>5</a-string></data>" + << "stringValue" << QVariant("5"); + QTest::newRow("string ok") << "<data><a-string>abc def g</a-string></data>" + << "stringValue" << QVariant("abc def g"); + + QTest::newRow("missing number field") << "<data></data>" + << "numberValue" << QVariant(""); + double nan = qQNaN(); + QTest::newRow("empty number field") << "<data><a-number></a-number></data>" + << "numberValue" << QVariant(nan); + QTest::newRow("number field with string") << "<data><a-number>a string</a-number></data>" + << "numberValue" << QVariant(nan); + QTest::newRow("-1") << "<data><a-number>-1</a-number></data>" + << "numberValue" << QVariant("-1"); + QTest::newRow("-1.5") << "<data><a-number>-1.5</a-number></data>" + << "numberValue" << QVariant("-1.5"); + QTest::newRow("0") << "<data><a-number>0</a-number></data>" + << "numberValue" << QVariant("0"); + QTest::newRow("+1") << "<data><a-number>1</a-number></data>" + << "numberValue" << QVariant("1"); + QTest::newRow("+1.5") << "<data><a-number>1.5</a-number></data>" + << "numberValue" << QVariant("1.5"); +} + void tst_qdeclarativexmllistmodel::cdata() { QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/recipes.qml")); diff --git a/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp index 704fea0..06baed8 100644 --- a/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp +++ b/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp @@ -546,7 +546,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(!nullProp.isUser()); QVERIFY(!nullProp.hasStdCppSet()); QVERIFY(!nullProp.isEnumOrFlag()); - QVERIFY(!nullProp.isDynamic()); QCOMPARE(nullProp.index(), 0); // Add a property and check its attributes. @@ -564,7 +563,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(!prop1.isUser()); QVERIFY(!prop1.hasStdCppSet()); QVERIFY(!prop1.isEnumOrFlag()); - QVERIFY(!prop1.isDynamic()); QCOMPARE(prop1.index(), 0); QCOMPARE(builder.propertyCount(), 1); @@ -583,7 +581,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(!prop2.isUser()); QVERIFY(!prop2.hasStdCppSet()); QVERIFY(!prop2.isEnumOrFlag()); - QVERIFY(!prop2.isDynamic()); QCOMPARE(prop2.index(), 1); QCOMPARE(builder.propertyCount(), 2); @@ -605,7 +602,6 @@ void tst_QMetaObjectBuilder::property() prop1.setUser(true); prop1.setStdCppSet(true); prop1.setEnumOrFlag(true); - prop1.setDynamic(true); // Check that prop1 is changed, but prop2 is not. QCOMPARE(prop1.name(), QByteArray("foo")); @@ -620,7 +616,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(prop1.isUser()); QVERIFY(prop1.hasStdCppSet()); QVERIFY(prop1.isEnumOrFlag()); - QVERIFY(prop1.isDynamic()); QVERIFY(prop2.isReadable()); QVERIFY(prop2.isWritable()); QCOMPARE(prop2.name(), QByteArray("bar")); @@ -633,7 +628,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(!prop2.isUser()); QVERIFY(!prop2.hasStdCppSet()); QVERIFY(!prop2.isEnumOrFlag()); - QVERIFY(!prop2.isDynamic()); // Remove prop1 and check that prop2 becomes index 0. builder.removeProperty(0); @@ -649,7 +643,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(!prop2.isUser()); QVERIFY(!prop2.hasStdCppSet()); QVERIFY(!prop2.isEnumOrFlag()); - QVERIFY(!prop2.isDynamic()); QCOMPARE(prop2.index(), 0); // Perform index-based lookup again. @@ -673,7 +666,6 @@ void tst_QMetaObjectBuilder::property() prop2.setUser(false); \ prop2.setStdCppSet(false); \ prop2.setEnumOrFlag(false); \ - prop2.setDynamic(false); \ } while (0) #define COUNT_FLAGS() \ ((prop2.isReadable() ? 1 : 0) + \ @@ -685,8 +677,7 @@ void tst_QMetaObjectBuilder::property() (prop2.isEditable() ? 1 : 0) + \ (prop2.isUser() ? 1 : 0) + \ (prop2.hasStdCppSet() ? 1 : 0) + \ - (prop2.isEnumOrFlag() ? 1 : 0) + \ - (prop2.isDynamic() ? 1 : 0)) + (prop2.isEnumOrFlag() ? 1 : 0)) #define CHECK_FLAG(setFunc,isFunc) \ do { \ CLEAR_FLAGS(); \ @@ -705,7 +696,6 @@ void tst_QMetaObjectBuilder::property() CHECK_FLAG(setUser, isUser); CHECK_FLAG(setStdCppSet, hasStdCppSet); CHECK_FLAG(setEnumOrFlag, isEnumOrFlag); - CHECK_FLAG(setDynamic, isDynamic); // Check that nothing else changed. QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Properties)); diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.0.png Binary files differnew file mode 100644 index 0000000..74c6934 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.qml new file mode 100644 index 0000000..e4dbeb1 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "justify.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/align/justify.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/justify.qml new file mode 100644 index 0000000..c3a7aaa --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/justify.qml @@ -0,0 +1,22 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: 450 + height: 250 + + TestText { + anchors.fill: parent + anchors { leftMargin: 10; rightMargin: 10; topMargin:10; bottomMargin: 10 } + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignJustify + + text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin a aliquet massa. Integer id velit a nibh imperdiet sagittis. Cras fringilla enim non nulla porta bibendum. Integer risus urna, hendrerit non interdum ut, dapibus id velit. Nullam fermentum viverra pellentesque. In molestie scelerisque lorem molestie ultrices. Curabitur dolor arcu, tristique in sodales in, varius sed diam. Quisque magna velit, tincidunt sed ullamcorper sit amet, ornare adipiscing ligula. In hac habitasse platea dictumst. Ut tincidunt urna vel mauris fermentum ornare quis a ligula. Suspendisse cursus volutpat sapien eget cursus." + + Rectangle { + anchors.fill: parent + color: "transparent" + border.color: "red" + } + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.0.png Binary files differnew file mode 100644 index 0000000..c24c7c6 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.qml new file mode 100644 index 0000000..affd3a6 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.0.png Binary files differnew file mode 100644 index 0000000..0ba68e5 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.qml new file mode 100644 index 0000000..410b47d --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines_wrap.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.0.png Binary files differnew file mode 100644 index 0000000..3f1144b --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.qml new file mode 100644 index 0000000..94cf1d2 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines_wrap_elide.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.0.png Binary files differnew file mode 100644 index 0000000..f0ad965 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.qml new file mode 100644 index 0000000..4b55312 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "wrap.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.0.png Binary files differnew file mode 100644 index 0000000..62274ce --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.qml new file mode 100644 index 0000000..7d002ea --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "wrap_elide.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.0.png Binary files differnew file mode 100644 index 0000000..c24c7c6 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.qml new file mode 100644 index 0000000..affd3a6 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.0.png Binary files differnew file mode 100644 index 0000000..0ba68e5 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.qml new file mode 100644 index 0000000..410b47d --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines_wrap.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.0.png Binary files differnew file mode 100644 index 0000000..3f1144b --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.qml new file mode 100644 index 0000000..94cf1d2 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines_wrap_elide.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.0.png Binary files differnew file mode 100644 index 0000000..f0ad965 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.qml new file mode 100644 index 0000000..4b55312 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "wrap.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.0.png Binary files differnew file mode 100644 index 0000000..62274ce --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.qml new file mode 100644 index 0000000..7d002ea --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "wrap_elide.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines.qml new file mode 100644 index 0000000..4e993c6 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines.qml @@ -0,0 +1,13 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: childrenRect.width + height: childrenRect.height + + TestText { + width: 80 + maximumLineCount: 2 + text: "Line1\nLine2\nLine3\nLine4" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap.qml new file mode 100644 index 0000000..5d8f50b --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap.qml @@ -0,0 +1,14 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: childrenRect.width + height: childrenRect.height + + TestText { + width: 80 + maximumLineCount: 3 + wrapMode: Text.WordWrap + text: "Line1 has a more\nLine2\nLine3\nLine4" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap_elide.qml new file mode 100644 index 0000000..ac7b5cb --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap_elide.qml @@ -0,0 +1,15 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: childrenRect.width + height: childrenRect.height + + TestText { + width: 80 + maximumLineCount: 3 + wrapMode: Text.WordWrap + elide: Text.ElideRight + text: "Line1 has a more\nLine2\nLine3\nLine4" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap.qml new file mode 100644 index 0000000..6d72430 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap.qml @@ -0,0 +1,14 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: childrenRect.width + height: childrenRect.height + + TestText { + width: 80 + maximumLineCount: 3 + wrapMode: Text.WordWrap + text: "The quick brown fox jumped over the lazy dog" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap_elide.qml new file mode 100644 index 0000000..785c5f5 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap_elide.qml @@ -0,0 +1,15 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: childrenRect.width + height: childrenRect.height + + TestText { + width: 80 + maximumLineCount: 3 + wrapMode: Text.WordWrap + elide: Text.ElideRight + text: "The quick brown fox jumped over the lazy dog" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.0.png Binary files differnew file mode 100644 index 0000000..74c6934 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.qml new file mode 100644 index 0000000..e4dbeb1 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "justify.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.0.png Binary files differnew file mode 100644 index 0000000..7d0d0ae --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.1.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.1.png Binary files differnew file mode 100644 index 0000000..7d612bf --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.1.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.qml new file mode 100644 index 0000000..8c7e380 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.qml @@ -0,0 +1,191 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "linkActivated.0.png" + } + Frame { + msec: 32 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 48 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 64 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 80 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 96 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 112 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 128 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 144 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 160 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 176 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 192 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 208 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 224 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 240 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 256 + hash: "53d97d0966197ea41364511dea13752f" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 21; y: 13 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 272 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Frame { + msec: 288 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Frame { + msec: 304 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 22; y: 11 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 320 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 23; y: 10 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 23; y: 10 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 336 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 352 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 368 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 384 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 400 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 416 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 432 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 448 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 464 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 480 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 496 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 512 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 528 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 544 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 560 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 576 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 592 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 608 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.0.png Binary files differnew file mode 100644 index 0000000..431bed8 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.1.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.1.png Binary files differnew file mode 100644 index 0000000..d8d6bac --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.1.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.2.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.2.png Binary files differnew file mode 100644 index 0000000..27e02e5 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.2.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.3.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.3.png Binary files differnew file mode 100644 index 0000000..00549b3 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.3.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.4.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.4.png Binary files differnew file mode 100644 index 0000000..5c2a885 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.4.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.5.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.5.png Binary files differnew file mode 100644 index 0000000..5c2a885 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.5.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.6.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.6.png Binary files differnew file mode 100644 index 0000000..fd7f010 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.6.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.qml new file mode 100644 index 0000000..dff5452 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/flickableEdit.qml @@ -0,0 +1,3551 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "flickableEdit.0.png" + } + Frame { + msec: 32 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 48 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 64 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 80 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 96 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 112 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 128 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 144 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 160 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 176 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 192 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 208 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 224 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 240 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 256 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 272 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 288 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 304 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 320 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 336 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 352 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 368 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 384 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 400 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 416 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 432 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 448 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 464 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 480 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 496 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 512 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 528 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 544 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 560 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 576 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 592 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 608 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 624 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 640 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 656 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 672 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 688 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 704 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 720 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 736 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 752 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 768 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 784 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 800 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 816 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 832 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 848 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 864 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 880 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 896 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 29; y: 12 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 912 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Frame { + msec: 928 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Frame { + msec: 944 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Frame { + msec: 960 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Frame { + msec: 976 + image: "flickableEdit.1.png" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 30; y: 12 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 32; y: 12 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 992 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 33; y: 12 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 34; y: 12 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1008 + hash: "1a426d2b8854412a3c91f927588f63ce" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 36; y: 12 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 39; y: 12 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1024 + hash: "4626e25f67dfd0fe3846322455762b3b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 41; y: 11 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 44; y: 11 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1040 + hash: "4626e25f67dfd0fe3846322455762b3b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 47; y: 11 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 50; y: 11 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1056 + hash: "e506425ea4a8eb6d94442ac0bccd0911" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 53; y: 11 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 56; y: 10 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1072 + hash: "3c45be5d00748154f9abce8d525b5791" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 58; y: 10 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 61; y: 10 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1088 + hash: "3e33ff0dfd478bad91472fa2bb4908a0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 64; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 66; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1104 + hash: "3e33ff0dfd478bad91472fa2bb4908a0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 69; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 71; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1120 + hash: "e8e7e98f3d7dbcdb4040ae81ef656e02" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 73; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 75; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1136 + hash: "e8e7e98f3d7dbcdb4040ae81ef656e02" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 78; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 80; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1152 + hash: "309c25ff85a361dfebd6464984fd9d79" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 83; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 85; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1168 + hash: "4b4fc7d9263af761222bb23f41021731" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 87; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 90; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1184 + hash: "4b4fc7d9263af761222bb23f41021731" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 93; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 96; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1200 + hash: "bd00eeda31cfc8d59a2c9677e771dadb" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 99; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 103; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1216 + hash: "adce307d674b8425fa39b69958d6acc5" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 106; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 111; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1232 + hash: "36e04d9124f32a21784f3017cc26ee71" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 114; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 116; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1248 + hash: "36e04d9124f32a21784f3017cc26ee71" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 119; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 122; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1264 + hash: "c6548ac358dd0eb4fa07ed305039d4e2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 124; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 126; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1280 + hash: "a0c4b8e21b0b04edaf7b32b2ab40edb2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 128; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 130; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1296 + hash: "a0c4b8e21b0b04edaf7b32b2ab40edb2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 132; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 134; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1312 + hash: "d32fb36408859c35dacc5787374b6ae4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 136; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 137; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1328 + hash: "d32fb36408859c35dacc5787374b6ae4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 139; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 141; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1344 + hash: "d32fb36408859c35dacc5787374b6ae4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 143; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 144; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1360 + hash: "90f44df899138e894b1a7e42657b8331" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 146; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 147; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1376 + hash: "90f44df899138e894b1a7e42657b8331" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 148; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 149; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1392 + hash: "8ec6bb08aac10a622df934421f64beb4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 150; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 151; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1408 + hash: "d4e52b7ca07033e4f2124607454fd81b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 152; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 154; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1424 + hash: "499d7c3d9cfb35db68f6eece23130e6b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 155; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1440 + hash: "499d7c3d9cfb35db68f6eece23130e6b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 157; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1456 + hash: "3ea13a21a5bbe336408c76ab17ff4268" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 158; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 160; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1472 + hash: "3ea13a21a5bbe336408c76ab17ff4268" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 161; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1488 + hash: "3ea13a21a5bbe336408c76ab17ff4268" + } + Frame { + msec: 1504 + hash: "3ea13a21a5bbe336408c76ab17ff4268" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 162; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1520 + hash: "3ea13a21a5bbe336408c76ab17ff4268" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 164; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1536 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 165; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1552 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 167; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 168; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1568 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 169; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1584 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1600 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 170; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1616 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1632 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1648 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1664 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1680 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1696 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1712 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1728 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1744 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1760 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1776 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1792 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1808 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1824 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1840 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 170; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1856 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1872 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1888 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1904 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 1920 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 1936 + image: "flickableEdit.2.png" + } + Frame { + msec: 1952 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 1968 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 1984 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2000 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2016 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2032 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2048 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2064 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2080 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2096 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2112 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2128 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2144 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2160 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2176 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2192 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2208 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2224 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2240 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2256 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2272 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2288 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2304 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2320 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2336 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2352 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2368 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2384 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2400 + hash: "4b8bc23e0153e6925c3e3a065fcc8dcd" + } + Frame { + msec: 2416 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2432 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2448 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2464 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2480 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2496 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2512 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2528 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2544 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2560 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2576 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2592 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2608 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2624 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2640 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2656 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2672 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2688 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Frame { + msec: 2704 + hash: "06bc360da9134471bf6e8e6ff36cbaa4" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 21; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2720 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2736 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2752 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2768 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2784 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2800 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2816 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2832 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2848 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2864 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2880 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2896 + image: "flickableEdit.3.png" + } + Frame { + msec: 2912 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2928 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 22; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2944 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2960 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 23; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2976 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Frame { + msec: 2992 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 24; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3008 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 25; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3024 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 26; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3040 + hash: "9d2c8b1f0f7da6a4914a54cf76393861" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 27; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 29; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3056 + hash: "e5daa45e1d798fdf2562dbb9a1a2c97b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 30; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 31; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3072 + hash: "698b572adf95ddc235b781b126a1cc10" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 33; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 35; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3088 + hash: "7a87fe9484b00f8c7039e3129fc24fb5" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 37; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 40; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3104 + hash: "2f17e7980a28789d0f262e3682c2da27" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 42; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 45; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3120 + hash: "0757f4c05233a25e6a8825b2c6052d8d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 49; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 52; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3136 + hash: "799da712f376033efdbaf9a342e4bc3f" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 55; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 58; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3152 + hash: "bf7b2a29664fe4acf52d56c73cf079b1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 62; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 66; y: 30 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3168 + hash: "7928b280e7a9ab89217c9abf3b709cd2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 69; y: 30 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 72; y: 30 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3184 + hash: "3102339f3e18640f6b508e88aafefb79" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 75; y: 30 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 78; y: 30 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3200 + hash: "98cddfbea5b96f9dd08c5a3655155d35" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 81; y: 30 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 84; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3216 + hash: "5604b2f85c3a90f8b29da3fec2f6c509" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 87; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 91; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3232 + hash: "5ca4055c8dded5d30c326d6d304da28d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 94; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 97; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3248 + hash: "b0afe256f8f89a77a5fa87c023cda469" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 101; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 104; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3264 + hash: "d7408be78c80e2b6e5848ee696a79ee0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 108; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 111; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3280 + hash: "f7e12621527fd52e21595cfbf804879c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 115; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 118; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3296 + hash: "6b8c9413ba1a791e42b06aaa711cdb4e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 122; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 127; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3312 + hash: "1c80e0f89033dedc66b236561042f4f6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 131; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 135; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3328 + hash: "6ec06d8844ff57e34af5316895250858" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 140; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 146; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3344 + hash: "f3c0159243555e919fd736866b00a5ab" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 151; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 157; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3360 + hash: "973ced5d6155240490acd6241610429d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 164; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 169; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3376 + hash: "0aee5feb94508f70c62cc3255c53bc8a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 175; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 182; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3392 + hash: "840cc661a50dd8bc1af8f6d53ccbece5" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 187; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 191; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3408 + hash: "34a470358ccfb7592cf47399ab6dbc19" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 195; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 198; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3424 + hash: "25c53ff3977ca8422c545c1608782833" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 202; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 205; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3440 + hash: "d4388550549d54e31640cda4672c3bfb" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 209; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 213; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3456 + hash: "8904c3b225a5e732fca4fc605d0fc12a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 216; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 219; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3472 + hash: "415a630fc6a963e99a0e13bf5e461849" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 223; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 226; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3488 + hash: "1526e90e0345e20a3455554c8f249de7" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 229; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 233; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3504 + hash: "2b215748d63e505469d343919b245af9" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 235; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 238; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3520 + hash: "6821e559cb1e45b0cd731c90c3b16934" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 241; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 243; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3536 + hash: "334ddaa8c2cd0506528fe20a21991b03" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 245; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 247; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3552 + hash: "6e651889e91d3de96d9aaf91f4ed9a2c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 250; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 251; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3568 + hash: "0554f22d8079ef0213dc25f9f1b59055" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 252; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 253; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3584 + hash: "1eb0805e4c706af1c7cfa113d32edda1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 255; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 256; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3600 + hash: "482f30ca992e9f92241523a47125d9b4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 257; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 259; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3616 + hash: "6b2bec317fad51fe85bab6a00ced9655" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 261; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 262; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3632 + hash: "acc661684f507375518fc73fe081f61e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 263; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 265; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3648 + hash: "f77143d0d7a3cf8c0163bf950940ad07" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 266; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 267; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3664 + hash: "8d0407ae3f55305e1d9780deaa30c064" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 268; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3680 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 3696 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 3712 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3728 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3744 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3760 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3776 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3792 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3808 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3824 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3840 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3856 + image: "flickableEdit.4.png" + } + Frame { + msec: 3872 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3888 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3904 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3920 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3936 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3952 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3968 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 3984 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4000 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4016 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4032 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4048 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4064 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4080 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4096 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4112 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4128 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4144 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4160 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4176 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4192 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4208 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4224 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4240 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4256 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4272 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4288 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4304 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4320 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4336 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4352 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4368 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4384 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4400 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4416 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4432 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4448 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4464 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4480 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4496 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4512 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4528 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4544 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4560 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4576 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4592 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4608 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4624 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4640 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4656 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4672 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4688 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4704 + hash: "c536946f28abb221cc38d6f438887e17" + } + Frame { + msec: 4720 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4736 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4752 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4768 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4784 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4800 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4816 + image: "flickableEdit.5.png" + } + Frame { + msec: 4832 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4848 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4864 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Frame { + msec: 4880 + hash: "91bd6701cbb1e836a01d1619e0421503" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 266; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4896 + hash: "e5a6693779ffb4e8a333756690a8f9e0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 264; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 262; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4912 + hash: "6acabe70146611091621ef5079cc97ec" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 259; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 256; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4928 + hash: "f75b5eaa04bfec866f088f665edb225e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 253; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 249; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4944 + hash: "1888acd9f3e48348c22e324d67ab2724" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 245; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 240; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4960 + hash: "cd24be347f20371f9d0796fa4a38ad0c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 235; y: 31 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 231; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4976 + hash: "f39bc67a8e83340f8e89cf11c89fb27c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 227; y: 30 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 222; y: 30 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4992 + hash: "80d8019485231c061ba1cf81fd4c42ca" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 217; y: 30 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 213; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5008 + hash: "72893900dfd007ea25a7d75982be6320" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 207; y: 29 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 203; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5024 + hash: "f3d02c4d2f0b8b75b0b6159c0ba8f4db" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 199; y: 28 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 195; y: 28 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5040 + hash: "8ecdf1325bb2084bf6212216bd86b324" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 190; y: 27 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 186; y: 27 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5056 + hash: "be5c62268b337c9d7f69ab01b02c816d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 182; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 178; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5072 + hash: "a0eea6c818a1cb71809aff4613e9655d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 175; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 171; y: 25 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5088 + hash: "27fcf1d4cd00dc7ac54fa92f9c7e2ac2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 168; y: 25 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 165; y: 24 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5104 + hash: "32f6bdc5e2f6ce34436a21dd8ee348dd" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 162; y: 24 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 159; y: 24 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5120 + hash: "4c11c9075429acd4acddc6ede4e5fe69" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 154; y: 23 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 151; y: 23 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5136 + hash: "8fdaf03e0b03698613092303945787d4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 148; y: 23 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 145; y: 22 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5152 + hash: "d9bc269f21d5eade8bb9555d05a86744" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 142; y: 22 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 138; y: 22 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5168 + hash: "f9dd0735682dba198febffcc85c9835a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 135; y: 21 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 131; y: 21 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5184 + hash: "a98869bb654e3b4c1f4d9d0e7e24197a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 128; y: 21 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 124; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5200 + hash: "50ceb9d6d58129b71009079a0028e7c4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 121; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 118; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5216 + hash: "6b8c9413ba1a791e42b06aaa711cdb4e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 114; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 111; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5232 + hash: "f7e12621527fd52e21595cfbf804879c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 108; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 105; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5248 + hash: "d7408be78c80e2b6e5848ee696a79ee0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 103; y: 19 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 99; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5264 + hash: "e648f25a978b9f14cf71d5f1d90edf15" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 96; y: 19 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 93; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5280 + hash: "64ce73aa32f2c08f4cee9a35a103a1d0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 91; y: 19 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 88; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5296 + hash: "1db1d100eb1f97a7c85ab8df3e558188" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 86; y: 18 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 84; y: 18 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5312 + hash: "5604b2f85c3a90f8b29da3fec2f6c509" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 81; y: 18 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 79; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5328 + hash: "fb57c6295d512821945754020ea6a3ce" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 77; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 75; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5344 + hash: "14dfd5b78901c9f63e4f5d0889f77805" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 73; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 72; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5360 + hash: "cc105198e78269be1240785b791c8612" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 69; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 67; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5376 + hash: "1ef97830b4f1be66a4f443ee4573547b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 66; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 64; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5392 + hash: "0ef86edc381e75c39ba067404817edb8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 63; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 60; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5408 + hash: "6a7605f59eb364fbc166aeea7b54695a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 59; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 57; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5424 + hash: "e86bb3698ad8b46e70237088ea056ab0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 55; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 53; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5440 + hash: "56db36cde05d74d6bf8eec0b21515b20" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 51; y: 17 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 49; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5456 + hash: "05adc602e827635ca43c0cff2b5b857d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 47; y: 18 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 45; y: 18 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5472 + hash: "cbdcdf9b7e640a79e2269247bb4d6cc2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 43; y: 18 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 41; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5488 + hash: "bc014e9feb5e69c4042385a6753d1884" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 38; y: 19 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 37; y: 19 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5504 + hash: "544e9ddbedae500955e6cec79eae709c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 35; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 33; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5520 + hash: "ec17a9dba3846c1919b67eaf3d234471" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 30; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 28; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5536 + hash: "8ab538f8baa170798c93e6eb4d5441f8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 27; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 26; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5552 + hash: "1b1636fecff90e602b87dbf84a986d2a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 25; y: 20 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 24; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5568 + hash: "27a84ee3fb8b306e22e50ba753828b7c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 23; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5584 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5600 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 23; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5616 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5632 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5648 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5664 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5680 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5696 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 5712 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5728 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5744 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5760 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5776 + image: "flickableEdit.6.png" + } + Frame { + msec: 5792 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5808 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5824 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5840 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5856 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5872 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5888 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5904 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5920 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5936 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5952 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5968 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 5984 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6000 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6016 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6032 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6048 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6064 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6080 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6096 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6112 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6128 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6144 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6160 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6176 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6192 + hash: "46af738f612bfe0fbf4f83eb847dacb7" + } + Frame { + msec: 6208 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6224 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6240 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6256 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6272 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6288 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6304 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6320 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6336 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6352 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6368 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6384 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6400 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6416 + hash: "ee9cd90fbe594efb411315a97b702a40" + } + Frame { + msec: 6432 + hash: "ee9cd90fbe594efb411315a97b702a40" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.0.png Binary files differnew file mode 100644 index 0000000..7d0d0ae --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.1.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.1.png Binary files differnew file mode 100644 index 0000000..7d612bf --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.1.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.qml new file mode 100644 index 0000000..8c7e380 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.qml @@ -0,0 +1,191 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "linkActivated.0.png" + } + Frame { + msec: 32 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 48 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 64 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 80 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 96 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 112 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 128 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 144 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 160 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 176 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 192 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 208 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 224 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 240 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 256 + hash: "53d97d0966197ea41364511dea13752f" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 21; y: 13 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 272 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Frame { + msec: 288 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Frame { + msec: 304 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 22; y: 11 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 320 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 23; y: 10 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 23; y: 10 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 336 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 352 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 368 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 384 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 400 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 416 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 432 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 448 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 464 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 480 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 496 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 512 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 528 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 544 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 560 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 576 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 592 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 608 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/flickableEdit.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/flickableEdit.qml new file mode 100644 index 0000000..6913fdd --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/flickableEdit.qml @@ -0,0 +1,20 @@ +import QtQuick 1.0 + +Flickable { + width: 200 + height: 50 + contentWidth: 400 + + Column { + anchors.fill: parent + + TextEdit { + selectByMouse: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + TextEdit { + selectByMouse: false + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/justify.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/justify.qml new file mode 100644 index 0000000..4aeb58c --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/justify.qml @@ -0,0 +1,22 @@ +import QtQuick 1.0 +import "../shared" 1.0 + +Rectangle { + width: 450 + height: 250 + + TestTextEdit { + anchors.fill: parent + anchors { leftMargin: 10; rightMargin: 10; topMargin:10; bottomMargin: 10 } + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignJustify + + text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin a aliquet massa. Integer id velit a nibh imperdiet sagittis. Cras fringilla enim non nulla porta bibendum. Integer risus urna, hendrerit non interdum ut, dapibus id velit. Nullam fermentum viverra pellentesque. In molestie scelerisque lorem molestie ultrices. Curabitur dolor arcu, tristique in sodales in, varius sed diam. Quisque magna velit, tincidunt sed ullamcorper sit amet, ornare adipiscing ligula. In hac habitasse platea dictumst. Ut tincidunt urna vel mauris fermentum ornare quis a ligula. Suspendisse cursus volutpat sapien eget cursus." + + Rectangle { + anchors.fill: parent + color: "transparent" + border.color: "red" + } + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/linkActivated.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/linkActivated.qml new file mode 100644 index 0000000..177d475 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/linkActivated.qml @@ -0,0 +1,15 @@ +import QtQuick 1.1 + +Rectangle{ + width: 100 + height: 100 + TextEdit{ + text: '<a href="clicked">Click Me</a> ' + onLinkActivated: txt.text=link; + } + Text{ + id: txt + y:50 + text: "unknown" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.0.png Binary files differnew file mode 100644 index 0000000..fc34b1a --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.1.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.1.png Binary files differnew file mode 100644 index 0000000..fc34b1a --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.1.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.2.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.2.png Binary files differnew file mode 100644 index 0000000..fc34b1a --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.2.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.3.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.3.png Binary files differnew file mode 100644 index 0000000..fb2c90b --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.3.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.4.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.4.png Binary files differnew file mode 100644 index 0000000..fb2c90b --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.4.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.5.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.5.png Binary files differnew file mode 100644 index 0000000..e2231ff --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.5.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.qml new file mode 100644 index 0000000..790dffa --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.qml @@ -0,0 +1,1039 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "qtbug-15818.0.png" + } + Frame { + msec: 32 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 48 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 64 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 80 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 96 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 112 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 128 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 144 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 160 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 176 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 192 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 208 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 224 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 240 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 256 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 272 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 288 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 304 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 320 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 336 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 352 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 368 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 384 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 400 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 416 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 432 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 448 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 464 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 480 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 496 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 512 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 528 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 544 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 560 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 576 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 592 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 608 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 624 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 640 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 656 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 672 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 688 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 704 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 720 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 736 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 752 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 768 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 784 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 800 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 816 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 832 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 848 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 864 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 880 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 26; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 896 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 912 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 928 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 27; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 27; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 944 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 960 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 976 + image: "qtbug-15818.1.png" + } + Frame { + msec: 992 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 4 + button: 1 + buttons: 1 + x: 27; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1008 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1024 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1040 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1056 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1072 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1088 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1104 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 27; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1120 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1136 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1152 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1168 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1184 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1200 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1216 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1232 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1248 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1264 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1280 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1296 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1312 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1328 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1344 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1360 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1376 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1392 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1408 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1424 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1440 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1456 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1472 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1488 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1504 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1520 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1536 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1552 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1568 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1584 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1600 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1616 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1632 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1648 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1664 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1680 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1696 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1712 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1728 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1744 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1760 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1776 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1792 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 43; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1808 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1824 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1840 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1856 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1872 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1888 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 43; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1904 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1920 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1936 + image: "qtbug-15818.2.png" + } + Frame { + msec: 1952 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 4 + button: 1 + buttons: 1 + x: 43; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1968 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 1984 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2000 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2016 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2032 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2048 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2064 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 43; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2080 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2096 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2112 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2128 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2144 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2160 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2176 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2192 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2208 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2224 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2240 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2256 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2272 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2288 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2304 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2320 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2336 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2352 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2368 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2384 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2400 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2416 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2432 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2448 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2464 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2480 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2496 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2512 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2528 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2544 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2560 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2576 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2592 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2608 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2624 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2640 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2656 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2672 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2688 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 54; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2704 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2720 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2736 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2752 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2768 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2784 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 55; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 55; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2800 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2816 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2832 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2848 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 4 + button: 1 + buttons: 1 + x: 55; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2864 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2880 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2896 + image: "qtbug-15818.3.png" + } + Frame { + msec: 2912 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2928 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2944 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2960 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2976 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 55; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2992 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3008 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3024 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3040 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3056 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3072 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3088 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3104 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3120 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3136 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3152 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3168 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3184 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3200 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3216 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3232 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3248 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3264 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3280 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3296 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3312 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3328 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3344 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3360 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3376 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3392 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3408 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3424 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3440 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3456 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3472 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3488 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3504 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3520 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3536 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3552 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3568 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3584 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3600 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3616 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3632 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3648 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3664 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3680 + hash: "270462ec02bce658757e0ea4fb2136b1" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.0.png Binary files differnew file mode 100644 index 0000000..431bed8 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.0.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.1.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.1.png Binary files differnew file mode 100644 index 0000000..9708b4f --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.1.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.2.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.2.png Binary files differnew file mode 100644 index 0000000..7034946 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.2.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.3.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.3.png Binary files differnew file mode 100644 index 0000000..7c56f00 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.3.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.4.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.4.png Binary files differnew file mode 100644 index 0000000..431bed8 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.4.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.5.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.5.png Binary files differnew file mode 100644 index 0000000..30b7a08 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.5.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.6.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.6.png Binary files differnew file mode 100644 index 0000000..54e13cb --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.6.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.7.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.7.png Binary files differnew file mode 100644 index 0000000..34c099b --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.7.png diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.qml new file mode 100644 index 0000000..de69c6a --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data/flickableInput.qml @@ -0,0 +1,3279 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "flickableInput.0.png" + } + Frame { + msec: 32 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 48 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 64 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 80 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 96 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 112 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 128 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 144 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 160 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 176 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 192 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 208 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 224 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 240 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 256 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 272 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 288 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 304 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 320 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 336 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 352 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 368 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 384 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 400 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 416 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 432 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 448 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 464 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 480 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 496 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 512 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 528 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 544 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 560 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 576 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 592 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 608 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 624 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 640 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 656 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 672 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 688 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 704 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 720 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 736 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 752 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 768 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 39; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 784 + hash: "6ef5c0ad42aca699271501f9358d3de6" + } + Frame { + msec: 800 + hash: "6ef5c0ad42aca699271501f9358d3de6" + } + Frame { + msec: 816 + hash: "6ef5c0ad42aca699271501f9358d3de6" + } + Frame { + msec: 832 + hash: "6ef5c0ad42aca699271501f9358d3de6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 41; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 43; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 848 + hash: "6ef5c0ad42aca699271501f9358d3de6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 46; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 50; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 864 + hash: "c54c442eb01186dc8d5be7ff7b242aa1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 53; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 57; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 880 + hash: "8eb5252ed783eae4dd998ea5a451c6bb" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 62; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 68; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 896 + hash: "f80423adedb40b1c9ed88bb171590626" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 73; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 79; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 912 + hash: "afb2d22b60113d05b038fd09b5966151" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 84; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 90; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 928 + hash: "e0a4a243acd0c4f3960ea77fdb5e30c1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 95; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 101; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 944 + hash: "24c5185a748dc4b02fdd40fd2d0420ff" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 106; y: 8 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 111; y: 8 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 960 + hash: "e271a2cd9847828da3e39c1e618f828a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 117; y: 7 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 122; y: 7 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 976 + image: "flickableInput.1.png" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 127; y: 7 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 132; y: 6 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 992 + hash: "3f40064784f716ce75ef9390d90a1eac" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 136; y: 6 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 139; y: 6 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1008 + hash: "77a95b3d8d4682eb8e613bd86ea7b3c7" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 142; y: 5 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 145; y: 5 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1024 + hash: "308ea214fc63e47141623bc436df0efc" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 148; y: 5 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 150; y: 5 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1040 + hash: "3e0a860238ab282aebd733a92321f86f" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 154; y: 4 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 156; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1056 + hash: "ed4c6a18ed003922f5724ebc8e798c6c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 159; y: 4 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 161; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1072 + hash: "ed4c6a18ed003922f5724ebc8e798c6c" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 163; y: 4 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 165; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1088 + hash: "90bc837ada7b6cd08028e790b1a87ae2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 166; y: 4 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 169; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1104 + hash: "90bc837ada7b6cd08028e790b1a87ae2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 170; y: 4 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 171; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1120 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 173; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1136 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 174; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1152 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1168 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 175; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1184 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 176; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1200 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1216 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1232 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1248 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1264 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1280 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1296 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1312 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1328 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1344 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1360 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1376 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 176; y: 4 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1392 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1408 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1424 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1440 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1456 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1472 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1488 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1504 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1520 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1536 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1552 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1568 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1584 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1600 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 1616 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1632 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1648 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1664 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1680 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1696 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1712 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1728 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1744 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1760 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1776 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1792 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1808 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1824 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1840 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1856 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1872 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1888 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1904 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1920 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1936 + image: "flickableInput.2.png" + } + Frame { + msec: 1952 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1968 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 1984 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2000 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2016 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2032 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2048 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2064 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2080 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2096 + hash: "44850466b240778a11644fdea11d26d0" + } + Frame { + msec: 2112 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2128 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2144 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2160 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2176 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2192 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2208 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2224 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2240 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2256 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2272 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Frame { + msec: 2288 + hash: "556d042ec98e01fc1bdb0b2a5032a39e" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 17; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2304 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2320 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2336 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2352 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2368 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2384 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2400 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 2416 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 10 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 12 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2432 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 13 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 14 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2448 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 15 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 17 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2464 + hash: "6865c870740497e31dfeb91e09737206" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 18 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2480 + hash: "541acf0d74762064d970506a40f6600b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 20 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2496 + hash: "956939b887f2bb0d45400214685f1fac" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 21 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2512 + hash: "956939b887f2bb0d45400214685f1fac" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 22 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2528 + hash: "3eff05a088e55df16f0b30546ad8c87f" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 23 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2544 + hash: "3eff05a088e55df16f0b30546ad8c87f" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 25 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2560 + hash: "5b0488fc2a7f840f73d4fc9d17a5a738" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 27 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2576 + hash: "e17d039213c12708ff378789705e281a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 28 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 29 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2592 + hash: "2e2eaab559d0dd7543c2e6e17e0f7740" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 30 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2608 + hash: "49a9baad5178009409e28618a4132544" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 31 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2624 + hash: "49a9baad5178009409e28618a4132544" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 32 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2640 + hash: "a867fe835626e562d5e060c0b2bc4ea3" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 33 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 34 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2656 + hash: "1479e0feffdff866bfd14cbbf76017c7" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 35 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2672 + hash: "1479e0feffdff866bfd14cbbf76017c7" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 36 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 37 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2688 + hash: "dfa99d1eee5ed8d2913c0e603be3ad0e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 38 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2704 + hash: "b55abbe5e7d2c3f5cdaf6dcf5a12c00a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 40 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2720 + hash: "46be0cd1b01d80de8e9d8cd78364fdd4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 41 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2736 + hash: "46be0cd1b01d80de8e9d8cd78364fdd4" + } + Frame { + msec: 2752 + hash: "46be0cd1b01d80de8e9d8cd78364fdd4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 17; y: 42 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2768 + hash: "c9ec87a419171b4d6311a36c952eaef1" + } + Frame { + msec: 2784 + hash: "c9ec87a419171b4d6311a36c952eaef1" + } + Frame { + msec: 2800 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2816 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2832 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2848 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2864 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2880 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2896 + image: "flickableInput.3.png" + } + Frame { + msec: 2912 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2928 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2944 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2960 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2976 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 2992 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 3008 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 17; y: 42 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3024 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 3040 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 3056 + hash: "34cb0a13417b38ff6c78a98a128f1b40" + } + Frame { + msec: 3072 + hash: "09201585ad57e87efda13c469e1bc95d" + } + Frame { + msec: 3088 + hash: "09201585ad57e87efda13c469e1bc95d" + } + Frame { + msec: 3104 + hash: "b816b96270a846ed5776e6f53d507eb8" + } + Frame { + msec: 3120 + hash: "6ee997c78cadb4357b30db81acf4ee40" + } + Frame { + msec: 3136 + hash: "abbab9e07614915a49fc8f30242932a7" + } + Frame { + msec: 3152 + hash: "47f0d0fe751a8ad3dd3f6341d76c929d" + } + Frame { + msec: 3168 + hash: "0304cbed0c52d5486df52312898fe81d" + } + Frame { + msec: 3184 + hash: "6ac82afa8805f1bdb4c67a2f1a1aff32" + } + Frame { + msec: 3200 + hash: "4cc6db0a1dbe6c70d5e2dfe60fe70a51" + } + Frame { + msec: 3216 + hash: "cf04ff1b13f5aa36470fd8ae23523153" + } + Frame { + msec: 3232 + hash: "20fcdfd24f21125d61ac45cbe94e48a7" + } + Frame { + msec: 3248 + hash: "e017109961b5e6c6701c3045f284ebf7" + } + Frame { + msec: 3264 + hash: "e017109961b5e6c6701c3045f284ebf7" + } + Frame { + msec: 3280 + hash: "c2a770b8c95959f4abf91420c0a3e8b2" + } + Frame { + msec: 3296 + hash: "6865c870740497e31dfeb91e09737206" + } + Frame { + msec: 3312 + hash: "6865c870740497e31dfeb91e09737206" + } + Frame { + msec: 3328 + hash: "6865c870740497e31dfeb91e09737206" + } + Frame { + msec: 3344 + hash: "6865c870740497e31dfeb91e09737206" + } + Frame { + msec: 3360 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3376 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3392 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3408 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3424 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3440 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3456 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3472 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3488 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3504 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3520 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3536 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3552 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3568 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3584 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3600 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3616 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3632 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3648 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3664 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3680 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3696 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3712 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3728 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3744 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3760 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3776 + hash: "7b10e4abcc38d2359bb253f8477858e6" + } + Frame { + msec: 3792 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3808 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3824 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3840 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3856 + image: "flickableInput.4.png" + } + Frame { + msec: 3872 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3888 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3904 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3920 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3936 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Frame { + msec: 3952 + hash: "a5480e4c53bbd8c58aa2d574c7644871" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 12; y: 24 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 3968 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Frame { + msec: 3984 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Frame { + msec: 4000 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Frame { + msec: 4016 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Frame { + msec: 4032 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Frame { + msec: 4048 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 13; y: 24 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4064 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 16; y: 24 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 20; y: 24 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4080 + hash: "b6dd7639973f6ee654a7ab6dec2fabbe" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 23; y: 24 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 27; y: 25 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4096 + hash: "ab2ea5988d2b3288d3c57369f68933dc" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 31; y: 25 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 36; y: 25 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4112 + hash: "986834600427959d170d547a1c5ecce0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 41; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 47; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4128 + hash: "52847e87c1fef2d7357c86abb0944df4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 52; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 58; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4144 + hash: "bc68a47163712646cf8439459fb0d100" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 62; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 66; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4160 + hash: "9e9f66e9545c77a2e7ee02d46acd102e" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 72; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 76; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4176 + hash: "4e9e7500185499c5a5f9d65e0e9406a0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 80; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 83; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4192 + hash: "550d6c645bf694c544734d67e2ae5ac3" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 87; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 90; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4208 + hash: "0736bab3f9c1cec0f944003bebe3d499" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 94; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 97; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4224 + hash: "efffb9f6d6a7dacf297530b1cb68a713" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 100; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 103; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4240 + hash: "d5458a8dd8a9bf22e67439c9d8d9c366" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 106; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 109; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4256 + hash: "2d30acf6dc0e186577bd6f7ce858ab92" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 112; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 115; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4272 + hash: "e1a926cc5f7a49c9320a8d49c8a1bb3f" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 117; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 120; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4288 + hash: "cfc9c0bca9e269887ad5c67cc684b753" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 122; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 124; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4304 + hash: "7b561e04ef93399460eb3b4b850c3cab" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 126; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 127; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4320 + hash: "1c17d036e08b24b47239f9a38df3d87d" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 128; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 130; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4336 + hash: "3ec95ad7622048b68a53cfd3fdeac999" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 132; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 133; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4352 + hash: "1e20084ed70b7423885a2d0f06fba660" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 134; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 136; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4368 + hash: "f19e136b3c3d57d8b8e63c64b17c29e4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 137; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4384 + hash: "f19e136b3c3d57d8b8e63c64b17c29e4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 138; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4400 + hash: "894d439a8463cf460e5a66fdcf51a1b5" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 139; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4416 + hash: "894d439a8463cf460e5a66fdcf51a1b5" + } + Frame { + msec: 4432 + hash: "894d439a8463cf460e5a66fdcf51a1b5" + } + Frame { + msec: 4448 + hash: "894d439a8463cf460e5a66fdcf51a1b5" + } + Frame { + msec: 4464 + hash: "03c99addee96254d19db72746f1bef11" + } + Frame { + msec: 4480 + hash: "03c99addee96254d19db72746f1bef11" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 140; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4496 + hash: "cb087b0af44fd7e767b3ff5da1f49790" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 142; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 143; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4512 + hash: "8c36fa6a9c8bfb66e272c8628aec7077" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 145; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 146; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4528 + hash: "971154dba58b18b1d82999f5b6a40cc1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 149; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 151; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4544 + hash: "253397b603f99f7d092dda82d794e944" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 153; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 155; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4560 + hash: "f8ded9e6f36a35a73fbe2264321838ca" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 158; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 161; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4576 + hash: "83b9cec7bbe65ba9d68b089211296116" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 164; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 166; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4592 + hash: "525ffec3a2d2a7a9e0c82f2c98b09ea0" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 168; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 171; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4608 + hash: "c4fb902f66abebb6b7c3489a073e17d4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 172; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 173; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4624 + hash: "0f4526d9f840c0a95e9d145c9822d6e1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 174; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4640 + hash: "db00d1ba5c8416b3418e9e5ca65be5ea" + } + Frame { + msec: 4656 + hash: "db00d1ba5c8416b3418e9e5ca65be5ea" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 175; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4672 + hash: "db00d1ba5c8416b3418e9e5ca65be5ea" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 176; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4688 + hash: "d6f7a50416c3805aeafbdf55905e8276" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 177; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4704 + hash: "d6f7a50416c3805aeafbdf55905e8276" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 178; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4720 + hash: "7586c3d3f46eba4a1abe2fe223e7fde2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 179; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4736 + hash: "7586c3d3f46eba4a1abe2fe223e7fde2" + } + Frame { + msec: 4752 + hash: "7586c3d3f46eba4a1abe2fe223e7fde2" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 180; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 4768 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4784 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4800 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4816 + image: "flickableInput.5.png" + } + Frame { + msec: 4832 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4848 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4864 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4880 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4896 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4912 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4928 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4944 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 4960 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 4976 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 4992 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5008 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5024 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5040 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5056 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5072 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5088 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5104 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5120 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5136 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5152 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5168 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5184 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5200 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5216 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5232 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5248 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5264 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5280 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5296 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5312 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5328 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5344 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5360 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5376 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5392 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5408 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5424 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5440 + hash: "9fcd1fb769766e6019fd7e85cd3e05dc" + } + Frame { + msec: 5456 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 5472 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 5488 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 5504 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 5520 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Frame { + msec: 5536 + hash: "4f63c550ebf5c52fe55558310b366b11" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 177; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5552 + hash: "d6f7a50416c3805aeafbdf55905e8276" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 176; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 175; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5568 + hash: "db00d1ba5c8416b3418e9e5ca65be5ea" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 174; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 171; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5584 + hash: "c4fb902f66abebb6b7c3489a073e17d4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 170; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 168; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5600 + hash: "04c6accf277b5bca4c53c1817f85bafe" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 166; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 164; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5616 + hash: "8eb14964fea798ceccc150310a12fd4b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 162; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 160; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5632 + hash: "83b9cec7bbe65ba9d68b089211296116" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 158; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 157; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5648 + hash: "e59ae71a5636c48e6befa305eba76ec8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 155; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 153; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5664 + hash: "73e178775ee01d28cf03378f267753b1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 151; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 150; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5680 + hash: "253397b603f99f7d092dda82d794e944" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 148; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 146; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5696 + hash: "971154dba58b18b1d82999f5b6a40cc1" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 145; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 144; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5712 + hash: "5bd30e73b37592c06f735541f802f367" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 142; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 140; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5728 + hash: "cb087b0af44fd7e767b3ff5da1f49790" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 138; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5744 + hash: "03c99addee96254d19db72746f1bef11" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 137; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 135; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5760 + hash: "0f76d8a89e383e7e742a3d194d770061" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 133; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 131; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5776 + image: "flickableInput.6.png" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 129; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 127; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5792 + hash: "f047f32822850b2c0fee18b4a8f8a96a" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 124; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 121; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5808 + hash: "160c8c8447a469291fc2f87c2b6c97ce" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 119; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 116; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5824 + hash: "4a9d610f3fa37336c0cab7b4e575713b" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 114; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 112; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5840 + hash: "5a00b185983ad89bcf1ceb036c424dd4" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 110; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 109; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5856 + hash: "a578449e7df3994d0806f7ee2e5a7815" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 107; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5872 + hash: "445cb1ae1934659c3c8b5800bc30fc74" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 106; y: 26 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 105; y: 26 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5888 + hash: "ad22110876a867ca80530ca6d132dfe3" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 105; y: 25 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 105; y: 25 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 5904 + hash: "7a644a888de5691c69543699229ec8ca" + } + Frame { + msec: 5920 + hash: "7a644a888de5691c69543699229ec8ca" + } + Frame { + msec: 5936 + hash: "41c14cc9ea05712aea8d1feb18ca85f3" + } + Frame { + msec: 5952 + hash: "921d476813711e64b9c2272aeff3ed40" + } + Frame { + msec: 5968 + hash: "2dad691263389dce74c99530f188cd20" + } + Frame { + msec: 5984 + hash: "b426ff8ba6d1c52974b117fb8b912b76" + } + Frame { + msec: 6000 + hash: "bbcae0d0547e1cfe9a4db1a6f86bf4b6" + } + Frame { + msec: 6016 + hash: "b8e54bc1a48d7a225cce25c3735c2933" + } + Frame { + msec: 6032 + hash: "b59e0f6eea3c41cedb10ac7a7e2629ef" + } + Frame { + msec: 6048 + hash: "48add89789f9d1be82aedeecf6fda362" + } + Frame { + msec: 6064 + hash: "3cf7a035a5b7dbc81c3da5e99efa5024" + } + Frame { + msec: 6080 + hash: "ff9c7173f7138e273cdbdfa8c6f5fedf" + } + Frame { + msec: 6096 + hash: "bc5e19862dfb38e687d1bfc37690a3b8" + } + Frame { + msec: 6112 + hash: "6ff97512731fd97d3c540245ffff6205" + } + Frame { + msec: 6128 + hash: "290e8c8bf51ced134e965f72a868e467" + } + Frame { + msec: 6144 + hash: "3a63687a5179896572be2e1e0d00766f" + } + Frame { + msec: 6160 + hash: "80f8d13272a23e8816ef45fbbef922fe" + } + Frame { + msec: 6176 + hash: "7888e0ece9522f751417944855824be8" + } + Frame { + msec: 6192 + hash: "3d81f8cde15b7d0b009fc9b46a1144e1" + } + Frame { + msec: 6208 + hash: "3d81f8cde15b7d0b009fc9b46a1144e1" + } + Frame { + msec: 6224 + hash: "d19f7d7d94695ca307b59ffdfea497d0" + } + Frame { + msec: 6240 + hash: "d19f7d7d94695ca307b59ffdfea497d0" + } + Frame { + msec: 6256 + hash: "d19f7d7d94695ca307b59ffdfea497d0" + } + Frame { + msec: 6272 + hash: "d19f7d7d94695ca307b59ffdfea497d0" + } + Frame { + msec: 6288 + hash: "d19f7d7d94695ca307b59ffdfea497d0" + } + Frame { + msec: 6304 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6320 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6336 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6352 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6368 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6384 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6400 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6416 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6432 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6448 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6464 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6480 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6496 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6512 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6528 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6544 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6560 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6576 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6592 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6608 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6624 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6640 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6656 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6672 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6688 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6704 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6720 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6736 + image: "flickableInput.7.png" + } + Frame { + msec: 6752 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6768 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6784 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6800 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6816 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6832 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6848 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6864 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6880 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6896 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6912 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6928 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6944 + hash: "399526752d472f9379d3d218d5d3fdf8" + } + Frame { + msec: 6960 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6976 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 6992 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7008 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7024 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7040 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7056 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7072 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7088 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7104 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7120 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7136 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7152 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7168 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7184 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7200 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7216 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7232 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7248 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7264 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7280 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } + Frame { + msec: 7296 + hash: "ef425c131e1c80a6d62d777963f3d08f" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/flickableInput.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/flickableInput.qml new file mode 100644 index 0000000..7af74ac --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/flickableInput.qml @@ -0,0 +1,21 @@ +import QtQuick 1.0 + +Flickable { + width: 200 + height: 50 + contentWidth: 400 + contentHeight: 100 + + Column { + anchors.fill: parent + + TextInput { + selectByMouse: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + TextInput { + selectByMouse: false + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/qtbug-15818.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/qtbug-15818.qml new file mode 100644 index 0000000..59710a4 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/qtbug-15818.qml @@ -0,0 +1,13 @@ +import QtQuick 1.1 +//Test that doubleclicking on the front of a word only selects that word, and not the word in front + +Item{ + width: 200 + height: 100 + TextInput{ + anchors.fill: parent + readOnly: true + selectByMouse: true + text: "abc a cba test" + } +} diff --git a/tests/auto/declarative/qmlvisual/qmlvisual.pro b/tests/auto/declarative/qmlvisual/qmlvisual.pro index 84df15c..416f8d9 100644 --- a/tests/auto/declarative/qmlvisual/qmlvisual.pro +++ b/tests/auto/declarative/qmlvisual/qmlvisual.pro @@ -19,6 +19,7 @@ symbian: { qdeclarativepathview \ qdeclarativepositioners \ qdeclarativesmoothedanimation \ + qdeclarativespringanimation \ qdeclarativetext \ qdeclarativetextedit \ qdeclarativetextinput \ diff --git a/tests/auto/declarative/qperformancetimer/qperformancetimer.pro b/tests/auto/declarative/qperformancetimer/qperformancetimer.pro new file mode 100644 index 0000000..656bf68 --- /dev/null +++ b/tests/auto/declarative/qperformancetimer/qperformancetimer.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative +SOURCES += tst_qperformancetimer.cpp +macx:CONFIG -= app_bundle + +CONFIG += parallel_test + diff --git a/tests/auto/declarative/qperformancetimer/tst_qperformancetimer.cpp b/tests/auto/declarative/qperformancetimer/tst_qperformancetimer.cpp new file mode 100644 index 0000000..2029c8a --- /dev/null +++ b/tests/auto/declarative/qperformancetimer/tst_qperformancetimer.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 <private/qperformancetimer_p.h> +#include <QObject> +#include <qtest.h> + +class tst_qperformancetimer : public QObject +{ + Q_OBJECT + +public: + tst_qperformancetimer() {} + +private slots: + void units(); +}; + +void tst_qperformancetimer::units() +{ + QPerformanceTimer timer; + timer.start(); + QTest::qWait(300); + qint64 elapsed = timer.elapsed(); + QVERIFY(elapsed > 300000000 && elapsed < 310000000); +} + +QTEST_MAIN(tst_qperformancetimer) + +#include "tst_qperformancetimer.moc" diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index f74da54..07dc5ef 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -2,7 +2,7 @@ # (i.e. QT=core gui network). # The test system is allowed to run these tests before the rest of Qt has # been compiled. -# +# TEMPLATE=subdirs SUBDIRS=\ gestures \ @@ -49,6 +49,7 @@ SUBDIRS=\ qfiledialog \ qfiledialog2 \ qfileiconprovider \ + qfileopenevent \ qfilesystemmodel \ qfocusframe \ qfont \ @@ -81,11 +82,6 @@ SUBDIRS=\ qgroupbox \ qguivariant \ qheaderview \ - qhelpcontentmodel \ - qhelpenginecore \ - qhelpgenerator \ - qhelpindexmodel \ - qhelpprojectdata \ qicoimageformat \ qicon \ qimageiohandler \ @@ -223,10 +219,5 @@ win32:SUBDIRS -= qtextpiecetable qtextpiecetable \ symbian:SUBDIRS -= \ - qhelpcontentmodel \ - qhelpenginecore \ - qhelpgenerator \ - qhelpindexmodel \ - qhelpprojectdata \ qsystemtrayicon \ diff --git a/tests/auto/help.pro b/tests/auto/help.pro new file mode 100644 index 0000000..e6ee552 --- /dev/null +++ b/tests/auto/help.pro @@ -0,0 +1,8 @@ +TEMPLATE=subdirs +SUBDIRS=\ + qhelpcontentmodel \ + qhelpenginecore \ + qhelpgenerator \ + qhelpindexmodel \ + qhelpprojectdata \ + diff --git a/tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml b/tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml index 768a4e2..c966fa1 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml +++ b/tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml @@ -93,5 +93,8 @@ QtObject { //: qsTrId() with comment, meta-data and plurals. //~ well-tested True qsTrId("qtn_bar_baz", 10); + + //% "Source text" + qsTrId("qtn_baz_biz"); } } diff --git a/tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result index 7dac8cb..4843902 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result +++ b/tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result @@ -27,6 +27,11 @@ </translation> <extra-well-tested>True</extra-well-tested> </message> + <message id="qtn_baz_biz"> + <location filename="main.qml" line="98"/> + <source>Source text</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>BarContext</name> diff --git a/tests/auto/moc/tst_moc.cpp b/tests/auto/moc/tst_moc.cpp index 1d78633..bbfa91f 100644 --- a/tests/auto/moc/tst_moc.cpp +++ b/tests/auto/moc/tst_moc.cpp @@ -494,6 +494,7 @@ private slots: void QTBUG12260_defaultTemplate(); void notifyError(); void QTBUG17635_invokableAndProperty(); + void revisions(); signals: void sigWithUnsignedArg(unsigned foo); void sigWithSignedArg(signed foo); @@ -508,6 +509,7 @@ private: bool user2() { return false; }; bool user3() { return false; }; bool userFunction(){ return false; }; + template <class T> void revisions_T(); private: QString qtIncludePath; @@ -1410,6 +1412,118 @@ void tst_Moc::QTBUG17635_invokableAndProperty() QVERIFY(mc.metaObject()->indexOfProperty("numberOfChickens") != -1); } +// If changed, update VersionTestNotify below +class VersionTest : public QObject +{ + Q_OBJECT + Q_PROPERTY(int prop1 READ foo) + Q_PROPERTY(int prop2 READ foo REVISION 2) + Q_ENUMS(TestEnum); + +public: + int foo() const { return 0; } + + Q_INVOKABLE void method1() {} + Q_INVOKABLE Q_REVISION(4) void method2() {} + + enum TestEnum { One, Two }; + +public slots: + void slot1() {} + Q_REVISION(3) void slot2() {} + +signals: + void signal1(); + Q_REVISION(5) void signal2(); + +public slots Q_REVISION(6): + void slot3() {} + void slot4() {} + +signals Q_REVISION(7): + void signal3(); + void signal4(); +}; + +// If changed, update VersionTest above +class VersionTestNotify : public QObject +{ + Q_OBJECT + Q_PROPERTY(int prop1 READ foo NOTIFY fooChanged) + Q_PROPERTY(int prop2 READ foo REVISION 2) + Q_ENUMS(TestEnum); + +public: + int foo() const { return 0; } + + Q_INVOKABLE void method1() {} + Q_INVOKABLE Q_REVISION(4) void method2() {} + + enum TestEnum { One, Two }; + +public slots: + void slot1() {} + Q_REVISION(3) void slot2() {} + +signals: + void fooChanged(); + void signal1(); + Q_REVISION(5) void signal2(); + +public slots Q_REVISION(6): + void slot3() {} + void slot4() {} + +signals Q_REVISION(7): + void signal3(); + void signal4(); +}; + +template <class T> +void tst_Moc::revisions_T() +{ + int idx = T::staticMetaObject.indexOfProperty("prop1"); + QVERIFY(T::staticMetaObject.property(idx).revision() == 0); + idx = T::staticMetaObject.indexOfProperty("prop2"); + QVERIFY(T::staticMetaObject.property(idx).revision() == 2); + + idx = T::staticMetaObject.indexOfMethod("method1()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 0); + idx = T::staticMetaObject.indexOfMethod("method2()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 4); + + idx = T::staticMetaObject.indexOfSlot("slot1()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 0); + idx = T::staticMetaObject.indexOfSlot("slot2()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 3); + + idx = T::staticMetaObject.indexOfSlot("slot3()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 6); + idx = T::staticMetaObject.indexOfSlot("slot4()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 6); + + idx = T::staticMetaObject.indexOfSignal("signal1()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 0); + idx = T::staticMetaObject.indexOfSignal("signal2()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 5); + + idx = T::staticMetaObject.indexOfSignal("signal3()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 7); + idx = T::staticMetaObject.indexOfSignal("signal4()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 7); + + idx = T::staticMetaObject.indexOfEnumerator("TestEnum"); + QCOMPARE(T::staticMetaObject.enumerator(idx).keyCount(), 2); + QCOMPARE(T::staticMetaObject.enumerator(idx).key(0), "One"); +} + +// test using both class that has properties with and without NOTIFY signals +void tst_Moc::revisions() +{ + revisions_T<VersionTest>(); + revisions_T<VersionTestNotify>(); +} + QTEST_APPLESS_MAIN(tst_Moc) #include "tst_moc.moc" diff --git a/tests/auto/networkselftest/networkselftest.pro b/tests/auto/networkselftest/networkselftest.pro index 98e981c..2742fcb 100644 --- a/tests/auto/networkselftest/networkselftest.pro +++ b/tests/auto/networkselftest/networkselftest.pro @@ -12,6 +12,7 @@ wince*: { addFiles.files = rfc3252.txt addFiles.path = . DEPLOYMENT += addFiles + TARGET.CAPABILITY = NetworkServices ReadUserData } else:vxworks*: { DEFINES += SRCDIR=\\\"\\\" } else { diff --git a/tests/auto/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/qcoreapplication/tst_qcoreapplication.cpp index 95055d1..bc69461 100644 --- a/tests/auto/qcoreapplication/tst_qcoreapplication.cpp +++ b/tests/auto/qcoreapplication/tst_qcoreapplication.cpp @@ -59,6 +59,9 @@ private slots: void applicationPid(); void globalPostedEventsCount(); void processEventsAlwaysSendsPostedEvents(); + void reexec(); + void execAfterExit(); + void eventLoopExecAfterExit(); }; class EventSpy : public QObject @@ -524,5 +527,47 @@ void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents() } while (t.elapsed() < 3000); } +void tst_QCoreApplication::reexec() +{ + int argc = 1; + char *argv[] = { "tst_qcoreapplication" }; + QCoreApplication app(argc, argv); + + // exec once + QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); + QCOMPARE(app.exec(), 0); + + // and again + QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); + QCOMPARE(app.exec(), 0); +} + +void tst_QCoreApplication::execAfterExit() +{ + int argc = 1; + char *argv[] = { "tst_qcoreapplication" }; + QCoreApplication app(argc, argv); + + app.exit(1); + QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); + QCOMPARE(app.exec(), 0); +} + +void tst_QCoreApplication::eventLoopExecAfterExit() +{ + int argc = 1; + char *argv[] = { "tst_qcoreapplication" }; + QCoreApplication app(argc, argv); + + // exec once and exit + QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); + QCOMPARE(app.exec(), 0); + + // and again, but this time using a QEventLoop + QEventLoop loop; + QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection); + QCOMPARE(loop.exec(), 0); +} + QTEST_APPLESS_MAIN(tst_QCoreApplication) #include "tst_qcoreapplication.moc" diff --git a/tests/auto/qdbusperformance/tst_qdbusperformance.cpp b/tests/auto/qdbusperformance/tst_qdbusperformance.cpp index 42db697..a5b4b98 100644 --- a/tests/auto/qdbusperformance/tst_qdbusperformance.cpp +++ b/tests/auto/qdbusperformance/tst_qdbusperformance.cpp @@ -125,7 +125,7 @@ void tst_QDBusPerformance::init() void tst_QDBusPerformance::callSpeed() { - QTime timer; + QElapsedTimer timer; int callCount = 0; timer.start(); @@ -141,7 +141,7 @@ void tst_QDBusPerformance::callSpeed() bool tst_QDBusPerformance::executeTest(const char *funcname, int size, const QVariant &data) { - QTime timer; + QElapsedTimer timer; int callCount = 0; qint64 transferred = 0; diff --git a/tests/auto/qeventloop/tst_qeventloop.cpp b/tests/auto/qeventloop/tst_qeventloop.cpp index 7af722f..6860f19 100644 --- a/tests/auto/qeventloop/tst_qeventloop.cpp +++ b/tests/auto/qeventloop/tst_qeventloop.cpp @@ -112,6 +112,10 @@ signals: public: QMutex mutex; QWaitCondition cond; + volatile int result1; + volatile int result2; + MultipleExecThread() : result1(0xdead), result2(0xbeef) {} + void run() { QMutexLocker locker(&mutex); @@ -124,13 +128,13 @@ public: connect(&timer, SIGNAL(timeout()), SLOT(quit()), Qt::DirectConnection); timer.setInterval(1000); timer.start(); - (void) exec(); + result1 = exec(); // this should return immediately, since exit() has been called cond.wakeOne(); cond.wait(&mutex); QEventLoop eventLoop; - (void) eventLoop.exec(); + result2 = eventLoop.exec(); } }; @@ -197,7 +201,9 @@ private slots: void symbianNestedActiveSchedulerLoop(); void processEvents(); void exec(); + void reexec(); void exit(); + void execAfterExit(); void wakeUp(); void quit(); void processEventsExcludeSocket(); @@ -398,7 +404,9 @@ void tst_QEventLoop::exec() } { - // calling exec() after exit()/quit() should return immediately + // calling QEventLoop::exec() after a thread loop has exit()ed should return immediately + // Note: this behaviour differs from QCoreApplication and QEventLoop + // see tst_QCoreApplication::eventLoopExecAfterExit, tst_QEventLoop::reexec MultipleExecThread thread; // start thread and wait for checkpoint @@ -411,6 +419,8 @@ void tst_QEventLoop::exec() thread.cond.wakeOne(); thread.cond.wait(&thread.mutex); QVERIFY(spy.count() > 0); + int v = thread.result1; + QCOMPARE(v, 0); // exec should return immediately spy.clear(); @@ -418,6 +428,8 @@ void tst_QEventLoop::exec() thread.mutex.unlock(); thread.wait(); QCOMPARE(spy.count(), 0); + v = thread.result2; + QCOMPARE(v, -1); } { @@ -462,9 +474,32 @@ void tst_QEventLoop::exec() #endif } +void tst_QEventLoop::reexec() +{ + QEventLoop loop; + + // exec once + QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection); + QCOMPARE(loop.exec(), 0); + + // and again + QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection); + QCOMPARE(loop.exec(), 0); +} + void tst_QEventLoop::exit() { DEPENDS_ON(exec()); } +void tst_QEventLoop::execAfterExit() +{ + QEventLoop loop; + EventLoopExiter obj(&loop); + + QMetaObject::invokeMethod(&obj, "exit", Qt::QueuedConnection); + loop.exit(1); + QCOMPARE(loop.exec(), 0); +} + void tst_QEventLoop::wakeUp() { EventLoopThread thread; diff --git a/tests/auto/qfileopenevent/qfileopenevent.pro b/tests/auto/qfileopenevent/qfileopenevent.pro new file mode 100644 index 0000000..45978d7 --- /dev/null +++ b/tests/auto/qfileopenevent/qfileopenevent.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS = test qfileopeneventexternal diff --git a/tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp b/tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp new file mode 100644 index 0000000..0a5e032 --- /dev/null +++ b/tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 <QtGui> +#include <QApplication> +#include <QEvent> + +struct MyApplication : public QApplication +{ + MyApplication(int& argc, char** argv) + : QApplication(argc, argv) + {} + + bool event(QEvent * event) + { + if (event->type() == QEvent::FileOpen) { + QFileOpenEvent* ev = static_cast<QFileOpenEvent *>(event); + QFile file; + bool ok = ev->openFile(file, QFile::Append | QFile::Unbuffered); + if (ok) + file.write(QByteArray("+external")); + return true; + } else { + return QApplication::event(event); + } + } +}; + +int main(int argc, char *argv[]) +{ + MyApplication a(argc, argv); + a.sendPostedEvents(&a, QEvent::FileOpen); + return 0; +} diff --git a/tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro b/tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro new file mode 100644 index 0000000..b95ed45 --- /dev/null +++ b/tests/auto/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +TARGET = qfileopeneventexternal +QT += core gui +SOURCES += qfileopeneventexternal.cpp +symbian: { + RSS_RULES += "embeddability=KAppEmbeddable;" + RSS_RULES.datatype_list += "priority = EDataTypePriorityHigh; type = \"application/x-tst_qfileopenevent\";" + LIBS += -lapparc \ + -leikcore -lefsrv -lcone +} diff --git a/tests/auto/qfileopenevent/test/test.pro b/tests/auto/qfileopenevent/test/test.pro new file mode 100644 index 0000000..3f16dcf --- /dev/null +++ b/tests/auto/qfileopenevent/test/test.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +TARGET = tst_qfileopenevent +HEADERS += +SOURCES += tst_qfileopenevent.cpp +symbian { + LIBS+=-lefsrv -lapgrfx -lapmime +} diff --git a/tests/auto/qfileopenevent/test/tst_qfileopenevent.cpp b/tests/auto/qfileopenevent/test/tst_qfileopenevent.cpp new file mode 100644 index 0000000..1177131 --- /dev/null +++ b/tests/auto/qfileopenevent/test/tst_qfileopenevent.cpp @@ -0,0 +1,362 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 <QtTest/QtTest> +#include <QEvent> + +#ifdef Q_OS_SYMBIAN +#include <apgcli.h> +#include "private/qcore_symbian_p.h" +#endif + +class tst_qfileopenevent : public QObject +{ + Q_OBJECT +public: + tst_qfileopenevent(){} + ~tst_qfileopenevent(); + +public slots: + void initTestCase(); + +private slots: + void constructor(); + void fileOpen(); + void handleLifetime(); + void multiOpen(); + void sendAndReceive(); + void external_data(); + void external(); + +private: +#ifdef Q_OS_SYMBIAN + RFile createRFile(const TDesC& filename, const TDesC8& content); +#else + void createFile(const QString &filename, const QByteArray &content); +#endif + QFileOpenEvent * createFileAndEvent(const QString &filename, const QByteArray &content); + void checkReadAndWrite(QFileOpenEvent& event, const QByteArray& readContent, const QByteArray& writeContent, bool writeOk); + QByteArray readFileContent(QFileOpenEvent& event); + bool appendFileContent(QFileOpenEvent& event, const QByteArray& writeContent); + + bool event(QEvent *); + +private: +#ifdef Q_OS_SYMBIAN + struct AutoRFs : public RFs + { + AutoRFs() + { + qt_symbian_throwIfError(Connect()); + qt_symbian_throwIfError(ShareProtected()); + } + + ~AutoRFs() + { + Close(); + } + }; + AutoRFs fsSession; +#endif +}; + +tst_qfileopenevent::~tst_qfileopenevent() +{ +}; + +void tst_qfileopenevent::initTestCase() +{ +} + +#ifdef Q_OS_SYMBIAN +RFile tst_qfileopenevent::createRFile(const TDesC& filename, const TDesC8& content) +{ + RFile file; + qt_symbian_throwIfError(file.Replace(fsSession, filename, EFileWrite)); + qt_symbian_throwIfError(file.Write(content)); + return file; +} +#else +void tst_qfileopenevent::createFile(const QString &filename, const QByteArray &content) +{ + QFile file(filename); + file.open(QFile::WriteOnly); + file.write(content); + file.close(); +} +#endif + +QFileOpenEvent * tst_qfileopenevent::createFileAndEvent(const QString &filename, const QByteArray &content) +{ +#ifdef Q_OS_SYMBIAN + RFile rFile = createRFile(qt_QString2TPtrC(filename), TPtrC8((TText8*)content.constData(), content.size())); + QScopedPointer<RFile, QScopedPointerRCloser<RFile> > closeRFile(&rFile); + return new QFileOpenEvent(rFile); +#else + createFile(filename, content); + return new QFileOpenEvent(filename); +#endif +} + +void tst_qfileopenevent::constructor() +{ + // check that filename get/set works + QFileOpenEvent nameTest(QLatin1String("fileNameTest")); + QCOMPARE(nameTest.file(), QLatin1String("fileNameTest")); + + // check that url get/set works + QFileOpenEvent urlTest(QUrl(QLatin1String("file:///urlNameTest"))); + QCOMPARE(urlTest.url().toString(), QLatin1String("file:///urlNameTest")); + +#ifdef Q_OS_SYMBIAN + // check that RFile construction works + RFile rFile = createRFile(_L("testRFile"), _L8("test content")); + QFileOpenEvent rFileTest(rFile); + QString targetName(QLatin1String("testRFile")); + QCOMPARE(rFileTest.file().right(targetName.size()), targetName); + QCOMPARE(rFileTest.url().toString().right(targetName.size()), targetName); + rFile.Close(); +#endif +} + +QByteArray tst_qfileopenevent::readFileContent(QFileOpenEvent& event) +{ + QFile file; + event.openFile(file, QFile::ReadOnly); + file.seek(0); + QByteArray data = file.readAll(); + return data; +} + +bool tst_qfileopenevent::appendFileContent(QFileOpenEvent& event, const QByteArray& writeContent) +{ + QFile file; + bool ok = event.openFile(file, QFile::Append | QFile::Unbuffered); + if (ok) + ok = file.write(writeContent) == writeContent.size(); + return ok; +} + +void tst_qfileopenevent::checkReadAndWrite(QFileOpenEvent& event, const QByteArray& readContent, const QByteArray& writeContent, bool writeOk) +{ + QCOMPARE(readFileContent(event), readContent); + QCOMPARE(appendFileContent(event, writeContent), writeOk); + QCOMPARE(readFileContent(event), writeOk ? readContent+writeContent : readContent); +} + +void tst_qfileopenevent::fileOpen() +{ +#ifdef Q_OS_SYMBIAN + // create writeable file + { + RFile rFile = createRFile(_L("testFileOpen"), _L8("test content")); + QFileOpenEvent rFileTest(rFile); + checkReadAndWrite(rFileTest, QByteArray("test content"), QByteArray("+RFileWrite"), true); + rFile.Close(); + } + + // open read-only RFile + { + RFile rFile; + int err = rFile.Open(fsSession, _L("testFileOpen"), EFileRead); + QFileOpenEvent rFileTest(rFile); + checkReadAndWrite(rFileTest, QByteArray("test content+RFileWrite"), QByteArray("+RFileRead"), false); + rFile.Close(); + } +#else + createFile(QLatin1String("testFileOpen"), QByteArray("test content+RFileWrite")); +#endif + + // filename event + QUrl fileUrl; // need to get the URL during the file test, for use in the URL test + { + QFileOpenEvent nameTest(QLatin1String("testFileOpen")); + fileUrl = nameTest.url(); + checkReadAndWrite(nameTest, QByteArray("test content+RFileWrite"), QByteArray("+nameWrite"), true); + } + + // url event + { + QFileOpenEvent urlTest(fileUrl); + checkReadAndWrite(urlTest, QByteArray("test content+RFileWrite+nameWrite"), QByteArray("+urlWrite"), true); + } + + QFile::remove(QLatin1String("testFileOpen")); +} + +void tst_qfileopenevent::handleLifetime() +{ + QScopedPointer<QFileOpenEvent> event(createFileAndEvent(QLatin1String("testHandleLifetime"), QByteArray("test content"))); + + // open a QFile after the original RFile is closed + QFile qFile; + QCOMPARE(event->openFile(qFile, QFile::Append | QFile::Unbuffered), true); + event.reset(0); + + // write to the QFile after the event is closed + QString writeContent(QLatin1String("+closed original handles")); + QCOMPARE(int(qFile.write(writeContent.toUtf8())), writeContent.size()); + qFile.close(); + + // check the content + QFile check("testHandleLifetime"); + check.open(QFile::ReadOnly); + QString content(check.readAll()); + QCOMPARE(content, QLatin1String("test content+closed original handles")); + check.close(); + + QFile::remove(QLatin1String("testHandleLifetime")); +} + +void tst_qfileopenevent::multiOpen() +{ + QScopedPointer<QFileOpenEvent> event(createFileAndEvent(QLatin1String("testMultiOpen"), QByteArray("itlum"))); + + QFile files[5]; + for (int i=0; i<5; i++) { + QCOMPARE(event->openFile(files[i], QFile::ReadOnly), true); + } + for (int i=0; i<5; i++) + files[i].seek(i); + QString str; + for (int i=4; i>=0; i--) { + char c; + files[i].getChar(&c); + str.append(c); + files[i].close(); + } + QCOMPARE(str, QLatin1String("multi")); + + QFile::remove(QLatin1String("testMultiOpen")); +} + +bool tst_qfileopenevent::event(QEvent *event) +{ + if (event->type() != QEvent::FileOpen) + return QObject::event(event); + QFileOpenEvent* fileOpenEvent = static_cast<QFileOpenEvent *>(event); + appendFileContent(*fileOpenEvent, "+received"); + return true; +} + +void tst_qfileopenevent::sendAndReceive() +{ + QScopedPointer<QFileOpenEvent> event(createFileAndEvent(QLatin1String("testSendAndReceive"), QByteArray("sending"))); + + QCoreApplication::instance()->postEvent(this, event.take()); + QCoreApplication::instance()->processEvents(); + + // QTBUG-17468: On Mac, processEvents doesn't always process posted events + QCoreApplication::instance()->sendPostedEvents(); + + // check the content + QFile check("testSendAndReceive"); + QCOMPARE(check.open(QFile::ReadOnly), true); + QString content(check.readAll()); + QCOMPARE(content, QLatin1String("sending+received")); + check.close(); + + QFile::remove(QLatin1String("testSendAndReceive")); +} + +void tst_qfileopenevent::external_data() +{ + QTest::addColumn<QString>("filename"); + QTest::addColumn<QByteArray>("targetContent"); + QTest::addColumn<bool>("sendHandle"); + + QString privateName(QLatin1String("tst_qfileopenevent_external")); + QString publicName(QLatin1String("C:\\Data\\tst_qfileopenevent_external")); + QByteArray writeSuccess("original+external"); + QByteArray writeFail("original"); + QTest::newRow("public name") << publicName << writeSuccess << false; + QTest::newRow("data caged name") << privateName << writeFail << false; + QTest::newRow("public handle") << publicName << writeSuccess << true; + QTest::newRow("data caged handle") << privateName << writeSuccess << true; +} + +void tst_qfileopenevent::external() +{ +#ifndef Q_OS_SYMBIAN + QSKIP("external app file open test only valid in Symbian", SkipAll); +#else + + QFETCH(QString, filename); + QFETCH(QByteArray, targetContent); + QFETCH(bool, sendHandle); + + RFile rFile = createRFile(qt_QString2TPtrC(filename), _L8("original")); + + // launch app with the file + RApaLsSession apa; + QCOMPARE(apa.Connect(), KErrNone); + TThreadId threadId; + TDataType type(_L8("application/x-tst_qfileopenevent")); + if (sendHandle) { + QCOMPARE(apa.StartDocument(rFile, type, threadId), KErrNone); + rFile.Close(); + } else { + TFileName fullName; + rFile.FullName(fullName); + rFile.Close(); + QCOMPARE(apa.StartDocument(fullName, type, threadId), KErrNone); + } + + // wait for app exit + RThread appThread; + if (appThread.Open(threadId) == KErrNone) { + TRequestStatus status; + appThread.Logon(status); + User::WaitForRequest(status); + } + + // check the contents + QFile check(filename); + QCOMPARE(check.open(QFile::ReadOnly), true); + QCOMPARE(check.readAll(), targetContent); + bool ok = check.remove(); + + QFile::remove(filename); +#endif +} + +QTEST_MAIN(tst_qfileopenevent) +#include "tst_qfileopenevent.moc" diff --git a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp index cf0406c..53781c9 100644 --- a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -980,8 +980,12 @@ void tst_QFileSystemModel::drives() model.setRootPath(path); model.fetchMore(QModelIndex()); QFileInfoList drives = QDir::drives(); + int driveCount = 0; + foreach(const QFileInfo& driveRoot, drives) + if (driveRoot.exists()) + driveCount++; QTest::qWait(5000); - QTRY_COMPARE(model.rowCount(), drives.count()); + QTRY_COMPARE(model.rowCount(), driveCount); } void tst_QFileSystemModel::dirsBeforeFiles() diff --git a/tests/auto/qglthreads/tst_qglthreads.cpp b/tests/auto/qglthreads/tst_qglthreads.cpp index 434fd9d..45c8cbc 100644 --- a/tests/auto/qglthreads/tst_qglthreads.cpp +++ b/tests/auto/qglthreads/tst_qglthreads.cpp @@ -210,7 +210,7 @@ public: // That's why we create only small textures. width = 50; height = 20; -#else +#endif QImage image(width, height, QImage::Format_RGB32); QPainter p(&image); p.fillRect(image.rect(), QColor(rand() % 256, rand() % 256, rand() % 256)); diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index b221cd9..d446ca7 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -3838,6 +3838,23 @@ public: mutable int queryCalls; }; +class TestInputContext : public QInputContext +{ +public: + TestInputContext() {} + + QString identifierName() { return QString(); } + QString language() { return QString(); } + + void reset() { + ++resetCalls; + sendEvent(QInputMethodEvent()); } + + bool isComposing() const { return false; } + + int resetCalls; +}; + void tst_QGraphicsScene::inputMethod() { QFETCH(int, flags); @@ -3847,14 +3864,22 @@ void tst_QGraphicsScene::inputMethod() item->setFlags((QGraphicsItem::GraphicsItemFlags)flags); QGraphicsScene scene; - QEvent activate(QEvent::WindowActivate); - QApplication::sendEvent(&scene, &activate); + QGraphicsView view(&scene); + TestInputContext inputContext; + view.setInputContext(&inputContext); + view.show(); + QApplication::setActiveWindow(&view); + view.setFocus(); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + inputContext.resetCalls = 0; scene.addItem(item); QInputMethodEvent event; scene.setFocusItem(item); QCOMPARE(!!(item->flags() & QGraphicsItem::ItemIsFocusable), scene.focusItem() == item); + QCOMPARE(inputContext.resetCalls, 0); item->eventCalls = 0; qApp->sendEvent(&scene, &event); @@ -3865,6 +3890,9 @@ void tst_QGraphicsScene::inputMethod() QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0); scene.setFocusItem(0); + // the input context is reset twice, once because an item has lost focus and again because + // the Qt::WA_InputMethodEnabled flag is cleared because no item has focus. + QCOMPARE(inputContext.resetCalls, callFocusItem ? 2 : 0); QCOMPARE(item->eventCalls, callFocusItem ? 2 : 0); // verify correct delivery of "reset" event QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0); // verify that value is unaffected diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index f8fc5d0..ca6b4d2 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -4146,11 +4146,14 @@ void tst_QGraphicsView::inputContextReset() inputContext.resets = 0; scene.setFocusItem(0); - QCOMPARE(inputContext.resets, 1); + // the input context is reset twice, once because an item has lost focus and again because + // the Qt::WA_InputMethodEnabled flag is cleared because no item has focus. + QCOMPARE(inputContext.resets, 2); // introduce another item that is focusable but does not accept input methods QGraphicsItem *item2 = new QGraphicsRectItem; - item1->setFlags(QGraphicsItem::ItemIsFocusable); + item2->setFlags(QGraphicsItem::ItemIsFocusable); + scene.addItem(item2); inputContext.resets = 0; scene.setFocusItem(item2); @@ -4159,6 +4162,11 @@ void tst_QGraphicsView::inputContextReset() inputContext.resets = 0; scene.setFocusItem(item1); QCOMPARE(inputContext.resets, 0); + + // test changing between between items that accept input methods. + item2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod); + scene.setFocusItem(item2); + QCOMPARE(inputContext.resets, 1); } void tst_QGraphicsView::indirectPainting() diff --git a/tests/auto/qimagereader/images/corrupt-pixel-count.xpm b/tests/auto/qimagereader/images/corrupt-pixel-count.xpm new file mode 100644 index 0000000..3a736ff --- /dev/null +++ b/tests/auto/qimagereader/images/corrupt-pixel-count.xpm @@ -0,0 +1,11 @@ +/* XPM */ +static const char *marble_xpm[] = { +/* width height num_colors chars_per_pixel */ +"2 2 2 -2", +/* colors */ +"a c #adadad", +"b c #dedede", +/* pixels */ +"ab", +"ba" +}; diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index 7c2aee8..f02fd6a 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -1410,6 +1410,9 @@ void tst_QImageReader::readFromResources_data() QTest::newRow("corrupt-pixels.xpm") << QString("corrupt-pixels.xpm") << QByteArray("xpm") << QSize(0, 0) << QString("QImage: XPM pixels missing on image line 3"); + QTest::newRow("corrupt-pixel-count.xpm") << QString("corrupt-pixel-count.xpm") + << QByteArray("xpm") << QSize(0, 0) + << QString(""); QTest::newRow("marble.xpm") << QString("marble.xpm") << QByteArray("xpm") << QSize(240, 240) << QString(""); diff --git a/tests/auto/qinputcontext/tst_qinputcontext.cpp b/tests/auto/qinputcontext/tst_qinputcontext.cpp index 800f9de..6a047f2 100644 --- a/tests/auto/qinputcontext/tst_qinputcontext.cpp +++ b/tests/auto/qinputcontext/tst_qinputcontext.cpp @@ -88,6 +88,7 @@ private slots: void closeSoftwareInputPanel(); void selections(); void focusProxy(); + void contextInheritance(); void symbianTestCoeFepInputContext_data(); void symbianTestCoeFepInputContext(); void symbianTestCoeFepAutoCommit_data(); @@ -473,6 +474,37 @@ void tst_QInputContext::focusProxy() QCOMPARE(gic->focusWidget(), &proxy); } +void tst_QInputContext::contextInheritance() +{ + QWidget parent; + QWidget child(&parent); + + parent.setAttribute(Qt::WA_InputMethodEnabled, true); + child.setAttribute(Qt::WA_InputMethodEnabled, true); + + QCOMPARE(parent.inputContext(), qApp->inputContext()); + QCOMPARE(child.inputContext(), qApp->inputContext()); + + QInputContext *qic = new QFilterInputContext; + parent.setInputContext(qic); + QCOMPARE(parent.inputContext(), qic); + QCOMPARE(child.inputContext(), qic); + + parent.setAttribute(Qt::WA_InputMethodEnabled, false); + QVERIFY(!parent.inputContext()); + QCOMPARE(child.inputContext(), qic); + parent.setAttribute(Qt::WA_InputMethodEnabled, true); + + parent.setInputContext(0); + QCOMPARE(parent.inputContext(), qApp->inputContext()); + QCOMPARE(child.inputContext(), qApp->inputContext()); + + qic = new QFilterInputContext; + qApp->setInputContext(qic); + QCOMPARE(parent.inputContext(), qic); + QCOMPARE(child.inputContext(), qic); +} + #ifdef QT_WEBKIT_LIB class AutoWebView : public QWebView { diff --git a/tests/auto/qmutex/tst_qmutex.cpp b/tests/auto/qmutex/tst_qmutex.cpp index 3c4c767..ea983cb 100644 --- a/tests/auto/qmutex/tst_qmutex.cpp +++ b/tests/auto/qmutex/tst_qmutex.cpp @@ -67,6 +67,7 @@ private slots: void lock_unlock_locked_tryLock(); void stressTest(); void tryLockRace(); + void qtbug16115_trylock(); }; static const int iterations = 100; @@ -464,5 +465,42 @@ void tst_QMutex::tryLockRace() TryLockRaceThread::mutex.unlock(); } +static volatile int qtbug16115_trylock_counter; + +void tst_QMutex::qtbug16115_trylock() +{ + //Used to deadlock on unix + struct TrylockThread : QThread { + TrylockThread(QMutex &mut) : mut(mut) {} + QMutex &mut; + void run() { + for (int i = 0; i < 1000000; ++i) { + if (mut.tryLock(0)) { + Q_ASSERT((++qtbug16115_trylock_counter) == 1); + Q_ASSERT((--qtbug16115_trylock_counter) == 0); + mut.unlock(); + } + } + } + }; + QMutex mut; + TrylockThread t1(mut); + TrylockThread t2(mut); + TrylockThread t3(mut); + t1.start(); + t2.start(); + t3.start(); + + for (int i = 0; i < 1000000; ++i) { + mut.lock(); + Q_ASSERT((++qtbug16115_trylock_counter) == 1); + Q_ASSERT((--qtbug16115_trylock_counter) == 0); + mut.unlock(); + } + t1.wait(); + t2.wait(); + t3.wait(); +} + QTEST_MAIN(tst_QMutex) #include "tst_qmutex.moc" diff --git a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp index 37fc9cd..3315836 100644 --- a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp +++ b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp @@ -60,8 +60,6 @@ QT_USE_NAMESPACE Q_DECLARE_METATYPE(QNetworkConfiguration) Q_DECLARE_METATYPE(QNetworkConfiguration::Type); -Q_DECLARE_METATYPE(QNetworkSession::State); -Q_DECLARE_METATYPE(QNetworkSession::SessionError); class tst_QNetworkSession : public QObject { @@ -126,8 +124,6 @@ QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfigur void tst_QNetworkSession::initTestCase() { - qRegisterMetaType<QNetworkSession::State>("QNetworkSession::State"); - qRegisterMetaType<QNetworkSession::SessionError>("QNetworkSession::SessionError"); qRegisterMetaType<QNetworkConfiguration>("QNetworkConfiguration"); qRegisterMetaType<QNetworkConfiguration::Type>("QNetworkConfiguration::Type"); diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp index b697431..2a8874e 100644 --- a/tests/auto/qprocess/tst_qprocess.cpp +++ b/tests/auto/qprocess/tst_qprocess.cpp @@ -249,6 +249,8 @@ void tst_QProcess::constructing() char c; QCOMPARE(process.read(&c, 1), qlonglong(-1)); QCOMPARE(process.write(&c, 1), qlonglong(-1)); + + QProcess proc2; } void tst_QProcess::simpleStart() @@ -265,7 +267,7 @@ void tst_QProcess::simpleStart() process->start("testProcessNormal/testProcessNormal"); if (process->state() != QProcess::Starting) QCOMPARE(process->state(), QProcess::Running); - QVERIFY(process->waitForStarted(5000)); + QVERIFY2(process->waitForStarted(5000), qPrintable(process->errorString())); QCOMPARE(process->state(), QProcess::Running); #if defined(Q_OS_WINCE) // Note: This actually seems incorrect, it will only exit the while loop when finishing fails @@ -277,7 +279,7 @@ void tst_QProcess::simpleStart() while (process->waitForReadyRead(5000)) { } #endif - QCOMPARE(process->state(), QProcess::NotRunning); + QCOMPARE(int(process->state()), int(QProcess::NotRunning)); delete process; process = 0; diff --git a/tests/auto/qscriptclass/tst_qscriptclass.cpp b/tests/auto/qscriptclass/tst_qscriptclass.cpp index 16f09b6..5286a5a 100644 --- a/tests/auto/qscriptclass/tst_qscriptclass.cpp +++ b/tests/auto/qscriptclass/tst_qscriptclass.cpp @@ -65,15 +65,27 @@ public: private slots: void newInstance(); - void getAndSetProperty(); + void setScriptClassOfExistingObject(); + void setScriptClassOfNonQtScriptObject(); + void getAndSetPropertyFromCpp(); + void getAndSetPropertyFromJS(); + void deleteUndeletableProperty(); + void writeReadOnlyProperty(); + void writePropertyWithoutWriteAccess(); void getProperty_invalidValue(); void enumerate(); - void extension(); + void extension_None(); + void extension_Callable(); + void extension_Callable_construct(); + void extension_HasInstance(); void originalProperties1(); void originalProperties2(); void originalProperties3(); void originalProperties4(); void defaultImplementations(); + void scriptClassObjectInPrototype(); + void scriptClassWithNullEngine(); + void scriptClassInOtherEngine(); }; tst_QScriptClass::tst_QScriptClass() @@ -306,7 +318,12 @@ void TestClass::setProperty(QScriptValue &object, const QScriptString &name, CustomProperty *prop = findCustomProperty(name); if (!prop) return; - prop->value = value; + if (prop->pflags & QScriptValue::ReadOnly) + return; + if (!value.isValid()) // deleteProperty() requested + removeCustomProperty(name); + else + prop->value = value; } QScriptValue::PropertyFlags TestClass::propertyFlags( @@ -611,7 +628,12 @@ void tst_QScriptClass::newInstance() QCOMPARE(obj2.scriptClass(), (QScriptClass*)&cls); QVERIFY(!obj2.equals(obj1)); QVERIFY(!obj2.strictlyEquals(obj1)); +} +void tst_QScriptClass::setScriptClassOfExistingObject() +{ + QScriptEngine eng; + TestClass cls(&eng); QScriptValue obj3 = eng.newObject(); QCOMPARE(obj3.scriptClass(), (QScriptClass*)0); obj3.setScriptClass(&cls); @@ -625,7 +647,12 @@ void tst_QScriptClass::newInstance() TestClass cls2(&eng); obj3.setScriptClass(&cls2); QCOMPARE(obj3.scriptClass(), (QScriptClass*)&cls2); +} +void tst_QScriptClass::setScriptClassOfNonQtScriptObject() +{ + QScriptEngine eng; + TestClass cls(&eng); // undefined behavior really, but shouldn't crash QScriptValue arr = eng.newArray(); QVERIFY(arr.isArray()); @@ -639,7 +666,7 @@ void tst_QScriptClass::newInstance() QVERIFY(arr.isObject()); } -void tst_QScriptClass::getAndSetProperty() +void tst_QScriptClass::getAndSetPropertyFromCpp() { QScriptEngine eng; @@ -651,7 +678,9 @@ void tst_QScriptClass::getAndSetProperty() QScriptString bar = eng.toStringHandle("bar"); QScriptValue num(&eng, 123); - // should behave just like normal + // Initially our TestClass instances have no custom properties, + // and queryProperty() will always return false. + // Hence, the properties will be created as normal JS properties. for (int x = 0; x < 2; ++x) { QScriptValue &o = (x == 0) ? obj1 : obj2; for (int y = 0; y < 2; ++y) { @@ -757,6 +786,80 @@ void tst_QScriptClass::getAndSetProperty() QVERIFY(!obj1.property(bar).isValid()); } +void tst_QScriptClass::getAndSetPropertyFromJS() +{ + QScriptEngine eng; + TestClass cls(&eng); + cls.addCustomProperty(eng.toStringHandle("x"), + QScriptClass::HandlesReadAccess + | QScriptClass::HandlesWriteAccess, + /*id=*/1, /*flags=*/0, /*value=*/123); + eng.globalObject().setProperty("o", eng.newObject(&cls)); + + // Accessing a custom property + QCOMPARE(eng.evaluate("o.x").toInt32(), 123); + QCOMPARE(eng.evaluate("o.x = 456; o.x").toInt32(), 456); + + // Accessing a new JS property + QVERIFY(eng.evaluate("o.y").isUndefined()); + QCOMPARE(eng.evaluate("o.y = 789; o.y").toInt32(), 789); + + // Deleting custom property + QVERIFY(eng.evaluate("delete o.x").toBool()); + QVERIFY(eng.evaluate("o.x").isUndefined()); + + // Deleting JS property + QVERIFY(eng.evaluate("delete o.y").toBool()); + QVERIFY(eng.evaluate("o.y").isUndefined()); +} + +void tst_QScriptClass::deleteUndeletableProperty() +{ + QScriptEngine eng; + TestClass cls(&eng); + cls.addCustomProperty(eng.toStringHandle("x"), QScriptClass::HandlesWriteAccess, + /*id=*/0, QScriptValue::Undeletable, QScriptValue()); + eng.globalObject().setProperty("o", eng.newObject(&cls)); + QVERIFY(!eng.evaluate("delete o.x").toBool()); +} + +void tst_QScriptClass::writeReadOnlyProperty() +{ + QScriptEngine eng; + TestClass cls(&eng); + cls.addCustomProperty(eng.toStringHandle("x"), + QScriptClass::HandlesReadAccess + | QScriptClass::HandlesWriteAccess, + /*id=*/0, QScriptValue::ReadOnly, 123); + eng.globalObject().setProperty("o", eng.newObject(&cls)); + // Note that if a property is read-only, the setProperty() + // reimplementation will still get called; it's up to that + // function to respect the ReadOnly flag. + QCOMPARE(eng.evaluate("o.x = 456; o.x").toInt32(), 123); +} + +void tst_QScriptClass::writePropertyWithoutWriteAccess() +{ + QScriptEngine eng; + TestClass cls(&eng); + cls.addCustomProperty(eng.toStringHandle("x"), + QScriptClass::HandlesReadAccess, + /*id=*/0, /*flags=*/0, 123); + eng.globalObject().setProperty("o", eng.newObject(&cls)); + QCOMPARE(eng.evaluate("o.x").toInt32(), 123); + + // This will create a JS property on the instance that + // shadows the custom property. + // This behavior is not documented. It might be more + // intuitive to treat a property that only handles read + // access as a read-only, non-shadowable property. + QCOMPARE(eng.evaluate("o.x = 456; o.x").toInt32(), 456); + + QVERIFY(eng.evaluate("delete o.x").toBool()); + // Now the custom property is seen again. + QCOMPARE(eng.evaluate("o.x").toInt32(), 123); +} + void tst_QScriptClass::getProperty_invalidValue() { QScriptEngine eng; @@ -806,10 +909,12 @@ void tst_QScriptClass::enumerate() cls.setIterationEnabled(true); QScriptValueIterator it(obj); + // This test relies on the order in which properties are enumerated, + // which we don't guarantee. However, for compatibility's sake we prefer + // that normal JS properties come before QScriptClass properties. for (int x = 0; x < 2; ++x) { QVERIFY(it.hasNext()); it.next(); - QEXPECT_FAIL("", "", Abort); QVERIFY(it.scriptName() == foo); QVERIFY(it.hasNext()); it.next(); @@ -828,229 +933,238 @@ void tst_QScriptClass::enumerate() } } -void tst_QScriptClass::extension() +void tst_QScriptClass::extension_None() +{ + QScriptEngine eng; + TestClass cls(&eng); + cls.setCallableMode(TestClass::NotCallable); + QVERIFY(!cls.supportsExtension(QScriptClass::Callable)); + QVERIFY(!cls.supportsExtension(QScriptClass::HasInstance)); + QScriptValue obj = eng.newObject(&cls); + QVERIFY(!obj.call().isValid()); + QCOMPARE((int)cls.lastExtensionType(), -1); + QVERIFY(!obj.instanceOf(obj)); + QCOMPARE((int)cls.lastExtensionType(), -1); + QVERIFY(!obj.construct().isValid()); +} + +void tst_QScriptClass::extension_Callable() { QScriptEngine eng; + TestClass cls(&eng); + cls.setCallableMode(TestClass::CallableReturnsSum); + QVERIFY(cls.supportsExtension(QScriptClass::Callable)); + + QScriptValue obj = eng.newObject(&cls); + eng.globalObject().setProperty("obj", obj); + obj.setProperty("one", QScriptValue(&eng, 1)); + obj.setProperty("two", QScriptValue(&eng, 2)); + obj.setProperty("three", QScriptValue(&eng, 3)); + // From C++ + cls.clearReceivedArgs(); { - TestClass cls(&eng); - cls.setCallableMode(TestClass::NotCallable); - QVERIFY(!cls.supportsExtension(QScriptClass::Callable)); - QVERIFY(!cls.supportsExtension(QScriptClass::HasInstance)); - QScriptValue obj = eng.newObject(&cls); - QVERIFY(!obj.call().isValid()); - QCOMPARE((int)cls.lastExtensionType(), -1); - QVERIFY(!obj.instanceOf(obj)); - QCOMPARE((int)cls.lastExtensionType(), -1); - QVERIFY(!obj.construct().isValid()); + QScriptValueList args; + args << QScriptValue(&eng, 4) << QScriptValue(&eng, 5); + QScriptValue ret = obj.call(obj, args); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isNumber()); + QCOMPARE(ret.toNumber(), qsreal(1+2+3+4+5)); } - // Callable + // From JS + cls.clearReceivedArgs(); { - TestClass cls(&eng); - cls.setCallableMode(TestClass::CallableReturnsSum); - QVERIFY(cls.supportsExtension(QScriptClass::Callable)); - - QScriptValue obj = eng.newObject(&cls); - eng.globalObject().setProperty("obj", obj); - obj.setProperty("one", QScriptValue(&eng, 1)); - obj.setProperty("two", QScriptValue(&eng, 2)); - obj.setProperty("three", QScriptValue(&eng, 3)); - // From C++ - cls.clearReceivedArgs(); - { - QScriptValueList args; - args << QScriptValue(&eng, 4) << QScriptValue(&eng, 5); - QScriptValue ret = obj.call(obj, args); - QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); - QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); - QVERIFY(ret.isNumber()); - QCOMPARE(ret.toNumber(), qsreal(15)); - } - // From JS - cls.clearReceivedArgs(); - { - QScriptValue ret = eng.evaluate("obj(4, 5)"); - QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); - QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); - QVERIFY(ret.isNumber()); - QCOMPARE(ret.toNumber(), qsreal(15)); - } + QScriptValue ret = eng.evaluate("obj(4, 5)"); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isNumber()); + QCOMPARE(ret.toNumber(), qsreal(1+2+3+4+5)); + } - cls.setCallableMode(TestClass::CallableReturnsArgument); - // From C++ - cls.clearReceivedArgs(); - { - QScriptValue ret = obj.call(obj, QScriptValueList() << 123); - QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); - QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); - QVERIFY(ret.isNumber()); - QCOMPARE(ret.toInt32(), 123); - } - cls.clearReceivedArgs(); - { - QScriptValue ret = obj.call(obj, QScriptValueList() << true); - QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); - QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); - QVERIFY(ret.isBoolean()); - QCOMPARE(ret.toBoolean(), true); - } - { - QScriptValue ret = obj.call(obj, QScriptValueList() << QString::fromLatin1("ciao")); - QVERIFY(ret.isString()); - QCOMPARE(ret.toString(), QString::fromLatin1("ciao")); - } - { - QScriptValue objobj = eng.newObject(); - QScriptValue ret = obj.call(obj, QScriptValueList() << objobj); - QVERIFY(ret.isObject()); - QVERIFY(ret.strictlyEquals(objobj)); - } - { - QScriptValue ret = obj.call(obj, QScriptValueList() << QScriptValue()); - QVERIFY(ret.isUndefined()); - } - // From JS - cls.clearReceivedArgs(); - { - QScriptValue ret = eng.evaluate("obj(123)"); - QVERIFY(ret.isNumber()); - QCOMPARE(ret.toInt32(), 123); - } + cls.setCallableMode(TestClass::CallableReturnsArgument); + // From C++ + cls.clearReceivedArgs(); + { + QScriptValue ret = obj.call(obj, QScriptValueList() << 123); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isNumber()); + QCOMPARE(ret.toInt32(), 123); + } + cls.clearReceivedArgs(); + { + QScriptValue ret = obj.call(obj, QScriptValueList() << true); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isBoolean()); + QCOMPARE(ret.toBoolean(), true); + } + { + QScriptValue ret = obj.call(obj, QScriptValueList() << QString::fromLatin1("ciao")); + QVERIFY(ret.isString()); + QCOMPARE(ret.toString(), QString::fromLatin1("ciao")); + } + { + QScriptValue objobj = eng.newObject(); + QScriptValue ret = obj.call(obj, QScriptValueList() << objobj); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(objobj)); + } + { + QScriptValue ret = obj.call(obj, QScriptValueList() << QScriptValue()); + QVERIFY(ret.isUndefined()); + } + // From JS + cls.clearReceivedArgs(); + { + QScriptValue ret = eng.evaluate("obj(123)"); + QVERIFY(ret.isNumber()); + QCOMPARE(ret.toInt32(), 123); + } - cls.setCallableMode(TestClass::CallableReturnsInvalidVariant); - { - QScriptValue ret = obj.call(obj); - QVERIFY(ret.isUndefined()); - } + cls.setCallableMode(TestClass::CallableReturnsInvalidVariant); + { + QScriptValue ret = obj.call(obj); + QVERIFY(ret.isUndefined()); + } - cls.setCallableMode(TestClass::CallableReturnsThisObject); - // From C++ - { - QScriptValue ret = obj.call(obj); - QVERIFY(ret.isObject()); - QVERIFY(ret.strictlyEquals(obj)); - } - // From JS - { - QScriptValue ret = eng.evaluate("obj()"); - QVERIFY(ret.isObject()); - QVERIFY(ret.strictlyEquals(eng.globalObject())); - } + cls.setCallableMode(TestClass::CallableReturnsThisObject); + // From C++ + { + QScriptValue ret = obj.call(obj); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(obj)); + } + // From JS + { + QScriptValue ret = eng.evaluate("obj()"); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(eng.globalObject())); + } - cls.setCallableMode(TestClass::CallableReturnsCallee); - // From C++ - { - QScriptValue ret = obj.call(); - QVERIFY(ret.isObject()); - QVERIFY(ret.strictlyEquals(obj)); - } - // From JS - { - QScriptValue ret = eng.evaluate("obj()"); - QVERIFY(ret.isObject()); - QVERIFY(ret.strictlyEquals(obj)); - } + cls.setCallableMode(TestClass::CallableReturnsCallee); + // From C++ + { + QScriptValue ret = obj.call(); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(obj)); + } + // From JS + { + QScriptValue ret = eng.evaluate("obj()"); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(obj)); + } - cls.setCallableMode(TestClass::CallableReturnsArgumentsObject); - // From C++ - { - QScriptValue ret = obj.call(obj, QScriptValueList() << 123); - QVERIFY(ret.isObject()); - QVERIFY(ret.property("length").isNumber()); - QCOMPARE(ret.property("length").toInt32(), 1); - QVERIFY(ret.property(0).isNumber()); - QCOMPARE(ret.property(0).toInt32(), 123); - } - // From JS - { - QScriptValue ret = eng.evaluate("obj(123)"); - QVERIFY(ret.isObject()); - QVERIFY(ret.property("length").isNumber()); - QCOMPARE(ret.property("length").toInt32(), 1); - QVERIFY(ret.property(0).isNumber()); - QCOMPARE(ret.property(0).toInt32(), 123); - } + cls.setCallableMode(TestClass::CallableReturnsArgumentsObject); + // From C++ + { + QScriptValue ret = obj.call(obj, QScriptValueList() << 123); + QVERIFY(ret.isObject()); + QVERIFY(ret.property("length").isNumber()); + QCOMPARE(ret.property("length").toInt32(), 1); + QVERIFY(ret.property(0).isNumber()); + QCOMPARE(ret.property(0).toInt32(), 123); + } + // From JS + { + QScriptValue ret = eng.evaluate("obj(123)"); + QVERIFY(ret.isObject()); + QVERIFY(ret.property("length").isNumber()); + QCOMPARE(ret.property("length").toInt32(), 1); + QVERIFY(ret.property(0).isNumber()); + QCOMPARE(ret.property(0).toInt32(), 123); + } +} - // construct() - // From C++ - cls.clearReceivedArgs(); - cls.setCallableMode(TestClass::CallableReturnsGlobalObject); - { - QScriptValue ret = obj.construct(); - QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); - QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); - QVERIFY(ret.isObject()); - QVERIFY(ret.strictlyEquals(eng.globalObject())); - } - // From JS - cls.clearReceivedArgs(); - { - QScriptValue ret = eng.evaluate("new obj()"); - QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); - QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); - QVERIFY(ret.isObject()); - QVERIFY(ret.strictlyEquals(eng.globalObject())); - } - // From C++ - cls.clearReceivedArgs(); - cls.setCallableMode(TestClass::CallableInitializesThisObject); - { - QScriptValue ret = obj.construct(); - QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); - QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); - QVERIFY(ret.isQObject()); - QCOMPARE(ret.toQObject(), (QObject*)&eng); - } - // From JS - cls.clearReceivedArgs(); - { - QScriptValue ret = eng.evaluate("new obj()"); - QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); - QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); - QVERIFY(ret.isQObject()); - QCOMPARE(ret.toQObject(), (QObject*)&eng); - } +void tst_QScriptClass::extension_Callable_construct() +{ + QScriptEngine eng; + TestClass cls(&eng); + QScriptValue obj = eng.newObject(&cls); + eng.globalObject().setProperty("obj", obj); + + // From C++ + cls.clearReceivedArgs(); + cls.setCallableMode(TestClass::CallableReturnsGlobalObject); + { + QScriptValue ret = obj.construct(); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(eng.globalObject())); + } + // From JS + cls.clearReceivedArgs(); + { + QScriptValue ret = eng.evaluate("new obj()"); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(eng.globalObject())); + } + // From C++ + cls.clearReceivedArgs(); + cls.setCallableMode(TestClass::CallableInitializesThisObject); + { + QScriptValue ret = obj.construct(); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isQObject()); + QCOMPARE(ret.toQObject(), (QObject*)&eng); } - // HasInstance + // From JS + cls.clearReceivedArgs(); { - TestClass cls(&eng); - cls.setHasInstance(true); - QVERIFY(cls.supportsExtension(QScriptClass::HasInstance)); + QScriptValue ret = eng.evaluate("new obj()"); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isQObject()); + QCOMPARE(ret.toQObject(), (QObject*)&eng); + } +} - QScriptValue obj = eng.newObject(&cls); - obj.setProperty("foo", QScriptValue(&eng, 123)); - QScriptValue plain = eng.newObject(); - QVERIFY(!plain.instanceOf(obj)); +void tst_QScriptClass::extension_HasInstance() +{ + QScriptEngine eng; + TestClass cls(&eng); + cls.setHasInstance(true); + QVERIFY(cls.supportsExtension(QScriptClass::HasInstance)); - eng.globalObject().setProperty("HasInstanceTester", obj); - eng.globalObject().setProperty("hasInstanceValue", plain); - cls.clearReceivedArgs(); - { - QScriptValue ret = eng.evaluate("hasInstanceValue instanceof HasInstanceTester"); - QCOMPARE(cls.lastExtensionType(), QScriptClass::HasInstance); - QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptValueList>()); - QScriptValueList lst = qvariant_cast<QScriptValueList>(cls.lastExtensionArgument()); - QCOMPARE(lst.size(), 2); - QVERIFY(lst.at(0).strictlyEquals(obj)); - QVERIFY(lst.at(1).strictlyEquals(plain)); - QVERIFY(ret.isBoolean()); - QVERIFY(!ret.toBoolean()); - } + QScriptValue obj = eng.newObject(&cls); + obj.setProperty("foo", QScriptValue(&eng, 123)); + QScriptValue plain = eng.newObject(); + QVERIFY(!plain.instanceOf(obj)); - plain.setProperty("foo", QScriptValue(&eng, 456)); - QVERIFY(!plain.instanceOf(obj)); - { - QScriptValue ret = eng.evaluate("hasInstanceValue instanceof HasInstanceTester"); - QVERIFY(ret.isBoolean()); - QVERIFY(!ret.toBoolean()); - } + eng.globalObject().setProperty("HasInstanceTester", obj); + eng.globalObject().setProperty("hasInstanceValue", plain); + cls.clearReceivedArgs(); + { + QScriptValue ret = eng.evaluate("hasInstanceValue instanceof HasInstanceTester"); + QCOMPARE(cls.lastExtensionType(), QScriptClass::HasInstance); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptValueList>()); + QScriptValueList lst = qvariant_cast<QScriptValueList>(cls.lastExtensionArgument()); + QCOMPARE(lst.size(), 2); + QVERIFY(lst.at(0).strictlyEquals(obj)); + QVERIFY(lst.at(1).strictlyEquals(plain)); + QVERIFY(ret.isBoolean()); + QVERIFY(!ret.toBoolean()); + } - plain.setProperty("foo", obj.property("foo")); - QVERIFY(plain.instanceOf(obj)); - { - QScriptValue ret = eng.evaluate("hasInstanceValue instanceof HasInstanceTester"); - QVERIFY(ret.isBoolean()); - QVERIFY(ret.toBoolean()); - } + plain.setProperty("foo", QScriptValue(&eng, 456)); + QVERIFY(!plain.instanceOf(obj)); + { + QScriptValue ret = eng.evaluate("hasInstanceValue instanceof HasInstanceTester"); + QVERIFY(ret.isBoolean()); + QVERIFY(!ret.toBoolean()); + } + + plain.setProperty("foo", obj.property("foo")); + QVERIFY(plain.instanceOf(obj)); + { + QScriptValue ret = eng.evaluate("hasInstanceValue instanceof HasInstanceTester"); + QVERIFY(ret.isBoolean()); + QVERIFY(ret.toBoolean()); } } @@ -1324,5 +1438,66 @@ void tst_QScriptClass::defaultImplementations() QVERIFY(!defaultClass.extension(QScriptClass::HasInstance).isValid()); } +void tst_QScriptClass::scriptClassObjectInPrototype() +{ + QScriptEngine eng; + TestClass cls(&eng); + QScriptValue plainObject = eng.newObject(); + QScriptValue classObject = eng.newObject(&cls); + plainObject.setPrototype(classObject); + QVERIFY(plainObject.prototype().equals(classObject)); + eng.globalObject().setProperty("plainObject", plainObject); + eng.globalObject().setProperty("classObject", classObject); + + QScriptString name = eng.toStringHandle("x"); + cls.addCustomProperty(name, QScriptClass::HandlesReadAccess, /*id=*/1, /*flags=*/0, /*value=*/123); + QVERIFY(plainObject.property(name).equals(classObject.property(name))); + QVERIFY(eng.evaluate("plainObject.x == classObject.x").toBool()); + + // Add a property that shadows the one in the script class. + plainObject.setProperty(name, 456); + QVERIFY(!plainObject.property(name).equals(classObject.property(name))); + QVERIFY(eng.evaluate("plainObject.x != classObject.x").toBool()); + + QVERIFY(eng.evaluate("delete plainObject.x").toBool()); + QVERIFY(eng.evaluate("plainObject.x == classObject.x").toBool()); +} + +void tst_QScriptClass::scriptClassWithNullEngine() +{ + QScriptClass cls(0); + QCOMPARE(cls.engine(), (QScriptEngine*)0); + QScriptEngine eng; + QScriptValue obj = eng.newObject(&cls); + QVERIFY(obj.isObject()); + QCOMPARE(obj.scriptClass(), &cls); + // The class could have been "bound" to the engine at this point, + // but it's currently not. + // This behavior is not documented and is subject to change. + QCOMPARE(cls.engine(), (QScriptEngine*)0); + // The engine pointer stored in the QScriptClass is not actually used + // during property access, so this still works. + obj.setProperty("x", 123); + QVERIFY(obj.property("x").isNumber()); +} + +void tst_QScriptClass::scriptClassInOtherEngine() +{ + QScriptEngine eng; + TestClass cls(&eng); + QScriptEngine eng2; + // We don't check that the class is associated with another engine, so + // we only get a warning when trying to set the prototype of the new + // instance. + // This behavior is not documented and is subject to change. + QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setPrototype() failed: cannot set a prototype created in a different engine"); + QScriptValue obj = eng2.newObject(&cls); + QVERIFY(obj.isObject()); + QCOMPARE(obj.scriptClass(), &cls); + + obj.setProperty("x", 123); + QVERIFY(obj.property("x").isNumber()); +} + QTEST_MAIN(tst_QScriptClass) #include "tst_qscriptclass.moc" diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index cb6311e..9d7e896 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -66,7 +66,9 @@ public: private slots: void callee(); + void callee_implicitCall(); void arguments(); + void argumentsInJS(); void thisObject(); void returnValue(); void throwError_data(); @@ -77,16 +79,29 @@ private slots: void throwValue(); void evaluateInFunction(); void pushAndPopContext(); + void pushAndPopContext_variablesInActivation(); + void pushAndPopContext_setThisObject(); + void pushAndPopContext_throwException(); void lineNumber(); void backtrace_data(); void backtrace(); - void scopeChain(); - void pushAndPopScope(); - void getSetActivationObject(); + void scopeChain_globalContext(); + void scopeChain_closure(); + void scopeChain_withStatement(); + void pushAndPopScope_globalContext(); + void pushAndPopScope_globalContext2(); + void getSetActivationObject_globalContext(); + void pushScopeEvaluate(); + void pushScopeCall(); + void popScopeSimple(); + void pushAndPopGlobalObjectSimple(); + void pushAndPopIterative(); void getSetActivationObject_customContext(); void inheritActivationAndThisObject(); void toString(); - void calledAsConstructor(); + void calledAsConstructor_fromCpp(); + void calledAsConstructor_fromJS(); + void calledAsConstructor_parentContext(); void argumentsObjectInNative(); void jsActivationObject(); void qobjectAsActivationObject(); @@ -121,33 +136,33 @@ void tst_QScriptContext::callee() { QScriptEngine eng; - { - QScriptValue fun = eng.newFunction(get_callee); - fun.setProperty("foo", QScriptValue(&eng, "bar")); - eng.globalObject().setProperty("get_callee", fun); + QScriptValue fun = eng.newFunction(get_callee); + fun.setProperty("foo", QScriptValue(&eng, "bar")); + eng.globalObject().setProperty("get_callee", fun); - QScriptValue result = eng.evaluate("get_callee()"); - QCOMPARE(result.isFunction(), true); - QCOMPARE(result.property("foo").toString(), QString("bar")); - } + QScriptValue result = eng.evaluate("get_callee()"); + QCOMPARE(result.isFunction(), true); + QCOMPARE(result.property("foo").toString(), QString("bar")); +} +void tst_QScriptContext::callee_implicitCall() +{ + QScriptEngine eng; // callee when toPrimitive() is called internally - { - QScriptValue fun = eng.newFunction(store_callee_and_return_primitive); - QScriptValue obj = eng.newObject(); - obj.setProperty("toString", fun); - QVERIFY(!obj.property("callee").isValid()); - (void)obj.toString(); - QVERIFY(obj.property("callee").isFunction()); - QVERIFY(obj.property("callee").strictlyEquals(fun)); - - obj.setProperty("callee", QScriptValue()); - QVERIFY(!obj.property("callee").isValid()); - obj.setProperty("valueOf", fun); - (void)obj.toNumber(); - QVERIFY(obj.property("callee").isFunction()); - QVERIFY(obj.property("callee").strictlyEquals(fun)); - } + QScriptValue fun = eng.newFunction(store_callee_and_return_primitive); + QScriptValue obj = eng.newObject(); + obj.setProperty("toString", fun); + QVERIFY(!obj.property("callee").isValid()); + (void)obj.toString(); + QVERIFY(obj.property("callee").isFunction()); + QVERIFY(obj.property("callee").strictlyEquals(fun)); + + obj.setProperty("callee", QScriptValue()); + QVERIFY(!obj.property("callee").isValid()); + obj.setProperty("valueOf", fun); + (void)obj.toNumber(); + QVERIFY(obj.property("callee").isFunction()); + QVERIFY(obj.property("callee").strictlyEquals(fun)); } static QScriptValue get_arguments(QScriptContext *ctx, QScriptEngine *eng) @@ -167,6 +182,8 @@ void tst_QScriptContext::arguments() { QScriptEngine eng; + // See section 10.6 ("Arguments Object") of ECMA-262. + { QScriptValue args = eng.currentContext()->argumentsObject(); QVERIFY(args.isObject()); @@ -178,6 +195,8 @@ void tst_QScriptContext::arguments() } for (int x = 0; x < 2; ++x) { + // The expected arguments array should be the same regardless of + // whether get_arguments() is called as a constructor. QString prefix; if (x == 0) prefix = ""; @@ -224,11 +243,15 @@ void tst_QScriptContext::arguments() QCOMPARE(result.propertyFlags("length"), QScriptValue::SkipInEnumeration); QCOMPARE(result.property("callee").strictlyEquals(fun), true); QCOMPARE(result.propertyFlags("callee"), QScriptValue::SkipInEnumeration); + + // callee and length properties should be writable. QScriptValue replacedCallee(&eng, 123); result.setProperty("callee", replacedCallee); QVERIFY(result.property("callee").equals(replacedCallee)); QScriptValue replacedLength(&eng, 456); result.setProperty("length", replacedLength); + + // callee and length properties should be deletable. QVERIFY(result.property("length").equals(replacedLength)); result.setProperty("callee", QScriptValue()); QVERIFY(!result.property("callee").isValid()); @@ -262,28 +285,31 @@ void tst_QScriptContext::arguments() QCOMPARE(result.property("2").toBoolean(), true); QCOMPARE(result.property("3").isUndefined(), true); } + } +} - // arguments object returned from script - { - QScriptValue result = eng.evaluate("(function() { return arguments; })(123)"); - QCOMPARE(result.isArray(), false); - QVERIFY(result.isObject()); - QCOMPARE(result.property("length").toUInt32(), quint32(1)); - QCOMPARE(result.property("0").isNumber(), true); - QCOMPARE(result.property("0").toNumber(), 123.0); - } +void tst_QScriptContext::argumentsInJS() +{ + QScriptEngine eng; + { + QScriptValue result = eng.evaluate("(function() { return arguments; })(123)"); + QCOMPARE(result.isArray(), false); + QVERIFY(result.isObject()); + QCOMPARE(result.property("length").toUInt32(), quint32(1)); + QCOMPARE(result.property("0").isNumber(), true); + QCOMPARE(result.property("0").toNumber(), 123.0); + } - { - QScriptValue result = eng.evaluate("(function() { return arguments; })('ciao', null, true, undefined)"); - QCOMPARE(result.isArray(), false); - QCOMPARE(result.property("length").toUInt32(), quint32(4)); - QCOMPARE(result.property("0").isString(), true); - QCOMPARE(result.property("0").toString(), QString("ciao")); - QCOMPARE(result.property("1").isNull(), true); - QCOMPARE(result.property("2").isBoolean(), true); - QCOMPARE(result.property("2").toBoolean(), true); - QCOMPARE(result.property("3").isUndefined(), true); - } + { + QScriptValue result = eng.evaluate("(function() { return arguments; })('ciao', null, true, undefined)"); + QCOMPARE(result.isArray(), false); + QCOMPARE(result.property("length").toUInt32(), quint32(4)); + QCOMPARE(result.property("0").isString(), true); + QCOMPARE(result.property("0").toString(), QString("ciao")); + QCOMPARE(result.property("1").isNull(), true); + QCOMPARE(result.property("2").isBoolean(), true); + QCOMPARE(result.property("2").toBoolean(), true); + QCOMPARE(result.property("3").isUndefined(), true); } } @@ -517,58 +543,65 @@ void tst_QScriptContext::pushAndPopContext() QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::popContext() doesn't match with pushContext()"); eng.popContext(); QCOMPARE(eng.currentContext(), topLevel); +} - { - QScriptContext *ctx3 = eng.pushContext(); - ctx3->activationObject().setProperty("foo", QScriptValue(&eng, 123)); - QVERIFY(eng.evaluate("foo").strictlyEquals(QScriptValue(&eng, 123))); - QCOMPARE(ctx3->activationObject().propertyFlags("foo"), QScriptValue::PropertyFlags(0)); - - ctx3->activationObject().setProperty(4, 456); - QVERIFY(ctx3->activationObject().property(4, QScriptValue::ResolveLocal).equals(456)); - - eng.evaluate("var bar = 'ciao'"); - QVERIFY(ctx3->activationObject().property("bar", QScriptValue::ResolveLocal).strictlyEquals(QScriptValue(&eng, "ciao"))); - - ctx3->activationObject().setProperty("baz", 789, QScriptValue::ReadOnly); - QVERIFY(eng.evaluate("baz").equals(789)); - QCOMPARE(ctx3->activationObject().propertyFlags("baz"), QScriptValue::ReadOnly); - - QSet<QString> activationPropertyNames; - QScriptValueIterator it(ctx3->activationObject()); - while (it.hasNext()) { - it.next(); - activationPropertyNames.insert(it.name()); - } - QCOMPARE(activationPropertyNames.size(), 4); - QVERIFY(activationPropertyNames.contains("foo")); - QVERIFY(activationPropertyNames.contains("4")); - QVERIFY(activationPropertyNames.contains("bar")); - QVERIFY(activationPropertyNames.contains("baz")); - - eng.popContext(); +void tst_QScriptContext::pushAndPopContext_variablesInActivation() +{ + QScriptEngine eng; + QScriptContext *ctx = eng.pushContext(); + ctx->activationObject().setProperty("foo", QScriptValue(&eng, 123)); + // evaluate() should use the current context. + QVERIFY(eng.evaluate("foo").strictlyEquals(QScriptValue(&eng, 123))); + QCOMPARE(ctx->activationObject().propertyFlags("foo"), QScriptValue::PropertyFlags(0)); + + ctx->activationObject().setProperty(4, 456); + QVERIFY(ctx->activationObject().property(4, QScriptValue::ResolveLocal).equals(456)); + + // New JS variables should become properties of the current context's activation. + eng.evaluate("var bar = 'ciao'"); + QVERIFY(ctx->activationObject().property("bar", QScriptValue::ResolveLocal).strictlyEquals(QScriptValue(&eng, "ciao"))); + + ctx->activationObject().setProperty("baz", 789, QScriptValue::ReadOnly); + QVERIFY(eng.evaluate("baz").equals(789)); + QCOMPARE(ctx->activationObject().propertyFlags("baz"), QScriptValue::ReadOnly); + + QSet<QString> activationPropertyNames; + QScriptValueIterator it(ctx->activationObject()); + while (it.hasNext()) { + it.next(); + activationPropertyNames.insert(it.name()); } + QCOMPARE(activationPropertyNames.size(), 4); + QVERIFY(activationPropertyNames.contains("foo")); + QVERIFY(activationPropertyNames.contains("4")); + QVERIFY(activationPropertyNames.contains("bar")); + QVERIFY(activationPropertyNames.contains("baz")); - { - QScriptContext *ctx4 = eng.pushContext(); - QScriptValue obj = eng.newObject(); - obj.setProperty("prop", QScriptValue(&eng, 456)); - ctx4->setThisObject(obj); - QScriptValue ret = eng.evaluate("var tmp = this.prop; tmp + 1"); - QCOMPARE(eng.currentContext(), ctx4); - QVERIFY(ret.strictlyEquals(QScriptValue(&eng, 457))); - eng.popContext(); - } + eng.popContext(); +} - // throwing an exception - { - QScriptContext *ctx5 = eng.pushContext(); - QScriptValue ret = eng.evaluate("throw new Error('oops')"); - QVERIFY(ret.isError()); - QVERIFY(eng.hasUncaughtException()); - QCOMPARE(eng.currentContext(), ctx5); - eng.popContext(); - } +void tst_QScriptContext::pushAndPopContext_setThisObject() +{ + QScriptEngine eng; + QScriptContext *ctx = eng.pushContext(); + QScriptValue obj = eng.newObject(); + obj.setProperty("prop", QScriptValue(&eng, 456)); + ctx->setThisObject(obj); + QScriptValue ret = eng.evaluate("var tmp = this.prop; tmp + 1"); + QCOMPARE(eng.currentContext(), ctx); + QVERIFY(ret.strictlyEquals(QScriptValue(&eng, 457))); + eng.popContext(); +} + +void tst_QScriptContext::pushAndPopContext_throwException() +{ + QScriptEngine eng; + QScriptContext *ctx = eng.pushContext(); + QScriptValue ret = eng.evaluate("throw new Error('oops')"); + QVERIFY(ret.isError()); + QVERIFY(eng.hasUncaughtException()); + QCOMPARE(eng.currentContext(), ctx); + eng.popContext(); } void tst_QScriptContext::popNativeContextScope() @@ -596,7 +629,7 @@ void tst_QScriptContext::popNativeContextScope() QVERIFY(ctx->activationObject().strictlyEquals(customScope)); QCOMPARE(ctx->scopeChain().size(), 2); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(customScope)); - QEXPECT_FAIL("", "QTBUG-11012", Continue); + QEXPECT_FAIL("", "QTBUG-11012: Global object is replaced in scope chain", Continue); QVERIFY(ctx->scopeChain().at(1).strictlyEquals(eng.globalObject())); QVERIFY(!eng.evaluate("baz = 456; var foo = 789; function barbar() {}").isError()); @@ -891,6 +924,50 @@ void tst_QScriptContext::backtrace_data() QTest::newRow("js recursive") << source << expected; } + + { + QString source = QString::fromLatin1( + "[0].forEach(\n" + " function() {\n" + " result = bt();\n" + "}); result"); + + QStringList expected; + expected << "<native>() at -1" + << "<anonymous>(0, 0, 0) at testfile:3" + << QString::fromLatin1("forEach(%0) at -1") + // Because the JIT doesn't store the arguments in the frame + // for built-in functions, arguments are not available. + // Will work when the copy of JavaScriptCore is updated + // (QTBUG-16568). + .arg(qt_script_isJITEnabled() + ? "" + : "function () {\n result = bt();\n}") + << "<global>() at testfile:4"; + QTest::newRow("js callback from built-in") << source << expected; + } + + { + QString source = QString::fromLatin1( + "[10,20].forEach(\n" + " function() {\n" + " result = bt();\n" + "}); result"); + + QStringList expected; + expected << "<native>() at -1" + << "<anonymous>(20, 1, 10,20) at testfile:3" + << QString::fromLatin1("forEach(%0) at -1") + // Because the JIT doesn't store the arguments in the frame + // for built-in functions, arguments are not available. + // Will work when the copy of JavaScriptCore is updated + // (QTBUG-16568). + .arg(qt_script_isJITEnabled() + ? "" + : "function () {\n result = bt();\n}") + << "<global>() at testfile:4"; + QTest::newRow("js callback from built-in") << source << expected; + } } @@ -918,7 +995,7 @@ static QScriptValue getScopeChain(QScriptContext *ctx, QScriptEngine *eng) return qScriptValueFromValue(eng, ctx->parentContext()->scopeChain()); } -void tst_QScriptContext::scopeChain() +void tst_QScriptContext::scopeChain_globalContext() { QScriptEngine eng; { @@ -932,19 +1009,35 @@ void tst_QScriptContext::scopeChain() QCOMPARE(ret.size(), 1); QVERIFY(ret.at(0).strictlyEquals(eng.globalObject())); } - { - eng.evaluate("function foo() { function bar() { return getScopeChain(); } return bar() }"); - QScriptValueList ret = qscriptvalue_cast<QScriptValueList>(eng.evaluate("foo()")); - QEXPECT_FAIL("", "Number of items in returned scope chain is incorrect", Abort); - QCOMPARE(ret.size(), 3); - QVERIFY(ret.at(2).strictlyEquals(eng.globalObject())); - QCOMPARE(ret.at(1).toString(), QString::fromLatin1("activation")); - QVERIFY(ret.at(1).property("arguments").isObject()); - QCOMPARE(ret.at(0).toString(), QString::fromLatin1("activation")); - QVERIFY(ret.at(0).property("arguments").isObject()); - } +} + +void tst_QScriptContext::scopeChain_closure() +{ + QScriptEngine eng; + eng.globalObject().setProperty("getScopeChain", eng.newFunction(getScopeChain)); + + eng.evaluate("function foo() { function bar() { return getScopeChain(); } return bar() }"); + QScriptValueList ret = qscriptvalue_cast<QScriptValueList>(eng.evaluate("foo()")); + // JSC will not create an activation for bar() unless we insert a call + // to eval() in the function body; JSC has no way of knowing that the + // native function will be asking for the activation, and we don't want + // to needlessly create it. + QEXPECT_FAIL("", "QTBUG-10313: JSC optimizes away the activation object", Abort); + QCOMPARE(ret.size(), 3); + QVERIFY(ret.at(2).strictlyEquals(eng.globalObject())); + QCOMPARE(ret.at(1).toString(), QString::fromLatin1("activation")); + QVERIFY(ret.at(1).property("arguments").isObject()); + QCOMPARE(ret.at(0).toString(), QString::fromLatin1("activation")); + QVERIFY(ret.at(0).property("arguments").isObject()); +} + +void tst_QScriptContext::scopeChain_withStatement() +{ + QScriptEngine eng; + eng.globalObject().setProperty("getScopeChain", eng.newFunction(getScopeChain)); { QScriptValueList ret = qscriptvalue_cast<QScriptValueList>(eng.evaluate("o = { x: 123 }; with(o) getScopeChain();")); + QEXPECT_FAIL("", "QTBUG-17131: with-scope isn't reflected by QScriptContext", Abort); QCOMPARE(ret.size(), 2); QVERIFY(ret.at(1).strictlyEquals(eng.globalObject())); QVERIFY(ret.at(0).isObject()); @@ -962,7 +1055,73 @@ void tst_QScriptContext::scopeChain() } } -void tst_QScriptContext::pushAndPopScope() +void tst_QScriptContext::pushScopeEvaluate() +{ + QScriptEngine engine; + QScriptValue object = engine.newObject(); + object.setProperty("foo", 1234); + object.setProperty(1, 1234); + engine.currentContext()->pushScope(object); + object.setProperty("bar", 4321); + object.setProperty(2, 4321); + QVERIFY(engine.evaluate("foo").equals(1234)); + QVERIFY(engine.evaluate("bar").equals(4321)); +} + +void tst_QScriptContext::pushScopeCall() +{ + QScriptEngine engine; + QScriptValue object = engine.globalObject(); + QScriptValue thisObject = engine.newObject(); + QScriptValue function = engine.evaluate("(function(property){return this[property]; })"); + QVERIFY(function.isFunction()); + object.setProperty("foo", 1234); + thisObject.setProperty("foo", "foo"); + engine.currentContext()->pushScope(object); + object.setProperty("bar", 4321); + thisObject.setProperty("bar", "bar"); + QVERIFY(function.call(QScriptValue(), QScriptValueList() << "foo").equals(1234)); + QVERIFY(function.call(QScriptValue(), QScriptValueList() << "bar").equals(4321)); + QVERIFY(function.call(thisObject, QScriptValueList() << "foo").equals("foo")); + QVERIFY(function.call(thisObject, QScriptValueList() << "bar").equals("bar")); +} + +void tst_QScriptContext::popScopeSimple() +{ + QScriptEngine engine; + QScriptValue object = engine.newObject(); + QScriptValue globalObject = engine.globalObject(); + engine.currentContext()->pushScope(object); + QVERIFY(engine.currentContext()->popScope().strictlyEquals(object)); + QVERIFY(engine.globalObject().strictlyEquals(globalObject)); +} + +void tst_QScriptContext::pushAndPopGlobalObjectSimple() +{ + QScriptEngine engine; + QScriptValue globalObject = engine.globalObject(); + engine.currentContext()->pushScope(globalObject); + QVERIFY(engine.currentContext()->popScope().strictlyEquals(globalObject)); + QVERIFY(engine.globalObject().strictlyEquals(globalObject)); +} + +void tst_QScriptContext::pushAndPopIterative() +{ + QScriptEngine engine; + for (uint repeat = 0; repeat < 2; ++repeat) { + for (uint i = 1; i < 11; ++i) { + QScriptValue object = engine.newObject(); + object.setProperty("x", i + 10 * repeat); + engine.currentContext()->pushScope(object); + } + for (uint i = 10; i > 0; --i) { + QScriptValue object = engine.currentContext()->popScope(); + QVERIFY(object.property("x").equals(i + 10 * repeat)); + } + } +} + +void tst_QScriptContext::pushAndPopScope_globalContext() { QScriptEngine eng; QScriptContext *ctx = eng.currentContext(); @@ -1019,14 +1178,19 @@ void tst_QScriptContext::pushAndPopScope() ctx->pushScope(QScriptValue()); QCOMPARE(ctx->scopeChain().size(), 1); +} +void tst_QScriptContext::pushAndPopScope_globalContext2() +{ + QScriptEngine eng; + QScriptContext *ctx = eng.currentContext(); QVERIFY(ctx->popScope().strictlyEquals(eng.globalObject())); QVERIFY(ctx->scopeChain().isEmpty()); // Used to work with old back-end, doesn't with new one because JSC requires that the last object in // a scope chain is the Global Object. QTest::ignoreMessage(QtWarningMsg, "QScriptContext::pushScope() failed: initial object in scope chain has to be the Global Object"); - ctx->pushScope(obj); + ctx->pushScope(eng.newObject()); QCOMPARE(ctx->scopeChain().size(), 0); QScriptEngine eng2; @@ -1043,7 +1207,7 @@ static QScriptValue get_activationObject(QScriptContext *ctx, QScriptEngine *) return ctx->activationObject(); } -void tst_QScriptContext::getSetActivationObject() +void tst_QScriptContext::getSetActivationObject_globalContext() { QScriptEngine eng; QScriptContext *ctx = eng.currentContext(); @@ -1076,7 +1240,7 @@ void tst_QScriptContext::getSetActivationObject() QScriptValue ret = eng.evaluate("get_activationObject(1, 2, 3)"); QVERIFY(ret.isObject()); QScriptValue arguments = ret.property("arguments"); - QEXPECT_FAIL("", "Getting arguments property of activation object doesn't work", Abort); + QEXPECT_FAIL("", "QTBUG-17136: arguments property of activation object is missing", Abort); QVERIFY(arguments.isObject()); QCOMPARE(arguments.property("length").toInt32(), 3); QCOMPARE(arguments.property("0").toInt32(), 1); @@ -1099,6 +1263,8 @@ void tst_QScriptContext::getSetActivationObject_customContext() QCOMPARE(act.property("foo").toInt32(), 123); } +// Helper function that's intended to have the same behavior +// as the built-in eval() function. static QScriptValue myEval(QScriptContext *ctx, QScriptEngine *eng) { QString code = ctx->argument(0).toString(); @@ -1127,13 +1293,14 @@ void tst_QScriptContext::inheritActivationAndThisObject() QCOMPARE(ret.toInt32(), 123); } - // QT-2219 { eng.globalObject().setProperty("a", 123); QScriptValue ret = eng.evaluate("(function() { myEval('var a = 456'); return a; })()"); QVERIFY(ret.isNumber()); QCOMPARE(ret.toInt32(), 456); - QEXPECT_FAIL("", "QT-2219: Wrong activation object is returned from native function's parent context", Continue); + // Since JSC doesn't create an activation object for the anonymous function call, + // myEval() will use the global object as the activation, which is wrong. + QEXPECT_FAIL("", "QTBUG-10313: Wrong activation object is returned from native function's parent context", Continue); QVERIFY(eng.globalObject().property("a").strictlyEquals(123)); } } @@ -1172,11 +1339,11 @@ static QScriptValue storeCalledAsConstructorV3(QScriptContext *ctx, QScriptEngin return eng->undefinedValue(); } -void tst_QScriptContext::calledAsConstructor() +void tst_QScriptContext::calledAsConstructor_fromCpp() { QScriptEngine eng; - QScriptValue fun1 = eng.newFunction(storeCalledAsConstructor); { + QScriptValue fun1 = eng.newFunction(storeCalledAsConstructor); fun1.call(); QVERIFY(!fun1.property("calledAsConstructor").toBool()); fun1.construct(); @@ -1189,25 +1356,31 @@ void tst_QScriptContext::calledAsConstructor() fun.construct(); QVERIFY(fun.property("calledAsConstructor").toBool()); } - { - eng.globalObject().setProperty("fun1", fun1); - eng.evaluate("fun1();"); - QVERIFY(!fun1.property("calledAsConstructor").toBool()); - eng.evaluate("new fun1();"); - QVERIFY(fun1.property("calledAsConstructor").toBool()); - } - { - QScriptValue fun3 = eng.newFunction(storeCalledAsConstructorV3); - eng.globalObject().setProperty("fun3", fun3); - eng.evaluate("function test() { fun3() }"); - eng.evaluate("test();"); - QVERIFY(!fun3.property("calledAsConstructor").toBool()); - eng.evaluate("new test();"); - if (qt_script_isJITEnabled()) - QEXPECT_FAIL("", "QTBUG-6132: calledAsConstructor is not correctly set for JS functions when JIT is enabled", Continue); - QVERIFY(fun3.property("calledAsConstructor").toBool()); - } +} + +void tst_QScriptContext::calledAsConstructor_fromJS() +{ + QScriptEngine eng; + QScriptValue fun1 = eng.newFunction(storeCalledAsConstructor); + eng.globalObject().setProperty("fun1", fun1); + eng.evaluate("fun1();"); + QVERIFY(!fun1.property("calledAsConstructor").toBool()); + eng.evaluate("new fun1();"); + QVERIFY(fun1.property("calledAsConstructor").toBool()); +} +void tst_QScriptContext::calledAsConstructor_parentContext() +{ + QScriptEngine eng; + QScriptValue fun3 = eng.newFunction(storeCalledAsConstructorV3); + eng.globalObject().setProperty("fun3", fun3); + eng.evaluate("function test() { fun3() }"); + eng.evaluate("test();"); + QVERIFY(!fun3.property("calledAsConstructor").toBool()); + eng.evaluate("new test();"); + if (qt_script_isJITEnabled()) + QEXPECT_FAIL("", "QTBUG-6132: calledAsConstructor is not correctly set for JS functions when JIT is enabled", Continue); + QVERIFY(fun3.property("calledAsConstructor").toBool()); } static QScriptValue argumentsObjectInNative_test1(QScriptContext *ctx, QScriptEngine *eng) @@ -1269,7 +1442,7 @@ void tst_QScriptContext::jsActivationObject() QScriptValue result1 = eng.evaluate("f2('hello', 'useless', 'world')"); QScriptValue result2 = eng.evaluate("f3()"); QVERIFY(result1.isObject()); - QEXPECT_FAIL("", "JSC optimize away the activation object", Abort); + QEXPECT_FAIL("", "QTBUG-10313: JSC optimizes away the activation object", Abort); QCOMPARE(result1.property("v1").toInt32() , 42); QCOMPARE(result1.property("arguments").property(1).toString() , QString::fromLatin1("useless")); QVERIFY(result2.isObject()); diff --git a/tests/auto/qscriptcontextinfo/tst_qscriptcontextinfo.cpp b/tests/auto/qscriptcontextinfo/tst_qscriptcontextinfo.cpp index aba16b2..89c5330 100644 --- a/tests/auto/qscriptcontextinfo/tst_qscriptcontextinfo.cpp +++ b/tests/auto/qscriptcontextinfo/tst_qscriptcontextinfo.cpp @@ -93,6 +93,7 @@ private slots: void qtPropertyFunction(); void nullContext(); void streaming(); + void comparison_null(); void assignmentAndComparison(); }; @@ -366,6 +367,13 @@ void tst_QScriptContextInfo::streaming() } } +void tst_QScriptContextInfo::comparison_null() +{ + QScriptContextInfo info1, info2, info3(0); + QCOMPARE(info1, info2); + QCOMPARE(info1, info3); +} + void tst_QScriptContextInfo::assignmentAndComparison() { QScriptEngine eng; diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index c4c53e9..589b3b1 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -93,7 +93,8 @@ private slots: void constructWithParent(); void currentContext(); void pushPopContext(); - void getSetDefaultPrototype(); + void getSetDefaultPrototype_int(); + void getSetDefaultPrototype_customType(); void newFunction(); void newFunctionWithArg(); void newFunctionWithProto(); @@ -109,7 +110,9 @@ private slots: void newVariant_promoteNonObject(); void newVariant_promoteNonQScriptObject(); void newRegExp(); + void jsRegExp(); void newDate(); + void jsParseDate(); void newQObject(); void newQObject_ownership(); void newQObject_promoteObject(); @@ -121,6 +124,7 @@ private slots: void newActivationObject(); void getSetGlobalObject(); void globalObjectProperties(); + void globalObjectProperties_enumerate(); void createGlobalObjectProperty(); void globalObjectGetterSetterProperty(); void customGlobalObjectWithPrototype(); @@ -136,7 +140,14 @@ private slots: void nestedEvaluate(); void uncaughtException(); void errorMessage_QT679(); - void valueConversion(); + void valueConversion_basic(); + void valueConversion_customType(); + void valueConversion_sequence(); + void valueConversion_QVariant(); + void valueConversion_hooliganTask248802(); + void valueConversion_basic2(); + void valueConversion_dateTime(); + void valueConversion_regExp(); void qScriptValueFromValue_noEngine(); void importExtension(); void infiniteRecursion(); @@ -152,32 +163,51 @@ private slots: void numberParsing_data(); void numberParsing(); void automaticSemicolonInsertion(); + void abortEvaluation_notEvaluating(); void abortEvaluation(); + void abortEvaluation_tryCatch(); + void abortEvaluation_fromNative(); void abortEvaluation_QTBUG9433(); - void isEvaluating(); + void isEvaluating_notEvaluating(); + void isEvaluating_fromNative(); + void isEvaluating_fromEvent(); void printFunctionWithCustomHandler(); void printThrowsException(); void errorConstructors(); - void argumentsProperty(); - void numberClass(); - void forInStatement(); - void functionExpression(); + void argumentsProperty_globalContext(); + void argumentsProperty_JS(); + void argumentsProperty_evaluateInNativeFunction(); + void jsNumberClass(); + void jsForInStatement_simple(); + void jsForInStatement_prototypeProperties(); + void jsForInStatement_mutateWhileIterating(); + void jsForInStatement_arrays(); + void jsForInStatement_nullAndUndefined(); + void jsFunctionDeclarationAsStatement(); void stringObjects(); + void jsStringPrototypeReplaceBugs(); void getterSetterThisObject_global(); void getterSetterThisObject_plain(); void getterSetterThisObject_prototypeChain(); void getterSetterThisObject_activation(); - void continueInSwitch(); - void readOnlyPrototypeProperty(); + void jsContinueInSwitch(); + void jsShadowReadOnlyPrototypeProperty(); void toObject(); - void reservedWords_data(); - void reservedWords(); - void futureReservedWords_data(); - void futureReservedWords(); - void throwInsideWithStatement(); - void getSetAgent(); - void reentrancy(); - void incDecNonObjectProperty(); + void jsReservedWords_data(); + void jsReservedWords(); + void jsFutureReservedWords_data(); + void jsFutureReservedWords(); + void jsThrowInsideWithStatement(); + void getSetAgent_ownership(); + void getSetAgent_deleteAgent(); + void getSetAgent_differentEngine(); + void reentrancy_stringHandles(); + void reentrancy_processEventsInterval(); + void reentrancy_typeConversion(); + void reentrancy_globalObjectProperties(); + void reentrancy_Array(); + void reentrancy_objectCreation(); + void jsIncDecNonObjectProperty(); void installTranslatorFunctions_data(); void installTranslatorFunctions(); void translateScript_data(); @@ -195,6 +225,7 @@ private slots: void translateScriptUnicode(); void translateScriptUnicodeIdBased_data(); void translateScriptUnicodeIdBased(); + void translateFromBuiltinCallback(); void functionScopes(); void nativeFunctionScopes(); void evaluateProgram(); @@ -314,8 +345,8 @@ void tst_QScriptEngine::newFunction() QScriptValue prot = fun.property("prototype", QScriptValue::ResolveLocal); QVERIFY(prot.isObject()); QVERIFY(prot.property("constructor").strictlyEquals(fun)); - QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable); - QCOMPARE(prot.propertyFlags("constructor"), QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + QCOMPARE(prot.propertyFlags("constructor"), QScriptValue::SkipInEnumeration); } // prototype should be Function.prototype QCOMPARE(fun.prototype().isValid(), true); @@ -339,8 +370,8 @@ void tst_QScriptEngine::newFunctionWithArg() QScriptValue prot = fun.property("prototype", QScriptValue::ResolveLocal); QVERIFY(prot.isObject()); QVERIFY(prot.property("constructor").strictlyEquals(fun)); - QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable); - QCOMPARE(prot.propertyFlags("constructor"), QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + QCOMPARE(prot.propertyFlags("constructor"), QScriptValue::SkipInEnumeration); } // prototype should be Function.prototype QCOMPARE(fun.prototype().isValid(), true); @@ -367,10 +398,9 @@ void tst_QScriptEngine::newFunctionWithProto() QCOMPARE(fun.prototype().strictlyEquals(eng.evaluate("Function.prototype")), true); // public prototype should be the one we passed QCOMPARE(fun.property("prototype").strictlyEquals(proto), true); - QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable); + QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); QCOMPARE(proto.property("constructor").strictlyEquals(fun), true); - QCOMPARE(proto.propertyFlags("constructor"), - QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + QCOMPARE(proto.propertyFlags("constructor"), QScriptValue::SkipInEnumeration); QCOMPARE(fun.call().isNull(), true); QCOMPARE(fun.construct().isObject(), true); @@ -609,54 +639,65 @@ void tst_QScriptEngine::newRegExp() QCOMPARE(rexp.toRegExp().pattern(), QRegExp("foo").pattern()); } - { - QScriptValue r = eng.evaluate("/foo/gim"); - QVERIFY(r.isRegExp()); - QCOMPARE(r.toString(), QString::fromLatin1("/foo/gim")); +} + +void tst_QScriptEngine::jsRegExp() +{ + // See ECMA-262 Section 15.10, "RegExp Objects". + // These should really be JS-only tests, as they test the implementation's + // ECMA-compliance, not the C++ API. Compliance should already be covered + // by the Mozilla tests (qscriptjstestsuite). + // We can consider updating the expected results of this test if the + // RegExp implementation changes. - QScriptValue rxCtor = eng.globalObject().property("RegExp"); - QScriptValue r2 = rxCtor.call(QScriptValue(), QScriptValueList() << r); - QVERIFY(r2.isRegExp()); - QVERIFY(r2.strictlyEquals(r)); + QScriptEngine eng; + QScriptValue r = eng.evaluate("/foo/gim"); + QVERIFY(r.isRegExp()); + QCOMPARE(r.toString(), QString::fromLatin1("/foo/gim")); - QScriptValue r3 = rxCtor.call(QScriptValue(), QScriptValueList() << r << "gim"); - QVERIFY(r3.isError()); - QCOMPARE(r3.toString(), QString::fromLatin1("TypeError: Cannot supply flags when constructing one RegExp from another.")); + QScriptValue rxCtor = eng.globalObject().property("RegExp"); + QScriptValue r2 = rxCtor.call(QScriptValue(), QScriptValueList() << r); + QVERIFY(r2.isRegExp()); + QVERIFY(r2.strictlyEquals(r)); - QScriptValue r4 = rxCtor.call(QScriptValue(), QScriptValueList() << "foo" << "gim"); - QVERIFY(r4.isRegExp()); + QScriptValue r3 = rxCtor.call(QScriptValue(), QScriptValueList() << r << "gim"); + QVERIFY(r3.isError()); + QVERIFY(r3.toString().contains(QString::fromLatin1("TypeError"))); // Cannot supply flags when constructing one RegExp from another - QScriptValue r5 = rxCtor.construct(QScriptValueList() << r); - QVERIFY(r5.isRegExp()); - QCOMPARE(r5.toString(), QString::fromLatin1("/foo/gim")); - // In JSC, constructing a RegExp from another produces the same identical object. - // This is different from SpiderMonkey and old back-end. - QVERIFY(r5.strictlyEquals(r)); + QScriptValue r4 = rxCtor.call(QScriptValue(), QScriptValueList() << "foo" << "gim"); + QVERIFY(r4.isRegExp()); - QScriptValue r6 = rxCtor.construct(QScriptValueList() << "foo" << "bar"); - QVERIFY(r6.isError()); - QCOMPARE(r6.toString(), QString::fromLatin1("SyntaxError: Invalid regular expression: invalid regular expression flag")); + QScriptValue r5 = rxCtor.construct(QScriptValueList() << r); + QVERIFY(r5.isRegExp()); + QCOMPARE(r5.toString(), QString::fromLatin1("/foo/gim")); + // In JSC, constructing a RegExp from another produces the same identical object. + // This is different from SpiderMonkey and old back-end. + QVERIFY(r5.strictlyEquals(r)); - QScriptValue r7 = eng.evaluate("/foo/gimp"); - QVERIFY(r7.isError()); - QCOMPARE(r7.toString(), QString::fromLatin1("SyntaxError: Invalid regular expression: invalid regular expression flag")); + QScriptValue r6 = rxCtor.construct(QScriptValueList() << "foo" << "bar"); + QVERIFY(r6.isError()); + QVERIFY(r6.toString().contains(QString::fromLatin1("SyntaxError"))); // Invalid regular expression flag - QScriptValue r8 = eng.evaluate("/foo/migmigmig"); - QVERIFY(r8.isRegExp()); - QCOMPARE(r8.toString(), QString::fromLatin1("/foo/gim")); + QScriptValue r7 = eng.evaluate("/foo/gimp"); + QVERIFY(r7.isError()); + QVERIFY(r7.toString().contains(QString::fromLatin1("SyntaxError"))); // Invalid regular expression flag - QScriptValue r9 = rxCtor.construct(); - QVERIFY(r9.isRegExp()); - QCOMPARE(r9.toString(), QString::fromLatin1("/(?:)/")); + // JSC doesn't complain about duplicate flags. + QScriptValue r8 = eng.evaluate("/foo/migmigmig"); + QVERIFY(r8.isRegExp()); + QCOMPARE(r8.toString(), QString::fromLatin1("/foo/gim")); - QScriptValue r10 = rxCtor.construct(QScriptValueList() << "" << "gim"); - QVERIFY(r10.isRegExp()); - QCOMPARE(r10.toString(), QString::fromLatin1("/(?:)/gim")); + QScriptValue r9 = rxCtor.construct(); + QVERIFY(r9.isRegExp()); + QCOMPARE(r9.toString(), QString::fromLatin1("/(?:)/")); - QScriptValue r11 = rxCtor.construct(QScriptValueList() << "{1.*}" << "g"); - QVERIFY(r11.isRegExp()); - QCOMPARE(r11.toString(), QString::fromLatin1("/{1.*}/g")); - } + QScriptValue r10 = rxCtor.construct(QScriptValueList() << "" << "gim"); + QVERIFY(r10.isRegExp()); + QCOMPARE(r10.toString(), QString::fromLatin1("/(?:)/gim")); + + QScriptValue r11 = rxCtor.construct(QScriptValueList() << "{1.*}" << "g"); + QVERIFY(r11.isRegExp()); + QCOMPARE(r11.toString(), QString::fromLatin1("/{1.*}/g")); } void tst_QScriptEngine::newDate() @@ -695,7 +736,11 @@ void tst_QScriptEngine::newDate() // toDateTime() result should be in local time QCOMPARE(date.toDateTime(), dt.toLocalTime()); } +} +void tst_QScriptEngine::jsParseDate() +{ + QScriptEngine eng; // Date.parse() should return NaN when it fails { QScriptValue ret = eng.evaluate("Date.parse()"); @@ -1196,6 +1241,8 @@ static QScriptValue getSetFoo(QScriptContext *ctx, QScriptEngine *) void tst_QScriptEngine::globalObjectProperties() { + // See ECMA-262 Section 15.1, "The Global Object". + QScriptEngine eng; QScriptValue global = eng.globalObject(); @@ -1271,8 +1318,13 @@ void tst_QScriptEngine::globalObjectProperties() QVERIFY(!global.property("Math").isFunction()); QEXPECT_FAIL("", "[ECMA compliance] JSC sets DontDelete flag for Math object", Continue); QCOMPARE(global.propertyFlags("Math"), QScriptValue::SkipInEnumeration); +} + +void tst_QScriptEngine::globalObjectProperties_enumerate() +{ + QScriptEngine eng; + QScriptValue global = eng.globalObject(); - // enumeration QSet<QString> expectedNames; expectedNames << "isNaN" @@ -1500,7 +1552,7 @@ void tst_QScriptEngine::globalObjectWithCustomPrototype() { QScriptValue ret = engine.evaluate("this.__proto__ = { 'a': 123 }; a"); QVERIFY(ret.isNumber()); - QEXPECT_FAIL("", "QTBUG-9737", Continue); + QEXPECT_FAIL("", "QTBUG-9737: Prototype change in JS not reflected on C++ side", Continue); QVERIFY(ret.strictlyEquals(global.property("a"))); } } @@ -1510,7 +1562,9 @@ void tst_QScriptEngine::builtinFunctionNames_data() QTest::addColumn<QString>("expression"); QTest::addColumn<QString>("expectedName"); - QTest::newRow("print") << QString("print") << QString("print"); + // See ECMA-262 Chapter 15, "Standard Built-in ECMAScript Objects". + + QTest::newRow("print") << QString("print") << QString("print"); // QtScript extension. QTest::newRow("parseInt") << QString("parseInt") << QString("parseInt"); QTest::newRow("parseFloat") << QString("parseFloat") << QString("parseFloat"); QTest::newRow("isNaN") << QString("isNaN") << QString("isNaN"); @@ -1521,8 +1575,8 @@ void tst_QScriptEngine::builtinFunctionNames_data() QTest::newRow("encodeURIComponent") << QString("encodeURIComponent") << QString("encodeURIComponent"); QTest::newRow("escape") << QString("escape") << QString("escape"); QTest::newRow("unescape") << QString("unescape") << QString("unescape"); - QTest::newRow("version") << QString("version") << QString("version"); - QTest::newRow("gc") << QString("gc") << QString("gc"); + QTest::newRow("version") << QString("version") << QString("version"); // QtScript extension. + QTest::newRow("gc") << QString("gc") << QString("gc"); // QtScript extension. QTest::newRow("Array") << QString("Array") << QString("Array"); QTest::newRow("Array.prototype.toString") << QString("Array.prototype.toString") << QString("toString"); @@ -1673,6 +1727,7 @@ void tst_QScriptEngine::builtinFunctionNames() QFETCH(QString, expression); QFETCH(QString, expectedName); QScriptEngine eng; + // The "name" property is actually non-standard, but JSC supports it. QScriptValue ret = eng.evaluate(QString::fromLatin1("%0.name").arg(expression)); QVERIFY(ret.isString()); QCOMPARE(ret.toString(), expectedName); @@ -1894,22 +1949,24 @@ static QScriptValue eval_nested(QScriptContext *ctx, QScriptEngine *eng) return result; } +// Tests that nested evaluate uses the "this" that was passed. void tst_QScriptEngine::nestedEvaluate() { QScriptEngine eng; QScriptValue fun = eng.newFunction(eval_nested); eng.globalObject().setProperty("fun", fun); + // From JS function call { QScriptValue result = eng.evaluate("o = { id:'foo'}; o.fun = fun; o.fun()"); QCOMPARE(result.property("local_bar").toString(), QString("local")); QCOMPARE(result.property("thisObjectIdBefore").toString(), QString("foo")); QCOMPARE(result.property("thisObjectIdAfter").toString(), QString("foo")); QCOMPARE(result.property("evaluatedThisObjectId").toString(), QString("foo")); - QScriptValue bar = eng.evaluate("bar"); + QScriptValue bar = eng.evaluate("bar"); // Was introduced in local scope. QVERIFY(bar.isError()); - QCOMPARE(bar.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bar")); + QVERIFY(bar.toString().contains(QString::fromLatin1("ReferenceError"))); } - + // From QScriptValue::call() { QScriptValue result = fun.call(eng.evaluate("p = { id:'foo' }") , QScriptValueList() ); QCOMPARE(result.property("local_bar").toString(), QString("local")); @@ -1918,7 +1975,7 @@ void tst_QScriptEngine::nestedEvaluate() QCOMPARE(result.property("evaluatedThisObjectId").toString(), QString("foo")); QScriptValue bar = eng.evaluate("bar"); QVERIFY(bar.isError()); - QCOMPARE(bar.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bar")); + QVERIFY(bar.toString().contains(QString::fromLatin1("ReferenceError"))); } } @@ -1985,6 +2042,7 @@ void tst_QScriptEngine::errorMessage_QT679() engine.globalObject().setProperty("foo", 15); QScriptValue error = engine.evaluate("'hello world';\nfoo.bar.blah"); QVERIFY(error.isError()); + // The exact message is back-end specific and subject to change. QCOMPARE(error.toString(), QString::fromLatin1("TypeError: Result of expression 'foo.bar' [undefined] is not an object.")); } @@ -1997,37 +2055,40 @@ public: Q_DECLARE_METATYPE(Foo) Q_DECLARE_METATYPE(Foo*) -void tst_QScriptEngine::getSetDefaultPrototype() +void tst_QScriptEngine::getSetDefaultPrototype_int() { QScriptEngine eng; - { - QScriptValue object = eng.newObject(); - QCOMPARE(eng.defaultPrototype(qMetaTypeId<int>()).isValid(), false); - eng.setDefaultPrototype(qMetaTypeId<int>(), object); - QCOMPARE(eng.defaultPrototype(qMetaTypeId<int>()).strictlyEquals(object), true); - QScriptValue value = eng.newVariant(int(123)); - QCOMPARE(value.prototype().isObject(), true); - QCOMPARE(value.prototype().strictlyEquals(object), true); - eng.setDefaultPrototype(qMetaTypeId<int>(), QScriptValue()); - QCOMPARE(eng.defaultPrototype(qMetaTypeId<int>()).isValid(), false); - QScriptValue value2 = eng.newVariant(int(123)); - QCOMPARE(value2.prototype().strictlyEquals(object), false); - } - { - QScriptValue object = eng.newObject(); - QCOMPARE(eng.defaultPrototype(qMetaTypeId<Foo>()).isValid(), false); - eng.setDefaultPrototype(qMetaTypeId<Foo>(), object); - QCOMPARE(eng.defaultPrototype(qMetaTypeId<Foo>()).strictlyEquals(object), true); - QScriptValue value = eng.newVariant(qVariantFromValue(Foo())); - QCOMPARE(value.prototype().isObject(), true); - QCOMPARE(value.prototype().strictlyEquals(object), true); + QScriptValue object = eng.newObject(); + QCOMPARE(eng.defaultPrototype(qMetaTypeId<int>()).isValid(), false); + eng.setDefaultPrototype(qMetaTypeId<int>(), object); + QCOMPARE(eng.defaultPrototype(qMetaTypeId<int>()).strictlyEquals(object), true); + QScriptValue value = eng.newVariant(int(123)); + QCOMPARE(value.prototype().isObject(), true); + QCOMPARE(value.prototype().strictlyEquals(object), true); - eng.setDefaultPrototype(qMetaTypeId<Foo>(), QScriptValue()); - QCOMPARE(eng.defaultPrototype(qMetaTypeId<Foo>()).isValid(), false); - QScriptValue value2 = eng.newVariant(qVariantFromValue(Foo())); - QCOMPARE(value2.prototype().strictlyEquals(object), false); - } + eng.setDefaultPrototype(qMetaTypeId<int>(), QScriptValue()); + QCOMPARE(eng.defaultPrototype(qMetaTypeId<int>()).isValid(), false); + QScriptValue value2 = eng.newVariant(int(123)); + QCOMPARE(value2.prototype().strictlyEquals(object), false); +} + +void tst_QScriptEngine::getSetDefaultPrototype_customType() +{ + QScriptEngine eng; + + QScriptValue object = eng.newObject(); + QCOMPARE(eng.defaultPrototype(qMetaTypeId<Foo>()).isValid(), false); + eng.setDefaultPrototype(qMetaTypeId<Foo>(), object); + QCOMPARE(eng.defaultPrototype(qMetaTypeId<Foo>()).strictlyEquals(object), true); + QScriptValue value = eng.newVariant(qVariantFromValue(Foo())); + QCOMPARE(value.prototype().isObject(), true); + QCOMPARE(value.prototype().strictlyEquals(object), true); + + eng.setDefaultPrototype(qMetaTypeId<Foo>(), QScriptValue()); + QCOMPARE(eng.defaultPrototype(qMetaTypeId<Foo>()).isValid(), false); + QScriptValue value2 = eng.newVariant(qVariantFromValue(Foo())); + QCOMPARE(value2.prototype().strictlyEquals(object), false); } static QScriptValue fooToScriptValue(QScriptEngine *eng, const Foo &foo) @@ -2061,7 +2122,7 @@ Q_DECLARE_METATYPE(QStack<int>) Q_DECLARE_METATYPE(QQueue<char>) Q_DECLARE_METATYPE(QLinkedList<QStack<int> >) -void tst_QScriptEngine::valueConversion() +void tst_QScriptEngine::valueConversion_basic() { QScriptEngine eng; { @@ -2123,7 +2184,11 @@ void tst_QScriptEngine::valueConversion() QCOMPARE(qScriptValueToValue<QChar>(code), c); QCOMPARE(qScriptValueToValue<QChar>(qScriptValueFromValue(&eng, c)), c); } +} +void tst_QScriptEngine::valueConversion_customType() +{ + QScriptEngine eng; { // a type that we don't have built-in conversion of // (it's stored as a variant) @@ -2169,7 +2234,11 @@ void tst_QScriptEngine::valueConversion() QVERIFY(fooVal2.property("x").strictlyEquals(QScriptValue(&eng, 56))); QVERIFY(fooVal2.property("y").strictlyEquals(QScriptValue(&eng, 78))); } +} +void tst_QScriptEngine::valueConversion_sequence() +{ + QScriptEngine eng; qScriptRegisterSequenceMetaType<QLinkedList<QString> >(&eng); { @@ -2248,7 +2317,11 @@ void tst_QScriptEngine::valueConversion() QCOMPARE(qscriptvalue_cast<QObjectList>(val), lst); } +} +void tst_QScriptEngine::valueConversion_QVariant() +{ + QScriptEngine eng; // qScriptValueFromValue() should be "smart" when the argument is a QVariant { QScriptValue val = qScriptValueFromValue(&eng, QVariant()); @@ -2325,7 +2398,12 @@ void tst_QScriptEngine::valueConversion() QCOMPARE(val.toVariant(), var); } - // task 248802 + QCOMPARE(qscriptvalue_cast<QVariant>(QScriptValue(123)), QVariant(123)); +} + +void tst_QScriptEngine::valueConversion_hooliganTask248802() +{ + QScriptEngine eng; qScriptRegisterMetaType<Foo>(&eng, fooToScriptValueV2, fooFromScriptValueV2); { QScriptValue num(&eng, 123); @@ -2343,6 +2421,11 @@ void tst_QScriptEngine::valueConversion() QCOMPARE(foo.x, 123); } +} + +void tst_QScriptEngine::valueConversion_basic2() +{ + QScriptEngine eng; // more built-in types { QScriptValue val = qScriptValueFromValue(&eng, uint(123)); @@ -2379,6 +2462,11 @@ void tst_QScriptEngine::valueConversion() QVERIFY(val.isNumber()); QCOMPARE(val.toInt32(), 123); } +} + +void tst_QScriptEngine::valueConversion_dateTime() +{ + QScriptEngine eng; { QDateTime in = QDateTime::currentDateTime(); QScriptValue val = qScriptValueFromValue(&eng, in); @@ -2391,6 +2479,11 @@ void tst_QScriptEngine::valueConversion() QVERIFY(val.isDate()); QCOMPARE(val.toDateTime().date(), in); } +} + +void tst_QScriptEngine::valueConversion_regExp() +{ + QScriptEngine eng; { QRegExp in = QRegExp("foo"); QScriptValue val = qScriptValueFromValue(&eng, in); @@ -2416,8 +2509,6 @@ void tst_QScriptEngine::valueConversion() QEXPECT_FAIL("", "QTBUG-6136: JSC-based back-end doesn't preserve QRegExp::minimal (always false)", Continue); QCOMPARE(val.toRegExp().isMinimal(), in.isMinimal()); } - - QCOMPARE(qscriptvalue_cast<QVariant>(QScriptValue(123)), QVariant(123)); } void tst_QScriptEngine::qScriptValueFromValue_noEngine() @@ -2522,7 +2613,7 @@ void tst_QScriptEngine::importExtension() QEXPECT_FAIL("", "JSC throws syntax error eagerly", Continue); QCOMPARE(eng.uncaughtExceptionLineNumber(), 4); QVERIFY(ret.isError()); - QCOMPARE(ret.property("message").toString(), QLatin1String("Parse error")); + QVERIFY(ret.toString().contains(QLatin1String("SyntaxError"))); } QStringList imp = eng.importedExtensions(); QCOMPARE(imp.size(), 2); @@ -2548,6 +2639,9 @@ static QScriptValue recurse2(QScriptContext *ctx, QScriptEngine *eng) void tst_QScriptEngine::infiniteRecursion() { + // Infinite recursion in JS should cause the VM to throw an error + // when the JS stack is exhausted. + // The exact error is back-end specific and subject to change. const QString stackOverflowError = QString::fromLatin1("RangeError: Maximum call stack size exceeded."); QScriptEngine eng; { @@ -2610,6 +2704,8 @@ void tst_QScriptEngine::castWithPrototypeChain() baz2.b = 456; QScriptValue baz2Value = qScriptValueFromValue(&eng, &baz2); { + // qscriptvalue_cast() does magic; if the QScriptValue contains + // t of type T, and the target type is T*, &t is returned. Baz *pbaz = qscriptvalue_cast<Baz*>(baz2Value); QVERIFY(pbaz != 0); QCOMPARE(pbaz->b, baz2.b); @@ -2632,6 +2728,13 @@ void tst_QScriptEngine::castWithPrototypeChain() } // establish chain -- now casting should work + // Why? because qscriptvalue_cast() does magic again. + // It the instance itself is not of type T, qscriptvalue_cast() + // searches the prototype chain for T, and if it finds one, it infers + // that the instance can also be casted to that type. This cast is + // _not_ safe and thus relies on the developer doing the right thing. + // This is an undocumented feature to enable qscriptvalue_cast() to + // be used by prototype functions to cast the JS this-object to C++. bazProto.setPrototype(barProto); { @@ -2740,6 +2843,9 @@ void tst_QScriptEngine::collectGarbage() void tst_QScriptEngine::reportAdditionalMemoryCost() { QScriptEngine eng; + // There isn't any reliable way to test whether calling + // this function affects garbage collection responsiveness; + // the best we can do is call it with a few different values. for (int x = 0; x < 1000; ++x) { eng.reportAdditionalMemoryCost(0); eng.reportAdditionalMemoryCost(10); @@ -2757,6 +2863,8 @@ void tst_QScriptEngine::reportAdditionalMemoryCost() void tst_QScriptEngine::gcWithNestedDataStructure() { + // The GC must be able to traverse deeply nested objects, otherwise this + // test would crash. QScriptEngine eng; eng.evaluate( "function makeList(size)" @@ -2778,6 +2886,7 @@ void tst_QScriptEngine::gcWithNestedDataStructure() if (x == 1) eng.evaluate("gc()"); QScriptValue l = head; + // Make sure all the nodes are still alive. for (int i = 0; i < 200; ++i) { QCOMPARE(l.property("data").toString(), QString::number(i)); l = l.property("next"); @@ -2807,6 +2916,8 @@ void tst_QScriptEngine::processEventsWhileRunning() if (x == 0) eng.pushContext(); + // This is running for a silly amount of time just to make sure + // the script doesn't finish before event processing is triggered. QString script = QString::fromLatin1( "var end = Number(new Date()) + 2000;" "var x = 0;" @@ -3012,13 +3123,15 @@ void tst_QScriptEngine::numberParsing() } // see ECMA-262, section 7.9 +// This is testing ECMA compliance, not our C++ API, but it's important that +// the back-end is conformant in this regard. void tst_QScriptEngine::automaticSemicolonInsertion() { QScriptEngine eng; { QScriptValue ret = eng.evaluate("{ 1 2 } 3"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("SyntaxError: Parse error")); + QVERIFY(ret.toString().contains("SyntaxError")); } { QScriptValue ret = eng.evaluate("{ 1\n2 } 3"); @@ -3028,7 +3141,7 @@ void tst_QScriptEngine::automaticSemicolonInsertion() { QScriptValue ret = eng.evaluate("for (a; b\n)"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("SyntaxError: Parse error")); + QVERIFY(ret.toString().contains("SyntaxError")); } { QScriptValue ret = eng.evaluate("(function() { return\n1 + 2 })()"); @@ -3043,7 +3156,7 @@ void tst_QScriptEngine::automaticSemicolonInsertion() { QScriptValue ret = eng.evaluate("if (a > b)\nelse c = d"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("SyntaxError: Parse error")); + QVERIFY(ret.toString().contains("SyntaxError")); } { eng.evaluate("function c() { return { foo: function() { return 5; } } }"); @@ -3055,7 +3168,7 @@ void tst_QScriptEngine::automaticSemicolonInsertion() { QScriptValue ret = eng.evaluate("throw\n1"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("SyntaxError: Parse error")); + QVERIFY(ret.toString().contains("SyntaxError")); } { QScriptValue ret = eng.evaluate("a = Number(1)\n++a"); @@ -3257,7 +3370,7 @@ static QScriptValue myFunctionAbortingEvaluation(QScriptContext *, QScriptEngine return eng->nullValue(); // should be ignored } -void tst_QScriptEngine::abortEvaluation() +void tst_QScriptEngine::abortEvaluation_notEvaluating() { QScriptEngine eng; @@ -3270,7 +3383,11 @@ void tst_QScriptEngine::abortEvaluation() QVERIFY(ret.isString()); QCOMPARE(ret.toString(), QString::fromLatin1("ciao")); } +} +void tst_QScriptEngine::abortEvaluation() +{ + QScriptEngine eng; EventReceiver3 receiver(&eng); eng.setProcessEventsInterval(100); @@ -3301,6 +3418,13 @@ void tst_QScriptEngine::abortEvaluation() } } +} + +void tst_QScriptEngine::abortEvaluation_tryCatch() +{ + QScriptEngine eng; + EventReceiver3 receiver(&eng); + eng.setProcessEventsInterval(100); // scripts cannot intercept the abortion with try/catch for (int y = 0; y < 4; ++y) { QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1))); @@ -3334,13 +3458,15 @@ void tst_QScriptEngine::abortEvaluation() break; } } +} - { - QScriptValue fun = eng.newFunction(myFunctionAbortingEvaluation); - eng.globalObject().setProperty("myFunctionAbortingEvaluation", fun); - QScriptValue ret = eng.evaluate("myFunctionAbortingEvaluation()"); - QVERIFY(!ret.isValid()); - } +void tst_QScriptEngine::abortEvaluation_fromNative() +{ + QScriptEngine eng; + QScriptValue fun = eng.newFunction(myFunctionAbortingEvaluation); + eng.globalObject().setProperty("myFunctionAbortingEvaluation", fun); + QScriptValue ret = eng.evaluate("myFunctionAbortingEvaluation()"); + QVERIFY(!ret.isValid()); } class ThreadedEngine : public QThread { @@ -3407,7 +3533,7 @@ public: bool wasEvaluating; }; -void tst_QScriptEngine::isEvaluating() +void tst_QScriptEngine::isEvaluating_notEvaluating() { QScriptEngine eng; @@ -3419,30 +3545,34 @@ void tst_QScriptEngine::isEvaluating() QVERIFY(!eng.isEvaluating()); eng.evaluate("0 = 0"); QVERIFY(!eng.isEvaluating()); +} - { - QScriptValue fun = eng.newFunction(myFunctionReturningIsEvaluating); - eng.globalObject().setProperty("myFunctionReturningIsEvaluating", fun); - QScriptValue ret = eng.evaluate("myFunctionReturningIsEvaluating()"); - QVERIFY(ret.isBoolean()); - QVERIFY(ret.toBoolean()); - } +void tst_QScriptEngine::isEvaluating_fromNative() +{ + QScriptEngine eng; + QScriptValue fun = eng.newFunction(myFunctionReturningIsEvaluating); + eng.globalObject().setProperty("myFunctionReturningIsEvaluating", fun); + QScriptValue ret = eng.evaluate("myFunctionReturningIsEvaluating()"); + QVERIFY(ret.isBoolean()); + QVERIFY(ret.toBoolean()); +} - { - EventReceiver4 receiver(&eng); - QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1))); +void tst_QScriptEngine::isEvaluating_fromEvent() +{ + QScriptEngine eng; + EventReceiver4 receiver(&eng); + QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1))); - QString script = QString::fromLatin1( - "var end = Number(new Date()) + 1000;" - "var x = 0;" - "while (Number(new Date()) < end) {" - " ++x;" - "}"); + QString script = QString::fromLatin1( + "var end = Number(new Date()) + 1000;" + "var x = 0;" + "while (Number(new Date()) < end) {" + " ++x;" + "}"); - eng.setProcessEventsInterval(100); - eng.evaluate(script); - QVERIFY(receiver.wasEvaluating); - } + eng.setProcessEventsInterval(100); + eng.evaluate(script); + QVERIFY(receiver.wasEvaluating); } static QtMsgType theMessageType; @@ -3456,24 +3586,33 @@ static void myMsgHandler(QtMsgType type, const char *msg) void tst_QScriptEngine::printFunctionWithCustomHandler() { + // The built-in print() function passes the output to Qt's message + // handler. By installing a custom message handler, the output can be + // redirected without changing the print() function itself. + // This behavior is not documented. QScriptEngine eng; QtMsgHandler oldHandler = qInstallMsgHandler(myMsgHandler); QVERIFY(eng.globalObject().property("print").isFunction()); + theMessageType = QtSystemMsg; QVERIFY(theMessage.isEmpty()); QVERIFY(eng.evaluate("print('test')").isUndefined()); QCOMPARE(theMessageType, QtDebugMsg); QCOMPARE(theMessage, QString::fromLatin1("test")); + theMessageType = QtSystemMsg; theMessage.clear(); QVERIFY(eng.evaluate("print(3, true, 'little pigs')").isUndefined()); QCOMPARE(theMessageType, QtDebugMsg); QCOMPARE(theMessage, QString::fromLatin1("3 true little pigs")); + qInstallMsgHandler(oldHandler); } void tst_QScriptEngine::printThrowsException() { + // If an argument to print() causes an exception to be thrown when + // it's converted to a string, print() should propagate the exception. QScriptEngine eng; QScriptValue ret = eng.evaluate("print({ toString: function() { throw 'foo'; } });"); QVERIFY(eng.hasUncaughtException()); @@ -3506,34 +3645,30 @@ void tst_QScriptEngine::errorConstructors() } } -static QScriptValue argumentsProperty_fun(QScriptContext *, QScriptEngine *eng) +void tst_QScriptEngine::argumentsProperty_globalContext() { - eng->evaluate("var a = arguments[0];"); - eng->evaluate("arguments[0] = 200;"); - return eng->evaluate("a + arguments[0]"); + QScriptEngine eng; + { + // Unlike function calls, the global context doesn't have an + // arguments property. + QScriptValue ret = eng.evaluate("arguments"); + QVERIFY(ret.isError()); + QVERIFY(ret.toString().contains(QString::fromLatin1("ReferenceError"))); + } + eng.evaluate("arguments = 10"); + { + QScriptValue ret = eng.evaluate("arguments"); + QVERIFY(ret.isNumber()); + QCOMPARE(ret.toInt32(), 10); + } + QVERIFY(eng.evaluate("delete arguments").toBoolean()); + QVERIFY(!eng.globalObject().property("arguments").isValid()); } - -void tst_QScriptEngine::argumentsProperty() +void tst_QScriptEngine::argumentsProperty_JS() { { QScriptEngine eng; - { - QScriptValue ret = eng.evaluate("arguments"); - QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: arguments")); - } - eng.evaluate("arguments = 10"); - { - QScriptValue ret = eng.evaluate("arguments"); - QVERIFY(ret.isNumber()); - QCOMPARE(ret.toInt32(), 10); - } - QVERIFY(eng.evaluate("delete arguments").toBoolean()); - QVERIFY(!eng.globalObject().property("arguments").isValid()); - } - { - QScriptEngine eng; eng.evaluate("o = { arguments: 123 }"); QScriptValue ret = eng.evaluate("with (o) { arguments; }"); QVERIFY(ret.isNumber()); @@ -3542,24 +3677,39 @@ void tst_QScriptEngine::argumentsProperty() { QScriptEngine eng; QVERIFY(!eng.globalObject().property("arguments").isValid()); + // This is testing ECMA-262 compliance. In function calls, "arguments" + // appears like a local variable, and it can be replaced. QScriptValue ret = eng.evaluate("(function() { arguments = 456; return arguments; })()"); QVERIFY(ret.isNumber()); QCOMPARE(ret.toInt32(), 456); QVERIFY(!eng.globalObject().property("arguments").isValid()); } +} - { - QScriptEngine eng; - QScriptValue fun = eng.newFunction(argumentsProperty_fun); - eng.globalObject().setProperty("fun", eng.newFunction(argumentsProperty_fun)); - QScriptValue result = eng.evaluate("fun(18)"); - QVERIFY(result.isNumber()); - QCOMPARE(result.toInt32(), 218); - } +static QScriptValue argumentsProperty_fun(QScriptContext *, QScriptEngine *eng) +{ + // Since evaluate() is done in the current context, "arguments" should + // refer to currentContext()->argumentsObject(). + // This is for consistency with the built-in JS eval() function. + eng->evaluate("var a = arguments[0];"); + eng->evaluate("arguments[0] = 200;"); + return eng->evaluate("a + arguments[0]"); +} + +void tst_QScriptEngine::argumentsProperty_evaluateInNativeFunction() +{ + QScriptEngine eng; + QScriptValue fun = eng.newFunction(argumentsProperty_fun); + eng.globalObject().setProperty("fun", eng.newFunction(argumentsProperty_fun)); + QScriptValue result = eng.evaluate("fun(18)"); + QVERIFY(result.isNumber()); + QCOMPARE(result.toInt32(), 200+18); } -void tst_QScriptEngine::numberClass() +void tst_QScriptEngine::jsNumberClass() { + // See ECMA-262 Section 15.7, "Number Objects". + QScriptEngine eng; QScriptValue ctor = eng.globalObject().property("Number"); @@ -3669,7 +3819,7 @@ void tst_QScriptEngine::numberClass() } } -void tst_QScriptEngine::forInStatement() +void tst_QScriptEngine::jsForInStatement_simple() { QScriptEngine eng; { @@ -3692,8 +3842,11 @@ void tst_QScriptEngine::forInStatement() QCOMPARE(lst.at(0), QString::fromLatin1("p")); QCOMPARE(lst.at(1), QString::fromLatin1("q")); } +} - // properties in prototype +void tst_QScriptEngine::jsForInStatement_prototypeProperties() +{ + QScriptEngine eng; { QScriptValue ret = eng.evaluate("o = { }; o.__proto__ = { p: 123 }; r = [];" "for (var p in o) r[r.length] = p; r"); @@ -3718,6 +3871,11 @@ void tst_QScriptEngine::forInStatement() QCOMPARE(lst.at(0), QString::fromLatin1("p")); } +} + +void tst_QScriptEngine::jsForInStatement_mutateWhileIterating() +{ + QScriptEngine eng; // deleting property during enumeration { QScriptValue ret = eng.evaluate("o = { p: 123 }; r = [];" @@ -3743,7 +3901,11 @@ void tst_QScriptEngine::forInStatement() QCOMPARE(lst.at(0), QString::fromLatin1("p")); } - // arrays +} + +void tst_QScriptEngine::jsForInStatement_arrays() +{ + QScriptEngine eng; { QScriptValue ret = eng.evaluate("a = [123, 456]; r = [];" "for (var p in a) r[r.length] = p; r"); @@ -3774,10 +3936,11 @@ void tst_QScriptEngine::forInStatement() QCOMPARE(lst.at(3), QString::fromLatin1("2")); QCOMPARE(lst.at(4), QString::fromLatin1("bar")); } +} - // null and undefined - // according to the spec, we should throw an exception; however, for - // compability with the real world, we don't +void tst_QScriptEngine::jsForInStatement_nullAndUndefined() +{ + QScriptEngine eng; { QScriptValue ret = eng.evaluate("r = true; for (var p in undefined) r = false; r"); QVERIFY(ret.isBool()); @@ -3790,9 +3953,17 @@ void tst_QScriptEngine::forInStatement() } } -void tst_QScriptEngine::functionExpression() +void tst_QScriptEngine::jsFunctionDeclarationAsStatement() { - // task 175679 + // ECMA-262 does not allow function declarations to be used as statements, + // but several popular implementations (including JSC) do. See the NOTE + // at the beginning of chapter 12 in ECMA-262 5th edition, where it's + // recommended that implementations either disallow this usage or issue + // a warning. + // Since we had a bug report long ago about QtScript not supporting this + // "feature" (and thus deviating from other implementations), we still + // check this behavior. + QScriptEngine eng; QVERIFY(!eng.globalObject().property("bar").isValid()); eng.evaluate("function foo(arg) {\n" @@ -3825,6 +3996,8 @@ void tst_QScriptEngine::functionExpression() void tst_QScriptEngine::stringObjects() { + // See ECMA-262 Section 15.5, "String Objects". + QScriptEngine eng; QString str("ciao"); // in C++ @@ -3886,7 +4059,11 @@ void tst_QScriptEngine::stringObjects() QVERIFY(ret7.isBoolean()); QVERIFY(ret7.toBoolean()); } +} +void tst_QScriptEngine::jsStringPrototypeReplaceBugs() +{ + QScriptEngine eng; // task 212440 { QScriptValue ret = eng.evaluate("replace_args = []; \"a a a\".replace(/(a)/g, function() { replace_args.push(arguments); }); replace_args"); @@ -4038,8 +4215,10 @@ void tst_QScriptEngine::getterSetterThisObject_activation() } } -void tst_QScriptEngine::continueInSwitch() +void tst_QScriptEngine::jsContinueInSwitch() { + // This is testing ECMA-262 compliance, not C++ API. + QScriptEngine eng; // switch - continue { @@ -4116,35 +4295,17 @@ void tst_QScriptEngine::continueInSwitch() } } -void tst_QScriptEngine::readOnlyPrototypeProperty() +void tst_QScriptEngine::jsShadowReadOnlyPrototypeProperty() { - QSKIP("JSC semantics differ from old back-end and SpiderMonkey", SkipAll); + // SpiderMonkey has different behavior than JSC and V8; it disallows + // creating a property on the instance if there's a property with the + // same name in the prototype, and that property is read-only. We + // adopted that behavior in the old (4.5) QtScript back-end, but it + // just seems weird -- and non-compliant. Adopt the JSC behavior instead. QScriptEngine eng; - QCOMPARE(eng.evaluate("o = {}; o.__proto__ = parseInt; o.length").toInt32(), 2); - QCOMPARE(eng.evaluate("o.length = 4; o.length").toInt32(), 2); - QVERIFY(!eng.evaluate("o.hasOwnProperty('length')").toBoolean()); - QCOMPARE(eng.evaluate("o.length *= 2; o.length").toInt32(), 2); - QCOMPARE(eng.evaluate("o.length /= 2; o.length").toInt32(), 2); - QCOMPARE(eng.evaluate("o.length %= 2; o.length").toInt32(), 2); - QCOMPARE(eng.evaluate("o.length += 2; o.length").toInt32(), 2); - QCOMPARE(eng.evaluate("o.length -= 2; o.length").toInt32(), 2); - QCOMPARE(eng.evaluate("o.length <<= 2; o.length").toInt32(), 2); - QCOMPARE(eng.evaluate("o.length >>= 2; o.length").toInt32(), 2); - QCOMPARE(eng.evaluate("o.length >>>= 2; o.length").toInt32(), 2); - QCOMPARE(eng.evaluate("o.length &= 0; o.length").toInt32(), 2); - QCOMPARE(eng.evaluate("o.length ^= 255; o.length").toInt32(), 2); - QCOMPARE(eng.evaluate("o.length |= 255; o.length").toInt32(), 2); - - { - QScriptValue ret = eng.evaluate("o.__defineGetter__('length', function() {})"); - QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("Error: cannot redefine read-only property")); - } - { - QScriptValue ret = eng.evaluate("o.__defineSetter__('length', function() {})"); - QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("Error: cannot redefine read-only property")); - } + QVERIFY(eng.evaluate("o = {}; o.__proto__ = parseInt; o.length").isNumber()); + QCOMPARE(eng.evaluate("o.length = 123; o.length").toInt32(), 123); + QVERIFY(eng.evaluate("o.hasOwnProperty('length')").toBoolean()); } void tst_QScriptEngine::toObject() @@ -4226,7 +4387,7 @@ void tst_QScriptEngine::toObject() QVERIFY(stringValue.isString()); } -void tst_QScriptEngine::reservedWords_data() +void tst_QScriptEngine::jsReservedWords_data() { QTest::addColumn<QString>("word"); QTest::newRow("break") << QString("break"); @@ -4259,8 +4420,13 @@ void tst_QScriptEngine::reservedWords_data() QTest::newRow("with") << QString("with"); } -void tst_QScriptEngine::reservedWords() +void tst_QScriptEngine::jsReservedWords() { + // See ECMA-262 Section 7.6.1, "Reserved Words". + // We prefer that the implementation is less strict than the spec; e.g. + // it's good to allow reserved words as identifiers in object literals, + // and when accessing properties using dot notation. + QFETCH(QString, word); { QScriptEngine eng; @@ -4298,7 +4464,7 @@ void tst_QScriptEngine::reservedWords() } } -void tst_QScriptEngine::futureReservedWords_data() +void tst_QScriptEngine::jsFutureReservedWords_data() { QTest::addColumn<QString>("word"); QTest::addColumn<bool>("allowed"); @@ -4335,8 +4501,12 @@ void tst_QScriptEngine::futureReservedWords_data() QTest::newRow("volatile") << QString("volatile") << true; } -void tst_QScriptEngine::futureReservedWords() +void tst_QScriptEngine::jsFutureReservedWords() { + // See ECMA-262 Section 7.6.1.2, "Future Reserved Words". + // In real-world implementations, most of these words are + // actually allowed as normal identifiers. + QFETCH(QString, word); QFETCH(bool, allowed); { @@ -4364,8 +4534,10 @@ void tst_QScriptEngine::futureReservedWords() } } -void tst_QScriptEngine::throwInsideWithStatement() +void tst_QScriptEngine::jsThrowInsideWithStatement() { + // This is testing ECMA-262 compliance, not C++ API. + // task 209988 QScriptEngine eng; { @@ -4379,7 +4551,7 @@ void tst_QScriptEngine::throwInsideWithStatement() " bad;" "}"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bad")); + QVERIFY(ret.toString().contains(QString::fromLatin1("ReferenceError"))); } { QScriptValue ret = eng.evaluate( @@ -4392,7 +4564,7 @@ void tst_QScriptEngine::throwInsideWithStatement() " bad;" "}"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bad")); + QVERIFY(ret.toString().contains(QString::fromLatin1("ReferenceError"))); } { eng.clearExceptions(); @@ -4419,7 +4591,7 @@ void tst_QScriptEngine::throwInsideWithStatement() QVERIFY(ret.isNumber()); QScriptValue ret2 = eng.evaluate("bug"); QVERIFY(ret2.isError()); - QCOMPARE(ret2.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bug")); + QVERIFY(ret2.toString().contains(QString::fromLatin1("ReferenceError"))); } } @@ -4429,106 +4601,116 @@ public: TestAgent(QScriptEngine *engine) : QScriptEngineAgent(engine) {} }; -void tst_QScriptEngine::getSetAgent() +void tst_QScriptEngine::getSetAgent_ownership() { - // case 1: engine deleted before agent --> agent deleted too - { - QScriptEngine *eng = new QScriptEngine; - QCOMPARE(eng->agent(), (QScriptEngineAgent*)0); - TestAgent *agent = new TestAgent(eng); - eng->setAgent(agent); - QCOMPARE(eng->agent(), (QScriptEngineAgent*)agent); - eng->setAgent(0); // the engine maintains ownership of the old agent - QCOMPARE(eng->agent(), (QScriptEngineAgent*)0); - delete eng; - } - // case 2: agent deleted before engine --> engine's agent should become 0 - { - QScriptEngine *eng = new QScriptEngine; - TestAgent *agent = new TestAgent(eng); - eng->setAgent(agent); - QCOMPARE(eng->agent(), (QScriptEngineAgent*)agent); - delete agent; - QCOMPARE(eng->agent(), (QScriptEngineAgent*)0); - eng->evaluate("(function(){ return 123; })()"); - delete eng; - } - { - QScriptEngine eng; - QScriptEngine eng2; - TestAgent *agent = new TestAgent(&eng); - QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::setAgent(): cannot set agent belonging to different engine"); - eng2.setAgent(agent); - QCOMPARE(eng2.agent(), (QScriptEngineAgent*)0); - } + // engine deleted before agent --> agent deleted too + QScriptEngine *eng = new QScriptEngine; + QCOMPARE(eng->agent(), (QScriptEngineAgent*)0); + TestAgent *agent = new TestAgent(eng); + eng->setAgent(agent); + QCOMPARE(eng->agent(), (QScriptEngineAgent*)agent); + eng->setAgent(0); // the engine maintains ownership of the old agent + QCOMPARE(eng->agent(), (QScriptEngineAgent*)0); + delete eng; } -void tst_QScriptEngine::reentrancy() +void tst_QScriptEngine::getSetAgent_deleteAgent() { + // agent deleted before engine --> engine's agent should become 0 + QScriptEngine *eng = new QScriptEngine; + TestAgent *agent = new TestAgent(eng); + eng->setAgent(agent); + QCOMPARE(eng->agent(), (QScriptEngineAgent*)agent); + delete agent; + QCOMPARE(eng->agent(), (QScriptEngineAgent*)0); + eng->evaluate("(function(){ return 123; })()"); + delete eng; +} + +void tst_QScriptEngine::getSetAgent_differentEngine() +{ + QScriptEngine eng; + QScriptEngine eng2; + TestAgent *agent = new TestAgent(&eng); + QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::setAgent(): cannot set agent belonging to different engine"); + eng2.setAgent(agent); + QCOMPARE(eng2.agent(), (QScriptEngineAgent*)0); +} + +void tst_QScriptEngine::reentrancy_stringHandles() +{ + QScriptEngine eng1; + QScriptEngine eng2; + QScriptString s1 = eng1.toStringHandle("foo"); + QScriptString s2 = eng2.toStringHandle("foo"); + QVERIFY(s1 != s2); +} + +void tst_QScriptEngine::reentrancy_processEventsInterval() +{ + QScriptEngine eng1; + QScriptEngine eng2; + eng1.setProcessEventsInterval(123); + QCOMPARE(eng2.processEventsInterval(), -1); + eng2.setProcessEventsInterval(456); + QCOMPARE(eng1.processEventsInterval(), 123); +} + +void tst_QScriptEngine::reentrancy_typeConversion() +{ + QScriptEngine eng1; + QScriptEngine eng2; + qScriptRegisterMetaType<Foo>(&eng1, fooToScriptValue, fooFromScriptValue); + Foo foo; + foo.x = 12; + foo.y = 34; { - QScriptEngine eng1; - QScriptEngine eng2; - QScriptString s1 = eng1.toStringHandle("foo"); - QScriptString s2 = eng2.toStringHandle("foo"); - QVERIFY(s1 != s2); - } - { - QScriptEngine eng1; - QScriptEngine eng2; - eng1.setProcessEventsInterval(123); - QCOMPARE(eng2.processEventsInterval(), -1); - eng2.setProcessEventsInterval(456); - QCOMPARE(eng1.processEventsInterval(), 123); + QScriptValue fooVal = qScriptValueFromValue(&eng1, foo); + QVERIFY(fooVal.isObject()); + QVERIFY(!fooVal.isVariant()); + QCOMPARE(fooVal.property("x").toInt32(), 12); + QCOMPARE(fooVal.property("y").toInt32(), 34); + fooVal.setProperty("x", 56); + fooVal.setProperty("y", 78); + + Foo foo2 = qScriptValueToValue<Foo>(fooVal); + QCOMPARE(foo2.x, 56); + QCOMPARE(foo2.y, 78); } { - QScriptEngine eng1; - QScriptEngine eng2; - qScriptRegisterMetaType<Foo>(&eng1, fooToScriptValue, fooFromScriptValue); - Foo foo; - foo.x = 12; - foo.y = 34; - { - QScriptValue fooVal = qScriptValueFromValue(&eng1, foo); - QVERIFY(fooVal.isObject()); - QVERIFY(!fooVal.isVariant()); - QCOMPARE(fooVal.property("x").toInt32(), 12); - QCOMPARE(fooVal.property("y").toInt32(), 34); - fooVal.setProperty("x", 56); - fooVal.setProperty("y", 78); - - Foo foo2 = qScriptValueToValue<Foo>(fooVal); - QCOMPARE(foo2.x, 56); - QCOMPARE(foo2.y, 78); - } - { - QScriptValue fooVal = qScriptValueFromValue(&eng2, foo); - QVERIFY(fooVal.isVariant()); + QScriptValue fooVal = qScriptValueFromValue(&eng2, foo); + QVERIFY(fooVal.isVariant()); - Foo foo2 = qScriptValueToValue<Foo>(fooVal); - QCOMPARE(foo2.x, 12); - QCOMPARE(foo2.y, 34); - } - QVERIFY(!eng1.defaultPrototype(qMetaTypeId<Foo>()).isValid()); - QVERIFY(!eng2.defaultPrototype(qMetaTypeId<Foo>()).isValid()); - QScriptValue proto1 = eng1.newObject(); - eng1.setDefaultPrototype(qMetaTypeId<Foo>(), proto1); - QVERIFY(!eng2.defaultPrototype(qMetaTypeId<Foo>()).isValid()); - QScriptValue proto2 = eng2.newObject(); - eng2.setDefaultPrototype(qMetaTypeId<Foo>(), proto2); - QVERIFY(eng2.defaultPrototype(qMetaTypeId<Foo>()).isValid()); - QVERIFY(eng1.defaultPrototype(qMetaTypeId<Foo>()).strictlyEquals(proto1)); - } - { - QScriptEngine eng1; - QScriptEngine eng2; - QVERIFY(!eng2.globalObject().property("a").isValid()); - eng1.evaluate("a = 10"); - QVERIFY(eng1.globalObject().property("a").isNumber()); - QVERIFY(!eng2.globalObject().property("a").isValid()); - eng2.evaluate("a = 20"); - QVERIFY(eng2.globalObject().property("a").isNumber()); - QCOMPARE(eng1.globalObject().property("a").toInt32(), 10); + Foo foo2 = qScriptValueToValue<Foo>(fooVal); + QCOMPARE(foo2.x, 12); + QCOMPARE(foo2.y, 34); } + QVERIFY(!eng1.defaultPrototype(qMetaTypeId<Foo>()).isValid()); + QVERIFY(!eng2.defaultPrototype(qMetaTypeId<Foo>()).isValid()); + QScriptValue proto1 = eng1.newObject(); + eng1.setDefaultPrototype(qMetaTypeId<Foo>(), proto1); + QVERIFY(!eng2.defaultPrototype(qMetaTypeId<Foo>()).isValid()); + QScriptValue proto2 = eng2.newObject(); + eng2.setDefaultPrototype(qMetaTypeId<Foo>(), proto2); + QVERIFY(eng2.defaultPrototype(qMetaTypeId<Foo>()).isValid()); + QVERIFY(eng1.defaultPrototype(qMetaTypeId<Foo>()).strictlyEquals(proto1)); +} + +void tst_QScriptEngine::reentrancy_globalObjectProperties() +{ + QScriptEngine eng1; + QScriptEngine eng2; + QVERIFY(!eng2.globalObject().property("a").isValid()); + eng1.evaluate("a = 10"); + QVERIFY(eng1.globalObject().property("a").isNumber()); + QVERIFY(!eng2.globalObject().property("a").isValid()); + eng2.evaluate("a = 20"); + QVERIFY(eng2.globalObject().property("a").isNumber()); + QCOMPARE(eng1.globalObject().property("a").toInt32(), 10); +} + +void tst_QScriptEngine::reentrancy_Array() +{ // weird bug with JSC backend { QScriptEngine eng; @@ -4540,79 +4722,82 @@ void tst_QScriptEngine::reentrancy() QScriptEngine eng; QCOMPARE(eng.evaluate("Array()").toString(), QString()); } +} +void tst_QScriptEngine::reentrancy_objectCreation() +{ + QScriptEngine eng1; + QScriptEngine eng2; { - QScriptEngine eng1; - QScriptEngine eng2; - { - QScriptValue d1 = eng1.newDate(0); - QScriptValue d2 = eng2.newDate(0); - QCOMPARE(d1.toDateTime(), d2.toDateTime()); - QCOMPARE(d2.toDateTime(), d1.toDateTime()); - } - { - QScriptValue r1 = eng1.newRegExp("foo", "gim"); - QScriptValue r2 = eng2.newRegExp("foo", "gim"); - QCOMPARE(r1.toRegExp(), r2.toRegExp()); - QCOMPARE(r2.toRegExp(), r1.toRegExp()); - } - { - QScriptValue o1 = eng1.newQObject(this); - QScriptValue o2 = eng2.newQObject(this); - QCOMPARE(o1.toQObject(), o2.toQObject()); - QCOMPARE(o2.toQObject(), o1.toQObject()); - } - { - QScriptValue mo1 = eng1.newQMetaObject(&staticMetaObject); - QScriptValue mo2 = eng2.newQMetaObject(&staticMetaObject); - QCOMPARE(mo1.toQMetaObject(), mo2.toQMetaObject()); - QCOMPARE(mo2.toQMetaObject(), mo1.toQMetaObject()); - } + QScriptValue d1 = eng1.newDate(0); + QScriptValue d2 = eng2.newDate(0); + QCOMPARE(d1.toDateTime(), d2.toDateTime()); + QCOMPARE(d2.toDateTime(), d1.toDateTime()); + } + { + QScriptValue r1 = eng1.newRegExp("foo", "gim"); + QScriptValue r2 = eng2.newRegExp("foo", "gim"); + QCOMPARE(r1.toRegExp(), r2.toRegExp()); + QCOMPARE(r2.toRegExp(), r1.toRegExp()); + } + { + QScriptValue o1 = eng1.newQObject(this); + QScriptValue o2 = eng2.newQObject(this); + QCOMPARE(o1.toQObject(), o2.toQObject()); + QCOMPARE(o2.toQObject(), o1.toQObject()); + } + { + QScriptValue mo1 = eng1.newQMetaObject(&staticMetaObject); + QScriptValue mo2 = eng2.newQMetaObject(&staticMetaObject); + QCOMPARE(mo1.toQMetaObject(), mo2.toQMetaObject()); + QCOMPARE(mo2.toQMetaObject(), mo1.toQMetaObject()); } } -void tst_QScriptEngine:: incDecNonObjectProperty() +void tst_QScriptEngine::jsIncDecNonObjectProperty() { + // This is testing ECMA-262 compliance, not C++ API. + QScriptEngine eng; { QScriptValue ret = eng.evaluate("var a; a.n++"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [undefined] is not an object.")); + QVERIFY(ret.toString().contains(QString::fromLatin1("TypeError"))); } { QScriptValue ret = eng.evaluate("var a; a.n--"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [undefined] is not an object.")); + QVERIFY(ret.toString().contains(QString::fromLatin1("TypeError"))); } { QScriptValue ret = eng.evaluate("var a = null; a.n++"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object.")); + QVERIFY(ret.toString().contains(QString::fromLatin1("TypeError"))); } { QScriptValue ret = eng.evaluate("var a = null; a.n--"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object.")); + QVERIFY(ret.toString().contains(QString::fromLatin1("TypeError"))); } { QScriptValue ret = eng.evaluate("var a; ++a.n"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object.")); + QVERIFY(ret.toString().contains(QString::fromLatin1("TypeError"))); } { QScriptValue ret = eng.evaluate("var a; --a.n"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object.")); + QVERIFY(ret.toString().contains(QString::fromLatin1("TypeError"))); } { QScriptValue ret = eng.evaluate("var a; a.n += 1"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object.")); + QVERIFY(ret.toString().contains(QString::fromLatin1("TypeError"))); } { QScriptValue ret = eng.evaluate("var a; a.n -= 1"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object.")); + QVERIFY(ret.toString().contains(QString::fromLatin1("TypeError"))); } { QScriptValue ret = eng.evaluate("var a = 'ciao'; a.length++"); @@ -5125,6 +5310,21 @@ void tst_QScriptEngine::translateScriptUnicodeIdBased() QVERIFY(!engine.hasUncaughtException()); } +void tst_QScriptEngine::translateFromBuiltinCallback() +{ + QScriptEngine eng; + eng.installTranslatorFunctions(); + + // Callback has no translation context. + eng.evaluate("function foo() { qsTr('foo'); }"); + + // Stack at translation time will be: + // qsTr, foo, forEach, global + // qsTr() needs to walk to the outer-most (global) frame before it finds + // a translation context, and this should not crash. + eng.evaluate("[10,20].forEach(foo)", "script.js"); +} + void tst_QScriptEngine::functionScopes() { QScriptEngine eng; @@ -5436,6 +5636,7 @@ void tst_QScriptEngine::collectGarbageAfterConnect() .isUndefined()); QVERIFY(widget != 0); engine.evaluate("widget = null;"); + // The connection should not keep the widget alive. collectGarbage_helper(engine); QVERIFY(widget == 0); } @@ -5599,6 +5800,17 @@ void tst_QScriptEngine::reentrency() void tst_QScriptEngine::newFixedStaticScopeObject() { + // "Static scope objects" is an optimization we do for QML. + // It enables the creation of JS objects that can guarantee to the + // compiler that no properties will be added or removed. This enables + // the compiler to generate a very simple (fast) property access, as + // opposed to a full virtual lookup. Due to the inherent use of scope + // chains in QML, this can make a huge difference (10x improvement for + // benchmark in QTBUG-8576). + // Ideally we would not need a special object type for this, and the + // VM would dynamically optimize it to be fast... + // See also QScriptEngine benchmark. + QScriptEngine eng; static const int propertyCount = 4; QString names[] = { "foo", "bar", "baz", "Math" }; @@ -5739,6 +5951,11 @@ void tst_QScriptEngine::newFixedStaticScopeObject() void tst_QScriptEngine::newGrowingStaticScopeObject() { + // The main use case for a growing static scope object is to set it as + // the activation object of a QScriptContext, so that all JS variable + // declarations end up in that object. It needs to be "growable" since + // we don't know in advance how many variables a script will declare. + QScriptEngine eng; QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(&eng); @@ -5826,10 +6043,10 @@ void tst_QScriptEngine::newGrowingStaticScopeObject() { QScriptValue fun = eng.evaluate("(function() { return futureProperty; })"); QVERIFY(fun.isFunction()); - QCOMPARE(fun.call().toString(), QString::fromLatin1("ReferenceError: Can't find variable: futureProperty")); + QVERIFY(fun.call().toString().contains(QString::fromLatin1("ReferenceError"))); scope.setProperty("futureProperty", "added after the function was compiled"); // If scope were dynamic, this would return the new property. - QCOMPARE(fun.call().toString(), QString::fromLatin1("ReferenceError: Can't find variable: futureProperty")); + QVERIFY(fun.call().toString().contains(QString::fromLatin1("ReferenceError"))); } eng.popContext(); diff --git a/tests/auto/qscriptengineagent/tst_qscriptengineagent.cpp b/tests/auto/qscriptengineagent/tst_qscriptengineagent.cpp index dce09d3..d89f9f1 100644 --- a/tests/auto/qscriptengineagent/tst_qscriptengineagent.cpp +++ b/tests/auto/qscriptengineagent/tst_qscriptengineagent.cpp @@ -73,6 +73,7 @@ signals: void testSignal(double arg); private slots: + void unloadRecursion(); void scriptLoadAndUnload_statement(); void scriptLoadAndUnload(); void scriptLoadAndUnload_eval(); @@ -345,6 +346,46 @@ QVariant ScriptEngineSpy::extension(Extension ext, const QVariant &arg) return QVariant(); } +static void collectScriptObjects(QScriptEngine *engine) +{ + // We call garbage collection few times to collect objects that + // are unreferenced after first gc. We try to force full gc. + engine->collectGarbage(); + engine->collectGarbage(); + engine->collectGarbage(); +} + +class EvaluatingAgent : public QScriptEngineAgent { +public: + EvaluatingAgent(QScriptEngine *engine) + : QScriptEngineAgent(engine) + , count(0) + {} + + virtual void scriptUnload(qint64) + { + if (++count > 10) // recursion breaker. + return; + // check if recursive evaluation works + engine()->evaluate(";"); + collectScriptObjects(engine()); + } + + bool isOk() const { return count > 10; } +private: + int count; +}; + +void tst_QScriptEngineAgent::unloadRecursion() +{ + QScriptEngine engine; + EvaluatingAgent *agent = new EvaluatingAgent(&engine); + engine.setAgent(agent); + engine.evaluate(";"); + collectScriptObjects(&engine); + QVERIFY(agent->isOk()); +} + void tst_QScriptEngineAgent::scriptLoadAndUnload_statement() { QScriptEngine eng; @@ -358,6 +399,8 @@ void tst_QScriptEngineAgent::scriptLoadAndUnload_statement() int lineNumber = 123; eng.evaluate(code, fileName, lineNumber); + // Script object have to be garbage collected first. + collectScriptObjects(&eng); QCOMPARE(spy->count(), 2); QCOMPARE(spy->at(0).type, ScriptEngineEvent::ScriptLoad); @@ -377,6 +420,8 @@ void tst_QScriptEngineAgent::scriptLoadAndUnload_statement() int lineNumber = 456; eng.evaluate(code, fileName, lineNumber); + // Script object have to be garbage collected first. + collectScriptObjects(&eng); QCOMPARE(spy->count(), 2); QCOMPARE(spy->at(0).type, ScriptEngineEvent::ScriptLoad); @@ -414,7 +459,8 @@ void tst_QScriptEngineAgent::scriptLoadAndUnload() code = "foo = null"; eng.evaluate(code); - QCOMPARE(spy->count(), 3); + collectScriptObjects(&eng); // foo() is GC'ed + QCOMPARE(spy->count(), 4); QCOMPARE(spy->at(1).type, ScriptEngineEvent::ScriptLoad); QVERIFY(spy->at(1).scriptId != -1); @@ -425,8 +471,6 @@ void tst_QScriptEngineAgent::scriptLoadAndUnload() QCOMPARE(spy->at(2).type, ScriptEngineEvent::ScriptUnload); QCOMPARE(spy->at(2).scriptId, spy->at(1).scriptId); - eng.collectGarbage(); // foo() is GC'ed - QCOMPARE(spy->count(), 4); QCOMPARE(spy->at(3).type, ScriptEngineEvent::ScriptUnload); QCOMPARE(spy->at(3).scriptId, spy->at(0).scriptId); } @@ -448,6 +492,7 @@ void tst_QScriptEngineAgent::scriptLoadAndUnload() code = "bar = foo(); foo = null"; eng.evaluate(code); + collectScriptObjects(&eng); QCOMPARE(spy->count(), 3); QCOMPARE(spy->at(1).type, ScriptEngineEvent::ScriptLoad); @@ -458,14 +503,12 @@ void tst_QScriptEngineAgent::scriptLoadAndUnload() QCOMPARE(spy->at(2).type, ScriptEngineEvent::ScriptUnload); QCOMPARE(spy->at(2).scriptId, spy->at(1).scriptId); - eng.collectGarbage(); // foo() is not GC'ed + collectScriptObjects(&eng); // foo() is not GC'ed QCOMPARE(spy->count(), 3); code = "bar = null"; eng.evaluate(code); - QCOMPARE(spy->count(), 5); - - eng.collectGarbage(); // foo() is GC'ed + collectScriptObjects(&eng); // foo() is GC'ed QCOMPARE(spy->count(), 6); } delete spy; diff --git a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp index cb29586..1607bed 100644 --- a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp +++ b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp @@ -549,10 +549,19 @@ private slots: void getSetDynamicProperty_doNotHideJSProperty(); void getSetChildren(); void callQtInvokable(); + void callQtInvokable2(); + void callQtInvokable3(); + void callQtInvokable4(); + void callQtInvokable5(); + void callQtInvokable6(); + void callQtInvokable7(); void connectAndDisconnect(); + void connectAndDisconnect_emitFromJS(); + void connectAndDisconnect_senderWrapperCollected(); void connectAndDisconnectWithBadArgs(); void connectAndDisconnect_senderDeleted(); void cppConnectAndDisconnect(); + void cppConnectAndDisconnect2(); void classEnums(); void classConstructor(); void overrideInvokable(); @@ -1270,7 +1279,10 @@ void tst_QScriptExtQObject::callQtInvokable() QCOMPARE(m_myObject->qtFunctionActuals().size(), 2); QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 123); QCOMPARE(m_myObject->qtFunctionActuals().at(1).toInt(), 456); +} +void tst_QScriptExtQObject::callQtInvokable2() +{ m_myObject->resetQtFunctionInvoked(); QVERIFY(m_engine->evaluate("myObject.myInvokableWithVoidStarArg(null)").isUndefined()); QCOMPARE(m_myObject->qtFunctionInvoked(), 44); @@ -1359,7 +1371,10 @@ void tst_QScriptExtQObject::callQtInvokable() QCOMPARE(ret.isArray(), true); QCOMPARE(m_myObject->qtFunctionInvoked(), 11); } +} +void tst_QScriptExtQObject::callQtInvokable3() +{ { QScriptValue ret = m_engine->evaluate("myObject.myInvokableWithVectorOfIntArg(myObject.myInvokableReturningVectorOfInt())"); QCOMPARE(ret.isUndefined(), true); @@ -1485,7 +1500,10 @@ void tst_QScriptExtQObject::callQtInvokable() QCOMPARE(ret.property("0").strictlyEquals(QScriptValue(m_engine, 1)), true); QCOMPARE(ret.property("1").strictlyEquals(QScriptValue(m_engine, 5)), true); } +} +void tst_QScriptExtQObject::callQtInvokable4() +{ m_myObject->resetQtFunctionInvoked(); { QScriptValue ret = m_engine->evaluate("myObject.myInvokableWithQObjectStarArg(myObject)"); @@ -1571,7 +1589,10 @@ void tst_QScriptExtQObject::callQtInvokable() QCOMPARE(v.userType(), int(QMetaType::ULongLong)); QCOMPARE(qvariant_cast<qulonglong>(v), qulonglong(123)); } +} +void tst_QScriptExtQObject::callQtInvokable5() +{ m_myObject->resetQtFunctionInvoked(); { QScriptValue fun = m_engine->evaluate("myObject.myInvokableWithQBrushArg"); @@ -1659,7 +1680,10 @@ void tst_QScriptExtQObject::callQtInvokable() QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); QCOMPARE(qvariant_cast<QObject*>(m_myObject->qtFunctionActuals().at(0)), (QObject*)m_myObject); } +} +void tst_QScriptExtQObject::callQtInvokable6() +{ // QScriptValue arguments should be passed on without conversion m_myObject->resetQtFunctionInvoked(); { @@ -1723,18 +1747,21 @@ void tst_QScriptExtQObject::callQtInvokable() QCOMPARE(m_myObject->qtFunctionInvoked(), 55); } } +} +void tst_QScriptExtQObject::callQtInvokable7() +{ // qscript_call() { m_myObject->resetQtFunctionInvoked(); QScriptValue ret = m_engine->evaluate("new myObject(123)"); QVERIFY(ret.isError()); - QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'myObject' [MyQObject(name = \"\")] is not a constructor.")); + QVERIFY(ret.toString().contains(QString::fromLatin1("TypeError"))); } { m_myObject->resetQtFunctionInvoked(); QScriptValue ret = m_engine->evaluate("myObject(123)"); - QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'myObject' [MyQObject(name = \"\")] is not a function.")); + QVERIFY(ret.toString().contains(QString::fromLatin1("TypeError"))); } // task 233624 @@ -1971,9 +1998,10 @@ void tst_QScriptExtQObject::connectAndDisconnect() QVERIFY(m_engine->evaluate("myObject.mySignal.connect(myObject, 'mySlot')").isUndefined()); QVERIFY(m_engine->evaluate("myObject.mySignal.disconnect(yetAnotherObject, 'func')").isUndefined()); QVERIFY(m_engine->evaluate("myObject.mySignal.disconnect(myObject, 'mySlot')").isUndefined()); +} - // check that emitting signals from script works - +void tst_QScriptExtQObject::connectAndDisconnect_emitFromJS() +{ // no arguments QVERIFY(m_engine->evaluate("myObject.mySignal.connect(myObject.mySlot)").isUndefined()); m_myObject->resetQtFunctionInvoked(); @@ -2022,7 +2050,10 @@ void tst_QScriptExtQObject::connectAndDisconnect() QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 456); QVERIFY(m_engine->evaluate("myObject.mySignalWithIntArg.disconnect(myObject['myOverloadedSlot(int)'])").isUndefined()); +} +void tst_QScriptExtQObject::connectAndDisconnect_senderWrapperCollected() +{ // when the wrapper dies, the connection stays alive QVERIFY(m_engine->evaluate("myObject.mySignal.connect(myObject.mySlot)").isUndefined()); m_myObject->resetQtFunctionInvoked(); @@ -2210,7 +2241,14 @@ void tst_QScriptExtQObject::cppConnectAndDisconnect() QVERIFY(!qScriptDisconnect(&edit2, SIGNAL(textChanged(const QString &)), receiver, fun)); } } +} +void tst_QScriptExtQObject::cppConnectAndDisconnect2() +{ + QScriptEngine eng; + QLineEdit edit; + QLineEdit edit2; + QScriptValue fun = eng.evaluate("function fun(text) { signalObject = this; signalArg = text; }; fun"); // make sure we don't crash when engine is deleted { QScriptEngine *eng2 = new QScriptEngine; diff --git a/tests/auto/qset/tst_qset.cpp b/tests/auto/qset/tst_qset.cpp index ae293db..c28b683 100644 --- a/tests/auto/qset/tst_qset.cpp +++ b/tests/auto/qset/tst_qset.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +//#define QT_STRICT_ITERATORS #include <QtTest/QtTest> #include <qset.h> @@ -826,6 +827,16 @@ void tst_QSet::javaMutableIterator() int sum = 0; QMutableSetIterator<QString> i(set1); while (i.hasNext()) { + i.next(); + sum += toNumber(i.value()); + } + QVERIFY(sum == 24999 * 25000 / 2); + } + + { + int sum = 0; + QMutableSetIterator<QString> i(set1); + while (i.hasNext()) { sum += toNumber(i.peekNext()); i.next(); } diff --git a/tests/auto/qsqldatabase/tst_databases.h b/tests/auto/qsqldatabase/tst_databases.h index 5dcf754..350e0d0 100644 --- a/tests/auto/qsqldatabase/tst_databases.h +++ b/tests/auto/qsqldatabase/tst_databases.h @@ -51,6 +51,7 @@ #include <QDir> #include <QVariant> #include <QDebug> +#include <QSqlTableModel> #include <QtTest/QtTest> @@ -166,6 +167,29 @@ public: return count; } + int fillTestTableWithStrategies( const QString& driverPrefix = QString() ) const + { + QTest::addColumn<QString>( "dbName" ); + QTest::addColumn<int>("submitpolicy_i"); + int count = 0; + + for ( int i = 0; i < dbNames.count(); ++i ) { + QSqlDatabase db = QSqlDatabase::database( dbNames.at( i ) ); + + if ( !db.isValid() ) + continue; + + if ( driverPrefix.isEmpty() || db.driverName().startsWith( driverPrefix ) ) { + QTest::newRow( QString("%1 [field]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnFieldChange; + QTest::newRow( QString("%1 [row]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnRowChange; + QTest::newRow( QString("%1 [manual]").arg(dbNames.at( i )).toLatin1() ) << dbNames.at( i ) << (int)QSqlTableModel::OnManualSubmit; + ++count; + } + } + + return count; + } + void addDb( const QString& driver, const QString& dbName, const QString& user = QString(), const QString& passwd = QString(), const QString& host = QString(), int port = -1, const QString params = QString() ) diff --git a/tests/auto/qsqlquerymodel/tst_qsqlquerymodel.cpp b/tests/auto/qsqlquerymodel/tst_qsqlquerymodel.cpp index 0ca1417..e876764 100644 --- a/tests/auto/qsqlquerymodel/tst_qsqlquerymodel.cpp +++ b/tests/auto/qsqlquerymodel/tst_qsqlquerymodel.cpp @@ -318,6 +318,11 @@ void tst_QSqlQueryModel::insertColumn() model.setQuery(QSqlQuery("select * from " + qTableName("test", __FILE__), db)); model.fetchMore(); // necessary??? + bool isToUpper = db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"); + const QString idColumn(isToUpper ? "ID" : "id"); + const QString nameColumn(isToUpper ? "NAME" : "name"); + const QString titleColumn(isToUpper ? "TITLE" : "title"); + QSignalSpy spy(&model, SIGNAL(columnsInserted(QModelIndex, int, int))); QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); @@ -325,6 +330,11 @@ void tst_QSqlQueryModel::insertColumn() QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); QCOMPARE(model.data(model.index(0, 3)), QVariant()); + QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), idColumn); + QCOMPARE(model.headerData(1, Qt::Horizontal).toString(), nameColumn); + QCOMPARE(model.headerData(2, Qt::Horizontal).toString(), titleColumn); + QCOMPARE(model.headerData(3, Qt::Horizontal).toString(), QString("4")); + QVERIFY(model.insertColumn(1)); QCOMPARE(spy.count(), 1); @@ -344,6 +354,12 @@ void tst_QSqlQueryModel::insertColumn() QCOMPARE(model.data(model.index(0, 3)).toInt(), 1); QCOMPARE(model.data(model.index(0, 4)), QVariant()); + QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), idColumn); + QCOMPARE(model.headerData(1, Qt::Horizontal).toString(), QString("2")); + QCOMPARE(model.headerData(2, Qt::Horizontal).toString(), nameColumn); + QCOMPARE(model.headerData(3, Qt::Horizontal).toString(), titleColumn); + QCOMPARE(model.headerData(4, Qt::Horizontal).toString(), QString("5")); + QVERIFY(!model.insertColumn(-1)); QVERIFY(!model.insertColumn(100)); QVERIFY(!model.insertColumn(1, model.index(1, 1))); @@ -378,14 +394,21 @@ void tst_QSqlQueryModel::insertColumn() QCOMPARE(model.indexInQuery(model.index(0, 5)).column(), -1); QCOMPARE(model.indexInQuery(model.index(0, 6)).column(), -1); - bool isToUpper = db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"); QCOMPARE(model.record().field(0).name(), QString()); - QCOMPARE(model.record().field(1).name(), isToUpper ? QString("ID") : QString("id")); + QCOMPARE(model.record().field(1).name(), idColumn); QCOMPARE(model.record().field(2).name(), QString()); - QCOMPARE(model.record().field(3).name(), isToUpper ? QString("NAME") : QString("name")); - QCOMPARE(model.record().field(4).name(), isToUpper ? QString("TITLE") : QString("title")); + QCOMPARE(model.record().field(3).name(), nameColumn); + QCOMPARE(model.record().field(4).name(), titleColumn); QCOMPARE(model.record().field(5).name(), QString()); QCOMPARE(model.record().field(6).name(), QString()); + + QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), QString("1")); + QCOMPARE(model.headerData(1, Qt::Horizontal).toString(), idColumn); + QCOMPARE(model.headerData(2, Qt::Horizontal).toString(), QString("3")); + QCOMPARE(model.headerData(3, Qt::Horizontal).toString(), nameColumn); + QCOMPARE(model.headerData(4, Qt::Horizontal).toString(), titleColumn); + QCOMPARE(model.headerData(5, Qt::Horizontal).toString(), QString("6")); + QCOMPARE(model.headerData(6, Qt::Horizontal).toString(), QString("7")); } void tst_QSqlQueryModel::record() diff --git a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp index f9fcaf0..bf68375 100644 --- a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp @@ -78,11 +78,13 @@ private slots: void select_data() { generic_data(); } void select(); + void insertColumns_data() { generic_data_with_strategies(); } + void insertColumns(); void submitAll_data() { generic_data(); } void submitAll(); void setRecord_data() { generic_data(); } void setRecord(); - void insertRow_data() { generic_data(); } + void insertRow_data() { generic_data_with_strategies(); } void insertRow(); void insertRecord_data() { generic_data(); } void insertRecord(); @@ -92,8 +94,10 @@ private slots: void removeRow(); void removeRows_data() { generic_data(); } void removeRows(); - void removeInsertedRow_data() { generic_data(); } + void removeInsertedRow_data() { generic_data_with_strategies(); } void removeInsertedRow(); + void removeInsertedRows_data() { generic_data(); } + void removeInsertedRows(); void setFilter_data() { generic_data(); } void setFilter(); void setInvalidFilter_data() { generic_data(); } @@ -130,6 +134,7 @@ private slots: void insertBeforeDelete(); private: void generic_data(const QString& engine=QString()); + void generic_data_with_strategies(const QString& engine=QString()); }; tst_QSqlTableModel::tst_QSqlTableModel() @@ -227,7 +232,17 @@ void tst_QSqlTableModel::recreateTestTables() void tst_QSqlTableModel::generic_data(const QString &engine) { if ( dbs.fillTestTable(engine) == 0 ) { - if(engine.isEmpty()) + if (engine.isEmpty()) + QSKIP( "No database drivers are available in this Qt configuration", SkipAll ); + else + QSKIP( (QString("No database drivers of type %1 are available in this Qt configuration").arg(engine)).toLocal8Bit(), SkipAll ); + } +} + +void tst_QSqlTableModel::generic_data_with_strategies(const QString &engine) +{ + if ( dbs.fillTestTableWithStrategies(engine) == 0 ) { + if (engine.isEmpty()) QSKIP( "No database drivers are available in this Qt configuration", SkipAll ); else QSKIP( (QString("No database drivers of type %1 are available in this Qt configuration").arg(engine)).toLocal8Bit(), SkipAll ); @@ -289,6 +304,81 @@ void tst_QSqlTableModel::select() QCOMPARE(model.data(model.index(3, 3)), QVariant()); } +void tst_QSqlTableModel::insertColumns() +{ + // Just like the select test, with extra stuff + QFETCH(QString, dbName); + QFETCH(int, submitpolicy_i); + QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i; + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlTableModel model(0, db); + model.setTable(test); + model.setSort(0, Qt::AscendingOrder); + model.setEditStrategy(submitpolicy); + + QVERIFY_SQL(model, select()); + + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.columnCount(), 3); + + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 3)), QVariant()); + + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 3)), QVariant()); + + QCOMPARE(model.data(model.index(2, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 3)), QVariant()); + + QCOMPARE(model.data(model.index(3, 0)), QVariant()); + QCOMPARE(model.data(model.index(3, 1)), QVariant()); + QCOMPARE(model.data(model.index(3, 2)), QVariant()); + QCOMPARE(model.data(model.index(3, 3)), QVariant()); + + // Now add a column at 0 and 2 + model.insertColumn(0); + model.insertColumn(2); + + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.columnCount(), 5); + + QCOMPARE(model.data(model.index(0, 0)), QVariant()); + QCOMPARE(model.data(model.index(0, 1)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 2)), QVariant()); + QCOMPARE(model.data(model.index(0, 3)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 4)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 5)), QVariant()); + + QCOMPARE(model.data(model.index(1, 0)), QVariant()); + QCOMPARE(model.data(model.index(1, 1)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 2)), QVariant()); + QCOMPARE(model.data(model.index(1, 3)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 4)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 5)), QVariant()); + + QCOMPARE(model.data(model.index(2, 0)), QVariant()); + QCOMPARE(model.data(model.index(2, 1)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 2)), QVariant()); + QCOMPARE(model.data(model.index(2, 3)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(2, 4)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 5)), QVariant()); + + QCOMPARE(model.data(model.index(3, 0)), QVariant()); + QCOMPARE(model.data(model.index(3, 1)), QVariant()); + QCOMPARE(model.data(model.index(3, 2)), QVariant()); + QCOMPARE(model.data(model.index(3, 3)), QVariant()); + QCOMPARE(model.data(model.index(3, 4)), QVariant()); + QCOMPARE(model.data(model.index(3, 5)), QVariant()); +} + void tst_QSqlTableModel::setRecord() { QFETCH(QString, dbName); @@ -314,9 +404,14 @@ void tst_QSqlTableModel::setRecord() rec.setValue(2, rec.value(2).toString() + 'X'); QVERIFY(model.setRecord(i, rec)); - if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnManualSubmit) + if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnManualSubmit) { + // setRecord should emit dataChanged() itself for manualSubmit + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).count(), 2); + QCOMPARE(qvariant_cast<QModelIndex>(spy.at(0).at(0)), model.index(i, 0)); + QCOMPARE(qvariant_cast<QModelIndex>(spy.at(0).at(1)), model.index(i, rec.count() - 1)); QVERIFY(model.submitAll()); - else if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnRowChange && i == model.rowCount() -1) + } else if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnRowChange && i == model.rowCount() -1) model.submit(); else { // dataChanged() is not emitted when submitAll() is called @@ -339,26 +434,90 @@ void tst_QSqlTableModel::setRecord() void tst_QSqlTableModel::insertRow() { QFETCH(QString, dbName); + QFETCH(int, submitpolicy_i); + QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i; QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); QSqlTableModel model(0, db); - model.setEditStrategy(QSqlTableModel::OnRowChange); + model.setEditStrategy(submitpolicy); model.setTable(test); model.setSort(0, Qt::AscendingOrder); QVERIFY_SQL(model, select()); + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(2, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 3); + QVERIFY(model.insertRow(2)); + + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(2, 0)).toInt(), 0); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 0); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(3, 2)).toInt(), 3); + QSqlRecord rec = model.record(1); rec.setValue(0, 42); - rec.setValue(1, QString("vohi")); + rec.setValue(1, QString("francis")); + + // FieldChange updates immediately and resorts + // Row/Manual submit does not resort QVERIFY(model.setRecord(2, rec)); - QCOMPARE(model.data(model.index(2, 0)).toInt(), 42); - QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); - QCOMPARE(model.data(model.index(2, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); + + // See comment above setRecord + if (submitpolicy == QSqlTableModel::OnFieldChange) { + QCOMPARE(model.data(model.index(2, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 3); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 42); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("francis")); + QCOMPARE(model.data(model.index(3, 2)).toInt(), 2); + } else { + QCOMPARE(model.data(model.index(2, 0)).toInt(), 42); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("francis")); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(3, 2)).toInt(), 3); + } QVERIFY(model.submitAll()); + + // After the submit we should have the resorted view + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(2, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 3); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 42); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("francis")); + QCOMPARE(model.data(model.index(3, 2)).toInt(), 2); + } void tst_QSqlTableModel::insertRecord() @@ -538,10 +697,19 @@ void tst_QSqlTableModel::removeRows() QCOMPARE(model.rowCount(), 3); QSignalSpy beforeDeleteSpy(&model, SIGNAL(beforeDelete(int))); + + // Make sure wrong stuff is ok + QVERIFY(!model.removeRows(-1,1)); // negative start + QVERIFY(!model.removeRows(-1, 0)); // negative start, and zero count + QVERIFY(!model.removeRows(1, 0)); // zero count + QVERIFY(!model.removeRows(5, 1)); // past end (causes a beforeDelete to be emitted) + QVERIFY(!model.removeRows(1, 0, model.index(2, 0))); // can't pass a valid modelindex + QVERIFY_SQL(model, removeRows(0, 2)); - QVERIFY(beforeDeleteSpy.count() == 2); - QVERIFY(beforeDeleteSpy.at(0).at(0).toInt() == 0); - QVERIFY(beforeDeleteSpy.at(1).at(0).toInt() == 1); + QCOMPARE(beforeDeleteSpy.count(), 3); + QVERIFY(beforeDeleteSpy.at(0).at(0).toInt() == 5); + QVERIFY(beforeDeleteSpy.at(1).at(0).toInt() == 0); + QVERIFY(beforeDeleteSpy.at(2).at(0).toInt() == 1); QCOMPARE(model.rowCount(), 1); QCOMPARE(model.data(model.index(0, 1)).toString(), QString("vohi")); model.clear(); @@ -555,6 +723,13 @@ void tst_QSqlTableModel::removeRows() // When the edit strategy is OnManualSubmit the beforeDelete() signal // isn't emitted until submitAll() is called. + + QVERIFY(!model.removeRows(-1,1)); // negative start + QVERIFY(!model.removeRows(-1, 0)); // negative start, and zero count + QVERIFY(!model.removeRows(1, 0)); // zero count + QVERIFY(!model.removeRows(5, 1)); // past end (DOESN'T cause a beforeDelete to be emitted) + QVERIFY(!model.removeRows(1, 0, model.index(2, 0))); // can't pass a valid modelindex + qRegisterMetaType<Qt::Orientation>("Qt::Orientation"); QSignalSpy headerDataChangedSpy(&model, SIGNAL(headerDataChanged(Qt::Orientation, int, int))); QVERIFY(model.removeRows(0, 2, QModelIndex())); @@ -576,33 +751,167 @@ void tst_QSqlTableModel::removeRows() void tst_QSqlTableModel::removeInsertedRow() { QFETCH(QString, dbName); + QFETCH(int, submitpolicy_i); + QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i; QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); - for (int i = 0; i <= 1; ++i) { + QSqlTableModel model(0, db); + model.setTable(test); + model.setSort(0, Qt::AscendingOrder); - QSqlTableModel model(0, db); - model.setTable(test); - model.setSort(0, Qt::AscendingOrder); + model.setEditStrategy(submitpolicy); + QVERIFY_SQL(model, select()); + QCOMPARE(model.rowCount(), 3); - model.setEditStrategy(i == 0 - ? QSqlTableModel::OnRowChange : QSqlTableModel::OnManualSubmit); - QVERIFY_SQL(model, select()); - QCOMPARE(model.rowCount(), 3); + QVERIFY(model.insertRow(1)); + QCOMPARE(model.rowCount(), 4); - QVERIFY(model.insertRow(1)); - QCOMPARE(model.rowCount(), 4); + QVERIFY(model.removeRow(1)); + QCOMPARE(model.rowCount(), 3); - QVERIFY(model.removeRow(1)); - QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); - QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); - QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); - QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); - model.clear(); + // Now insert a row with a null, and check that removing it also works (QTBUG-15979 etc) + model.insertRow(1); + model.setData(model.index(1,0), 55); + model.setData(model.index(1,1), QString("null columns")); + model.setData(model.index(1,2), QVariant()); - recreateTestTables(); - } + model.submitAll(); + + QCOMPARE(model.rowCount(), 4); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 55); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("null columns")); + QCOMPARE(model.data(model.index(3, 2)).isNull(), true); + + QVERIFY(model.removeRow(3)); + model.submitAll(); + QCOMPARE(model.rowCount(), 3); + + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); +} + +void tst_QSqlTableModel::removeInsertedRows() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlTableModel model(0, db); + model.setTable(test); + model.setSort(0, Qt::AscendingOrder); + model.setEditStrategy(QSqlTableModel::OnManualSubmit); // you can't insert more than one row otherwise + QVERIFY_SQL(model, select()); + QCOMPARE(model.rowCount(), 3); + + // First put two empty rows, and remove them one by one + QVERIFY(model.insertRows(1, 2)); + QCOMPARE(model.rowCount(), 5); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRow(1)); + QCOMPARE(model.rowCount(), 4); + + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRow(1)); + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + + // Now put two empty rows, and remove them all at once + QVERIFY(model.insertRows(1, 2)); + QCOMPARE(model.rowCount(), 5); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRows(1, 2)); + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + + + // Now put two empty rows, and remove one good and two empty + QVERIFY(model.insertRows(1, 2)); + QCOMPARE(model.rowCount(), 5); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRows(0, 3)); + QVERIFY(model.submitAll()); // otherwise the remove of the real row doesn't work + + QCOMPARE(model.rowCount(), 2); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi")); + + // Reset back again + model.clear(); + recreateTestTables(); + model.setTable(test); + model.setSort(0, Qt::AscendingOrder); + model.setEditStrategy(QSqlTableModel::OnManualSubmit); // you can't insert more than one row otherwise + QVERIFY_SQL(model, select()); + QCOMPARE(model.rowCount(), 3); + + // Now two empty and one good + QVERIFY(model.insertRows(1, 2)); + QCOMPARE(model.rowCount(), 5); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRows(1, 3)); + QVERIFY(model.submitAll()); + QCOMPARE(model.rowCount(), 2); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi")); + + // Reset back again + model.clear(); + recreateTestTables(); + model.setTable(test); + model.setSort(0, Qt::AscendingOrder); + model.setEditStrategy(QSqlTableModel::OnManualSubmit); // you can't insert more than one row otherwise + QVERIFY_SQL(model, select()); + QCOMPARE(model.rowCount(), 3); + + // one empty, one good, one empty + QVERIFY(model.insertRows(1, 1)); + QVERIFY(model.insertRows(3, 1)); + QCOMPARE(model.rowCount(), 5); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString()); + QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi")); + + QVERIFY(model.removeRows(1, 3)); + QVERIFY(model.submitAll()); + QCOMPARE(model.rowCount(), 2); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi")); } void tst_QSqlTableModel::emptyTable() diff --git a/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp index 50002a6..83adf49 100644 --- a/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -100,6 +100,7 @@ private slots: void task188195_baseBackground(); void task232085_spinBoxLineEditBg(); void changeStyleInChangeEvent(); + void QTBUG15910_crashNullWidget(); //at the end because it mess with the style. void widgetStyle(); @@ -1657,6 +1658,23 @@ void tst_QStyleSheetStyle::QTBUG11658_cachecrash() qApp->setStyleSheet(QString()); } +void tst_QStyleSheetStyle::QTBUG15910_crashNullWidget() +{ + struct : QWidget { + virtual void paintEvent(QPaintEvent* ) { + QStyleOption opt; + opt.init(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, 0); + style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, 0); + style()->drawControl(QStyle::CE_PushButton, &opt, &p, 0); + } + } w; + w.setStyleSheet("* { background-color: white; color:black; border 3px solid yellow }"); + w.show(); + QTest::qWaitForWindowShown(&w); +} + QTEST_MAIN(tst_QStyleSheetStyle) #include "tst_qstylesheetstyle.moc" diff --git a/tests/auto/qsvgrenderer/qsvgrenderer.pro b/tests/auto/qsvgrenderer/qsvgrenderer.pro index 49337e2..fc98776 100644 --- a/tests/auto/qsvgrenderer/qsvgrenderer.pro +++ b/tests/auto/qsvgrenderer/qsvgrenderer.pro @@ -18,3 +18,6 @@ wince*|symbian { } } +!symbian: { + DEFINES += SRCDIR=\\\"$$PWD/\\\" +} diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index 5928a09..9fbf2a0 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -51,6 +51,10 @@ #include <QPicture> #include <QXmlStreamReader> +#ifndef SRCDIR +#define SRCDIR +#endif + //TESTED_CLASS= //TESTED_FILES= @@ -647,13 +651,13 @@ void tst_QSvgRenderer::gradientRefs() #ifndef QT_NO_COMPRESS void tst_QSvgRenderer::testGzLoading() { - QSvgRenderer renderer(QLatin1String("heart.svgz")); + QSvgRenderer renderer(QLatin1String(SRCDIR "heart.svgz")); QVERIFY(renderer.isValid()); QSvgRenderer resourceRenderer(QLatin1String(":/heart.svgz")); QVERIFY(resourceRenderer.isValid()); - QFile largeFileGz("large.svgz"); + QFile largeFileGz(SRCDIR "large.svgz"); largeFileGz.open(QIODevice::ReadOnly); QByteArray data = largeFileGz.readAll(); QSvgRenderer autoDetectGzData(data); diff --git a/tests/benchmarks/corelib/corelib.pro b/tests/benchmarks/corelib/corelib.pro index 335280e..a2efe91 100644 --- a/tests/benchmarks/corelib/corelib.pro +++ b/tests/benchmarks/corelib/corelib.pro @@ -11,6 +11,7 @@ TRUSTED_BENCHMARKS += \ kernel/qmetaobject \ kernel/qmetatype \ kernel/qobject \ - thread/qthreadstorage + thread/qthreadstorage \ + io/qdir/tree include(../trusted-benchmarks.pri)
\ No newline at end of file diff --git a/tests/benchmarks/declarative/qperformancetimer/qperformancetimer.pro b/tests/benchmarks/declarative/qperformancetimer/qperformancetimer.pro new file mode 100644 index 0000000..a39cd3d --- /dev/null +++ b/tests/benchmarks/declarative/qperformancetimer/qperformancetimer.pro @@ -0,0 +1,8 @@ +load(qttest_p4) +QT += declarative +TEMPLATE = app +TARGET = tst_qperformancetimer +macx:CONFIG -= app_bundle + +SOURCES += tst_qperformancetimer.cpp + diff --git a/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp b/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp new file mode 100644 index 0000000..497a556 --- /dev/null +++ b/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 <private/qperformancetimer_p.h> +#include <QObject> +#include <qtest.h> + +class tst_qperformancetimer : public QObject +{ + Q_OBJECT + +public: + tst_qperformancetimer() {} + +private slots: + void all(); + void startElapsed(); + void doubleElapsed(); + void trace(); +}; + +void tst_qperformancetimer::all() +{ + QBENCHMARK { + QPerformanceTimer t; + t.start(); + t.elapsed(); + } +} + +void tst_qperformancetimer::startElapsed() +{ + QPerformanceTimer t; + QBENCHMARK { + t.start(); + t.elapsed(); + } +} + +void tst_qperformancetimer::doubleElapsed() +{ + QPerformanceTimer t; + t.start(); + QBENCHMARK { + t.elapsed(); + t.elapsed(); + } +} + +void tst_qperformancetimer::trace() +{ + QString s("A decent sized string of text here."); + QBENCHMARK { + QByteArray data; + QDataStream ds(&data, QIODevice::WriteOnly); + ds << (qint64)100 << (int)5 << (int)5 << s; + } +} + +QTEST_MAIN(tst_qperformancetimer) + +#include "tst_qperformancetimer.moc" diff --git a/tests/benchmarks/script/context2d/context2d.pro b/tests/benchmarks/script/context2d/context2d.pro new file mode 100644 index 0000000..bc94c4f --- /dev/null +++ b/tests/benchmarks/script/context2d/context2d.pro @@ -0,0 +1,22 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_bench_context2d + +SOURCES += tst_context2d.cpp + +CONTEXT2D_EXAMPLE_DIR = $$QT_SOURCE_TREE/examples/script/context2d +INCLUDEPATH += $$CONTEXT2D_EXAMPLE_DIR + +HEADERS += $$CONTEXT2D_EXAMPLE_DIR/qcontext2dcanvas.h \ + $$CONTEXT2D_EXAMPLE_DIR/context2d.h \ + $$CONTEXT2D_EXAMPLE_DIR/domimage.h \ + $$CONTEXT2D_EXAMPLE_DIR/environment.h + +SOURCES += $$CONTEXT2D_EXAMPLE_DIR/qcontext2dcanvas.cpp \ + $$CONTEXT2D_EXAMPLE_DIR/context2d.cpp \ + $$CONTEXT2D_EXAMPLE_DIR/domimage.cpp \ + $$CONTEXT2D_EXAMPLE_DIR/environment.cpp + +RESOURCES += $$CONTEXT2D_EXAMPLE_DIR/context2d.qrc + +QT += script diff --git a/tests/benchmarks/script/context2d/tst_context2d.cpp b/tests/benchmarks/script/context2d/tst_context2d.cpp new file mode 100644 index 0000000..8401590 --- /dev/null +++ b/tests/benchmarks/script/context2d/tst_context2d.cpp @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 <QtCore/qdir.h> +#include <QtCore/qfile.h> +#include <QtCore/qtextstream.h> +#include <QtScript/qscriptengine.h> +#include <QtScript/qscriptvalue.h> +#include "context2d.h" +#include "environment.h" +#include "qcontext2dcanvas.h" + +static QString readFile(const QString &filename) +{ + QFile file(filename); + if (!file.open(QFile::ReadOnly)) + return QString(); + QTextStream stream(&file); + stream.setCodec("UTF-8"); + return stream.readAll(); +} + +class tst_Context2D : public QObject +{ + Q_OBJECT + +public: + tst_Context2D(); + ~tst_Context2D(); + +private slots: + void singleExecution_data(); + void singleExecution(); + void repeatedExecution_data(); + void repeatedExecution(); + +private: + void newEnvironment(); + +private: + QDir testsDir; + Environment *m_env; + QContext2DCanvas *m_canvas; +}; + +tst_Context2D::tst_Context2D() + : m_env(0), m_canvas(0) +{ + testsDir = QDir(":/scripts"); + if (!testsDir.exists()) + qWarning("*** no scripts/ dir!"); +} + +tst_Context2D::~tst_Context2D() +{ + delete m_canvas; + delete m_env; +} + +void tst_Context2D::newEnvironment() +{ + delete m_canvas; + delete m_env; + m_env = new Environment(); + Context2D *context = new Context2D(m_env); + context->setSize(150, 150); // Hard-coded in many of the scripts. + m_canvas = new QContext2DCanvas(context, m_env); + m_canvas->setFixedSize(context->size()); + m_canvas->setObjectName("tutorial"); // Acts as the DOM element ID. + m_env->addCanvas(m_canvas); +} + +void tst_Context2D::singleExecution_data() +{ + QTest::addColumn<QString>("testName"); + QFileInfoList testFileInfos = testsDir.entryInfoList(QStringList() << "*.js", QDir::Files); + foreach (QFileInfo tfi, testFileInfos) { + QString name = tfi.baseName(); + QTest::newRow(name.toLatin1().constData()) << name; + } +} + +void tst_Context2D::singleExecution() +{ + QFETCH(QString, testName); + QString script = readFile(testsDir.absoluteFilePath(testName + ".js")); + QVERIFY(!script.isEmpty()); + + newEnvironment(); + QBENCHMARK { + m_env->evaluate(script, testName); + // Some of the scripts (e.g. plasma.js) merely start a timer and do + // the actual drawing in the timer event. Trigger the timers now to + // ensure that the real work is done. + m_env->triggerTimers(); + } + QVERIFY(!m_env->engine()->hasUncaughtException()); +} + +void tst_Context2D::repeatedExecution_data() +{ + // We look for scripts that register an interval timer. + // Such scripts run a function every n milliseconds to update the canvas. + // The benchmark will execute this function repeatedly, which can allow + // us to observe potential effects of profiling-based JIT optimizations. + QTest::addColumn<QString>("testName"); + QTest::addColumn<QString>("script"); + QFileInfoList testFileInfos = testsDir.entryInfoList(QStringList() << "*.js", QDir::Files); + foreach (QFileInfo tfi, testFileInfos) { + QString script = readFile(tfi.absoluteFilePath()); + QString name = tfi.baseName(); + newEnvironment(); + m_env->evaluate(script, name); + if (m_env->engine()->hasUncaughtException()) + continue; + if (m_env->hasIntervalTimers()) + QTest::newRow(name.toLatin1().constData()) << name << script; + } +} + +void tst_Context2D::repeatedExecution() +{ + QFETCH(QString, testName); + QFETCH(QString, script); + + newEnvironment(); + m_env->evaluate(script, testName); + QBENCHMARK { + // Trigger the update function repeatedly, effectively + // performing several frames of animation. + for (int i = 0; i < 16; ++i) + m_env->triggerTimers(); + } + QVERIFY(!m_env->engine()->hasUncaughtException()); +} + +QTEST_MAIN(tst_Context2D) +#include "tst_context2d.moc" diff --git a/tests/benchmarks/script/qscriptclass_bytearray/qscriptclass_bytearray.pro b/tests/benchmarks/script/qscriptclass_bytearray/qscriptclass_bytearray.pro new file mode 100644 index 0000000..d64f705 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/qscriptclass_bytearray.pro @@ -0,0 +1,10 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_bench_qscriptclass_bytearray + +SOURCES += tst_qscriptclass_bytearray.cpp +RESOURCES += qscriptclass_bytearray.qrc + +include($$QT_SOURCE_TREE/examples/script/customclass/bytearrayclass.pri) + +QT = core script diff --git a/tests/benchmarks/script/qscriptclass_bytearray/qscriptclass_bytearray.qrc b/tests/benchmarks/script/qscriptclass_bytearray/qscriptclass_bytearray.qrc new file mode 100644 index 0000000..a894ee5 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/qscriptclass_bytearray.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>tests</file> +</qresource> +</RCC> diff --git a/tests/benchmarks/script/qscriptclass_bytearray/tests/construct-copy.js b/tests/benchmarks/script/qscriptclass_bytearray/tests/construct-copy.js new file mode 100644 index 0000000..9c03871 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/tests/construct-copy.js @@ -0,0 +1,3 @@ +ba = new ByteArray(123); +for (i = 0; i < 5000; ++i) + new ByteArray(ba); diff --git a/tests/benchmarks/script/qscriptclass_bytearray/tests/construct.js b/tests/benchmarks/script/qscriptclass_bytearray/tests/construct.js new file mode 100644 index 0000000..2c2bbf5 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/tests/construct.js @@ -0,0 +1,2 @@ +for (i = 0; i < 5000; ++i) + new ByteArray(123); diff --git a/tests/benchmarks/script/qscriptclass_bytearray/tests/for-in.js b/tests/benchmarks/script/qscriptclass_bytearray/tests/for-in.js new file mode 100644 index 0000000..46bc9f3 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/tests/for-in.js @@ -0,0 +1,3 @@ +ba = new ByteArray(8000); +for (var p in ba) + ; diff --git a/tests/benchmarks/script/qscriptclass_bytearray/tests/get-element.js b/tests/benchmarks/script/qscriptclass_bytearray/tests/get-element.js new file mode 100644 index 0000000..9f6a503 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/tests/get-element.js @@ -0,0 +1,3 @@ +ba = new ByteArray(123); +for (i = 0; i < 10000; ++i) + ba[10]; diff --git a/tests/benchmarks/script/qscriptclass_bytearray/tests/get-length.js b/tests/benchmarks/script/qscriptclass_bytearray/tests/get-length.js new file mode 100644 index 0000000..5de2f58 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/tests/get-length.js @@ -0,0 +1,3 @@ +ba = new ByteArray(123); +for (i = 0; i < 10000; ++i) + ba.length; diff --git a/tests/benchmarks/script/qscriptclass_bytearray/tests/mid.js b/tests/benchmarks/script/qscriptclass_bytearray/tests/mid.js new file mode 100644 index 0000000..752d875 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/tests/mid.js @@ -0,0 +1,3 @@ +ba = new ByteArray(123); +for (i = 0; i < 3000; ++i) + ba.mid(50); diff --git a/tests/benchmarks/script/qscriptclass_bytearray/tests/set-element.js b/tests/benchmarks/script/qscriptclass_bytearray/tests/set-element.js new file mode 100644 index 0000000..4883765 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/tests/set-element.js @@ -0,0 +1,3 @@ +ba = new ByteArray(123); +for (i = 0; i < 10000; ++i) + ba[10] = 123; diff --git a/tests/benchmarks/script/qscriptclass_bytearray/tests/set-length.js b/tests/benchmarks/script/qscriptclass_bytearray/tests/set-length.js new file mode 100644 index 0000000..18c9f59 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/tests/set-length.js @@ -0,0 +1,3 @@ +ba = new ByteArray(); +for (i = 0; i < 10000; ++i) + ba.length = 123; diff --git a/tests/benchmarks/script/qscriptclass_bytearray/tests/sum.js b/tests/benchmarks/script/qscriptclass_bytearray/tests/sum.js new file mode 100644 index 0000000..096937d --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/tests/sum.js @@ -0,0 +1,8 @@ +function sum(ba) { + var result = 0; + for (var i = 0; i < ba.length; ++i) + result += ba[i]; + return result; +} + +sum(new ByteArray(10000)); diff --git a/tests/benchmarks/script/qscriptclass_bytearray/tests/trimmed.js b/tests/benchmarks/script/qscriptclass_bytearray/tests/trimmed.js new file mode 100644 index 0000000..967dba6 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/tests/trimmed.js @@ -0,0 +1,3 @@ +ba = new ByteArray(123); +for (i = 0; i < 3000; ++i) + ba.trimmed(); diff --git a/tests/benchmarks/script/qscriptclass_bytearray/tst_qscriptclass_bytearray.cpp b/tests/benchmarks/script/qscriptclass_bytearray/tst_qscriptclass_bytearray.cpp new file mode 100644 index 0000000..351adc8 --- /dev/null +++ b/tests/benchmarks/script/qscriptclass_bytearray/tst_qscriptclass_bytearray.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 <QtCore/qdir.h> +#include <QtCore/qfile.h> +#include <QtCore/qtextstream.h> +#include <QtScript/qscriptengine.h> +#include <QtScript/qscriptvalue.h> +#include "bytearrayclass.h" + +static QString readFile(const QString &filename) +{ + QFile file(filename); + if (!file.open(QFile::ReadOnly)) + return QString(); + QTextStream stream(&file); + stream.setCodec("UTF-8"); + return stream.readAll(); +} + +class tst_QScriptClass_ByteArray : public QObject +{ + Q_OBJECT + +public: + tst_QScriptClass_ByteArray(); + +private slots: + void benchmark_data(); + void benchmark(); + +private: + QDir testsDir; +}; + +tst_QScriptClass_ByteArray::tst_QScriptClass_ByteArray() +{ + testsDir = QDir(":/tests"); + if (!testsDir.exists()) + qWarning("*** no tests/ dir!"); +} + +void tst_QScriptClass_ByteArray::benchmark_data() +{ + QTest::addColumn<QString>("testName"); + QFileInfoList testFileInfos = testsDir.entryInfoList(QStringList() << "*.js", QDir::Files); + foreach (QFileInfo tfi, testFileInfos) { + QString name = tfi.baseName(); + QTest::newRow(name.toLatin1().constData()) << name; + } +} + +void tst_QScriptClass_ByteArray::benchmark() +{ + QFETCH(QString, testName); + QString testContents = readFile(testsDir.absoluteFilePath(testName + ".js")); + QVERIFY(!testContents.isEmpty()); + + QScriptEngine eng; + ByteArrayClass *baClass = new ByteArrayClass(&eng); + eng.globalObject().setProperty("ByteArray", baClass->constructor()); + + QBENCHMARK { + eng.evaluate(testContents); + } + QVERIFY(!eng.hasUncaughtException()); +} + +QTEST_MAIN(tst_QScriptClass_ByteArray) +#include "tst_qscriptclass_bytearray.moc" diff --git a/tests/benchmarks/script/script.pro b/tests/benchmarks/script/script.pro index b0770ca..d4fc822 100644 --- a/tests/benchmarks/script/script.pro +++ b/tests/benchmarks/script/script.pro @@ -1,6 +1,8 @@ TEMPLATE = subdirs SUBDIRS = \ + context2d \ qscriptclass \ + qscriptclass_bytearray \ qscriptengine \ qscriptvalue \ sunspider \ @@ -13,4 +15,4 @@ TRUSTED_BENCHMARKS += \ qscriptvalue \ qscriptengine -include(../trusted-benchmarks.pri)
\ No newline at end of file +include(../trusted-benchmarks.pri) |