aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2011-09-12 08:12:58 +0200
committerGunnar Sletta <gunnar.sletta@nokia.com>2011-09-12 08:12:58 +0200
commitd77218522eb480c8d528de18049cd7b604cdeb2a (patch)
treea6433a8e9205a95006eae10b53285a0e3487423d /tests
parent589c8445e2623ef8e0b8294d7c558a2948b2a5e3 (diff)
parentd5686fa2ac2248d5a31237573fa08697f18f035f (diff)
Merge branch 'master' into refactor
Conflicts: examples/declarative/cppextensions/qwidgets/qwidgets.pro examples/declarative/minehunt/main.cpp examples/declarative/minehunt/minehunt.pro src/declarative/items/context2d/qsgcontext2d.cpp src/declarative/items/qsgflickable.cpp src/declarative/items/qsgtextedit.cpp src/declarative/items/qsgtextinput.cpp src/declarative/particles/qsgangleddirection.cpp src/declarative/particles/qsgcumulativedirection.cpp src/declarative/particles/qsgcumulativedirection_p.h src/declarative/particles/qsgfollowemitter.cpp src/declarative/particles/qsgmodelparticle.cpp src/declarative/particles/qsgparticlesystem.cpp src/qtquick1/util/qdeclarativeview.h tests/auto/declarative/examples/examples.pro tests/auto/declarative/qsgfocusscope/tst_qsgfocusscope.cpp Change-Id: Ib4be2a5e742dee1a399d73da97161736f77448e5
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/declarative/declarative.pro3
-rw-r--r--tests/auto/declarative/examples/examples.pro17
-rw-r--r--tests/auto/declarative/examples/tst_examples.cpp49
-rw-r--r--tests/auto/declarative/qdeclarativeanimations/data/pathAnimation.qml27
-rw-r--r--tests/auto/declarative/qdeclarativeanimations/data/pathInterpolator.qml13
-rw-r--r--tests/auto/declarative/qdeclarativeanimations/data/pathTransition.qml41
-rw-r--r--tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp81
-rw-r--r--tests/auto/declarative/qdeclarativeconnection/data/moduleapi-target.qml22
-rw-r--r--tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp64
-rw-r--r--tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp7
-rw-r--r--tests/auto/declarative/qdeclarativedebugjs/data/test.js53
-rw-r--r--tests/auto/declarative/qdeclarativedebugjs/data/test.qml86
-rw-r--r--tests/auto/declarative/qdeclarativedebugjs/qdeclarativedebugjs.pro25
-rw-r--r--tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp1712
-rw-r--r--tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp5
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.handle.1.qml25
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.handle.2.qml26
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.object.1.qml31
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.object.2.qml32
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/signalHandlers.qml60
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp3
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/testtypes.h105
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp284
-rw-r--r--tests/auto/declarative/qdeclarativeenginedebug/qdeclarativeenginedebug.pro (renamed from tests/auto/declarative/qdeclarativedebug/qdeclarativedebug.pro)2
-rw-r--r--tests/auto/declarative/qdeclarativeenginedebug/tst_qdeclarativeenginedebug.cpp (renamed from tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp)70
-rw-r--r--tests/auto/declarative/qdeclarativepath/data/arc.qml11
-rw-r--r--tests/auto/declarative/qdeclarativepath/data/curve.qml9
-rw-r--r--tests/auto/declarative/qdeclarativepath/data/svg.qml5
-rw-r--r--tests/auto/declarative/qdeclarativepath/qdeclarativepath.pro17
-rw-r--r--tests/auto/declarative/qdeclarativepath/tst_qdeclarativepath.cpp169
-rw-r--r--tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp18
-rw-r--r--tests/auto/declarative/qdeclarativestates/data/avoidFastForward.qml17
-rw-r--r--tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp15
-rw-r--r--tests/auto/declarative/qsgfocusscope/tst_qsgfocusscope.cpp40
-rw-r--r--tests/auto/declarative/qsggridview/data/header.qml4
-rw-r--r--tests/auto/declarative/qsggridview/tst_qsggridview.cpp370
-rw-r--r--tests/auto/declarative/qsglistview/data/header.qml4
-rw-r--r--tests/auto/declarative/qsglistview/tst_qsglistview.cpp411
-rw-r--r--tests/auto/declarative/qsgtextedit/data/horizontalAlignment_RightToLeft.qml1
-rw-r--r--tests/auto/declarative/qsgtextedit/data/mouseselection_false_words.qml3
-rw-r--r--tests/auto/declarative/qsgtextedit/data/mouseselection_true_words.qml3
-rw-r--r--tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp100
-rw-r--r--tests/auto/declarative/qsgtextinput/data/horizontalAlignment_RightToLeft.qml1
-rw-r--r--tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp71
-rw-r--r--tests/auto/qmltest/tst_qmltest.cpp2
-rw-r--r--tests/auto/qtquick1/examples/data/dummytest.qml6
-rw-r--r--tests/auto/qtquick1/examples/data/webbrowser/webbrowser.qml6
-rw-r--r--tests/auto/qtquick1/examples/examples.pro14
-rw-r--r--tests/auto/qtquick1/examples/tst_examples.cpp212
-rw-r--r--tests/auto/qtquick1/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml1
-rw-r--r--tests/auto/qtquick1/qdeclarativetextedit/data/mouseselection_false_words.qml5
-rw-r--r--tests/auto/qtquick1/qdeclarativetextedit/data/mouseselection_true_words.qml5
-rw-r--r--tests/auto/qtquick1/qdeclarativetextedit/tst_qdeclarativetextedit.cpp82
-rw-r--r--tests/auto/qtquick1/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml1
-rw-r--r--tests/auto/qtquick1/qdeclarativetextinput/tst_qdeclarativetextinput.cpp74
-rw-r--r--tests/auto/qtquick1/qtquick1.pro1
-rw-r--r--tests/benchmarks/declarative/js/qjsengine/tst_qjsengine.cpp34
-rw-r--r--tests/benchmarks/declarative/js/qjsvalue/tst_qjsvalue.cpp34
-rw-r--r--tests/benchmarks/declarative/js/qjsvalueiterator/tst_qjsvalueiterator.cpp34
59 files changed, 4306 insertions, 317 deletions
diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro
index 8563dc6fe6..fa075459b5 100644
--- a/tests/auto/declarative/declarative.pro
+++ b/tests/auto/declarative/declarative.pro
@@ -31,9 +31,10 @@ PRIVATETESTS += \
qdeclarativebehaviors \
qdeclarativebinding \
qdeclarativeconnection \
- qdeclarativedebug \
+ qdeclarativeenginedebug \
qdeclarativedebugclient \
qdeclarativedebugservice \
+ qdeclarativedebugjs \
qdeclarativeecmascript \
qdeclarativeimageprovider \
qdeclarativeinstruction \
diff --git a/tests/auto/declarative/examples/examples.pro b/tests/auto/declarative/examples/examples.pro
index 75adbb53ba..b1e120094d 100644
--- a/tests/auto/declarative/examples/examples.pro
+++ b/tests/auto/declarative/examples/examples.pro
@@ -1,20 +1,9 @@
load(qttest_p4)
-contains(QT_CONFIG,declarative): QT += declarative qtquick1
+contains(QT_CONFIG,declarative): QT += declarative
macx:CONFIG -= app_bundle
-SOURCES += tst_examples.cpp
-
-include(../../../../tools/qmlviewer/qml.pri)
-
-include(../symbianlibs.pri)
-
-symbian: {
- importFiles.files = data
- importFiles.path = .
- DEPLOYMENT += importFiles
-} else {
- DEFINES += SRCDIR=\\\"$$PWD\\\"
-}
+SOURCES += tst_examples.cpp
+DEFINES += SRCDIR=\\\"$$PWD\\\"
CONFIG += parallel_test
diff --git a/tests/auto/declarative/examples/tst_examples.cpp b/tests/auto/declarative/examples/tst_examples.cpp
index e2edc3e93c..563aa3ce84 100644
--- a/tests/auto/declarative/examples/tst_examples.cpp
+++ b/tests/auto/declarative/examples/tst_examples.cpp
@@ -38,21 +38,15 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
#include <qtest.h>
#include <QLibraryInfo>
#include <QDir>
#include <QProcess>
#include <QDebug>
-#include "qmlruntime.h"
-#include <QDeclarativeView>
#include <QSGView>
#include <QDeclarativeError>
-#ifdef Q_OS_SYMBIAN
-// In Symbian OS test data is located in applications private dir
-#define SRCDIR "."
-#endif
-
class tst_examples : public QObject
{
Q_OBJECT
@@ -60,8 +54,6 @@ public:
tst_examples();
private slots:
- void examples_data();
- void examples();
void sgexamples_data();
void sgexamples();
@@ -77,6 +69,9 @@ tst_examples::tst_examples()
{
// Add directories you want excluded here
+ // Not run in QSGView
+ excludedDirs << "examples/declarative/qtquick1";
+
// These snippets are not expected to run on their own.
excludedDirs << "doc/src/snippets/declarative/visualdatamodel_rootindex";
excludedDirs << "doc/src/snippets/declarative/qtbinding";
@@ -185,7 +180,12 @@ that they start and exit cleanly.
Examples are any .qml files under the examples/ directory that start
with a lower case letter.
*/
-void tst_examples::examples_data()
+static void silentErrorsMsgHandler(QtMsgType, const char *)
+{
+}
+
+
+void tst_examples::sgexamples_data()
{
QTest::addColumn<QString>("file");
@@ -200,37 +200,8 @@ void tst_examples::examples_data()
QTest::newRow(qPrintable(file)) << file;
}
-static void silentErrorsMsgHandler(QtMsgType, const char *)
-{
-}
-
-void tst_examples::examples()
-{
- QFETCH(QString, file);
-
- QDeclarativeViewer viewer;
-
- QtMsgHandler old = qInstallMsgHandler(silentErrorsMsgHandler);
- QVERIFY(viewer.open(file));
- qInstallMsgHandler(old);
-
- if (viewer.view()->status() == QDeclarativeView::Error)
- qWarning() << viewer.view()->errors();
-
- QCOMPARE(viewer.view()->status(), QDeclarativeView::Ready);
- viewer.show();
-
- QTest::qWaitForWindowShown(&viewer);
-}
-
-void tst_examples::sgexamples_data()
-{
- examples_data();
-}
-
void tst_examples::sgexamples()
{
- qputenv("QMLSCENE_IMPORT_NAME", "quick1");
QFETCH(QString, file);
QSGView view;
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/pathAnimation.qml b/tests/auto/declarative/qdeclarativeanimations/data/pathAnimation.qml
new file mode 100644
index 0000000000..d2006a1c6a
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeanimations/data/pathAnimation.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 400
+ height: 400
+
+ Rectangle {
+ id: redRect
+ color: "red"
+ width: 100; height: 100
+ x: 50; y: 50
+ }
+
+ PathAnimation {
+ target: redRect
+ duration: 100;
+ path: Path {
+ startX: 50; startY: 50
+ PathCubic {
+ x: 300; y: 300
+
+ control1X: 300; control1Y: 50
+ control2X: 50; control2Y: 300
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/pathInterpolator.qml b/tests/auto/declarative/qdeclarativeanimations/data/pathInterpolator.qml
new file mode 100644
index 0000000000..0104412d7c
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeanimations/data/pathInterpolator.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+PathInterpolator {
+ path: Path {
+ startX: 50; startY: 50
+ PathCubic {
+ x: 300; y: 300
+
+ control1X: 300; control1Y: 50
+ control2X: 50; control2Y: 300
+ }
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeanimations/data/pathTransition.qml b/tests/auto/declarative/qdeclarativeanimations/data/pathTransition.qml
new file mode 100644
index 0000000000..55ffc33f95
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeanimations/data/pathTransition.qml
@@ -0,0 +1,41 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 800
+ height: 800
+
+ Rectangle {
+ id: redRect; objectName: "redRect"
+ color: "red"
+ width: 50; height: 50
+ x: 500; y: 50
+ }
+
+ states: State {
+ name: "moved"
+ PropertyChanges {
+ target: redRect
+ x: 100; y: 700
+ }
+ }
+
+ transitions: Transition {
+ to: "moved"; reversible: true
+ PathAnimation {
+ id: pathAnim
+ target: redRect
+ duration: 300
+ path: Path {
+ PathCurve { x: 100; y: 100 }
+ PathCurve { x: 200; y: 350 }
+ PathCurve { x: 600; y: 500 }
+ PathCurve {}
+ }
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: parent.state = parent.state == "moved" ? "" : "moved"
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp
index 367de014b4..df840e9d5c 100644
--- a/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp
+++ b/tests/auto/declarative/qdeclarativeanimations/tst_qdeclarativeanimations.cpp
@@ -44,6 +44,8 @@
#include <QtDeclarative/qsgview.h>
#include <QtDeclarative/private/qsgrectangle_p.h>
#include <QtDeclarative/private/qdeclarativeanimation_p.h>
+#include <QtDeclarative/private/qsganimation_p.h>
+#include <QtDeclarative/private/qdeclarativepathinterpolator_p.h>
#include <QtDeclarative/private/qsgitem_p.h>
#include <QVariantAnimation>
#include <QEasingCurve>
@@ -68,6 +70,8 @@ private slots:
void simpleNumber();
void simpleColor();
void simpleRotation();
+ void simplePath();
+ void pathInterpolator();
void alwaysRunToEnd();
void complete();
void resume();
@@ -77,6 +81,7 @@ private slots:
void mixedTypes();
void properties();
void propertiesTransition();
+ void pathTransition();
void disabledTransition();
void invalidDuration();
void attached();
@@ -213,6 +218,62 @@ void tst_qdeclarativeanimations::simpleRotation()
QCOMPARE(rect.rotation(), qreal(135));
}
+void tst_qdeclarativeanimations::simplePath()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathAnimation.qml"));
+ QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QSGRectangle *redRect = rect->findChild<QSGRectangle*>();
+ QVERIFY(redRect);
+ QSGPathAnimation *pathAnim = rect->findChild<QSGPathAnimation*>();
+ QVERIFY(pathAnim);
+
+ pathAnim->start();
+ pathAnim->pause();
+
+ pathAnim->setCurrentTime(50);
+ QCOMPARE(redRect->x(), qreal(175));
+ QCOMPARE(redRect->y(), qreal(175));
+
+ pathAnim->setCurrentTime(100);
+ QCOMPARE(redRect->x(), qreal(300));
+ QCOMPARE(redRect->y(), qreal(300));
+
+ //verify animation runs to end
+ pathAnim->start();
+ QCOMPARE(redRect->x(), qreal(50));
+ QCOMPARE(redRect->y(), qreal(50));
+ QTRY_COMPARE(redRect->x(), qreal(300));
+ QCOMPARE(redRect->y(), qreal(300));
+}
+
+void tst_qdeclarativeanimations::pathInterpolator()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathInterpolator.qml"));
+ QDeclarativePathInterpolator *interpolator = qobject_cast<QDeclarativePathInterpolator*>(c.create());
+ QVERIFY(interpolator);
+
+ QCOMPARE(interpolator->progress(), qreal(0));
+ QCOMPARE(interpolator->x(), qreal(50));
+ QCOMPARE(interpolator->y(), qreal(50));
+ QCOMPARE(interpolator->angle(), qreal(0));
+
+ interpolator->setProgress(.5);
+ QCOMPARE(interpolator->progress(), qreal(.5));
+ QCOMPARE(interpolator->x(), qreal(175));
+ QCOMPARE(interpolator->y(), qreal(175));
+ QCOMPARE(interpolator->angle(), qreal(270));
+
+ interpolator->setProgress(1);
+ QCOMPARE(interpolator->progress(), qreal(1));
+ QCOMPARE(interpolator->x(), qreal(300));
+ QCOMPARE(interpolator->y(), qreal(300));
+ QCOMPARE(interpolator->angle(), qreal(0));
+}
+
void tst_qdeclarativeanimations::alwaysRunToEnd()
{
QSGRectangle rect;
@@ -577,6 +638,26 @@ void tst_qdeclarativeanimations::propertiesTransition()
}
+void tst_qdeclarativeanimations::pathTransition()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathTransition.qml"));
+ QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
+ QVERIFY(rect);
+
+ QSGRectangle *myRect = rect->findChild<QSGRectangle*>("redRect");
+ QVERIFY(myRect);
+
+ QSGItemPrivate::get(rect)->setState("moved");
+ QTRY_VERIFY(myRect->x() < 500 && myRect->x() > 100 && myRect->y() > 50 && myRect->y() < 700 ); //animation started
+ QTRY_VERIFY(qFuzzyCompare(myRect->x(), qreal(100)) && qFuzzyCompare(myRect->y(), qreal(700)));
+ QTest::qWait(100);
+
+ QSGItemPrivate::get(rect)->setState("");
+ QTRY_VERIFY(myRect->x() < 500 && myRect->x() > 100 && myRect->y() > 50 && myRect->y() < 700 ); //animation started
+ QTRY_VERIFY(qFuzzyCompare(myRect->x(), qreal(500)) && qFuzzyCompare(myRect->y(), qreal(50)));
+}
+
void tst_qdeclarativeanimations::disabledTransition()
{
QDeclarativeEngine engine;
diff --git a/tests/auto/declarative/qdeclarativeconnection/data/moduleapi-target.qml b/tests/auto/declarative/qdeclarativeconnection/data/moduleapi-target.qml
new file mode 100644
index 0000000000..8803f24542
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeconnection/data/moduleapi-target.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.0
+import MyTestModuleApi 1.0 as MyTestModuleApi
+
+Item {
+ id: rootObject
+ objectName: "rootObject"
+ property int newIntPropValue: 12
+
+ property int moduleIntPropChangedCount: 0
+ property int moduleOtherSignalCount: 0
+
+ function setModuleIntProp() {
+ MyTestModuleApi.intProp = newIntPropValue;
+ newIntPropValue = newIntPropValue + 1;
+ }
+
+ Connections {
+ target: MyTestModuleApi
+ onIntPropChanged: moduleIntPropChangedCount = moduleIntPropChangedCount + 1;
+ onOtherSignal: moduleOtherSignalCount = moduleOtherSignalCount + 1;
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp b/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp
index 37cce5c578..c726fde0e8 100644
--- a/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp
+++ b/tests/auto/declarative/qdeclarativeconnection/tst_qdeclarativeconnection.cpp
@@ -68,6 +68,7 @@ private slots:
void unknownSignals();
void errors_data();
void errors();
+ void moduleApiTarget();
private:
QDeclarativeEngine engine;
@@ -229,6 +230,69 @@ void tst_qdeclarativeconnection::errors()
QCOMPARE(errors.at(0).description(), error);
}
+
+class MyTestModuleApi : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(int intProp READ intProp WRITE setIntProp NOTIFY intPropChanged)
+
+public:
+ MyTestModuleApi(QObject *parent = 0) : QObject(parent), m_intProp(0), m_changeCount(0) {}
+ ~MyTestModuleApi() {}
+
+ Q_INVOKABLE int otherMethod(int val) { return val + 4; }
+
+ int intProp() const { return m_intProp; }
+ void setIntProp(int val)
+ {
+ if (++m_changeCount % 3 == 0) emit otherSignal();
+ m_intProp = val; emit intPropChanged();
+ }
+
+signals:
+ void intPropChanged();
+ void otherSignal();
+
+private:
+ int m_intProp;
+ int m_changeCount;
+};
+
+static QObject *module_api_factory(QDeclarativeEngine *engine, QJSEngine *scriptEngine)
+{
+ Q_UNUSED(engine)
+ Q_UNUSED(scriptEngine)
+ MyTestModuleApi *api = new MyTestModuleApi();
+ return api;
+}
+
+// QTBUG-20937
+void tst_qdeclarativeconnection::moduleApiTarget()
+{
+ qmlRegisterModuleApi("MyTestModuleApi", 1, 0, module_api_factory);
+ QDeclarativeComponent component(&engine, QUrl(SRCDIR "/data/moduleapi-target.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 0);
+ QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0);
+
+ QMetaObject::invokeMethod(object, "setModuleIntProp");
+ QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 1);
+ QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0);
+
+ QMetaObject::invokeMethod(object, "setModuleIntProp");
+ QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 2);
+ QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0);
+
+ // the module API emits otherSignal every 3 times the int property changes.
+ QMetaObject::invokeMethod(object, "setModuleIntProp");
+ QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 3);
+ QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 1);
+
+ delete object;
+}
+
QTEST_MAIN(tst_qdeclarativeconnection)
#include "tst_qdeclarativeconnection.moc"
diff --git a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp
index d7f53c9620..41486877d6 100644
--- a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp
+++ b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp
@@ -47,10 +47,6 @@
#include <QtDeclarative/qdeclarativeengine.h>
-#include <private/qdeclarativedebug_p.h>
-#include <private/qdeclarativeenginedebug_p.h>
-#include <private/qdeclarativedebugservice_p.h>
-
#include "../../../shared/util.h"
#include "../shared/debugutil_p.h"
@@ -144,7 +140,8 @@ 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:13770";
+ char arg[] = "-qmljsdebugger=port:13770";
+ _argv[_argc - 1] = arg;
QApplication app(_argc, _argv);
tst_QDeclarativeDebugClient tc;
diff --git a/tests/auto/declarative/qdeclarativedebugjs/data/test.js b/tests/auto/declarative/qdeclarativedebugjs/data/test.js
new file mode 100644
index 0000000000..230a4ea7de
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativedebugjs/data/test.js
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+function printMessage(msg)
+{
+ print(msg);
+}
+
+function add(a,b)
+{
+ //This is a comment and below is an empty line
+
+ var out = a + b;
+ return out;
+}
diff --git a/tests/auto/declarative/qdeclarativedebugjs/data/test.qml b/tests/auto/declarative/qdeclarativedebugjs/data/test.qml
new file mode 100644
index 0000000000..386b366cab
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativedebugjs/data/test.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import "test.js" as Script
+
+//DO NOT CHANGE
+
+Rectangle {
+ id: root
+ width: 10; height: 10;
+ Component.onCompleted: print("onCompleted")
+
+ property int result:0
+
+ property int someValue: 10
+
+ function doSomething() {
+ var a = root.result;
+ var b = commonFunction();
+ var c = [1,2,3];
+ var d = Script.add(a,c[2]);
+ result += d;
+ doSomethingElse();
+ }
+
+ Timer {
+ interval: 4000; running: true; repeat: true
+ onTriggered: {
+ doSomething();
+ Script.printMessage("onTriggered");
+ }
+ }
+
+ function commonFunction() {
+ console.log("commonFunction");
+ return 5;
+ }
+
+ function doSomethingElse() {
+ result = Script.add(result,8);
+ eval("print(root.result)");
+ if (root.result > 15)
+ dummy();
+ }
+
+}
+
diff --git a/tests/auto/declarative/qdeclarativedebugjs/qdeclarativedebugjs.pro b/tests/auto/declarative/qdeclarativedebugjs/qdeclarativedebugjs.pro
new file mode 100644
index 0000000000..883f94111a
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativedebugjs/qdeclarativedebugjs.pro
@@ -0,0 +1,25 @@
+load(qttest_p4)
+QT += declarative network script declarative-private
+macx:CONFIG -= app_bundle
+
+HEADERS += ../shared/debugutil_p.h
+
+SOURCES += tst_qdeclarativedebugjs.cpp \
+ ../shared/debugutil.cpp
+
+INCLUDEPATH += ../shared
+
+# QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage
+# LIBS += -lgcov
+
+symbian {
+ importFiles.files = data
+ importFiles.path = .
+ DEPLOYMENT += importFiles
+}
+
+OTHER_FILES = data/test.qml \
+ data/test.js
+
+
+CONFIG += parallel_test
diff --git a/tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp b/tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp
new file mode 100644
index 0000000000..d76fa749a2
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativedebugjs/tst_qdeclarativedebugjs.cpp
@@ -0,0 +1,1712 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QtCore/QProcess>
+#include <QtCore/QTimer>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QMutex>
+#include <QtCore/QLibraryInfo>
+#include <QtDeclarative/private/qdeclarativedebugclient_p.h>
+#include <QtDeclarative/QJSEngine>
+
+//QDeclarativeDebugTest
+#include "../../../shared/util.h"
+#include "../shared/debugutil_p.h"
+
+const char *SEQ = "seq";
+const char *TYPE = "type";
+const char *COMMAND = "command";
+const char *ARGUMENTS = "arguments";
+const char *STEPACTION = "stepaction";
+const char *STEPCOUNT = "stepcount";
+const char *EXPRESSION = "expression";
+const char *FRAME = "frame";
+const char *GLOBAL = "global";
+const char *DISABLEBREAK = "disable_break";
+const char *HANDLES = "handles";
+const char *INCLUDESOURCE = "includeSource";
+const char *FROMFRAME = "fromFrame";
+const char *TOFRAME = "toFrame";
+const char *BOTTOM = "bottom";
+const char *NUMBER = "number";
+const char *FRAMENUMBER = "frameNumber";
+const char *TYPES = "types";
+const char *IDS = "ids";
+const char *FILTER = "filter";
+const char *FROMLINE = "fromLine";
+const char *TOLINE = "toLine";
+const char *TARGET = "target";
+const char *LINE = "line";
+const char *COLUMN = "column";
+const char *ENABLED = "enabled";
+const char *CONDITION = "condition";
+const char *IGNORECOUNT = "ignoreCount";
+const char *BREAKPOINT = "breakpoint";
+const char *FLAGS = "flags";
+
+const char *CONTINEDEBUGGING = "continue";
+const char *EVALUATE = "evaluate";
+const char *LOOKUP = "lookup";
+const char *BACKTRACE = "backtrace";
+const char *SCOPE = "scope";
+const char *SCOPES = "scopes";
+const char *SCRIPTS = "scripts";
+const char *SOURCE = "source";
+const char *SETBREAKPOINT = "setbreakpoint";
+const char *CHANGEBREAKPOINT = "changebreakpoint";
+const char *CLEARBREAKPOINT = "clearbreakpoint";
+const char *SETEXCEPTIONBREAK = "setexceptionbreak";
+const char *V8FLAGS = "v8flags";
+const char *VERSION = "version";
+const char *DISCONNECT = "disconnect";
+const char *LISTBREAKPOINTS = "listbreakpoints";
+const char *GARBAGECOLLECTOR = "gc";
+//const char *PROFILE = "profile";
+
+const char *CONNECT = "connect";
+const char *INTERRUPT = "interrupt";
+
+const char *REQUEST = "request";
+const char *IN = "in";
+const char *NEXT = "next";
+const char *OUT = "out";
+
+const char *FUNCTION = "function";
+const char *SCRIPT = "script";
+
+const char *ALL = "all";
+const char *UNCAUGHT = "uncaught";
+
+//const char *PAUSE = "pause";
+//const char *RESUME = "resume";
+
+const char *BLOCKMODE = "-qmljsdebugger=port:3771,block";
+const char *NORMALMODE = "-qmljsdebugger=port:3771";
+const char *QMLFILE = "test.qml";
+const char *JSFILE = "test.js";
+
+#define VARIANTMAPINIT \
+ QString obj("{}"); \
+ QJSValue jsonVal = parser.call(QJSValue(), QJSValueList() << obj); \
+ jsonVal.setProperty(SEQ,QJSValue(seq++)); \
+ jsonVal.setProperty(TYPE,REQUEST);
+
+inline QString TEST_FILE(const QString &filename)
+{
+ QFileInfo fileInfo(__FILE__);
+ return fileInfo.absoluteDir().filePath("data/" + filename);
+}
+
+class QJSDebugProcess;
+class QJSDebugClient;
+
+class tst_QDeclarativeDebugJS : public QObject
+{
+ Q_OBJECT
+
+private slots:
+
+ void initTestCase();
+ void cleanupTestCase();
+
+ void init();
+ void cleanup();
+
+ void getVersion();
+
+ void applyV8Flags();
+
+ void disconnect();
+
+ void gc();
+
+ void listBreakpoints();
+
+ void setBreakpointInScriptOnCompleted();
+ void setBreakpointInScriptOnTimerCallback();
+ void setBreakpointInScriptInDifferentFile();
+ void setBreakpointInScriptOnComment();
+ void setBreakpointInScriptOnEmptyLine();
+ void setBreakpointInScriptWithCondition();
+ //void setBreakpointInFunction(); //NOT SUPPORTED
+
+ void changeBreakpoint();
+ void changeBreakpointOnCondition();
+
+ void clearBreakpoint();
+
+ void setExceptionBreak();
+
+ void stepNext();
+ void stepNextWithCount();
+ void stepIn();
+ void stepOut();
+ void continueDebugging();
+
+ void backtrace();
+
+ void getFrameDetails();
+
+ void getScopeDetails();
+
+ void evaluateInGlobalScope();
+ void evaluateInLocalScope();
+
+ void getScopes();
+
+ void getScripts();
+
+ void getSource();
+
+ // void profile(); //NOT SUPPORTED
+
+ // void verifyQMLOptimizerDisabled();
+
+private:
+ QJSDebugProcess *process;
+ QJSDebugClient *client;
+ QDeclarativeDebugConnection *connection;
+};
+
+class QJSDebugProcess : public QObject
+{
+ Q_OBJECT
+public:
+ QJSDebugProcess();
+ ~QJSDebugProcess();
+
+ void start(const QStringList &arguments);
+ bool waitForSessionStart();
+
+private slots:
+ void processAppOutput();
+
+private:
+ void stop();
+
+private:
+ QProcess m_process;
+ QTimer m_timer;
+ QEventLoop m_eventLoop;
+ QMutex m_mutex;
+ bool m_started;
+};
+
+QJSDebugProcess::QJSDebugProcess()
+ : m_started(false)
+{
+ m_process.setProcessChannelMode(QProcess::MergedChannels);
+ m_timer.setSingleShot(true);
+ m_timer.setInterval(5000);
+ connect(&m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processAppOutput()));
+ connect(&m_timer, SIGNAL(timeout()), &m_eventLoop, SLOT(quit()));
+
+// QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+// env.insert("QML_DISABLE_OPTIMIZER", "1"); // Add an environment variable
+// m_process.setProcessEnvironment(env);
+
+}
+
+QJSDebugProcess::~QJSDebugProcess()
+{
+ stop();
+}
+
+void QJSDebugProcess::start(const QStringList &arguments)
+{
+ m_mutex.lock();
+ m_process.start(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", arguments);
+ m_process.waitForStarted();
+ m_timer.start();
+ m_mutex.unlock();
+}
+
+void QJSDebugProcess::stop()
+{
+ if (m_process.state() != QProcess::NotRunning) {
+ m_process.terminate();
+ m_process.waitForFinished(5000);
+ }
+}
+
+bool QJSDebugProcess::waitForSessionStart()
+{
+ m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
+
+ return m_started;
+}
+
+void QJSDebugProcess::processAppOutput()
+{
+ m_mutex.lock();
+ const QString appOutput = m_process.readAll();
+ static QRegExp newline("[\n\r]{1,2}");
+ QStringList lines = appOutput.split(newline);
+ foreach (const QString &line, lines) {
+ if (line.isEmpty())
+ continue;
+ if (line.startsWith("Qml debugging is enabled")) // ignore
+ continue;
+ if (line.startsWith("QDeclarativeDebugServer:")) {
+ if (line.contains("Waiting for connection ")) {
+ m_started = true;
+ m_eventLoop.quit();
+ continue;
+ }
+ if (line.contains("Connection established")) {
+ continue;
+ }
+ }
+ }
+ m_mutex.unlock();
+}
+
+class QJSDebugClient : public QDeclarativeDebugClient
+{
+ Q_OBJECT
+public:
+ enum StepAction
+ {
+ Continue,
+ In,
+ Out,
+ Next
+ };
+
+ enum Exception
+ {
+ All,
+ Uncaught
+ };
+
+// enum ProfileCommand
+// {
+// Pause,
+// Resume
+// };
+
+ QJSDebugClient(QDeclarativeDebugConnection *connection)
+ : QDeclarativeDebugClient(QLatin1String("V8Debugger"), connection),
+ seq(0)
+ {
+ parser = jsEngine.evaluate(QLatin1String("JSON.parse"));
+ stringify = jsEngine.evaluate(QLatin1String("JSON.stringify"));
+ }
+
+ void startDebugging();
+ void interrupt();
+
+ void continueDebugging(StepAction stepAction, int stepCount = 1);
+ void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
+ void lookup(QList<int> handles, bool includeSource = false);
+ void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
+ void frame(int number = -1);
+ void scope(int number = -1, int frameNumber = -1);
+ void scopes(int frameNumber = -1);
+ void scripts(int types = 4, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
+ void source(int frame = -1, int fromLine = -1, int toLine = -1);
+ void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = true, QString condition = QString(), int ignoreCount = -1);
+ void changeBreakpoint(int breakpoint, bool enabled = true, QString condition = QString(), int ignoreCount = -1);
+ void clearBreakpoint(int breakpoint);
+ void setExceptionBreak(Exception type, bool enabled = false);
+ void v8flags(QString flags);
+ void version();
+ //void profile(ProfileCommand command); //NOT SUPPORTED
+ void disconnect();
+ void gc();
+ void listBreakpoints();
+
+protected:
+ //inherited from QDeclarativeDebugClient
+ void statusChanged(Status status);
+ void messageReceived(const QByteArray &data);
+
+signals:
+ void enabled();
+ void breakpointSet();
+ void result();
+ void stopped();
+
+private:
+ void sendMessage(const QByteArray &);
+ void flushSendBuffer();
+ QByteArray packMessage(QByteArray message);
+
+private:
+ QJSEngine jsEngine;
+ int seq;
+
+ QList<QByteArray> sendBuffer;
+
+public:
+ QJSValue parser;
+ QJSValue stringify;
+ QByteArray response;
+
+};
+
+void QJSDebugClient::startDebugging()
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "connect",
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CONNECT)));
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::interrupt()
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "interrupt",
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(INTERRUPT)));
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::continueDebugging(StepAction action, int count)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "continue",
+ // "arguments" : { "stepaction" : <"in", "next" or "out">,
+ // "stepcount" : <number of steps (default 1)>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CONTINEDEBUGGING)));
+
+ if (action != Continue) {
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+ switch (action) {
+ case In: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(IN)));
+ break;
+ case Out: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(OUT)));
+ break;
+ case Next: args.setProperty(QLatin1String(STEPACTION),QJSValue(QLatin1String(NEXT)));
+ break;
+ default:break;
+ }
+ if (args.isValid()) {
+ if (count != 1)
+ args.setProperty(QLatin1String(STEPCOUNT),QJSValue(count));
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+ }
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::evaluate(QString expr, bool global, bool disableBreak, int frame, const QVariantMap &/*addContext*/)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "evaluate",
+ // "arguments" : { "expression" : <expression to evaluate>,
+ // "frame" : <number>,
+ // "global" : <boolean>,
+ // "disable_break" : <boolean>,
+ // "additional_context" : [
+ // { "name" : <name1>, "handle" : <handle1> },
+ // { "name" : <name2>, "handle" : <handle2> },
+ // ...
+ // ]
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(EVALUATE)));
+
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+ args.setProperty(QLatin1String(EXPRESSION),QJSValue(expr));
+
+ if (frame != -1)
+ args.setProperty(QLatin1String(FRAME),QJSValue(frame));
+
+ if (global)
+ args.setProperty(QLatin1String(GLOBAL),QJSValue(global));
+
+ if (disableBreak)
+ args.setProperty(QLatin1String(DISABLEBREAK),QJSValue(disableBreak));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::lookup(QList<int> handles, bool includeSource)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "lookup",
+ // "arguments" : { "handles" : <array of handles>,
+ // "includeSource" : <boolean indicating whether the source will be included when script objects are returned>,
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LOOKUP)));
+
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+
+ QString arr("[]");
+ QJSValue array = parser.call(QJSValue(), QJSValueList() << arr);
+ int index = 0;
+ foreach (int handle, handles) {
+ array.setProperty(index++,QJSValue(handle));
+ }
+ args.setProperty(QLatin1String(HANDLES),array);
+
+ if (includeSource)
+ args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::backtrace(int fromFrame, int toFrame, bool bottom)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "backtrace",
+ // "arguments" : { "fromFrame" : <number>
+ // "toFrame" : <number>
+ // "bottom" : <boolean, set to true if the bottom of the stack is requested>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(BACKTRACE)));
+
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+
+ if (fromFrame != -1)
+ args.setProperty(QLatin1String(FROMFRAME),QJSValue(fromFrame));
+
+ if (toFrame != -1)
+ args.setProperty(QLatin1String(TOFRAME),QJSValue(toFrame));
+
+ if (bottom)
+ args.setProperty(QLatin1String(BOTTOM),QJSValue(bottom));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::frame(int number)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "frame",
+ // "arguments" : { "number" : <frame number>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(FRAME)));
+
+ if (number != -1) {
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+ args.setProperty(QLatin1String(NUMBER),QJSValue(number));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::scope(int number, int frameNumber)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "scope",
+ // "arguments" : { "number" : <scope number>
+ // "frameNumber" : <frame number, optional uses selected frame if missing>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPE)));
+
+ if (number != -1) {
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+ args.setProperty(QLatin1String(NUMBER),QJSValue(number));
+
+ if (frameNumber != -1)
+ args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::scopes(int frameNumber)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "scopes",
+ // "arguments" : { "frameNumber" : <frame number, optional uses selected frame if missing>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCOPES)));
+
+ if (frameNumber != -1) {
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+ args.setProperty(QLatin1String(FRAMENUMBER),QJSValue(frameNumber));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::scripts(int types, QList<int> ids, bool includeSource, QVariant /*filter*/)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "scripts",
+ // "arguments" : { "types" : <types of scripts to retrieve
+ // set bit 0 for native scripts
+ // set bit 1 for extension scripts
+ // set bit 2 for normal scripts
+ // (default is 4 for normal scripts)>
+ // "ids" : <array of id's of scripts to return. If this is not specified all scripts are requrned>
+ // "includeSource" : <boolean indicating whether the source code should be included for the scripts returned>
+ // "filter" : <string or number: filter string or script id.
+ // If a number is specified, then only the script with the same number as its script id will be retrieved.
+ // If a string is specified, then only scripts whose names contain the filter string will be retrieved.>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SCRIPTS)));
+
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+ args.setProperty(QLatin1String(TYPES),QJSValue(types));
+
+ if (ids.count()) {
+ QString arr("[]");
+ QJSValue array = parser.call(QJSValue(), QJSValueList() << arr);
+ int index = 0;
+ foreach (int id, ids) {
+ array.setProperty(index++,QJSValue(id));
+ }
+ args.setProperty(QLatin1String(IDS),array);
+ }
+
+ if (includeSource)
+ args.setProperty(QLatin1String(INCLUDESOURCE),QJSValue(includeSource));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::source(int frame, int fromLine, int toLine)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "source",
+ // "arguments" : { "frame" : <frame number (default selected frame)>
+ // "fromLine" : <from line within the source default is line 0>
+ // "toLine" : <to line within the source this line is not included in
+ // the result default is the number of lines in the script>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SOURCE)));
+
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+
+ if (frame != -1)
+ args.setProperty(QLatin1String(FRAME),QJSValue(frame));
+
+ if (fromLine != -1)
+ args.setProperty(QLatin1String(FROMLINE),QJSValue(fromLine));
+
+ if (toLine != -1)
+ args.setProperty(QLatin1String(TOLINE),QJSValue(toLine));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::setBreakpoint(QString type, QString target, int line, int column, bool enabled, QString condition, int ignoreCount)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "setbreakpoint",
+ // "arguments" : { "type" : <"function" or "script" or "scriptId" or "scriptRegExp">
+ // "target" : <function expression or script identification>
+ // "line" : <line in script or function>
+ // "column" : <character position within the line>
+ // "enabled" : <initial enabled state. True or false, default is true>
+ // "condition" : <string with break point condition>
+ // "ignoreCount" : <number specifying the number of break point hits to ignore, default value is 0>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETBREAKPOINT)));
+
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+
+ args.setProperty(QLatin1String(TYPE),QJSValue(type));
+ args.setProperty(QLatin1String(TARGET),QJSValue(target));
+
+ if (line != -1)
+ args.setProperty(QLatin1String(LINE),QJSValue(line));
+
+ if (column != -1)
+ args.setProperty(QLatin1String(COLUMN),QJSValue(column));
+
+ args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
+
+ if (!condition.isEmpty())
+ args.setProperty(QLatin1String(CONDITION),QJSValue(condition));
+
+ if (ignoreCount != -1)
+ args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::changeBreakpoint(int breakpoint, bool enabled, QString condition, int ignoreCount)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "changebreakpoint",
+ // "arguments" : { "breakpoint" : <number of the break point to clear>
+ // "enabled" : <initial enabled state. True or false, default is true>
+ // "condition" : <string with break point condition>
+ // "ignoreCount" : <number specifying the number of break point hits }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CHANGEBREAKPOINT)));
+
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+
+ args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint));
+
+ args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
+
+ if (!condition.isEmpty())
+ args.setProperty(QLatin1String(CONDITION),QJSValue(condition));
+
+ if (ignoreCount != -1)
+ args.setProperty(QLatin1String(IGNORECOUNT),QJSValue(ignoreCount));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::clearBreakpoint(int breakpoint)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "clearbreakpoint",
+ // "arguments" : { "breakpoint" : <number of the break point to clear>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(CLEARBREAKPOINT)));
+
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+
+ args.setProperty(QLatin1String(BREAKPOINT),QJSValue(breakpoint));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::setExceptionBreak(Exception type, bool enabled)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "setexceptionbreak",
+ // "arguments" : { "type" : <string: "all", or "uncaught">,
+ // "enabled" : <optional bool: enables the break type if true>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(SETEXCEPTIONBREAK)));
+
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+
+ if (type == All)
+ args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(ALL)));
+ else if (type == Uncaught)
+ args.setProperty(QLatin1String(TYPE),QJSValue(QLatin1String(UNCAUGHT)));
+
+ if (enabled)
+ args.setProperty(QLatin1String(ENABLED),QJSValue(enabled));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::v8flags(QString flags)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "v8flags",
+ // "arguments" : { "flags" : <string: a sequence of v8 flags just like those used on the command line>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(V8FLAGS)));
+
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+
+ args.setProperty(QLatin1String(FLAGS),QJSValue(flags));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::version()
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "version",
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(VERSION)));
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+//void QJSDebugClient::profile(ProfileCommand command)
+//{
+//// { "seq" : <number>,
+//// "type" : "request",
+//// "command" : "profile",
+//// "arguments" : { "command" : "resume" or "pause" }
+//// }
+// VARIANTMAPINIT;
+// jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PROFILE)));
+
+// QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+
+// if (command == Resume)
+// args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(RESUME)));
+// else
+// args.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(PAUSE)));
+
+// args.setProperty(QLatin1String("modules"),QJSValue(1));
+// if (args.isValid()) {
+// jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+// }
+
+// QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+// sendMessage(packMessage(json.toString().toUtf8()));
+//}
+
+void QJSDebugClient::disconnect()
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "disconnect",
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(DISCONNECT)));
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::gc()
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "gc",
+ // "arguments" : { "type" : <string: "all">,
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(GARBAGECOLLECTOR)));
+
+ QJSValue args = parser.call(QJSValue(), QJSValueList() << obj);
+
+ args.setProperty(QLatin1String(FLAGS),QJSValue(QLatin1String(ALL)));
+
+ if (args.isValid()) {
+ jsonVal.setProperty(QLatin1String(ARGUMENTS),args);
+ }
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::listBreakpoints()
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "listbreakpoints",
+ // }
+ VARIANTMAPINIT;
+ jsonVal.setProperty(QLatin1String(COMMAND),QJSValue(QLatin1String(LISTBREAKPOINTS)));
+
+ QJSValue json = stringify.call(QJSValue(), QJSValueList() << jsonVal);
+ sendMessage(packMessage(json.toString().toUtf8()));
+}
+
+void QJSDebugClient::statusChanged(Status status)
+{
+ if (status == Enabled) {
+ flushSendBuffer();
+ emit enabled();
+ }
+}
+
+void QJSDebugClient::messageReceived(const QByteArray &data)
+{
+ QDataStream ds(data);
+ QByteArray command;
+ ds >> command;
+
+ if (command == "V8DEBUG") {
+ ds >> response;
+ QString jsonString(response);
+ QVariantMap value = parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+ QString type = value.value("type").toString();
+
+ if (type == "response") {
+
+ if (!value.value("success").toBool()) {
+ qDebug() << "Error: The test case will fail since no signal is emitted";
+ return;
+ }
+
+ QString debugCommand(value.value("command").toString());
+ if (debugCommand == "backtrace" ||
+ debugCommand == "lookup" ||
+ debugCommand == "setbreakpoint" ||
+ debugCommand == "evaluate" ||
+ debugCommand == "listbreakpoints" ||
+ debugCommand == "version" ||
+ debugCommand == "v8flags" ||
+ debugCommand == "disconnect" ||
+ debugCommand == "gc" ||
+ debugCommand == "changebreakpoint" ||
+ debugCommand == "clearbreakpoint" ||
+ debugCommand == "frame" ||
+ debugCommand == "scope" ||
+ debugCommand == "scopes" ||
+ debugCommand == "scripts" ||
+ debugCommand == "source" ||
+ debugCommand == "setexceptionbreak" /*||
+ debugCommand == "profile"*/) {
+ emit result();
+
+ } else {
+ // DO NOTHING
+ }
+
+ } else if (type == "event") {
+ QString event(value.value("event").toString());
+
+ if (event == "break" ||
+ event == "exception") {
+ emit stopped();
+ }
+ }
+ }
+}
+
+void QJSDebugClient::sendMessage(const QByteArray &msg)
+{
+ if (status() == Enabled) {
+ QDeclarativeDebugClient::sendMessage(msg);
+ } else {
+ sendBuffer.append(msg);
+ }
+}
+
+void QJSDebugClient::flushSendBuffer()
+{
+ foreach (const QByteArray &msg, sendBuffer)
+ QDeclarativeDebugClient::sendMessage(msg);
+ sendBuffer.clear();
+}
+
+QByteArray QJSDebugClient::packMessage(QByteArray message)
+{
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ QByteArray cmd = "V8DEBUG";
+ rs << cmd << message;
+ return reply;
+}
+
+void tst_QDeclarativeDebugJS::initTestCase()
+{
+ process = 0;
+ client = 0;
+ connection = 0;
+}
+
+void tst_QDeclarativeDebugJS::cleanupTestCase()
+{
+ if (process)
+ delete process;
+
+ if (client)
+ delete client;
+
+ if (connection)
+ delete connection;
+}
+
+void tst_QDeclarativeDebugJS::init()
+{
+ connection = new QDeclarativeDebugConnection();
+ process = new QJSDebugProcess();
+ client = new QJSDebugClient(connection);
+
+ process->start(QStringList() << QLatin1String(BLOCKMODE) << TEST_FILE(QLatin1String(QMLFILE)));
+ QVERIFY(process->waitForSessionStart());
+
+ connection->connectToHost("127.0.0.1", 3771);
+ QVERIFY(connection->waitForConnected());
+
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(enabled())));
+}
+
+void tst_QDeclarativeDebugJS::cleanup()
+{
+ if (process)
+ delete process;
+
+ if (client)
+ delete client;
+
+ if (connection)
+ delete connection;
+
+ process = 0;
+ client = 0;
+ connection = 0;
+}
+
+void tst_QDeclarativeDebugJS::getVersion()
+{
+ //void version()
+
+ client->interrupt();
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->version();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+}
+
+void tst_QDeclarativeDebugJS::applyV8Flags()
+{
+ //void v8flags(QString flags)
+
+ client->interrupt();
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->v8flags(QString());
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+}
+
+void tst_QDeclarativeDebugJS::disconnect()
+{
+ //void disconnect()
+
+ client->interrupt();
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->disconnect();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+}
+
+void tst_QDeclarativeDebugJS::gc()
+{
+ //void gc()
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), 2, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->gc();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+}
+
+void tst_QDeclarativeDebugJS::listBreakpoints()
+{
+ //void listBreakpoints()
+
+ int sourceLine1 = 57;
+ int sourceLine2 = 60;
+ int sourceLine3 = 67;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine1, -1, true);
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine2, -1, true);
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), sourceLine3, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->listBreakpoints();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QList<QVariant> breakpoints = value.value("body").toMap().value("breakpoints").toList();
+
+ QCOMPARE(breakpoints.count(), 3);
+}
+
+void tst_QDeclarativeDebugJS::setBreakpointInScriptOnCompleted()
+{
+ //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
+
+ int sourceLine = 49;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
+ QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
+}
+
+void tst_QDeclarativeDebugJS::setBreakpointInScriptOnTimerCallback()
+{
+ //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
+
+ int sourceLine = 67;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
+ QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
+}
+
+void tst_QDeclarativeDebugJS::setBreakpointInScriptInDifferentFile()
+{
+ //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
+
+ int sourceLine = 43;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), sourceLine);
+ QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(JSFILE));
+}
+
+void tst_QDeclarativeDebugJS::setBreakpointInScriptOnComment()
+{
+ //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
+
+ int sourceLine = 48;
+ int actualLine = 50;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), actualLine);
+ QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(JSFILE));
+}
+
+void tst_QDeclarativeDebugJS::setBreakpointInScriptOnEmptyLine()
+{
+ //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
+
+ int sourceLine = 49;
+ int actualLine = 50;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), actualLine);
+ QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(JSFILE));
+}
+
+void tst_QDeclarativeDebugJS::setBreakpointInScriptWithCondition()
+{
+ //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
+
+ int out = 10;
+ int sourceLine = 51;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(JSFILE), sourceLine, -1, true, QLatin1String("out > 10"));
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ //Get the frame index
+ QString jsonString = client->response;
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ int frameIndex = body.value("index").toInt();
+
+ //Verify the value of 'result'
+ client->evaluate(QLatin1String("out"),frameIndex);
+
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+
+ jsonString = client->response;
+ value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ body = value.value("body").toMap();
+
+ QVERIFY(body.value("value").toInt() > out);
+}
+
+//void tst_QDeclarativeDebugJS::setBreakpointInFunction()
+//{
+// //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
+
+// int actualLine = 31;
+
+// client->startDebugging();
+// client->setBreakpoint(QLatin1String(FUNCTION), QLatin1String("doSomethingElse"), -1, -1, true);
+
+// QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+// QString jsonString(client->response);
+// QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+// QVariantMap body = value.value("body").toMap();
+
+// QCOMPARE(body.value("sourceLine").toInt(), actualLine);
+// QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
+//}
+
+void tst_QDeclarativeDebugJS::changeBreakpoint()
+{
+ //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
+
+ int sourceLine1 = 77;
+ int sourceLine2 = 78;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine1, -1, true);
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine2, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ //Will hit 1st brakpoint, change this breakpoint enable = false
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+ QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
+
+ int breakpoint = breakpointsHit.at(0).toInt();
+ client->changeBreakpoint(breakpoint,false);
+
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+
+ //Continue with debugging
+ client->continueDebugging(QJSDebugClient::Continue);
+ //Hit 2nd breakpoint
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+ //Continue with debugging
+ client->continueDebugging(QJSDebugClient::Continue);
+ //Should stop at 2nd breakpoint
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ jsonString = client->response;
+ value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
+}
+
+void tst_QDeclarativeDebugJS::changeBreakpointOnCondition()
+{
+ //void changeBreakpoint(int breakpoint, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
+
+ int sourceLine1 = 56;
+ int sourceLine2 = 60;
+ int result = 0;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine1, -1, true);
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine2, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ //Will hit 1st brakpoint, change this breakpoint enable = false
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+ QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
+
+ int breakpoint = breakpointsHit.at(0).toInt();
+ client->changeBreakpoint(breakpoint,false,QLatin1String("a = 0"));
+
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+
+ //Continue with debugging
+ client->continueDebugging(QJSDebugClient::Continue);
+ //Hit 2nd breakpoint
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+ //Continue with debugging
+ client->continueDebugging(QJSDebugClient::Continue);
+ //Should stop at 2nd breakpoint
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ jsonString = client->response;
+ value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
+
+ client->frame();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+
+ //Get the frame index
+ jsonString = client->response;
+ value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ body = value.value("body").toMap();
+
+ int frameIndex = body.value("index").toInt();
+
+ //Verify the value of 'result'
+ client->evaluate(QLatin1String("root.result"),frameIndex);
+
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+
+ jsonString = client->response;
+ value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ body = value.value("body").toMap();
+
+ QVERIFY(body.value("value").toInt() > result);
+}
+
+void tst_QDeclarativeDebugJS::clearBreakpoint()
+{
+ //void clearBreakpoint(int breakpoint);
+
+ int sourceLine1 = 77;
+ int sourceLine2 = 78;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine1, -1, true);
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine2, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ //Will hit 1st brakpoint, change this breakpoint enable = false
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+ QList<QVariant> breakpointsHit = body.value("breakpoints").toList();
+
+ int breakpoint = breakpointsHit.at(0).toInt();
+ client->changeBreakpoint(breakpoint,false,QLatin1String("result > 5"));
+
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+
+ //Continue with debugging
+ client->continueDebugging(QJSDebugClient::Continue);
+ //Hit 2nd breakpoint
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+ //Continue with debugging
+ client->continueDebugging(QJSDebugClient::Continue);
+ //Should stop at 2nd breakpoint
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ jsonString = client->response;
+ value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
+}
+
+void tst_QDeclarativeDebugJS::setExceptionBreak()
+{
+ //void setExceptionBreak(QString type, bool enabled = false);
+
+ client->interrupt();
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->setExceptionBreak(QJSDebugClient::All,true);
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+
+ client->continueDebugging(QJSDebugClient::Continue);
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
+}
+
+void tst_QDeclarativeDebugJS::stepNext()
+{
+ //void continueDebugging(StepAction stepAction, int stepCount = 1);
+
+ int sourceLine = 57;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->continueDebugging(QJSDebugClient::Next);
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 1);
+ QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
+}
+
+void tst_QDeclarativeDebugJS::stepNextWithCount()
+{
+ //void continueDebugging(StepAction stepAction, int stepCount = 1);
+
+ int sourceLine = 59;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->continueDebugging(QJSDebugClient::Next,2);
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), sourceLine + 2);
+ QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
+}
+
+void tst_QDeclarativeDebugJS::stepIn()
+{
+ //void continueDebugging(StepAction stepAction, int stepCount = 1);
+
+ int sourceLine = 67;
+ int actualLine = 56;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->continueDebugging(QJSDebugClient::In);
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), actualLine);
+ QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
+}
+
+void tst_QDeclarativeDebugJS::stepOut()
+{
+ //void continueDebugging(StepAction stepAction, int stepCount = 1);
+
+ int sourceLine = 56;
+ int actualLine = 68;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->continueDebugging(QJSDebugClient::Out);
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), actualLine);
+ QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
+}
+
+void tst_QDeclarativeDebugJS::continueDebugging()
+{
+ //void continueDebugging(StepAction stepAction, int stepCount = 1);
+
+ int sourceLine1 = 56;
+ int sourceLine2 = 60;
+
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine1, -1, true);
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine2, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->continueDebugging(QJSDebugClient::Continue);
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped()), 10000));
+
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("sourceLine").toInt(), sourceLine2);
+ QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(QMLFILE));
+}
+
+void tst_QDeclarativeDebugJS::backtrace()
+{
+ //void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
+
+ int sourceLine = 60;
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->backtrace();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+}
+
+void tst_QDeclarativeDebugJS::getFrameDetails()
+{
+ //void frame(int number = -1);
+
+ int sourceLine = 60;
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->frame();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+}
+
+void tst_QDeclarativeDebugJS::getScopeDetails()
+{
+ //void scope(int number = -1, int frameNumber = -1);
+
+ int sourceLine = 60;
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->scope();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+}
+
+void tst_QDeclarativeDebugJS::evaluateInGlobalScope()
+{
+ //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
+
+ int sourceLine = 49;
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->evaluate(QLatin1String("print('Hello World')"),true);
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+
+ //Verify the value of 'print'
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ QCOMPARE(body.value("text").toString(),QLatin1String("undefined"));
+}
+
+void tst_QDeclarativeDebugJS::evaluateInLocalScope()
+{
+ //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap());
+
+ int sourceLine = 60;
+ client->setBreakpoint(QLatin1String(SCRIPT), QLatin1String(QMLFILE), sourceLine, -1, true);
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->frame();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+
+ //Get the frame index
+ QString jsonString(client->response);
+ QVariantMap value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ QVariantMap body = value.value("body").toMap();
+
+ int frameIndex = body.value("index").toInt();
+
+ client->evaluate(QLatin1String("root.someValue"),frameIndex);
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+
+ //Verify the value of 'root.someValue'
+ jsonString = client->response;
+ value = client->parser.call(QJSValue(), QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
+
+ body = value.value("body").toMap();
+
+ QCOMPARE(body.value("value").toInt(),10);
+}
+
+void tst_QDeclarativeDebugJS::getScopes()
+{
+ //void scopes(int frameNumber = -1);
+
+ client->interrupt();
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->scopes();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+}
+
+void tst_QDeclarativeDebugJS::getScripts()
+{
+ //void scripts(int types = -1, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
+
+ client->interrupt();
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->scripts();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+}
+
+void tst_QDeclarativeDebugJS::getSource()
+{
+ //void source(int frame = -1, int fromLine = -1, int toLine = -1);
+
+ client->interrupt();
+ client->startDebugging();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(stopped())));
+
+ client->source();
+ QVERIFY(QDeclarativeDebugTest::waitForSignal(client, SIGNAL(result())));
+}
+
+QTEST_MAIN(tst_QDeclarativeDebugJS)
+
+#include "tst_qdeclarativedebugjs.moc"
+
diff --git a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp
index 74f549c076..d849ad2a79 100644
--- a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp
+++ b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp
@@ -47,8 +47,6 @@
#include <QtDeclarative/qdeclarativeengine.h>
-#include <private/qdeclarativedebug_p.h>
-#include <private/qdeclarativeenginedebug_p.h>
#include <private/qdeclarativedebugclient_p.h>
#include <private/qdeclarativedebugservice_p.h>
@@ -189,7 +187,8 @@ 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:13769";
+ char arg[] = "-qmljsdebugger=port:13769";
+ _argv[_argc - 1] = arg;
QApplication app(_argc, _argv);
tst_QDeclarativeDebugService tc;
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.handle.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.handle.1.qml
new file mode 100644
index 0000000000..9c27653b34
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.handle.1.qml
@@ -0,0 +1,25 @@
+import QtQuick 2.0
+import Qt.test 1.0
+
+Item {
+ id: obj
+ objectName: "obj"
+ property CircularReferenceHandle first
+ property CircularReferenceHandle second
+
+ CircularReferenceHandle {
+ id: crh
+ objectName: "crh"
+ }
+
+ function createReference() {
+ first = crh.generate(crh);
+ second = crh.generate(crh);
+ // NOTE: manually add reference from first to second
+ // in unit test prior reparenting and gc.
+ }
+
+ function performGc() {
+ gc();
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.handle.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.handle.2.qml
new file mode 100644
index 0000000000..dc196263b4
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.handle.2.qml
@@ -0,0 +1,26 @@
+import QtQuick 2.0
+import Qt.test 1.0
+
+Item {
+ id: obj
+ objectName: "obj"
+ property CircularReferenceHandle first
+ property CircularReferenceHandle second
+
+ CircularReferenceHandle {
+ id: crh
+ objectName: "crh"
+ }
+
+ function circularReference() {
+ // generate the circularly referential pair
+ first = crh.generate(crh);
+ second = crh.generate(crh);
+ // note: must manually reparent in unit test
+ // after setting the handle references.
+ }
+
+ function performGc() {
+ gc();
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.object.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.object.1.qml
new file mode 100644
index 0000000000..4fd1311c29
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.object.1.qml
@@ -0,0 +1,31 @@
+import QtQuick 2.0
+import Qt.test 1.0
+
+Item {
+ id: obj
+ objectName: "obj"
+
+ property CircularReferenceObject first
+ property CircularReferenceObject second
+
+
+ CircularReferenceObject {
+ id: cro
+ objectName: "cro"
+ }
+
+ function createReference() {
+ // generate the objects
+ first = cro.generate(cro); // has parent, so won't be collected
+ second = cro.generate(); // no parent, but will be kept alive by first's reference
+ first.addReference(second);
+
+ // remove top level references
+ first = cro;
+ second = cro;
+ }
+
+ function performGc() {
+ gc();
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.object.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.object.2.qml
new file mode 100644
index 0000000000..3f8415ce0f
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/handleReferenceManagement.object.2.qml
@@ -0,0 +1,32 @@
+import QtQuick 2.0
+import Qt.test 1.0
+
+Item {
+ id: obj
+ objectName: "obj"
+
+ property CircularReferenceObject first
+ property CircularReferenceObject second
+
+
+ CircularReferenceObject {
+ id: cro
+ objectName: "cro"
+ }
+
+ function circularReference() {
+ // generate the circularly referential pair - they should still be collected
+ first = cro.generate(); // no parent, so should be collected
+ second = cro.generate(); // no parent, so should be collected
+ first.addReference(second);
+ second.addReference(first);
+
+ // remove top level references
+ first = cro;
+ second = cro;
+ }
+
+ function performGc() {
+ gc();
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/signalHandlers.qml b/tests/auto/declarative/qdeclarativeecmascript/data/signalHandlers.qml
new file mode 100644
index 0000000000..975be1b2ad
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/signalHandlers.qml
@@ -0,0 +1,60 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+QtObject {
+ id: root
+
+ property int count: 0
+ signal testSignal
+ onTestSignal: count++
+
+ property int funcCount: 0
+ function testFunction() {
+ funcCount++;
+ }
+
+ //should increment count
+ function testSignalCall() {
+ testSignal()
+ }
+
+ //should NOT increment count, and should throw an exception
+ property string errorString
+ function testSignalHandlerCall() {
+ try {
+ onTestSignal()
+ } catch (error) {
+ errorString = error.toString();
+ }
+ }
+
+ //should increment funcCount once
+ function testSignalConnection() {
+ testSignal.connect(testFunction)
+ testSignal();
+ testSignal.disconnect(testFunction)
+ testSignal();
+ }
+
+ //should increment funcCount once
+ function testSignalHandlerConnection() {
+ onTestSignal.connect(testFunction)
+ testSignal();
+ onTestSignal.disconnect(testFunction)
+ testSignal();
+ }
+
+ //should be defined
+ property bool definedResult: false
+ function testSignalDefined() {
+ if (testSignal !== undefined)
+ definedResult = true;
+ }
+
+ //should be defined
+ property bool definedHandlerResult: false
+ function testSignalHandlerDefined() {
+ if (onTestSignal !== undefined)
+ definedHandlerResult = true;
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp
index 05d5510033..0057c117fa 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp
@@ -189,6 +189,9 @@ void registerTypes()
qRegisterMetaType<MyQmlObject::MyType>("MyEnum2");
qRegisterMetaType<Qt::MouseButtons>("Qt::MouseButtons");
+
+ qmlRegisterType<CircularReferenceObject>("Qt.test", 1, 0, "CircularReferenceObject");
+ qmlRegisterType<CircularReferenceHandle>("Qt.test", 1, 0, "CircularReferenceHandle");
}
#include "testtypes.moc"
diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h
index 2738ee3d60..52b74affa8 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h
+++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h
@@ -57,6 +57,9 @@
#include <QtDeclarative/qdeclarativescriptstring.h>
#include <QtDeclarative/qdeclarativecomponent.h>
+#include <private/qv8gccallback_p.h>
+#include <private/qdeclarativeengine_p.h>
+
class MyQmlAttachedObject : public QObject
{
Q_OBJECT
@@ -966,6 +969,108 @@ private:
int m_methodCallCount;
};
+class CircularReferenceObject : public QObject,
+ public QV8GCCallback::Node
+{
+ Q_OBJECT
+
+public:
+ CircularReferenceObject(QObject *parent = 0)
+ : QObject(parent), QV8GCCallback::Node(callback), m_referenced(0), m_dtorCount(0)
+ {
+ QV8GCCallback::addGcCallbackNode(this);
+ }
+
+ ~CircularReferenceObject()
+ {
+ if (m_dtorCount) *m_dtorCount = *m_dtorCount + 1;
+ }
+
+ Q_INVOKABLE void setDtorCount(int *dtorCount)
+ {
+ m_dtorCount = dtorCount;
+ }
+
+ Q_INVOKABLE CircularReferenceObject *generate(QObject *parent = 0)
+ {
+ CircularReferenceObject *retn = new CircularReferenceObject(parent);
+ retn->m_dtorCount = m_dtorCount;
+ return retn;
+ }
+
+ Q_INVOKABLE void addReference(QObject *other)
+ {
+ m_referenced = other;
+ }
+
+ static void callback(QV8GCCallback::Referencer *r, QV8GCCallback::Node *n)
+ {
+ CircularReferenceObject *cro = static_cast<CircularReferenceObject*>(n);
+ if (cro->m_referenced) {
+ r->addRelationship(cro, cro->m_referenced);
+ }
+ }
+
+private:
+ QObject *m_referenced;
+ int *m_dtorCount;
+};
+Q_DECLARE_METATYPE(CircularReferenceObject*)
+
+class CircularReferenceHandle : public QObject,
+ public QV8GCCallback::Node
+{
+ Q_OBJECT
+
+public:
+ CircularReferenceHandle(QObject *parent = 0)
+ : QObject(parent), QV8GCCallback::Node(gccallback), m_dtorCount(0)
+ {
+ QV8GCCallback::addGcCallbackNode(this);
+ }
+
+ ~CircularReferenceHandle()
+ {
+ if (m_dtorCount) *m_dtorCount = *m_dtorCount + 1;
+ }
+
+ Q_INVOKABLE void setDtorCount(int *dtorCount)
+ {
+ m_dtorCount = dtorCount;
+ }
+
+ Q_INVOKABLE CircularReferenceHandle *generate(QObject *parent = 0)
+ {
+ CircularReferenceHandle *retn = new CircularReferenceHandle(parent);
+ retn->m_dtorCount = m_dtorCount;
+ return retn;
+ }
+
+ Q_INVOKABLE void addReference(v8::Persistent<v8::Value> handle)
+ {
+ m_referenced = qPersistentNew(handle);
+ m_referenced.MakeWeak(static_cast<void*>(this), wrcallback);
+ }
+
+ static void wrcallback(v8::Persistent<v8::Value> handle, void *params)
+ {
+ CircularReferenceHandle *crh = static_cast<CircularReferenceHandle*>(params);
+ qPersistentDispose(handle);
+ crh->m_referenced.Clear();
+ }
+
+ static void gccallback(QV8GCCallback::Referencer *r, QV8GCCallback::Node *n)
+ {
+ CircularReferenceHandle *crh = static_cast<CircularReferenceHandle*>(n);
+ r->addRelationship(crh, crh->m_referenced);
+ }
+
+private:
+ v8::Persistent<v8::Value> m_referenced;
+ int *m_dtorCount;
+};
+Q_DECLARE_METATYPE(CircularReferenceHandle*)
+
void registerTypes();
#endif // TESTTYPES_H
diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
index f14db0a330..b732cd8193 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
@@ -153,6 +153,7 @@ private slots:
void elementAssign();
void objectPassThroughSignals();
void booleanConversion();
+ void handleReferenceManagement();
void bug1();
void bug2();
@@ -188,6 +189,7 @@ private slots:
void realToInt();
void dynamicString();
void include();
+ void signalHandlers();
void callQtInvokables();
void invokableObjectArg();
@@ -687,6 +689,8 @@ void tst_qdeclarativeecmascript::attachedProperties()
QCOMPARE(object->property("b").toInt(), 26);
QCOMPARE(object->property("c").toInt(), 26);
QCOMPARE(object->property("d").toInt(), 26);
+
+ delete object;
}
{
@@ -3207,6 +3211,256 @@ void tst_qdeclarativeecmascript::booleanConversion()
delete object;
}
+void tst_qdeclarativeecmascript::handleReferenceManagement()
+{
+
+ int dtorCount = 0;
+ {
+ // Linear QObject reference
+ QDeclarativeEngine hrmEngine;
+ QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.object.1.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ CircularReferenceObject *cro = object->findChild<CircularReferenceObject*>("cro");
+ cro->setDtorCount(&dtorCount);
+ QMetaObject::invokeMethod(object, "createReference");
+ QMetaObject::invokeMethod(object, "performGc");
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 0); // second has JS ownership, kept alive by first's reference
+ delete object;
+ hrmEngine.collectGarbage();
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 3);
+ }
+
+ dtorCount = 0;
+ {
+ // Circular QObject reference
+ QDeclarativeEngine hrmEngine;
+ QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.object.2.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ CircularReferenceObject *cro = object->findChild<CircularReferenceObject*>("cro");
+ cro->setDtorCount(&dtorCount);
+ QMetaObject::invokeMethod(object, "circularReference");
+ QMetaObject::invokeMethod(object, "performGc");
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 2); // both should be cleaned up, since circular references shouldn't keep alive.
+ delete object;
+ hrmEngine.collectGarbage();
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 3);
+ }
+
+ dtorCount = 0;
+ {
+ // Linear handle reference
+ QDeclarativeEngine hrmEngine;
+ QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.handle.1.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ CircularReferenceHandle *crh = object->findChild<CircularReferenceHandle*>("crh");
+ QVERIFY(crh != 0);
+ crh->setDtorCount(&dtorCount);
+ QMetaObject::invokeMethod(object, "createReference");
+ CircularReferenceHandle *first = object->property("first").value<CircularReferenceHandle*>();
+ CircularReferenceHandle *second = object->property("second").value<CircularReferenceHandle*>();
+ QVERIFY(first != 0);
+ QVERIFY(second != 0);
+ first->addReference(QDeclarativeData::get(second)->v8object); // create reference
+ // now we have to reparent second and make second owned by JS.
+ second->setParent(0);
+ QDeclarativeEngine::setObjectOwnership(second, QDeclarativeEngine::JavaScriptOwnership);
+ QMetaObject::invokeMethod(object, "performGc");
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 0); // due to reference from first to second, second shouldn't be collected.
+ delete object;
+ hrmEngine.collectGarbage();
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 3);
+ }
+
+ dtorCount = 0;
+ {
+ // Circular handle reference
+ QDeclarativeEngine hrmEngine;
+ QDeclarativeComponent component(&hrmEngine, TEST_FILE("handleReferenceManagement.handle.2.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ CircularReferenceHandle *crh = object->findChild<CircularReferenceHandle*>("crh");
+ QVERIFY(crh != 0);
+ crh->setDtorCount(&dtorCount);
+ QMetaObject::invokeMethod(object, "circularReference");
+ CircularReferenceHandle *first = object->property("first").value<CircularReferenceHandle*>();
+ CircularReferenceHandle *second = object->property("second").value<CircularReferenceHandle*>();
+ QVERIFY(first != 0);
+ QVERIFY(second != 0);
+ first->addReference(QDeclarativeData::get(second)->v8object); // create circular reference
+ second->addReference(QDeclarativeData::get(first)->v8object); // note: must be weak.
+ // now we have to reparent and change ownership.
+ first->setParent(0);
+ second->setParent(0);
+ QDeclarativeEngine::setObjectOwnership(first, QDeclarativeEngine::JavaScriptOwnership);
+ QDeclarativeEngine::setObjectOwnership(second, QDeclarativeEngine::JavaScriptOwnership);
+ QMetaObject::invokeMethod(object, "performGc");
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 2); // despite circular references, both will be collected.
+ delete object;
+ hrmEngine.collectGarbage();
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 3);
+ }
+
+ dtorCount = 0;
+ {
+ // multiple engine interaction - linear reference
+ QDeclarativeEngine hrmEngine1;
+ QDeclarativeEngine hrmEngine2;
+ QDeclarativeComponent component1(&hrmEngine1, TEST_FILE("handleReferenceManagement.handle.1.qml"));
+ QDeclarativeComponent component2(&hrmEngine2, TEST_FILE("handleReferenceManagement.handle.1.qml"));
+ QObject *object1 = component1.create();
+ QObject *object2 = component2.create();
+ QVERIFY(object1 != 0);
+ QVERIFY(object2 != 0);
+ CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
+ CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
+ QVERIFY(crh1 != 0);
+ QVERIFY(crh2 != 0);
+ crh1->setDtorCount(&dtorCount);
+ crh2->setDtorCount(&dtorCount);
+ QMetaObject::invokeMethod(object1, "createReference");
+ QMetaObject::invokeMethod(object2, "createReference");
+ CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
+ CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
+ CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
+ CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
+ QVERIFY(first1 != 0);
+ QVERIFY(second1 != 0);
+ QVERIFY(first2 != 0);
+ QVERIFY(second2 != 0);
+ first1->addReference(QDeclarativeData::get(second2)->v8object); // create reference across engines
+ // now we have to reparent second2 and make second2 owned by JS.
+ second2->setParent(0);
+ QDeclarativeEngine::setObjectOwnership(second2, QDeclarativeEngine::JavaScriptOwnership);
+ QMetaObject::invokeMethod(object1, "performGc");
+ QMetaObject::invokeMethod(object2, "performGc");
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 0); // due to reference from first1 to second2, second2 shouldn't be collected.
+ delete object1;
+ delete object2;
+ hrmEngine1.collectGarbage();
+ hrmEngine2.collectGarbage();
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 6);
+ }
+
+ dtorCount = 0;
+ {
+ // multiple engine interaction - circular reference
+ QDeclarativeEngine hrmEngine1;
+ QDeclarativeEngine hrmEngine2;
+ QDeclarativeComponent component1(&hrmEngine1, TEST_FILE("handleReferenceManagement.handle.1.qml"));
+ QDeclarativeComponent component2(&hrmEngine2, TEST_FILE("handleReferenceManagement.handle.1.qml"));
+ QObject *object1 = component1.create();
+ QObject *object2 = component2.create();
+ QVERIFY(object1 != 0);
+ QVERIFY(object2 != 0);
+ CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
+ CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
+ QVERIFY(crh1 != 0);
+ QVERIFY(crh2 != 0);
+ crh1->setDtorCount(&dtorCount);
+ crh2->setDtorCount(&dtorCount);
+ QMetaObject::invokeMethod(object1, "createReference");
+ QMetaObject::invokeMethod(object2, "createReference");
+ CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
+ CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
+ CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
+ CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
+ QVERIFY(first1 != 0);
+ QVERIFY(second1 != 0);
+ QVERIFY(first2 != 0);
+ QVERIFY(second2 != 0);
+ first1->addReference(QDeclarativeData::get(second1)->v8object); // create linear reference within engine1
+ second1->addReference(QDeclarativeData::get(second2)->v8object); // create linear reference across engines
+ second2->addReference(QDeclarativeData::get(first2)->v8object); // create linear reference within engine2
+ first2->addReference(QDeclarativeData::get(first1)->v8object); // close the loop - circular ref across engines
+ // now we have to reparent and change ownership to JS.
+ first1->setParent(0);
+ second1->setParent(0);
+ first2->setParent(0);
+ second2->setParent(0);
+ QDeclarativeEngine::setObjectOwnership(first1, QDeclarativeEngine::JavaScriptOwnership);
+ QDeclarativeEngine::setObjectOwnership(second1, QDeclarativeEngine::JavaScriptOwnership);
+ QDeclarativeEngine::setObjectOwnership(first2, QDeclarativeEngine::JavaScriptOwnership);
+ QDeclarativeEngine::setObjectOwnership(second2, QDeclarativeEngine::JavaScriptOwnership);
+ QMetaObject::invokeMethod(object1, "performGc");
+ QMetaObject::invokeMethod(object2, "performGc");
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 4); // circular references shouldn't keep them alive.
+ delete object1;
+ delete object2;
+ hrmEngine1.collectGarbage();
+ hrmEngine2.collectGarbage();
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 6);
+ }
+
+ dtorCount = 0;
+ {
+ // multiple engine interaction - linear reference with engine deletion
+ QDeclarativeEngine *hrmEngine1 = new QDeclarativeEngine;
+ QDeclarativeEngine *hrmEngine2 = new QDeclarativeEngine;
+ QDeclarativeComponent component1(hrmEngine1, TEST_FILE("handleReferenceManagement.handle.1.qml"));
+ QDeclarativeComponent component2(hrmEngine2, TEST_FILE("handleReferenceManagement.handle.1.qml"));
+ QObject *object1 = component1.create();
+ QObject *object2 = component2.create();
+ QVERIFY(object1 != 0);
+ QVERIFY(object2 != 0);
+ CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
+ CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
+ QVERIFY(crh1 != 0);
+ QVERIFY(crh2 != 0);
+ crh1->setDtorCount(&dtorCount);
+ crh2->setDtorCount(&dtorCount);
+ QMetaObject::invokeMethod(object1, "createReference");
+ QMetaObject::invokeMethod(object2, "createReference");
+ CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
+ CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
+ CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
+ CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
+ QVERIFY(first1 != 0);
+ QVERIFY(second1 != 0);
+ QVERIFY(first2 != 0);
+ QVERIFY(second2 != 0);
+ first1->addReference(QDeclarativeData::get(second1)->v8object); // create linear reference within engine1
+ second1->addReference(QDeclarativeData::get(second2)->v8object); // create linear reference across engines
+ second2->addReference(QDeclarativeData::get(first2)->v8object); // create linear reference within engine2
+ // now we have to reparent and change ownership to JS.
+ first1->setParent(crh1);
+ second1->setParent(0);
+ first2->setParent(0);
+ second2->setParent(0);
+ QDeclarativeEngine::setObjectOwnership(second1, QDeclarativeEngine::JavaScriptOwnership);
+ QDeclarativeEngine::setObjectOwnership(first2, QDeclarativeEngine::JavaScriptOwnership);
+ QDeclarativeEngine::setObjectOwnership(second2, QDeclarativeEngine::JavaScriptOwnership);
+ QMetaObject::invokeMethod(object1, "performGc");
+ QMetaObject::invokeMethod(object2, "performGc");
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 0);
+ delete hrmEngine2;
+ QMetaObject::invokeMethod(object1, "performGc");
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 0);
+ delete object1;
+ delete object2;
+ hrmEngine1->collectGarbage();
+ QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+ QCOMPARE(dtorCount, 6);
+ delete hrmEngine1;
+ }
+}
+
// Test that assigning a null object works
// Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
void tst_qdeclarativeecmascript::nullObjectBinding()
@@ -3597,6 +3851,36 @@ void tst_qdeclarativeecmascript::include()
}
}
+void tst_qdeclarativeecmascript::signalHandlers()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("signalHandlers.qml"));
+ QObject *o = component.create();
+ QVERIFY(o != 0);
+
+ QVERIFY(o->property("count").toInt() == 0);
+ QMetaObject::invokeMethod(o, "testSignalCall");
+ QCOMPARE(o->property("count").toInt(), 1);
+
+ QMetaObject::invokeMethod(o, "testSignalHandlerCall");
+ QCOMPARE(o->property("count").toInt(), 1);
+ QCOMPARE(o->property("errorString").toString(), QLatin1String("TypeError: Property 'onTestSignal' of object [object Object] is not a function"));
+
+ QVERIFY(o->property("funcCount").toInt() == 0);
+ QMetaObject::invokeMethod(o, "testSignalConnection");
+ QCOMPARE(o->property("funcCount").toInt(), 1);
+
+ QMetaObject::invokeMethod(o, "testSignalHandlerConnection");
+ QCOMPARE(o->property("funcCount").toInt(), 2);
+
+ QMetaObject::invokeMethod(o, "testSignalDefined");
+ QCOMPARE(o->property("definedResult").toBool(), true);
+
+ QMetaObject::invokeMethod(o, "testSignalHandlerDefined");
+ QCOMPARE(o->property("definedHandlerResult").toBool(), true);
+
+ delete o;
+}
+
void tst_qdeclarativeecmascript::qtbug_10696()
{
QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
diff --git a/tests/auto/declarative/qdeclarativedebug/qdeclarativedebug.pro b/tests/auto/declarative/qdeclarativeenginedebug/qdeclarativeenginedebug.pro
index 6187020a38..acf62acaf9 100644
--- a/tests/auto/declarative/qdeclarativedebug/qdeclarativedebug.pro
+++ b/tests/auto/declarative/qdeclarativeenginedebug/qdeclarativeenginedebug.pro
@@ -3,7 +3,7 @@ contains(QT_CONFIG,declarative): QT += network declarative
macx:CONFIG -= app_bundle
HEADERS += ../shared/debugutil_p.h
-SOURCES += tst_qdeclarativedebug.cpp \
+SOURCES += tst_qdeclarativeenginedebug.cpp \
../shared/debugutil.cpp
CONFIG += parallel_test declarative_debug
diff --git a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp b/tests/auto/declarative/qdeclarativeenginedebug/tst_qdeclarativeenginedebug.cpp
index b47579ea6a..d202a79eb9 100644
--- a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp
+++ b/tests/auto/declarative/qdeclarativeenginedebug/tst_qdeclarativeenginedebug.cpp
@@ -53,7 +53,6 @@
#include <QtDeclarative/qsgitem.h>
#include <private/qdeclarativebinding_p.h>
-#include <private/qdeclarativedebug_p.h>
#include <private/qdeclarativeenginedebug_p.h>
#include <private/qdeclarativedebugservice_p.h>
#include <private/qdeclarativemetatype_p.h>
@@ -64,7 +63,7 @@
Q_DECLARE_METATYPE(QDeclarativeDebugWatch::State)
-class tst_QDeclarativeDebug : public QObject
+class tst_QDeclarativeEngineDebug : public QObject
{
Q_OBJECT
@@ -128,7 +127,7 @@ signals:
QML_DECLARE_TYPE(NonScriptProperty)
-QDeclarativeDebugObjectReference tst_QDeclarativeDebug::findRootObject(int context, bool recursive)
+QDeclarativeDebugObjectReference tst_QDeclarativeEngineDebug::findRootObject(int context, bool recursive)
{
QDeclarativeDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
waitForQuery(q_engines);
@@ -154,7 +153,7 @@ QDeclarativeDebugObjectReference tst_QDeclarativeDebug::findRootObject(int conte
return result;
}
-QDeclarativeDebugPropertyReference tst_QDeclarativeDebug::findProperty(const QList<QDeclarativeDebugPropertyReference> &props, const QString &name) const
+QDeclarativeDebugPropertyReference tst_QDeclarativeEngineDebug::findProperty(const QList<QDeclarativeDebugPropertyReference> &props, const QString &name) const
{
foreach(const QDeclarativeDebugPropertyReference &p, props) {
if (p.name() == name)
@@ -163,7 +162,7 @@ QDeclarativeDebugPropertyReference tst_QDeclarativeDebug::findProperty(const QLi
return QDeclarativeDebugPropertyReference();
}
-void tst_QDeclarativeDebug::waitForQuery(QDeclarativeDebugQuery *query)
+void tst_QDeclarativeEngineDebug::waitForQuery(QDeclarativeDebugQuery *query)
{
QVERIFY(query);
QCOMPARE(query->parent(), qobject_cast<QObject*>(this));
@@ -172,7 +171,7 @@ void tst_QDeclarativeDebug::waitForQuery(QDeclarativeDebugQuery *query)
QFAIL("query timed out");
}
-void tst_QDeclarativeDebug::recursiveObjectTest(QObject *o, const QDeclarativeDebugObjectReference &oref, bool recursive) const
+void tst_QDeclarativeEngineDebug::recursiveObjectTest(QObject *o, const QDeclarativeDebugObjectReference &oref, bool recursive) const
{
const QMetaObject *meta = o->metaObject();
@@ -241,7 +240,7 @@ void tst_QDeclarativeDebug::recursiveObjectTest(QObject *o, const QDeclarativeDe
}
}
-void tst_QDeclarativeDebug::recursiveCompareObjects(const QDeclarativeDebugObjectReference &a, const QDeclarativeDebugObjectReference &b) const
+void tst_QDeclarativeEngineDebug::recursiveCompareObjects(const QDeclarativeDebugObjectReference &a, const QDeclarativeDebugObjectReference &b) const
{
QCOMPARE(a.debugId(), b.debugId());
QCOMPARE(a.className(), b.className());
@@ -265,7 +264,7 @@ void tst_QDeclarativeDebug::recursiveCompareObjects(const QDeclarativeDebugObjec
recursiveCompareObjects(a.children()[i], b.children()[i]);
}
-void tst_QDeclarativeDebug::recursiveCompareContexts(const QDeclarativeDebugContextReference &a, const QDeclarativeDebugContextReference &b) const
+void tst_QDeclarativeEngineDebug::recursiveCompareContexts(const QDeclarativeDebugContextReference &a, const QDeclarativeDebugContextReference &b) const
{
QCOMPARE(a.debugId(), b.debugId());
QCOMPARE(a.name(), b.name());
@@ -279,7 +278,7 @@ void tst_QDeclarativeDebug::recursiveCompareContexts(const QDeclarativeDebugCont
recursiveCompareContexts(a.contexts()[i], b.contexts()[i]);
}
-void tst_QDeclarativeDebug::compareProperties(const QDeclarativeDebugPropertyReference &a, const QDeclarativeDebugPropertyReference &b) const
+void tst_QDeclarativeEngineDebug::compareProperties(const QDeclarativeDebugPropertyReference &a, const QDeclarativeDebugPropertyReference &b) const
{
QCOMPARE(a.objectDebugId(), b.objectDebugId());
QCOMPARE(a.name(), b.name());
@@ -289,7 +288,7 @@ void tst_QDeclarativeDebug::compareProperties(const QDeclarativeDebugPropertyRef
QCOMPARE(a.hasNotifySignal(), b.hasNotifySignal());
}
-void tst_QDeclarativeDebug::initTestCase()
+void tst_QDeclarativeEngineDebug::initTestCase()
{
qRegisterMetaType<QDeclarativeDebugWatch::State>();
qmlRegisterType<NonScriptProperty>("Test", 1, 0, "NonScriptPropertyElement");
@@ -383,7 +382,7 @@ void tst_QDeclarativeDebug::initTestCase()
QTRY_VERIFY(m_dbg->status() == QDeclarativeEngineDebug::Enabled);
}
-void tst_QDeclarativeDebug::cleanupTestCase()
+void tst_QDeclarativeEngineDebug::cleanupTestCase()
{
delete m_dbg;
delete m_conn;
@@ -391,7 +390,7 @@ void tst_QDeclarativeDebug::cleanupTestCase()
delete m_engine;
}
-void tst_QDeclarativeDebug::setMethodBody()
+void tst_QDeclarativeEngineDebug::setMethodBody()
{
QDeclarativeDebugObjectReference obj = findRootObject(2);
@@ -428,7 +427,7 @@ void tst_QDeclarativeDebug::setMethodBody()
}
}
-void tst_QDeclarativeDebug::watch_property()
+void tst_QDeclarativeEngineDebug::watch_property()
{
QDeclarativeDebugObjectReference obj = findRootObject();
QDeclarativeDebugPropertyReference prop = findProperty(obj.properties(), "width");
@@ -473,7 +472,7 @@ void tst_QDeclarativeDebug::watch_property()
QCOMPARE(spy.at(0).at(1).value<QVariant>(), qVariantFromValue(origWidth*2));
}
-void tst_QDeclarativeDebug::watch_object()
+void tst_QDeclarativeEngineDebug::watch_object()
{
QDeclarativeDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
waitForQuery(q_engines);
@@ -546,7 +545,7 @@ void tst_QDeclarativeDebug::watch_object()
QCOMPARE(newHeight, origHeight * 2);
}
-void tst_QDeclarativeDebug::watch_expression()
+void tst_QDeclarativeEngineDebug::watch_expression()
{
QFETCH(QString, expr);
QFETCH(int, increment);
@@ -609,7 +608,7 @@ void tst_QDeclarativeDebug::watch_expression()
}
}
-void tst_QDeclarativeDebug::watch_expression_data()
+void tst_QDeclarativeEngineDebug::watch_expression_data()
{
QTest::addColumn<QString>("expr");
QTest::addColumn<int>("increment");
@@ -619,21 +618,21 @@ void tst_QDeclarativeDebug::watch_expression_data()
QTest::newRow("width+10") << "width + 10" << 10 << 5;
}
-void tst_QDeclarativeDebug::watch_context()
+void tst_QDeclarativeEngineDebug::watch_context()
{
QDeclarativeDebugContextReference c;
QTest::ignoreMessage(QtWarningMsg, "QDeclarativeEngineDebug::addWatch(): Not implemented");
QVERIFY(!m_dbg->addWatch(c, QString(), this));
}
-void tst_QDeclarativeDebug::watch_file()
+void tst_QDeclarativeEngineDebug::watch_file()
{
QDeclarativeDebugFileReference f;
QTest::ignoreMessage(QtWarningMsg, "QDeclarativeEngineDebug::addWatch(): Not implemented");
QVERIFY(!m_dbg->addWatch(f, this));
}
-void tst_QDeclarativeDebug::queryAvailableEngines()
+void tst_QDeclarativeEngineDebug::queryAvailableEngines()
{
QDeclarativeDebugEnginesQuery *q_engines;
@@ -668,7 +667,7 @@ void tst_QDeclarativeDebug::queryAvailableEngines()
m_dbg = new QDeclarativeEngineDebug(m_conn, this);
}
-void tst_QDeclarativeDebug::queryRootContexts()
+void tst_QDeclarativeEngineDebug::queryRootContexts()
{
QDeclarativeDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
waitForQuery(q_engines);
@@ -714,7 +713,7 @@ void tst_QDeclarativeDebug::queryRootContexts()
m_dbg = new QDeclarativeEngineDebug(m_conn, this);
}
-void tst_QDeclarativeDebug::queryObject()
+void tst_QDeclarativeEngineDebug::queryObject()
{
QFETCH(bool, recursive);
@@ -786,7 +785,7 @@ void tst_QDeclarativeDebug::queryObject()
}
}
-void tst_QDeclarativeDebug::queryObject_data()
+void tst_QDeclarativeEngineDebug::queryObject_data()
{
QTest::addColumn<bool>("recursive");
@@ -794,7 +793,7 @@ void tst_QDeclarativeDebug::queryObject_data()
QTest::newRow("recursive") << true;
}
-void tst_QDeclarativeDebug::queryExpressionResult()
+void tst_QDeclarativeEngineDebug::queryExpressionResult()
{
QFETCH(QString, expr);
QFETCH(QVariant, result);
@@ -835,7 +834,7 @@ void tst_QDeclarativeDebug::queryExpressionResult()
m_dbg = new QDeclarativeEngineDebug(m_conn, this);
}
-void tst_QDeclarativeDebug::queryExpressionResult_data()
+void tst_QDeclarativeEngineDebug::queryExpressionResult_data()
{
QTest::addColumn<QString>("expr");
QTest::addColumn<QVariant>("result");
@@ -847,7 +846,7 @@ void tst_QDeclarativeDebug::queryExpressionResult_data()
QTest::newRow("list of QObject*") << "varObjList" << qVariantFromValue(QString("<unknown value>"));
}
-void tst_QDeclarativeDebug::tst_QDeclarativeDebugFileReference()
+void tst_QDeclarativeEngineDebug::tst_QDeclarativeDebugFileReference()
{
QDeclarativeDebugFileReference ref;
QVERIFY(ref.url().isEmpty());
@@ -871,7 +870,7 @@ void tst_QDeclarativeDebug::tst_QDeclarativeDebugFileReference()
}
}
-void tst_QDeclarativeDebug::tst_QDeclarativeDebugEngineReference()
+void tst_QDeclarativeEngineDebug::tst_QDeclarativeDebugEngineReference()
{
QDeclarativeDebugEngineReference ref;
QCOMPARE(ref.debugId(), -1);
@@ -895,7 +894,7 @@ void tst_QDeclarativeDebug::tst_QDeclarativeDebugEngineReference()
}
}
-void tst_QDeclarativeDebug::tst_QDeclarativeDebugObjectReference()
+void tst_QDeclarativeEngineDebug::tst_QDeclarativeDebugObjectReference()
{
QDeclarativeDebugObjectReference ref;
QCOMPARE(ref.debugId(), -1);
@@ -928,7 +927,7 @@ void tst_QDeclarativeDebug::tst_QDeclarativeDebugObjectReference()
recursiveCompareObjects(r, ref);
}
-void tst_QDeclarativeDebug::tst_QDeclarativeDebugContextReference()
+void tst_QDeclarativeEngineDebug::tst_QDeclarativeDebugContextReference()
{
QDeclarativeDebugContextReference ref;
QCOMPARE(ref.debugId(), -1);
@@ -953,7 +952,7 @@ void tst_QDeclarativeDebug::tst_QDeclarativeDebugContextReference()
recursiveCompareContexts(r, ref);
}
-void tst_QDeclarativeDebug::tst_QDeclarativeDebugPropertyReference()
+void tst_QDeclarativeEngineDebug::tst_QDeclarativeDebugPropertyReference()
{
QDeclarativeDebugObjectReference rootObject = findRootObject();
QDeclarativeDebugObjectQuery *query = m_dbg->queryObject(rootObject, this);
@@ -976,7 +975,7 @@ void tst_QDeclarativeDebug::tst_QDeclarativeDebugPropertyReference()
compareProperties(r, ref);
}
-void tst_QDeclarativeDebug::setBindingForObject()
+void tst_QDeclarativeEngineDebug::setBindingForObject()
{
QDeclarativeDebugObjectReference rootObject = findRootObject();
QVERIFY(rootObject.debugId() != -1);
@@ -1047,7 +1046,7 @@ void tst_QDeclarativeDebug::setBindingForObject()
QCOMPARE(onEnteredRef.value(), QVariant("{console.log('hello, world') }"));
}
-void tst_QDeclarativeDebug::setBindingInStates()
+void tst_QDeclarativeEngineDebug::setBindingInStates()
{
// Check if changing bindings of propertychanges works
@@ -1139,7 +1138,7 @@ void tst_QDeclarativeDebug::setBindingInStates()
QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 300);
}
-void tst_QDeclarativeDebug::queryObjectTree()
+void tst_QDeclarativeEngineDebug::queryObjectTree()
{
const int sourceIndex = 3;
@@ -1209,12 +1208,13 @@ 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:3768";
+ char arg[] = "-qmljsdebugger=port:3768";
+ _argv[_argc - 1] = arg;
QApplication app(_argc, _argv);
- tst_QDeclarativeDebug tc;
+ tst_QDeclarativeEngineDebug tc;
return QTest::qExec(&tc, _argc, _argv);
delete _argv;
}
-#include "tst_qdeclarativedebug.moc"
+#include "tst_qdeclarativeenginedebug.moc"
diff --git a/tests/auto/declarative/qdeclarativepath/data/arc.qml b/tests/auto/declarative/qdeclarativepath/data/arc.qml
new file mode 100644
index 0000000000..000221c784
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativepath/data/arc.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+Path {
+ startX: 0; startY: 0
+
+ PathArc {
+ x: 100; y: 100
+ radiusX: 100; radiusY: 100
+ direction: PathArc.Clockwise
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativepath/data/curve.qml b/tests/auto/declarative/qdeclarativepath/data/curve.qml
new file mode 100644
index 0000000000..c571186496
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativepath/data/curve.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+Path {
+ startX: 0; startY: 0
+
+ PathCurve { x: 100; y: 50 }
+ PathCurve { x: 50; y: 100 }
+ PathCurve { x: 100; y: 150 }
+}
diff --git a/tests/auto/declarative/qdeclarativepath/data/svg.qml b/tests/auto/declarative/qdeclarativepath/data/svg.qml
new file mode 100644
index 0000000000..cec0f75061
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativepath/data/svg.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Path {
+ PathSvg { path: "M200,300 Q400,50 600,300 T1000,300" }
+}
diff --git a/tests/auto/declarative/qdeclarativepath/qdeclarativepath.pro b/tests/auto/declarative/qdeclarativepath/qdeclarativepath.pro
new file mode 100644
index 0000000000..d6fe1cf789
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativepath/qdeclarativepath.pro
@@ -0,0 +1,17 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativepath.cpp
+
+symbian: {
+ importFiles.files = data
+ importFiles.path = .
+ DEPLOYMENT += importFiles
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+}
+
+CONFIG += parallel_test
+
+QT += core-private gui-private v8-private declarative-private
diff --git a/tests/auto/declarative/qdeclarativepath/tst_qdeclarativepath.cpp b/tests/auto/declarative/qdeclarativepath/tst_qdeclarativepath.cpp
new file mode 100644
index 0000000000..d8a539ea2a
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativepath/tst_qdeclarativepath.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/private/qdeclarativepath_p.h>
+
+#include "../../../shared/util.h"
+
+#ifdef Q_OS_SYMBIAN
+// In Symbian OS test data is located in applications private dir
+#define SRCDIR "."
+#endif
+
+class tst_QDeclarativePath : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QDeclarativePath() {}
+
+private slots:
+ void arc();
+ void catmullromCurve();
+ void svg();
+};
+
+void tst_QDeclarativePath::arc()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/arc.qml"));
+ QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->startX(), 0.);
+ QCOMPARE(obj->startY(), 0.);
+
+ QDeclarativeListReference list(obj, "pathElements");
+ QCOMPARE(list.count(), 1);
+
+ QDeclarativePathArc* arc = qobject_cast<QDeclarativePathArc*>(list.at(0));
+ QVERIFY(arc != 0);
+ QCOMPARE(arc->x(), 100.);
+ QCOMPARE(arc->y(), 100.);
+ QCOMPARE(arc->radiusX(), 100.);
+ QCOMPARE(arc->radiusY(), 100.);
+ QCOMPARE(arc->useLargeArc(), false);
+ QCOMPARE(arc->direction(), QDeclarativePathArc::Clockwise);
+
+ QPainterPath path = obj->path();
+ QVERIFY(path != QPainterPath());
+
+ QPointF pos = obj->pointAt(0);
+ QCOMPARE(pos, QPointF(0,0));
+ pos = obj->pointAt(.25);
+ QCOMPARE(pos.toPoint(), QPoint(39,8)); //fuzzy compare
+ pos = obj->pointAt(.75);
+ QCOMPARE(pos.toPoint(), QPoint(92,61)); //fuzzy compare
+ pos = obj->pointAt(1);
+ QCOMPARE(pos, QPointF(100,100));
+}
+
+void tst_QDeclarativePath::catmullromCurve()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/curve.qml"));
+ QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->startX(), 0.);
+ QCOMPARE(obj->startY(), 0.);
+
+ QDeclarativeListReference list(obj, "pathElements");
+ QCOMPARE(list.count(), 3);
+
+ QDeclarativePathCatmullRomCurve* arc = qobject_cast<QDeclarativePathCatmullRomCurve*>(list.at(0));
+// QVERIFY(arc != 0);
+// QCOMPARE(arc->x(), 100.);
+// QCOMPARE(arc->y(), 100.);
+// QCOMPARE(arc->radiusX(), 100.);
+// QCOMPARE(arc->radiusY(), 100.);
+// QCOMPARE(arc->useLargeArc(), false);
+// QCOMPARE(arc->direction(), QDeclarativePathArc::Clockwise);
+
+ QPainterPath path = obj->path();
+ QVERIFY(path != QPainterPath());
+
+ QPointF pos = obj->pointAt(0);
+ QCOMPARE(pos, QPointF(0,0));
+ pos = obj->pointAt(.25);
+ QCOMPARE(pos.toPoint(), QPoint(63,26)); //fuzzy compare
+ pos = obj->pointAt(.75);
+ QCOMPARE(pos.toPoint(), QPoint(51,105)); //fuzzy compare
+ pos = obj->pointAt(1);
+ QCOMPARE(pos, QPointF(100,150));
+}
+
+void tst_QDeclarativePath::svg()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/svg.qml"));
+ QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->startX(), 0.);
+ QCOMPARE(obj->startY(), 0.);
+
+ QDeclarativeListReference list(obj, "pathElements");
+ QCOMPARE(list.count(), 1);
+
+ QDeclarativePathSvg* svg = qobject_cast<QDeclarativePathSvg*>(list.at(0));
+ QVERIFY(svg != 0);
+ QCOMPARE(svg->path(), QLatin1String("M200,300 Q400,50 600,300 T1000,300"));
+
+ QPainterPath path = obj->path();
+ QVERIFY(path != QPainterPath());
+
+ QPointF pos = obj->pointAt(0);
+ QCOMPARE(pos, QPointF(200,300));
+ pos = obj->pointAt(.25);
+ QCOMPARE(pos.toPoint(), QPoint(400,175)); //fuzzy compare
+ pos = obj->pointAt(.75);
+ QCOMPARE(pos.toPoint(), QPoint(800,425)); //fuzzy compare
+ pos = obj->pointAt(1);
+ QCOMPARE(pos, QPointF(1000,300));
+}
+
+
+QTEST_MAIN(tst_QDeclarativePath)
+
+#include "tst_qdeclarativepath.moc"
diff --git a/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp b/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp
index 5583701b12..966ac1950c 100644
--- a/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp
+++ b/tests/auto/declarative/qdeclarativepropertymap/tst_qdeclarativepropertymap.cpp
@@ -61,6 +61,7 @@ private slots:
void count();
void crashBug();
+ void QTBUG_17868();
};
void tst_QDeclarativePropertyMap::insert()
@@ -218,6 +219,23 @@ void tst_QDeclarativePropertyMap::crashBug()
delete obj;
}
+void tst_QDeclarativePropertyMap::QTBUG_17868()
+{
+ QDeclarativePropertyMap map;
+
+ QDeclarativeEngine engine;
+ QDeclarativeContext context(&engine);
+ context.setContextProperty("map", &map);
+ map.insert("key", 1);
+ QDeclarativeComponent c(&engine);
+ c.setData("import QtQuick 2.0\nItem {property bool error:false; Component.onCompleted: {try{console.log(map.keys());}catch(e) {error=true;}}}",QUrl());
+ QObject *obj = c.create(&context);
+ QVERIFY(obj);
+ QVERIFY(!obj->property("error").toBool());
+ delete obj;
+
+}
+
QTEST_MAIN(tst_QDeclarativePropertyMap)
#include "tst_qdeclarativepropertymap.moc"
diff --git a/tests/auto/declarative/qdeclarativestates/data/avoidFastForward.qml b/tests/auto/declarative/qdeclarativestates/data/avoidFastForward.qml
new file mode 100644
index 0000000000..519befc31e
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativestates/data/avoidFastForward.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.0
+
+Rectangle {
+ id: rect
+ width: 200
+ height: 200
+
+ property int updateCount: 0
+ onColorChanged: updateCount++
+
+ property color aColor: "green"
+
+ states: State {
+ name: "a"
+ PropertyChanges { target: rect; color: aColor }
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
index e13a6c4305..165179e35d 100644
--- a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
+++ b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
@@ -149,6 +149,7 @@ private slots:
void extendsBug();
void editProperties();
void QTBUG_14830();
+ void avoidFastForward();
};
void tst_qdeclarativestates::initTestCase()
@@ -1513,6 +1514,20 @@ void tst_qdeclarativestates::QTBUG_14830()
QCOMPARE(item->width(), qreal(171));
}
+void tst_qdeclarativestates::avoidFastForward()
+{
+ QDeclarativeEngine engine;
+
+ //shouldn't fast forward if there isn't a transition
+ QDeclarativeComponent c(&engine, SRCDIR "/data/avoidFastForward.qml");
+ QSGRectangle *rect = qobject_cast<QSGRectangle*>(c.create());
+ QVERIFY(rect != 0);
+
+ QSGItemPrivate *rectPrivate = QSGItemPrivate::get(rect);
+ rectPrivate->setState("a");
+ QCOMPARE(rect->property("updateCount").toInt(), 1);
+}
+
QTEST_MAIN(tst_qdeclarativestates)
#include "tst_qdeclarativestates.moc"
diff --git a/tests/auto/declarative/qsgfocusscope/tst_qsgfocusscope.cpp b/tests/auto/declarative/qsgfocusscope/tst_qsgfocusscope.cpp
index 83da0bae27..a5e998d1fa 100644
--- a/tests/auto/declarative/qsgfocusscope/tst_qsgfocusscope.cpp
+++ b/tests/auto/declarative/qsgfocusscope/tst_qsgfocusscope.cpp
@@ -127,10 +127,7 @@ void tst_qsgfocusscope::basic()
view->requestActivateWindow();
qApp->processEvents();
-#ifdef Q_WS_X11
- // to be safe and avoid failing setFocus with window managers
- qt_x11_wait_for_window_manager(view);
-#endif
+ QTest::qWaitForWindowShown(view);
QVERIFY(view->isTopLevel());
QVERIFY(item0->hasActiveFocus() == true);
@@ -173,10 +170,7 @@ void tst_qsgfocusscope::nested()
view->requestActivateWindow();
qApp->processEvents();
-#ifdef Q_WS_X11
- // to be safe and avoid failing setFocus with window managers
- qt_x11_wait_for_window_manager(view);
-#endif
+ QTest::qWaitForWindowShown(view);
QVERIFY(view->windowState() == Qt::WindowActive);
@@ -206,10 +200,7 @@ void tst_qsgfocusscope::noFocus()
view->requestActivateWindow();
qApp->processEvents();
-#ifdef Q_WS_X11
- // to be safe and avoid failing setFocus with window managers
- qt_x11_wait_for_window_manager(view);
-#endif
+ QTest::qWaitForWindowShown(view);
QVERIFY(view->windowState() == Qt::WindowActive);
QVERIFY(item0->hasActiveFocus() == false);
@@ -250,10 +241,7 @@ void tst_qsgfocusscope::textEdit()
view->requestActivateWindow();
qApp->processEvents();
-#ifdef Q_WS_X11
- // to be safe and avoid failing setFocus with window managers
- qt_x11_wait_for_window_manager(view);
-#endif
+ QTest::qWaitForWindowShown(view);
QVERIFY(view->windowState() == Qt::WindowActive);
QVERIFY(item0->hasActiveFocus() == true);
@@ -308,10 +296,7 @@ void tst_qsgfocusscope::forceFocus()
view->requestActivateWindow();
qApp->processEvents();
-#ifdef Q_WS_X11
- // to be safe and avoid failing setFocus with window managers
- qt_x11_wait_for_window_manager(view);
-#endif
+ QTest::qWaitForWindowShown(view);
QVERIFY(view->windowState() == Qt::WindowActive);
QVERIFY(item0->hasActiveFocus() == true);
@@ -382,10 +367,7 @@ void tst_qsgfocusscope::signalEmission()
view->requestActivateWindow();
qApp->processEvents();
-#ifdef Q_WS_X11
- // to be safe and avoid failing setFocus with window managers
- qt_x11_wait_for_window_manager(view);
-#endif
+ QTest::qWaitForWindowShown(view);
QVariant blue(QColor("blue"));
QVariant red(QColor("red"));
@@ -434,10 +416,7 @@ void tst_qsgfocusscope::qtBug13380()
view->requestActivateWindow();
qApp->processEvents();
-#ifdef Q_WS_X11
- // to be safe and avoid failing setFocus with window managers
- qt_x11_wait_for_window_manager(view);
-#endif
+ QTest::qWaitForWindowShown(view);
QVERIFY(view->windowState() == Qt::WindowActive);
QVERIFY(view->rootObject()->property("noFocus").toBool());
@@ -613,10 +592,7 @@ void tst_qsgfocusscope::canvasFocus()
view->requestActivateWindow();
qApp->processEvents();
-#ifdef Q_WS_X11
- // to be safe and avoid failing setFocus with window managers
- qt_x11_wait_for_window_manager(view);
-#endif
+ QTest::qWaitForWindowShown(view);
// Now the canvas has focus, active focus given to item1
QTRY_COMPARE((view->windowState() == Qt::WindowActive), true);
diff --git a/tests/auto/declarative/qsggridview/data/header.qml b/tests/auto/declarative/qsggridview/data/header.qml
index 5978317a76..648e2a2298 100644
--- a/tests/auto/declarative/qsggridview/data/header.qml
+++ b/tests/auto/declarative/qsggridview/data/header.qml
@@ -24,8 +24,8 @@ Rectangle {
GridView {
id: grid
objectName: "grid"
- width: 240
- height: 320
+ width: initialViewWidth
+ height: initialViewHeight
cellWidth: 80
cellHeight: 60
model: testModel
diff --git a/tests/auto/declarative/qsggridview/tst_qsggridview.cpp b/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
index 5933ee1103..98953aef40 100644
--- a/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
+++ b/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
@@ -78,6 +78,8 @@ private slots:
void clear();
void moved();
void moved_data();
+ void multipleChanges();
+ void multipleChanges_data();
void swapWithFirstItem();
void changeFlow();
void currentIndex();
@@ -147,6 +149,8 @@ void tst_QSGGridView::cleanupTestCase()
{
}
+
+
class TestModel : public QAbstractListModel
{
public:
@@ -193,6 +197,13 @@ public:
emit endInsertRows();
}
+ void insertItems(int index, const QList<QPair<QString, QString> > &items) {
+ emit beginInsertRows(QModelIndex(), index, index + items.count() - 1);
+ for (int i=0; i<items.count(); i++)
+ list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
+ emit endInsertRows();
+ }
+
void removeItem(int index) {
emit beginRemoveRows(QModelIndex(), index, index);
list.removeAt(index);
@@ -352,8 +363,8 @@ void tst_QSGGridView::inserted()
QTRY_VERIFY(contentItem != 0);
model.insertItem(1, "Will", "9876");
- QCOMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
@@ -431,7 +442,7 @@ void tst_QSGGridView::removed()
QTRY_VERIFY(contentItem != 0);
model.removeItem(1);
- QCOMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
QTRY_VERIFY(name != 0);
@@ -440,6 +451,7 @@ void tst_QSGGridView::removed()
QTRY_VERIFY(number != 0);
QTRY_COMPARE(number->text(), model.number(1));
+
// Checks that onRemove is called
QString removed = canvas->rootObject()->property("removed").toString();
QTRY_COMPARE(removed, QString("Item1"));
@@ -449,13 +461,13 @@ void tst_QSGGridView::removed()
for (int i = 0; i < model.count() && i < itemCount; ++i) {
QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
QTRY_VERIFY(item->x() == (i%3)*80);
QTRY_VERIFY(item->y() == (i/3)*60);
}
// Remove first item (which is the current item);
model.removeItem(0);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
name = findItem<QSGText>(contentItem, "textName", 0);
QTRY_VERIFY(name != 0);
@@ -464,25 +476,25 @@ void tst_QSGGridView::removed()
QTRY_VERIFY(number != 0);
QTRY_COMPARE(number->text(), model.number(0));
+
// Confirm items positioned correctly
itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
for (int i = 0; i < model.count() && i < itemCount; ++i) {
QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
QTRY_VERIFY(item->x() == (i%3)*80);
QTRY_VERIFY(item->y() == (i/3)*60);
}
// Remove items not visible
model.removeItem(25);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
// Confirm items positioned correctly
itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
for (int i = 0; i < model.count() && i < itemCount; ++i) {
QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
QTRY_VERIFY(item->x() == (i%3)*80);
QTRY_VERIFY(item->y() == (i/3)*60);
}
@@ -495,12 +507,12 @@ void tst_QSGGridView::removed()
QTRY_COMPARE(gridview->contentY(), 120.0);
model.removeItem(1);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
// Confirm items positioned correctly
for (int i = 6; i < 18; ++i) {
QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
QTRY_VERIFY(item->x() == (i%3)*80);
QTRY_VERIFY(item->y() == (i/3)*60);
}
@@ -508,20 +520,19 @@ void tst_QSGGridView::removed()
// Remove currentIndex
QSGItem *oldCurrent = gridview->currentItem();
model.removeItem(9);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
QTRY_COMPARE(gridview->currentIndex(), 9);
QTRY_VERIFY(gridview->currentItem() != oldCurrent);
gridview->setContentY(0);
// let transitions settle.
- QTest::qWait(100);
+ QTest::qWait(300);
// Confirm items positioned correctly
itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
for (int i = 0; i < model.count() && i < itemCount; ++i) {
QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
QTRY_VERIFY(item->x() == (i%3)*80);
QTRY_VERIFY(item->y() == (i/3)*60);
}
@@ -584,7 +595,7 @@ void tst_QSGGridView::clear()
// confirm sanity when adding an item to cleared list
model.addItem("New", "1");
- QVERIFY(gridview->count() == 1);
+ QTRY_COMPARE(gridview->count(), 1);
QVERIFY(gridview->currentItem() != 0);
QVERIFY(gridview->currentIndex() == 0);
@@ -628,10 +639,12 @@ void tst_QSGGridView::moved()
gridview->setContentY(contentY);
model.moveItems(from, to, count);
+ // wait for items to move
+ QTest::qWait(300);
+
// Confirm items positioned correctly and indexes correct
int firstVisibleIndex = qCeil(contentY / 60.0) * 3;
int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
-
for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
if (i >= firstVisibleIndex + 18) // index has moved out of view
continue;
@@ -675,12 +688,12 @@ void tst_QSGGridView::moved_data()
QTest::newRow("move 1 forwards, from non-visible -> visible")
<< 120.0 // show 6-23
<< 1 << 23 << 1
- << 0.0;
+ << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down
QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
<< 120.0 // // show 6-23
<< 0 << 6 << 1
- << 0.0;
+ << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down
QTest::newRow("move 1 forwards, from visible -> non-visible")
<< 0.0
@@ -698,6 +711,11 @@ void tst_QSGGridView::moved_data()
<< 10 << 5 << 1
<< 0.0;
+ QTest::newRow("move 1 backwards, within visible items (to first index)")
+ << 0.0
+ << 10 << 0 << 1
+ << 0.0;
+
QTest::newRow("move 1 backwards, from non-visible -> visible")
<< 0.0
<< 28 << 8 << 1
@@ -711,12 +729,12 @@ void tst_QSGGridView::moved_data()
QTest::newRow("move 1 backwards, from visible -> non-visible")
<< 120.0 // show 6-23
<< 7 << 1 << 1
- << 60.0 * 2; // this results in a forward movement that removes 6 items (2 rows)
+ << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
QTest::newRow("move 1 backwards, from visible -> non-visible (move first item)")
<< 120.0 // show 6-23
<< 7 << 0 << 1
- << 60.0 * 2; // first visible item moved, so all items shift 2 rows down with it
+ << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
QTest::newRow("move multiple forwards, within visible items")
@@ -727,12 +745,12 @@ void tst_QSGGridView::moved_data()
QTest::newRow("move multiple forwards, from non-visible -> visible")
<< 120.0 // show 6-23
<< 1 << 6 << 3
- << 60.0; // top row moved, all items should shift down by 1 row
+ << 60.0; // 1st row (it's above visible area) disappears, 0 drops down 1 row, first visible item (6) stays where it is
QTest::newRow("move multiple forwards, from non-visible -> visible (move first item)")
<< 120.0 // show 6-23
<< 0 << 6 << 3
- << 60.0; // top row moved, all items should shift down by 1 row
+ << 60.0; // top row moved and shifted to below 3rd row, all items should shift down by 1 row
QTest::newRow("move multiple forwards, from visible -> non-visible")
<< 0.0
@@ -763,14 +781,248 @@ void tst_QSGGridView::moved_data()
QTest::newRow("move multiple backwards, from visible -> non-visible")
<< 120.0 // show 6-23
<< 16 << 1 << 3
- << 60.0 * 5; // this results in a forward movement that removes 15 items (5 rows)
+ << -60.0; // to minimize movement, items are added above visible area, all items move up by 1 row
QTest::newRow("move multiple backwards, from visible -> non-visible (move first item)")
<< 120.0 // show 6-23
<< 16 << 0 << 3
- << 60.0 * 5; // this results in a forward movement that removes 16 items (5 rows)
+ << -60.0; // 16,17,18 move to above item 0, all items move up by 1 row
}
+struct ListChange {
+ enum { Inserted, Removed, Moved, SetCurrent } type;
+ int index;
+ int count;
+ int to; // Move
+
+ static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1 }; return c; }
+ static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1 }; return c; }
+ static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to }; return c; }
+ static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1 }; return c; }
+};
+Q_DECLARE_METATYPE(QList<ListChange>)
+
+void tst_QSGGridView::multipleChanges()
+{
+ QFETCH(int, startCount);
+ QFETCH(QList<ListChange>, changes);
+ QFETCH(int, newCount);
+ QFETCH(int, newCurrentIndex);
+
+ QSGView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < startCount; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
+ qApp->processEvents();
+
+ QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ for (int i=0; i<changes.count(); i++) {
+ switch (changes[i].type) {
+ case ListChange::Inserted:
+ {
+ QList<QPair<QString, QString> > items;
+ for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
+ items << qMakePair(QString("new item " + j), QString::number(j));
+ model.insertItems(changes[i].index, items);
+ break;
+ }
+ case ListChange::Removed:
+ model.removeItems(changes[i].index, changes[i].count);
+ break;
+ case ListChange::Moved:
+ model.moveItems(changes[i].index, changes[i].to, changes[i].count);
+ break;
+ case ListChange::SetCurrent:
+ gridview->setCurrentIndex(changes[i].index);
+ break;
+ }
+ }
+
+ QTRY_COMPARE(gridview->count(), newCount);
+ QCOMPARE(gridview->count(), model.count());
+ QTRY_COMPARE(gridview->currentIndex(), newCurrentIndex);
+
+ QSGText *name;
+ QSGText *number;
+ QSGItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+ int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
+ for (int i=0; i < model.count() && i < itemCount; ++i) {
+ QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ name = findItem<QSGText>(contentItem, "textName", i);
+ QVERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ number = findItem<QSGText>(contentItem, "textNumber", i);
+ QVERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QSGGridView::multipleChanges_data()
+{
+ QTest::addColumn<int>("startCount");
+ QTest::addColumn<QList<ListChange> >("changes");
+ QTest::addColumn<int>("newCount");
+ QTest::addColumn<int>("newCurrentIndex");
+
+ QList<ListChange> changes;
+
+ for (int i=1; i<30; i++)
+ changes << ListChange::remove(0);
+ QTest::newRow("remove all but 1, first->last") << 30 << changes << 1 << 0;
+
+ changes << ListChange::remove(0);
+ QTest::newRow("remove all") << 30 << changes << 0 << -1;
+
+ changes.clear();
+ changes << ListChange::setCurrent(29);
+ for (int i=29; i>0; i--)
+ changes << ListChange::remove(i);
+ QTest::newRow("remove last (current) -> first") << 30 << changes << 1 << 0;
+
+ QTest::newRow("remove then insert at 0") << 10 << (QList<ListChange>()
+ << ListChange::remove(0, 1)
+ << ListChange::insert(0, 1)
+ ) << 10 << 1;
+
+ QTest::newRow("remove then insert at non-zero index") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::remove(2, 1)
+ << ListChange::insert(2, 1)
+ ) << 10 << 3;
+
+ QTest::newRow("remove current then insert below it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::remove(1, 3)
+ << ListChange::insert(2, 2)
+ ) << 9 << 1;
+
+ QTest::newRow("remove current index then move it down") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::remove(1, 3)
+ << ListChange::move(1, 5, 1)
+ ) << 7 << 5;
+
+ QTest::newRow("remove current index then move it up") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::remove(4, 3)
+ << ListChange::move(4, 1, 1)
+ ) << 7 << 1;
+
+
+ QTest::newRow("insert multiple times") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 2)
+ << ListChange::insert(0, 4)
+ << ListChange::insert(0, 6)
+ ) << 12 << 10;
+
+ QTest::newRow("insert multiple times with current index changes") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 2)
+ << ListChange::insert(0, 4)
+ << ListChange::insert(0, 6)
+ << ListChange::setCurrent(3)
+ << ListChange::insert(3, 2)
+ ) << 14 << 5;
+
+ QTest::newRow("insert and remove all") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 30)
+ << ListChange::remove(0, 30)
+ ) << 0 << -1;
+
+ QTest::newRow("insert and remove current") << 30 << (QList<ListChange>()
+ << ListChange::insert(1)
+ << ListChange::setCurrent(1)
+ << ListChange::remove(1)
+ ) << 30 << 1;
+
+ QTest::newRow("insert before 0, then remove cross section of new and old items") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 10)
+ << ListChange::remove(5, 10)
+ ) << 10 << 5;
+
+ QTest::newRow("insert multiple, then move new items to end") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 3)
+ << ListChange::move(0, 10, 3)
+ ) << 13 << 0;
+
+ QTest::newRow("insert multiple, then move new and some old items to end") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 3)
+ << ListChange::move(0, 8, 5)
+ ) << 13 << 11;
+
+ QTest::newRow("insert multiple at end, then move new and some old items to start") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(9)
+ << ListChange::insert(10, 3)
+ << ListChange::move(8, 0, 5)
+ ) << 13 << 1;
+
+
+ QTest::newRow("move back and forth to same index") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::move(1, 2, 2)
+ << ListChange::move(2, 1, 2)
+ ) << 10 << 1;
+
+ QTest::newRow("move forwards then back") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::move(1, 2, 3)
+ << ListChange::move(3, 0, 5)
+ ) << 10 << 0;
+
+ QTest::newRow("move current, then remove it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 0, 1)
+ << ListChange::remove(0)
+ ) << 9 << 0;
+
+ QTest::newRow("move current, then insert before it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 0, 1)
+ << ListChange::insert(0)
+ ) << 11 << 1;
+
+ QTest::newRow("move multiple, then remove them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::move(5, 1, 3)
+ << ListChange::remove(1, 3)
+ ) << 7 << 1;
+
+ QTest::newRow("move multiple, then insert before them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 1, 3)
+ << ListChange::insert(1, 5)
+ ) << 15 << 6;
+
+ QTest::newRow("move multiple, then insert after them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(3)
+ << ListChange::move(0, 1, 2)
+ << ListChange::insert(3, 5)
+ ) << 15 << 8;
+
+
+ QTest::newRow("clear current") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 5)
+ << ListChange::setCurrent(-1)
+ << ListChange::remove(0, 5)
+ << ListChange::insert(0, 5)
+ ) << 5 << -1;
+}
+
+
void tst_QSGGridView::swapWithFirstItem()
{
// QTBUG_9697
@@ -2041,6 +2293,7 @@ void tst_QSGGridView::footer()
QFETCH(QPointF, initialContentPos);
QFETCH(QPointF, changedContentPos);
QFETCH(QPointF, firstDelegatePos);
+ QFETCH(QPointF, resizeContentPos);
QSGView *canvas = createView();
canvas->show();
@@ -2130,6 +2383,11 @@ void tst_QSGGridView::footer()
QVERIFY(item);
QCOMPARE(item->pos(), firstDelegatePos);
+ gridview->positionViewAtEnd();
+ footer->setHeight(10);
+ footer->setWidth(40);
+ QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
+
delete canvas;
}
@@ -2142,11 +2400,13 @@ void tst_QSGGridView::footer_data()
QTest::addColumn<QPointF>("initialContentPos");
QTest::addColumn<QPointF>("changedContentPos");
QTest::addColumn<QPointF>("firstDelegatePos");
+ QTest::addColumn<QPointF>("resizeContentPos");
// footer1 = 100 x 30
- // footer2 = 100 x 20
+ // footer2 = 50 x 20
// cells = 80 * 60
// view width = 240
+ // view height = 320
// footer below items, bottom left
QTest::newRow("flow left to right") << QSGGridView::LeftToRight << Qt::LeftToRight
@@ -2154,7 +2414,8 @@ void tst_QSGGridView::footer_data()
<< QPointF(0, 10 * 60) // 30 items = 10 rows
<< QPointF(0, 0)
<< QPointF(0, 0)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(0, 10 * 60 - 320 + 10);
// footer below items, bottom right
QTest::newRow("flow left to right, layout right to left") << QSGGridView::LeftToRight << Qt::RightToLeft
@@ -2162,7 +2423,8 @@ void tst_QSGGridView::footer_data()
<< QPointF((240 - 100) + 50, 10 * 60) // 50 = width diff between old and new footers
<< QPointF(0, 0)
<< QPointF(0, 0)
- << QPointF(240 - 80, 0);
+ << QPointF(240 - 80, 0)
+ << QPointF(0, 10 * 60 - 320 + 10);
// footer to right of items
QTest::newRow("flow top to bottom, layout left to right") << QSGGridView::TopToBottom << Qt::LeftToRight
@@ -2170,7 +2432,8 @@ void tst_QSGGridView::footer_data()
<< QPointF(6 * 80, 0) // 30 items = 6 columns
<< QPointF(0, 0)
<< QPointF(0, 0)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(6 * 80 - 240 + 40, 0);
// footer to left of items
QTest::newRow("flow top to bottom, layout right to left") << QSGGridView::TopToBottom << Qt::RightToLeft
@@ -2178,7 +2441,8 @@ void tst_QSGGridView::footer_data()
<< QPointF(-(6 * 80) - 50, 0) // 50 = new footer width
<< QPointF(-240, 0)
<< QPointF(-240, 0) // unchanged, footer change doesn't change content pos
- << QPointF(-80, 0);
+ << QPointF(-80, 0)
+ << QPointF(-(6 * 80) - 40, 0);
}
void tst_QSGGridView::header()
@@ -2190,18 +2454,17 @@ void tst_QSGGridView::header()
QFETCH(QPointF, initialContentPos);
QFETCH(QPointF, changedContentPos);
QFETCH(QPointF, firstDelegatePos);
-
- QSGView *canvas = createView();
+ QFETCH(QPointF, resizeContentPos);
TestModel model;
for (int i = 0; i < 30; i++)
model.addItem("Item" + QString::number(i), "");
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
+ QSGView *canvas = createView();
+ canvas->rootContext()->setContextProperty("testModel", &model);
+ canvas->rootContext()->setContextProperty("initialViewWidth", 240);
+ canvas->rootContext()->setContextProperty("initialViewHeight", 320);
canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header.qml"));
- qApp->processEvents();
QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
QTRY_VERIFY(gridview != 0);
@@ -2252,6 +2515,31 @@ void tst_QSGGridView::header()
QVERIFY(item);
QCOMPARE(item->pos(), firstDelegatePos);
+ header->setHeight(10);
+ header->setWidth(40);
+ QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
+
+ delete canvas;
+
+
+ // QTBUG-21207 header should become visible if view resizes from initial empty size
+
+ canvas = createView();
+ canvas->rootContext()->setContextProperty("testModel", &model);
+ canvas->rootContext()->setContextProperty("initialViewWidth", 240);
+ canvas->rootContext()->setContextProperty("initialViewHeight", 320);
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header.qml"));
+
+ gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+ gridview->setFlow(flow);
+ gridview->setLayoutDirection(layoutDirection);
+
+ gridview->setWidth(240);
+ gridview->setHeight(320);
+ QTRY_COMPARE(gridview->headerItem()->pos(), initialHeaderPos);
+ QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
+
delete canvas;
}
@@ -2264,9 +2552,10 @@ void tst_QSGGridView::header_data()
QTest::addColumn<QPointF>("initialContentPos");
QTest::addColumn<QPointF>("changedContentPos");
QTest::addColumn<QPointF>("firstDelegatePos");
+ QTest::addColumn<QPointF>("resizeContentPos");
// header1 = 100 x 30
- // header2 = 100 x 20
+ // header2 = 50 x 20
// cells = 80 x 60
// view width = 240
@@ -2276,7 +2565,8 @@ void tst_QSGGridView::header_data()
<< QPointF(0, -20)
<< QPointF(0, -30)
<< QPointF(0, -20)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(0, -10);
// header above items, top right
QTest::newRow("flow left to right, layout right to left") << QSGGridView::LeftToRight << Qt::RightToLeft
@@ -2284,7 +2574,8 @@ void tst_QSGGridView::header_data()
<< QPointF((240 - 100) + 50, -20) // 50 = width diff between old and new headers
<< QPointF(0, -30)
<< QPointF(0, -20)
- << QPointF(160, 0);
+ << QPointF(160, 0)
+ << QPointF(0, -10);
// header to left of items
QTest::newRow("flow top to bottom, layout left to right") << QSGGridView::TopToBottom << Qt::LeftToRight
@@ -2292,7 +2583,8 @@ void tst_QSGGridView::header_data()
<< QPointF(-50, 0)
<< QPointF(-100, 0)
<< QPointF(-50, 0)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(-40, 0);
// header to right of items
QTest::newRow("flow top to bottom, layout right to left") << QSGGridView::TopToBottom << Qt::RightToLeft
@@ -2300,7 +2592,8 @@ void tst_QSGGridView::header_data()
<< QPointF(0, 0)
<< QPointF(-(240 - 100), 0)
<< QPointF(-(240 - 50), 0)
- << QPointF(-80, 0);
+ << QPointF(-80, 0)
+ << QPointF(-(240 - 40), 0);
}
void tst_QSGGridView::indexAt()
@@ -2372,10 +2665,11 @@ void tst_QSGGridView::onAdd()
items << qMakePair(QString("value %1").arg(i), QString::number(i));
model.addItems(items);
+ QTRY_COMPARE(model.count(), qobject_cast<QSGGridView*>(canvas->rootObject())->count());
qApp->processEvents();
QVariantList result = object->property("addedDelegates").toList();
- QCOMPARE(result.count(), items.count());
+ QTRY_COMPARE(result.count(), items.count());
for (int i=0; i<items.count(); i++)
QCOMPARE(result[i].toString(), items[i].first);
@@ -2420,10 +2714,8 @@ void tst_QSGGridView::onRemove()
canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml"));
QObject *object = canvas->rootObject();
- qApp->processEvents();
-
model.removeItems(indexToRemove, removeCount);
- qApp->processEvents();
+ QTRY_COMPARE(model.count(), qobject_cast<QSGGridView*>(canvas->rootObject())->count());
QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
delete canvas;
diff --git a/tests/auto/declarative/qsglistview/data/header.qml b/tests/auto/declarative/qsglistview/data/header.qml
index b073146582..bf70310630 100644
--- a/tests/auto/declarative/qsglistview/data/header.qml
+++ b/tests/auto/declarative/qsglistview/data/header.qml
@@ -24,8 +24,8 @@ Rectangle {
id: list
objectName: "list"
focus: true
- width: 240
- height: 320
+ width: initialViewWidth
+ height: initialViewHeight
snapMode: ListView.SnapToItem
model: testModel
delegate: myDelegate
diff --git a/tests/auto/declarative/qsglistview/tst_qsglistview.cpp b/tests/auto/declarative/qsglistview/tst_qsglistview.cpp
index 2b81f7cfd9..5a6fb35ab9 100644
--- a/tests/auto/declarative/qsglistview/tst_qsglistview.cpp
+++ b/tests/auto/declarative/qsglistview/tst_qsglistview.cpp
@@ -51,6 +51,7 @@
#include <QtDeclarative/private/qsgvisualitemmodel_p.h>
#include <QtDeclarative/private/qdeclarativelistmodel_p.h>
#include <QtDeclarative/private/qlistmodelinterface_p.h>
+#include <QtDeclarative/private/qdeclarativechangeset_p.h>
#include "../../../shared/util.h"
#include "incrementalmodel.h"
#include <QtOpenGL/QGLShaderProgram>
@@ -90,6 +91,9 @@ private slots:
void qAbstractItemModel_moved();
void qAbstractItemModel_moved_data();
+ void multipleChanges();
+ void multipleChanges_data();
+
void qListModelInterface_clear();
void qAbstractItemModel_clear();
@@ -291,6 +295,12 @@ public:
emit itemsInserted(index, 1);
}
+ void insertItems(int index, const QList<QPair<QString, QString> > &items) {
+ for (int i=0; i<items.count(); i++)
+ list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
+ emit itemsInserted(index, items.count());
+ }
+
void removeItem(int index) {
list.removeAt(index);
emit itemsRemoved(index, 1);
@@ -375,6 +385,13 @@ public:
emit endInsertRows();
}
+ void insertItems(int index, const QList<QPair<QString, QString> > &items) {
+ emit beginInsertRows(QModelIndex(), index, index+items.count()-1);
+ for (int i=0; i<items.count(); i++)
+ list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
+ emit endInsertRows();
+ }
+
void removeItem(int index) {
emit beginRemoveRows(QModelIndex(), index, index);
list.removeAt(index);
@@ -541,6 +558,7 @@ template <class T>
void tst_QSGListView::inserted()
{
QSGView *canvas = createView();
+ canvas->show();
T model;
model.addItem("Fred", "12345");
@@ -564,6 +582,7 @@ void tst_QSGListView::inserted()
model.insertItem(1, "Will", "9876");
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
@@ -581,7 +600,7 @@ void tst_QSGListView::inserted()
model.insertItem(0, "Foo", "1111"); // zero index, and current item
- QCOMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
name = findItem<QSGText>(contentItem, "textName", 0);
@@ -622,6 +641,8 @@ void tst_QSGListView::inserted()
// QTBUG-19675
model.clear();
model.insertItem(0, "Hello", "1234");
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", 0);
QVERIFY(item);
QCOMPARE(item->y(), 0.);
@@ -657,7 +678,7 @@ void tst_QSGListView::removed(bool animated)
QTRY_VERIFY(contentItem != 0);
model.removeItem(1);
- QCOMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
QTRY_VERIFY(name != 0);
@@ -677,8 +698,7 @@ void tst_QSGListView::removed(bool animated)
// Remove first item (which is the current item);
model.removeItem(0); // post: top item starts at 20
-
- QTest::qWait(300);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
name = findItem<QSGText>(contentItem, "textName", 0);
QTRY_VERIFY(name != 0);
@@ -698,7 +718,7 @@ void tst_QSGListView::removed(bool animated)
// Remove items not visible
model.removeItem(18);
- qApp->processEvents();
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
// Confirm items positioned correctly
itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
@@ -714,7 +734,7 @@ void tst_QSGListView::removed(bool animated)
listview->setCurrentIndex(10);
model.removeItem(1); // post: top item will be at 40
- qApp->processEvents();
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
// Confirm items positioned correctly
for (int i = 2; i < 18; ++i) {
@@ -766,7 +786,7 @@ void tst_QSGListView::removed(bool animated)
// remove all visible items
model.removeItems(1, 18);
- QTest::qWait(300);
+ QTRY_COMPARE(listview->count() , model.count());
// Confirm items positioned correctly
itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
@@ -778,10 +798,13 @@ void tst_QSGListView::removed(bool animated)
}
model.removeItems(1, 17);
-// QTest::qWait(300);
+ QTRY_COMPARE(listview->count() , model.count());
model.removeItems(2, 1);
+ QTRY_COMPARE(listview->count() , model.count());
+
model.addItem("New", "1");
+ QTRY_COMPARE(listview->count() , model.count());
QTRY_VERIFY(name = findItem<QSGText>(contentItem, "textName", model.count()-1));
QCOMPARE(name->text(), QString("New"));
@@ -886,12 +909,23 @@ void tst_QSGListView::moved()
listview->setContentY(contentY);
model.moveItems(from, to, count);
- qApp->processEvents();
+
+ // wait for items to move
+ QTest::qWait(300);
+
+ QList<QSGItem*> items = findItems<QSGItem>(contentItem, "wrapper");
+ int firstVisibleIndex = -1;
+ for (int i=0; i<items.count(); i++) {
+ if (items[i]->y() >= contentY) {
+ QDeclarativeExpression e(qmlContext(items[i]), items[i], "index");
+ firstVisibleIndex = e.evaluate().toInt();
+ break;
+ }
+ }
+ QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
// Confirm items positioned correctly and indexes correct
- int firstVisibleIndex = qCeil(contentY / 20.0);
int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
-
for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
if (i >= firstVisibleIndex + 16) // index has moved out of view
continue;
@@ -934,12 +968,12 @@ void tst_QSGListView::moved_data()
QTest::newRow("move 1 forwards, from non-visible -> visible")
<< 80.0 // show 4-19
<< 1 << 18 << 1
- << 20.0;
+ << 20.0; // removed 1 item above the first visible, so item 0 should drop down by 1 to minimize movement
QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
<< 80.0 // show 4-19
<< 0 << 4 << 1
- << 20.0;
+ << 20.0; // first item has moved to below item4, everything drops down by size of 1 item
QTest::newRow("move 1 forwards, from visible -> non-visible")
<< 0.0
@@ -957,6 +991,11 @@ void tst_QSGListView::moved_data()
<< 4 << 1 << 1
<< 0.0;
+ QTest::newRow("move 1 backwards, within visible items (to first index)")
+ << 0.0
+ << 4 << 0 << 1
+ << 0.0;
+
QTest::newRow("move 1 backwards, from non-visible -> visible")
<< 0.0
<< 20 << 4 << 1
@@ -970,12 +1009,12 @@ void tst_QSGListView::moved_data()
QTest::newRow("move 1 backwards, from visible -> non-visible")
<< 80.0 // show 4-19
<< 16 << 1 << 1
- << 20.0 * 15; // this results in a forward movement that removes 15 items
+ << -20.0; // to minimize movement, item 0 moves to -20, and other items do not move
QTest::newRow("move 1 backwards, from visible -> non-visible (move first item)")
<< 80.0 // show 4-19
<< 16 << 0 << 1
- << 20.0 * 16; // everything should move to after item 16
+ << -20.0; // to minimize movement, item 16 (now at 0) moves to -20, and other items do not move
QTest::newRow("move multiple forwards, within visible items")
@@ -1022,12 +1061,248 @@ void tst_QSGListView::moved_data()
QTest::newRow("move multiple backwards, from visible -> non-visible")
<< 80.0 // show 4-19
<< 16 << 1 << 3
- << 20.0 * 15; // this results in a forward movement that removes 15 items
+ << -20.0 * 3; // to minimize movement, 0 moves by -60, and other items do not move
QTest::newRow("move multiple backwards, from visible -> non-visible (move first item)")
<< 80.0 // show 4-19
<< 16 << 0 << 3
- << 20.0 * 16;
+ << -20.0 * 3; // to minimize movement, 16,17,18 move to above item 0, and other items do not move
+}
+
+
+struct ListChange {
+ enum { Inserted, Removed, Moved, SetCurrent } type;
+ int index;
+ int count;
+ int to; // Move
+
+ static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1 }; return c; }
+ static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1 }; return c; }
+ static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to }; return c; }
+ static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1 }; return c; }
+};
+Q_DECLARE_METATYPE(QList<ListChange>)
+
+void tst_QSGListView::multipleChanges()
+{
+ QFETCH(int, startCount);
+ QFETCH(QList<ListChange>, changes);
+ QFETCH(int, newCount);
+ QFETCH(int, newCurrentIndex);
+
+ QSGView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < startCount; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", testObject);
+
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
+ qApp->processEvents();
+
+ QSGListView *listview = findItem<QSGListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ for (int i=0; i<changes.count(); i++) {
+ switch (changes[i].type) {
+ case ListChange::Inserted:
+ {
+ QList<QPair<QString, QString> > items;
+ for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
+ items << qMakePair(QString("new item " + j), QString::number(j));
+ model.insertItems(changes[i].index, items);
+ break;
+ }
+ case ListChange::Removed:
+ model.removeItems(changes[i].index, changes[i].count);
+ break;
+ case ListChange::Moved:
+ model.moveItems(changes[i].index, changes[i].to, changes[i].count);
+ break;
+ case ListChange::SetCurrent:
+ listview->setCurrentIndex(changes[i].index);
+ break;
+ }
+ }
+
+ QTRY_COMPARE(listview->count(), newCount);
+ QCOMPARE(listview->count(), model.count());
+ QTRY_COMPARE(listview->currentIndex(), newCurrentIndex);
+
+ QSGText *name;
+ QSGText *number;
+ QSGItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+ int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
+ for (int i=0; i < model.count() && i < itemCount; ++i) {
+ QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ name = findItem<QSGText>(contentItem, "textName", i);
+ QVERIFY(name != 0);
+ QTRY_COMPARE(name->text(), model.name(i));
+ number = findItem<QSGText>(contentItem, "textNumber", i);
+ QVERIFY(number != 0);
+ QTRY_COMPARE(number->text(), model.number(i));
+ }
+
+ delete testObject;
+ delete canvas;
+}
+
+void tst_QSGListView::multipleChanges_data()
+{
+ QTest::addColumn<int>("startCount");
+ QTest::addColumn<QList<ListChange> >("changes");
+ QTest::addColumn<int>("newCount");
+ QTest::addColumn<int>("newCurrentIndex");
+
+ QList<ListChange> changes;
+
+ for (int i=1; i<30; i++)
+ changes << ListChange::remove(0);
+ QTest::newRow("remove all but 1, first->last") << 30 << changes << 1 << 0;
+
+ changes << ListChange::remove(0);
+ QTest::newRow("remove all") << 30 << changes << 0 << -1;
+
+ changes.clear();
+ changes << ListChange::setCurrent(29);
+ for (int i=29; i>0; i--)
+ changes << ListChange::remove(i);
+ QTest::newRow("remove last (current) -> first") << 30 << changes << 1 << 0;
+
+ QTest::newRow("remove then insert at 0") << 10 << (QList<ListChange>()
+ << ListChange::remove(0, 1)
+ << ListChange::insert(0, 1)
+ ) << 10 << 1;
+
+ QTest::newRow("remove then insert at non-zero index") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::remove(2, 1)
+ << ListChange::insert(2, 1)
+ ) << 10 << 3;
+
+ QTest::newRow("remove current then insert below it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::remove(1, 3)
+ << ListChange::insert(2, 2)
+ ) << 9 << 1;
+
+ QTest::newRow("remove current index then move it down") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::remove(1, 3)
+ << ListChange::move(1, 5, 1)
+ ) << 7 << 5;
+
+ QTest::newRow("remove current index then move it up") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::remove(4, 3)
+ << ListChange::move(4, 1, 1)
+ ) << 7 << 1;
+
+
+ QTest::newRow("insert multiple times") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 2)
+ << ListChange::insert(0, 4)
+ << ListChange::insert(0, 6)
+ ) << 12 << 10;
+
+ QTest::newRow("insert multiple times with current index changes") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 2)
+ << ListChange::insert(0, 4)
+ << ListChange::insert(0, 6)
+ << ListChange::setCurrent(3)
+ << ListChange::insert(3, 2)
+ ) << 14 << 5;
+
+ QTest::newRow("insert and remove all") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 30)
+ << ListChange::remove(0, 30)
+ ) << 0 << -1;
+
+ QTest::newRow("insert and remove current") << 30 << (QList<ListChange>()
+ << ListChange::insert(1)
+ << ListChange::setCurrent(1)
+ << ListChange::remove(1)
+ ) << 30 << 1;
+
+ QTest::newRow("insert before 0, then remove cross section of new and old items") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 10)
+ << ListChange::remove(5, 10)
+ ) << 10 << 5;
+
+ QTest::newRow("insert multiple, then move new items to end") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 3)
+ << ListChange::move(0, 10, 3)
+ ) << 13 << 0;
+
+ QTest::newRow("insert multiple, then move new and some old items to end") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 3)
+ << ListChange::move(0, 8, 5)
+ ) << 13 << 11;
+
+ QTest::newRow("insert multiple at end, then move new and some old items to start") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(9)
+ << ListChange::insert(10, 3)
+ << ListChange::move(8, 0, 5)
+ ) << 13 << 1;
+
+
+ QTest::newRow("move back and forth to same index") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::move(1, 2, 2)
+ << ListChange::move(2, 1, 2)
+ ) << 10 << 1;
+
+ QTest::newRow("move forwards then back") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::move(1, 2, 3)
+ << ListChange::move(3, 0, 5)
+ ) << 10 << 0;
+
+ QTest::newRow("move current, then remove it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 0, 1)
+ << ListChange::remove(0)
+ ) << 9 << 0;
+
+ QTest::newRow("move current, then insert before it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 0, 1)
+ << ListChange::insert(0)
+ ) << 11 << 1;
+
+ QTest::newRow("move multiple, then remove them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::move(5, 1, 3)
+ << ListChange::remove(1, 3)
+ ) << 7 << 1;
+
+ QTest::newRow("move multiple, then insert before them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 1, 3)
+ << ListChange::insert(1, 5)
+ ) << 15 << 6;
+
+ QTest::newRow("move multiple, then insert after them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(3)
+ << ListChange::move(0, 1, 2)
+ << ListChange::insert(3, 5)
+ ) << 15 << 8;
+
+
+ QTest::newRow("clear current") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 5)
+ << ListChange::setCurrent(-1)
+ << ListChange::remove(0, 5)
+ << ListChange::insert(0, 5)
+ ) << 5 << -1;
}
void tst_QSGListView::swapWithFirstItem()
@@ -1164,6 +1439,7 @@ void tst_QSGListView::enforceRange_withoutHighlight()
void tst_QSGListView::spacing()
{
QSGView *canvas = createView();
+ canvas->show();
TestModel model;
for (int i = 0; i < 30; i++)
@@ -1223,6 +1499,7 @@ void tst_QSGListView::spacing()
void tst_QSGListView::sections()
{
QSGView *canvas = createView();
+ canvas->show();
TestModel model;
for (int i = 0; i < 30; i++)
@@ -1254,6 +1531,7 @@ void tst_QSGListView::sections()
// Remove section boundary
model.removeItem(5);
+ QTRY_COMPARE(listview->count(), model.count());
// New section header created
QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", 5);
@@ -1261,6 +1539,7 @@ void tst_QSGListView::sections()
QTRY_COMPARE(item->height(), 40.0);
model.insertItem(3, "New Item", "0");
+ QTRY_COMPARE(listview->count(), model.count());
// Section header moved
item = findItem<QSGItem>(contentItem, "wrapper", 5);
@@ -1273,6 +1552,7 @@ void tst_QSGListView::sections()
// insert item which will become a section header
model.insertItem(6, "Replace header", "1");
+ QTRY_COMPARE(listview->count(), model.count());
item = findItem<QSGItem>(contentItem, "wrapper", 6);
QTRY_VERIFY(item);
@@ -1301,6 +1581,7 @@ void tst_QSGListView::sections()
// check that headers change when item changes
listview->setContentY(0);
model.modifyItem(0, "changed", "2");
+ QTest::qWait(300);
item = findItem<QSGItem>(contentItem, "wrapper", 1);
QTRY_VERIFY(item);
@@ -1312,6 +1593,7 @@ void tst_QSGListView::sections()
void tst_QSGListView::sectionsDelegate()
{
QSGView *canvas = createView();
+ canvas->show();
TestModel model;
for (int i = 0; i < 30; i++)
@@ -1350,6 +1632,7 @@ void tst_QSGListView::sectionsDelegate()
model.modifyItem(2, "Three", "aaa");
model.modifyItem(3, "Four", "aaa");
model.modifyItem(4, "Five", "aaa");
+ QTest::qWait(300);
for (int i = 0; i < 3; ++i) {
QSGItem *item = findItem<QSGItem>(contentItem,
@@ -1360,7 +1643,7 @@ void tst_QSGListView::sectionsDelegate()
// remove section boundary
model.removeItem(5);
- qApp->processEvents();
+ QTRY_COMPARE(listview->count(), model.count());
for (int i = 0; i < 3; ++i) {
QSGItem *item = findItem<QSGItem>(contentItem,
"sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
@@ -2175,18 +2458,17 @@ void tst_QSGListView::header()
QFETCH(QPointF, initialContentPos);
QFETCH(QPointF, changedHeaderPos);
QFETCH(QPointF, changedContentPos);
-
- QSGView *canvas = createView();
+ QFETCH(QPointF, resizeContentPos);
TestModel model;
for (int i = 0; i < 30; i++)
model.addItem("Item" + QString::number(i), "");
- QDeclarativeContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("testModel", &model);
-
+ QSGView *canvas = createView();
+ canvas->rootContext()->setContextProperty("testModel", &model);
+ canvas->rootContext()->setContextProperty("initialViewWidth", 240);
+ canvas->rootContext()->setContextProperty("initialViewHeight", 320);
canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header.qml"));
- qApp->processEvents();
QSGListView *listview = findItem<QSGListView>(canvas->rootObject(), "list");
QTRY_VERIFY(listview != 0);
@@ -2235,6 +2517,31 @@ void tst_QSGListView::header()
QCOMPARE(item->pos(), firstDelegatePos);
delete canvas;
+
+
+ // QTBUG-21207 header should become visible if view resizes from initial empty size
+
+ canvas = createView();
+ canvas->rootContext()->setContextProperty("testModel", &model);
+ canvas->rootContext()->setContextProperty("initialViewWidth", 0.0);
+ canvas->rootContext()->setContextProperty("initialViewHeight", 0.0);
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header.qml"));
+
+ listview = findItem<QSGListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+ listview->setOrientation(orientation);
+ listview->setLayoutDirection(layoutDirection);
+
+ listview->setWidth(240);
+ listview->setHeight(320);
+ QTRY_COMPARE(listview->headerItem()->pos(), initialHeaderPos);
+ QCOMPARE(QPointF(listview->contentX(), listview->contentY()), initialContentPos);
+
+ header->setHeight(10);
+ header->setWidth(40);
+ QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), resizeContentPos);
+
+ delete canvas;
}
void tst_QSGListView::header_data()
@@ -2246,6 +2553,7 @@ void tst_QSGListView::header_data()
QTest::addColumn<QPointF>("initialContentPos");
QTest::addColumn<QPointF>("changedContentPos");
QTest::addColumn<QPointF>("firstDelegatePos");
+ QTest::addColumn<QPointF>("resizeContentPos");
// header1 = 100 x 30
// header2 = 50 x 20
@@ -2258,7 +2566,8 @@ void tst_QSGListView::header_data()
<< QPointF(0, -20)
<< QPointF(0, -30)
<< QPointF(0, -20)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(0, -10);
// header above items, top right
QTest::newRow("vertical, layout right to left") << QSGListView::Vertical << Qt::RightToLeft
@@ -2266,7 +2575,8 @@ void tst_QSGListView::header_data()
<< QPointF(0, -20)
<< QPointF(0, -30)
<< QPointF(0, -20)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(0, -10);
// header to left of items
QTest::newRow("horizontal, layout left to right") << QSGListView::Horizontal << Qt::LeftToRight
@@ -2274,7 +2584,8 @@ void tst_QSGListView::header_data()
<< QPointF(-50, 0)
<< QPointF(-100, 0)
<< QPointF(-50, 0)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(-40, 0);
// header to right of items
QTest::newRow("horizontal, layout right to left") << QSGListView::Horizontal << Qt::RightToLeft
@@ -2282,7 +2593,8 @@ void tst_QSGListView::header_data()
<< QPointF(0, 0)
<< QPointF(-240 + 100, 0)
<< QPointF(-240 + 50, 0)
- << QPointF(-240, 0);
+ << QPointF(-240, 0)
+ << QPointF(-240 + 40, 0);
}
void tst_QSGListView::header_delayItemCreation()
@@ -2321,6 +2633,7 @@ void tst_QSGListView::footer()
QFETCH(QPointF, initialContentPos);
QFETCH(QPointF, changedFooterPos);
QFETCH(QPointF, changedContentPos);
+ QFETCH(QPointF, resizeContentPos);
QSGView *canvas = createView();
@@ -2405,6 +2718,11 @@ void tst_QSGListView::footer()
QVERIFY(item);
QCOMPARE(item->pos(), firstDelegatePos);
+ listview->positionViewAtEnd();
+ footer->setHeight(10);
+ footer->setWidth(40);
+ QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), resizeContentPos);
+
delete canvas;
}
@@ -2417,11 +2735,13 @@ void tst_QSGListView::footer_data()
QTest::addColumn<QPointF>("initialContentPos");
QTest::addColumn<QPointF>("changedContentPos");
QTest::addColumn<QPointF>("firstDelegatePos");
+ QTest::addColumn<QPointF>("resizeContentPos");
// footer1 = 100 x 30
- // footer2 = 100 x 20
+ // footer2 = 50 x 20
// delegates = 40 x 20
// view width = 240
+ // view height = 320
// footer below items, bottom left
QTest::newRow("vertical, layout left to right") << QSGListView::Vertical << Qt::LeftToRight
@@ -2429,7 +2749,8 @@ void tst_QSGListView::footer_data()
<< QPointF(0, 30 * 20) // added 30 items
<< QPointF(0, 0)
<< QPointF(0, 0)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(0, 30 * 20 - 320 + 10);
// footer below items, bottom right
QTest::newRow("vertical, layout right to left") << QSGListView::Vertical << Qt::RightToLeft
@@ -2437,7 +2758,8 @@ void tst_QSGListView::footer_data()
<< QPointF(0, 30 * 20)
<< QPointF(0, 0)
<< QPointF(0, 0)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(0, 30 * 20 - 320 + 10);
// footer to right of items
QTest::newRow("horizontal, layout left to right") << QSGListView::Horizontal << Qt::LeftToRight
@@ -2445,7 +2767,8 @@ void tst_QSGListView::footer_data()
<< QPointF(40 * 30, 0)
<< QPointF(0, 0)
<< QPointF(0, 0)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(40 * 30 - 240 + 40, 0);
// footer to left of items
QTest::newRow("horizontal, layout right to left") << QSGListView::Horizontal << Qt::RightToLeft
@@ -2453,7 +2776,8 @@ void tst_QSGListView::footer_data()
<< QPointF(-(40 * 30) - 50, 0) // 50 = new footer width
<< QPointF(-240, 0)
<< QPointF(-240, 0)
- << QPointF(-40, 0);
+ << QPointF(-40, 0)
+ << QPointF(-(40 * 30) - 40, 0);
}
class LVAccessor : public QSGListView
@@ -2492,8 +2816,8 @@ void tst_QSGListView::headerFooter()
QVERIFY(footer);
QCOMPARE(footer->y(), 0.);
- QVERIFY(static_cast<LVAccessor*>(listview)->minY() == 0);
- QVERIFY(static_cast<LVAccessor*>(listview)->maxY() == 0);
+ QCOMPARE(static_cast<LVAccessor*>(listview)->minY(), header->height());
+ QCOMPARE(static_cast<LVAccessor*>(listview)->maxY(), header->height());
delete canvas;
}
@@ -2523,8 +2847,8 @@ void tst_QSGListView::headerFooter()
QVERIFY(footer);
QCOMPARE(footer->x(), 0.);
- QVERIFY(static_cast<LVAccessor*>(listview)->minX() == 0);
- QVERIFY(static_cast<LVAccessor*>(listview)->maxX() == 0);
+ QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), header->width());
+ QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), header->width());
delete canvas;
}
@@ -2555,8 +2879,8 @@ void tst_QSGListView::headerFooter()
QVERIFY(footer);
QCOMPARE(footer->x(), -footer->width());
- QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), 240.);
- QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), 240.);
+ QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), 240. - header->width());
+ QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), 240. - header->width());
delete canvas;
}
@@ -2691,6 +3015,7 @@ void tst_QSGListView::resizeDelegate()
listview->setCurrentIndex(25);
listview->setContentY(0);
+ QTest::qWait(300);
for (int i = 0; i < 16; ++i) {
QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
@@ -2902,8 +3227,7 @@ void tst_QSGListView::onAdd()
for (int i=0; i<itemsToAdd; i++)
items << qMakePair(QString("value %1").arg(i), QString::number(i));
model.addItems(items);
-
- qApp->processEvents();
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
QVariantList result = object->property("addedDelegates").toList();
QCOMPARE(result.count(), items.count());
@@ -2949,10 +3273,9 @@ void tst_QSGListView::onRemove()
canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml"));
QObject *object = canvas->rootObject();
- qApp->processEvents();
-
model.removeItems(indexToRemove, removeCount);
- qApp->processEvents();
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+
QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
delete canvas;
diff --git a/tests/auto/declarative/qsgtextedit/data/horizontalAlignment_RightToLeft.qml b/tests/auto/declarative/qsgtextedit/data/horizontalAlignment_RightToLeft.qml
index 74592fed7f..4cd92367ec 100644
--- a/tests/auto/declarative/qsgtextedit/data/horizontalAlignment_RightToLeft.qml
+++ b/tests/auto/declarative/qsgtextedit/data/horizontalAlignment_RightToLeft.qml
@@ -18,6 +18,7 @@ Rectangle {
objectName: "text"
anchors.fill: parent
text: top.text
+ focus: true
}
}
}
diff --git a/tests/auto/declarative/qsgtextedit/data/mouseselection_false_words.qml b/tests/auto/declarative/qsgtextedit/data/mouseselection_false_words.qml
index ac32f4ced7..86aea46a85 100644
--- a/tests/auto/declarative/qsgtextedit/data/mouseselection_false_words.qml
+++ b/tests/auto/declarative/qsgtextedit/data/mouseselection_false_words.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
TextEdit {
focus: true
- text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ text: "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"
selectByMouse: false
+ mouseSelectionMode: TextEdit.SelectWords
}
diff --git a/tests/auto/declarative/qsgtextedit/data/mouseselection_true_words.qml b/tests/auto/declarative/qsgtextedit/data/mouseselection_true_words.qml
index 7c7cb0b6fc..c356999220 100644
--- a/tests/auto/declarative/qsgtextedit/data/mouseselection_true_words.qml
+++ b/tests/auto/declarative/qsgtextedit/data/mouseselection_true_words.qml
@@ -2,6 +2,7 @@ import QtQuick 2.0
TextEdit {
focus: true
- text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ text: "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"
selectByMouse: true
+ mouseSelectionMode: TextEdit.SelectWords
}
diff --git a/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp b/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp
index 79ff8ea3ec..7c0f097358 100644
--- a/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp
+++ b/tests/auto/declarative/qsgtextedit/tst_qsgtextedit.cpp
@@ -489,6 +489,8 @@ void tst_qsgtextedit::hAlign_RightToLeft()
QVERIFY(textEdit != 0);
canvas.show();
+ const QString rtlText = textEdit->text();
+
// implicit alignment should follow the reading direction of text
QCOMPARE(textEdit->hAlign(), QSGTextEdit::AlignRight);
QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
@@ -565,6 +567,16 @@ void tst_qsgtextedit::hAlign_RightToLeft()
QCOMPARE(textEdit->hAlign(), QSGTextEdit::AlignLeft);
QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+ QApplication::setActiveWindow(&canvas);
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&canvas));
+
+ textEdit->setText(QString());
+ { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(&canvas, &ev); }
+ QCOMPARE(textEdit->hAlign(), QSGTextEdit::AlignRight);
+ { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(&canvas, &ev); }
+ QCOMPARE(textEdit->hAlign(), QSGTextEdit::AlignLeft);
+
#ifndef Q_OS_MAC // QTBUG-18040
// empty text with implicit alignment follows the system locale-based
// keyboard input direction from QApplication::keyboardInputDirection
@@ -1336,20 +1348,32 @@ void tst_qsgtextedit::moveCursorSelectionSequence()
void tst_qsgtextedit::mouseSelection_data()
{
QTest::addColumn<QString>("qmlfile");
- QTest::addColumn<bool>("expectSelection");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("to");
+ QTest::addColumn<QString>("selectedText");
// import installed
- QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << true;
- QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << false;
- QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << false;
- QTest::newRow("on word selection") << SRCDIR "/data/mouseselection_true_words.qml" << true;
- QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << false;
+ QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << 4 << 9 << "45678";
+ QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << 4 << 9 << QString();
+ QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << 4 << 9 << QString();
+ QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << 4 << 9 << QString();
+ QTest::newRow("on word selection (4,9)") << SRCDIR "/data/mouseselection_true_words.qml" << 4 << 9 << "0123456789";
+ QTest::newRow("on word selection (2,13)") << SRCDIR "/data/mouseselection_true_words.qml" << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (2,30)") << SRCDIR "/data/mouseselection_true_words.qml" << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (9,13)") << SRCDIR "/data/mouseselection_true_words.qml" << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (9,30)") << SRCDIR "/data/mouseselection_true_words.qml" << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (13,2)") << SRCDIR "/data/mouseselection_true_words.qml" << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (20,2)") << SRCDIR "/data/mouseselection_true_words.qml" << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (12,9)") << SRCDIR "/data/mouseselection_true_words.qml" << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (30,9)") << SRCDIR "/data/mouseselection_true_words.qml" << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
void tst_qsgtextedit::mouseSelection()
{
QFETCH(QString, qmlfile);
- QFETCH(bool, expectSelection);
+ QFETCH(int, from);
+ QFETCH(int, to);
+ QFETCH(QString, selectedText);
QSGView canvas(QUrl::fromLocalFile(qmlfile));
@@ -1363,19 +1387,20 @@ void tst_qsgtextedit::mouseSelection()
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, Qt::LeftButton, 0, QPoint(x1,y));
- //QTest::mouseMove(canvas, QPoint(x2,y)); // doesn't work
- QMouseEvent mv(QEvent::MouseMove, QPoint(x2,y), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint();
+ QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint();
+ QTest::mousePress(&canvas, Qt::LeftButton, 0, p1);
+ //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work
+ QMouseEvent mv(QEvent::MouseMove, p2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
QApplication::sendEvent(&canvas, &mv);
- QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
- QString str = textEditObject->selectedText();
- if (expectSelection)
- QVERIFY(str.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform)
- else
- QVERIFY(str.isEmpty());
+ QTest::mouseRelease(&canvas, Qt::LeftButton, 0, p2);
+ QCOMPARE(textEditObject->selectedText(), selectedText);
+
+ // Clicking and shift to clicking between the same points should select the same text.
+ textEditObject->setCursorPosition(0);
+ QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, p1);
+ QTest::mouseClick(&canvas, Qt::LeftButton, Qt::ShiftModifier, p2);
+ QCOMPARE(textEditObject->selectedText(), selectedText);
}
void tst_qsgtextedit::dragMouseSelection()
@@ -1569,6 +1594,43 @@ void tst_qsgtextedit::cursorDelegate()
QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
}
+ // Clear preedit text;
+ QInputMethodEvent event;
+ QApplication::sendEvent(&view, &event);
+
+
+ // Test delegate gets moved on mouse press.
+ textEditObject->setSelectByMouse(true);
+ textEditObject->setCursorPosition(0);
+ const QPoint point1 = textEditObject->positionToRectangle(5).center().toPoint();
+ QTest::mouseClick(&view, Qt::LeftButton, 0, point1);
+ QVERIFY(textEditObject->cursorPosition() != 0);
+ QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+
+ // Test delegate gets moved on mouse drag
+ textEditObject->setCursorPosition(0);
+ const QPoint point2 = textEditObject->positionToRectangle(10).center().toPoint();
+ QTest::mousePress(&view, Qt::LeftButton, 0, point1);
+ QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(&view, &mv);
+ QTest::mouseRelease(&view, Qt::LeftButton, 0, point2);
+ QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+
+ textEditObject->setReadOnly(true);
+ textEditObject->setCursorPosition(0);
+ QTest::mouseClick(&view, Qt::LeftButton, 0, textEditObject->positionToRectangle(5).center().toPoint());
+ QVERIFY(textEditObject->cursorPosition() != 0);
+ QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+
+ textEditObject->setCursorPosition(0);
+ QTest::mouseClick(&view, Qt::LeftButton, 0, textEditObject->positionToRectangle(5).center().toPoint());
+ QVERIFY(textEditObject->cursorPosition() != 0);
+ QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+
textEditObject->setCursorPosition(0);
QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
diff --git a/tests/auto/declarative/qsgtextinput/data/horizontalAlignment_RightToLeft.qml b/tests/auto/declarative/qsgtextinput/data/horizontalAlignment_RightToLeft.qml
index 15fbabe28c..5f88025536 100644
--- a/tests/auto/declarative/qsgtextinput/data/horizontalAlignment_RightToLeft.qml
+++ b/tests/auto/declarative/qsgtextinput/data/horizontalAlignment_RightToLeft.qml
@@ -18,6 +18,7 @@ Rectangle {
objectName: "text"
anchors.fill: parent
text: top.text
+ focus: true
}
}
}
diff --git a/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp b/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp
index 7da6ee23e8..483fa74c06 100644
--- a/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp
+++ b/tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp
@@ -55,6 +55,8 @@
#include <QtOpenGL/QGLShaderProgram>
#include <math.h>
+#include "qplatformdefs.h"
+
#ifdef Q_OS_SYMBIAN
// In Symbian OS test data is located in applications private dir
#define SRCDIR "."
@@ -132,6 +134,9 @@ private slots:
void focusOutClearSelection();
void echoMode();
+#ifdef QT_GUI_PASSWORD_ECHO_DELAY
+ void passwordEchoDelay();
+#endif
void geometrySignals();
void testQtQuick11Attributes();
void testQtQuick11Attributes_data();
@@ -1081,6 +1086,8 @@ void tst_qsgtextinput::horizontalAlignment_RightToLeft()
QVERIFY(textInput != 0);
canvas.show();
+ const QString rtlText = textInput->text();
+
QSGTextInputPrivate *textInputPrivate = QSGTextInputPrivate::get(textInput);
QVERIFY(textInputPrivate != 0);
QVERIFY(-textInputPrivate->hscroll > canvas.width()/2);
@@ -1145,6 +1152,17 @@ void tst_qsgtextinput::horizontalAlignment_RightToLeft()
QCOMPARE(textInput->hAlign(), QSGTextInput::AlignLeft);
QVERIFY(-textInputPrivate->hscroll < canvas.width()/2);
+ QApplication::setActiveWindow(&canvas);
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&canvas));
+
+ // If there is no commited text, the preedit text should determine the alignment.
+ textInput->setText(QString());
+ { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(&canvas, &ev); }
+ QCOMPARE(textInput->hAlign(), QSGTextInput::AlignRight);
+ { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(&canvas, &ev); }
+ QCOMPARE(textInput->hAlign(), QSGTextInput::AlignLeft);
+
#ifndef Q_OS_MAC // QTBUG-18040
// empty text with implicit alignment follows the system locale-based
// keyboard input direction from QApplication::keyboardInputDirection
@@ -1937,6 +1955,59 @@ void tst_qsgtextinput::echoMode()
QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
}
+#ifdef QT_GUI_PASSWORD_ECHO_DELAY
+void tst_qdeclarativetextinput::passwordEchoDelay()
+{
+ QSGView canvas(QUrl::fromLocalFile(SRCDIR "/data/echoMode.qml"));
+ canvas.show();
+ canvas.setFocus();
+ QApplication::setActiveWindow(&canvas);
+ QTest::qWaitForWindowShown(&canvas);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&canvas));
+
+ QVERIFY(canvas.rootObject() != 0);
+
+ QSGTextInput *input = qobject_cast<QSGTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+
+ QChar fillChar = QLatin1Char('*');
+
+ input->setEchoMode(QDeclarativeTextInput::Password);
+ QCOMPARE(input->displayText(), QString(8, fillChar));
+ input->setText(QString());
+ QCOMPARE(input->displayText(), QString());
+
+ QTest::keyPress(&canvas, '0');
+ QTest::keyPress(&canvas, '1');
+ QTest::keyPress(&canvas, '2');
+ QCOMPARE(input->displayText(), QString(2, fillChar) + QLatin1Char('2'));
+ QTest::keyPress(&canvas, '3');
+ QTest::keyPress(&canvas, '4');
+ QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
+ QTest::keyPress(&canvas, Qt::Key_Backspace);
+ QCOMPARE(input->displayText(), QString(4, fillChar));
+ QTest::keyPress(&canvas, '4');
+ QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
+ QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
+ QTRY_COMPARE(input->displayText(), QString(5, fillChar));
+ QTest::keyPress(&canvas, '5');
+ QCOMPARE(input->displayText(), QString(5, fillChar) + QLatin1Char('5'));
+ input->setFocus(false);
+ QVERIFY(!input->hasFocus());
+ QCOMPARE(input->displayText(), QString(6, fillChar));
+ input->setFocus(true);
+ QTRY_VERIFY(input->hasFocus());
+ QCOMPARE(input->displayText(), QString(6, fillChar));
+ QTest::keyPress(&canvas, '6');
+ QCOMPARE(input->displayText(), QString(6, fillChar) + QLatin1Char('6'));
+
+ QInputMethodEvent ev;
+ ev.setCommitString(QLatin1String("7"));
+ QApplication::sendEvent(&canvas, &ev);
+ QCOMPARE(input->displayText(), QString(7, fillChar) + QLatin1Char('7'));
+}
+#endif
+
+
void tst_qsgtextinput::simulateKey(QSGView *view, int key)
{
QKeyEvent press(QKeyEvent::KeyPress, key, 0);
diff --git a/tests/auto/qmltest/tst_qmltest.cpp b/tests/auto/qmltest/tst_qmltest.cpp
index e1bad75b82..a1e8c039e4 100644
--- a/tests/auto/qmltest/tst_qmltest.cpp
+++ b/tests/auto/qmltest/tst_qmltest.cpp
@@ -40,4 +40,4 @@
****************************************************************************/
#include <QtQuickTest/quicktest.h>
-QUICK_TEST_MAIN(qmlauto)
+QUICK_TEST_MAIN(qmltest) \ No newline at end of file
diff --git a/tests/auto/qtquick1/examples/data/dummytest.qml b/tests/auto/qtquick1/examples/data/dummytest.qml
new file mode 100644
index 0000000000..b20e907f27
--- /dev/null
+++ b/tests/auto/qtquick1/examples/data/dummytest.qml
@@ -0,0 +1,6 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame { msec: 0 }
+ Frame { msec: 10 }
+}
diff --git a/tests/auto/qtquick1/examples/data/webbrowser/webbrowser.qml b/tests/auto/qtquick1/examples/data/webbrowser/webbrowser.qml
new file mode 100644
index 0000000000..d31787b939
--- /dev/null
+++ b/tests/auto/qtquick1/examples/data/webbrowser/webbrowser.qml
@@ -0,0 +1,6 @@
+import Qt.VisualTest 4.6
+
+VisualTest {
+ Frame { msec: 0 }
+ Frame { msec: 2000 }
+}
diff --git a/tests/auto/qtquick1/examples/examples.pro b/tests/auto/qtquick1/examples/examples.pro
new file mode 100644
index 0000000000..14756b9df2
--- /dev/null
+++ b/tests/auto/qtquick1/examples/examples.pro
@@ -0,0 +1,14 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative qtquick1
+macx:CONFIG -= app_bundle
+
+include(../../../../tools/qmlviewer/qml.pri)
+
+SOURCES += tst_examples.cpp
+DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+CONFIG += parallel_test
+
+QT += core-private gui-private declarative-private qtquick1-private
+
+qpa:CONFIG+=insignificant_test # QTBUG-20990, aborts
diff --git a/tests/auto/qtquick1/examples/tst_examples.cpp b/tests/auto/qtquick1/examples/tst_examples.cpp
new file mode 100644
index 0000000000..c2859dc5ef
--- /dev/null
+++ b/tests/auto/qtquick1/examples/tst_examples.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QLibraryInfo>
+#include <QDir>
+#include <QProcess>
+#include <QDebug>
+#include "qmlruntime.h"
+#include <QDeclarativeView>
+#include <QDeclarativeError>
+
+class tst_examples : public QObject
+{
+ Q_OBJECT
+public:
+ tst_examples();
+
+private slots:
+ void examples_data();
+ void examples();
+
+ void namingConvention();
+private:
+ QStringList excludedDirs;
+
+ void namingConvention(const QDir &);
+ QStringList findQmlFiles(const QDir &);
+};
+
+tst_examples::tst_examples()
+{
+ // Add directories you want excluded here
+
+#ifdef QT_NO_WEBKIT
+ excludedDirs << "examples/declarative/qtquick1/modelviews/webview";
+ excludedDirs << "examples/declarative/qtquick1/webbrowser";
+ excludedDirs << "doc/src/snippets/declarative/qtquick1/webview";
+ excludedDirs << "doc/src/snippets/qtquick1/qtquick1/webview";
+#endif
+
+#ifdef QT_NO_XMLPATTERNS
+ excludedDirs << "examples/declarative/qtquick1/xml/xmldata";
+ excludedDirs << "examples/declarative/qtquick1/twitter";
+ excludedDirs << "examples/declarative/qtquick1/flickr";
+ excludedDirs << "examples/declarative/qtquick1/photoviewer";
+#endif
+}
+
+/*
+This tests that the examples follow the naming convention required
+to have them tested by the examples() test.
+*/
+void tst_examples::namingConvention(const QDir &d)
+{
+ for (int ii = 0; ii < excludedDirs.count(); ++ii) {
+ QString s = excludedDirs.at(ii);
+ if (d.absolutePath().endsWith(s))
+ return;
+ }
+
+ QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
+ QDir::Files);
+
+ bool seenQml = !files.isEmpty();
+ bool seenLowercase = false;
+
+ foreach (const QString &file, files) {
+ if (file.at(0).isLower())
+ seenLowercase = true;
+ }
+
+ if (!seenQml) {
+ QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ QDir::NoSymLinks);
+ foreach (const QString &dir, dirs) {
+ QDir sub = d;
+ sub.cd(dir);
+ namingConvention(sub);
+ }
+ } else if (!seenLowercase) {
+ QFAIL(qPrintable(QString(
+ "Directory %1 violates naming convention; expected at least one qml file "
+ "starting with lower case, got: %2"
+ ).arg(d.absolutePath()).arg(files.join(","))));
+ }
+}
+
+void tst_examples::namingConvention()
+{
+ QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
+
+ namingConvention(QDir(examples));
+}
+
+QStringList tst_examples::findQmlFiles(const QDir &d)
+{
+ for (int ii = 0; ii < excludedDirs.count(); ++ii) {
+ QString s = excludedDirs.at(ii);
+ if (d.absolutePath().endsWith(s))
+ return QStringList();
+ }
+
+ QStringList rv;
+
+ QStringList cppfiles = d.entryList(QStringList() << QLatin1String("*.cpp"), QDir::Files);
+ if (cppfiles.isEmpty()) {
+ QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
+ QDir::Files);
+ foreach (const QString &file, files) {
+ if (file.at(0).isLower()) {
+ rv << d.absoluteFilePath(file);
+ }
+ }
+ }
+
+ QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ QDir::NoSymLinks);
+ foreach (const QString &dir, dirs) {
+ QDir sub = d;
+ sub.cd(dir);
+ rv << findQmlFiles(sub);
+ }
+
+ return rv;
+}
+
+/*
+This test runs all the examples in the declarative UI source tree and ensures
+that they start and exit cleanly.
+
+Examples are any .qml files under the examples/ directory that start
+with a lower case letter.
+*/
+static void silentErrorsMsgHandler(QtMsgType, const char *)
+{
+}
+
+
+void tst_examples::examples_data()
+{
+ QTest::addColumn<QString>("file");
+
+ QString examples = QLatin1String(SRCDIR) + "/../../../../examples/declarative/qtquick1";
+
+ QStringList files;
+ files << findQmlFiles(QDir(examples));
+
+ foreach (const QString &file, files)
+ QTest::newRow(qPrintable(file)) << file;
+}
+
+void tst_examples::examples()
+{
+ QFETCH(QString, file);
+
+ QDeclarativeViewer viewer;
+
+ QtMsgHandler old = qInstallMsgHandler(silentErrorsMsgHandler);
+ QVERIFY(viewer.open(file));
+ qInstallMsgHandler(old);
+
+ if (viewer.view()->status() == QDeclarativeView::Error)
+ qWarning() << viewer.view()->errors();
+
+ QCOMPARE(viewer.view()->status(), QDeclarativeView::Ready);
+ viewer.show();
+
+ QTest::qWaitForWindowShown(&viewer);
+}
+
+QTEST_MAIN(tst_examples)
+
+#include "tst_examples.moc"
diff --git a/tests/auto/qtquick1/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml b/tests/auto/qtquick1/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml
index 43ea8d8a12..6e739bf2bb 100644
--- a/tests/auto/qtquick1/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml
+++ b/tests/auto/qtquick1/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml
@@ -18,6 +18,7 @@ Rectangle {
objectName: "text"
anchors.fill: parent
text: top.text
+ focus: true
}
}
}
diff --git a/tests/auto/qtquick1/qdeclarativetextedit/data/mouseselection_false_words.qml b/tests/auto/qtquick1/qdeclarativetextedit/data/mouseselection_false_words.qml
index 22a9871306..f8d2e4e2f2 100644
--- a/tests/auto/qtquick1/qdeclarativetextedit/data/mouseselection_false_words.qml
+++ b/tests/auto/qtquick1/qdeclarativetextedit/data/mouseselection_false_words.qml
@@ -1,7 +1,8 @@
-import QtQuick 1.0
+import QtQuick 1.1
TextEdit {
focus: true
- text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ text: "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"
selectByMouse: false
+ mouseSelectionMode: TextEdit.SelectWords
}
diff --git a/tests/auto/qtquick1/qdeclarativetextedit/data/mouseselection_true_words.qml b/tests/auto/qtquick1/qdeclarativetextedit/data/mouseselection_true_words.qml
index d61da46f48..f58fd45837 100644
--- a/tests/auto/qtquick1/qdeclarativetextedit/data/mouseselection_true_words.qml
+++ b/tests/auto/qtquick1/qdeclarativetextedit/data/mouseselection_true_words.qml
@@ -1,7 +1,8 @@
-import QtQuick 1.0
+import QtQuick 1.1
TextEdit {
focus: true
- text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ text: "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"
selectByMouse: true
+ mouseSelectionMode: TextEdit.SelectWords
}
diff --git a/tests/auto/qtquick1/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/qtquick1/qdeclarativetextedit/tst_qdeclarativetextedit.cpp
index 3af539f5eb..bcad6377f3 100644
--- a/tests/auto/qtquick1/qdeclarativetextedit/tst_qdeclarativetextedit.cpp
+++ b/tests/auto/qtquick1/qdeclarativetextedit/tst_qdeclarativetextedit.cpp
@@ -454,6 +454,8 @@ void tst_qdeclarativetextedit::hAlign_RightToLeft()
QVERIFY(textEdit != 0);
canvas->show();
+ const QString rtlText = textEdit->text();
+
// implicit alignment should follow the reading direction of text
QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2);
@@ -530,6 +532,16 @@ void tst_qdeclarativetextedit::hAlign_RightToLeft()
QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignLeft);
QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2);
+ QApplication::setActiveWindow(canvas);
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
+
+ textEdit->setText(QString());
+ { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
+ QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignRight);
+ { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
+ QCOMPARE(textEdit->hAlign(), QDeclarative1TextEdit::AlignLeft);
+
#ifndef Q_OS_MAC // QTBUG-18040
// empty text with implicit alignment follows the system locale-based
// keyboard input direction from QApplication::keyboardInputDirection
@@ -1315,20 +1327,32 @@ void tst_qdeclarativetextedit::moveCursorSelectionSequence()
void tst_qdeclarativetextedit::mouseSelection_data()
{
QTest::addColumn<QString>("qmlfile");
- QTest::addColumn<bool>("expectSelection");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("to");
+ QTest::addColumn<QString>("selectedText");
// import installed
- QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << true;
- QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << false;
- QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << false;
- QTest::newRow("on word selection") << SRCDIR "/data/mouseselection_true_words.qml" << true;
- QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << false;
+ QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << 4 << 9 << "45678";
+ QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << 4 << 9 << QString();
+ QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << 4 << 9 << QString();
+ QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << 4 << 9 << QString();
+ QTest::newRow("on word selection (4,9)") << SRCDIR "/data/mouseselection_true_words.qml" << 4 << 9 << "0123456789";
+ QTest::newRow("on word selection (2,13)") << SRCDIR "/data/mouseselection_true_words.qml" << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (2,30)") << SRCDIR "/data/mouseselection_true_words.qml" << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (9,13)") << SRCDIR "/data/mouseselection_true_words.qml" << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (9,30)") << SRCDIR "/data/mouseselection_true_words.qml" << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (13,2)") << SRCDIR "/data/mouseselection_true_words.qml" << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (20,2)") << SRCDIR "/data/mouseselection_true_words.qml" << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (12,9)") << SRCDIR "/data/mouseselection_true_words.qml" << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ QTest::newRow("on word selection (30,9)") << SRCDIR "/data/mouseselection_true_words.qml" << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
void tst_qdeclarativetextedit::mouseSelection()
{
QFETCH(QString, qmlfile);
- QFETCH(bool, expectSelection);
+ QFETCH(int, from);
+ QFETCH(int, to);
+ QFETCH(QString, selectedText);
QDeclarativeView *canvas = createView(qmlfile);
@@ -1342,25 +1366,20 @@ void tst_qdeclarativetextedit::mouseSelection()
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)));
+ QPoint p1 = canvas->mapFromScene(textEditObject->positionToRectangle(from).center());
+ QPoint p2 = canvas->mapFromScene(textEditObject->positionToRectangle(to).center());
+ QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, p1);
//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);
+ QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(p2), 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 (expectSelection)
- QVERIFY(str.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform)
- else
- QVERIFY(str.isEmpty());
+ QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, p2);
+ QCOMPARE(textEditObject->selectedText(), selectedText);
// Clicking and shift to clicking between the same points should select the same text.
textEditObject->setCursorPosition(0);
- QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::NoModifier, canvas->mapFromScene(QPoint(x1,y)));
- QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::ShiftModifier, canvas->mapFromScene(QPoint(x2,y)));
- QCOMPARE(textEditObject->selectedText(), str);
+ QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::NoModifier, p1);
+ QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::ShiftModifier, p2);
+ QCOMPARE(textEditObject->selectedText(), selectedText);
delete canvas;
}
@@ -1682,15 +1701,26 @@ void tst_qdeclarativetextedit::cursorDelegate()
QInputMethodEvent event;
QApplication::sendEvent(view, &event);
+
// Test delegate gets moved on mouse press.
textEditObject->setSelectByMouse(true);
textEditObject->setCursorPosition(0);
- qDebug() << textEditObject->boundingRect() << textEditObject->positionToRectangle(5).center() << view->mapFromScene(textEditObject->positionToRectangle(5).center());
- QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(textEditObject->positionToRectangle(5).center()));
+ const QPoint point1 = view->mapFromScene(textEditObject->positionToRectangle(5).center());
+ QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, point1);
QVERIFY(textEditObject->cursorPosition() != 0);
QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+ // Test delegate gets moved on mouse drag
+ textEditObject->setCursorPosition(0);
+ const QPoint point2 = view->mapFromScene(textEditObject->positionToRectangle(10).center());
+ QTest::mousePress(view->viewport(), Qt::LeftButton, 0, point1);
+ QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
+ QApplication::sendEvent(view->viewport(), &mv);
+ QTest::mouseRelease(view->viewport(), Qt::LeftButton, 0, point2);
+ QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+
textEditObject->setReadOnly(true);
textEditObject->setCursorPosition(0);
QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(textEditObject->positionToRectangle(5).center()));
@@ -1699,6 +1729,12 @@ void tst_qdeclarativetextedit::cursorDelegate()
QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
textEditObject->setCursorPosition(0);
+ QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(textEditObject->positionToRectangle(5).center()));
+ QVERIFY(textEditObject->cursorPosition() != 0);
+ QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
+ QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
+
+ textEditObject->setCursorPosition(0);
QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
QVERIFY(textEditObject->cursorRectangle().y() >= 0);
diff --git a/tests/auto/qtquick1/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml b/tests/auto/qtquick1/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml
index b11535e50b..7f27bbe5cb 100644
--- a/tests/auto/qtquick1/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml
+++ b/tests/auto/qtquick1/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml
@@ -18,6 +18,7 @@ Rectangle {
objectName: "text"
anchors.fill: parent
text: top.text
+ focus: true
}
}
}
diff --git a/tests/auto/qtquick1/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/qtquick1/qdeclarativetextinput/tst_qdeclarativetextinput.cpp
index 413f04d496..633ab17a27 100644
--- a/tests/auto/qtquick1/qdeclarativetextinput/tst_qdeclarativetextinput.cpp
+++ b/tests/auto/qtquick1/qdeclarativetextinput/tst_qdeclarativetextinput.cpp
@@ -52,6 +52,8 @@
#include <QInputContext>
#include <QtWidgets/5.0.0/QtWidgets/private/qapplication_p.h>
+#include "qplatformdefs.h"
+
#ifdef Q_OS_SYMBIAN
// In Symbian OS test data is located in applications private dir
#define SRCDIR "."
@@ -133,6 +135,9 @@ private slots:
void focusOutClearSelection();
void echoMode();
+#ifdef QT_GUI_PASSWORD_ECHO_DELAY
+ void passwordEchoDelay();
+#endif
void geometrySignals();
void testQtQuick11Attributes();
void testQtQuick11Attributes_data();
@@ -1197,6 +1202,8 @@ void tst_qdeclarativetextinput::horizontalAlignment_RightToLeft()
QVERIFY(textInput != 0);
canvas->show();
+ const QString rtlText = textInput->text();
+
QDeclarative1TextInputPrivate *textInputPrivate = QDeclarative1TextInputPrivate::get(textInput);
QVERIFY(textInputPrivate != 0);
QVERIFY(-textInputPrivate->hscroll > canvas->width()/2);
@@ -1261,6 +1268,17 @@ void tst_qdeclarativetextinput::horizontalAlignment_RightToLeft()
QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
QVERIFY(-textInputPrivate->hscroll < canvas->width()/2);
+ QApplication::setActiveWindow(canvas);
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
+
+ // If there is no commited text, the preedit text should determine the alignment.
+ textInput->setText(QString());
+ { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
+ QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignRight);
+ { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QApplication::sendEvent(canvas, &ev); }
+ QCOMPARE(textInput->hAlign(), QDeclarative1TextInput::AlignLeft);
+
#ifndef Q_OS_MAC // QTBUG-18040
// empty text with implicit alignment follows the system locale-based
// keyboard input direction from QApplication::keyboardInputDirection
@@ -2062,6 +2080,62 @@ void tst_qdeclarativetextinput::echoMode()
delete canvas;
}
+
+#ifdef QT_GUI_PASSWORD_ECHO_DELAY
+void tst_qdeclarativetextinput::passwordEchoDelay()
+{
+ QDeclarativeView *canvas = createView(SRCDIR "/data/echoMode.qml");
+ canvas->show();
+ canvas->setFocus();
+ QApplication::setActiveWindow(canvas);
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
+
+ QVERIFY(canvas->rootObject() != 0);
+
+ QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));
+
+ QChar fillChar = QLatin1Char('*');
+
+ input->setEchoMode(QDeclarativeTextInput::Password);
+ QCOMPARE(input->displayText(), QString(8, fillChar));
+ input->setText(QString());
+ QCOMPARE(input->displayText(), QString());
+
+ QTest::keyPress(canvas, '0');
+ QTest::keyPress(canvas, '1');
+ QTest::keyPress(canvas, '2');
+ QCOMPARE(input->displayText(), QString(2, fillChar) + QLatin1Char('2'));
+ QTest::keyPress(canvas, '3');
+ QTest::keyPress(canvas, '4');
+ QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
+ QTest::keyPress(canvas, Qt::Key_Backspace);
+ QCOMPARE(input->displayText(), QString(4, fillChar));
+ QTest::keyPress(canvas, '4');
+ QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
+ QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
+ QTRY_COMPARE(input->displayText(), QString(5, fillChar));
+ QTest::keyPress(canvas, '5');
+ QCOMPARE(input->displayText(), QString(5, fillChar) + QLatin1Char('5'));
+ input->setFocus(false);
+ QVERIFY(!input->hasFocus());
+ QCOMPARE(input->displayText(), QString(6, fillChar));
+ input->setFocus(true);
+ QTRY_VERIFY(input->hasFocus());
+ QCOMPARE(input->displayText(), QString(6, fillChar));
+ QTest::keyPress(canvas, '6');
+ QCOMPARE(input->displayText(), QString(6, fillChar) + QLatin1Char('6'));
+
+ QInputMethodEvent ev;
+ ev.setCommitString(QLatin1String("7"));
+ QApplication::sendEvent(canvas, &ev);
+ QCOMPARE(input->displayText(), QString(7, fillChar) + QLatin1Char('7'));
+
+ delete canvas;
+}
+#endif
+
+
void tst_qdeclarativetextinput::simulateKey(QDeclarativeView *view, int key)
{
QKeyEvent press(QKeyEvent::KeyPress, key, 0);
diff --git a/tests/auto/qtquick1/qtquick1.pro b/tests/auto/qtquick1/qtquick1.pro
index 0c3e2498ff..489accb839 100644
--- a/tests/auto/qtquick1/qtquick1.pro
+++ b/tests/auto/qtquick1/qtquick1.pro
@@ -43,6 +43,7 @@ contains(QT_CONFIG, private_tests) {
qdeclarativetimer \
qdeclarativevisualdatamodel \
qdeclarativexmllistmodel \
+ examples
}
diff --git a/tests/benchmarks/declarative/js/qjsengine/tst_qjsengine.cpp b/tests/benchmarks/declarative/js/qjsengine/tst_qjsengine.cpp
index ba486df2b1..f8bade3f9d 100644
--- a/tests/benchmarks/declarative/js/qjsengine/tst_qjsengine.cpp
+++ b/tests/benchmarks/declarative/js/qjsengine/tst_qjsengine.cpp
@@ -7,29 +7,29 @@
** 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.
+** 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
+** 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.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/tests/benchmarks/declarative/js/qjsvalue/tst_qjsvalue.cpp b/tests/benchmarks/declarative/js/qjsvalue/tst_qjsvalue.cpp
index afe6d1c4db..5ebcbd86ac 100644
--- a/tests/benchmarks/declarative/js/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/benchmarks/declarative/js/qjsvalue/tst_qjsvalue.cpp
@@ -7,29 +7,29 @@
** 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.
+** 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
+** 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.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
diff --git a/tests/benchmarks/declarative/js/qjsvalueiterator/tst_qjsvalueiterator.cpp b/tests/benchmarks/declarative/js/qjsvalueiterator/tst_qjsvalueiterator.cpp
index 8b4921cf8e..14dc75d204 100644
--- a/tests/benchmarks/declarative/js/qjsvalueiterator/tst_qjsvalueiterator.cpp
+++ b/tests/benchmarks/declarative/js/qjsvalueiterator/tst_qjsvalueiterator.cpp
@@ -7,29 +7,29 @@
** 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.
+** 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
+** 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.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**