summaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/auto.pro5
-rw-r--r--tests/auto/declarative/.gitignore3
-rw-r--r--tests/auto/declarative/datetimeformatter/datetimeformatter.pro3
-rw-r--r--tests/auto/declarative/datetimeformatter/tst_datetimeformatter.cpp83
-rw-r--r--tests/auto/declarative/declarative.pro22
-rw-r--r--tests/auto/declarative/layouts/data/grid-margin.xml9
-rw-r--r--tests/auto/declarative/layouts/data/grid-spacing-margin.xml9
-rw-r--r--tests/auto/declarative/layouts/data/grid-spacing.xml9
-rw-r--r--tests/auto/declarative/layouts/data/grid.xml9
-rw-r--r--tests/auto/declarative/layouts/data/horizontal-margin.xml7
-rw-r--r--tests/auto/declarative/layouts/data/horizontal-spacing-margin.xml7
-rw-r--r--tests/auto/declarative/layouts/data/horizontal-spacing.xml7
-rw-r--r--tests/auto/declarative/layouts/data/horizontal.xml7
-rw-r--r--tests/auto/declarative/layouts/data/vertical-margin.xml7
-rw-r--r--tests/auto/declarative/layouts/data/vertical-spacing-margin.xml7
-rw-r--r--tests/auto/declarative/layouts/data/vertical-spacing.xml7
-rw-r--r--tests/auto/declarative/layouts/data/vertical.xml7
-rw-r--r--tests/auto/declarative/layouts/layouts.pro6
-rw-r--r--tests/auto/declarative/layouts/tst_layouts.cpp392
-rw-r--r--tests/auto/declarative/listview/data/listview.xml14
-rw-r--r--tests/auto/declarative/listview/listview.pro6
-rw-r--r--tests/auto/declarative/listview/tst_listview.cpp484
-rw-r--r--tests/auto/declarative/namespaces/data/Red/Rect.qml2
-rw-r--r--tests/auto/declarative/namespaces/namespaces.pro6
-rw-r--r--tests/auto/declarative/namespaces/tst_namespaces.cpp94
-rw-r--r--tests/auto/declarative/numberformatter/numberformatter.pro3
-rw-r--r--tests/auto/declarative/numberformatter/tst_numberformatter.cpp216
-rw-r--r--tests/auto/declarative/pathview/data/pathview.xml20
-rw-r--r--tests/auto/declarative/pathview/pathview.pro6
-rw-r--r--tests/auto/declarative/pathview/tst_pathview.cpp259
-rw-r--r--tests/auto/declarative/qbindablemap/qbindablemap.pro3
-rw-r--r--tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp72
-rw-r--r--tests/auto/declarative/qfxtext/qfxtext.pro3
-rw-r--r--tests/auto/declarative/qfxtext/tst_qfxtext.cpp412
-rw-r--r--tests/auto/declarative/qfxtextedit/qfxtextedit.pro3
-rw-r--r--tests/auto/declarative/qfxtextedit/tst_qfxtextedit.cpp326
-rw-r--r--tests/auto/declarative/qmlbindengine/qmlbindengine.pro3
-rw-r--r--tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp123
-rw-r--r--tests/auto/declarative/qmllist/qmllist.pro3
-rw-r--r--tests/auto/declarative/qmllist/tst_qmllist.cpp38
-rw-r--r--tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro3
-rw-r--r--tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp61
-rw-r--r--tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro3
-rw-r--r--tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp104
-rw-r--r--tests/auto/declarative/qmlparser/qmlparser.pro3
-rw-r--r--tests/auto/declarative/qmlparser/tst_qmlparser.cpp444
-rw-r--r--tests/auto/declarative/repeater/data/repeater.xml7
-rw-r--r--tests/auto/declarative/repeater/repeater.pro6
-rw-r--r--tests/auto/declarative/repeater/tst_repeater.cpp91
-rw-r--r--tests/auto/declarative/simplecanvasitem/data/test.xml12
-rw-r--r--tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro6
-rw-r--r--tests/auto/declarative/simplecanvasitem/tst_simplecanvasitem.cpp79
-rw-r--r--tests/auto/declarative/visual/ListView/basic1/basic1.xml19
-rw-r--r--tests/auto/declarative/visual/ListView/basic1/data/opengl/image0.pngbin0 -> 3759 bytes
-rw-r--r--tests/auto/declarative/visual/ListView/basic1/data/opengl/manifest.xml4
-rw-r--r--tests/auto/declarative/visual/ListView/basic1/test1
-rw-r--r--tests/auto/declarative/visual/ListView/basic2/basic2.xml20
-rw-r--r--tests/auto/declarative/visual/ListView/basic2/data/opengl/image0.pngbin0 -> 3759 bytes
-rw-r--r--tests/auto/declarative/visual/ListView/basic2/data/opengl/manifest.xml4
-rw-r--r--tests/auto/declarative/visual/ListView/basic2/test1
-rw-r--r--tests/auto/declarative/visual/ListView/basic3/basic3.xml18
-rw-r--r--tests/auto/declarative/visual/ListView/basic3/data/opengl/image0.pngbin0 -> 3759 bytes
-rw-r--r--tests/auto/declarative/visual/ListView/basic3/data/opengl/manifest.xml4
-rw-r--r--tests/auto/declarative/visual/ListView/basic3/test1
-rw-r--r--tests/auto/declarative/visual/ListView/basic4/basic4.xml19
-rw-r--r--tests/auto/declarative/visual/ListView/basic4/data/opengl/image0.pngbin0 -> 3759 bytes
-rw-r--r--tests/auto/declarative/visual/ListView/basic4/data/opengl/manifest.xml4
-rw-r--r--tests/auto/declarative/visual/ListView/basic4/test1
-rw-r--r--tests/auto/declarative/visual/bindinganimation/bindinganimation.xml19
-rw-r--r--tests/auto/declarative/visual/bindinganimation/data/opengl/image0.pngbin0 -> 817 bytes
-rw-r--r--tests/auto/declarative/visual/bindinganimation/data/opengl/manifest-play.xml104
-rw-r--r--tests/auto/declarative/visual/bindinganimation/data/opengl/manifest.xml104
-rw-r--r--tests/auto/declarative/visual/bindinganimation/test1
-rw-r--r--tests/auto/declarative/visual/colorAnimation/colorAnimation.xml18
-rw-r--r--tests/auto/declarative/visual/colorAnimation/image0.pngbin0 -> 947 bytes
-rw-r--r--tests/auto/declarative/visual/colorAnimation/manifest-play.xml73
-rw-r--r--tests/auto/declarative/visual/colorAnimation/manifest.xml73
-rw-r--r--tests/auto/declarative/visual/easing/easing.xml70
-rw-r--r--tests/auto/declarative/visual/easing/image0.pngbin0 -> 17530 bytes
-rw-r--r--tests/auto/declarative/visual/easing/manifest-play.xml23
-rw-r--r--tests/auto/declarative/visual/easing/manifest.xml23
-rw-r--r--tests/auto/declarative/visual/easing/pics/qtlogo.pngbin0 -> 2738 bytes
-rw-r--r--tests/auto/declarative/visual/flickable/Day.qml8
-rw-r--r--tests/auto/declarative/visual/flickable/cork.jpgbin0 -> 88766 bytes
-rw-r--r--tests/auto/declarative/visual/flickable/flickable.xml43
-rw-r--r--tests/auto/declarative/visual/flickable/image0.pngbin0 -> 360547 bytes
-rw-r--r--tests/auto/declarative/visual/flickable/manifest-fail.xml30
-rw-r--r--tests/auto/declarative/visual/flickable/manifest.xml190
-rw-r--r--tests/auto/declarative/visual/flipable/flipable.xml138
-rw-r--r--tests/auto/declarative/visual/flipable/image0.pngbin0 -> 6184 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/manifest-play.xml24
-rw-r--r--tests/auto/declarative/visual/flipable/manifest.xml24
-rw-r--r--tests/auto/declarative/visual/flipable/pics/arrow.pngbin0 -> 546 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/face.pngbin0 -> 10112 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo0.pngbin0 -> 10412 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo1.pngbin0 -> 11068 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo10.pngbin0 -> 12539 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo2.pngbin0 -> 11490 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo3.pngbin0 -> 11308 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo4.pngbin0 -> 11322 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo5.pngbin0 -> 11497 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo6.pngbin0 -> 11707 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo7.pngbin0 -> 11101 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo8.pngbin0 -> 11558 bytes
-rw-r--r--tests/auto/declarative/visual/flipable/pics/photo9.pngbin0 -> 10943 bytes
-rw-r--r--tests/auto/declarative/visual/pauseAnimation/image0.pngbin0 -> 3209 bytes
-rw-r--r--tests/auto/declarative/visual/pauseAnimation/manifest-play.xml138
-rw-r--r--tests/auto/declarative/visual/pauseAnimation/manifest.xml138
-rw-r--r--tests/auto/declarative/visual/pauseAnimation/pauseAnimation.xml13
-rw-r--r--tests/auto/declarative/visual/pauseAnimation/pics/qtlogo.pngbin0 -> 2738 bytes
-rw-r--r--tests/auto/declarative/visual/qfxtext/elide/data/opengl/image0.pngbin0 -> 980 bytes
-rw-r--r--tests/auto/declarative/visual/qfxtext/elide/data/opengl/manifest.xml4
-rw-r--r--tests/auto/declarative/visual/qfxtext/elide/elide.xml6
-rw-r--r--tests/auto/declarative/visual/qfxtext/elide/test1
-rw-r--r--tests/auto/declarative/visual/repeater/basic1/basic1.xml21
-rw-r--r--tests/auto/declarative/visual/repeater/basic1/data/opengl/image0.pngbin0 -> 3493 bytes
-rw-r--r--tests/auto/declarative/visual/repeater/basic1/data/opengl/manifest.xml4
-rw-r--r--tests/auto/declarative/visual/repeater/basic1/test1
-rw-r--r--tests/auto/declarative/visual/repeater/basic2/basic2.xml22
-rw-r--r--tests/auto/declarative/visual/repeater/basic2/data/opengl/image0.pngbin0 -> 3493 bytes
-rw-r--r--tests/auto/declarative/visual/repeater/basic2/data/opengl/manifest.xml4
-rw-r--r--tests/auto/declarative/visual/repeater/basic2/test1
-rw-r--r--tests/auto/declarative/visual/repeater/basic3/basic3.xml19
-rw-r--r--tests/auto/declarative/visual/repeater/basic3/data/opengl/image0.pngbin0 -> 3493 bytes
-rw-r--r--tests/auto/declarative/visual/repeater/basic3/data/opengl/manifest.xml4
-rw-r--r--tests/auto/declarative/visual/repeater/basic3/test1
-rw-r--r--tests/auto/declarative/visual/repeater/basic4/basic4.xml18
-rw-r--r--tests/auto/declarative/visual/repeater/basic4/data/opengl/image0.pngbin0 -> 3493 bytes
-rw-r--r--tests/auto/declarative/visual/repeater/basic4/data/opengl/manifest.xml4
-rw-r--r--tests/auto/declarative/visual/repeater/basic4/test1
-rwxr-xr-xtests/auto/declarative/visual/runtests.sh2
-rw-r--r--tests/auto/declarative/visual/tests11
-rw-r--r--tests/auto/declarative/visual/tst_visual.cpp72
-rw-r--r--tests/auto/declarative/visual/visual.pro5
-rw-r--r--tests/auto/declarative/visual/webview/autosize/data/opengl/image0.pngbin0 -> 5396 bytes
-rw-r--r--tests/auto/declarative/visual/webview/autosize/data/opengl/manifest.xml4
-rw-r--r--tests/auto/declarative/visual/webview/autosize/test1
-rw-r--r--tests/auto/dynamicobject/dynamicobject.pro6
-rw-r--r--tests/auto/dynamicobject/qdynamicmetaobject.cpp254
-rw-r--r--tests/auto/dynamicobject/qdynamicmetaobject.h47
-rw-r--r--tests/auto/dynamicobject/qmetaobjectbuilder.cpp2347
-rw-r--r--tests/auto/dynamicobject/qmetaobjectbuilder.h258
-rw-r--r--tests/auto/dynamicobject/tst_qobject.cpp325
-rw-r--r--tests/auto/math3d/math3d.pro2
-rw-r--r--tests/auto/math3d/qmatrixnxn/qmatrixnxn.pro5
-rw-r--r--tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp3185
-rw-r--r--tests/auto/math3d/qquaternion/qquaternion.pro5
-rw-r--r--tests/auto/math3d/qquaternion/tst_qquaternion.cpp830
-rw-r--r--tests/auto/math3d/qvectornd/qvectornd.pro5
-rw-r--r--tests/auto/math3d/qvectornd/tst_qvectornd.cpp2045
-rw-r--r--tests/auto/math3d/shared/math3dincludes.h52
-rw-r--r--tests/auto/q3filedialog/tst_q3filedialog.cpp12
-rw-r--r--tests/auto/q3tabdialog/tst_q3tabdialog.cpp28
-rw-r--r--tests/auto/qaccessibility/tst_qaccessibility.cpp6
-rw-r--r--tests/auto/qaction/tst_qaction.cpp86
-rw-r--r--tests/auto/qfiledialog/tst_qfiledialog.cpp116
-rw-r--r--tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp41
-rw-r--r--tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp269
-rw-r--r--tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp64
-rw-r--r--tests/auto/qgraphicsview/tst_qgraphicsview.cpp153
-rw-r--r--tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp387
-rw-r--r--tests/auto/qheaderview/tst_qheaderview.cpp24
-rw-r--r--tests/auto/qlineedit/tst_qlineedit.cpp13
-rw-r--r--tests/auto/qmake/testdata/bundle-spaces/some-file6
-rw-r--r--tests/auto/qmenu/tst_qmenu.cpp2
-rw-r--r--tests/auto/qpainterpath/tst_qpainterpath.cpp40
-rw-r--r--tests/auto/qpicture/tst_qpicture.cpp38
-rw-r--r--tests/auto/qpixmap/images/designer.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_-10_dy_-10_50_50_100_100.pngbin0 -> 4385 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_-10_dy_-10_x_y_w_h.pngbin0 -> 4104 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_-10_dy_0_50_50_100_100.pngbin0 -> 4243 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_-10_dy_0_x_y_w_h.pngbin0 -> 4116 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_-128_dy_-128_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_-128_dy_0_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_0_dy_-10_50_50_100_100.pngbin0 -> 4367 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_0_dy_-10_x_y_w_h.pngbin0 -> 4157 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_0_dy_-128_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_0_dy_0_50_50_100_100.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_0_dy_0_null.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_0_dy_0_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_0_dy_10_50_50_100_100.pngbin0 -> 4271 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_0_dy_10_x_y_w_h.pngbin0 -> 4188 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_0_dy_128_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_0_dy_1_null.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_10_dy_0_50_50_100_100.pngbin0 -> 4248 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_10_dy_0_x_y_w_h.pngbin0 -> 4196 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_10_dy_10_50_50_100_100.pngbin0 -> 4243 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_10_dy_10_x_y_w_h.pngbin0 -> 4220 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_128_dy_0_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_128_dy_128_64_64_128_128.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_128_dy_128_x_y_w_h.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/images/dx_1_dy_0_null.pngbin0 -> 4282 bytes
-rw-r--r--tests/auto/qpixmap/qpixmap.pro3
-rw-r--r--tests/auto/qpixmap/qpixmap.qrc29
-rw-r--r--tests/auto/qpixmap/tst_qpixmap.cpp96
-rw-r--r--tests/auto/qpoint/tst_qpoint.cpp20
-rw-r--r--tests/auto/qprocess/qprocess.pro1
-rw-r--r--tests/auto/qprocess/testProcessEnvironment/main.cpp61
-rw-r--r--tests/auto/qprocess/testProcessEnvironment/testProcessEnvironment.pro12
-rw-r--r--tests/auto/qprocess/tst_qprocess.cpp106
-rw-r--r--tests/auto/qset/tst_qset.cpp35
-rw-r--r--tests/auto/qshortcut/tst_qshortcut.cpp7
-rw-r--r--tests/auto/qsplitter/qsplitter.pro3
-rw-r--r--tests/auto/qsplitter/tst_qsplitter.cpp2
-rw-r--r--tests/auto/qsqldatabase/tst_databases.h43
-rw-r--r--tests/auto/qsslsocket/tst_qsslsocket.cpp27
-rw-r--r--tests/auto/qtabbar/tst_qtabbar.cpp32
-rw-r--r--tests/auto/qtableview/tst_qtableview.cpp5
-rw-r--r--tests/auto/qtextdocumentfragment/tst_qtextdocumentfragment.cpp2
-rw-r--r--tests/auto/qtoolbutton/tst_qtoolbutton.cpp20
-rw-r--r--tests/auto/qtreeview/tst_qtreeview.cpp18
-rw-r--r--tests/auto/qwidget/tst_qwidget.cpp41
-rw-r--r--tests/auto/selftests/badxml/badxml.pro11
-rw-r--r--tests/auto/selftests/badxml/tst_badxml.cpp199
-rw-r--r--tests/auto/selftests/expected_skip.txt10
-rw-r--r--tests/auto/selftests/expected_xunit.txt24
-rw-r--r--tests/auto/selftests/selftests.pro2
-rw-r--r--tests/auto/selftests/selftests.qrc1
-rw-r--r--tests/auto/selftests/skip/tst_skip.cpp6
-rw-r--r--tests/auto/selftests/tst_selftests.cpp94
-rwxr-xr-xtests/auto/selftests/xunit/tst_xunitbin0 -> 11624 bytes
-rw-r--r--tests/auto/selftests/xunit/tst_xunit.cpp86
-rw-r--r--tests/auto/selftests/xunit/xunit.pro15
-rw-r--r--tests/auto/uiloader/baseline/css_splitter.ui63
224 files changed, 16643 insertions, 159 deletions
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index f8f15a3..869f1c4 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -5,9 +5,11 @@ TEMPLATE = subdirs
headers
SUBDIRS += bic \
+ dynamicobject \
collections \
compile \
compilerwarnings \
+ dynamicobject \
exceptionsafety \
macgui \
macplist \
@@ -437,3 +439,6 @@ contains(QT_CONFIG, webkit): SUBDIRS += \
qwebframe \
qwebpage
+SUBDIRS += math3d
+
+contains(QT_CONFIG, declarative): SUBDIRS += declarative
diff --git a/tests/auto/declarative/.gitignore b/tests/auto/declarative/.gitignore
new file mode 100644
index 0000000..c8bbd2f
--- /dev/null
+++ b/tests/auto/declarative/.gitignore
@@ -0,0 +1,3 @@
+tst_*
+!tst_*.*
+tst_*~
diff --git a/tests/auto/declarative/datetimeformatter/datetimeformatter.pro b/tests/auto/declarative/datetimeformatter/datetimeformatter.pro
new file mode 100644
index 0000000..e3d6cd0
--- /dev/null
+++ b/tests/auto/declarative/datetimeformatter/datetimeformatter.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_datetimeformatter.cpp
diff --git a/tests/auto/declarative/datetimeformatter/tst_datetimeformatter.cpp b/tests/auto/declarative/datetimeformatter/tst_datetimeformatter.cpp
new file mode 100644
index 0000000..4593033
--- /dev/null
+++ b/tests/auto/declarative/datetimeformatter/tst_datetimeformatter.cpp
@@ -0,0 +1,83 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmldatetimeformatter.h>
+
+class tst_datetimeformatter : public QObject
+{
+ Q_OBJECT
+public:
+ tst_datetimeformatter() {}
+
+private slots:
+ void date();
+ void time();
+ void dateTime();
+};
+
+void tst_datetimeformatter::date()
+{
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine, "<DateTimeFormatter date=\"2008-12-24\"/>");
+ QmlDateTimeFormatter *formatter = qobject_cast<QmlDateTimeFormatter*>(formatterComponent.create());
+ QVERIFY(formatter != 0);
+
+ QDate date(2008,12,24);
+ QCOMPARE(formatter->dateText(),date.toString(Qt::SystemLocaleShortDate));
+
+ formatter->setLongStyle(true);
+ QCOMPARE(formatter->dateText(),date.toString(Qt::SystemLocaleLongDate));
+
+ formatter->setDateFormat("ddd MMMM d yy");
+ QCOMPARE(formatter->dateText(),date.toString("ddd MMMM d yy"));
+
+ QVERIFY(formatter->timeText().isEmpty());
+ QVERIFY(formatter->dateTimeText().isEmpty());
+}
+
+void tst_datetimeformatter::time()
+{
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine, "<DateTimeFormatter time=\"14:15:38.200\"/>");
+ QmlDateTimeFormatter *formatter = qobject_cast<QmlDateTimeFormatter*>(formatterComponent.create());
+ QVERIFY(formatter != 0);
+
+ QTime time(14,15,38,200);
+
+ QCOMPARE(formatter->time(),time);
+
+ QCOMPARE(formatter->timeText(),time.toString(Qt::SystemLocaleShortDate));
+
+ formatter->setLongStyle(true);
+ QCOMPARE(formatter->timeText(),time.toString(Qt::SystemLocaleLongDate));
+
+ formatter->setTimeFormat("H:m:s a");
+ QCOMPARE(formatter->timeText(),time.toString("H:m:s a"));
+
+ formatter->setTimeFormat("hh:mm:ss.zzz");
+ QCOMPARE(formatter->timeText(),time.toString("hh:mm:ss.zzz"));
+
+ QVERIFY(formatter->dateText().isEmpty());
+ QVERIFY(formatter->dateTimeText().isEmpty());
+}
+
+void tst_datetimeformatter::dateTime()
+{
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine, "<DateTimeFormatter dateTime=\"1978-03-04T09:13:54\"/>");
+ QmlDateTimeFormatter *formatter = qobject_cast<QmlDateTimeFormatter*>(formatterComponent.create());
+ QVERIFY(formatter != 0);
+
+ QDateTime dateTime(QDate(1978,03,04),QTime(9,13,54));
+ QCOMPARE(formatter->dateTimeText(),dateTime.toString(Qt::SystemLocaleShortDate));
+
+ formatter->setLongStyle(true);
+ QCOMPARE(formatter->dateTimeText(),dateTime.toString(Qt::SystemLocaleLongDate));
+
+ formatter->setDateTimeFormat("M/d/yy H:m:s a");
+ QCOMPARE(formatter->dateTimeText(),dateTime.toString("M/d/yy H:m:s a"));
+}
+
+QTEST_MAIN(tst_datetimeformatter)
+
+#include "tst_datetimeformatter.moc"
diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro
new file mode 100644
index 0000000..b6e3584
--- /dev/null
+++ b/tests/auto/declarative/declarative.pro
@@ -0,0 +1,22 @@
+TEMPLATE = subdirs
+SUBDIRS += datetimeformatter \
+ numberformatter \
+ qbindablemap \
+ layouts \
+ listview \
+ pathview \
+ qfxtext \
+ qfxtextedit \
+ simplecanvasitem \
+ repeater \
+ qmlparser \
+ qmlbindengine \
+ qmlmetaproperty \
+ qmllist \
+ qmllistaccessor \
+ visual
+
+# Tests which should run in Pulse
+PULSE_TESTS = $$SUBDIRS
+PULSE_TESTS -= visual # All except 'visual' tests, allegedly too flaky
+
diff --git a/tests/auto/declarative/layouts/data/grid-margin.xml b/tests/auto/declarative/layouts/data/grid-margin.xml
new file mode 100644
index 0000000..fe58eef
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/grid-margin.xml
@@ -0,0 +1,9 @@
+<Item width="640" height="480">
+ <GridLayout columns="3" margin="8">
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="green" width="20" height="50"/>
+ <Rect id="three" color="blue" width="50" height="20"/>
+ <Rect id="four" color="cyan" width="50" height="50"/>
+ <Rect id="five" color="magenta" width="10" height="10"/>
+ </GridLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/data/grid-spacing-margin.xml b/tests/auto/declarative/layouts/data/grid-spacing-margin.xml
new file mode 100644
index 0000000..807b653
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/grid-spacing-margin.xml
@@ -0,0 +1,9 @@
+<Item width="640" height="480">
+ <GridLayout columns="3" spacing="4" margin="8">
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="green" width="20" height="50"/>
+ <Rect id="three" color="blue" width="50" height="20"/>
+ <Rect id="four" color="cyan" width="50" height="50"/>
+ <Rect id="five" color="magenta" width="10" height="10"/>
+ </GridLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/data/grid-spacing.xml b/tests/auto/declarative/layouts/data/grid-spacing.xml
new file mode 100644
index 0000000..55ef5a5
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/grid-spacing.xml
@@ -0,0 +1,9 @@
+<Item width="640" height="480">
+ <GridLayout columns="3" spacing="4">
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="green" width="20" height="50"/>
+ <Rect id="three" color="blue" width="50" height="20"/>
+ <Rect id="four" color="cyan" width="50" height="50"/>
+ <Rect id="five" color="magenta" width="10" height="10"/>
+ </GridLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/data/grid.xml b/tests/auto/declarative/layouts/data/grid.xml
new file mode 100644
index 0000000..abef813
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/grid.xml
@@ -0,0 +1,9 @@
+<Item width="640" height="480">
+ <GridLayout columns="3">
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="green" width="20" height="50"/>
+ <Rect id="three" color="blue" width="50" height="20"/>
+ <Rect id="four" color="cyan" width="50" height="50"/>
+ <Rect id="five" color="magenta" width="10" height="10"/>
+ </GridLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/data/horizontal-margin.xml b/tests/auto/declarative/layouts/data/horizontal-margin.xml
new file mode 100644
index 0000000..7ee9706
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/horizontal-margin.xml
@@ -0,0 +1,7 @@
+<Item width="640" height="480">
+ <HorizontalLayout margin="10">
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="red" width="20" height="10"/>
+ <Rect id="three" color="red" width="40" height="20"/>
+ </HorizontalLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/data/horizontal-spacing-margin.xml b/tests/auto/declarative/layouts/data/horizontal-spacing-margin.xml
new file mode 100644
index 0000000..8767818
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/horizontal-spacing-margin.xml
@@ -0,0 +1,7 @@
+<Item width="640" height="480">
+ <HorizontalLayout spacing="5" margin="10">
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="red" width="20" height="10"/>
+ <Rect id="three" color="red" width="40" height="20"/>
+ </HorizontalLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/data/horizontal-spacing.xml b/tests/auto/declarative/layouts/data/horizontal-spacing.xml
new file mode 100644
index 0000000..cb58711
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/horizontal-spacing.xml
@@ -0,0 +1,7 @@
+<Item width="640" height="480">
+ <HorizontalLayout spacing="10">
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="red" width="20" height="10"/>
+ <Rect id="three" color="red" width="40" height="20"/>
+ </HorizontalLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/data/horizontal.xml b/tests/auto/declarative/layouts/data/horizontal.xml
new file mode 100644
index 0000000..f9deaf1
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/horizontal.xml
@@ -0,0 +1,7 @@
+<Item width="640" height="480">
+ <HorizontalLayout>
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="red" width="20" height="10"/>
+ <Rect id="three" color="red" width="40" height="20"/>
+ </HorizontalLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/data/vertical-margin.xml b/tests/auto/declarative/layouts/data/vertical-margin.xml
new file mode 100644
index 0000000..abd7635
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/vertical-margin.xml
@@ -0,0 +1,7 @@
+<Item width="640" height="480">
+ <VerticalLayout margin="10">
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="red" width="20" height="10"/>
+ <Rect id="three" color="red" width="40" height="20"/>
+ </VerticalLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/data/vertical-spacing-margin.xml b/tests/auto/declarative/layouts/data/vertical-spacing-margin.xml
new file mode 100644
index 0000000..3d41ca0
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/vertical-spacing-margin.xml
@@ -0,0 +1,7 @@
+<Item width="640" height="480">
+ <VerticalLayout spacing="5" margin="10">
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="red" width="20" height="10"/>
+ <Rect id="three" color="red" width="40" height="20"/>
+ </VerticalLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/data/vertical-spacing.xml b/tests/auto/declarative/layouts/data/vertical-spacing.xml
new file mode 100644
index 0000000..e25f981
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/vertical-spacing.xml
@@ -0,0 +1,7 @@
+<Item width="640" height="480">
+ <VerticalLayout spacing="10">
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="red" width="20" height="10"/>
+ <Rect id="three" color="red" width="40" height="20"/>
+ </VerticalLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/data/vertical.xml b/tests/auto/declarative/layouts/data/vertical.xml
new file mode 100644
index 0000000..198d99f
--- /dev/null
+++ b/tests/auto/declarative/layouts/data/vertical.xml
@@ -0,0 +1,7 @@
+<Item width="640" height="480">
+ <VerticalLayout>
+ <Rect id="one" color="red" width="50" height="50"/>
+ <Rect id="two" color="red" width="20" height="10"/>
+ <Rect id="three" color="red" width="40" height="20"/>
+ </VerticalLayout>
+</Item>
diff --git a/tests/auto/declarative/layouts/layouts.pro b/tests/auto/declarative/layouts/layouts.pro
new file mode 100644
index 0000000..f7e7622
--- /dev/null
+++ b/tests/auto/declarative/layouts/layouts.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_layouts.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/layouts/tst_layouts.cpp b/tests/auto/declarative/layouts/tst_layouts.cpp
new file mode 100644
index 0000000..ad6a0b2
--- /dev/null
+++ b/tests/auto/declarative/layouts/tst_layouts.cpp
@@ -0,0 +1,392 @@
+#include <QtTest/QtTest>
+#include <qlistmodelinterface.h>
+#include <qfxview.h>
+#include <qfxrect.h>
+#include <qmlexpression.h>
+
+class tst_QFxLayouts : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QFxLayouts();
+
+private slots:
+ void test_horizontal();
+ void test_horizontal_spacing();
+ void test_horizontal_margin();
+ void test_horizontal_spacing_margin();
+ void test_vertical();
+ void test_vertical_spacing();
+ void test_vertical_margin();
+ void test_vertical_spacing_margin();
+ void test_grid();
+ void test_grid_spacing();
+ void test_grid_margin();
+ void test_grid_spacing_margin();
+
+private:
+ QFxView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QFxItem *parent, const QString &id, int index=0);
+};
+
+tst_QFxLayouts::tst_QFxLayouts()
+{
+}
+
+void tst_QFxLayouts::test_horizontal()
+{
+ QFxView *canvas = createView(SRCDIR "/data/horizontal.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+}
+
+void tst_QFxLayouts::test_horizontal_spacing()
+{
+ QFxView *canvas = createView(SRCDIR "/data/horizontal-spacing.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 60.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 90.0);
+ QCOMPARE(three->y(), 0.0);
+}
+
+void tst_QFxLayouts::test_horizontal_margin()
+{
+ QFxView *canvas = createView(SRCDIR "/data/horizontal-margin.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 10.0);
+ QCOMPARE(one->y(), 10.0);
+ QCOMPARE(two->x(), 60.0);
+ QCOMPARE(two->y(), 10.0);
+ QCOMPARE(three->x(), 80.0);
+ QCOMPARE(three->y(), 10.0);
+}
+
+void tst_QFxLayouts::test_horizontal_spacing_margin()
+{
+ QFxView *canvas = createView(SRCDIR "/data/horizontal-spacing-margin.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 10.0);
+ QCOMPARE(one->y(), 10.0);
+ QCOMPARE(two->x(), 65.0);
+ QCOMPARE(two->y(), 10.0);
+ QCOMPARE(three->x(), 90.0);
+ QCOMPARE(three->y(), 10.0);
+}
+
+void tst_QFxLayouts::test_vertical()
+{
+ QFxView *canvas = createView(SRCDIR "/data/vertical.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(two->y(), 50.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 60.0);
+}
+
+void tst_QFxLayouts::test_vertical_spacing()
+{
+ QFxView *canvas = createView(SRCDIR "/data/vertical-spacing.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 0.0);
+ QCOMPARE(two->y(), 60.0);
+ QCOMPARE(three->x(), 0.0);
+ QCOMPARE(three->y(), 80.0);
+}
+
+void tst_QFxLayouts::test_vertical_margin()
+{
+ QFxView *canvas = createView(SRCDIR "/data/vertical-margin.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 10.0);
+ QCOMPARE(one->y(), 10.0);
+ QCOMPARE(two->x(), 10.0);
+ QCOMPARE(two->y(), 60.0);
+ QCOMPARE(three->x(), 10.0);
+ QCOMPARE(three->y(), 70.0);
+}
+
+void tst_QFxLayouts::test_vertical_spacing_margin()
+{
+ QFxView *canvas = createView(SRCDIR "/data/vertical-spacing-margin.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+
+ QCOMPARE(one->x(), 10.0);
+ QCOMPARE(one->y(), 10.0);
+ QCOMPARE(two->x(), 10.0);
+ QCOMPARE(two->y(), 65.0);
+ QCOMPARE(three->x(), 10.0);
+ QCOMPARE(three->y(), 80.0);
+}
+
+void tst_QFxLayouts::test_grid()
+{
+ QFxView *canvas = createView("data/grid.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+ QFxRect *four = findItem<QFxRect>(canvas->root(), "four");
+ QVERIFY(four != 0);
+ QFxRect *five = findItem<QFxRect>(canvas->root(), "five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 50.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 70.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 50.0);
+ QCOMPARE(five->x(), 50.0);
+ QCOMPARE(five->y(), 50.0);
+}
+
+void tst_QFxLayouts::test_grid_spacing()
+{
+ QFxView *canvas = createView("data/grid-spacing.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+ QFxRect *four = findItem<QFxRect>(canvas->root(), "four");
+ QVERIFY(four != 0);
+ QFxRect *five = findItem<QFxRect>(canvas->root(), "five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 0.0);
+ QCOMPARE(one->y(), 0.0);
+ QCOMPARE(two->x(), 54.0);
+ QCOMPARE(two->y(), 0.0);
+ QCOMPARE(three->x(), 78.0);
+ QCOMPARE(three->y(), 0.0);
+ QCOMPARE(four->x(), 0.0);
+ QCOMPARE(four->y(), 54.0);
+ QCOMPARE(five->x(), 54.0);
+ QCOMPARE(five->y(), 54.0);
+}
+
+void tst_QFxLayouts::test_grid_margin()
+{
+ QFxView *canvas = createView("data/grid-margin.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+ QFxRect *four = findItem<QFxRect>(canvas->root(), "four");
+ QVERIFY(four != 0);
+ QFxRect *five = findItem<QFxRect>(canvas->root(), "five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 8.0);
+ QCOMPARE(one->y(), 8.0);
+ QCOMPARE(two->x(), 58.0);
+ QCOMPARE(two->y(), 8.0);
+ QCOMPARE(three->x(), 78.0);
+ QCOMPARE(three->y(), 8.0);
+ QCOMPARE(four->x(), 8.0);
+ QCOMPARE(four->y(), 58.0);
+ QCOMPARE(five->x(), 58.0);
+ QCOMPARE(five->y(), 58.0);
+}
+
+
+void tst_QFxLayouts::test_grid_spacing_margin()
+{
+ QFxView *canvas = createView("data/grid-spacing-margin.xml");
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRect *one = findItem<QFxRect>(canvas->root(), "one");
+ QVERIFY(one != 0);
+ QFxRect *two = findItem<QFxRect>(canvas->root(), "two");
+ QVERIFY(two != 0);
+ QFxRect *three = findItem<QFxRect>(canvas->root(), "three");
+ QVERIFY(three != 0);
+ QFxRect *four = findItem<QFxRect>(canvas->root(), "four");
+ QVERIFY(four != 0);
+ QFxRect *five = findItem<QFxRect>(canvas->root(), "five");
+ QVERIFY(five != 0);
+
+ QCOMPARE(one->x(), 8.0);
+ QCOMPARE(one->y(), 8.0);
+ QCOMPARE(two->x(), 62.0);
+ QCOMPARE(two->y(), 8.0);
+ QCOMPARE(three->x(), 86.0);
+ QCOMPARE(three->y(), 8.0);
+ QCOMPARE(four->x(), 8.0);
+ QCOMPARE(four->y(), 62.0);
+ QCOMPARE(five->x(), 62.0);
+ QCOMPARE(five->y(), 62.0);
+}
+
+QFxView *tst_QFxLayouts::createView(const QString &filename)
+{
+ QFxView *canvas = new QFxView(0);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setXml(xml, filename);
+
+ return canvas;
+}
+
+/*
+ Find an item with the specified id. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+*/
+template<typename T>
+T *tst_QFxLayouts::findItem(QFxItem *parent, const QString &id, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ for (int i = 0; i < parent->children()->count(); ++i) {
+ QFxItem *item = parent->children()->at(i);
+ if (mo.cast(item) && (id.isEmpty() || item->id() == id)) {
+ if (index != -1) {
+ QmlExpression e(item->itemContext(), "index", item);
+ e.setTrackChange(false);
+ if (e.value().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, id, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_QFxLayouts)
+
+#include "tst_layouts.moc"
diff --git a/tests/auto/declarative/listview/data/listview.xml b/tests/auto/declarative/listview/data/listview.xml
new file mode 100644
index 0000000..7fda2b5
--- /dev/null
+++ b/tests/auto/declarative/listview/data/listview.xml
@@ -0,0 +1,14 @@
+<Rect width="240" height="320" color="#ffffff">
+ <resources>
+ <Component id="Delegate">
+ <Item id="wrapper" height="20" width="240">
+ <Text text="{index}"/>
+ <Text x="30" id="textName" text="{name}"/>
+ <Text x="120" id="textNumber" text="{number}"/>
+ <Text x="200" text="{wrapper.y}"/>
+ </Item>
+ </Component>
+ </resources>
+ <ListView id="list" width="240" height="320" model="{testModel}" delegate="{Delegate}">
+ </ListView>
+</Rect>
diff --git a/tests/auto/declarative/listview/listview.pro b/tests/auto/declarative/listview/listview.pro
new file mode 100644
index 0000000..bf68268
--- /dev/null
+++ b/tests/auto/declarative/listview/listview.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_listview.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/listview/tst_listview.cpp b/tests/auto/declarative/listview/tst_listview.cpp
new file mode 100644
index 0000000..681af57
--- /dev/null
+++ b/tests/auto/declarative/listview/tst_listview.cpp
@@ -0,0 +1,484 @@
+#include <QtTest/QtTest>
+#include <qlistmodelinterface.h>
+#include <qfxview.h>
+#include <qfxlistview.h>
+#include <qfxtext.h>
+#include <qmlcontext.h>
+#include <qmlexpression.h>
+
+class tst_QFxListView : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QFxListView();
+
+private slots:
+ // Test both QListModelInterface and QAbstractItemModel model types
+ void qListModelInterface_items();
+ void qAbstractItemModel_items();
+
+ void qListModelInterface_changed();
+ void qAbstractItemModel_changed();
+
+ void qListModelInterface_inserted();
+ void qAbstractItemModel_inserted();
+
+ void qListModelInterface_removed();
+ void qAbstractItemModel_removed();
+
+private:
+ template <class T> void items();
+ template <class T> void changed();
+ template <class T> void inserted();
+ template <class T> void removed();
+ QFxView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QFxItem *parent, const QString &id, int index=0);
+};
+
+class TestModel : public QListModelInterface
+{
+ Q_OBJECT
+public:
+ TestModel(QObject *parent = 0) : QListModelInterface(parent) {}
+ ~TestModel() {}
+
+ enum Roles { Name, Number };
+
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ int count() const { return list.count(); }
+
+ QList<int> roles() const { return QList<int>() << Name << Number; }
+ QString toString(int role) const {
+ switch(role) {
+ case Name:
+ return "name";
+ case Number:
+ return "number";
+ default:
+ return "";
+ }
+ }
+
+ QHash<int, QVariant> data(int index, const QList<int> &roles) const {
+ QHash<int,QVariant> returnHash;
+
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ QVariant info;
+ switch(role) {
+ case Name:
+ info = list.at(index).first;
+ break;
+ case Number:
+ info = list.at(index).second;
+ break;
+ default:
+ break;
+ }
+ returnHash.insert(role, info);
+ }
+ return returnHash;
+ }
+
+ void addItem(const QString &name, const QString &number) {
+ list.append(QPair<QString,QString>(name, number));
+ emit itemsInserted(list.count()-1, 1);
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit itemsInserted(index, 1);
+ }
+
+ void removeItem(int index) {
+ list.removeAt(index);
+ emit itemsRemoved(index, 1);
+ }
+
+ void modifyItem(int index, const QString &name, const QString &number) {
+ list[index] = QPair<QString,QString>(name, number);
+ emit itemsChanged(index, 1, roles());
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+
+class TestModel2 : public QAbstractListModel
+{
+public:
+ enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
+
+ TestModel2(QObject *parent=0) : QAbstractListModel(parent) {
+ QHash<int, QByteArray> roles;
+ roles[Name] = "name";
+ roles[Number] = "number";
+ setRoleNames(roles);
+ }
+
+ int rowCount(const QModelIndex &parent=QModelIndex()) const { return list.count(); }
+ QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
+ QVariant rv;
+ if (role == Name)
+ rv = list.at(index.row()).first;
+ else if (role == Number)
+ rv = list.at(index.row()).second;
+
+ return rv;
+ }
+
+ int count() const { return rowCount(); }
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ void addItem(const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), list.count(), list.count());
+ list.append(QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ emit beginInsertRows(QModelIndex(), index, index);
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit endInsertRows();
+ }
+
+ void removeItem(int index) {
+ emit beginRemoveRows(QModelIndex(), index, index);
+ list.removeAt(index);
+ emit endRemoveRows();
+ }
+
+ void modifyItem(int idx, const QString &name, const QString &number) {
+ list[idx] = QPair<QString,QString>(name, number);
+ emit dataChanged(index(idx,0), index(idx,0));
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+tst_QFxListView::tst_QFxListView()
+{
+}
+
+template <class T>
+void tst_QFxListView::items()
+{
+ QFxView *canvas = createView(SRCDIR "/data/listview.xml");
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxFlickable *listview = findItem<QFxFlickable>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QFxItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ QCOMPARE(viewport->children()->count(), model.count()); // assumes all are visible
+
+ for (int i = 0; i < model.count(); ++i) {
+ QFxText *name = findItem<QFxText>(viewport, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ QFxText *number = findItem<QFxText>(viewport, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+template <class T>
+void tst_QFxListView::changed()
+{
+ QFxView *canvas = createView(SRCDIR "/data/listview.xml");
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxFlickable *listview = findItem<QFxFlickable>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QFxItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.modifyItem(1, "Will", "9876");
+ QFxText *name = findItem<QFxText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QFxText *number = findItem<QFxText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ delete canvas;
+}
+
+template <class T>
+void tst_QFxListView::inserted()
+{
+ QFxView *canvas = createView(SRCDIR "/data/listview.xml");
+
+ T model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxListView *listview = findItem<QFxListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QFxItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.insertItem(1, "Will", "9876");
+
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ QCOMPARE(viewport->children()->count(), model.count()); // assumes all are visible
+
+ QFxText *name = findItem<QFxText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QFxText *number = findItem<QFxText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QVERIFY(item->y() == i*20);
+ }
+
+ model.insertItem(0, "Foo", "1111"); // zero index, and current item
+
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ QCOMPARE(viewport->children()->count(), model.count()); // assumes all are visible
+
+ name = findItem<QFxText>(viewport, "textName", 0);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(0));
+ number = findItem<QFxText>(viewport, "textNumber", 0);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(0));
+
+ QCOMPARE(listview->currentIndex(), 1);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QVERIFY(item->y() == i*20);
+ }
+
+ delete canvas;
+}
+
+template <class T>
+void tst_QFxListView::removed()
+{
+ QFxView *canvas = createView(SRCDIR "/data/listview.xml");
+
+ T model;
+ for (int i = 0; i < 30; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxListView *listview = findItem<QFxListView>(canvas->root(), "list");
+ QVERIFY(listview != 0);
+
+ QFxItem *viewport = listview->viewport();
+ QVERIFY(viewport != 0);
+
+ model.removeItem(1);
+
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ QFxText *name = findItem<QFxText>(viewport, "textName", 1);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(1));
+ QFxText *number = findItem<QFxText>(viewport, "textNumber", 1);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(1));
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count() && i < viewport->children()->count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QVERIFY(item->y() == i*20);
+ }
+
+ // Remove first item (which is the current item);
+ model.removeItem(0); // post: top item starts at 20
+
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ name = findItem<QFxText>(viewport, "textName", 0);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(0));
+ number = findItem<QFxText>(viewport, "textNumber", 0);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(0));
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count() && i < viewport->children()->count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QCOMPARE(item->y(),i*20.0 + 20.0);
+ }
+
+ // Remove items not visible
+ model.removeItem(18);
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count() && i < viewport->children()->count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QCOMPARE(item->y(),i*20.0+20.0);
+ }
+
+ // Remove items before visible
+ listview->setYPosition(80);
+ listview->setCurrentIndex(10);
+
+ model.removeItem(1); // post: top item will be at 40
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ // Confirm items positioned correctly
+ for (int i = 2; i < 18; ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QCOMPARE(item->y(),40+i*20.0);
+ }
+
+ listview->setYPosition(40); // That's the top now
+ // let transitions settle.
+ QTest::qWait(1000);
+
+ // Confirm items positioned correctly
+ for (int i = 0; i < model.count() && i < viewport->children()->count(); ++i) {
+ QFxItem *item = findItem<QFxItem>(viewport, "wrapper", i);
+ QCOMPARE(item->y(),40+i*20.0);
+ }
+
+ delete canvas;
+}
+
+void tst_QFxListView::qListModelInterface_items()
+{
+ items<TestModel>();
+}
+
+void tst_QFxListView::qAbstractItemModel_items()
+{
+ items<TestModel2>();
+}
+
+void tst_QFxListView::qListModelInterface_changed()
+{
+ changed<TestModel>();
+}
+
+void tst_QFxListView::qAbstractItemModel_changed()
+{
+ changed<TestModel2>();
+}
+
+void tst_QFxListView::qListModelInterface_inserted()
+{
+ inserted<TestModel>();
+}
+
+void tst_QFxListView::qAbstractItemModel_inserted()
+{
+ inserted<TestModel2>();
+}
+
+void tst_QFxListView::qListModelInterface_removed()
+{
+ removed<TestModel>();
+}
+
+void tst_QFxListView::qAbstractItemModel_removed()
+{
+ removed<TestModel2>();
+}
+
+QFxView *tst_QFxListView::createView(const QString &filename)
+{
+ QFxView *canvas = new QFxView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setXml(xml, filename);
+
+ return canvas;
+}
+
+/*
+ Find an item with the specified id. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+*/
+template<typename T>
+T *tst_QFxListView::findItem(QFxItem *parent, const QString &id, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ for (int i = 0; i < parent->children()->count(); ++i) {
+ QFxItem *item = parent->children()->at(i);
+ if (mo.cast(item) && (id.isEmpty() || item->id() == id)) {
+ if (index != -1) {
+ QmlExpression e(item->itemContext(), "index", item);
+ e.setTrackChange(false);
+ if (e.value().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, id, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_QFxListView)
+
+#include "tst_listview.moc"
diff --git a/tests/auto/declarative/namespaces/data/Red/Rect.qml b/tests/auto/declarative/namespaces/data/Red/Rect.qml
new file mode 100644
index 0000000..c7b3d8c
--- /dev/null
+++ b/tests/auto/declarative/namespaces/data/Red/Rect.qml
@@ -0,0 +1,2 @@
+<Text objectName="x" text="Pretending to be a Rect" color="red">
+</Text>
diff --git a/tests/auto/declarative/namespaces/namespaces.pro b/tests/auto/declarative/namespaces/namespaces.pro
new file mode 100644
index 0000000..f232770
--- /dev/null
+++ b/tests/auto/declarative/namespaces/namespaces.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_namespaces.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/namespaces/tst_namespaces.cpp b/tests/auto/declarative/namespaces/tst_namespaces.cpp
new file mode 100644
index 0000000..665651d
--- /dev/null
+++ b/tests/auto/declarative/namespaces/tst_namespaces.cpp
@@ -0,0 +1,94 @@
+#include <qtest.h>
+#include <QtDeclarative/qfxview.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qfxrect.h>
+#include <QtDeclarative/qfxtext.h>
+#include <QDir>
+
+class tst_namespaces : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_namespaces();
+
+private slots:
+ void simple();
+ void simple_data();
+};
+
+tst_namespaces::tst_namespaces()
+{
+}
+
+void tst_namespaces::simple_data()
+{
+ QTest::addColumn<QString>("qml");
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QString>("texts");
+ QTest::addColumn<QString>("rects");
+
+ QTest::newRow("Control") <<
+ "<Rect objectName=\"a\">"
+ "<Rect objectName=\"b\"/>"
+ "</Rect>"
+ << true << "" << "ab";
+
+ QTest::newRow("Control2") <<
+ "<Rect objectName=\"a\">"
+ "<Text objectName=\"b\"/>"
+ "</Rect>"
+ << true << "b" << "a";
+
+ QTest::newRow("Replace builtin") <<
+ "<Rect objectName=\"a\" xmlns:rs=\"http://nokia.com/qml/Red\">"
+ "<rs:Rect objectName=\"b\"/>"
+ "</Rect>"
+ << true << "b" << "a";
+}
+
+void tst_namespaces::simple()
+{
+ QFETCH(QString, qml);
+ QFETCH(bool, valid);
+ QFETCH(QString, texts);
+ QFETCH(QString, rects);
+
+ QFxView canvas(0);
+ canvas.rootContext()->engine()->addNameSpacePath("http://nokia.com/qml", SRCDIR "/data");
+ canvas.setXml(qml);
+ canvas.execute();
+ qApp->processEvents();
+
+ QFxItem *testObject = qobject_cast<QFxItem*>(canvas.root());
+
+ QCOMPARE((testObject != 0),valid);
+
+ if (valid && testObject != 0) {
+ QString textids;
+ QList<QFxText*> textobjects = testObject->findChildren<QFxText*>();
+ if (qobject_cast<QFxText*>(testObject))
+ textids += testObject->objectName();
+ foreach (QFxText *obj, textobjects) {
+ textids += obj->objectName();
+ }
+ if (textids != texts)
+ testObject->dump();
+ QCOMPARE(textids,texts);
+
+ QString rectids;
+ QList<QFxRect*> rectobjects = testObject->findChildren<QFxRect*>();
+ if (qobject_cast<QFxRect*>(testObject))
+ rectids += testObject->objectName();
+ foreach (QFxRect *obj, rectobjects)
+ rectids += obj->objectName();
+ if (rectids != rects)
+ testObject->dump();
+ QCOMPARE(rectids,rects);
+ }
+}
+
+QTEST_MAIN(tst_namespaces)
+
+#include "tst_namespaces.moc"
diff --git a/tests/auto/declarative/numberformatter/numberformatter.pro b/tests/auto/declarative/numberformatter/numberformatter.pro
new file mode 100644
index 0000000..ba391ed
--- /dev/null
+++ b/tests/auto/declarative/numberformatter/numberformatter.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_numberformatter.cpp
diff --git a/tests/auto/declarative/numberformatter/tst_numberformatter.cpp b/tests/auto/declarative/numberformatter/tst_numberformatter.cpp
new file mode 100644
index 0000000..eaeab51
--- /dev/null
+++ b/tests/auto/declarative/numberformatter/tst_numberformatter.cpp
@@ -0,0 +1,216 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qnumberformat.h>
+#include <QtDeclarative/qmlnumberformatter.h>
+
+class tst_numberformat : public QObject
+{
+ Q_OBJECT
+public:
+ tst_numberformat();
+
+ void init() {}
+ void initTestCase() {}
+
+ void cleanup() {}
+ void cleanupTestCase() {}
+
+private slots:
+ void number_data();
+ void number();
+
+ void text_data();
+ void text();
+
+private:
+ QStringList strings;
+ QList<float> numbers;
+ QStringList formats;
+ QStringList texts;
+};
+
+tst_numberformat::tst_numberformat()
+{
+ strings << "100.0"
+ << "12345"
+ << "1234567"
+ << "0.123"
+ << "0.9999"
+ << "0.989"
+ << "1"
+ << "1.0"
+ << "1.01";
+
+ numbers << 100
+ << 12345
+ << 1234567
+ << 0.123
+ << 0.9999
+ << 0.989
+ << 1
+ << 1.0
+ << 1.01;
+
+ formats << ""
+ << "0000"
+ << "0000.00"
+ << "##"
+ << "##.##"
+ << "#0.00#"
+ << "##,##0.##"
+ << "(000) 000 - 000"
+ << "00000,000.0000";
+
+ //US locale only.
+ texts << "100.000000"
+ << "12345.000000"
+ << "1234567.000000"
+ << "0.123000"
+ << "0.999900"
+ << "0.989000"
+ << "1.000000"
+ << "1.000000"
+ << "1.010000" //end ""
+ << "0100"
+ << "12345"
+ << "1234567"
+ << "0000"
+ << "0001"
+ << "0001"
+ << "0001"
+ << "0001"
+ << "0001" // end "0000"
+ << "0100.00"
+ << "12345.00"
+ << "1234567.00"
+ << "0000.12"
+ << "0001.00"
+ << "0000.99"
+ << "0001.00"
+ << "0001.00"
+ << "0001.01" // end "0000.00"
+ << "100"
+ << "12345"
+ << "1234567"
+ << "0"
+ << "1"
+ << "1"
+ << "1"
+ << "1"
+ << "1" // end "##"
+ << "100"//start "##.##"
+ << "12345"
+ << "1234567"
+ << "0.12"
+ << "1"
+ << "0.99"
+ << "1"
+ << "1"
+ << "1.01" // end "##.##" -- ### EXPECT FAIL ### QNumberFormat::formatDecimal() bug
+ << "100.00" //start "#0.00#"
+ << "12345.00"
+ << "1234567.00"
+ << "0.123"
+ << "1.00"
+ << "0.989"
+ << "1.00"
+ << "1.00"
+ << "1.01" //end "#0.00#"
+ << "100" //start "##,##0.##"
+ << "12,345"
+ << "1,234,567"
+ << "0.12"
+ << "1"
+ << "0.99"
+ << "1"
+ << "1"
+ << "1.01" //end "##,##0.##" -- ### EXPECT FAIL ### QNumberFormat::formatDecimal() bug
+ << "(000) 000 - 100" //start "(000) 000 - 000"
+ << "(000) 012 - 345"
+ << "(001) 234 - 567"
+ << "(000) 000 - 000"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001"
+ << "(000) 000 - 001" // end "(000) 000 - 000"
+ << "00,000,100.0000" // start "00000,000.0000"
+ << "00,012,345.0000"
+ << "01,234,567.0000"
+ << "00,000,000.1230"
+ << "00,000,000.9999"
+ << "00,000,000.9890"
+ << "00,000,001.0000"
+ << "00,000,001.0000"
+ << "00,000,001.0100"; // end
+
+ qDebug() << "strings.size()" << strings.size()
+ << "\nformats.size()" << formats.size()
+ << "texts.size()" << texts.size();
+}
+
+void tst_numberformat::number_data()
+{
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<float>("number");
+
+ for (int i = 0; i < strings.size(); i++)
+ QTest::newRow(QString::number(i).toAscii()) << strings.at(i) << numbers.at(i);
+}
+
+void tst_numberformat::number()
+{
+ // ### tests the conversion from string to float
+ QFETCH(QString, string);
+ QFETCH(float, number);
+
+ QString componentStr = QString("<NumberFormatter number=\"") + string + QString("\"/>");
+
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine, componentStr.toAscii());
+ QmlNumberFormatter *formatter = qobject_cast<QmlNumberFormatter*>(formatterComponent.create());
+ QVERIFY(formatter != 0);
+ QCOMPARE((float)formatter->number(), number);
+ //qDebug() << formatter->format() << formatter->text();
+ QVERIFY(formatter->format().isEmpty());
+ QVERIFY(formatter->text() == QString("%1").arg(number, -1, 'f', -1));
+}
+
+void tst_numberformat::text_data()
+{
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<QString>("format");
+ QTest::addColumn<QString>("text");
+
+ for (int j=0; j < formats.size(); j++)
+ {
+ for (int i=0; i < strings.size(); i++)
+ {
+ QTest::newRow(QString("%1, %2").arg(strings.at(i)).arg(formats.at(j)).toAscii())
+ << strings.at(i) << formats.at(j) << texts.at(j*formats.size()+i);
+ }
+ }
+
+}
+
+void tst_numberformat::text()
+{
+ QFETCH(QString, string);
+ QFETCH(QString, format);
+ QFETCH(QString, text);
+
+ QString componentStr = QString("<NumberFormatter number=\"") + string + QString("\" format=\"") + format + QString("\" />");
+
+ QmlEngine engine;
+ QmlComponent formatterComponent(&engine, componentStr.toAscii());
+ QmlNumberFormatter *formatter = qobject_cast<QmlNumberFormatter*>(formatterComponent.create());
+ QVERIFY(formatter != 0);
+
+ QCOMPARE(formatter->format(), format);
+ QCOMPARE(formatter->text(), text);
+}
+
+QTEST_MAIN(tst_numberformat)
+
+#include "tst_numberformatter.moc"
diff --git a/tests/auto/declarative/pathview/data/pathview.xml b/tests/auto/declarative/pathview/data/pathview.xml
new file mode 100644
index 0000000..26b426c
--- /dev/null
+++ b/tests/auto/declarative/pathview/data/pathview.xml
@@ -0,0 +1,20 @@
+<Rect width="240" height="320" color="#ffffff">
+ <resources>
+ <Component id="Delegate">
+ <Rect id="wrapper" height="20" width="60" color="white" pen.color="black">
+ <Text text="{index}"/>
+ <Text x="20" id="textName" text="{name}"/>
+ <Text x="40" id="textNumber" text="{number}"/>
+ </Rect>
+ </Component>
+ </resources>
+ <PathView id="view" width="240" height="320" model="{testModel}" delegate="{Delegate}" snapPos="0.01">
+ <path>
+ <Path startY="120" startX="160">
+ <PathQuad y="120" x="80" controlY="330" controlX="100"/>
+ <PathLine y="160" x="20"/>
+ <PathCubic y="120" x="160" control1Y="0" control1X="100" control2Y="000" control2X="200"/>
+ </Path>
+ </path>
+ </PathView>
+</Rect>
diff --git a/tests/auto/declarative/pathview/pathview.pro b/tests/auto/declarative/pathview/pathview.pro
new file mode 100644
index 0000000..28bbe49
--- /dev/null
+++ b/tests/auto/declarative/pathview/pathview.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_pathview.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/pathview/tst_pathview.cpp b/tests/auto/declarative/pathview/tst_pathview.cpp
new file mode 100644
index 0000000..110d129
--- /dev/null
+++ b/tests/auto/declarative/pathview/tst_pathview.cpp
@@ -0,0 +1,259 @@
+#include <QtTest/QtTest>
+#include <qlistmodelinterface.h>
+#include <qfxview.h>
+#include <qfxpathview.h>
+#include <qfxtext.h>
+#include <qfxrect.h>
+#include <qmlcontext.h>
+#include <qmlexpression.h>
+
+class tst_QFxPathView : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QFxPathView();
+
+private slots:
+ void items();
+ void pathMoved();
+ void limitedItems();
+
+private:
+ QFxView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QFxItem *parent, const QString &id, int index=0);
+};
+
+class TestModel : public QListModelInterface
+{
+ Q_OBJECT
+public:
+ TestModel(QObject *parent = 0) : QListModelInterface(parent) {}
+ ~TestModel() {}
+
+ enum Roles { Name, Number };
+
+ QString name(int index) const { return list.at(index).first; }
+ QString number(int index) const { return list.at(index).second; }
+
+ int count() const { return list.count(); }
+
+ QList<int> roles() const { return QList<int>() << Name << Number; }
+ QString toString(int role) const {
+ switch(role) {
+ case Name:
+ return "name";
+ case Number:
+ return "number";
+ default:
+ return "";
+ }
+ }
+
+ QHash<int, QVariant> data(int index, const QList<int> &roles) const {
+ QHash<int,QVariant> returnHash;
+
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ QVariant info;
+ switch(role) {
+ case Name:
+ info = list.at(index).first;
+ break;
+ case Number:
+ info = list.at(index).second;
+ break;
+ default:
+ break;
+ }
+ returnHash.insert(role, info);
+ }
+ return returnHash;
+ }
+
+ void addItem(const QString &name, const QString &number) {
+ list.append(QPair<QString,QString>(name, number));
+ emit itemsInserted(list.count()-1, 1);
+ }
+
+ void insertItem(int index, const QString &name, const QString &number) {
+ list.insert(index, QPair<QString,QString>(name, number));
+ emit itemsInserted(index, 1);
+ }
+
+ void removeItem(int index) {
+ list.removeAt(index);
+ emit itemsRemoved(index, 1);
+ }
+
+ void modifyItem(int index, const QString &name, const QString &number) {
+ list[index] = QPair<QString,QString>(name, number);
+ emit itemsChanged(index, 1, roles());
+ }
+
+private:
+ QList<QPair<QString,QString> > list;
+};
+
+tst_QFxPathView::tst_QFxPathView()
+{
+}
+
+void tst_QFxPathView::items()
+{
+ QFxView *canvas = createView(SRCDIR "/data/pathview.xml");
+
+ TestModel model;
+ model.addItem("Fred", "12345");
+ model.addItem("John", "2345");
+ model.addItem("Bob", "54321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxPathView *pathview = findItem<QFxPathView>(canvas->root(), "view");
+ QVERIFY(pathview != 0);
+
+ QCOMPARE(pathview->children()->count(), model.count()); // assumes all are visible
+
+ for (int i = 0; i < model.count(); ++i) {
+ QFxText *name = findItem<QFxText>(pathview, "textName", i);
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), model.name(i));
+ QFxText *number = findItem<QFxText>(pathview, "textNumber", i);
+ QVERIFY(number != 0);
+ QCOMPARE(number->text(), model.number(i));
+ }
+
+ delete canvas;
+}
+
+void tst_QFxPathView::pathMoved()
+{
+ QFxView *canvas = createView(SRCDIR "/data/pathview.xml");
+
+ TestModel model;
+ model.addItem("Ben", "12345");
+ model.addItem("Bohn", "2345");
+ model.addItem("Bob", "54321");
+ model.addItem("Bill", "4321");
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxPathView *pathview = findItem<QFxPathView>(canvas->root(), "view");
+ QVERIFY(pathview != 0);
+
+ QFxRect *firstItem = findItem<QFxRect>(pathview, "wrapper", 0);
+ QVERIFY(firstItem);
+ QFxPath *path = qobject_cast<QFxPath*>(pathview->path());
+ QVERIFY(path);
+ QPointF start = path->pointAt(0.0);
+ QPointF offset;//Center of item is at point, but pos is from corner
+ offset.setX(firstItem->width()/2);
+ offset.setY(firstItem->height()/2);
+ QCOMPARE(firstItem->pos() + offset, start);
+ pathview->setOffset(10);
+ QTest::qWait(1000);//Moving is animated?
+
+ for(int i=0; i<model.count(); i++){
+ QFxRect *curItem = findItem<QFxRect>(pathview, "wrapper", i);
+ QCOMPARE(curItem->pos() + offset, path->pointAt(0.1 + i*0.25));
+ }
+
+ pathview->setOffset(100);
+ QTest::qWait(1000);//Moving is animated?
+ QCOMPARE(firstItem->pos() + offset, start);
+
+ delete canvas;
+}
+
+void tst_QFxPathView::limitedItems()
+{
+ QFxView *canvas = createView(SRCDIR "/data/pathview.xml");
+
+ TestModel model;
+ for(int i=0; i<100; i++)
+ model.addItem("Bob", QString::number(i));
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxPathView *pathview = findItem<QFxPathView>(canvas->root(), "view");
+ QVERIFY(pathview != 0);
+
+ pathview->setPathItemCount(10);
+ QCOMPARE(pathview->pathItemCount(), 10);
+
+ QFxRect *testItem = findItem<QFxRect>(pathview, "wrapper", 0);
+ QVERIFY(testItem != 0);
+ testItem = findItem<QFxRect>(pathview, "wrapper", 9);
+ QVERIFY(testItem != 0);
+ testItem = findItem<QFxRect>(pathview, "wrapper", 10);
+ QVERIFY(testItem == 0);
+
+ pathview->setCurrentIndex(50);
+ QTest::qWait(5100);//Moving is animated and it's travelling far - should be reconsidered.
+ testItem = findItem<QFxRect>(pathview, "wrapper", 0);
+ QVERIFY(testItem == 0);
+ testItem = findItem<QFxRect>(pathview, "wrapper", 1);
+ QVERIFY(testItem == 0);
+ testItem = findItem<QFxRect>(pathview, "wrapper", 9);
+ QVERIFY(testItem == 0);
+ testItem = findItem<QFxRect>(pathview, "wrapper", 50);
+ QVERIFY(testItem != 0);
+}
+
+QFxView *tst_QFxPathView::createView(const QString &filename)
+{
+ QFxView *canvas = new QFxView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setXml(xml, filename);
+
+ return canvas;
+}
+
+/*
+ Find an item with the specified id. If index is supplied then the
+ item must also evaluate the {index} expression equal to index
+*/
+template<typename T>
+T *tst_QFxPathView::findItem(QFxItem *parent, const QString &id, int index)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ for (int i = 0; i < parent->children()->count(); ++i) {
+ QFxItem *item = parent->children()->at(i);
+ if (mo.cast(item) && (id.isEmpty() || item->id() == id)) {
+ if (index != -1) {
+ QmlExpression e(item->itemContext(), "index", item);
+ e.setTrackChange(false);
+ if (e.value().toInt() == index)
+ return static_cast<T*>(item);
+ } else {
+ return static_cast<T*>(item);
+ }
+ }
+ item = findItem<T>(item, id, index);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_QFxPathView)
+
+#include "tst_pathview.moc"
diff --git a/tests/auto/declarative/qbindablemap/qbindablemap.pro b/tests/auto/declarative/qbindablemap/qbindablemap.pro
new file mode 100644
index 0000000..b042405
--- /dev/null
+++ b/tests/auto/declarative/qbindablemap/qbindablemap.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qbindablemap.cpp
diff --git a/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp b/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp
new file mode 100644
index 0000000..da58857
--- /dev/null
+++ b/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp
@@ -0,0 +1,72 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qbindablemap.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QSignalSpy>
+
+class tst_QBindableMap : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QBindableMap() {}
+
+private slots:
+ void insert();
+ void clear();
+ void changed();
+};
+
+void tst_QBindableMap::insert()
+{
+ QBindableMap map;
+ map.setValue(QLatin1String("key1"),100);
+ map.setValue(QLatin1String("key2"),200);
+ QVERIFY(map.keys().count() == 2);
+
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant(100));
+ QCOMPARE(map.value(QLatin1String("key2")), QVariant(200));
+
+ map.setValue(QLatin1String("key1"),"Hello World");
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World"));
+}
+
+void tst_QBindableMap::clear()
+{
+ QBindableMap map;
+ map.setValue(QLatin1String("key1"),100);
+ QVERIFY(map.keys().count() == 1);
+
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant(100));
+
+ map.clearValue(QLatin1String("key1"));
+ QVERIFY(map.keys().count() == 1);
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant());
+}
+
+void tst_QBindableMap::changed()
+{
+ QBindableMap map;
+ QSignalSpy spy(&map, SIGNAL(changed(const QString&)));
+ map.setValue(QLatin1String("key1"),100);
+ map.setValue(QLatin1String("key2"),200);
+ QCOMPARE(spy.count(), 0);
+
+ map.clearValue(QLatin1String("key1"));
+ QCOMPARE(spy.count(), 0);
+
+ //make changes in QML
+ QmlEngine engine;
+ QmlContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty(QLatin1String("data"), &map);
+ QmlComponent component(&engine, "<Script script=\"data.key1 = 'Hello World';\"/>");
+ component.create();
+ QCOMPARE(spy.count(), 1);
+ QList<QVariant> arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toString(),QLatin1String("key1"));
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World"));
+}
+
+QTEST_MAIN(tst_QBindableMap)
+
+#include "tst_qbindablemap.moc"
diff --git a/tests/auto/declarative/qfxtext/qfxtext.pro b/tests/auto/declarative/qfxtext/qfxtext.pro
new file mode 100644
index 0000000..f705334
--- /dev/null
+++ b/tests/auto/declarative/qfxtext/qfxtext.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+SOURCES += tst_qfxtext.cpp
diff --git a/tests/auto/declarative/qfxtext/tst_qfxtext.cpp b/tests/auto/declarative/qfxtext/tst_qfxtext.cpp
new file mode 100644
index 0000000..ee74040
--- /dev/null
+++ b/tests/auto/declarative/qfxtext/tst_qfxtext.cpp
@@ -0,0 +1,412 @@
+#include <qtest.h>
+#include <QTextDocument>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qfxtext.h>
+#include <QFontMetrics>
+
+class tst_qfxtext : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qfxtext();
+
+private slots:
+ void text();
+ void width();
+ void wrap();
+ void elide();
+
+ // ### these tests may be trivial
+ void hAlign();
+ void vAlign();
+ void font();
+ void style();
+ void color();
+
+private:
+ QStringList standard;
+ QStringList richText;
+
+ QStringList hAlignmentStrings;
+ QStringList vAlignmentStrings;
+
+ QList<Qt::Alignment> vAlignments;
+ QList<Qt::Alignment> hAlignments;
+
+ QStringList styleStrings;
+ QList<QFxText::TextStyle> styles;
+
+ QStringList colorStrings;
+
+ QmlEngine engine;
+};
+
+tst_qfxtext::tst_qfxtext()
+{
+ standard << "the quick brown fox jumped over the lazy dog"
+ << "the quick brown fox\n jumped over the lazy dog";
+
+ richText << "<i>the <b>quick</b> brown <a href=\"http://www.google.com\">fox</a> jumped over the <b>lazy</b> dog</i>"
+ << "<i>the <b>quick</b> brown <a href=\"http://www.google.com\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
+
+ hAlignmentStrings << "AlignLeft"
+ << "AlignRight"
+ << "AlignHCenter";
+
+ vAlignmentStrings << "AlignTop"
+ << "AlignBottom"
+ << "AlignVCenter";
+
+ hAlignments << Qt::AlignLeft
+ << Qt::AlignRight
+ << Qt::AlignHCenter;
+
+ vAlignments << Qt::AlignTop
+ << Qt::AlignBottom
+ << Qt::AlignVCenter;
+
+ styleStrings << "Normal"
+ << "Outline"
+ << "Raised"
+ << "Sunken";
+
+ styles << QFxText::Normal
+ << QFxText::Outline
+ << QFxText::Raised
+ << QFxText::Sunken;
+
+ colorStrings << "aliceblue"
+ << "antiquewhite"
+ << "aqua"
+ << "darkkhaki"
+ << "darkolivegreen"
+ << "dimgray"
+ << "palevioletred"
+ << "lightsteelblue"
+ << "#000000"
+ << "#AAAAAA"
+ << "#FFFFFF"
+ << "#2AC05F";
+ //
+ // need a different test to do alpha channel test
+ // << "#AA0011DD"
+ // << "#00F16B11";
+ //
+}
+
+void tst_qfxtext::text()
+{
+ {
+ QmlComponent textComponent(&engine, "<Text text=\"\" />");
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->text(), QString(""));
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "<Text>" + standard.at(i) + "</Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->text(), standard.at(i));
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "<Text><![CDATA[" + richText.at(i) + "]]></Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QVERIFY(textObject != 0);
+ QCOMPARE(textObject->text(), richText.at(i));
+ }
+}
+
+void tst_qfxtext::width()
+{
+ // uses Font metrics to find the width for standard and document to find the width for rich
+ {
+ QmlComponent textComponent(&engine, "<Text text=\"\"/>");
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 0.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QFont f;
+ QFontMetrics fm(f);
+ int metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
+
+ QString componentStr = "<Text>" + standard.at(i) + "</Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), qreal(metricWidth));
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QTextDocument document;
+ document.setHtml(richText.at(i));
+ document.setDocumentMargin(0);
+
+ int documentWidth = document.idealWidth();
+
+ QString componentStr = "<Text><![CDATA[" + richText.at(i) + "]]></Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), qreal(documentWidth));
+ }
+}
+
+void tst_qfxtext::wrap()
+{
+ // XXX Poor coverage - should at least be testing an expected height.
+
+ // for specified width and wrap set true
+ {
+ QmlComponent textComponent(&engine, "<Text text=\"\" wrap=\"true\" width=\"300\"/>");
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "<Text wrap=\"true\" width=\"300\">" + standard.at(i) + "</Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "<Text wrap=\"true\" width=\"300\"><![CDATA[" + richText.at(i) + "]]></Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+
+}
+
+void tst_qfxtext::elide()
+{
+ for (Qt::TextElideMode m = Qt::ElideLeft; m<=Qt::ElideNone; m=Qt::TextElideMode(int(m)+1)) {
+ const char* elidename[]={"ElideLeft", "ElideRight", "ElideMiddle", "ElideNone"};
+ QString elide = "elide=\""+QString(elidename[int(m)])+"\"";
+
+ // XXX Poor coverage.
+
+ {
+ QmlComponent textComponent(&engine, ("<Text text=\"\" "+elide+" width=\"300\"/>").toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "<Text "+elide+" width=\"300\">" + standard.at(i) + "</Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+
+ // richtext - does nothing
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "<Text "+elide+" width=\"300\"><![CDATA[" + richText.at(i) + "]]></Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->width(), 300.);
+ }
+ }
+}
+
+//the alignment tests may be trivial o.oa
+void tst_qfxtext::hAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "<Text hAlign=\"" + hAlignmentStrings.at(j) + "\">" + standard.at(i) + "</Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "<Text hAlign=\"" + hAlignmentStrings.at(j) + "\"><![CDATA[" + richText.at(i) + "]]></Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qfxtext::vAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "<Text vAlign=\"" + vAlignmentStrings.at(j) + "\">" + standard.at(i) + "</Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "<Text vAlign=\"" + vAlignmentStrings.at(j) + "\"><![CDATA[" + richText.at(i) + "]]></Text>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qfxtext::font()
+{
+ //test size, then bold, then italic, then family
+ {
+ QString componentStr = "<Text font.size=\"40\" text=\"Hello World\"/>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->font()->size(), qreal(40));
+ QCOMPARE(textObject->font()->bold(), false);
+ QCOMPARE(textObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "<Text font.bold=\"true\" text=\"Hello World\"/>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->font()->bold(), true);
+ QCOMPARE(textObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "<Text font.italic=\"true\" text=\"Hello World\"/>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->font()->italic(), true);
+ QCOMPARE(textObject->font()->bold(), false);
+ }
+
+ {
+ QString componentStr = "<Text font.family=\"Helvetica\" text=\"Hello World\"/>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->font()->family(), QString("Helvetica"));
+ QCOMPARE(textObject->font()->bold(), false);
+ QCOMPARE(textObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "<Text font.family=\"\" text=\"Hello World\"/>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->font()->family(), QString(""));
+ }
+}
+
+void tst_qfxtext::style()
+{
+ //test style
+ for (int i = 0; i < styles.size(); i++)
+ {
+ QString componentStr = "<Text style=\"" + styleStrings.at(i) + "\" text=\"Hello World\"/>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE((int)textObject->style(), (int)styles.at(i));
+ QCOMPARE(textObject->styleColor(), QColor());
+ }
+}
+
+void tst_qfxtext::color()
+{
+ //test style
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "<Text color=\"" + colorStrings.at(i) + "\" text=\"Hello World\"/>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
+ QCOMPARE(textObject->styleColor(), QColor());
+ }
+
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "<Text styleColor=\"" + colorStrings.at(i) + "\" text=\"Hello World\"/>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(i)));
+ // default color to black?
+ QCOMPARE(textObject->color(), QColor("black"));
+ }
+
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ for (int j = 0; j < colorStrings.size(); j++)
+ {
+ QString componentStr = "<Text color=\"" + colorStrings.at(i) + "\" styleColor=\"" + colorStrings.at(j) + "\" text=\"Hello World\"/>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
+ QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(j)));
+ }
+ }
+ {
+ QString colorStr = "#AA001234";
+ QColor testColor("#001234");
+ testColor.setAlpha(170);
+
+ QString componentStr = "<Text color=\"" + colorStr + "\" text=\"Hello World\"/>";
+ QmlComponent textComponent(&engine, componentStr.toLatin1());
+ QFxText *textObject = qobject_cast<QFxText*>(textComponent.create());
+
+ QCOMPARE(textObject->color(), testColor);
+ }
+}
+QTEST_MAIN(tst_qfxtext)
+
+#include "tst_qfxtext.moc"
diff --git a/tests/auto/declarative/qfxtextedit/qfxtextedit.pro b/tests/auto/declarative/qfxtextedit/qfxtextedit.pro
new file mode 100644
index 0000000..59ab6e5
--- /dev/null
+++ b/tests/auto/declarative/qfxtextedit/qfxtextedit.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+SOURCES += tst_qfxtextedit.cpp
diff --git a/tests/auto/declarative/qfxtextedit/tst_qfxtextedit.cpp b/tests/auto/declarative/qfxtextedit/tst_qfxtextedit.cpp
new file mode 100644
index 0000000..8baef3d
--- /dev/null
+++ b/tests/auto/declarative/qfxtextedit/tst_qfxtextedit.cpp
@@ -0,0 +1,326 @@
+#include <qtest.h>
+#include <QTextDocument>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qfxtextedit.h>
+#include <QFontMetrics>
+
+class tst_qfxtextedit : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qfxtextedit();
+
+private slots:
+ void text();
+ void width();
+ void wrap();
+
+ // ### these tests may be trivial
+ void hAlign();
+ void vAlign();
+ void font();
+ void color();
+
+private:
+ QStringList standard;
+ QStringList richText;
+
+ QStringList hAlignmentStrings;
+ QStringList vAlignmentStrings;
+
+ QList<Qt::Alignment> vAlignments;
+ QList<Qt::Alignment> hAlignments;
+
+ QStringList colorStrings;
+
+ QmlEngine engine;
+};
+
+tst_qfxtextedit::tst_qfxtextedit()
+{
+ standard << "the quick brown fox jumped over the lazy dog"
+ << "the quick brown fox\n jumped over the lazy dog";
+
+ richText << "<i>the <b>quick</b> brown <a href=\"http://www.google.com\">fox</a> jumped over the <b>lazy</b> dog</i>"
+ << "<i>the <b>quick</b> brown <a href=\"http://www.google.com\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
+
+ hAlignmentStrings << "AlignLeft"
+ << "AlignRight"
+ << "AlignHCenter";
+
+ vAlignmentStrings << "AlignTop"
+ << "AlignBottom"
+ << "AlignVCenter";
+
+ hAlignments << Qt::AlignLeft
+ << Qt::AlignRight
+ << Qt::AlignHCenter;
+
+ vAlignments << Qt::AlignTop
+ << Qt::AlignBottom
+ << Qt::AlignVCenter;
+
+ colorStrings << "aliceblue"
+ << "antiquewhite"
+ << "aqua"
+ << "darkkhaki"
+ << "darkolivegreen"
+ << "dimgray"
+ << "palevioletred"
+ << "lightsteelblue"
+ << "#000000"
+ << "#AAAAAA"
+ << "#FFFFFF"
+ << "#2AC05F";
+ //
+ // need a different test to do alpha channel test
+ // << "#AA0011DD"
+ // << "#00F16B11";
+ //
+}
+
+void tst_qfxtextedit::text()
+{
+ {
+ QmlComponent texteditComponent(&engine, "<TextEdit text=\"\" />");
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->text(), QString(""));
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "<TextEdit>" + standard.at(i) + "</TextEdit>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QCOMPARE(textEditObject->text(), standard.at(i));
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "<TextEdit><![CDATA[" + richText.at(i) + "]]></TextEdit>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QVERIFY(textEditObject != 0);
+ QString actual = textEditObject->text();
+ QString expected = richText.at(i);
+ actual.replace(QRegExp(".*<body[^>]*>"),"");
+ actual.replace(QRegExp("(<[^>]*>)+"),"<>");
+ expected.replace(QRegExp("(<[^>]*>)+"),"<>");
+ QCOMPARE(actual.simplified(),expected.simplified());
+ }
+}
+
+void tst_qfxtextedit::width()
+{
+ // uses Font metrics to find the width for standard and document to find the width for rich
+ {
+ QmlComponent texteditComponent(&engine, "<TextEdit text=\"\"/>");
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), 0.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QFont f;
+ QFontMetrics fm(f);
+ int metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
+
+ QString componentStr = "<TextEdit>" + standard.at(i) + "</TextEdit>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), qreal(metricWidth));
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QTextDocument document;
+ document.setHtml(richText.at(i));
+ document.setDocumentMargin(0);
+
+ int documentWidth = document.idealWidth();
+
+ QString componentStr = "<TextEdit><![CDATA[" + richText.at(i) + "]]></TextEdit>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), qreal(documentWidth));
+ }
+}
+
+void tst_qfxtextedit::wrap()
+{
+ // for specified width and wrap set true
+ {
+ QmlComponent texteditComponent(&engine, "<TextEdit text=\"\" wrap=\"true\" width=\"300\"/>");
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ QString componentStr = "<TextEdit wrap=\"true\" width=\"300\">" + standard.at(i) + "</TextEdit>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ QString componentStr = "<TextEdit wrap=\"true\" width=\"300\"><![CDATA[" + richText.at(i) + "]]></TextEdit>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->width(), 300.);
+ }
+
+}
+
+//the alignment tests may be trivial o.oa
+void tst_qfxtextedit::hAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "<TextEdit hAlign=\"" + hAlignmentStrings.at(j) + "\">" + standard.at(i) + "</TextEdit>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < hAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "<TextEdit hAlign=\"" + hAlignmentStrings.at(j) + "\"><![CDATA[" + richText.at(i) + "]]></TextEdit>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qfxtextedit::vAlign()
+{
+ //test one align each, and then test if two align fails.
+
+ for (int i = 0; i < standard.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "<TextEdit vAlign=\"" + vAlignmentStrings.at(j) + "\">" + standard.at(i) + "</TextEdit>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+ for (int i = 0; i < richText.size(); i++)
+ {
+ for (int j=0; j < vAlignmentStrings.size(); j++)
+ {
+ QString componentStr = "<TextEdit vAlign=\"" + vAlignmentStrings.at(j) + "\"><![CDATA[" + richText.at(i) + "]]></TextEdit>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
+ }
+ }
+
+}
+
+void tst_qfxtextedit::font()
+{
+ //test size, then bold, then italic, then family
+ {
+ QString componentStr = "<TextEdit font.size=\"40\" text=\"Hello World\"/>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->font()->size(), qreal(40));
+ QCOMPARE(textEditObject->font()->bold(), false);
+ QCOMPARE(textEditObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "<TextEdit font.bold=\"true\" text=\"Hello World\"/>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->font()->bold(), true);
+ QCOMPARE(textEditObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "<TextEdit font.italic=\"true\" text=\"Hello World\"/>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->font()->italic(), true);
+ QCOMPARE(textEditObject->font()->bold(), false);
+ }
+
+ {
+ QString componentStr = "<TextEdit font.family=\"Helvetica\" text=\"Hello World\"/>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->font()->family(), QString("Helvetica"));
+ QCOMPARE(textEditObject->font()->bold(), false);
+ QCOMPARE(textEditObject->font()->italic(), false);
+ }
+
+ {
+ QString componentStr = "<TextEdit font.family=\"\" text=\"Hello World\"/>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->font()->family(), QString(""));
+ }
+}
+
+void tst_qfxtextedit::color()
+{
+ //test style
+ for (int i = 0; i < colorStrings.size(); i++)
+ {
+ QString componentStr = "<TextEdit color=\"" + colorStrings.at(i) + "\" text=\"Hello World\"/>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+ //qDebug() << "textEditObject: " << textEditObject->color() << "vs. " << QColor(colorStrings.at(i));
+ QCOMPARE(textEditObject->color(), QColor(colorStrings.at(i)));
+ }
+
+ {
+ QString colorStr = "#AA001234";
+ QColor testColor("#001234");
+ testColor.setAlpha(170);
+
+ QString componentStr = "<TextEdit color=\"" + colorStr + "\" text=\"Hello World\"/>";
+ QmlComponent texteditComponent(&engine, componentStr.toLatin1());
+ QFxTextEdit *textEditObject = qobject_cast<QFxTextEdit*>(texteditComponent.create());
+
+ QCOMPARE(textEditObject->color(), testColor);
+ }
+}
+QTEST_MAIN(tst_qfxtextedit)
+
+#include "tst_qfxtextedit.moc"
diff --git a/tests/auto/declarative/qmlbindengine/qmlbindengine.pro b/tests/auto/declarative/qmlbindengine/qmlbindengine.pro
new file mode 100644
index 0000000..6d84931
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/qmlbindengine.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlbindengine.cpp
diff --git a/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp b/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp
new file mode 100644
index 0000000..f5b32e8
--- /dev/null
+++ b/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp
@@ -0,0 +1,123 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlengine.h>
+
+class MyQmlObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool trueProperty READ trueProperty)
+ Q_PROPERTY(bool falseProperty READ falseProperty)
+ Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty)
+public:
+ MyQmlObject(): m_methodCalled(false), m_methodIntCalled(false) {}
+
+ bool trueProperty() const { return true; }
+ bool falseProperty() const { return false; }
+
+ QString stringProperty() const { return m_string; }
+ void setStringProperty(const QString &s) { m_string = s; }
+
+ bool methodCalled() const { return m_methodCalled; }
+ bool methodIntCalled() const { return m_methodIntCalled; }
+
+ QString string() const { return m_string; }
+signals:
+ void basicSignal();
+ void argumentSignal(int a, QString b, qreal c);
+
+public slots:
+ void method() { m_methodCalled = true; }
+ void method(int a) { if(a == 163) m_methodIntCalled = true; }
+ void setString(const QString &s) { m_string = s; }
+
+private:
+ friend class tst_qmlbindengine;
+ bool m_methodCalled;
+ bool m_methodIntCalled;
+
+ QString m_string;
+};
+
+QML_DECLARE_TYPE(MyQmlObject);
+QML_DEFINE_TYPE(MyQmlObject,MyQmlObject);
+
+class tst_qmlbindengine : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlbindengine() {}
+
+private slots:
+ void boolPropertiesEvaluateAsBool();
+ void methods();
+ void signalAssignment();
+
+private:
+ QmlEngine engine;
+};
+
+void tst_qmlbindengine::boolPropertiesEvaluateAsBool()
+{
+ {
+ QmlComponent component(&engine, "<MyQmlObject stringProperty=\"{trueProperty?'pass':'fail'}\" />");
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->stringProperty(), QLatin1String("pass"));
+ }
+ {
+ QmlComponent component(&engine, "<MyQmlObject stringProperty=\"{falseProperty?'fail':'pass'}\" />");
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->stringProperty(), QLatin1String("pass"));
+ }
+}
+
+void tst_qmlbindengine::signalAssignment()
+{
+ {
+ QmlComponent component(&engine, "<MyQmlObject onBasicSignal=\"setString('pass')\" />");
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->string(), QString());
+ emit object->basicSignal();
+ QCOMPARE(object->string(), QString("pass"));
+ }
+
+ {
+ QmlComponent component(&engine, "<MyQmlObject onArgumentSignal=\"setString('pass ' + a + ' ' + b + ' ' + c)\" />");
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->string(), QString());
+ emit object->argumentSignal(19, "Hello world!", 10.3);
+ QCOMPARE(object->string(), QString("pass 19 Hello world! 10.3"));
+ }
+}
+
+void tst_qmlbindengine::methods()
+{
+ {
+ QmlComponent component(&engine, "<MyQmlObject id=\"MyObject\" onBasicSignal=\"MyObject.method()\" />");
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->methodCalled(), false);
+ QCOMPARE(object->methodIntCalled(), false);
+ emit object->basicSignal();
+ QCOMPARE(object->methodCalled(), true);
+ QCOMPARE(object->methodIntCalled(), false);
+ }
+
+ {
+ QmlComponent component(&engine, "<MyQmlObject id=\"MyObject\" onBasicSignal=\"MyObject.method(163)\" />");
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->methodCalled(), false);
+ QCOMPARE(object->methodIntCalled(), false);
+ emit object->basicSignal();
+ QCOMPARE(object->methodCalled(), false);
+ QCOMPARE(object->methodIntCalled(), true);
+ }
+}
+
+QTEST_MAIN(tst_qmlbindengine)
+
+#include "tst_qmlbindengine.moc"
diff --git a/tests/auto/declarative/qmllist/qmllist.pro b/tests/auto/declarative/qmllist/qmllist.pro
new file mode 100644
index 0000000..e5558f1
--- /dev/null
+++ b/tests/auto/declarative/qmllist/qmllist.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmllist.cpp
diff --git a/tests/auto/declarative/qmllist/tst_qmllist.cpp b/tests/auto/declarative/qmllist/tst_qmllist.cpp
new file mode 100644
index 0000000..541ca64
--- /dev/null
+++ b/tests/auto/declarative/qmllist/tst_qmllist.cpp
@@ -0,0 +1,38 @@
+#include <qtest.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlprivate.h>
+
+class tst_QmlList : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlList() {}
+
+private slots:
+ void interface();
+};
+
+void tst_QmlList::interface()
+{
+ QmlConcreteList<QObject*> list;
+ QObject *obj = new QObject;
+ obj->setObjectName("foo");
+ list.append(obj);
+ QVERIFY(list.count() == 1);
+ QCOMPARE(list.at(0), obj);
+
+ QmlPrivate::ListInterface *li = (QmlPrivate::ListInterface*)&list;
+
+ void *ptr[1];
+ li->at(0, ptr);
+ QVERIFY(li->count() == 1);
+ QCOMPARE(ptr[0], obj);
+
+ li->removeAt(0);
+ QVERIFY(li->count() == 0);
+ QVERIFY(list.count() == 0);
+}
+
+QTEST_MAIN(tst_QmlList)
+
+#include "tst_qmllist.moc"
diff --git a/tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro b/tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro
new file mode 100644
index 0000000..4aa0450
--- /dev/null
+++ b/tests/auto/declarative/qmllistaccessor/qmllistaccessor.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmllistaccessor.cpp
diff --git a/tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp b/tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp
new file mode 100644
index 0000000..f5b57ea
--- /dev/null
+++ b/tests/auto/declarative/qmllistaccessor/tst_qmllistaccessor.cpp
@@ -0,0 +1,61 @@
+#include <qtest.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmllistaccessor.h>
+
+class tst_QmlListAccessor : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlListAccessor() {}
+
+private slots:
+ void qmllist();
+ //void qlist();
+ //void qstringlist();
+};
+
+void tst_QmlListAccessor::qmllist()
+{
+ QmlConcreteList<QObject*> list;
+ QObject *obj = new QObject;
+ list.append(obj);
+ QVERIFY(list.count() == 1);
+ QCOMPARE(list.at(0), obj);
+
+ QmlListAccessor accessor;
+ accessor.setList(qVariantFromValue((QmlList<QObject*>*)&list));
+
+ QVERIFY(accessor.isValid());
+ QVERIFY(accessor.count() == 1);
+
+ QVariant v = accessor.at(0);
+ QCOMPARE(qvariant_cast<QObject*>(v), obj);
+
+ accessor.removeAt(3);
+ QVERIFY(accessor.count() == 1);
+
+ accessor.removeAt(0);
+ QVERIFY(accessor.count() == 0);
+
+ accessor.insert(4, qVariantFromValue(obj));
+ QVERIFY(accessor.count() == 1);
+
+ v = accessor.at(0);
+ QCOMPARE(qvariant_cast<QObject*>(v), obj);
+
+ QObject *obj2 = new QObject;
+ accessor.append(qVariantFromValue(obj2));
+ QVERIFY(accessor.count() == 2);
+
+ v = accessor.at(1);
+ QCOMPARE(qvariant_cast<QObject*>(v), obj2);
+
+ accessor.clear();
+ QVERIFY(accessor.count() == 0);
+
+ QVERIFY(accessor.isValid());
+}
+
+QTEST_MAIN(tst_QmlListAccessor)
+
+#include "tst_qmllistaccessor.moc"
diff --git a/tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro b/tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro
new file mode 100644
index 0000000..af67373
--- /dev/null
+++ b/tests/auto/declarative/qmlmetaproperty/qmlmetaproperty.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlmetaproperty.cpp
diff --git a/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp b/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp
new file mode 100644
index 0000000..3a87070
--- /dev/null
+++ b/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp
@@ -0,0 +1,104 @@
+#include <qtest.h>
+#include <QtDeclarative/QmlEngine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlmetaproperty.h>
+#include <QtGui/QLineEdit>
+
+class MyQmlObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyQmlObject() {}
+};
+
+QML_DECLARE_TYPE(MyQmlObject);
+QML_DEFINE_TYPE(MyQmlObject,MyQmlObject);
+
+class MyContainer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<MyQmlObject*>* children READ children)
+ Q_PROPERTY(QmlList<MyQmlObject*>* qmlChildren READ qmlChildren)
+public:
+ MyContainer() {}
+
+ QList<MyQmlObject*> *children() { return &m_children; }
+ QmlConcreteList<MyQmlObject *> *qmlChildren() { return &m_qmlChildren; }
+
+private:
+ QList<MyQmlObject*> m_children;
+ QmlConcreteList<MyQmlObject *> m_qmlChildren;
+};
+
+QML_DECLARE_TYPE(MyContainer);
+QML_DEFINE_TYPE(MyContainer,MyContainer);
+
+class tst_QmlMetaProperty : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QmlMetaProperty() {}
+
+private slots:
+ void writeObjectToList();
+ void writeListToList();
+ void writeObjectToQmlList();
+
+ //writeToReadOnly();
+
+private:
+ QmlEngine engine;
+};
+
+void tst_QmlMetaProperty::writeObjectToList()
+{
+ QmlComponent containerComponent(&engine, "<MyContainer><children><MyQmlObject/></children></MyContainer>");
+ MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->children()->size() == 1);
+
+ MyQmlObject *object = new MyQmlObject;
+ QmlMetaProperty prop(container, "children");
+ prop.write(qVariantFromValue(object));
+ QCOMPARE(container->children()->size(), 2);
+ QCOMPARE(container->children()->at(1), object);
+}
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+void tst_QmlMetaProperty::writeListToList()
+{
+ QmlComponent containerComponent(&engine, "<MyContainer><children><MyQmlObject/></children></MyContainer>");
+ MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->children()->size() == 1);
+
+ QList<QObject*> objList;
+ objList << new MyQmlObject() << new MyQmlObject() << new MyQmlObject() << new MyQmlObject();
+ QmlMetaProperty prop(container, "children");
+ prop.write(qVariantFromValue(objList));
+ QCOMPARE(container->children()->size(), 4);
+
+ //XXX need to try this with read/write prop (for read-only it correctly doesn't write)
+ /*QList<MyQmlObject*> typedObjList;
+ typedObjList << new MyQmlObject();
+ prop.write(qVariantFromValue(&typedObjList));
+ QCOMPARE(container->children()->size(), 1);*/
+}
+
+void tst_QmlMetaProperty::writeObjectToQmlList()
+{
+ QmlComponent containerComponent(&engine, "<MyContainer><qmlChildren><MyQmlObject/></qmlChildren></MyContainer>");
+ MyContainer *container = qobject_cast<MyContainer*>(containerComponent.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->qmlChildren()->size() == 1);
+
+ MyQmlObject *object = new MyQmlObject;
+ QmlMetaProperty prop(container, "qmlChildren");
+ prop.write(qVariantFromValue(object));
+ QCOMPARE(container->qmlChildren()->size(), 2);
+ QCOMPARE(container->qmlChildren()->at(1), object);
+}
+
+QTEST_MAIN(tst_QmlMetaProperty)
+
+#include "tst_qmlmetaproperty.moc"
diff --git a/tests/auto/declarative/qmlparser/qmlparser.pro b/tests/auto/declarative/qmlparser/qmlparser.pro
new file mode 100644
index 0000000..3e0b6ea
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/qmlparser.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_qmlparser.cpp
diff --git a/tests/auto/declarative/qmlparser/tst_qmlparser.cpp b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp
new file mode 100644
index 0000000..24d3c22
--- /dev/null
+++ b/tests/auto/declarative/qmlparser/tst_qmlparser.cpp
@@ -0,0 +1,444 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+
+class MyInterface
+{
+public:
+ MyInterface() : id(913) {}
+ int id;
+};
+
+Q_DECLARE_INTERFACE(MyInterface, "com.trolltech.Qt.Test.MyInterface");
+QML_DECLARE_INTERFACE(MyInterface);
+QML_DEFINE_INTERFACE(MyInterface);
+
+class MyQmlObject : public QObject, public MyInterface
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+ Q_PROPERTY(QString readOnlyString READ readOnlyString)
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled)
+ Q_PROPERTY(QRect rect READ rect WRITE setRect)
+ Q_PROPERTY(QMatrix matrix READ matrix WRITE setMatrix) //assumed to be unsupported by QML
+ Q_PROPERTY(MyInterface *interface READ interface WRITE setInterface)
+ Q_INTERFACES(MyInterface)
+public:
+ MyQmlObject() : m_value(-1), m_interface(0) {}
+
+ int value() const { return m_value; }
+ void setValue(int v) { m_value = v; }
+
+ QString readOnlyString() const { return QLatin1String(""); }
+
+ bool enabled() const { return false; }
+ void setEnabled(bool) {}
+
+ QRect rect() const { return QRect(); }
+ void setRect(const QRect&) {}
+
+ QMatrix matrix() const { return QMatrix(); }
+ void setMatrix(const QMatrix&) {}
+
+ MyInterface *interface() const { return m_interface; }
+ void setInterface(MyInterface *iface) { m_interface = iface; }
+
+ Q_CLASSINFO("defaultMethod", "basicSlot()");
+
+public slots:
+ void basicSlot() { qWarning("MyQmlObject::basicSlot"); }
+
+signals:
+ void basicSignal();
+
+private:
+ friend class tst_qmlparser;
+ int m_value;
+ MyInterface *m_interface;
+};
+
+QML_DECLARE_TYPE(MyQmlObject);
+QML_DEFINE_TYPE(MyQmlObject,MyQmlObject);
+
+class MyContainer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<QObject*>* children READ children)
+ Q_PROPERTY(QList<MyInterface*>* qlistInterfaces READ qlistInterfaces)
+ Q_PROPERTY(QmlList<MyInterface*>* qmllistInterfaces READ qmllistInterfaces)
+ Q_CLASSINFO("DefaultProperty", "children");
+public:
+ MyContainer() {}
+
+ QList<QObject*> *children() { return &m_children; }
+ QList<MyInterface *> *qlistInterfaces() { return &m_interfaces; }
+ QmlList<MyInterface *> *qmllistInterfaces() { return &m_qmlinterfaces; }
+ const QmlConcreteList<MyInterface *> &qmllistAccessor() const { return m_qmlinterfaces; }
+
+private:
+ QList<QObject*> m_children;
+ QList<MyInterface *> m_interfaces;
+ QmlConcreteList<MyInterface *> m_qmlinterfaces;
+};
+
+QML_DECLARE_TYPE(MyContainer);
+QML_DEFINE_TYPE(MyContainer,MyContainer);
+
+class MyDotPropertyObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(MyQmlObject *obj READ obj)
+ Q_PROPERTY(MyQmlObject *readWriteObj READ readWriteObj WRITE setReadWriteObj)
+public:
+ MyDotPropertyObject() : m_rwobj(0), m_ownRWObj(false) {}
+ ~MyDotPropertyObject()
+ {
+ if (m_ownRWObj)
+ delete m_rwobj;
+ }
+
+ MyQmlObject *obj() { return 0; }
+
+ MyQmlObject *readWriteObj()
+ {
+ if (!m_rwobj) {
+ m_rwobj = new MyQmlObject;
+ m_ownRWObj = true;
+ }
+ return m_rwobj;
+ }
+
+ void setReadWriteObj(MyQmlObject *obj)
+ {
+ if (m_ownRWObj) {
+ delete m_rwobj;
+ m_ownRWObj = false;
+ }
+
+ m_rwobj = obj;
+ }
+
+private:
+ MyQmlObject *m_rwobj;
+ bool m_ownRWObj;
+};
+
+QML_DECLARE_TYPE(MyDotPropertyObject);
+QML_DEFINE_TYPE(MyDotPropertyObject,MyDotPropertyObject);
+
+class tst_qmlparser : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qmlparser() {}
+
+private slots:
+ void simpleObject();
+ void simpleContainer();
+ void unregisteredObject();
+ void nonexistantProperty();
+ void unsupportedProperty();
+ //void setProperties();
+ void wrongType();
+ void readOnly();
+ //void dotProperties();
+ void nullDotProperty();
+ void fakeDotProperty();
+ //void readWriteDotProperty();
+ void emptyInput();
+ void missingObject();
+ void invalidXML();
+ void duplicateIDs();
+ void invalidID();
+ void interfaceProperty();
+ void interfaceQmlList();
+ void interfaceQList();
+ void cannotAssignBindingToSignal();
+ void assignObjectToSignal();
+
+private:
+ QmlEngine engine;
+};
+
+void tst_qmlparser::simpleObject()
+{
+ QmlComponent component(&engine, "<MyQmlObject/>");
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
+void tst_qmlparser::simpleContainer()
+{
+ QmlComponent component(&engine, "<MyContainer>\n<MyQmlObject/>\n<MyQmlObject/>\n</MyContainer>");
+ MyContainer *container= qobject_cast<MyContainer*>(component.create());
+ QVERIFY(container != 0);
+ QCOMPARE(container->children()->count(),2);
+}
+
+void tst_qmlparser::unregisteredObject()
+{
+ QmlComponent component(&engine, "<UnRegisteredObject/>", QUrl("myprogram.qml"));
+ QTest::ignoreMessage(QtWarningMsg, "Unable to create object of type 'UnRegisteredObject' @myprogram.qml:1");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+}
+
+void tst_qmlparser::nonexistantProperty()
+{
+ //NOTE: these first 3 should all have the same error message
+ {
+ QmlComponent component(&engine, "<MyQmlObject something=\"24\"/>");
+ QTest::ignoreMessage(QtWarningMsg, "Unknown property 'something' @<unspecified file>:1");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+
+ {
+ QmlComponent component(&engine, "<MyQmlObject>\n<something>24</something>\n</MyQmlObject>");
+ QTest::ignoreMessage(QtWarningMsg, "Unknown property 'something' @<unspecified file>:2");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+
+ //non-existant using binding
+ {
+ QmlComponent component(&engine, "<MyQmlObject something=\"{1}\"/>");
+ QTest::ignoreMessage(QtWarningMsg, "Unknown property 'something' @<unspecified file>:1");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+
+ {
+ QmlComponent component(&engine, "<MyQmlObject><something></something></MyQmlObject>");
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ }
+
+ //non-existant value-type default property
+ {
+ QmlComponent component(&engine, "<MyQmlObject>\n24\n</MyQmlObject>");
+ QTest::ignoreMessage(QtWarningMsg, "Unable to resolve default property @<unspecified file>:3");
+ // XXX would 2 be a better line number in this case? Message should also be improved.
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+
+ //non-existant object-type default property
+ {
+ QmlComponent component(&engine, "<MyQmlObject>\n<MyQmlObject/>\n</MyQmlObject>");
+ QTest::ignoreMessage(QtWarningMsg, "Unable to assign to non-existant property @<unspecified file>:2");
+ // XXX Message needs to be improved (and should be closer to value-type message).
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+}
+
+void tst_qmlparser::unsupportedProperty()
+{
+ QTest::ignoreMessage(QtWarningMsg, "Property 'matrix' is of an unknown type @<unspecified file>:1");
+ QmlComponent component(&engine, "<MyQmlObject matrix=\"1,0,0,0,1,0,0,0,1\"/>");
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object == 0);
+}
+
+void tst_qmlparser::wrongType()
+{
+ //string for int
+ {
+ QTest::ignoreMessage(QtWarningMsg, "Can't assign value 'hello' to property 'value' @<unspecified file>:1");
+ QmlComponent component(&engine, "<MyQmlObject value=\"hello\"/>");
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object == 0);
+ }
+
+ //int for bool
+ {
+ QTest::ignoreMessage(QtWarningMsg, "Can't assign value '5' to property 'enabled' @<unspecified file>:1");
+ QmlComponent component(&engine, "<MyQmlObject enabled=\"5\"/>");
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object == 0);
+ }
+
+ //bad format for rect
+ {
+ QTest::ignoreMessage(QtWarningMsg, "Can't assign value '5,5x10' to property 'rect' @<unspecified file>:1");
+ QmlComponent component(&engine, "<MyQmlObject rect=\"5,5x10\"/>");
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object == 0);
+ }
+
+ //TODO: more types (including float-to-int, complex types, etc)
+}
+
+void tst_qmlparser::readOnly()
+{
+ {
+ QTest::ignoreMessage(QtWarningMsg, "Can't assign value 'hello' to property 'readOnlyString' because 'readOnlyString' is read-only @<unspecified file>:1");
+ QmlComponent component(&engine, "<MyQmlObject readOnlyString=\"hello\"/>");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+
+ {
+ QTest::ignoreMessage(QtWarningMsg, "Can't assign a binding to property 'readOnlyString' because 'readOnlyString' is read-only @<unspecified file>:1");
+ QmlComponent component(&engine, "<MyQmlObject readOnlyString=\"{'hello'}\"/>");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+}
+
+void tst_qmlparser::nullDotProperty()
+{
+ QTest::ignoreMessage(QtWarningMsg, "Can't set properties on 'obj' because it is null @<unspecified file>:1");
+ QmlComponent component(&engine, "<MyDotPropertyObject obj.value=\"1\"/>");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+}
+
+void tst_qmlparser::fakeDotProperty()
+{
+ QTest::ignoreMessage(QtWarningMsg, "Can't set properties on 'value' because it isn't a known object type @<unspecified file>:1");
+ QmlComponent component(&engine, "<MyQmlObject value.something=\"hello\"/>");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+}
+
+//XXX need to define correct behavior first
+/*void tst_qmlparser::readWriteDotProperty()
+{
+ QmlComponent component(&engine, "<MyDotPropertyObject readWriteObj.value=\"1\"/>");
+ MyDotPropertyObject *object = qobject_cast<MyDotPropertyObject*>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->readWriteObj()->value(),1);
+
+ {
+ QmlComponent component(&engine, "<MyContainer><MyQmlObject id=\"Obj\" value=\"1\"/><MyDotPropertyObject readWriteObj=\"{Obj}\"/></MyContainer>");
+ MyContainer *object = qobject_cast<MyContainer*>(component.create());
+ QVERIFY(object != 0);
+ MyDotPropertyObject *dpo = qobject_cast<MyDotPropertyObject *>(object->children()->at(1));
+ QCOMPARE(dpo->readWriteObj()->value(),1);
+ }
+}*/
+
+void tst_qmlparser::emptyInput()
+{
+ QTest::ignoreMessage(QtCriticalMsg, "No Qml was specified for parsing.");
+ QTest::ignoreMessage(QtWarningMsg, "Can't compile because of earlier errors @<unspecified file>:-1");
+ QmlComponent component(&engine, "");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+}
+
+void tst_qmlparser::missingObject()
+{
+ QTest::ignoreMessage(QtCriticalMsg, "Can't have a property with no object @<unspecified file>:1");
+ QTest::ignoreMessage(QtWarningMsg, "Can't compile because of earlier errors @<unspecified file>:-1");
+ QmlComponent component(&engine, "<something/>");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+}
+
+
+void tst_qmlparser::invalidXML()
+{
+ //extra stuff on end
+ {
+ QTest::ignoreMessage(QtCriticalMsg, "Extra content at end of document. @myprogram.qml:1");
+ QTest::ignoreMessage(QtWarningMsg, "Can't compile because of earlier errors @myprogram.qml:-1");
+ QmlComponent component(&engine, "<MyQmlObject/><something/>", QUrl("myprogram.qml"));
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+
+ //mismatched tags
+ {
+ QTest::ignoreMessage(QtCriticalMsg, "Opening and ending tag mismatch. @myprogram.qml:2");
+ QTest::ignoreMessage(QtWarningMsg, "Can't compile because of earlier errors @myprogram.qml:-1");
+ QmlComponent component(&engine, "<MyQmlObject>\n</MyContainer>", QUrl("myprogram.qml"));
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+
+ {
+ QTest::ignoreMessage(QtCriticalMsg, "Expected '>' or '/', but got '<'. @myprogram.qml:1");
+ QTest::ignoreMessage(QtWarningMsg, "Can't compile because of earlier errors @myprogram.qml:-1");
+ QmlComponent component(&engine, "<MyQmlObject < />", QUrl("myprogram.qml"));
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+
+ {
+ QTest::ignoreMessage(QtCriticalMsg, "Premature end of document. @myprogram.qml:1");
+ QTest::ignoreMessage(QtWarningMsg, "Can't compile because of earlier errors @myprogram.qml:-1");
+ QmlComponent component(&engine, "<MyQmlObject something=\" />", QUrl("myprogram.qml"));
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+ }
+
+}
+
+void tst_qmlparser::duplicateIDs()
+{
+ QTest::ignoreMessage(QtWarningMsg, "An id (\"MyID\") is not unique within its scope. @<unspecified file>:3");
+ QmlComponent component(&engine, "<MyContainer>\n<MyQmlObject id=\"MyID\"/>\n<MyQmlObject id=\"MyID\"/>\n</MyContainer>");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+}
+
+void tst_qmlparser::invalidID()
+{
+ QTest::ignoreMessage(QtWarningMsg, "'1' is not a valid id @<unspecified file>:1");
+ QmlComponent component(&engine, "<MyQmlObject id=\"1\"/>");
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+}
+
+void tst_qmlparser::interfaceProperty()
+{
+ QmlComponent component(&engine, "<MyQmlObject><interface>\n<MyQmlObject/></interface>\n</MyQmlObject>");
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+ QVERIFY(object->interface());
+ QVERIFY(object->interface()->id == 913);
+}
+
+void tst_qmlparser::interfaceQmlList()
+{
+ QmlComponent component(&engine, "<MyContainer><qmllistInterfaces>\n<MyQmlObject/>\n<MyQmlObject/>\n</qmllistInterfaces>\n</MyContainer>");
+ MyContainer *container= qobject_cast<MyContainer*>(component.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->qmllistAccessor().count() == 2);
+ for(int ii = 0; ii < 2; ++ii)
+ QVERIFY(container->qmllistAccessor().at(ii)->id == 913);
+}
+
+void tst_qmlparser::interfaceQList()
+{
+ QmlComponent component(&engine, "<MyContainer><qlistInterfaces>\n<MyQmlObject/>\n<MyQmlObject/>\n</qlistInterfaces>\n</MyContainer>");
+ MyContainer *container= qobject_cast<MyContainer*>(component.create());
+ QVERIFY(container != 0);
+ QVERIFY(container->qlistInterfaces()->count() == 2);
+ for(int ii = 0; ii < 2; ++ii)
+ QVERIFY(container->qlistInterfaces()->at(ii)->id == 913);
+}
+
+void tst_qmlparser::cannotAssignBindingToSignal()
+{
+ QTest::ignoreMessage(QtWarningMsg, "Cannot assign binding to signal property @<unspecified file>:1");
+ QmlComponent component(&engine, "<MyQmlObject onBasicSignal=\"{print(1921)}\" />");
+ MyContainer *container= qobject_cast<MyContainer*>(component.create());
+ QVERIFY(container == 0);
+}
+
+void tst_qmlparser::assignObjectToSignal()
+{
+ QmlComponent component(&engine, "<MyQmlObject><onBasicSignal><MyQmlObject /></onBasicSignal></MyQmlObject>");
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+ QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
+ emit object->basicSignal();
+}
+
+QTEST_MAIN(tst_qmlparser)
+
+#include "tst_qmlparser.moc"
diff --git a/tests/auto/declarative/repeater/data/repeater.xml b/tests/auto/declarative/repeater/data/repeater.xml
new file mode 100644
index 0000000..f863716
--- /dev/null
+++ b/tests/auto/declarative/repeater/data/repeater.xml
@@ -0,0 +1,7 @@
+<Rect id="container" width="240" height="320" color="white">
+ <Repeater id="repeater" width="240" height="320" dataSource="{testData}">
+ <Component>
+ <Text y="{index*20}" text="{modelData}"/>
+ </Component>
+ </Repeater>
+</Rect>
diff --git a/tests/auto/declarative/repeater/repeater.pro b/tests/auto/declarative/repeater/repeater.pro
new file mode 100644
index 0000000..0ecd7ee
--- /dev/null
+++ b/tests/auto/declarative/repeater/repeater.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_repeater.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/repeater/tst_repeater.cpp b/tests/auto/declarative/repeater/tst_repeater.cpp
new file mode 100644
index 0000000..cdf1716
--- /dev/null
+++ b/tests/auto/declarative/repeater/tst_repeater.cpp
@@ -0,0 +1,91 @@
+#include <QtTest/QtTest>
+#include <qlistmodelinterface.h>
+#include <qfxview.h>
+#include <qfxrepeater.h>
+#include <qfxtext.h>
+#include <qmlcontext.h>
+
+class tst_QFxRepeater : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QFxRepeater();
+
+private slots:
+ void stringList();
+
+private:
+ QFxView *createView(const QString &filename);
+ template<typename T>
+ T *findItem(QFxItem *parent, const QString &id);
+};
+
+tst_QFxRepeater::tst_QFxRepeater()
+{
+}
+
+void tst_QFxRepeater::stringList()
+{
+ QFxView *canvas = createView(SRCDIR "/data/repeater.xml");
+
+ QStringList data;
+ data << "One";
+ data << "Two";
+ data << "Three";
+ data << "Four";
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->setProperty("testData", data);
+
+ canvas->execute();
+ qApp->processEvents();
+
+ QFxRepeater *repeater = findItem<QFxRepeater>(canvas->root(), "repeater");
+ QVERIFY(repeater != 0);
+
+ QFxItem *container = findItem<QFxItem>(canvas->root(), "container");
+ QVERIFY(container != 0);
+
+ QCOMPARE(container->children()->count(), data.count() + 1);
+
+ for (int i = 1; i < container->children()->count(); ++i) {
+ QFxText *name = qobject_cast<QFxText*>(container->children()->at(i));
+ QVERIFY(name != 0);
+ QCOMPARE(name->text(), data.at(i-1));
+ }
+
+ delete canvas;
+}
+
+
+QFxView *tst_QFxRepeater::createView(const QString &filename)
+{
+ QFxView *canvas = new QFxView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setXml(xml, filename);
+
+ return canvas;
+}
+
+template<typename T>
+T *tst_QFxRepeater::findItem(QFxItem *parent, const QString &id)
+{
+ const QMetaObject &mo = T::staticMetaObject;
+ if (mo.cast(parent) && (id.isEmpty() || parent->id() == id))
+ return static_cast<T*>(parent);
+ for (int i = 0; i < parent->children()->count(); ++i) {
+ QFxItem *item = findItem<T>(parent->children()->at(i), id);
+ if (item)
+ return static_cast<T*>(item);
+ }
+
+ return 0;
+}
+
+QTEST_MAIN(tst_QFxRepeater)
+
+#include "tst_repeater.moc"
diff --git a/tests/auto/declarative/simplecanvasitem/data/test.xml b/tests/auto/declarative/simplecanvasitem/data/test.xml
new file mode 100644
index 0000000..9b8f10a
--- /dev/null
+++ b/tests/auto/declarative/simplecanvasitem/data/test.xml
@@ -0,0 +1,12 @@
+<Item width="320" height="480">
+ <Rect color="blue" x="20" y="20" width="20" height="20">
+ <Rect color="black" x="20" y="20" width="10" height="10"/>
+ </Rect>
+ <Rect color="red" x="40" y="20" width="20" height="20"/>
+ <Rect color="green" x="60" y="20" width="20" height="20"/>
+ <Rect color="yellow" x="20" y="40" width="20" height="20"/>
+ <Rect color="purple" x="20" y="60" width="20" height="20"/>
+ <Rect color="white" x="40" y="40" width="20" height="20"/>
+ <Rect anchors.fill="{parent}" color="gray" z="-1"/>
+</Item>
+
diff --git a/tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro b/tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro
new file mode 100644
index 0000000..114be8e
--- /dev/null
+++ b/tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_simplecanvasitem.cpp
+
+# Define SRCDIR equal to test's source directory
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/simplecanvasitem/tst_simplecanvasitem.cpp b/tests/auto/declarative/simplecanvasitem/tst_simplecanvasitem.cpp
new file mode 100644
index 0000000..47608a0
--- /dev/null
+++ b/tests/auto/declarative/simplecanvasitem/tst_simplecanvasitem.cpp
@@ -0,0 +1,79 @@
+#include <QtTest/QtTest>
+#include <qfxview.h>
+#include <qfxitem.h>
+#include <qsimplecanvasitem.h>
+
+/*
+ Note: this autotest is specifically to test SimpleCanvasItem as a component of
+ Qt Declarative, and therefore will have all items created in XML.
+*/
+class tst_SimpleCanvasItem : public QObject
+{
+ Q_OBJECT
+public:
+ tst_SimpleCanvasItem();
+
+private slots:
+ void test_pos();
+ void test_scenePos();
+private:
+ QFxView *createView(const QString &filename);
+};
+
+tst_SimpleCanvasItem::tst_SimpleCanvasItem()
+{
+}
+
+void tst_SimpleCanvasItem::test_pos()
+{
+ QFxView *canvas = createView(SRCDIR "/data/test.xml");
+ canvas->execute();
+ qApp->processEvents();
+ QSimpleCanvasItem* root = qobject_cast<QSimpleCanvasItem*>(canvas->root());
+ QVERIFY(root);
+
+ QCOMPARE(root->pos(), QPointF(0,0));
+ QCOMPARE(root->children().at(0)->pos(), QPointF(20,20));
+ QCOMPARE(root->children().at(0)->children().at(0)->pos(), QPointF(20,20));
+ QCOMPARE(root->children().at(2)->pos(), QPointF(60,20));
+ QCOMPARE(root->children().at(3)->pos(), QPointF(20,40));
+ QCOMPARE(root->children().at(5)->pos(), QPointF(40,40));
+}
+
+void tst_SimpleCanvasItem::test_scenePos()
+{
+ QFxView *canvas = createView(SRCDIR "/data/test.xml");
+ canvas->execute();
+ qApp->processEvents();
+ QSimpleCanvasItem* root = qobject_cast<QSimpleCanvasItem*>(canvas->root());
+ QVERIFY(root);
+
+#ifdef CANVAS_GL
+ QCOMPARE(root->transform(), QMatrix4x4());
+#else
+ QCOMPARE(root->transform(), QTransform());
+#endif
+ QCOMPARE(root->scenePos(), QPointF(0,0));
+ QCOMPARE(root->children().at(0)->scenePos(), QPointF(20,20));
+ QCOMPARE(root->children().at(0)->children().at(0)->scenePos(), QPointF(40,40));
+ QCOMPARE(root->children().at(2)->scenePos(), QPointF(60,20));
+ QCOMPARE(root->children().at(3)->scenePos(), QPointF(20,40));
+ QCOMPARE(root->children().at(5)->scenePos(), QPointF(40,40));
+}
+
+QFxView *tst_SimpleCanvasItem::createView(const QString &filename)
+{
+ QFxView *canvas = new QFxView(0);
+ canvas->setFixedSize(240,320);
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setXml(xml, filename);
+
+ return canvas;
+}
+
+QTEST_MAIN(tst_SimpleCanvasItem)
+
+#include "tst_simplecanvasitem.moc"
diff --git a/tests/auto/declarative/visual/ListView/basic1/basic1.xml b/tests/auto/declarative/visual/ListView/basic1/basic1.xml
new file mode 100644
index 0000000..5038c0a
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic1/basic1.xml
@@ -0,0 +1,19 @@
+<Rect color="blue" width="800" height="600" id="Page">
+ <ListView anchors.fill="{parent}">
+ <delegate>
+ <Rect color="red" width="100" height="100">
+ <Text text="{name}" />
+ </Rect>
+ </delegate>
+ <model>
+ <ListModel>
+ <Month>
+ <name>January</name>
+ </Month>
+ <Month>
+ <name>February</name>
+ </Month>
+ </ListModel>
+ </model>
+ </ListView>
+</Rect>
diff --git a/tests/auto/declarative/visual/ListView/basic1/data/opengl/image0.png b/tests/auto/declarative/visual/ListView/basic1/data/opengl/image0.png
new file mode 100644
index 0000000..403b407
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic1/data/opengl/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/basic1/data/opengl/manifest.xml b/tests/auto/declarative/visual/ListView/basic1/data/opengl/manifest.xml
new file mode 100644
index 0000000..b784f42
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic1/data/opengl/manifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/ListView/basic1/test b/tests/auto/declarative/visual/ListView/basic1/test
new file mode 100644
index 0000000..62f0665
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic1/test
@@ -0,0 +1 @@
+basic1.xml
diff --git a/tests/auto/declarative/visual/ListView/basic2/basic2.xml b/tests/auto/declarative/visual/ListView/basic2/basic2.xml
new file mode 100644
index 0000000..5e139fe
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic2/basic2.xml
@@ -0,0 +1,20 @@
+<Rect color="blue" width="800" height="600" id="Page">
+ <Component id="Delegate">
+ <Rect color="red" width="100" height="100">
+ <Text text="{name}" />
+ </Rect>
+ </Component>
+
+ <ListView anchors.fill="{parent}" delegate="{Delegate}">
+ <model>
+ <ListModel>
+ <Month>
+ <name>January</name>
+ </Month>
+ <Month>
+ <name>February</name>
+ </Month>
+ </ListModel>
+ </model>
+ </ListView>
+</Rect>
diff --git a/tests/auto/declarative/visual/ListView/basic2/data/opengl/image0.png b/tests/auto/declarative/visual/ListView/basic2/data/opengl/image0.png
new file mode 100644
index 0000000..403b407
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic2/data/opengl/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/basic2/data/opengl/manifest.xml b/tests/auto/declarative/visual/ListView/basic2/data/opengl/manifest.xml
new file mode 100644
index 0000000..f3fa6c9
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic2/data/opengl/manifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="31" frameId="0"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/ListView/basic2/test b/tests/auto/declarative/visual/ListView/basic2/test
new file mode 100644
index 0000000..ae974fe
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic2/test
@@ -0,0 +1 @@
+basic2.xml
diff --git a/tests/auto/declarative/visual/ListView/basic3/basic3.xml b/tests/auto/declarative/visual/ListView/basic3/basic3.xml
new file mode 100644
index 0000000..a587b82
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic3/basic3.xml
@@ -0,0 +1,18 @@
+<Rect color="blue" width="800" height="600" id="Page">
+ <ListModel id="Model">
+ <Month>
+ <name>January</name>
+ </Month>
+ <Month>
+ <name>February</name>
+ </Month>
+ </ListModel>
+
+ <ListView anchors.fill="{parent}" model="{Model}">
+ <delegate>
+ <Rect color="red" width="100" height="100">
+ <Text text="{name}" />
+ </Rect>
+ </delegate>
+ </ListView>
+</Rect>
diff --git a/tests/auto/declarative/visual/ListView/basic3/data/opengl/image0.png b/tests/auto/declarative/visual/ListView/basic3/data/opengl/image0.png
new file mode 100644
index 0000000..403b407
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic3/data/opengl/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/basic3/data/opengl/manifest.xml b/tests/auto/declarative/visual/ListView/basic3/data/opengl/manifest.xml
new file mode 100644
index 0000000..b784f42
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic3/data/opengl/manifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/ListView/basic3/test b/tests/auto/declarative/visual/ListView/basic3/test
new file mode 100644
index 0000000..ea3154e
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic3/test
@@ -0,0 +1 @@
+basic3.xml
diff --git a/tests/auto/declarative/visual/ListView/basic4/basic4.xml b/tests/auto/declarative/visual/ListView/basic4/basic4.xml
new file mode 100644
index 0000000..4b9201c
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic4/basic4.xml
@@ -0,0 +1,19 @@
+<Rect color="blue" width="800" height="600" id="Page">
+ <ListModel id="Model">
+ <Month>
+ <name>January</name>
+ </Month>
+ <Month>
+ <name>February</name>
+ </Month>
+ </ListModel>
+
+ <Component id="Delegate">
+ <Rect color="red" width="100" height="100">
+ <Text text="{name}" />
+ </Rect>
+ </Component>
+
+ <ListView anchors.fill="{parent}" model="{Model}" delegate="{Delegate}">
+ </ListView>
+</Rect>
diff --git a/tests/auto/declarative/visual/ListView/basic4/data/opengl/image0.png b/tests/auto/declarative/visual/ListView/basic4/data/opengl/image0.png
new file mode 100644
index 0000000..403b407
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic4/data/opengl/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/ListView/basic4/data/opengl/manifest.xml b/tests/auto/declarative/visual/ListView/basic4/data/opengl/manifest.xml
new file mode 100644
index 0000000..b784f42
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic4/data/opengl/manifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/ListView/basic4/test b/tests/auto/declarative/visual/ListView/basic4/test
new file mode 100644
index 0000000..891e0be
--- /dev/null
+++ b/tests/auto/declarative/visual/ListView/basic4/test
@@ -0,0 +1 @@
+basic4.xml
diff --git a/tests/auto/declarative/visual/bindinganimation/bindinganimation.xml b/tests/auto/declarative/visual/bindinganimation/bindinganimation.xml
new file mode 100644
index 0000000..30b0b6a
--- /dev/null
+++ b/tests/auto/declarative/visual/bindinganimation/bindinganimation.xml
@@ -0,0 +1,19 @@
+<Rect color="blue" width="320" height="240" id="Page">
+ <Rect id="MyRect" width="100" height="100" color="red" x="{10}" />
+
+ <states>
+ <State name="hello">
+ <SetProperty target="{MyRect}" property="x" binding="100" />
+ <SetProperty target="{MyMouseRegion}" property="onClick" value="Page.currentState = ''" />
+ </State>
+ </states>
+
+ <transitions>
+ <Transition>
+ <NumericAnimation properties="x" />
+ </Transition>
+ </transitions>
+
+ <MouseRegion id="MyMouseRegion" anchors.fill="{parent}" onClick="Page.currentState= 'hello'" />
+
+</Rect>
diff --git a/tests/auto/declarative/visual/bindinganimation/data/opengl/image0.png b/tests/auto/declarative/visual/bindinganimation/data/opengl/image0.png
new file mode 100644
index 0000000..2cda3fa
--- /dev/null
+++ b/tests/auto/declarative/visual/bindinganimation/data/opengl/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/bindinganimation/data/opengl/manifest-play.xml b/tests/auto/declarative/visual/bindinganimation/data/opengl/manifest-play.xml
new file mode 100644
index 0000000..6c5856f
--- /dev/null
+++ b/tests/auto/declarative/visual/bindinganimation/data/opengl/manifest-play.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="1770" type="2" button="1" buttons="1" globalPos="614,528" pos="175,131"/>
+ <TestMouse time="1860" type="3" button="1" buttons="0" globalPos="614,528" pos="175,131"/>
+ <TestFrame time="1860" hash="7CB5FC371040E587DE9F06CE14A4B29A"/>
+ <TestFrame time="1920" hash="8F88EE8780C32F038C9ACDC7172DE04E"/>
+ <TestFrame time="1950" hash="BE859D598C5DB953A8FC506DED4940EB"/>
+ <TestFrame time="1980" hash="16FE17B15900FF0464AB20EA921E5B1F"/>
+ <TestFrame time="2010" hash="FCB17070EF24575C61046928A8BBE440"/>
+ <TestFrame time="2040" hash="4F58226BDBDA7339D972ECA065F75766"/>
+ <TestFrame time="2070" hash="D9AF30557F99B086BB1A185A946B580D"/>
+ <TestFrame time="2100" hash="082E0E7650D187A54EF0948CCCA98E5A"/>
+ <TestFrame time="2130" hash="4F41101378A104E72228EEB4BA395CA8"/>
+ <TestFrame time="2160" hash="3223ED179C828FADB3ECA9C6373176C1"/>
+ <TestFrame time="2190" hash="DAFCCE427161A70C3513841AC22AEA00"/>
+ <TestFrame time="2220" hash="7F465A99FCA50503736E470A0B4E1C7A"/>
+ <TestFrame time="2250" hash="97542160B249135B1F3957DBBB329C2E"/>
+ <TestFrame time="2280" hash="F9F74A2E38B52C9266F33E428B6ACD9D"/>
+ <TestFrame time="2310" hash="65AD7E0189C096792331BD1BB0DAF0DB"/>
+ <TestFrame time="2340" hash="BA403842BA3128B1CDF6A9CB28C90751"/>
+ <TestFrame time="2370" hash="1BCDCD0E8166D69F4349E05D5E92FD9D"/>
+ <TestFrame time="2400" hash="383BA6B9EFCC58FCA512982A207631F6"/>
+ <TestMouse time="2820" type="2" button="1" buttons="1" globalPos="614,528" pos="175,131"/>
+ <TestMouse time="2910" type="3" button="1" buttons="0" globalPos="614,528" pos="175,131"/>
+ <TestFrame time="2910" hash="383BA6B9EFCC58FCA512982A207631F6"/>
+ <TestFrame time="2970" hash="ADC501A3A2B8AAF72F58BA985B57424E"/>
+ <TestFrame time="3000" hash="BFA51B7C19753EF7B16D78AFFFC7B9DD"/>
+ <TestFrame time="3030" hash="A93F930EC8528F954CD4A770C9A8171B"/>
+ <TestFrame time="3060" hash="0B0C6419E1E5B016D9C22BD98FD452B1"/>
+ <TestFrame time="3090" hash="1D5CD86AB732DA3705A7BB1DEAB77923"/>
+ <TestFrame time="3120" hash="69058485CED6BC992A1A7C5EE34ADD4C"/>
+ <TestFrame time="3150" hash="72731478D80F024076EA639B55152360"/>
+ <TestFrame time="3180" hash="37739777A5979F3EBF85E47E63341660"/>
+ <TestFrame time="3210" hash="FCAE0317F81A3DDD713F4DB1349A9DA0"/>
+ <TestFrame time="3240" hash="82363265ED2B611A54F8D48B2AF22F11"/>
+ <TestFrame time="3270" hash="5FAE0BDC65C609CB766CE585B8C649DB"/>
+ <TestFrame time="3300" hash="2D21B4AF3780EF2BBCCFCEC957CE49C8"/>
+ <TestFrame time="3330" hash="4AB21E266919FB8D340F87091D8E1F62"/>
+ <TestFrame time="3360" hash="5F5DA43901938FA244F536336FFD2DFC"/>
+ <TestFrame time="3390" hash="9B7685F5933C5E06883EE4D1BB2BD2C6"/>
+ <TestFrame time="3420" hash="96C077E3A572EDFF04FA9B2F7020FFD0"/>
+ <TestFrame time="3450" hash="7CB5FC371040E587DE9F06CE14A4B29A"/>
+ <TestMouse time="3840" type="2" button="1" buttons="1" globalPos="614,528" pos="175,131"/>
+ <TestMouse time="3930" type="3" button="1" buttons="0" globalPos="614,528" pos="175,131"/>
+ <TestFrame time="3930" hash="7CB5FC371040E587DE9F06CE14A4B29A"/>
+ <TestFrame time="3990" hash="8F88EE8780C32F038C9ACDC7172DE04E"/>
+ <TestFrame time="4020" hash="BE859D598C5DB953A8FC506DED4940EB"/>
+ <TestFrame time="4050" hash="16FE17B15900FF0464AB20EA921E5B1F"/>
+ <TestFrame time="4080" hash="FCB17070EF24575C61046928A8BBE440"/>
+ <TestFrame time="4110" hash="4F58226BDBDA7339D972ECA065F75766"/>
+ <TestFrame time="4140" hash="D9AF30557F99B086BB1A185A946B580D"/>
+ <TestFrame time="4170" hash="082E0E7650D187A54EF0948CCCA98E5A"/>
+ <TestFrame time="4200" hash="4F41101378A104E72228EEB4BA395CA8"/>
+ <TestFrame time="4230" hash="3223ED179C828FADB3ECA9C6373176C1"/>
+ <TestFrame time="4260" hash="DAFCCE427161A70C3513841AC22AEA00"/>
+ <TestFrame time="4290" hash="7F465A99FCA50503736E470A0B4E1C7A"/>
+ <TestFrame time="4320" hash="97542160B249135B1F3957DBBB329C2E"/>
+ <TestFrame time="4350" hash="F9F74A2E38B52C9266F33E428B6ACD9D"/>
+ <TestFrame time="4380" hash="65AD7E0189C096792331BD1BB0DAF0DB"/>
+ <TestFrame time="4410" hash="BA403842BA3128B1CDF6A9CB28C90751"/>
+ <TestFrame time="4440" hash="1BCDCD0E8166D69F4349E05D5E92FD9D"/>
+ <TestFrame time="4470" hash="383BA6B9EFCC58FCA512982A207631F6"/>
+ <TestMouse time="4920" type="2" button="1" buttons="1" globalPos="614,528" pos="175,131"/>
+ <TestMouse time="5010" type="3" button="1" buttons="0" globalPos="614,528" pos="175,131"/>
+ <TestFrame time="5010" hash="383BA6B9EFCC58FCA512982A207631F6"/>
+ <TestFrame time="5070" hash="ADC501A3A2B8AAF72F58BA985B57424E"/>
+ <TestFrame time="5100" hash="BFA51B7C19753EF7B16D78AFFFC7B9DD"/>
+ <TestFrame time="5130" hash="A93F930EC8528F954CD4A770C9A8171B"/>
+ <TestFrame time="5160" hash="0B0C6419E1E5B016D9C22BD98FD452B1"/>
+ <TestFrame time="5190" hash="1D5CD86AB732DA3705A7BB1DEAB77923"/>
+ <TestFrame time="5220" hash="69058485CED6BC992A1A7C5EE34ADD4C"/>
+ <TestFrame time="5250" hash="72731478D80F024076EA639B55152360"/>
+ <TestFrame time="5280" hash="37739777A5979F3EBF85E47E63341660"/>
+ <TestFrame time="5310" hash="FCAE0317F81A3DDD713F4DB1349A9DA0"/>
+ <TestFrame time="5340" hash="82363265ED2B611A54F8D48B2AF22F11"/>
+ <TestFrame time="5370" hash="5FAE0BDC65C609CB766CE585B8C649DB"/>
+ <TestFrame time="5400" hash="2D21B4AF3780EF2BBCCFCEC957CE49C8"/>
+ <TestFrame time="5430" hash="4AB21E266919FB8D340F87091D8E1F62"/>
+ <TestFrame time="5460" hash="5F5DA43901938FA244F536336FFD2DFC"/>
+ <TestFrame time="5490" hash="9B7685F5933C5E06883EE4D1BB2BD2C6"/>
+ <TestFrame time="5520" hash="96C077E3A572EDFF04FA9B2F7020FFD0"/>
+ <TestFrame time="5550" hash="7CB5FC371040E587DE9F06CE14A4B29A"/>
+ <TestMouse time="5910" type="2" button="1" buttons="1" globalPos="614,528" pos="175,131"/>
+ <TestMouse time="6030" type="3" button="1" buttons="0" globalPos="614,528" pos="175,131"/>
+ <TestFrame time="6030" hash="7CB5FC371040E587DE9F06CE14A4B29A"/>
+ <TestFrame time="6090" hash="8F88EE8780C32F038C9ACDC7172DE04E"/>
+ <TestFrame time="6120" hash="BE859D598C5DB953A8FC506DED4940EB"/>
+ <TestFrame time="6150" hash="16FE17B15900FF0464AB20EA921E5B1F"/>
+ <TestFrame time="6180" hash="FCB17070EF24575C61046928A8BBE440"/>
+ <TestFrame time="6210" hash="4F58226BDBDA7339D972ECA065F75766"/>
+ <TestFrame time="6240" hash="D9AF30557F99B086BB1A185A946B580D"/>
+ <TestFrame time="6270" hash="082E0E7650D187A54EF0948CCCA98E5A"/>
+ <TestFrame time="6300" hash="4F41101378A104E72228EEB4BA395CA8"/>
+ <TestFrame time="6330" hash="3223ED179C828FADB3ECA9C6373176C1"/>
+ <TestFrame time="6360" hash="DAFCCE427161A70C3513841AC22AEA00"/>
+ <TestFrame time="6390" hash="7F465A99FCA50503736E470A0B4E1C7A"/>
+ <TestFrame time="6420" hash="97542160B249135B1F3957DBBB329C2E"/>
+ <TestFrame time="6450" hash="F9F74A2E38B52C9266F33E428B6ACD9D"/>
+ <TestFrame time="6480" hash="65AD7E0189C096792331BD1BB0DAF0DB"/>
+ <TestFrame time="6510" hash="BA403842BA3128B1CDF6A9CB28C90751"/>
+ <TestFrame time="6540" hash="1BCDCD0E8166D69F4349E05D5E92FD9D"/>
+ <TestFrame time="6570" hash="383BA6B9EFCC58FCA512982A207631F6"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/bindinganimation/data/opengl/manifest.xml b/tests/auto/declarative/visual/bindinganimation/data/opengl/manifest.xml
new file mode 100644
index 0000000..6c5856f
--- /dev/null
+++ b/tests/auto/declarative/visual/bindinganimation/data/opengl/manifest.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="1770" type="2" button="1" buttons="1" globalPos="614,528" pos="175,131"/>
+ <TestMouse time="1860" type="3" button="1" buttons="0" globalPos="614,528" pos="175,131"/>
+ <TestFrame time="1860" hash="7CB5FC371040E587DE9F06CE14A4B29A"/>
+ <TestFrame time="1920" hash="8F88EE8780C32F038C9ACDC7172DE04E"/>
+ <TestFrame time="1950" hash="BE859D598C5DB953A8FC506DED4940EB"/>
+ <TestFrame time="1980" hash="16FE17B15900FF0464AB20EA921E5B1F"/>
+ <TestFrame time="2010" hash="FCB17070EF24575C61046928A8BBE440"/>
+ <TestFrame time="2040" hash="4F58226BDBDA7339D972ECA065F75766"/>
+ <TestFrame time="2070" hash="D9AF30557F99B086BB1A185A946B580D"/>
+ <TestFrame time="2100" hash="082E0E7650D187A54EF0948CCCA98E5A"/>
+ <TestFrame time="2130" hash="4F41101378A104E72228EEB4BA395CA8"/>
+ <TestFrame time="2160" hash="3223ED179C828FADB3ECA9C6373176C1"/>
+ <TestFrame time="2190" hash="DAFCCE427161A70C3513841AC22AEA00"/>
+ <TestFrame time="2220" hash="7F465A99FCA50503736E470A0B4E1C7A"/>
+ <TestFrame time="2250" hash="97542160B249135B1F3957DBBB329C2E"/>
+ <TestFrame time="2280" hash="F9F74A2E38B52C9266F33E428B6ACD9D"/>
+ <TestFrame time="2310" hash="65AD7E0189C096792331BD1BB0DAF0DB"/>
+ <TestFrame time="2340" hash="BA403842BA3128B1CDF6A9CB28C90751"/>
+ <TestFrame time="2370" hash="1BCDCD0E8166D69F4349E05D5E92FD9D"/>
+ <TestFrame time="2400" hash="383BA6B9EFCC58FCA512982A207631F6"/>
+ <TestMouse time="2820" type="2" button="1" buttons="1" globalPos="614,528" pos="175,131"/>
+ <TestMouse time="2910" type="3" button="1" buttons="0" globalPos="614,528" pos="175,131"/>
+ <TestFrame time="2910" hash="383BA6B9EFCC58FCA512982A207631F6"/>
+ <TestFrame time="2970" hash="ADC501A3A2B8AAF72F58BA985B57424E"/>
+ <TestFrame time="3000" hash="BFA51B7C19753EF7B16D78AFFFC7B9DD"/>
+ <TestFrame time="3030" hash="A93F930EC8528F954CD4A770C9A8171B"/>
+ <TestFrame time="3060" hash="0B0C6419E1E5B016D9C22BD98FD452B1"/>
+ <TestFrame time="3090" hash="1D5CD86AB732DA3705A7BB1DEAB77923"/>
+ <TestFrame time="3120" hash="69058485CED6BC992A1A7C5EE34ADD4C"/>
+ <TestFrame time="3150" hash="72731478D80F024076EA639B55152360"/>
+ <TestFrame time="3180" hash="37739777A5979F3EBF85E47E63341660"/>
+ <TestFrame time="3210" hash="FCAE0317F81A3DDD713F4DB1349A9DA0"/>
+ <TestFrame time="3240" hash="82363265ED2B611A54F8D48B2AF22F11"/>
+ <TestFrame time="3270" hash="5FAE0BDC65C609CB766CE585B8C649DB"/>
+ <TestFrame time="3300" hash="2D21B4AF3780EF2BBCCFCEC957CE49C8"/>
+ <TestFrame time="3330" hash="4AB21E266919FB8D340F87091D8E1F62"/>
+ <TestFrame time="3360" hash="5F5DA43901938FA244F536336FFD2DFC"/>
+ <TestFrame time="3390" hash="9B7685F5933C5E06883EE4D1BB2BD2C6"/>
+ <TestFrame time="3420" hash="96C077E3A572EDFF04FA9B2F7020FFD0"/>
+ <TestFrame time="3450" hash="7CB5FC371040E587DE9F06CE14A4B29A"/>
+ <TestMouse time="3840" type="2" button="1" buttons="1" globalPos="614,528" pos="175,131"/>
+ <TestMouse time="3930" type="3" button="1" buttons="0" globalPos="614,528" pos="175,131"/>
+ <TestFrame time="3930" hash="7CB5FC371040E587DE9F06CE14A4B29A"/>
+ <TestFrame time="3990" hash="8F88EE8780C32F038C9ACDC7172DE04E"/>
+ <TestFrame time="4020" hash="BE859D598C5DB953A8FC506DED4940EB"/>
+ <TestFrame time="4050" hash="16FE17B15900FF0464AB20EA921E5B1F"/>
+ <TestFrame time="4080" hash="FCB17070EF24575C61046928A8BBE440"/>
+ <TestFrame time="4110" hash="4F58226BDBDA7339D972ECA065F75766"/>
+ <TestFrame time="4140" hash="D9AF30557F99B086BB1A185A946B580D"/>
+ <TestFrame time="4170" hash="082E0E7650D187A54EF0948CCCA98E5A"/>
+ <TestFrame time="4200" hash="4F41101378A104E72228EEB4BA395CA8"/>
+ <TestFrame time="4230" hash="3223ED179C828FADB3ECA9C6373176C1"/>
+ <TestFrame time="4260" hash="DAFCCE427161A70C3513841AC22AEA00"/>
+ <TestFrame time="4290" hash="7F465A99FCA50503736E470A0B4E1C7A"/>
+ <TestFrame time="4320" hash="97542160B249135B1F3957DBBB329C2E"/>
+ <TestFrame time="4350" hash="F9F74A2E38B52C9266F33E428B6ACD9D"/>
+ <TestFrame time="4380" hash="65AD7E0189C096792331BD1BB0DAF0DB"/>
+ <TestFrame time="4410" hash="BA403842BA3128B1CDF6A9CB28C90751"/>
+ <TestFrame time="4440" hash="1BCDCD0E8166D69F4349E05D5E92FD9D"/>
+ <TestFrame time="4470" hash="383BA6B9EFCC58FCA512982A207631F6"/>
+ <TestMouse time="4920" type="2" button="1" buttons="1" globalPos="614,528" pos="175,131"/>
+ <TestMouse time="5010" type="3" button="1" buttons="0" globalPos="614,528" pos="175,131"/>
+ <TestFrame time="5010" hash="383BA6B9EFCC58FCA512982A207631F6"/>
+ <TestFrame time="5070" hash="ADC501A3A2B8AAF72F58BA985B57424E"/>
+ <TestFrame time="5100" hash="BFA51B7C19753EF7B16D78AFFFC7B9DD"/>
+ <TestFrame time="5130" hash="A93F930EC8528F954CD4A770C9A8171B"/>
+ <TestFrame time="5160" hash="0B0C6419E1E5B016D9C22BD98FD452B1"/>
+ <TestFrame time="5190" hash="1D5CD86AB732DA3705A7BB1DEAB77923"/>
+ <TestFrame time="5220" hash="69058485CED6BC992A1A7C5EE34ADD4C"/>
+ <TestFrame time="5250" hash="72731478D80F024076EA639B55152360"/>
+ <TestFrame time="5280" hash="37739777A5979F3EBF85E47E63341660"/>
+ <TestFrame time="5310" hash="FCAE0317F81A3DDD713F4DB1349A9DA0"/>
+ <TestFrame time="5340" hash="82363265ED2B611A54F8D48B2AF22F11"/>
+ <TestFrame time="5370" hash="5FAE0BDC65C609CB766CE585B8C649DB"/>
+ <TestFrame time="5400" hash="2D21B4AF3780EF2BBCCFCEC957CE49C8"/>
+ <TestFrame time="5430" hash="4AB21E266919FB8D340F87091D8E1F62"/>
+ <TestFrame time="5460" hash="5F5DA43901938FA244F536336FFD2DFC"/>
+ <TestFrame time="5490" hash="9B7685F5933C5E06883EE4D1BB2BD2C6"/>
+ <TestFrame time="5520" hash="96C077E3A572EDFF04FA9B2F7020FFD0"/>
+ <TestFrame time="5550" hash="7CB5FC371040E587DE9F06CE14A4B29A"/>
+ <TestMouse time="5910" type="2" button="1" buttons="1" globalPos="614,528" pos="175,131"/>
+ <TestMouse time="6030" type="3" button="1" buttons="0" globalPos="614,528" pos="175,131"/>
+ <TestFrame time="6030" hash="7CB5FC371040E587DE9F06CE14A4B29A"/>
+ <TestFrame time="6090" hash="8F88EE8780C32F038C9ACDC7172DE04E"/>
+ <TestFrame time="6120" hash="BE859D598C5DB953A8FC506DED4940EB"/>
+ <TestFrame time="6150" hash="16FE17B15900FF0464AB20EA921E5B1F"/>
+ <TestFrame time="6180" hash="FCB17070EF24575C61046928A8BBE440"/>
+ <TestFrame time="6210" hash="4F58226BDBDA7339D972ECA065F75766"/>
+ <TestFrame time="6240" hash="D9AF30557F99B086BB1A185A946B580D"/>
+ <TestFrame time="6270" hash="082E0E7650D187A54EF0948CCCA98E5A"/>
+ <TestFrame time="6300" hash="4F41101378A104E72228EEB4BA395CA8"/>
+ <TestFrame time="6330" hash="3223ED179C828FADB3ECA9C6373176C1"/>
+ <TestFrame time="6360" hash="DAFCCE427161A70C3513841AC22AEA00"/>
+ <TestFrame time="6390" hash="7F465A99FCA50503736E470A0B4E1C7A"/>
+ <TestFrame time="6420" hash="97542160B249135B1F3957DBBB329C2E"/>
+ <TestFrame time="6450" hash="F9F74A2E38B52C9266F33E428B6ACD9D"/>
+ <TestFrame time="6480" hash="65AD7E0189C096792331BD1BB0DAF0DB"/>
+ <TestFrame time="6510" hash="BA403842BA3128B1CDF6A9CB28C90751"/>
+ <TestFrame time="6540" hash="1BCDCD0E8166D69F4349E05D5E92FD9D"/>
+ <TestFrame time="6570" hash="383BA6B9EFCC58FCA512982A207631F6"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/bindinganimation/test b/tests/auto/declarative/visual/bindinganimation/test
new file mode 100644
index 0000000..964c489
--- /dev/null
+++ b/tests/auto/declarative/visual/bindinganimation/test
@@ -0,0 +1 @@
+bindinganimation.xml
diff --git a/tests/auto/declarative/visual/colorAnimation/colorAnimation.xml b/tests/auto/declarative/visual/colorAnimation/colorAnimation.xml
new file mode 100644
index 0000000..39d08be
--- /dev/null
+++ b/tests/auto/declarative/visual/colorAnimation/colorAnimation.xml
@@ -0,0 +1,18 @@
+<Rect id="mainrect" currentState="first">
+<states>
+ <State name="first">
+ <SetProperty target="{mainrect}" property="color" value="red"/>
+ </State>
+ <State name="second" >
+ <SetProperty target="{mainrect}" property="color" value="blue"/>
+ </State>
+</states>
+<transitions>
+ <Transition fromState="first" toState="second" reversible="true" >
+ <SerialAnimation>
+ <ColorAnimation duration="2000" target="{mainrect}" property="color" />
+ </SerialAnimation>
+ </Transition>
+</transitions>
+<MouseRegion anchors.fill="{parent}" onClick="mainrect.currentState = 'second'" />
+</Rect>
diff --git a/tests/auto/declarative/visual/colorAnimation/image0.png b/tests/auto/declarative/visual/colorAnimation/image0.png
new file mode 100644
index 0000000..9e1caf7
--- /dev/null
+++ b/tests/auto/declarative/visual/colorAnimation/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/colorAnimation/manifest-play.xml b/tests/auto/declarative/visual/colorAnimation/manifest-play.xml
new file mode 100644
index 0000000..8e3de2e
--- /dev/null
+++ b/tests/auto/declarative/visual/colorAnimation/manifest-play.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="480" type="2" button="1" buttons="1" globalPos="93,129" pos="89,102"/>
+ <TestMouse time="570" type="3" button="1" buttons="0" globalPos="93,129" pos="89,102"/>
+ <TestFrame time="630" hash="D42762ECD293C6922C5F9593126DE636"/>
+ <TestFrame time="660" hash="8962505FCCB2E7559A99A8EDD325A82B"/>
+ <TestFrame time="690" hash="6812EFDA80607D4FA05CD3A5077F8EF7"/>
+ <TestFrame time="720" hash="A116DF73809679C1C5F9261F49B989F0"/>
+ <TestFrame time="750" hash="DC1B9D40AEE306171AD6625DDCA4EB45"/>
+ <TestFrame time="780" hash="B2DAF0E4C32080229664A8B0A155DE3B"/>
+ <TestFrame time="810" hash="496677B0D8707B91566D1244C46D50DB"/>
+ <TestFrame time="840" hash="A6558D8B0D1FB1D11BEBE36C078386CE"/>
+ <TestFrame time="870" hash="601436BB436D391B0BD5FCC289666208"/>
+ <TestFrame time="900" hash="8CF3CF9EAD875497870CC7C1035802DC"/>
+ <TestFrame time="930" hash="FF6BA6BAC30DADD3DBBFD96F127EB1FE"/>
+ <TestFrame time="960" hash="1D97A2A6890078DCF4CE9E508E5F9F08"/>
+ <TestFrame time="990" hash="58C9116FDDD03DD036820EFCD0DCD392"/>
+ <TestFrame time="1020" hash="E51287B911C140B41D350FCB2091AB80"/>
+ <TestFrame time="1050" hash="7B107411B436FABE469A069E6E5B0C3C"/>
+ <TestFrame time="1080" hash="9D1CB0E58F2BD00DDA0FB463F6BFF526"/>
+ <TestFrame time="1110" hash="35AB7788489B79E5A5C6F2BE11AFC9E1"/>
+ <TestFrame time="1140" hash="C82177AC4A7A497469292C5F0F8C4913"/>
+ <TestFrame time="1170" hash="18763D1B911FDC524DB9E7B2569FE984"/>
+ <TestFrame time="1200" hash="27F63572AAEF6D835272D5D65FCF608B"/>
+ <TestFrame time="1230" hash="585727CAEC1F83ADB9E422BAF058A622"/>
+ <TestFrame time="1260" hash="2C3BBFEFBE6E5FDA1905E9F50985E1B4"/>
+ <TestFrame time="1290" hash="81675C4ABB2696D960BC5F204F05F16B"/>
+ <TestFrame time="1320" hash="6D0F3CCC06EF1E3A895ECC9A8DE90039"/>
+ <TestFrame time="1350" hash="0BF36093CCAEA8BDAE96D4939A8DDE20"/>
+ <TestFrame time="1380" hash="5A1CBC68AB59977B65492B0F8A664418"/>
+ <TestFrame time="1410" hash="C35831A8C59D56193CED2C4AADB4DFCE"/>
+ <TestFrame time="1440" hash="ED15973425A8B8528896B344A61393AA"/>
+ <TestFrame time="1470" hash="EA8FC02A8606680C089F0C0CE454ABE3"/>
+ <TestFrame time="1500" hash="CFB5CFBA0A0BC62C0D03908FB9599A8E"/>
+ <TestFrame time="1530" hash="09FAA04AFB50B48BD6A83F9E25F9DDDB"/>
+ <TestFrame time="1560" hash="0FDD0B8CDCCEB78C7C67AB0F5EA74D6A"/>
+ <TestFrame time="1590" hash="058D26146879900B5E5CCE05AE38BA0E"/>
+ <TestFrame time="1620" hash="80F9074C50F967C99D4C3A3FF9EC3E71"/>
+ <TestFrame time="1650" hash="AD9BDCEEC1C058D6B658C5BA0D0BC1F0"/>
+ <TestFrame time="1680" hash="AC14DF5458F91001181154F8C68BCE2B"/>
+ <TestFrame time="1710" hash="AE9225263E4C8E75E4D0F1D7192B4260"/>
+ <TestFrame time="1740" hash="D3D50F1B7F476E79E5B99E0E6D4CF827"/>
+ <TestFrame time="1770" hash="A1367445C5232ACCBF4904A415416EA4"/>
+ <TestFrame time="1800" hash="A21C0F1DA9B64A5B000558BA1F2E495D"/>
+ <TestFrame time="1830" hash="61AF477B6FB22E38E698375EA5793D22"/>
+ <TestFrame time="1860" hash="B3AD3501D527939CEAA4F124AB10B2DF"/>
+ <TestFrame time="1890" hash="0C2BF65A43AE87AFB0068F9FA4A74707"/>
+ <TestFrame time="1920" hash="5B7F96C797BEE4FD1B04538DE5549C1B"/>
+ <TestFrame time="1950" hash="4C861E936A3F1AFE323395E30174F8CC"/>
+ <TestFrame time="1980" hash="87F1966E5B0E924EB7CEED5520D120BF"/>
+ <TestFrame time="2010" hash="1980755E0D80469D4DC0B9B0309F2DEB"/>
+ <TestFrame time="2040" hash="38A7ACC2E5607FC0965B7B376A0D3524"/>
+ <TestFrame time="2070" hash="4434746833EFF5A3A76491024763990A"/>
+ <TestFrame time="2100" hash="A8BAD928F92E851B45723068B7FEF739"/>
+ <TestFrame time="2130" hash="A96F5C522C0ECA5C78E982E4235218CB"/>
+ <TestFrame time="2160" hash="135F0EFEDE2832B76F49966EBD629879"/>
+ <TestFrame time="2190" hash="A51C6E443413F184CAAE8A7F98A369C8"/>
+ <TestFrame time="2220" hash="62A7521EE62E6A2543B3141C1EFCE72A"/>
+ <TestFrame time="2250" hash="D416A41125659167B3E6AD68F66F6E64"/>
+ <TestFrame time="2280" hash="0F653B5E965665A43F50437724DC704C"/>
+ <TestFrame time="2310" hash="13A6E2485179501FF3AA8BA91A5050B4"/>
+ <TestFrame time="2340" hash="9423475D3832FBABEC56B80FA9161020"/>
+ <TestFrame time="2370" hash="497B21108A6CB127DB066B32D06D992A"/>
+ <TestFrame time="2400" hash="22F01CB9B4F8FF01410566A61E281373"/>
+ <TestFrame time="2430" hash="A099640BC088E14E20585CB87FC5C6F1"/>
+ <TestFrame time="2460" hash="AC2954553C333EA1D524CE51CD35958A"/>
+ <TestFrame time="2490" hash="771E882CC788BECAA82E71E6FBAB150D"/>
+ <TestFrame time="2520" hash="42CEDA45D88A8D2B3DA5B749F4C3C1BF"/>
+ <TestFrame time="2550" hash="C6E1F91B917E47246E012D1B203E0DC2"/>
+ <TestFrame time="2580" hash="EFB3E57CF265B6E36AA4DF72771D119C"/>
+ <TestFrame time="2610" hash="657FC7FD496E5A2FC84F63930E0D1DE3"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/colorAnimation/manifest.xml b/tests/auto/declarative/visual/colorAnimation/manifest.xml
new file mode 100644
index 0000000..8e3de2e
--- /dev/null
+++ b/tests/auto/declarative/visual/colorAnimation/manifest.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="480" type="2" button="1" buttons="1" globalPos="93,129" pos="89,102"/>
+ <TestMouse time="570" type="3" button="1" buttons="0" globalPos="93,129" pos="89,102"/>
+ <TestFrame time="630" hash="D42762ECD293C6922C5F9593126DE636"/>
+ <TestFrame time="660" hash="8962505FCCB2E7559A99A8EDD325A82B"/>
+ <TestFrame time="690" hash="6812EFDA80607D4FA05CD3A5077F8EF7"/>
+ <TestFrame time="720" hash="A116DF73809679C1C5F9261F49B989F0"/>
+ <TestFrame time="750" hash="DC1B9D40AEE306171AD6625DDCA4EB45"/>
+ <TestFrame time="780" hash="B2DAF0E4C32080229664A8B0A155DE3B"/>
+ <TestFrame time="810" hash="496677B0D8707B91566D1244C46D50DB"/>
+ <TestFrame time="840" hash="A6558D8B0D1FB1D11BEBE36C078386CE"/>
+ <TestFrame time="870" hash="601436BB436D391B0BD5FCC289666208"/>
+ <TestFrame time="900" hash="8CF3CF9EAD875497870CC7C1035802DC"/>
+ <TestFrame time="930" hash="FF6BA6BAC30DADD3DBBFD96F127EB1FE"/>
+ <TestFrame time="960" hash="1D97A2A6890078DCF4CE9E508E5F9F08"/>
+ <TestFrame time="990" hash="58C9116FDDD03DD036820EFCD0DCD392"/>
+ <TestFrame time="1020" hash="E51287B911C140B41D350FCB2091AB80"/>
+ <TestFrame time="1050" hash="7B107411B436FABE469A069E6E5B0C3C"/>
+ <TestFrame time="1080" hash="9D1CB0E58F2BD00DDA0FB463F6BFF526"/>
+ <TestFrame time="1110" hash="35AB7788489B79E5A5C6F2BE11AFC9E1"/>
+ <TestFrame time="1140" hash="C82177AC4A7A497469292C5F0F8C4913"/>
+ <TestFrame time="1170" hash="18763D1B911FDC524DB9E7B2569FE984"/>
+ <TestFrame time="1200" hash="27F63572AAEF6D835272D5D65FCF608B"/>
+ <TestFrame time="1230" hash="585727CAEC1F83ADB9E422BAF058A622"/>
+ <TestFrame time="1260" hash="2C3BBFEFBE6E5FDA1905E9F50985E1B4"/>
+ <TestFrame time="1290" hash="81675C4ABB2696D960BC5F204F05F16B"/>
+ <TestFrame time="1320" hash="6D0F3CCC06EF1E3A895ECC9A8DE90039"/>
+ <TestFrame time="1350" hash="0BF36093CCAEA8BDAE96D4939A8DDE20"/>
+ <TestFrame time="1380" hash="5A1CBC68AB59977B65492B0F8A664418"/>
+ <TestFrame time="1410" hash="C35831A8C59D56193CED2C4AADB4DFCE"/>
+ <TestFrame time="1440" hash="ED15973425A8B8528896B344A61393AA"/>
+ <TestFrame time="1470" hash="EA8FC02A8606680C089F0C0CE454ABE3"/>
+ <TestFrame time="1500" hash="CFB5CFBA0A0BC62C0D03908FB9599A8E"/>
+ <TestFrame time="1530" hash="09FAA04AFB50B48BD6A83F9E25F9DDDB"/>
+ <TestFrame time="1560" hash="0FDD0B8CDCCEB78C7C67AB0F5EA74D6A"/>
+ <TestFrame time="1590" hash="058D26146879900B5E5CCE05AE38BA0E"/>
+ <TestFrame time="1620" hash="80F9074C50F967C99D4C3A3FF9EC3E71"/>
+ <TestFrame time="1650" hash="AD9BDCEEC1C058D6B658C5BA0D0BC1F0"/>
+ <TestFrame time="1680" hash="AC14DF5458F91001181154F8C68BCE2B"/>
+ <TestFrame time="1710" hash="AE9225263E4C8E75E4D0F1D7192B4260"/>
+ <TestFrame time="1740" hash="D3D50F1B7F476E79E5B99E0E6D4CF827"/>
+ <TestFrame time="1770" hash="A1367445C5232ACCBF4904A415416EA4"/>
+ <TestFrame time="1800" hash="A21C0F1DA9B64A5B000558BA1F2E495D"/>
+ <TestFrame time="1830" hash="61AF477B6FB22E38E698375EA5793D22"/>
+ <TestFrame time="1860" hash="B3AD3501D527939CEAA4F124AB10B2DF"/>
+ <TestFrame time="1890" hash="0C2BF65A43AE87AFB0068F9FA4A74707"/>
+ <TestFrame time="1920" hash="5B7F96C797BEE4FD1B04538DE5549C1B"/>
+ <TestFrame time="1950" hash="4C861E936A3F1AFE323395E30174F8CC"/>
+ <TestFrame time="1980" hash="87F1966E5B0E924EB7CEED5520D120BF"/>
+ <TestFrame time="2010" hash="1980755E0D80469D4DC0B9B0309F2DEB"/>
+ <TestFrame time="2040" hash="38A7ACC2E5607FC0965B7B376A0D3524"/>
+ <TestFrame time="2070" hash="4434746833EFF5A3A76491024763990A"/>
+ <TestFrame time="2100" hash="A8BAD928F92E851B45723068B7FEF739"/>
+ <TestFrame time="2130" hash="A96F5C522C0ECA5C78E982E4235218CB"/>
+ <TestFrame time="2160" hash="135F0EFEDE2832B76F49966EBD629879"/>
+ <TestFrame time="2190" hash="A51C6E443413F184CAAE8A7F98A369C8"/>
+ <TestFrame time="2220" hash="62A7521EE62E6A2543B3141C1EFCE72A"/>
+ <TestFrame time="2250" hash="D416A41125659167B3E6AD68F66F6E64"/>
+ <TestFrame time="2280" hash="0F653B5E965665A43F50437724DC704C"/>
+ <TestFrame time="2310" hash="13A6E2485179501FF3AA8BA91A5050B4"/>
+ <TestFrame time="2340" hash="9423475D3832FBABEC56B80FA9161020"/>
+ <TestFrame time="2370" hash="497B21108A6CB127DB066B32D06D992A"/>
+ <TestFrame time="2400" hash="22F01CB9B4F8FF01410566A61E281373"/>
+ <TestFrame time="2430" hash="A099640BC088E14E20585CB87FC5C6F1"/>
+ <TestFrame time="2460" hash="AC2954553C333EA1D524CE51CD35958A"/>
+ <TestFrame time="2490" hash="771E882CC788BECAA82E71E6FBAB150D"/>
+ <TestFrame time="2520" hash="42CEDA45D88A8D2B3DA5B749F4C3C1BF"/>
+ <TestFrame time="2550" hash="C6E1F91B917E47246E012D1B203E0DC2"/>
+ <TestFrame time="2580" hash="EFB3E57CF265B6E36AA4DF72771D119C"/>
+ <TestFrame time="2610" hash="657FC7FD496E5A2FC84F63930E0D1DE3"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/easing/easing.xml b/tests/auto/declarative/visual/easing/easing.xml
new file mode 100644
index 0000000..01a7d6c
--- /dev/null
+++ b/tests/auto/declarative/visual/easing/easing.xml
@@ -0,0 +1,70 @@
+<Rect id="item" width="600" height="{layout.height}" color="white">
+ <resources>
+ <ListModel id="easingtypes">
+ <ListItem><type>easeNone</type></ListItem>
+ <ListItem><type>easeInQuad</type></ListItem>
+ <ListItem><type>easeOutQuad</type></ListItem>
+ <ListItem><type>easeInOutQuad</type></ListItem>
+ <ListItem><type>easeOutInQuad</type></ListItem>
+ <ListItem><type>easeInCubic</type></ListItem>
+ <ListItem><type>easeOutCubic</type></ListItem>
+ <ListItem><type>easeInOutCubic</type></ListItem>
+ <ListItem><type>easeOutInCubic</type></ListItem>
+ <ListItem><type>easeInQuart</type></ListItem>
+ <ListItem><type>easeOutQuart</type></ListItem>
+ <ListItem><type>easeInOutQuart</type></ListItem>
+ <ListItem><type>easeOutInQuart</type></ListItem>
+ <ListItem><type>easeInQuint</type></ListItem>
+ <ListItem><type>easeOutQuint</type></ListItem>
+ <ListItem><type>easeInOutQuint</type></ListItem>
+ <ListItem><type>easeOutInQuint</type></ListItem>
+ <ListItem><type>easeInSine</type></ListItem>
+ <ListItem><type>easeOutSine</type></ListItem>
+ <ListItem><type>easeInOutSine</type></ListItem>
+ <ListItem><type>easeOutInSine</type></ListItem>
+ <ListItem><type>easeInExpo</type></ListItem>
+ <ListItem><type>easeOutExpo</type></ListItem>
+ <ListItem><type>easeInOutExpo</type></ListItem>
+ <ListItem><type>easeOutInExpo</type></ListItem>
+ <ListItem><type>easeInCirc</type></ListItem>
+ <ListItem><type>easeOutCirc</type></ListItem>
+ <ListItem><type>easeInOutCirc</type></ListItem>
+ <ListItem><type>easeOutInCirc</type></ListItem>
+ <ListItem><type>easeInElastic</type></ListItem>
+ <ListItem><type>easeOutElastic</type></ListItem>
+ <ListItem><type>easeInOutElastic</type></ListItem>
+ <ListItem><type>easeOutInElastic</type></ListItem>
+ <ListItem><type>easeInBack</type></ListItem>
+ <ListItem><type>easeOutBack</type></ListItem>
+ <ListItem><type>easeInOutBack</type></ListItem>
+ <ListItem><type>easeOutInBack</type></ListItem>
+ <ListItem><type>easeOutBounce</type></ListItem>
+ <ListItem><type>easeInBounce</type></ListItem>
+ <ListItem><type>easeInOutBounce</type></ListItem>
+ <ListItem><type>easeOutInBounce</type></ListItem>
+ </ListModel>
+ </resources>
+
+ <VerticalLayout id="layout" anchors.left="{item.left}" anchors.right="{item.right}">
+ <Repeater dataSource="{easingtypes}" >
+ <Component>
+ <Text id="text" text="{type}" height="18" font.italic="true" color="black">
+ <states>
+ <State name="from" when="{!mouse.pressed}">
+ <SetProperty target="{text}" property="x" value="0"/>
+ </State>
+ <State name="to" when="{mouse.pressed}">
+ <SetProperty target="{text}" property="x" value="{item.width-100}"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="to" reversible="true">
+ <NumericAnimation properties="x" easing="{type}" />
+ </Transition>
+ </transitions>
+ </Text>
+ </Component>
+ </Repeater>
+ </VerticalLayout>
+ <MouseRegion id="mouse" anchors.fill="{layout}"/>
+</Rect>
diff --git a/tests/auto/declarative/visual/easing/image0.png b/tests/auto/declarative/visual/easing/image0.png
new file mode 100644
index 0000000..dbe03aa
--- /dev/null
+++ b/tests/auto/declarative/visual/easing/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/easing/manifest-play.xml b/tests/auto/declarative/visual/easing/manifest-play.xml
new file mode 100644
index 0000000..3c84452
--- /dev/null
+++ b/tests/auto/declarative/visual/easing/manifest-play.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="480" type="2" button="1" buttons="1" globalPos="487,444" pos="483,417"/>
+ <TestFrame time="510" hash="83FB660D6CABAAFCB27C6EC001B14110"/>
+ <TestFrame time="540" hash="27FCD68F610024000CA6D3A8D9F0CF09"/>
+ <TestFrame time="570" hash="14728A6160AF51FCA8562D6A020BBA79"/>
+ <TestFrame time="600" hash="BDDB81682B30A6918927ACB59608D14E"/>
+ <TestFrame time="630" hash="03F16A41DCD31E41935E54763757C6D5"/>
+ <TestFrame time="660" hash="2D04EA1EBEDC77CF5D42A1B491A57EA6"/>
+ <TestFrame time="690" hash="762C36B33B75F24427CA45F4AD06B64E"/>
+ <TestFrame time="720" hash="AA02624CC889C95A99BBE58365F4FAAD"/>
+ <TestFrame time="750" hash="0529200188188708A18CE0F931780DBD"/>
+ <TestFrame time="780" hash="56036B63822AF34F26B149069CD189C6"/>
+ <TestFrame time="810" hash="CFFC6583E2BA1E47E1439BED6FE69665"/>
+ <TestFrame time="840" hash="25A1AFDC945D5264FF0337A421143A3C"/>
+ <TestFrame time="870" hash="601FA34B5E15E7B87E6490580C2E1858"/>
+ <TestFrame time="900" hash="1CA085F6CB8509957A51F6182F7F5443"/>
+ <TestFrame time="930" hash="09B5849DF18F6817F7450230DFEC0E95"/>
+ <TestFrame time="960" hash="15D212C1291DF97E3DEA5AA8793AD5CB"/>
+ <TestFrame time="990" hash="D6E42E8F4D06BDDBAE998079AC2C79AD"/>
+ <TestFrame time="1020" hash="7016B5C435006D859AB087A73299B6D5"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/easing/manifest.xml b/tests/auto/declarative/visual/easing/manifest.xml
new file mode 100644
index 0000000..3c84452
--- /dev/null
+++ b/tests/auto/declarative/visual/easing/manifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="480" type="2" button="1" buttons="1" globalPos="487,444" pos="483,417"/>
+ <TestFrame time="510" hash="83FB660D6CABAAFCB27C6EC001B14110"/>
+ <TestFrame time="540" hash="27FCD68F610024000CA6D3A8D9F0CF09"/>
+ <TestFrame time="570" hash="14728A6160AF51FCA8562D6A020BBA79"/>
+ <TestFrame time="600" hash="BDDB81682B30A6918927ACB59608D14E"/>
+ <TestFrame time="630" hash="03F16A41DCD31E41935E54763757C6D5"/>
+ <TestFrame time="660" hash="2D04EA1EBEDC77CF5D42A1B491A57EA6"/>
+ <TestFrame time="690" hash="762C36B33B75F24427CA45F4AD06B64E"/>
+ <TestFrame time="720" hash="AA02624CC889C95A99BBE58365F4FAAD"/>
+ <TestFrame time="750" hash="0529200188188708A18CE0F931780DBD"/>
+ <TestFrame time="780" hash="56036B63822AF34F26B149069CD189C6"/>
+ <TestFrame time="810" hash="CFFC6583E2BA1E47E1439BED6FE69665"/>
+ <TestFrame time="840" hash="25A1AFDC945D5264FF0337A421143A3C"/>
+ <TestFrame time="870" hash="601FA34B5E15E7B87E6490580C2E1858"/>
+ <TestFrame time="900" hash="1CA085F6CB8509957A51F6182F7F5443"/>
+ <TestFrame time="930" hash="09B5849DF18F6817F7450230DFEC0E95"/>
+ <TestFrame time="960" hash="15D212C1291DF97E3DEA5AA8793AD5CB"/>
+ <TestFrame time="990" hash="D6E42E8F4D06BDDBAE998079AC2C79AD"/>
+ <TestFrame time="1020" hash="7016B5C435006D859AB087A73299B6D5"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/easing/pics/qtlogo.png b/tests/auto/declarative/visual/easing/pics/qtlogo.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/tests/auto/declarative/visual/easing/pics/qtlogo.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flickable/Day.qml b/tests/auto/declarative/visual/flickable/Day.qml
new file mode 100644
index 0000000..0765e2f
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/Day.qml
@@ -0,0 +1,8 @@
+<Rect width="400" height="500" radius="7" pen.color="black" id="Page">
+ <properties>
+ <Property name="day" type="string" />
+ </properties>
+
+ <Image x="10" y="10" file="cork.jpg" opaque="true"/>
+ <Text x="20" y="20" height="40" font.size="14" font.bold="true" width="370" text="{day}" style="Outline" styleColor="#dedede"/>
+</Rect>
diff --git a/tests/auto/declarative/visual/flickable/cork.jpg b/tests/auto/declarative/visual/flickable/cork.jpg
new file mode 100644
index 0000000..d4d706c
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/cork.jpg
Binary files differ
diff --git a/tests/auto/declarative/visual/flickable/flickable.xml b/tests/auto/declarative/visual/flickable/flickable.xml
new file mode 100644
index 0000000..78bf42f
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/flickable.xml
@@ -0,0 +1,43 @@
+<Rect color="lightSteelBlue" width="800" height="500">
+ <ListModel id="List">
+ <Day>
+ <name>Sunday</name>
+ <dayColor>#808080</dayColor>
+ </Day>
+ <Day>
+ <name>Monday</name>
+ <dayColor>blue</dayColor>
+ </Day>
+ <Day>
+ <name>Tuesday</name>
+ <dayColor>yellow</dayColor>
+ </Day>
+ <Day>
+ <name>Wednesday</name>
+ <dayColor>purple</dayColor>
+ </Day>
+ <Day>
+ <name>Thursday</name>
+ <dayColor>blue</dayColor>
+ </Day>
+ <Day>
+ <name>Friday</name>
+ <dayColor>green</dayColor>
+ </Day>
+ <Day>
+ <name>Saturday</name>
+ <dayColor>orange</dayColor>
+ </Day>
+ </ListModel>
+
+ <Flickable id="Flick" anchors.fill="{parent}" viewportWidth="{Lay.width}">
+ <HorizontalLayout id="Lay">
+ <Repeater dataSource="{List}">
+ <Component>
+ <Day day="{name}" color="{dayColor}" />
+ </Component>
+ </Repeater>
+ </HorizontalLayout>
+ </Flickable>
+
+</Rect>
diff --git a/tests/auto/declarative/visual/flickable/image0.png b/tests/auto/declarative/visual/flickable/image0.png
new file mode 100644
index 0000000..a70ec71
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flickable/manifest-fail.xml b/tests/auto/declarative/visual/flickable/manifest-fail.xml
new file mode 100644
index 0000000..0701fa1
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/manifest-fail.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="930" type="2" button="1" buttons="1" globalPos="1459,490" pos="712,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1457,490" pos="710,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1454,490" pos="707,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1446,488" pos="699,461"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1438,488" pos="691,461"/>
+ <TestFrame time="1020" hash="3A44CE7B924456B70E9ACAA4D6211036"/>
+ <TestMouse time="1050" type="5" button="0" buttons="1" globalPos="1402,484" pos="655,457"/>
+ <TestMouse time="1050" type="5" button="0" buttons="1" globalPos="1386,484" pos="639,457"/>
+ <TestFrame time="1050" hash="CC4B8F76C3758329C4792CC2499588B9"/>
+ <TestMouse time="1080" type="5" button="0" buttons="1" globalPos="1328,478" pos="581,451"/>
+ <TestFrame time="1080" hash="A314FC89F9915A0F62E77C649052F30B"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1306,476" pos="559,449"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1258,472" pos="511,445"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1234,468" pos="487,441"/>
+ <TestFrame time="1110" hash="496BEE45FD87ACA4335EB656DAB38E7C"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1206,466" pos="459,439"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1140,460" pos="393,433"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1106,454" pos="359,427"/>
+ <TestFrame time="1140" hash="9052B7F038D1BE19B5C603F2B376D95C"/>
+ <TestMouse time="1170" type="5" button="0" buttons="1" globalPos="980,438" pos="233,411"/>
+ <TestFrame time="1170" hash="75EBD16D2210983178EC267DD5C7E3DC"/>
+ <TestMouse time="1200" type="5" button="0" buttons="1" globalPos="930,432" pos="183,405"/>
+ <TestMouse time="1200" type="3" button="1" buttons="0" globalPos="930,432" pos="183,405"/>
+ <TestFrame time="1200" hash="A016C7981ACC7C26D0CDE0CF7D71E929"/>
+ <TestFrame time="1260" hash="A2EA153F54B2D98DEC895FC72D3279F0"/>
+ <TestFrame time="1290" hash="2702B6D7429FC955B2061C368910309F"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/flickable/manifest.xml b/tests/auto/declarative/visual/flickable/manifest.xml
new file mode 100644
index 0000000..84d6890
--- /dev/null
+++ b/tests/auto/declarative/visual/flickable/manifest.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="930" type="2" button="1" buttons="1" globalPos="1459,490" pos="712,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1457,490" pos="710,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1454,490" pos="707,463"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1446,488" pos="699,461"/>
+ <TestMouse time="1020" type="5" button="0" buttons="1" globalPos="1438,488" pos="691,461"/>
+ <TestFrame time="1020" hash="3A44CE7B924456B70E9ACAA4D6211036"/>
+ <TestMouse time="1050" type="5" button="0" buttons="1" globalPos="1402,484" pos="655,457"/>
+ <TestMouse time="1050" type="5" button="0" buttons="1" globalPos="1386,484" pos="639,457"/>
+ <TestFrame time="1050" hash="CC4B8F76C3758329C4792CC2499588B9"/>
+ <TestMouse time="1080" type="5" button="0" buttons="1" globalPos="1328,478" pos="581,451"/>
+ <TestFrame time="1080" hash="A314FC89F9915A0F62E77C649052F30B"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1306,476" pos="559,449"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1258,472" pos="511,445"/>
+ <TestMouse time="1110" type="5" button="0" buttons="1" globalPos="1234,468" pos="487,441"/>
+ <TestFrame time="1110" hash="496BEE45FD87ACA4335EB656DAB38E7C"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1206,466" pos="459,439"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1140,460" pos="393,433"/>
+ <TestMouse time="1140" type="5" button="0" buttons="1" globalPos="1106,454" pos="359,427"/>
+ <TestFrame time="1140" hash="9052B7F038D1BE19B5C603F2B376D95C"/>
+ <TestMouse time="1170" type="5" button="0" buttons="1" globalPos="980,438" pos="233,411"/>
+ <TestFrame time="1170" hash="75EBD16D2210983178EC267DD5C7E3DC"/>
+ <TestMouse time="1200" type="5" button="0" buttons="1" globalPos="930,432" pos="183,405"/>
+ <TestMouse time="1200" type="3" button="1" buttons="0" globalPos="930,432" pos="183,405"/>
+ <TestFrame time="1200" hash="A016C7981ACC7C26D0CDE0CF7D71E929"/>
+ <TestFrame time="1260" hash="203B3D2224AA0B9CB9DB64C837402047"/>
+ <TestFrame time="1290" hash="E9974E5662F22716C9BC2CF8D1FF12FE"/>
+ <TestFrame time="1320" hash="1218CCCC399AE53D5D99D3E7AFD73A16"/>
+ <TestFrame time="1350" hash="FA5D19578629F56972955E9FE530BE59"/>
+ <TestFrame time="1380" hash="B5B23BBDF1FEB6E6B55AE3909F607D96"/>
+ <TestFrame time="1410" hash="17EDC257AF24F178455CDEE7B9D73A9F"/>
+ <TestFrame time="1440" hash="F62E75656DC8AEF20426535DC25FC9F7"/>
+ <TestFrame time="1470" hash="973D39071B13FBBC700964CA1E4995DA"/>
+ <TestFrame time="1500" hash="391C67A59AC71B498381FC4D3DA1E8BB"/>
+ <TestFrame time="1530" hash="C1D86256E4BE487CB61AB1CC8D277FF2"/>
+ <TestFrame time="1560" hash="D5324FF0B16AA4B532007236222FEEAA"/>
+ <TestFrame time="1590" hash="4B14446DE1B9DE22D3DFF86A7CC46A05"/>
+ <TestFrame time="1620" hash="49E6FF8DEB537ECE9BDF56135FCB8BE3"/>
+ <TestFrame time="1650" hash="25D8D454CD32513F2E711D1B09DF87AF"/>
+ <TestFrame time="1680" hash="AB511F44DD761AC1070733CB81731451"/>
+ <TestFrame time="1710" hash="3441D361DB85B2522C8CCB8C21D95E70"/>
+ <TestFrame time="1740" hash="DB333DF49E6DB519F1F5436F6EEEF18E"/>
+ <TestFrame time="1770" hash="97044C41A8C27B534707352334CB100E"/>
+ <TestFrame time="1800" hash="C9EE4321669BB45A574D2CD3448553FE"/>
+ <TestFrame time="1830" hash="6E1067FB547479F8AC0214B1DE4F1ABD"/>
+ <TestFrame time="1860" hash="9AC3067759043EF1C8138C6E3D3B26D1"/>
+ <TestFrame time="1890" hash="F90BB455E7D0266C631BFD6657AC673F"/>
+ <TestFrame time="1920" hash="064CA0BCE5BCE1E5409F7E95F501843A"/>
+ <TestFrame time="1950" hash="AC5489FE171E537E5AF6EC9F8B5241DA"/>
+ <TestFrame time="1980" hash="BBF5D953DCF7FF64D99BF10E244FACE0"/>
+ <TestFrame time="2010" hash="309FC8E37A3EC93C41BC5E2F8F2962DB"/>
+ <TestFrame time="2040" hash="192B13ADD78B36E54E3D39E998641F82"/>
+ <TestFrame time="2070" hash="10F9D012CD1ECD9C8A872AA28191599E"/>
+ <TestFrame time="2100" hash="E3C9CE476A02915B7EEAA5D16747BD74"/>
+ <TestFrame time="2130" hash="24AD4F88A8BE8E4059517DA5AB9EC3F9"/>
+ <TestFrame time="2160" hash="74CE8AFFE7BAC8380E9EE27E482107E8"/>
+ <TestFrame time="2190" hash="C3377013131C3D1EEFFAEC37C0359E7B"/>
+ <TestFrame time="2220" hash="1850C61F261E6E148E12C9D9508411E4"/>
+ <TestFrame time="2250" hash="30EEAD3AC4C869FEB9A2E2F18BB5F335"/>
+ <TestFrame time="2280" hash="EB0F744274AF8FF27CAFC73053B63C87"/>
+ <TestFrame time="2310" hash="ADF16B9E820CF7F77E17E2383E0BF345"/>
+ <TestFrame time="2340" hash="8623C727CB6605607679B7C973E5CE61"/>
+ <TestFrame time="2370" hash="DE795BC19AD3B24FF091D6EB500C0C9A"/>
+ <TestFrame time="2400" hash="E85F53F766BE13A62272442916217181"/>
+ <TestFrame time="2430" hash="B5B05BF6D74AC22BC0DC5ECF8AFFD571"/>
+ <TestFrame time="2460" hash="C9DB0041AEA560EA3569FA6A37A8E226"/>
+ <TestFrame time="2490" hash="96B6E45404C4CB7C65A7113294679C96"/>
+ <TestFrame time="2520" hash="780599814A9AEEB63B6604F8627966FC"/>
+ <TestFrame time="2550" hash="40D7E36CD63DC9B6F5E0340F8E61DE4F"/>
+ <TestFrame time="2580" hash="127E4A92CC2AF9B6C7B5686ECED260E3"/>
+ <TestFrame time="2610" hash="10FEB4963AAD931587BAC2101367CB92"/>
+ <TestFrame time="2640" hash="2926893CD68516281E47EAD04720E4DB"/>
+ <TestFrame time="2670" hash="23F790EF701E37C3959465BF5298C9C2"/>
+ <TestFrame time="2700" hash="461224D0A6662450BA361FAF90CA3087"/>
+ <TestFrame time="2730" hash="3779C1CC5CD18633C70CE5614C2FCA33"/>
+ <TestFrame time="2760" hash="D93F3000F95110464793C9BAEF58D694"/>
+ <TestFrame time="2790" hash="0BFCCED8AE73FBCAC251442F002D603C"/>
+ <TestFrame time="2820" hash="AC1D13A5508255DCA994CC4685FB0AE3"/>
+ <TestFrame time="2850" hash="A6709853B44AB203FC8806D3F4159639"/>
+ <TestFrame time="2880" hash="171589A0F67D72F1685836F5EFF2DD10"/>
+ <TestFrame time="2910" hash="D4984C2B663CFA0CDE95F9AD5BC9937B"/>
+ <TestFrame time="2940" hash="1BB6D261C9E800004B180FB8EC0B45AD"/>
+ <TestFrame time="2970" hash="46CD4E37C989FACF2B7CD71A16DB495A"/>
+ <TestFrame time="3000" hash="8ED436FF855C96A8CEB795AE175A7C54"/>
+ <TestFrame time="3030" hash="8ED436FF855C96A8CEB795AE175A7C54"/>
+ <TestFrame time="3060" hash="138D8CC351C847F266C63F323BABD7FE"/>
+ <TestFrame time="3090" hash="8D90560CCF5EEB1475F3AA46295E4DD0"/>
+ <TestFrame time="3120" hash="DD893A953B945365B0F9287A79826A6D"/>
+ <TestFrame time="3150" hash="386A768FD485BB66C9DC1465399B58C8"/>
+ <TestFrame time="3180" hash="21340437F1A05C216005157A8E8A9EEF"/>
+ <TestFrame time="3210" hash="6E2DA9DA5964F59715B08FD59D8BC3EF"/>
+ <TestFrame time="3240" hash="DC7108F44E225D70349889D9E3F62E74"/>
+ <TestMouse time="4110" type="2" button="1" buttons="1" globalPos="853,492" pos="106,465"/>
+ <TestMouse time="4170" type="5" button="0" buttons="1" globalPos="854,493" pos="107,466"/>
+ <TestMouse time="4170" type="5" button="0" buttons="1" globalPos="855,493" pos="108,466"/>
+ <TestMouse time="4170" type="5" button="0" buttons="1" globalPos="856,494" pos="109,467"/>
+ <TestMouse time="4170" type="5" button="0" buttons="1" globalPos="857,494" pos="110,467"/>
+ <TestMouse time="4200" type="5" button="0" buttons="1" globalPos="859,494" pos="112,467"/>
+ <TestMouse time="4200" type="5" button="0" buttons="1" globalPos="860,495" pos="113,468"/>
+ <TestMouse time="4200" type="5" button="0" buttons="1" globalPos="862,495" pos="115,468"/>
+ <TestFrame time="4200" hash="3946A595E81E4388AFDDDB2539B21BF3"/>
+ <TestMouse time="4230" type="5" button="0" buttons="1" globalPos="864,495" pos="117,468"/>
+ <TestMouse time="4230" type="5" button="0" buttons="1" globalPos="869,495" pos="122,468"/>
+ <TestMouse time="4230" type="5" button="0" buttons="1" globalPos="872,495" pos="125,468"/>
+ <TestFrame time="4230" hash="D9F7C86886CC5309846694F5DA98A123"/>
+ <TestMouse time="4260" type="5" button="0" buttons="1" globalPos="875,495" pos="128,468"/>
+ <TestMouse time="4260" type="5" button="0" buttons="1" globalPos="892,497" pos="145,470"/>
+ <TestFrame time="4260" hash="0B923428F4EAF40CB032FE8880B10943"/>
+ <TestMouse time="4290" type="5" button="0" buttons="1" globalPos="911,499" pos="164,472"/>
+ <TestMouse time="4290" type="5" button="0" buttons="1" globalPos="919,499" pos="172,472"/>
+ <TestFrame time="4290" hash="F1FCED7910188DBEDC62E289EC98D14A"/>
+ <TestMouse time="4320" type="5" button="0" buttons="1" globalPos="938,499" pos="191,472"/>
+ <TestFrame time="4320" hash="71A01976611816A5D42BBB6BC6DE5336"/>
+ <TestMouse time="4350" type="5" button="0" buttons="1" globalPos="957,501" pos="210,474"/>
+ <TestMouse time="4350" type="5" button="0" buttons="1" globalPos="960,501" pos="213,474"/>
+ <TestFrame time="4350" hash="204D5511DFAA28AF3E499FD5E503592A"/>
+ <TestMouse time="4380" type="5" button="0" buttons="1" globalPos="968,501" pos="221,474"/>
+ <TestMouse time="4380" type="5" button="0" buttons="1" globalPos="986,503" pos="239,476"/>
+ <TestMouse time="4380" type="5" button="0" buttons="1" globalPos="989,503" pos="242,476"/>
+ <TestFrame time="4380" hash="E7F2934FB80FD155AAE4E558B1D31AF9"/>
+ <TestMouse time="4410" type="5" button="0" buttons="1" globalPos="1015,501" pos="268,474"/>
+ <TestMouse time="4410" type="5" button="0" buttons="1" globalPos="1025,499" pos="278,472"/>
+ <TestFrame time="4410" hash="DE795BC19AD3B24FF091D6EB500C0C9A"/>
+ <TestMouse time="4440" type="5" button="0" buttons="1" globalPos="1065,497" pos="318,470"/>
+ <TestFrame time="4440" hash="3A2D5734CCC3E5690EF24D412B5ADE32"/>
+ <TestMouse time="4470" type="5" button="0" buttons="1" globalPos="1083,495" pos="336,468"/>
+ <TestMouse time="4470" type="5" button="0" buttons="1" globalPos="1135,493" pos="388,466"/>
+ <TestMouse time="4470" type="5" button="0" buttons="1" globalPos="1171,489" pos="424,462"/>
+ <TestFrame time="4470" hash="A5F66816E008610C1DA44270F837C9DF"/>
+ <TestMouse time="4500" type="5" button="0" buttons="1" globalPos="1215,489" pos="468,462"/>
+ <TestMouse time="4500" type="5" button="0" buttons="1" globalPos="1319,483" pos="572,456"/>
+ <TestMouse time="4500" type="5" button="0" buttons="1" globalPos="1379,479" pos="632,452"/>
+ <TestFrame time="4500" hash="6AE11928E7948AD5F9CE5EE07B5E7390"/>
+ <TestMouse time="4530" type="5" button="0" buttons="1" globalPos="1441,475" pos="694,448"/>
+ <TestMouse time="4530" type="3" button="1" buttons="0" globalPos="1441,475" pos="694,448"/>
+ <TestFrame time="4530" hash="47B438BC833CFF7984D3E158B54F0EA5"/>
+ <TestFrame time="4590" hash="DA134DD6826A87BC08F3BE59F3D2866D"/>
+ <TestFrame time="4620" hash="D1E87BD1C6264CE83979D34500EEB85B"/>
+ <TestFrame time="4650" hash="37C13A368649152DD1D43BDD17BEEE97"/>
+ <TestFrame time="4680" hash="C461AE2C388F4B06E958C12B543E53C0"/>
+ <TestFrame time="4710" hash="6070DD498E15C27243F09FD8CF8C0D2F"/>
+ <TestFrame time="4740" hash="FB74E95CF41BDA785991BA01369E9320"/>
+ <TestFrame time="4770" hash="F52AE455BBA3BAD36ABB4DB2480549D6"/>
+ <TestFrame time="4800" hash="9BC4E043F6595493ED32BBAAB949CC15"/>
+ <TestFrame time="4830" hash="4C87F70F6A46B2066021A68435BB285D"/>
+ <TestFrame time="4860" hash="282A523039F702F22C5D7F2B00BCA1F4"/>
+ <TestFrame time="4890" hash="D1623E75F20C00F6F357346F57E5C343"/>
+ <TestFrame time="4920" hash="F96CC72E3671C64D87719E5DF8303FA9"/>
+ <TestFrame time="4950" hash="44D4E09F9AB5C20E7A7F1AEF920B3599"/>
+ <TestFrame time="4980" hash="BBAD1BD87E29C1F0834B16DA9C1317A4"/>
+ <TestFrame time="5010" hash="66DF69AD2EA4823E59F6FC296910822F"/>
+ <TestFrame time="5040" hash="A0DCE22CFADFE091C5474C231EAD191E"/>
+ <TestFrame time="5070" hash="AE67DD3CD8B77D001288558E3C67E675"/>
+ <TestFrame time="5100" hash="B028CC11B70C5288436E49DD439F9F46"/>
+ <TestFrame time="5130" hash="2FBEFA9C751317D668A1074E8BCB8B10"/>
+ <TestFrame time="5160" hash="2DB3A59F7CB89B89CD45B86008CC0541"/>
+ <TestFrame time="5190" hash="AFE0FD3CB16F9DDD3E8DAD46656BE099"/>
+ <TestFrame time="5220" hash="90C04F980A0C008D4B919D9A4B663762"/>
+ <TestFrame time="5250" hash="215CB75F6359548B7A4A408E83049A25"/>
+ <TestFrame time="5280" hash="8EC68EA3F6B54415EC9B860B0207351E"/>
+ <TestFrame time="5310" hash="8FC14C2EB103B4FDC5B17E6E0F2386D1"/>
+ <TestFrame time="5340" hash="938DA507656430E1758CB8B5E9D874B1"/>
+ <TestFrame time="5370" hash="30A3166F0169715DA9FECD48DA257625"/>
+ <TestFrame time="5400" hash="0C24CD68AFE9C24380178417FE835494"/>
+ <TestFrame time="5430" hash="C8A18880023CB12BA98EBDFF65875874"/>
+ <TestFrame time="5460" hash="FE3BCA8DC715A19161FCD48C728366A0"/>
+ <TestFrame time="5490" hash="4771F9D8AA2A177A190879EB543FA138"/>
+ <TestFrame time="5520" hash="971D611BC939AB20B998D659DF2235FE"/>
+ <TestFrame time="5550" hash="7AF899892AE28C61B71A5682F9540DB5"/>
+ <TestFrame time="5580" hash="CCF349DCA802D5D68B6C9CB368104EF8"/>
+ <TestFrame time="5610" hash="3DC13F8B693648ABBE8FD6935832BEC7"/>
+ <TestFrame time="5640" hash="ED2AD5E716D69FD1A87133209695E911"/>
+ <TestFrame time="5670" hash="037B45A66950DF70D8BD7BC0E000ECC7"/>
+ <TestFrame time="5700" hash="43B59CF46A829CAFF7D9C0A6D1175581"/>
+ <TestFrame time="5730" hash="6FF016CE82BFD220418C0A9A644F2F81"/>
+ <TestFrame time="5760" hash="96D37AFF283210D59287526798E9376D"/>
+ <TestFrame time="5790" hash="7289570ABB671359AC2F2DF1898748CA"/>
+ <TestFrame time="5820" hash="2B3AF6424765512B8949BBB9BF6571DC"/>
+ <TestFrame time="5850" hash="23054E1F931342B8A6C5F6D30A9FF158"/>
+ <TestFrame time="5880" hash="E3D6EBB07FC90AD2483E95C09CB9E074"/>
+ <TestFrame time="5910" hash="08EE4C4D9F161AB4118EAD4F4AA8D5B3"/>
+ <TestFrame time="5940" hash="96D37AFF283210D59287526798E9376D"/>
+ <TestFrame time="5970" hash="40FB8747AACD078576573CF346E2C418"/>
+ <TestFrame time="6000" hash="4095D9B46D265D28C88DE0D0E02AC840"/>
+ <TestFrame time="6030" hash="E370C2A5451DC73AE4F742D52E3DAD4D"/>
+ <TestFrame time="6060" hash="AC4DC18BEFE0895C1ADF8EE2E3094A09"/>
+ <TestFrame time="6090" hash="AC4DC18BEFE0895C1ADF8EE2E3094A09"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/flipable/flipable.xml b/tests/auto/declarative/visual/flipable/flipable.xml
new file mode 100644
index 0000000..d769e55
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/flipable.xml
@@ -0,0 +1,138 @@
+<Rect color="lightsteelblue" height="400" width="500">
+ <VisualModel id="MyVisualModel">
+ <model>
+ <ListModel id="ListModel">
+ <Person>
+ <name>Jessica</name>
+ <picture>face.png</picture>
+ </Person>
+ <Person>
+ <name>John</name>
+ <picture>photo0.png</picture>
+ </Person>
+ <Person>
+ <name>Susan</name>
+ <picture>photo10.png</picture>
+ </Person>
+ <Person>
+ <name>Samantha</name>
+ <picture>photo1.png</picture>
+ </Person>
+ <Person>
+ <name>Mark</name>
+ <picture>photo2.png</picture>
+ </Person>
+ <Person>
+ <name>Sarah</name>
+ <picture>photo3.png</picture>
+ </Person>
+ <Person>
+ <name>Pam</name>
+ <picture>photo4.png</picture>
+ </Person>
+ <Person>
+ <name>April</name>
+ <picture>photo5.png</picture>
+ </Person>
+ <Person>
+ <name>Tarryn</name>
+ <picture>photo6.png</picture>
+ </Person>
+ <Person>
+ <name>Geoff</name>
+ <picture>photo7.png</picture>
+ </Person>
+ <Person>
+ <name>Bill</name>
+ <picture>photo8.png</picture>
+ </Person>
+ <Person>
+ <name>Stuart</name>
+ <picture>photo9.png</picture>
+ </Person>
+ </ListModel>
+ </model>
+ <delegate>
+ <Package>
+ <Flipable id="MeRect" width="100" height="100">
+ <properties>
+ <Property name="r" type="Real" />
+ </properties>
+ <transform>
+ <Perspective angle="90" x="50" y="50" aspect="1" scale="256"/>
+ <Axis xStart="50" xEnd="50" yStart="0" yEnd="1" rotation="{MeRect.r}" />
+ </transform>
+
+ <front>
+ <Rect radius="5" color="red" width="100" height="100">
+ <Text text="{name}" />
+ </Rect>
+ </front>
+
+ <back>
+ <Rect radius="5" color="red" width="100" height="100">
+ <Image anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}" file="{picture}" />
+ </Rect>
+ </back>
+ </Flipable>
+
+ <Item Package.name="leftBox" id="LeftBox"
+ width="100" height="100">
+ <Rect opacity="0.1" width="80" height="80" radius="4"
+ color="grey" x="10" y="10">
+ <Text text="{name}" />
+ <MouseRegion anchors.fill="{parent}" onClick="if(MyItem.currentState=='left') MyItem.currentState='right'; else MyItem.currentState='left';" />
+ </Rect>
+ </Item>
+ <Item Package.name="rightBox" id="RightBox"
+ width="100" height="100">
+ <Rect opacity="0.1" width="80" height="80" radius="4"
+ color="grey" x="10" y="10">
+ <Text text="{name}" />
+ <MouseRegion anchors.fill="{parent}" onClick="if(MyItem.currentState=='left') MyItem.currentState='right'; else MyItem.currentState='left';" />
+ </Rect>
+ </Item>
+ <Item id="MyItem">
+ <states>
+ <State name="left">
+ <SetProperty target="{MeRect}" property="moveToParent" value="{LeftBox}" />
+ </State>
+ <State name="right">
+ <SetProperty target="{MeRect}" property="moveToParent" value="{RightBox}" />
+ <SetProperty target="{MeRect}" property="r" value="180" />
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="*">
+ <NumericAnimation property="r" duration="500" />
+ <SerialAnimation>
+ <SetPropertyAction target="{MeRect}" property="moveToParent" value="{Bounce}" />
+ <ParallelAnimation>
+ <NumericAnimation target="{MeRect}" properties="x" to="0" duration="250" />
+ <NumericAnimation target="{MeRect}" properties="y" to="0" easing="easeInQuad" duration="250"/>
+ </ParallelAnimation>
+ <SetPropertyAction target="{MeRect}" property="moveToParent" />
+ <ParallelAnimation>
+ <NumericAnimation target="{MeRect}" properties="x" to="0" duration="250"/>
+ <NumericAnimation target="{MeRect}" properties="y" to="0" easing="easeOutQuad" duration="250"/>
+ </ParallelAnimation>
+ </SerialAnimation>
+ </Transition>
+ </transitions>
+ <currentState>left</currentState>
+ </Item>
+
+ </Package>
+ </delegate>
+ </VisualModel>
+
+ <Item width="800" height="400" clip="true">
+ <Item z="100" id="Bounce" x="200" y="300" />
+ <ListView id="MyListView" width="400" height="400" x="400"
+ model="{MyVisualModel.parts.rightBox}" />
+
+ <ListView id="MyListView2" width="400" height="400"
+ model="{MyVisualModel.parts.leftBox}" />
+ </Item>
+
+</Rect>
diff --git a/tests/auto/declarative/visual/flipable/image0.png b/tests/auto/declarative/visual/flipable/image0.png
new file mode 100644
index 0000000..affb8a5
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/manifest-play.xml b/tests/auto/declarative/visual/flipable/manifest-play.xml
new file mode 100644
index 0000000..81c08e4
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/manifest-play.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="2040" type="2" button="1" buttons="1" globalPos="812,72" pos="65,45"/>
+ <TestMouse time="2100" type="3" button="1" buttons="0" globalPos="812,72" pos="65,45"/>
+ <TestFrame time="2130" hash="210454ECF70EEA9CA43DD391BC23178B"/>
+ <TestFrame time="2160" hash="F6612DAD879208F4AF100337271C445C"/>
+ <TestFrame time="2190" hash="C77FC41100D0B066F8F0BF4ABCF2F0BF"/>
+ <TestFrame time="2220" hash="1AB3A42E6FC271E049E6071A88AB8EE4"/>
+ <TestFrame time="2250" hash="DB3D5BC6882699DCC0208E4F5294B609"/>
+ <TestFrame time="2280" hash="DC5A8B44283DA4A81D3994B873FC5695"/>
+ <TestFrame time="2310" hash="5149027ECF7813BA64D3AB8FFE0265F5"/>
+ <TestFrame time="2340" hash="B7E801DF476C012AC3E9E48A9D4AA321"/>
+ <TestFrame time="2370" hash="F31A647A6A3EC86D7F16EB3147E5FC29"/>
+ <TestFrame time="2400" hash="FBB068C39D5188A175075667B584F1BE"/>
+ <TestFrame time="2430" hash="EC487AB66384A4A3A718D03555EBFD41"/>
+ <TestFrame time="2460" hash="C7AD11EB051B11ACBA38027013215A05"/>
+ <TestFrame time="2490" hash="AA38FD8E97EC394488274127630E7946"/>
+ <TestFrame time="2520" hash="1CA2B617AC966B54FFA1A61914F68A9D"/>
+ <TestFrame time="2550" hash="1726C0BAA930CAF282154F14AC2FD120"/>
+ <TestFrame time="2580" hash="58F8196148C8B64191AF7B897A811CFB"/>
+ <TestFrame time="2610" hash="D56D3FA137AA63A0215611450B40F3E0"/>
+ <TestFrame time="2640" hash="5E1BCDF996B2903D1EAEAC65E17783C2"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/flipable/manifest.xml b/tests/auto/declarative/visual/flipable/manifest.xml
new file mode 100644
index 0000000..81c08e4
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/manifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestMouse time="2040" type="2" button="1" buttons="1" globalPos="812,72" pos="65,45"/>
+ <TestMouse time="2100" type="3" button="1" buttons="0" globalPos="812,72" pos="65,45"/>
+ <TestFrame time="2130" hash="210454ECF70EEA9CA43DD391BC23178B"/>
+ <TestFrame time="2160" hash="F6612DAD879208F4AF100337271C445C"/>
+ <TestFrame time="2190" hash="C77FC41100D0B066F8F0BF4ABCF2F0BF"/>
+ <TestFrame time="2220" hash="1AB3A42E6FC271E049E6071A88AB8EE4"/>
+ <TestFrame time="2250" hash="DB3D5BC6882699DCC0208E4F5294B609"/>
+ <TestFrame time="2280" hash="DC5A8B44283DA4A81D3994B873FC5695"/>
+ <TestFrame time="2310" hash="5149027ECF7813BA64D3AB8FFE0265F5"/>
+ <TestFrame time="2340" hash="B7E801DF476C012AC3E9E48A9D4AA321"/>
+ <TestFrame time="2370" hash="F31A647A6A3EC86D7F16EB3147E5FC29"/>
+ <TestFrame time="2400" hash="FBB068C39D5188A175075667B584F1BE"/>
+ <TestFrame time="2430" hash="EC487AB66384A4A3A718D03555EBFD41"/>
+ <TestFrame time="2460" hash="C7AD11EB051B11ACBA38027013215A05"/>
+ <TestFrame time="2490" hash="AA38FD8E97EC394488274127630E7946"/>
+ <TestFrame time="2520" hash="1CA2B617AC966B54FFA1A61914F68A9D"/>
+ <TestFrame time="2550" hash="1726C0BAA930CAF282154F14AC2FD120"/>
+ <TestFrame time="2580" hash="58F8196148C8B64191AF7B897A811CFB"/>
+ <TestFrame time="2610" hash="D56D3FA137AA63A0215611450B40F3E0"/>
+ <TestFrame time="2640" hash="5E1BCDF996B2903D1EAEAC65E17783C2"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/flipable/pics/arrow.png b/tests/auto/declarative/visual/flipable/pics/arrow.png
new file mode 100644
index 0000000..997190d
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/arrow.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/face.png b/tests/auto/declarative/visual/flipable/pics/face.png
new file mode 100644
index 0000000..e9529ac
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/face.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo0.png b/tests/auto/declarative/visual/flipable/pics/photo0.png
new file mode 100644
index 0000000..26bbf5b
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo1.png b/tests/auto/declarative/visual/flipable/pics/photo1.png
new file mode 100644
index 0000000..2230f71
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo1.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo10.png b/tests/auto/declarative/visual/flipable/pics/photo10.png
new file mode 100644
index 0000000..119f142
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo10.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo2.png b/tests/auto/declarative/visual/flipable/pics/photo2.png
new file mode 100644
index 0000000..e3d58c1
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo2.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo3.png b/tests/auto/declarative/visual/flipable/pics/photo3.png
new file mode 100644
index 0000000..4b58df4
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo3.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo4.png b/tests/auto/declarative/visual/flipable/pics/photo4.png
new file mode 100644
index 0000000..4ed4bd2
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo4.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo5.png b/tests/auto/declarative/visual/flipable/pics/photo5.png
new file mode 100644
index 0000000..eb26704
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo5.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo6.png b/tests/auto/declarative/visual/flipable/pics/photo6.png
new file mode 100644
index 0000000..69875ce
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo6.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo7.png b/tests/auto/declarative/visual/flipable/pics/photo7.png
new file mode 100644
index 0000000..0b117c9
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo7.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo8.png b/tests/auto/declarative/visual/flipable/pics/photo8.png
new file mode 100644
index 0000000..b77b997
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo8.png
Binary files differ
diff --git a/tests/auto/declarative/visual/flipable/pics/photo9.png b/tests/auto/declarative/visual/flipable/pics/photo9.png
new file mode 100644
index 0000000..8a974d6
--- /dev/null
+++ b/tests/auto/declarative/visual/flipable/pics/photo9.png
Binary files differ
diff --git a/tests/auto/declarative/visual/pauseAnimation/image0.png b/tests/auto/declarative/visual/pauseAnimation/image0.png
new file mode 100644
index 0000000..80fd4d1
--- /dev/null
+++ b/tests/auto/declarative/visual/pauseAnimation/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/pauseAnimation/manifest-play.xml b/tests/auto/declarative/visual/pauseAnimation/manifest-play.xml
new file mode 100644
index 0000000..6b15341
--- /dev/null
+++ b/tests/auto/declarative/visual/pauseAnimation/manifest-play.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestFrame time="60" hash="0C20D12464ABBDC45041EA5D9F2719B1"/>
+ <TestFrame time="90" hash="6579681C59DD571DF0EE4429D74FB5C7"/>
+ <TestFrame time="120" hash="7DA50C2984E012F217DC44F79AD86D55"/>
+ <TestFrame time="150" hash="D5E2A4ABDCA59FA26FCE968AB11F0719"/>
+ <TestFrame time="180" hash="005ACBEF952A8EE536E6308A48223E65"/>
+ <TestFrame time="210" hash="C4F844EE71F23635BB3EC7375F6A134F"/>
+ <TestFrame time="240" hash="D9604BE23A91327E6AB454609A9D4A13"/>
+ <TestFrame time="270" hash="DA60100DC55023C3BAB367D97C8F6A85"/>
+ <TestFrame time="300" hash="79EC710576427DF73DD03F39FBA6E2EB"/>
+ <TestFrame time="330" hash="FFD39C1122FE2F7877EF30591B539B40"/>
+ <TestFrame time="360" hash="C1A7B7D6D64AC5584C073C2881290696"/>
+ <TestFrame time="390" hash="29ECE1BCA4D21FB5862091317D430A13"/>
+ <TestFrame time="420" hash="C1A7B7D6D64AC5584C073C2881290696"/>
+ <TestFrame time="450" hash="4AC43A03CC6F2020AB5F894D704092AC"/>
+ <TestFrame time="480" hash="6CC9DE62A0C8FA5E42EAC1B01E99AC32"/>
+ <TestFrame time="510" hash="D754D35D0793F9F7D4F6249A874E4C45"/>
+ <TestFrame time="540" hash="B2C778A5EFF5F01EDC54F03D8B4DE8C7"/>
+ <TestFrame time="570" hash="A4D9DFDBF32C0AD31794B04A2E23A0DB"/>
+ <TestFrame time="600" hash="5025EB75C88F0760F637E0342B7F88A2"/>
+ <TestFrame time="630" hash="F4732FF2DF93FE67CB850DEC34184924"/>
+ <TestFrame time="660" hash="97566CE9558D13EA0780BCE233097B27"/>
+ <TestFrame time="690" hash="2AD64CB01C9D50E0118D5ECE0A644DF2"/>
+ <TestFrame time="720" hash="721D7061811B5439C2E8E395917494BC"/>
+ <TestFrame time="750" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="780" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="810" hash="336D31586171F22D541B989D24B95CBB"/>
+ <TestFrame time="840" hash="6D63FB5C8A80F0280E88B2CDF8641BB9"/>
+ <TestFrame time="870" hash="EF8941674CB61F54853DC33652BB854E"/>
+ <TestFrame time="900" hash="0C20D12464ABBDC45041EA5D9F2719B1"/>
+ <TestFrame time="930" hash="53AE93140252373EAA4D9DA73756BD8E"/>
+ <TestFrame time="960" hash="AF3120FE262D2489C0ED33FBBEE1549F"/>
+ <TestFrame time="990" hash="A88A8129259F86DF5A73ADDC3649AD37"/>
+ <TestFrame time="1020" hash="3DB5E30EF19EA693C21CCF72892C4390"/>
+ <TestFrame time="1050" hash="E553F365912586C6408C8C53B1B7D118"/>
+ <TestFrame time="1080" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="1110" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="1140" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="1170" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="1200" hash="E553F365912586C6408C8C53B1B7D118"/>
+ <TestFrame time="1230" hash="3DB5E30EF19EA693C21CCF72892C4390"/>
+ <TestFrame time="1260" hash="A8B624EBFC9AB713D1CE55F318A6E90D"/>
+ <TestFrame time="1290" hash="AF3120FE262D2489C0ED33FBBEE1549F"/>
+ <TestFrame time="1320" hash="53AE93140252373EAA4D9DA73756BD8E"/>
+ <TestFrame time="1350" hash="BC426FB7C31751665B0D3F16E2CB0173"/>
+ <TestFrame time="1380" hash="DD60CBAFF6F34027474E92315DBC0EBC"/>
+ <TestFrame time="1410" hash="F0D8132489C2F2EF760E905B3C093726"/>
+ <TestFrame time="1440" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="1470" hash="DCF2867C127E041970047EC8F3EDC04F"/>
+ <TestFrame time="1500" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="1530" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="1560" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="1590" hash="A725B59B4947357546BBFC7DF3D830AF"/>
+ <TestFrame time="1620" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="1650" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="1680" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="1710" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="1740" hash="A725B59B4947357546BBFC7DF3D830AF"/>
+ <TestFrame time="1770" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="1800" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="1830" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="1860" hash="A350B70C5238A340E85FD4A3EC0390A3"/>
+ <TestFrame time="1890" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="1920" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="1950" hash="DCF2867C127E041970047EC8F3EDC04F"/>
+ <TestFrame time="1980" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="2010" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="2040" hash="A350B70C5238A340E85FD4A3EC0390A3"/>
+ <TestFrame time="3060" hash="0C20D12464ABBDC45041EA5D9F2719B1"/>
+ <TestFrame time="3090" hash="6579681C59DD571DF0EE4429D74FB5C7"/>
+ <TestFrame time="3120" hash="7DA50C2984E012F217DC44F79AD86D55"/>
+ <TestFrame time="3150" hash="D5E2A4ABDCA59FA26FCE968AB11F0719"/>
+ <TestFrame time="3180" hash="005ACBEF952A8EE536E6308A48223E65"/>
+ <TestFrame time="3210" hash="C4F844EE71F23635BB3EC7375F6A134F"/>
+ <TestFrame time="3240" hash="D9604BE23A91327E6AB454609A9D4A13"/>
+ <TestFrame time="3270" hash="DA60100DC55023C3BAB367D97C8F6A85"/>
+ <TestFrame time="3300" hash="79EC710576427DF73DD03F39FBA6E2EB"/>
+ <TestFrame time="3330" hash="FFD39C1122FE2F7877EF30591B539B40"/>
+ <TestFrame time="3360" hash="C1A7B7D6D64AC5584C073C2881290696"/>
+ <TestFrame time="3390" hash="29ECE1BCA4D21FB5862091317D430A13"/>
+ <TestFrame time="3420" hash="C1A7B7D6D64AC5584C073C2881290696"/>
+ <TestFrame time="3450" hash="4AC43A03CC6F2020AB5F894D704092AC"/>
+ <TestFrame time="3480" hash="6CC9DE62A0C8FA5E42EAC1B01E99AC32"/>
+ <TestFrame time="3510" hash="D754D35D0793F9F7D4F6249A874E4C45"/>
+ <TestFrame time="3540" hash="B2C778A5EFF5F01EDC54F03D8B4DE8C7"/>
+ <TestFrame time="3570" hash="A4D9DFDBF32C0AD31794B04A2E23A0DB"/>
+ <TestFrame time="3600" hash="5025EB75C88F0760F637E0342B7F88A2"/>
+ <TestFrame time="3630" hash="F4732FF2DF93FE67CB850DEC34184924"/>
+ <TestFrame time="3660" hash="97566CE9558D13EA0780BCE233097B27"/>
+ <TestFrame time="3690" hash="2AD64CB01C9D50E0118D5ECE0A644DF2"/>
+ <TestFrame time="3720" hash="721D7061811B5439C2E8E395917494BC"/>
+ <TestFrame time="3750" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="3780" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="3810" hash="336D31586171F22D541B989D24B95CBB"/>
+ <TestFrame time="3840" hash="6D63FB5C8A80F0280E88B2CDF8641BB9"/>
+ <TestFrame time="3870" hash="EF8941674CB61F54853DC33652BB854E"/>
+ <TestFrame time="3900" hash="0C20D12464ABBDC45041EA5D9F2719B1"/>
+ <TestFrame time="3930" hash="53AE93140252373EAA4D9DA73756BD8E"/>
+ <TestFrame time="3960" hash="AF3120FE262D2489C0ED33FBBEE1549F"/>
+ <TestFrame time="3990" hash="A88A8129259F86DF5A73ADDC3649AD37"/>
+ <TestFrame time="4020" hash="3DB5E30EF19EA693C21CCF72892C4390"/>
+ <TestFrame time="4050" hash="E553F365912586C6408C8C53B1B7D118"/>
+ <TestFrame time="4080" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="4110" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="4140" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="4170" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="4200" hash="E553F365912586C6408C8C53B1B7D118"/>
+ <TestFrame time="4230" hash="3DB5E30EF19EA693C21CCF72892C4390"/>
+ <TestFrame time="4260" hash="A8B624EBFC9AB713D1CE55F318A6E90D"/>
+ <TestFrame time="4290" hash="AF3120FE262D2489C0ED33FBBEE1549F"/>
+ <TestFrame time="4320" hash="53AE93140252373EAA4D9DA73756BD8E"/>
+ <TestFrame time="4350" hash="BC426FB7C31751665B0D3F16E2CB0173"/>
+ <TestFrame time="4380" hash="DD60CBAFF6F34027474E92315DBC0EBC"/>
+ <TestFrame time="4410" hash="F0D8132489C2F2EF760E905B3C093726"/>
+ <TestFrame time="4440" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="4470" hash="DCF2867C127E041970047EC8F3EDC04F"/>
+ <TestFrame time="4500" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="4530" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="4560" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="4590" hash="A725B59B4947357546BBFC7DF3D830AF"/>
+ <TestFrame time="4620" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="4650" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="4680" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="4710" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="4740" hash="A725B59B4947357546BBFC7DF3D830AF"/>
+ <TestFrame time="4770" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="4800" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="4830" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="4860" hash="A350B70C5238A340E85FD4A3EC0390A3"/>
+ <TestFrame time="4890" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="4920" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="4950" hash="DCF2867C127E041970047EC8F3EDC04F"/>
+ <TestFrame time="4980" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="5010" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="5040" hash="A350B70C5238A340E85FD4A3EC0390A3"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/pauseAnimation/manifest.xml b/tests/auto/declarative/visual/pauseAnimation/manifest.xml
new file mode 100644
index 0000000..6b15341
--- /dev/null
+++ b/tests/auto/declarative/visual/pauseAnimation/manifest.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+ <TestFrame time="60" hash="0C20D12464ABBDC45041EA5D9F2719B1"/>
+ <TestFrame time="90" hash="6579681C59DD571DF0EE4429D74FB5C7"/>
+ <TestFrame time="120" hash="7DA50C2984E012F217DC44F79AD86D55"/>
+ <TestFrame time="150" hash="D5E2A4ABDCA59FA26FCE968AB11F0719"/>
+ <TestFrame time="180" hash="005ACBEF952A8EE536E6308A48223E65"/>
+ <TestFrame time="210" hash="C4F844EE71F23635BB3EC7375F6A134F"/>
+ <TestFrame time="240" hash="D9604BE23A91327E6AB454609A9D4A13"/>
+ <TestFrame time="270" hash="DA60100DC55023C3BAB367D97C8F6A85"/>
+ <TestFrame time="300" hash="79EC710576427DF73DD03F39FBA6E2EB"/>
+ <TestFrame time="330" hash="FFD39C1122FE2F7877EF30591B539B40"/>
+ <TestFrame time="360" hash="C1A7B7D6D64AC5584C073C2881290696"/>
+ <TestFrame time="390" hash="29ECE1BCA4D21FB5862091317D430A13"/>
+ <TestFrame time="420" hash="C1A7B7D6D64AC5584C073C2881290696"/>
+ <TestFrame time="450" hash="4AC43A03CC6F2020AB5F894D704092AC"/>
+ <TestFrame time="480" hash="6CC9DE62A0C8FA5E42EAC1B01E99AC32"/>
+ <TestFrame time="510" hash="D754D35D0793F9F7D4F6249A874E4C45"/>
+ <TestFrame time="540" hash="B2C778A5EFF5F01EDC54F03D8B4DE8C7"/>
+ <TestFrame time="570" hash="A4D9DFDBF32C0AD31794B04A2E23A0DB"/>
+ <TestFrame time="600" hash="5025EB75C88F0760F637E0342B7F88A2"/>
+ <TestFrame time="630" hash="F4732FF2DF93FE67CB850DEC34184924"/>
+ <TestFrame time="660" hash="97566CE9558D13EA0780BCE233097B27"/>
+ <TestFrame time="690" hash="2AD64CB01C9D50E0118D5ECE0A644DF2"/>
+ <TestFrame time="720" hash="721D7061811B5439C2E8E395917494BC"/>
+ <TestFrame time="750" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="780" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="810" hash="336D31586171F22D541B989D24B95CBB"/>
+ <TestFrame time="840" hash="6D63FB5C8A80F0280E88B2CDF8641BB9"/>
+ <TestFrame time="870" hash="EF8941674CB61F54853DC33652BB854E"/>
+ <TestFrame time="900" hash="0C20D12464ABBDC45041EA5D9F2719B1"/>
+ <TestFrame time="930" hash="53AE93140252373EAA4D9DA73756BD8E"/>
+ <TestFrame time="960" hash="AF3120FE262D2489C0ED33FBBEE1549F"/>
+ <TestFrame time="990" hash="A88A8129259F86DF5A73ADDC3649AD37"/>
+ <TestFrame time="1020" hash="3DB5E30EF19EA693C21CCF72892C4390"/>
+ <TestFrame time="1050" hash="E553F365912586C6408C8C53B1B7D118"/>
+ <TestFrame time="1080" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="1110" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="1140" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="1170" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="1200" hash="E553F365912586C6408C8C53B1B7D118"/>
+ <TestFrame time="1230" hash="3DB5E30EF19EA693C21CCF72892C4390"/>
+ <TestFrame time="1260" hash="A8B624EBFC9AB713D1CE55F318A6E90D"/>
+ <TestFrame time="1290" hash="AF3120FE262D2489C0ED33FBBEE1549F"/>
+ <TestFrame time="1320" hash="53AE93140252373EAA4D9DA73756BD8E"/>
+ <TestFrame time="1350" hash="BC426FB7C31751665B0D3F16E2CB0173"/>
+ <TestFrame time="1380" hash="DD60CBAFF6F34027474E92315DBC0EBC"/>
+ <TestFrame time="1410" hash="F0D8132489C2F2EF760E905B3C093726"/>
+ <TestFrame time="1440" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="1470" hash="DCF2867C127E041970047EC8F3EDC04F"/>
+ <TestFrame time="1500" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="1530" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="1560" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="1590" hash="A725B59B4947357546BBFC7DF3D830AF"/>
+ <TestFrame time="1620" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="1650" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="1680" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="1710" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="1740" hash="A725B59B4947357546BBFC7DF3D830AF"/>
+ <TestFrame time="1770" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="1800" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="1830" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="1860" hash="A350B70C5238A340E85FD4A3EC0390A3"/>
+ <TestFrame time="1890" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="1920" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="1950" hash="DCF2867C127E041970047EC8F3EDC04F"/>
+ <TestFrame time="1980" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="2010" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="2040" hash="A350B70C5238A340E85FD4A3EC0390A3"/>
+ <TestFrame time="3060" hash="0C20D12464ABBDC45041EA5D9F2719B1"/>
+ <TestFrame time="3090" hash="6579681C59DD571DF0EE4429D74FB5C7"/>
+ <TestFrame time="3120" hash="7DA50C2984E012F217DC44F79AD86D55"/>
+ <TestFrame time="3150" hash="D5E2A4ABDCA59FA26FCE968AB11F0719"/>
+ <TestFrame time="3180" hash="005ACBEF952A8EE536E6308A48223E65"/>
+ <TestFrame time="3210" hash="C4F844EE71F23635BB3EC7375F6A134F"/>
+ <TestFrame time="3240" hash="D9604BE23A91327E6AB454609A9D4A13"/>
+ <TestFrame time="3270" hash="DA60100DC55023C3BAB367D97C8F6A85"/>
+ <TestFrame time="3300" hash="79EC710576427DF73DD03F39FBA6E2EB"/>
+ <TestFrame time="3330" hash="FFD39C1122FE2F7877EF30591B539B40"/>
+ <TestFrame time="3360" hash="C1A7B7D6D64AC5584C073C2881290696"/>
+ <TestFrame time="3390" hash="29ECE1BCA4D21FB5862091317D430A13"/>
+ <TestFrame time="3420" hash="C1A7B7D6D64AC5584C073C2881290696"/>
+ <TestFrame time="3450" hash="4AC43A03CC6F2020AB5F894D704092AC"/>
+ <TestFrame time="3480" hash="6CC9DE62A0C8FA5E42EAC1B01E99AC32"/>
+ <TestFrame time="3510" hash="D754D35D0793F9F7D4F6249A874E4C45"/>
+ <TestFrame time="3540" hash="B2C778A5EFF5F01EDC54F03D8B4DE8C7"/>
+ <TestFrame time="3570" hash="A4D9DFDBF32C0AD31794B04A2E23A0DB"/>
+ <TestFrame time="3600" hash="5025EB75C88F0760F637E0342B7F88A2"/>
+ <TestFrame time="3630" hash="F4732FF2DF93FE67CB850DEC34184924"/>
+ <TestFrame time="3660" hash="97566CE9558D13EA0780BCE233097B27"/>
+ <TestFrame time="3690" hash="2AD64CB01C9D50E0118D5ECE0A644DF2"/>
+ <TestFrame time="3720" hash="721D7061811B5439C2E8E395917494BC"/>
+ <TestFrame time="3750" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="3780" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="3810" hash="336D31586171F22D541B989D24B95CBB"/>
+ <TestFrame time="3840" hash="6D63FB5C8A80F0280E88B2CDF8641BB9"/>
+ <TestFrame time="3870" hash="EF8941674CB61F54853DC33652BB854E"/>
+ <TestFrame time="3900" hash="0C20D12464ABBDC45041EA5D9F2719B1"/>
+ <TestFrame time="3930" hash="53AE93140252373EAA4D9DA73756BD8E"/>
+ <TestFrame time="3960" hash="AF3120FE262D2489C0ED33FBBEE1549F"/>
+ <TestFrame time="3990" hash="A88A8129259F86DF5A73ADDC3649AD37"/>
+ <TestFrame time="4020" hash="3DB5E30EF19EA693C21CCF72892C4390"/>
+ <TestFrame time="4050" hash="E553F365912586C6408C8C53B1B7D118"/>
+ <TestFrame time="4080" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="4110" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="4140" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="4170" hash="1373545E43FFF7251CEC9E8375EA267F"/>
+ <TestFrame time="4200" hash="E553F365912586C6408C8C53B1B7D118"/>
+ <TestFrame time="4230" hash="3DB5E30EF19EA693C21CCF72892C4390"/>
+ <TestFrame time="4260" hash="A8B624EBFC9AB713D1CE55F318A6E90D"/>
+ <TestFrame time="4290" hash="AF3120FE262D2489C0ED33FBBEE1549F"/>
+ <TestFrame time="4320" hash="53AE93140252373EAA4D9DA73756BD8E"/>
+ <TestFrame time="4350" hash="BC426FB7C31751665B0D3F16E2CB0173"/>
+ <TestFrame time="4380" hash="DD60CBAFF6F34027474E92315DBC0EBC"/>
+ <TestFrame time="4410" hash="F0D8132489C2F2EF760E905B3C093726"/>
+ <TestFrame time="4440" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="4470" hash="DCF2867C127E041970047EC8F3EDC04F"/>
+ <TestFrame time="4500" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="4530" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="4560" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="4590" hash="A725B59B4947357546BBFC7DF3D830AF"/>
+ <TestFrame time="4620" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="4650" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="4680" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="4710" hash="3042003C067B257DE2CB32F650DDE693"/>
+ <TestFrame time="4740" hash="A725B59B4947357546BBFC7DF3D830AF"/>
+ <TestFrame time="4770" hash="CE57E27AF329EBA4FAC3AB891F0407CE"/>
+ <TestFrame time="4800" hash="41BA853C3403F68A23E708DF82E21C53"/>
+ <TestFrame time="4830" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="4860" hash="A350B70C5238A340E85FD4A3EC0390A3"/>
+ <TestFrame time="4890" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="4920" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="4950" hash="DCF2867C127E041970047EC8F3EDC04F"/>
+ <TestFrame time="4980" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="5010" hash="675EBBDD22DD22CE45993DF4AF1ACFE9"/>
+ <TestFrame time="5040" hash="A350B70C5238A340E85FD4A3EC0390A3"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/pauseAnimation/pauseAnimation.xml b/tests/auto/declarative/visual/pauseAnimation/pauseAnimation.xml
new file mode 100644
index 0000000..bb411e2
--- /dev/null
+++ b/tests/auto/declarative/visual/pauseAnimation/pauseAnimation.xml
@@ -0,0 +1,13 @@
+<Rect id="rect" width="120" height="200" color="white">
+ <Image id="img" file="pics/qtlogo.png"
+ x="{60-img.width/2}" y="{200-img.height}">
+ <y>
+ <SerialAnimation running="true" repeat="true">
+ <NumericAnimation to="{200-img.height}"
+ easing="easeOutBounce(amplitude:100)"
+ duration="2000" />
+ <PauseAnimation duration="1000" />
+ </SerialAnimation>
+ </y>
+ </Image>
+</Rect>
diff --git a/tests/auto/declarative/visual/pauseAnimation/pics/qtlogo.png b/tests/auto/declarative/visual/pauseAnimation/pics/qtlogo.png
new file mode 100644
index 0000000..399bd0b
--- /dev/null
+++ b/tests/auto/declarative/visual/pauseAnimation/pics/qtlogo.png
Binary files differ
diff --git a/tests/auto/declarative/visual/qfxtext/elide/data/opengl/image0.png b/tests/auto/declarative/visual/qfxtext/elide/data/opengl/image0.png
new file mode 100644
index 0000000..7d45407
--- /dev/null
+++ b/tests/auto/declarative/visual/qfxtext/elide/data/opengl/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/qfxtext/elide/data/opengl/manifest.xml b/tests/auto/declarative/visual/qfxtext/elide/data/opengl/manifest.xml
new file mode 100644
index 0000000..b784f42
--- /dev/null
+++ b/tests/auto/declarative/visual/qfxtext/elide/data/opengl/manifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/qfxtext/elide/elide.xml b/tests/auto/declarative/visual/qfxtext/elide/elide.xml
new file mode 100644
index 0000000..398da82
--- /dev/null
+++ b/tests/auto/declarative/visual/qfxtext/elide/elide.xml
@@ -0,0 +1,6 @@
+<VerticalLayout width="80" height="{Text.height*4}">
+ <Text elide="ElideLeft" text="aaa bbb ccc ddd eee fff" width="80" color="white" id="Text"/>
+ <Text elide="ElideMiddle" text="aaa bbb ccc ddd eee fff" width="80" color="white"/>
+ <Text elide="ElideRight" text="aaa bbb ccc ddd eee fff" width="80" color="white"/>
+ <Text elide="ElideNone" text="aaa bbb ccc ddd eee fff" width="80" color="white"/>
+</VerticalLayout>
diff --git a/tests/auto/declarative/visual/qfxtext/elide/test b/tests/auto/declarative/visual/qfxtext/elide/test
new file mode 100644
index 0000000..d35cbc9
--- /dev/null
+++ b/tests/auto/declarative/visual/qfxtext/elide/test
@@ -0,0 +1 @@
+elide.xml
diff --git a/tests/auto/declarative/visual/repeater/basic1/basic1.xml b/tests/auto/declarative/visual/repeater/basic1/basic1.xml
new file mode 100644
index 0000000..def809f
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic1/basic1.xml
@@ -0,0 +1,21 @@
+<Rect color="blue" width="800" height="600" id="Page">
+ <HorizontalLayout>
+ <Repeater >
+ <component>
+ <Rect color="red" width="100" height="100">
+ <Text text="{name}" />
+ </Rect>
+ </component>
+ <dataSource>
+ <ListModel>
+ <Month>
+ <name>January</name>
+ </Month>
+ <Month>
+ <name>February</name>
+ </Month>
+ </ListModel>
+ </dataSource>
+ </Repeater>
+ </HorizontalLayout>
+</Rect>
diff --git a/tests/auto/declarative/visual/repeater/basic1/data/opengl/image0.png b/tests/auto/declarative/visual/repeater/basic1/data/opengl/image0.png
new file mode 100644
index 0000000..f0be97f
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic1/data/opengl/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/repeater/basic1/data/opengl/manifest.xml b/tests/auto/declarative/visual/repeater/basic1/data/opengl/manifest.xml
new file mode 100644
index 0000000..b784f42
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic1/data/opengl/manifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/repeater/basic1/test b/tests/auto/declarative/visual/repeater/basic1/test
new file mode 100644
index 0000000..62f0665
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic1/test
@@ -0,0 +1 @@
+basic1.xml
diff --git a/tests/auto/declarative/visual/repeater/basic2/basic2.xml b/tests/auto/declarative/visual/repeater/basic2/basic2.xml
new file mode 100644
index 0000000..b16fbfe
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic2/basic2.xml
@@ -0,0 +1,22 @@
+<Rect color="blue" width="800" height="600" id="Page">
+ <Component id="Delegate">
+ <Rect color="red" width="100" height="100">
+ <Text text="{name}" />
+ </Rect>
+ </Component>
+
+ <HorizontalLayout>
+ <Repeater component="{Delegate}">
+ <dataSource>
+ <ListModel>
+ <Month>
+ <name>January</name>
+ </Month>
+ <Month>
+ <name>February</name>
+ </Month>
+ </ListModel>
+ </dataSource>
+ </Repeater>
+ </HorizontalLayout>
+</Rect>
diff --git a/tests/auto/declarative/visual/repeater/basic2/data/opengl/image0.png b/tests/auto/declarative/visual/repeater/basic2/data/opengl/image0.png
new file mode 100644
index 0000000..f0be97f
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic2/data/opengl/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/repeater/basic2/data/opengl/manifest.xml b/tests/auto/declarative/visual/repeater/basic2/data/opengl/manifest.xml
new file mode 100644
index 0000000..b784f42
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic2/data/opengl/manifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/repeater/basic2/test b/tests/auto/declarative/visual/repeater/basic2/test
new file mode 100644
index 0000000..ae974fe
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic2/test
@@ -0,0 +1 @@
+basic2.xml
diff --git a/tests/auto/declarative/visual/repeater/basic3/basic3.xml b/tests/auto/declarative/visual/repeater/basic3/basic3.xml
new file mode 100644
index 0000000..1135f16
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic3/basic3.xml
@@ -0,0 +1,19 @@
+<Rect color="blue" width="800" height="600" id="Page">
+ <ListModel id="DataSource">
+ <Month>
+ <name>January</name>
+ </Month>
+ <Month>
+ <name>February</name>
+ </Month>
+ </ListModel>
+ <HorizontalLayout>
+ <Repeater dataSource="{DataSource}">
+ <component>
+ <Rect color="red" width="100" height="100">
+ <Text text="{name}" />
+ </Rect>
+ </component>
+ </Repeater>
+ </HorizontalLayout>
+</Rect>
diff --git a/tests/auto/declarative/visual/repeater/basic3/data/opengl/image0.png b/tests/auto/declarative/visual/repeater/basic3/data/opengl/image0.png
new file mode 100644
index 0000000..f0be97f
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic3/data/opengl/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/repeater/basic3/data/opengl/manifest.xml b/tests/auto/declarative/visual/repeater/basic3/data/opengl/manifest.xml
new file mode 100644
index 0000000..b784f42
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic3/data/opengl/manifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/repeater/basic3/test b/tests/auto/declarative/visual/repeater/basic3/test
new file mode 100644
index 0000000..ea3154e
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic3/test
@@ -0,0 +1 @@
+basic3.xml
diff --git a/tests/auto/declarative/visual/repeater/basic4/basic4.xml b/tests/auto/declarative/visual/repeater/basic4/basic4.xml
new file mode 100644
index 0000000..53b8ff9
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic4/basic4.xml
@@ -0,0 +1,18 @@
+<Rect color="blue" width="800" height="600" id="Page">
+ <ListModel id="DataSource">
+ <Month>
+ <name>January</name>
+ </Month>
+ <Month>
+ <name>February</name>
+ </Month>
+ </ListModel>
+ <Component id="Delegate">
+ <Rect color="red" width="100" height="100">
+ <Text text="{name}" />
+ </Rect>
+ </Component>
+ <HorizontalLayout>
+ <Repeater dataSource="{DataSource}" component="{Delegate}" />
+ </HorizontalLayout>
+</Rect>
diff --git a/tests/auto/declarative/visual/repeater/basic4/data/opengl/image0.png b/tests/auto/declarative/visual/repeater/basic4/data/opengl/image0.png
new file mode 100644
index 0000000..f0be97f
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic4/data/opengl/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/repeater/basic4/data/opengl/manifest.xml b/tests/auto/declarative/visual/repeater/basic4/data/opengl/manifest.xml
new file mode 100644
index 0000000..b784f42
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic4/data/opengl/manifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/repeater/basic4/test b/tests/auto/declarative/visual/repeater/basic4/test
new file mode 100644
index 0000000..891e0be
--- /dev/null
+++ b/tests/auto/declarative/visual/repeater/basic4/test
@@ -0,0 +1 @@
+basic4.xml
diff --git a/tests/auto/declarative/visual/runtests.sh b/tests/auto/declarative/visual/runtests.sh
new file mode 100755
index 0000000..f690381
--- /dev/null
+++ b/tests/auto/declarative/visual/runtests.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+for a in `cat tests`; do ./tst_visual -testdir $a; done
diff --git a/tests/auto/declarative/visual/tests b/tests/auto/declarative/visual/tests
new file mode 100644
index 0000000..ca72e9e
--- /dev/null
+++ b/tests/auto/declarative/visual/tests
@@ -0,0 +1,11 @@
+ListView/basic1
+ListView/basic2
+ListView/basic3
+ListView/basic4
+bindinganimation
+repeater/basic1
+repeater/basic2
+repeater/basic3
+repeater/basic4
+webview/autosize
+qfxtext/elide
diff --git a/tests/auto/declarative/visual/tst_visual.cpp b/tests/auto/declarative/visual/tst_visual.cpp
new file mode 100644
index 0000000..f077994
--- /dev/null
+++ b/tests/auto/declarative/visual/tst_visual.cpp
@@ -0,0 +1,72 @@
+#include <qtest.h>
+#include <QFxView>
+#include <QApplication>
+#include <QFxTestView>
+#include <QFile>
+
+static QString testdir;
+class tst_visual : public QObject
+{
+ Q_OBJECT
+public:
+ tst_visual() {}
+
+private slots:
+ void visual();
+};
+
+#ifdef QT_OPENGL_ES
+#define RASTER_TESTDIR "/data/opengl"
+#else
+#define RASTER_TESTDIR "/data/raster"
+#endif
+
+void tst_visual::visual()
+{
+ QVERIFY(!testdir.isEmpty());
+
+ QFile configFile(QLatin1String(QT_TEST_SOURCE_DIR) + "/" + testdir + "/test");
+ QVERIFY(configFile.open(QIODevice::ReadOnly));
+
+ QString testfile = configFile.readLine().trimmed();
+ QVERIFY(!testfile.isEmpty());
+
+ if(testfile.startsWith("QTDIR/")) {
+ testfile.remove(0, 6);
+ testfile.prepend(QLatin1String(QT_TEST_SOURCE_DIR) + "/../../../../");
+ } else {
+ testfile.prepend(QLatin1String(QT_TEST_SOURCE_DIR) + "/" + testdir + "/");
+ }
+
+ QFxTestView *view = new QFxTestView(testfile, QLatin1String(QT_TEST_SOURCE_DIR) + "/" + testdir + RASTER_TESTDIR);
+ QVERIFY(view->runTest());
+}
+
+#include <QtTest/qtest_gui.h>
+
+int main(int argc, char *argv[])
+{
+ int newArgc = 1;
+ char **newArgv = new char*[argc];
+
+ newArgv[0] = argv[0];
+
+ QApplication app(newArgc, newArgv);
+
+ for(int ii = 1; ii < argc; ii++) {
+ if(QLatin1String(argv[ii]) == "-testdir" && (ii + 1) < argc) {
+ testdir = QLatin1String(argv[ii + 1]);
+ ii++;
+ } else {
+ newArgv[newArgc++] = argv[ii];
+ }
+ }
+
+ tst_visual tc;
+ int rv = QTest::qExec(&tc, newArgc, newArgv);
+
+ delete [] newArgv;
+ return rv;
+}
+
+#include "tst_visual.moc"
diff --git a/tests/auto/declarative/visual/visual.pro b/tests/auto/declarative/visual/visual.pro
new file mode 100644
index 0000000..203b691
--- /dev/null
+++ b/tests/auto/declarative/visual/visual.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_visual.cpp
+
+DEFINES += QT_TEST_SOURCE_DIR=\"\\\"$$PWD\\\"\"
diff --git a/tests/auto/declarative/visual/webview/autosize/data/opengl/image0.png b/tests/auto/declarative/visual/webview/autosize/data/opengl/image0.png
new file mode 100644
index 0000000..351a7b7
--- /dev/null
+++ b/tests/auto/declarative/visual/webview/autosize/data/opengl/image0.png
Binary files differ
diff --git a/tests/auto/declarative/visual/webview/autosize/data/opengl/manifest.xml b/tests/auto/declarative/visual/webview/autosize/data/opengl/manifest.xml
new file mode 100644
index 0000000..b784f42
--- /dev/null
+++ b/tests/auto/declarative/visual/webview/autosize/data/opengl/manifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestLog>
+ <TestFullFrame time="30" frameId="0"/>
+</TestLog>
diff --git a/tests/auto/declarative/visual/webview/autosize/test b/tests/auto/declarative/visual/webview/autosize/test
new file mode 100644
index 0000000..446d3f9
--- /dev/null
+++ b/tests/auto/declarative/visual/webview/autosize/test
@@ -0,0 +1 @@
+QTDIR/examples/declarative/webview/autosize.qml
diff --git a/tests/auto/dynamicobject/dynamicobject.pro b/tests/auto/dynamicobject/dynamicobject.pro
new file mode 100644
index 0000000..1b2a075
--- /dev/null
+++ b/tests/auto/dynamicobject/dynamicobject.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+SOURCES += tst_qobject.cpp qmetaobjectbuilder.cpp qdynamicmetaobject.cpp
+HEADERS += qmetaobjectbuilder.h qdynamicmetaobject.h
+
+QT = core
+
diff --git a/tests/auto/dynamicobject/qdynamicmetaobject.cpp b/tests/auto/dynamicobject/qdynamicmetaobject.cpp
new file mode 100644
index 0000000..b44555f
--- /dev/null
+++ b/tests/auto/dynamicobject/qdynamicmetaobject.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+****************************************************************************/
+
+#include <qcoreapplication.h>
+
+#include <qmetaobject.h>
+
+#include "qobject.h"
+#include "private/qobject_p.h"
+#include "qmetaobjectbuilder.h"
+#include "qdynamicmetaobject.h"
+
+class QDynamicMetaObjectData
+{
+public:
+ QDynamicMetaObjectData() : ref(1), baseMeta(0), meta(0) {}
+ ~QDynamicMetaObjectData() { qFree(meta); }
+
+ QAtomicInt ref;
+ QMetaObjectBuilder builder;
+ const QMetaObject *baseMeta;
+ QMetaObject *meta;
+};
+
+/*!
+ \class QDynamicMetaObject
+ \brief The QDynamicMetaObject class allows adding signals, slots and properties to
+ QObjects at runtime.
+
+ Any QObject derived class can be extended by creating a QDynamicMetaObject
+ based on the QObject's QMetaObject.
+
+ QObject::setDynamicMetaObject() is called to set the dynamic meta-object for
+ the QObject.
+
+ \sa QMetaObject
+*/
+
+/*!
+ Constructs a dynamic meta-object based on \a baseMetaObject.
+
+ QObject::setDynamicMetaObject() should be called to install it.
+*/
+QDynamicMetaObject::QDynamicMetaObject(const QMetaObject *baseMetaObject)
+{
+ data_ptr = new QDynamicMetaObjectData;
+ data_ptr->baseMeta = baseMetaObject;
+ data_ptr->builder.setSuperClass(data_ptr->baseMeta);
+ data_ptr->builder.setClassName(data_ptr->baseMeta->className());
+ updateMetaData();
+}
+
+/*!
+ Constructs a dynamic meta-object that is a copy of \a other.
+*/
+QDynamicMetaObject::QDynamicMetaObject(const QDynamicMetaObject &other)
+{
+ data_ptr = other.data_ptr;
+ data_ptr->ref.ref();
+}
+
+/*!
+ Destroys the dynamic meta-ovject.
+*/
+QDynamicMetaObject::~QDynamicMetaObject()
+{
+ if (!data_ptr->ref.deref())
+ delete data_ptr;
+}
+
+/*!
+ Copies the dynamic metadata from \a that. The static metadata must be identical,
+ i.e. the dynamic metadata is constructed for the same class.
+*/
+QDynamicMetaObject &QDynamicMetaObject::operator=(const QDynamicMetaObject &that)
+{
+ Q_ASSERT(data_ptr->baseMeta == that.data_ptr->baseMeta);
+ qAtomicAssign(data_ptr, that.data_ptr);
+ return *this;
+}
+
+/*!
+ \internal
+*/
+QDynamicMetaObject &QDynamicMetaObject::operator=(const QMetaObject &that)
+{
+ static_cast<QMetaObject*>(this)->d = that.d;
+ return *this;
+}
+
+/*!
+ \internal
+*/
+void QDynamicMetaObject::detach()
+{
+ if (data_ptr->ref == 1)
+ return;
+
+ //XXX copy builder faster.
+ QByteArray buf;
+ QDataStream ds(&buf, QIODevice::ReadWrite);
+ data_ptr->builder.serialize(ds);
+ if (!data_ptr->ref.deref())
+ delete data_ptr;
+ data_ptr = new QDynamicMetaObjectData;
+ QMap<QByteArray, const QMetaObject *> refs;
+ data_ptr->builder.deserialize(ds, refs);
+ updateMetaData();
+}
+
+/*!
+ Adds the signal with \a signature.
+*/
+void QDynamicMetaObject::addSignal(const char *signature)
+{
+ detach();
+ data_ptr->builder.addSignal(signature);
+ updateMetaData();
+}
+
+/*!
+ Adds the signal with \a signature and sets the \a parameterNames.
+*/
+void QDynamicMetaObject::addSignal(const char *signature, const QList<QByteArray> &parameterNames)
+{
+ detach();
+ QMetaMethodBuilder method = data_ptr->builder.addSignal(signature);
+ method.setParameterNames(parameterNames);
+ updateMetaData();
+}
+
+/*!
+ Adds the slot with \a signature.
+*/
+void QDynamicMetaObject::addSlot(const char *signature)
+{
+ detach();
+ data_ptr->builder.addSlot(signature);
+ updateMetaData();
+}
+
+
+/*!
+ Adds the slot with \a signature and sets the \a parameterNames.
+*/
+void QDynamicMetaObject::addSlot(const char *signature, const QList<QByteArray> &parameterNames)
+{
+ detach();
+ QMetaMethodBuilder method = data_ptr->builder.addSlot(signature);
+ method.setParameterNames(parameterNames);
+ updateMetaData();
+}
+
+/*!
+ Adds the property with \a name of \a type. If \a notifier specified it is
+ set as the change notifier for the property.
+*/
+void QDynamicMetaObject::addProperty(const char *name, const char *type, const char *notifier)
+{
+ int notifierId = -1;
+ if (notifier)
+ notifierId = data_ptr->builder.indexOfSignal(notifier);
+ data_ptr->builder.addProperty(name, type, notifierId);
+ updateMetaData();
+}
+
+/*!
+ Adds the property with \a name of \a type. If \a notifierId is specified it is
+ set as the change notifier for the property.
+*/
+void QDynamicMetaObject::addProperty(const char *name, const char *type, int notifierId)
+{
+ data_ptr->builder.addProperty(name, type, notifierId);
+ updateMetaData();
+}
+
+/*!
+ \reimp
+*/
+int QDynamicMetaObject::metaCall(QObject *object, QMetaObject::Call _c, int _id, void **_a)
+{
+ if (_c == QMetaObject::InvokeMetaMethod && _id >= data_ptr->baseMeta->methodCount()) {
+ QMetaMethod metaMethod = method(_id);
+ if (metaMethod.methodType() == QMetaMethod::Slot) {
+ if (metaMethod.parameterTypes().count() == 0) {
+ static QList<QVariant> noArgs;
+ callSlot(object, _id, noArgs);
+ } else {
+ QList<QVariant> args;
+ for (int i = 0; i < metaMethod.parameterTypes().count(); ++i) {
+ int typeId = QVariant::nameToType(metaMethod.parameterTypes().at(i));
+ args.append(QVariant(typeId, _a[i+1]));
+ }
+ callSlot(object, _id, args);
+ }
+ } else if (metaMethod.methodType() == QMetaMethod::Signal)
+ activate(object, _id, _a);
+ _id = -1;
+ } else if (_c == QMetaObject::ReadProperty && _id >= data_ptr->baseMeta->propertyCount()) {
+ *(reinterpret_cast<QVariant*>(_a[1])) = readProperty(object, _id);
+ _id = -1;
+ } else if (_c == QMetaObject::WriteProperty && _id >= data_ptr->baseMeta->propertyCount()) {
+ writeProperty(object, _id, *(reinterpret_cast<QVariant*>(_a[1])));
+ if (property(_id).hasNotifySignal())
+ activate(object, property(_id).notifySignalIndex(), 0);
+ _id = -1;
+ } else {
+ _id = object->qt_metacall(_c, _id, _a);
+ }
+
+ return _id;
+}
+
+/*!
+ The slot with \a id has been called for \a object. The parameters are available via \a args.
+*/
+void QDynamicMetaObject::callSlot(QObject *object, int id, const QList<QVariant> &args)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(id);
+ Q_UNUSED(args);
+}
+
+/*!
+ The \a value of property with \a id has changed for \a object.
+*/
+void QDynamicMetaObject::writeProperty(QObject *object, int id, const QVariant &value)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(id);
+ Q_UNUSED(value);
+}
+
+/*!
+ Return the value of the property with \a id belonging to \a object.
+*/
+QVariant QDynamicMetaObject::readProperty(QObject *object, int id) const
+{
+ Q_UNUSED(object);
+ Q_UNUSED(id);
+ return QVariant();
+}
+
+void QDynamicMetaObject::updateMetaData()
+{
+ qFree(data_ptr->meta);
+ data_ptr->meta = data_ptr->builder.toMetaObject();
+ *this = *data_ptr->meta;
+}
+
diff --git a/tests/auto/dynamicobject/qdynamicmetaobject.h b/tests/auto/dynamicobject/qdynamicmetaobject.h
new file mode 100644
index 0000000..747d118
--- /dev/null
+++ b/tests/auto/dynamicobject/qdynamicmetaobject.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+****************************************************************************/
+
+#ifndef _QDYNAMICMETAOBJECT_H_
+#define _QDYNAMICMETAOBJECT_H_
+
+#include <qmetaobject.h>
+#include <qobject.h>
+
+class QDynamicMetaObjectData;
+
+class QDynamicMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QDynamicMetaObject(const QMetaObject *baseMetaObject);
+ QDynamicMetaObject(const QDynamicMetaObject &other);
+ virtual ~QDynamicMetaObject();
+
+ QDynamicMetaObject &operator=(const QDynamicMetaObject &that);
+
+ void addSignal(const char *sigName);
+ void addSignal(const char *sigName, const QList<QByteArray> &parameterNames);
+ void addSlot(const char *slotName);
+ void addSlot(const char *slotName, const QList<QByteArray> &parameterNames);
+ void addProperty(const char *name, const char *type, const char *notifier);
+ void addProperty(const char *name, const char *type, int notifierId=-1);
+
+protected:
+ virtual int metaCall(QObject *object, QMetaObject::Call _c, int _id, void **_a);
+ virtual void callSlot(QObject *object, int id, const QList<QVariant> &args);
+ virtual void writeProperty(QObject *object, int id, const QVariant &value);
+ virtual QVariant readProperty(QObject *object, int id) const;
+
+private:
+ void detach();
+ void updateMetaData();
+ QDynamicMetaObject &operator=(const QMetaObject &that);
+
+private:
+ QDynamicMetaObjectData *data_ptr;
+};
+
+#endif
diff --git a/tests/auto/dynamicobject/qmetaobjectbuilder.cpp b/tests/auto/dynamicobject/qmetaobjectbuilder.cpp
new file mode 100644
index 0000000..3927f6a
--- /dev/null
+++ b/tests/auto/dynamicobject/qmetaobjectbuilder.cpp
@@ -0,0 +1,2347 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qmetaobjectbuilder.h"
+#include <QDebug>
+
+/*!
+ \class QMetaObjectBuilder
+ \brief The QMetaObjectBuilder class supports the building of QMetaObject objects at runtime.
+
+ See the QDynamicMetaObject class documentation for an example
+ of using this class.
+
+ \sa QDynamicMetaObject, QDynamicObject
+*/
+
+/*!
+ \enum QMetaObjectBuilder::AddMember
+ This enum defines which members of QMetaObject should be copied by QMetaObjectBuilder::addMetaObject()
+
+ \value ClassName Add the class name.
+ \value SuperClass Add the super class.
+ \value Methods Add methods that aren't signals or slots.
+ \value Signals Add signals.
+ \value Slots Add slots.
+ \value Constructors Add constructors.
+ \value Properties Add properties.
+ \value Enumerators Add enumerators.
+ \value ClassInfos Add items of class information.
+ \value RelatedMetaObjects Add related meta objects.
+ \value StaticMetacall Add the static metacall function.
+ \value PublicMethods Add public methods (ignored for signals).
+ \value ProtectedMethods Add protected methods (ignored for signals).
+ \value PrivateMethods All private methods (ignored for signals).
+ \value AllMembers Add all members.
+ \value AllPrimaryMembers Add everything except the class name, super class, and static metacall function.
+*/
+
+// copied from qmetaobject.cpp
+// do not touch without touching the moc as well
+enum PropertyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resettable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+// Override = 0x00000200,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000,
+ User = 0x00100000,
+ ResolveUser = 0x00200000,
+ Notify = 0x00400000
+};
+
+enum MethodFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ AccessMask = 0x03, //mask
+
+ MethodMethod = 0x00,
+ MethodSignal = 0x04,
+ MethodSlot = 0x08,
+ MethodConstructor = 0x0c,
+ MethodTypeMask = 0x0c,
+
+ MethodCompatibility = 0x10,
+ MethodCloned = 0x20,
+ MethodScriptable = 0x40
+};
+
+struct QMetaObjectPrivate
+{
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ int propertyCount, propertyData;
+ int enumeratorCount, enumeratorData;
+ int constructorCount, constructorData;
+};
+
+static inline const QMetaObjectPrivate *priv(const uint* data)
+{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
+// end of copied lines from qmetaobject.cpp
+
+class QMetaMethodBuilderPrivate
+{
+public:
+ QMetaMethodBuilderPrivate
+ (QMetaMethod::MethodType _methodType,
+ const QByteArray& _signature,
+ const QByteArray& _returnType = QByteArray(),
+ QMetaMethod::Access _access = QMetaMethod::Public)
+ : signature(QMetaObject::normalizedSignature(_signature.constData())),
+ returnType(QMetaObject::normalizedType(_returnType)),
+ attributes(((int)_access) | (((int)_methodType) << 2))
+ {
+ }
+
+ QByteArray signature;
+ QByteArray returnType;
+ QList<QByteArray> parameterNames;
+ QByteArray tag;
+ int attributes;
+
+ QMetaMethod::MethodType methodType() const
+ {
+ return (QMetaMethod::MethodType)((attributes & MethodTypeMask) >> 2);
+ }
+
+ QMetaMethod::Access access() const
+ {
+ return (QMetaMethod::Access)(attributes & AccessMask);
+ }
+
+ void setAccess(QMetaMethod::Access value)
+ {
+ attributes = ((attributes & ~AccessMask) | (int)value);
+ }
+};
+
+class QMetaPropertyBuilderPrivate
+{
+public:
+ QMetaPropertyBuilderPrivate
+ (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1)
+ : name(_name),
+ type(QMetaObject::normalizedType(_type.constData())),
+ flags(Readable | Writable), notifySignal(-1)
+ {
+ if (notifierIdx >= 0) {
+ flags |= Notify;
+ notifySignal = notifierIdx;
+ }
+ }
+
+ QByteArray name;
+ QByteArray type;
+ int flags;
+ int notifySignal;
+
+ bool flag(int f) const
+ {
+ return ((flags & f) != 0);
+ }
+
+ void setFlag(int f, bool value)
+ {
+ if (value)
+ flags |= f;
+ else
+ flags &= ~f;
+ }
+};
+
+class QMetaEnumBuilderPrivate
+{
+public:
+ QMetaEnumBuilderPrivate(const QByteArray& _name)
+ : name(_name), isFlag(false)
+ {
+ }
+
+ QByteArray name;
+ bool isFlag;
+ QList<QByteArray> keys;
+ QList<int> values;
+};
+
+class QMetaObjectBuilderPrivate
+{
+public:
+ QMetaObjectBuilderPrivate()
+ {
+ superClass = &QObject::staticMetaObject;
+ staticMetacallFunction = 0;
+ }
+
+ QByteArray className;
+ const QMetaObject *superClass;
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction;
+ QList<QMetaMethodBuilderPrivate> methods;
+ QList<QMetaMethodBuilderPrivate> constructors;
+ QList<QMetaPropertyBuilderPrivate> properties;
+ QList<QByteArray> classInfoNames;
+ QList<QByteArray> classInfoValues;
+ QList<QMetaEnumBuilderPrivate> enumerators;
+ QList<const QMetaObject *> relatedMetaObjects;
+};
+
+/*!
+ Constructs a new QMetaObjectBuilder.
+*/
+QMetaObjectBuilder::QMetaObjectBuilder()
+{
+ d = new QMetaObjectBuilderPrivate();
+}
+
+/*!
+ Constructs a new QMetaObjectBuilder which is a copy of the
+ meta object information in \a prototype. Note: the super class
+ contents for \a prototype are not copied, only the immediate
+ class that is defined by \a prototype.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+
+ \sa addMetaObject()
+*/
+QMetaObjectBuilder::QMetaObjectBuilder
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ d = new QMetaObjectBuilderPrivate();
+ addMetaObject(prototype, members);
+}
+
+/*!
+ Destroys this meta object builder.
+*/
+QMetaObjectBuilder::~QMetaObjectBuilder()
+{
+ delete d;
+}
+
+/*!
+ Returns the name of the class being constructed by this
+ meta object builder. The default value is an empty QByteArray.
+
+ \sa setClassName(), superClass()
+*/
+QByteArray QMetaObjectBuilder::className() const
+{
+ return d->className;
+}
+
+/*!
+ Sets the \a name of the class being constructed by this
+ meta object builder.
+
+ \sa className(), setSuperClass()
+*/
+void QMetaObjectBuilder::setClassName(const QByteArray& name)
+{
+ d->className = name;
+}
+
+/*!
+ Returns the superclass meta object of the class being constructed
+ by this meta object builder. The default value is the meta object
+ for QObject.
+
+ \sa setSuperClass(), className()
+*/
+const QMetaObject *QMetaObjectBuilder::superClass() const
+{
+ return d->superClass;
+}
+
+/*!
+ Sets the superclass meta object of the class being constructed
+ by this meta object builder to \a meta. The \a meta parameter
+ must not be null.
+
+ \sa superClass(), setClassName()
+*/
+void QMetaObjectBuilder::setSuperClass(const QMetaObject *meta)
+{
+ Q_ASSERT(meta);
+ d->superClass = meta;
+}
+
+/*!
+ Returns the number of methods in this class, excluding the number
+ of methods in the base class. These include signals and slots
+ as well as normal member functions.
+
+ \sa addMethod(), method(), removeMethod(), indexOfMethod()
+*/
+int QMetaObjectBuilder::methodCount() const
+{
+ return d->methods.size();
+}
+
+/*!
+ Returns the number of constructors in this class.
+
+ \sa addConstructor(), constructor(), removeConstructor(), indexOfConstructor()
+*/
+int QMetaObjectBuilder::constructorCount() const
+{
+ return d->constructors.size();
+}
+
+/*!
+ Returns the number of properties in this class, excluding the number
+ of properties in the base class.
+
+ \sa addProperty(), property(), removeProperty(), indexOfProperty()
+*/
+int QMetaObjectBuilder::propertyCount() const
+{
+ return d->properties.size();
+}
+
+/*!
+ Returns the number of enumerators in this class, excluding the
+ number of enumerators in the base class.
+
+ \sa addEnumerator(), enumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+int QMetaObjectBuilder::enumeratorCount() const
+{
+ return d->enumerators.size();
+}
+
+/*!
+ Returns the number of items of class information in this class,
+ exclusing the number of items of class information in the base class.
+
+ \sa addClassInfo(), classInfoName(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+int QMetaObjectBuilder::classInfoCount() const
+{
+ return d->classInfoNames.size();
+}
+
+/*!
+ Returns the number of related meta objects that are associated
+ with this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa addRelatedMetaObject(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+int QMetaObjectBuilder::relatedMetaObjectCount() const
+{
+ return d->relatedMetaObjects.size();
+}
+
+/*!
+ Adds a new public method to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the method. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Method, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class with the specified
+ \a signature and \a returnType. Returns an object that can be
+ used to adjust the other attributes of the method. The \a signature
+ and \a returnType will be normalized before they are added to
+ the class. If \a returnType is empty, then it indicates that
+ the method has \c{void} as its return type.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod
+ (const QByteArray& signature, const QByteArray& returnType)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Method, signature, returnType));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class that has the same information as
+ \a prototype. This is used to clone the methods of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the method.
+
+ This function will detect if \a prototype is an ordinary method,
+ signal, slot, or constructor and act accordingly.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
+{
+ QMetaMethodBuilder method;
+ if (prototype.methodType() == QMetaMethod::Method)
+ method = addMethod(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Signal)
+ method = addSignal(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Slot)
+ method = addSlot(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Constructor)
+ method = addConstructor(prototype.signature());
+ method.setReturnType(prototype.typeName());
+ method.setParameterNames(prototype.parameterNames());
+ method.setTag(prototype.tag());
+ method.setAccess(prototype.access());
+ method.setAttributes(prototype.attributes());
+ return method;
+}
+
+/*!
+ Adds a new public slot to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the slot. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSignal(), indexOfSlot()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Slot, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new signal to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the signal. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSlot(), indexOfSignal()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Signal, signature, QByteArray(), QMetaMethod::Protected));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new constructor to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the constructor. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signature)
+{
+ int index = d->constructors.size();
+ d->constructors.append(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature));
+ return QMetaMethodBuilder(this, -(index + 1));
+}
+
+/*!
+ Adds a new constructor to this class that has the same information as
+ \a prototype. This is used to clone the constructors of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the constructor.
+
+ This function requires that \a prototype be a constructor.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototype)
+{
+ Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
+ QMetaMethodBuilder ctor = addConstructor(prototype.signature());
+ ctor.setReturnType(prototype.typeName());
+ ctor.setParameterNames(prototype.parameterNames());
+ ctor.setTag(prototype.tag());
+ ctor.setAccess(prototype.access());
+ ctor.setAttributes(prototype.attributes());
+ return ctor;
+}
+
+/*!
+ Adds a new readable/writable property to this class with the specified
+ \a name and \a type. Returns an object that can be used to adjust
+ the other attributes of the property. The \a type will be
+ normalized before it is added to the class.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty
+ (const QByteArray& name, const QByteArray& type, int notifierId)
+{
+ int index = d->properties.size();
+ d->properties.append(QMetaPropertyBuilderPrivate(name, type, notifierId));
+ return QMetaPropertyBuilder(this, index);
+}
+
+/*!
+ Adds a new property to this class that has the same information as
+ \a prototype. This is used to clone the properties of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the property.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& prototype)
+{
+ QMetaPropertyBuilder property = addProperty(prototype.name(), prototype.typeName());
+ property.setReadable(prototype.isReadable());
+ property.setWritable(prototype.isWritable());
+ property.setResettable(prototype.isResettable());
+ property.setDesignable(prototype.isDesignable());
+ property.setScriptable(prototype.isScriptable());
+ property.setStored(prototype.isStored());
+ property.setEditable(prototype.isEditable());
+ property.setUser(prototype.isUser());
+ property.setStdCppSet(prototype.hasStdCppSet());
+ property.setEnumOrFlag(prototype.isEnumType());
+ if (prototype.hasNotifySignal()) {
+ // Find an existing method for the notify signal, or add a new one.
+ QMetaMethod method = prototype.notifySignal();
+ int index = indexOfMethod(method.signature());
+ if (index == -1)
+ index = addMethod(method).index();
+ d->properties[property._index].notifySignal = index;
+ d->properties[property._index].setFlag(Notify, true);
+ }
+ return property;
+}
+
+/*!
+ Adds a new enumerator to this class with the specified
+ \a name. Returns an object that can be used to adjust
+ the other attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator(),
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
+{
+ int index = d->enumerators.size();
+ d->enumerators.append(QMetaEnumBuilderPrivate(name));
+ return QMetaEnumBuilder(this, index);
+}
+
+/*!
+ Adds a new enumerator to this class that has the same information as
+ \a prototype. This is used to clone the enumerators of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator(),
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
+{
+ QMetaEnumBuilder en = addEnumerator(prototype.name());
+ en.setIsFlag(prototype.isFlag());
+ int count = prototype.keyCount();
+ for (int index = 0; index < count; ++index)
+ en.addKey(prototype.key(index), prototype.value(index));
+ return en;
+}
+
+/*!
+ Adds \a name and \a value as an item of class information to this class.
+ Returns the index of the new item of class information.
+
+ \sa classInfoCount(), classInfoName(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+int QMetaObjectBuilder::addClassInfo(const QByteArray& name, const QByteArray& value)
+{
+ int index = d->classInfoNames.size();
+ d->classInfoNames += name;
+ d->classInfoValues += value;
+ return index;
+}
+
+/*!
+ Adds \a meta to this class as a related meta object. Returns
+ the index of the new related meta object entry.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+int QMetaObjectBuilder::addRelatedMetaObject(const QMetaObject *meta)
+{
+ Q_ASSERT(meta);
+ int index = d->relatedMetaObjects.size();
+ d->relatedMetaObjects.append(meta);
+ return index;
+}
+
+/*!
+ Adds the contents of \a prototype to this meta object builder.
+ This function is useful for cloning the contents of an existing QMetaObject.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+*/
+void QMetaObjectBuilder::addMetaObject
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ Q_ASSERT(prototype);
+ int index;
+
+ if ((members & ClassName) != 0)
+ d->className = prototype->className();
+
+ if ((members & SuperClass) != 0)
+ d->superClass = prototype->superClass();
+
+ if ((members & (Methods | Signals | Slots)) != 0) {
+ for (index = prototype->methodOffset(); index < prototype->methodCount(); ++index) {
+ QMetaMethod method = prototype->method(index);
+ if (method.methodType() != QMetaMethod::Signal) {
+ if (method.access() == QMetaMethod::Public && (members & PublicMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Private && (members & PrivateMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Protected && (members & ProtectedMethods) == 0)
+ continue;
+ }
+ if (method.methodType() == QMetaMethod::Method && (members & Methods) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Signal &&
+ (members & Signals) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Slot &&
+ (members & Slots) != 0) {
+ addMethod(method);
+ }
+ }
+ }
+
+ if ((members & Constructors) != 0) {
+ for (index = 0; index < prototype->constructorCount(); ++index)
+ addConstructor(prototype->constructor(index));
+ }
+
+ if ((members & Properties) != 0) {
+ for (index = prototype->propertyOffset(); index < prototype->propertyCount(); ++index)
+ addProperty(prototype->property(index));
+ }
+
+ if ((members & Enumerators) != 0) {
+ for (index = prototype->enumeratorOffset(); index < prototype->enumeratorCount(); ++index)
+ addEnumerator(prototype->enumerator(index));
+ }
+
+ if ((members & ClassInfos) != 0) {
+ for (index = prototype->classInfoOffset(); index < prototype->classInfoCount(); ++index) {
+ QMetaClassInfo ci = prototype->classInfo(index);
+ addClassInfo(ci.name(), ci.value());
+ }
+ }
+
+ if ((members & RelatedMetaObjects) != 0) {
+ const QMetaObject **objects;
+ if (priv(prototype->d.data)->revision < 2) {
+ objects = (const QMetaObject **)(prototype->d.extradata);
+ } else {
+ const QMetaObjectExtraData *extra = (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra)
+ objects = extra->objects;
+ else
+ objects = 0;
+ }
+ if (objects) {
+ while (*objects != 0) {
+ addRelatedMetaObject(*objects);
+ ++objects;
+ }
+ }
+ }
+
+ if ((members & StaticMetacall) != 0) {
+ if (priv(prototype->d.data)->revision >= 2) {
+ const QMetaObjectExtraData *extra =
+ (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra && extra->static_metacall)
+ setStaticMetacallFunction(extra->static_metacall);
+ }
+ }
+}
+
+/*!
+ Returns the method at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::method(int index) const
+{
+ if (index >= 0 && index < d->methods.size())
+ return QMetaMethodBuilder(this, index);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the constructor at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::constructor(int index) const
+{
+ if (index >= 0 && index < d->constructors.size())
+ return QMetaMethodBuilder(this, -(index + 1));
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the property at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::property(int index) const
+{
+ if (index >= 0 && index < d->properties.size())
+ return QMetaPropertyBuilder(this, index);
+ else
+ return QMetaPropertyBuilder();
+}
+
+/*!
+ Returns the enumerator at \a index in this class.
+
+ \sa enumeratorCount(), addEnumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::enumerator(int index) const
+{
+ if (index >= 0 && index < d->enumerators.size())
+ return QMetaEnumBuilder(this, index);
+ else
+ return QMetaEnumBuilder();
+}
+
+/*!
+ Returns the related meta object at \a index in this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+const QMetaObject *QMetaObjectBuilder::relatedMetaObject(int index) const
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+ return d->relatedMetaObjects[index];
+ else
+ return 0;
+}
+
+/*!
+ Returns the name of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoName(int index) const
+{
+ if (index >= 0 && index < d->classInfoNames.size())
+ return d->classInfoNames[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoValue(int index) const
+{
+ if (index >= 0 && index < d->classInfoValues.size())
+ return d->classInfoValues[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Removes the method at \a index from this class. The indices of
+ all following methods will be adjusted downwards by 1. If the
+ method is registered as a notify signal on a property, then the
+ notify signal will be removed from the property.
+
+ \sa methodCount(), addMethod(), method(), indexOfMethod()
+*/
+void QMetaObjectBuilder::removeMethod(int index)
+{
+ if (index >= 0 && index < d->methods.size()) {
+ d->methods.removeAt(index);
+ for (int prop = 0; prop < d->properties.size(); ++prop) {
+ // Adjust the indices of property notify signal references.
+ if (d->properties[prop].notifySignal == index)
+ d->properties[prop].notifySignal = -1;
+ else if (d->properties[prop].notifySignal > index)
+ (d->properties[prop].notifySignal)--;
+ }
+ }
+}
+
+/*!
+ Removes the constructor at \a index from this class. The indices of
+ all following constructors will be adjusted downwards by 1.
+
+ \sa constructorCount(), addConstructor(), constructor()
+ \sa indexOfConstructor()
+*/
+void QMetaObjectBuilder::removeConstructor(int index)
+{
+ if (index >= 0 && index < d->constructors.size())
+ d->constructors.removeAt(index);
+}
+
+/*!
+ Removes the property at \a index from this class. The indices of
+ all following properties will be adjusted downwards by 1.
+
+ \sa propertyCount(), addProperty(), property(), indexOfProperty()
+*/
+void QMetaObjectBuilder::removeProperty(int index)
+{
+ if (index >= 0 && index < d->properties.size())
+ d->properties.removeAt(index);
+}
+
+/*!
+ Removes the enumerator at \a index from this class. The indices of
+ all following enumerators will be adjusted downwards by 1.
+
+ \sa enumertorCount(), addEnumerator(), enumerator()
+ \sa indexOfEnumerator()
+*/
+void QMetaObjectBuilder::removeEnumerator(int index)
+{
+ if (index >= 0 && index < d->enumerators.size())
+ d->enumerators.removeAt(index);
+}
+
+/*!
+ Removes the item of class information at \a index from this class.
+ The indices of all following items will be adjusted downwards by 1.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName(), classInfoValue()
+ \sa indexOfClassInfo()
+*/
+void QMetaObjectBuilder::removeClassInfo(int index)
+{
+ if (index >= 0 && index < d->classInfoNames.size()) {
+ d->classInfoNames.removeAt(index);
+ d->classInfoValues.removeAt(index);
+ }
+}
+
+/*!
+ Removes the related meta object at \a index from this class.
+ The indices of all following related meta objects will be adjusted
+ downwards by 1.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa relatedMetaObject()
+*/
+void QMetaObjectBuilder::removeRelatedMetaObject(int index)
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+ d->relatedMetaObjects.removeAt(index);
+}
+
+/*!
+ Finds a method with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa method(), methodCount(), addMethod(), removeMethod()
+*/
+int QMetaObjectBuilder::indexOfMethod(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a signal with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSlot()
+*/
+int QMetaObjectBuilder::indexOfSignal(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Signal)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a slot with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSignal()
+*/
+int QMetaObjectBuilder::indexOfSlot(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Slot)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a constructor with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa constructor(), constructorCount(), addConstructor(), removeConstructor()
+*/
+int QMetaObjectBuilder::indexOfConstructor(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->constructors.size(); ++index) {
+ if (sig == d->constructors[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a property with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa property(), propertyCount(), addProperty(), removeProperty()
+*/
+int QMetaObjectBuilder::indexOfProperty(const QByteArray& name)
+{
+ for (int index = 0; index < d->properties.size(); ++index) {
+ if (name == d->properties[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an enumerator with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa enumertor(), enumeratorCount(), addEnumerator(), removeEnumerator()
+*/
+int QMetaObjectBuilder::indexOfEnumerator(const QByteArray& name)
+{
+ for (int index = 0; index < d->enumerators.size(); ++index) {
+ if (name == d->enumerators[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an item of class information with the specified \a name and
+ returns its index; otherwise returns -1.
+
+ \sa classInfoName(), classInfoValue(), classInfoCount(), addClassInfo()
+ \sa removeClassInfo()
+*/
+int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
+{
+ for (int index = 0; index < d->classInfoNames.size(); ++index) {
+ if (name == d->classInfoNames[index])
+ return index;
+ }
+ return -1;
+}
+
+// Align on a specific type boundary.
+#define ALIGN(size,type) \
+ (size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
+
+// Build a string into a QMetaObject representation. Returns the
+// position in the string table where the string was placed.
+static int buildString
+ (char *buf, char *str, int *offset, const QByteArray& value, int empty)
+{
+ if (value.size() == 0 && empty >= 0)
+ return empty;
+ if (buf) {
+ memcpy(str + *offset, value.constData(), value.size());
+ str[*offset + value.size()] = '\0';
+ }
+ int posn = *offset;
+ *offset += value.size() + 1;
+ return posn;
+}
+
+// Build the parameter array string for a method.
+static QByteArray buildParameterNames
+ (const QByteArray& signature, const QList<QByteArray>& parameterNames)
+{
+ // If the parameter name list is specified, then concatenate them.
+ if (!parameterNames.isEmpty()) {
+ QByteArray names;
+ bool first = true;
+ foreach (QByteArray name, parameterNames) {
+ if (first)
+ first = false;
+ else
+ names += (char)',';
+ names += name;
+ }
+ return names;
+ }
+
+ // Count commas in the signature, excluding those inside template arguments.
+ int index = signature.indexOf('(');
+ if (index < 0)
+ return QByteArray();
+ ++index;
+ if (index >= signature.size())
+ return QByteArray();
+ if (signature[index] == ')')
+ return QByteArray();
+ int count = 1;
+ int brackets = 0;
+ while (index < signature.size() && signature[index] != ',') {
+ char ch = signature[index++];
+ if (ch == '<')
+ ++brackets;
+ else if (ch == '>')
+ --brackets;
+ else if (ch == ',' && brackets <= 0)
+ ++count;
+ }
+ return QByteArray(count - 1, ',');
+}
+
+// Build a QMetaObject in "buf" based on the information in "d".
+// If "buf" is null, then return the number of bytes needed to
+// build the QMetaObject.
+static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf)
+{
+ int size = 0;
+ int dataIndex;
+ int enumIndex;
+ int index;
+ bool hasNotifySignals = false;
+
+ // Create the main QMetaObject structure at the start of the buffer.
+ QMetaObject *meta = reinterpret_cast<QMetaObject *>(buf);
+ size += sizeof(QMetaObject);
+ ALIGN(size, int);
+ if (buf) {
+ meta->d.superdata = d->superClass;
+ meta->d.extradata = 0;
+ }
+
+ // Populate the QMetaObjectPrivate structure.
+ QMetaObjectPrivate *pmeta
+ = reinterpret_cast<QMetaObjectPrivate *>(buf + size);
+ dataIndex = 12; // Number of fields in the QMetaObjectPrivate.
+ for (index = 0; index < d->properties.size(); ++index) {
+ if (d->properties[index].notifySignal != -1) {
+ hasNotifySignals = true;
+ break;
+ }
+ }
+ if (buf) {
+ pmeta->revision = 2;
+ pmeta->className = 0; // Class name is always the first string.
+
+ pmeta->classInfoCount = d->classInfoNames.size();
+ pmeta->classInfoData = dataIndex;
+ dataIndex += 2 * d->classInfoNames.size();
+
+ pmeta->methodCount = d->methods.size();
+ pmeta->methodData = dataIndex;
+ dataIndex += 5 * d->methods.size();
+
+ pmeta->propertyCount = d->properties.size();
+ pmeta->propertyData = dataIndex;
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+
+ pmeta->enumeratorCount = d->enumerators.size();
+ pmeta->enumeratorData = dataIndex;
+ dataIndex += 4 * d->enumerators.size();
+
+ pmeta->constructorCount = d->constructors.size();
+ pmeta->constructorData = dataIndex;
+ dataIndex += 5 * d->constructors.size();
+ } else {
+ dataIndex += 2 * d->classInfoNames.size();
+ dataIndex += 5 * d->methods.size();
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+ dataIndex += 4 * d->enumerators.size();
+ dataIndex += 5 * d->constructors.size();
+ }
+
+ // Allocate space for the enumerator key names and values.
+ enumIndex = dataIndex;
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ dataIndex += 2 * enumerator->keys.size();
+ }
+
+ // Zero terminator at the end of the data offset table.
+ ++dataIndex;
+
+ // Find the start of the data and string tables.
+ int *data = reinterpret_cast<int *>(pmeta);
+ size += dataIndex * sizeof(int);
+ char *str = reinterpret_cast<char *>(buf + size);
+ if (buf) {
+ meta->d.stringdata = str;
+ meta->d.data = reinterpret_cast<uint *>(data);
+ }
+
+ // Reset the current data position to just past the QMetaObjectPrivate.
+ dataIndex = 12;
+
+ // Add the class name to the string table.
+ int offset = 0;
+ buildString(buf, str, &offset, d->className, -1);
+
+ // Add a common empty string, which is used to indicate "void"
+ // method returns, empty tag strings, etc.
+ int empty = buildString(buf, str, &offset, QByteArray(), -1);
+
+ // Output the class infos,
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ int name = buildString(buf, str, &offset, d->classInfoNames[index], empty);
+ int value = buildString(buf, str, &offset, d->classInfoValues[index], empty);
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = value;
+ }
+ dataIndex += 2;
+ }
+
+ // Output the methods in the class.
+ for (index = 0; index < d->methods.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // Output the properties in the class.
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ int name = buildString(buf, str, &offset, prop->name, empty);
+ int type = buildString(buf, str, &offset, prop->type, empty);
+ int flags = prop->flags;
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = type;
+ data[dataIndex + 2] = flags;
+ }
+ dataIndex += 3;
+ }
+ if (hasNotifySignals) {
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ if (buf) {
+ if (prop->notifySignal != -1)
+ data[dataIndex] = prop->notifySignal;
+ else
+ data[dataIndex] = 0;
+ }
+ ++dataIndex;
+ }
+ }
+
+ // Output the enumerators in the class.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ int name = buildString(buf, str, &offset, enumerator->name, empty);
+ int isFlag = (int)(enumerator->isFlag);
+ int count = enumerator->keys.size();
+ int enumOffset = enumIndex;
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = isFlag;
+ data[dataIndex + 2] = count;
+ data[dataIndex + 3] = enumOffset;
+ }
+ for (int key = 0; key < count; ++key) {
+ int keyIndex = buildString(buf, str, &offset, enumerator->keys[key], empty);
+ if (buf) {
+ data[enumOffset++] = keyIndex;
+ data[enumOffset++] = enumerator->values[key];
+ }
+ }
+ dataIndex += 4;
+ enumIndex += 2 * count;
+ }
+
+ // Output the constructors in the class.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // One more empty string to act as a terminator.
+ buildString(buf, str, &offset, QByteArray(), -1);
+ size += offset;
+
+ // Output the zero terminator in the data array.
+ if (buf)
+ data[enumIndex] = 0;
+
+ // Create the extradata block if we need one.
+ if (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction) {
+ ALIGN(size, QMetaObject **);
+ ALIGN(size, QMetaObjectBuilder::StaticMetacallFunction);
+ QMetaObjectExtraData *extra =
+ reinterpret_cast<QMetaObjectExtraData *>(buf + size);
+ size += sizeof(QMetaObjectExtraData);
+ ALIGN(size, QMetaObject *);
+ const QMetaObject **objects =
+ reinterpret_cast<const QMetaObject **>(buf + size);
+ if (buf) {
+ if (d->relatedMetaObjects.size() > 0) {
+ extra->objects = objects;
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index)
+ objects[index] = d->relatedMetaObjects[index];
+ objects[index] = 0;
+ } else {
+ extra->objects = 0;
+ }
+ extra->static_metacall = d->staticMetacallFunction;
+ meta->d.extradata = reinterpret_cast<void *>(extra);
+ }
+ if (d->relatedMetaObjects.size() > 0)
+ size += sizeof(QMetaObject *) * (d->relatedMetaObjects.size() + 1);
+ }
+
+ // Align the final size and return it.
+ ALIGN(size, void *);
+ return size;
+}
+
+/*!
+ Converts this meta object builder into a concrete QMetaObject.
+ The return value should be deallocated using qFree() once it
+ is no longer needed.
+
+ The returned meta object is a snapshot of the state of the
+ QMetaObjectBuilder. Any further modifications to the QMetaObjectBuilder
+ will not be reflected in previous meta objects returned by
+ this method.
+*/
+QMetaObject *QMetaObjectBuilder::toMetaObject() const
+{
+ int size = buildMetaObject(d, 0);
+ char *buf = reinterpret_cast<char *>(qMalloc(size));
+ buildMetaObject(d, buf);
+ return reinterpret_cast<QMetaObject *>(buf);
+}
+
+/*!
+ \typedef QMetaObjectBuilder::StaticMetacallFunction
+
+ Typedef for static metacall functions. The three parameters are
+ the call type value, the constructor index, and the
+ array of parameters.
+*/
+
+/*!
+ Returns the static metacall function to use to construct objects
+ of this class. The default value is null.
+
+ \sa setStaticMetacallFunction()
+*/
+QMetaObjectBuilder::StaticMetacallFunction QMetaObjectBuilder::staticMetacallFunction() const
+{
+ return d->staticMetacallFunction;
+}
+
+/*!
+ Sets the static metacall function to use to construct objects
+ of this class to \a value. The default value is null.
+
+ \sa staticMetacallFunction()
+*/
+void QMetaObjectBuilder::setStaticMetacallFunction
+ (QMetaObjectBuilder::StaticMetacallFunction value)
+{
+ d->staticMetacallFunction = value;
+}
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ Serializes the contents of the meta object builder onto \a stream.
+
+ \sa deserialize()
+*/
+void QMetaObjectBuilder::serialize(QDataStream& stream) const
+{
+ int index;
+
+ // Write the class and super class names.
+ stream << d->className;
+ if (d->superClass)
+ stream << QByteArray(d->superClass->className());
+ else
+ stream << QByteArray();
+
+ // Write the counts for each type of class member.
+ stream << d->classInfoNames.size();
+ stream << d->methods.size();
+ stream << d->properties.size();
+ stream << d->enumerators.size();
+ stream << d->constructors.size();
+ stream << d->relatedMetaObjects.size();
+
+ // Write the items of class information.
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ stream << d->classInfoNames[index];
+ stream << d->classInfoValues[index];
+ }
+
+ // Write the methods.
+ for (index = 0; index < d->methods.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the properties.
+ for (index = 0; index < d->properties.size(); ++index) {
+ const QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream << property->name;
+ stream << property->type;
+ stream << property->flags;
+ stream << property->notifySignal;
+ }
+
+ // Write the enumerators.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ const QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream << enumerator->name;
+ stream << enumerator->isFlag;
+ stream << enumerator->keys;
+ stream << enumerator->values;
+ }
+
+ // Write the constructors.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the related meta objects.
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index) {
+ const QMetaObject *meta = d->relatedMetaObjects[index];
+ stream << QByteArray(meta->className());
+ }
+
+ // Add an extra empty QByteArray for additional data in future versions.
+ // This should help maintain backwards compatibility, allowing older
+ // versions to read newer data.
+ stream << QByteArray();
+}
+
+// Resolve a class name using the name reference map.
+static const QMetaObject *resolveClassName
+ (const QMap<QByteArray, const QMetaObject *>& references,
+ const QByteArray& name)
+{
+ if (name == QByteArray("QObject"))
+ return &QObject::staticMetaObject;
+ else
+ return references.value(name, 0);
+}
+
+/*!
+ Deserializes a meta object builder from \a stream into
+ this meta object builder.
+
+ The \a references parameter specifies a mapping from class names
+ to QMetaObject instances for resolving the super class name and
+ related meta objects in the object that is deserialized.
+ The meta object for QObject is implicitly added to \a references
+ and does not need to be supplied.
+
+ The QDataStream::status() value on \a stream will be set to
+ QDataStream::ReadCorruptData if the input data is corrupt.
+ The status will be set to QDataStream::ReadPastEnd if the
+ input was exhausted before the full meta object was read.
+
+ \sa serialize()
+*/
+void QMetaObjectBuilder::deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references)
+{
+ QByteArray name;
+ const QMetaObject *cl;
+ int index;
+
+ // Clear all members in the builder to their default states.
+ d->className.clear();
+ d->superClass = &QObject::staticMetaObject;
+ d->classInfoNames.clear();
+ d->classInfoValues.clear();
+ d->methods.clear();
+ d->properties.clear();
+ d->enumerators.clear();
+ d->constructors.clear();
+ d->relatedMetaObjects.clear();
+ d->staticMetacallFunction = 0;
+
+ // Read the class and super class names.
+ stream >> d->className;
+ stream >> name;
+ if (name.isEmpty()) {
+ d->superClass = 0;
+ } else if ((cl = resolveClassName(references, name)) != 0) {
+ d->superClass = cl;
+ } else {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the counts for each type of class member.
+ int classInfoCount, methodCount, propertyCount;
+ int enumeratorCount, constructorCount, relatedMetaObjectCount;
+ stream >> classInfoCount;
+ stream >> methodCount;
+ stream >> propertyCount;
+ stream >> enumeratorCount;
+ stream >> constructorCount;
+ stream >> relatedMetaObjectCount;
+ if (classInfoCount < 0 || methodCount < 0 ||
+ propertyCount < 0 || enumeratorCount < 0 ||
+ constructorCount < 0 || relatedMetaObjectCount < 0) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the items of class information.
+ for (index = 0; index < classInfoCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray value;
+ stream >> name;
+ stream >> value;
+ addClassInfo(name, value);
+ }
+
+ // Read the member methods.
+ for (index = 0; index < methodCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addMethod(name);
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() == QMetaMethod::Constructor) {
+ // Cannot add a constructor in this set of methods.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the properties.
+ for (index = 0; index < propertyCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray type;
+ stream >> name;
+ stream >> type;
+ addProperty(name, type);
+ QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream >> property->flags;
+ stream >> property->notifySignal;
+ if (property->notifySignal < -1 ||
+ property->notifySignal >= d->methods.size()) {
+ // Notify signal method index is out of range.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ if (property->notifySignal >= 0 &&
+ d->methods[property->notifySignal].methodType() != QMetaMethod::Signal) {
+ // Notify signal method index does not refer to a signal.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the enumerators.
+ for (index = 0; index < enumeratorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addEnumerator(name);
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream >> enumerator->isFlag;
+ stream >> enumerator->keys;
+ stream >> enumerator->values;
+ if (enumerator->keys.size() != enumerator->values.size()) {
+ // Mismatch between number of keys and number of values.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the constructor methods.
+ for (index = 0; index < constructorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addConstructor(name);
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() != QMetaMethod::Constructor) {
+ // The type must be Constructor.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the related meta objects.
+ for (index = 0; index < relatedMetaObjectCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ cl = resolveClassName(references, name);
+ if (!cl) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ addRelatedMetaObject(cl);
+ }
+
+ // Read the extra data block, which is reserved for future use.
+ stream >> name;
+}
+
+#endif // !QT_NO_DATASTREAM
+
+/*!
+ \class QMetaMethodBuilder
+ \brief The QMetaMethodBuilder class enables modifications to a method definition on a meta object builder.
+*/
+
+QMetaMethodBuilderPrivate *QMetaMethodBuilder::d_func() const
+{
+ // Positive indices indicate methods, negative indices indicate constructors.
+ if (_mobj && _index >= 0 && _index < _mobj->d->methods.size())
+ return &(_mobj->d->methods[_index]);
+ else if (_mobj && -_index >= 1 && -_index <= _mobj->d->constructors.size())
+ return &(_mobj->d->constructors[(-_index) - 1]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaMethodBuilder::QMetaMethodBuilder()
+ \internal
+*/
+
+/*!
+ Returns the index of this method within its QMetaObjectBuilder.
+*/
+int QMetaMethodBuilder::index() const
+{
+ if (_index >= 0)
+ return _index; // Method, signal, or slot
+ else
+ return (-_index) - 1; // Constructor
+}
+
+/*!
+ Returns the type of this method (signal, slot, method, or constructor).
+*/
+QMetaMethod::MethodType QMetaMethodBuilder::methodType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->methodType();
+ else
+ return QMetaMethod::Method;
+}
+
+/*!
+ Returns the signature of this method.
+
+ \sa parameterNames(), returnType()
+*/
+QByteArray QMetaMethodBuilder::signature() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->signature;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the return type for this method; empty if the method's
+ return type is \c{void}.
+
+ \sa setReturnType(), signature()
+*/
+QByteArray QMetaMethodBuilder::returnType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->returnType;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the return type for this method to \a value. If \a value
+ is empty, then the method's return type is \c{void}. The \a value
+ will be normalized before it is added to the method.
+
+ \sa returnType(), signature()
+*/
+void QMetaMethodBuilder::setReturnType(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->returnType = QMetaObject::normalizedType(value);
+}
+
+/*!
+ Returns the list of parameter names for this method.
+
+ \sa setParameterNames()
+*/
+QList<QByteArray> QMetaMethodBuilder::parameterNames() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->parameterNames;
+ else
+ return QList<QByteArray>();
+}
+
+/*!
+ Sets the list of parameter names for this method to \a value.
+
+ \sa parameterNames()
+*/
+void QMetaMethodBuilder::setParameterNames(const QList<QByteArray>& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->parameterNames = value;
+}
+
+/*!
+ Returns the tag associated with this method.
+
+ \sa setTag()
+*/
+QByteArray QMetaMethodBuilder::tag() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->tag;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the tag associated with this method to \a value.
+
+ \sa setTag()
+*/
+void QMetaMethodBuilder::setTag(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->tag = value;
+}
+
+/*!
+ Returns the access specification of this method (private, protected,
+ or public). The default value is QMetaMethod::Public for methods,
+ slots, and constructors. The default value is QMetaMethod::Protected
+ for signals.
+
+ \sa setAccess()
+*/
+QMetaMethod::Access QMetaMethodBuilder::access() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->access();
+ else
+ return QMetaMethod::Public;
+}
+
+/*!
+ Sets the access specification of this method (private, protected,
+ or public) to \a value. If the method is a signal, this function
+ will be ignored.
+
+ \sa access()
+*/
+void QMetaMethodBuilder::setAccess(QMetaMethod::Access value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d && d->methodType() != QMetaMethod::Signal)
+ d->setAccess(value);
+}
+
+/*!
+ Returns the additional attributes for this method.
+
+ \sa setAttributes()
+*/
+int QMetaMethodBuilder::attributes() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return (d->attributes >> 4);
+ else
+ return 0;
+}
+
+/*!
+ Sets the additional attributes for this method to \a value.
+
+ \sa attributes()
+*/
+void QMetaMethodBuilder::setAttributes(int value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->attributes = ((d->attributes & 0x0f) | (value << 4));
+}
+
+/*!
+ \class QMetaPropertyBuilder
+ \brief The QMetaPropertyBuilder class enables modifications to a property definition on a meta object builder.
+*/
+
+QMetaPropertyBuilderPrivate *QMetaPropertyBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->properties.size())
+ return &(_mobj->d->properties[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaPropertyBuilder::QMetaPropertyBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaPropertyBuilder::index() const
+
+ Returns the index of this property within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name associated with this property.
+
+ \sa type()
+*/
+QByteArray QMetaPropertyBuilder::name() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the type associated with this property.
+
+ \sa name()
+*/
+QByteArray QMetaPropertyBuilder::type() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->type;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this property has a notify signal; false otherwise.
+
+ \sa notifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+bool QMetaPropertyBuilder::hasNotifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Notify);
+ else
+ return false;
+}
+
+/*!
+ Returns the notify signal associated with this property.
+
+ \sa hasNotifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+QMetaMethodBuilder QMetaPropertyBuilder::notifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d && d->notifySignal >= 0)
+ return QMetaMethodBuilder(_mobj, d->notifySignal);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Sets the notify signal associated with this property to \a value.
+
+ \sa hasNotifySignal(), notifySignal(), removeNotifySignal()
+*/
+void QMetaPropertyBuilder::setNotifySignal(const QMetaMethodBuilder& value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ if (value._mobj) {
+ d->notifySignal = value._index;
+ d->setFlag(Notify, true);
+ } else {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+ }
+}
+
+/*!
+ Removes the notify signal from this property.
+
+ \sa hasNotifySignal(), notifySignal(), setNotifySignal()
+*/
+void QMetaPropertyBuilder::removeNotifySignal()
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+}
+
+/*!
+ Returns true if this property is readable; otherwise returns false.
+ The default value is true.
+
+ \sa setReadable(), isWritable()
+*/
+bool QMetaPropertyBuilder::isReadable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Readable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is writable; otherwise returns false.
+ The default value is true.
+
+ \sa setWritable(), isReadable()
+*/
+bool QMetaPropertyBuilder::isWritable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Writable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property can be reset to a default value; otherwise
+ returns false. The default value is false.
+
+ \sa setResettable()
+*/
+bool QMetaPropertyBuilder::isResettable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Resettable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designable; otherwise returns false.
+ This default value is false.
+
+ \sa setDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isDesignable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Designable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is scriptable; otherwise returns false.
+ This default value is false.
+
+ \sa setScriptable(), isDesignable(), isStored()
+*/
+bool QMetaPropertyBuilder::isScriptable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Scriptable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is stored; otherwise returns false.
+ This default value is false.
+
+ \sa setStored(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isStored() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Stored);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is editable; otherwise returns false.
+ This default value is false.
+
+ \sa setEditable(), isDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isEditable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Editable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designated as the \c USER
+ property, i.e., the one that the user can edit or that is
+ significant in some other way. Otherwise it returns
+ false. This default value is false.
+
+ \sa setUser(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isUser() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(User);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has a C++ setter function that
+ follows Qt's standard "name" / "setName" pattern. Designer and uic
+ query hasStdCppSet() in order to avoid expensive
+ QObject::setProperty() calls. All properties in Qt [should] follow
+ this pattern. The default value is false.
+
+ \sa setStdCppSet()
+*/
+bool QMetaPropertyBuilder::hasStdCppSet() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(StdCppSet);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is an enumerator or flag type;
+ otherwise returns false. This default value is false.
+
+ \sa setEnumOrFlag()
+*/
+bool QMetaPropertyBuilder::isEnumOrFlag() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(EnumOrFlag);
+ else
+ return false;
+}
+
+/*!
+ Sets this property to readable if \a value is true.
+
+ \sa isReadable(), setWritable()
+*/
+void QMetaPropertyBuilder::setReadable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Readable, value);
+}
+
+/*!
+ Sets this property to writable if \a value is true.
+
+ \sa isWritable(), setReadable()
+*/
+void QMetaPropertyBuilder::setWritable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Writable, value);
+}
+
+/*!
+ Sets this property to resettable if \a value is true.
+
+ \sa isResettable()
+*/
+void QMetaPropertyBuilder::setResettable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Resettable, value);
+}
+
+/*!
+ Sets this property to designable if \a value is true.
+
+ \sa isDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setDesignable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Designable, value);
+}
+
+/*!
+ Sets this property to scriptable if \a value is true.
+
+ \sa isScriptable(), setDesignable(), setStored()
+*/
+void QMetaPropertyBuilder::setScriptable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Scriptable, value);
+}
+
+/*!
+ Sets this property to storable if \a value is true.
+
+ \sa isStored(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setStored(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Stored, value);
+}
+
+/*!
+ Sets this property to editable if \a value is true.
+
+ \sa isEditable(), setDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setEditable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Editable, value);
+}
+
+/*!
+ Sets the \c USER flag on this property to \a value.
+
+ \sa isUser(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setUser(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(User, value);
+}
+
+/*!
+ Sets the C++ setter flag on this property to \a value, which is
+ true if the property has a C++ setter function that follows Qt's
+ standard "name" / "setName" pattern.
+
+ \sa hasStdCppSet()
+*/
+void QMetaPropertyBuilder::setStdCppSet(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(StdCppSet, value);
+}
+
+/*!
+ Sets this property to be of an enumerator or flag type if
+ \a value is true.
+
+ \sa isEnumOrFlag()
+*/
+void QMetaPropertyBuilder::setEnumOrFlag(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(EnumOrFlag, value);
+}
+
+/*!
+ \class QMetaEnumBuilder
+ \brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder.
+*/
+
+QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->enumerators.size())
+ return &(_mobj->d->enumerators[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaEnumBuilder::QMetaEnumBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaEnumBuilder::index() const
+
+ Returns the index of this enumerator within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name of the enumerator (without the scope).
+*/
+QByteArray QMetaEnumBuilder::name() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this enumerator is used as a flag; otherwise returns
+ false.
+
+ \sa setIsFlag()
+*/
+bool QMetaEnumBuilder::isFlag() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->isFlag;
+ else
+ return false;
+}
+
+/*!
+ Sets this enumerator to be used as a flag if \a value is true.
+
+ \sa isFlag()
+*/
+void QMetaEnumBuilder::setIsFlag(bool value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ d->isFlag = value;
+}
+
+/*!
+ Returns the number of keys.
+
+ \sa key(), addKey()
+*/
+int QMetaEnumBuilder::keyCount() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->keys.size();
+ else
+ return 0;
+}
+
+/*!
+ Returns the key with the given \a index, or an empty QByteArray
+ if no such key exists.
+
+ \sa keyCount(), addKey(), value()
+*/
+QByteArray QMetaEnumBuilder::key(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->keys[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value with the given \a index; or returns -1 if there
+ is no such value.
+
+ \sa keyCount(), addKey(), key()
+*/
+int QMetaEnumBuilder::value(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->values[index];
+ else
+ return -1;
+}
+
+/*!
+ Adds a new key called \a name to this enumerator, associated
+ with \a value. Returns the index of the new key.
+
+ \sa keyCount(), key(), value(), removeKey()
+*/
+int QMetaEnumBuilder::addKey(const QByteArray& name, int value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d) {
+ int index = d->keys.size();
+ d->keys += name;
+ d->values += value;
+ return index;
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ Removes the key at \a index from this enumerator.
+
+ \sa addKey()
+*/
+void QMetaEnumBuilder::removeKey(int index)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size()) {
+ d->keys.removeAt(index);
+ d->values.removeAt(index);
+ }
+}
diff --git a/tests/auto/dynamicobject/qmetaobjectbuilder.h b/tests/auto/dynamicobject/qmetaobjectbuilder.h
new file mode 100644
index 0000000..d820860
--- /dev/null
+++ b/tests/auto/dynamicobject/qmetaobjectbuilder.h
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
+**
+** Copyright (C) $THISYEAR$ $COMPANY_NAME$.
+**
+** $QT_EXTENDED_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMETAOBJECTBUILDER_H
+#define QMETAOBJECTBUILDER_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmap.h>
+
+class QMetaObjectBuilderPrivate;
+class QMetaMethodBuilder;
+class QMetaMethodBuilderPrivate;
+class QMetaPropertyBuilder;
+class QMetaPropertyBuilderPrivate;
+class QMetaEnumBuilder;
+class QMetaEnumBuilderPrivate;
+
+class QMetaObjectBuilder
+{
+public:
+ enum AddMember
+ {
+ ClassName = 0x00000001,
+ SuperClass = 0x00000002,
+ Methods = 0x00000004,
+ Signals = 0x00000008,
+ Slots = 0x00000010,
+ Constructors = 0x00000020,
+ Properties = 0x00000040,
+ Enumerators = 0x00000080,
+ ClassInfos = 0x00000100,
+ RelatedMetaObjects = 0x00000200,
+ StaticMetacall = 0x00000400,
+ PublicMethods = 0x00000800,
+ ProtectedMethods = 0x00001000,
+ PrivateMethods = 0x00002000,
+ AllMembers = 0x7FFFFFFF,
+ AllPrimaryMembers = 0x7FFFFBFC
+ };
+ Q_DECLARE_FLAGS(AddMembers, AddMember)
+
+ QMetaObjectBuilder();
+ explicit QMetaObjectBuilder(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+ virtual ~QMetaObjectBuilder();
+
+ QByteArray className() const;
+ void setClassName(const QByteArray& name);
+
+ const QMetaObject *superClass() const;
+ void setSuperClass(const QMetaObject *meta);
+
+ int methodCount() const;
+ int constructorCount() const;
+ int propertyCount() const;
+ int enumeratorCount() const;
+ int classInfoCount() const;
+ int relatedMetaObjectCount() const;
+
+ QMetaMethodBuilder addMethod(const QByteArray& signature);
+ QMetaMethodBuilder addMethod(const QByteArray& signature, const QByteArray& returnType);
+ QMetaMethodBuilder addMethod(const QMetaMethod& prototype);
+
+ QMetaMethodBuilder addSlot(const QByteArray& signature);
+ QMetaMethodBuilder addSignal(const QByteArray& signature);
+
+ QMetaMethodBuilder addConstructor(const QByteArray& signature);
+ QMetaMethodBuilder addConstructor(const QMetaMethod& prototype);
+
+ QMetaPropertyBuilder addProperty(const QByteArray& name, const QByteArray& type, int notifierId=-1);
+ QMetaPropertyBuilder addProperty(const QMetaProperty& prototype);
+
+ QMetaEnumBuilder addEnumerator(const QByteArray& name);
+ QMetaEnumBuilder addEnumerator(const QMetaEnum& prototype);
+
+ int addClassInfo(const QByteArray& name, const QByteArray& value);
+
+ int addRelatedMetaObject(const QMetaObject *meta);
+
+ void addMetaObject(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+
+ QMetaMethodBuilder method(int index) const;
+ QMetaMethodBuilder constructor(int index) const;
+ QMetaPropertyBuilder property(int index) const;
+ QMetaEnumBuilder enumerator(int index) const;
+ const QMetaObject *relatedMetaObject(int index) const;
+
+ QByteArray classInfoName(int index) const;
+ QByteArray classInfoValue(int index) const;
+
+ void removeMethod(int index);
+ void removeConstructor(int index);
+ void removeProperty(int index);
+ void removeEnumerator(int index);
+ void removeClassInfo(int index);
+ void removeRelatedMetaObject(int index);
+
+ int indexOfMethod(const QByteArray& signature);
+ int indexOfSignal(const QByteArray& signature);
+ int indexOfSlot(const QByteArray& signature);
+ int indexOfConstructor(const QByteArray& signature);
+ int indexOfProperty(const QByteArray& name);
+ int indexOfEnumerator(const QByteArray& name);
+ int indexOfClassInfo(const QByteArray& name);
+
+ typedef int (*StaticMetacallFunction)(QMetaObject::Call, int, void **);
+
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction() const;
+ void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value);
+
+ QMetaObject *toMetaObject() const;
+
+#ifndef QT_NO_DATASTREAM
+ void serialize(QDataStream& stream) const;
+ void deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references);
+#endif
+
+private:
+ Q_DISABLE_COPY(QMetaObjectBuilder);
+
+ QMetaObjectBuilderPrivate *d;
+
+ friend class QMetaMethodBuilder;
+ friend class QMetaPropertyBuilder;
+ friend class QMetaEnumBuilder;
+};
+
+class QMetaMethodBuilder
+{
+public:
+ QMetaMethodBuilder() : _mobj(0), _index(0) {}
+
+ int index() const;
+
+ QMetaMethod::MethodType methodType() const;
+ QByteArray signature() const;
+
+ QByteArray returnType() const;
+ void setReturnType(const QByteArray& value);
+
+ QList<QByteArray> parameterNames() const;
+ void setParameterNames(const QList<QByteArray>& value);
+
+ QByteArray tag() const;
+ void setTag(const QByteArray& value);
+
+ QMetaMethod::Access access() const;
+ void setAccess(QMetaMethod::Access value);
+
+ int attributes() const;
+ void setAttributes(int value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+ friend class QMetaPropertyBuilder;
+
+ QMetaMethodBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaMethodBuilderPrivate *d_func() const;
+};
+
+class QMetaPropertyBuilder
+{
+public:
+ QMetaPropertyBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+ QByteArray type() const;
+
+ bool hasNotifySignal() const;
+ QMetaMethodBuilder notifySignal() const;
+ void setNotifySignal(const QMetaMethodBuilder& value);
+ void removeNotifySignal();
+
+ bool isReadable() const;
+ bool isWritable() const;
+ bool isResettable() const;
+ bool isDesignable() const;
+ bool isScriptable() const;
+ bool isStored() const;
+ bool isEditable() const;
+ bool isUser() const;
+ bool hasStdCppSet() const;
+ bool isEnumOrFlag() const;
+
+ void setReadable(bool value);
+ void setWritable(bool value);
+ void setResettable(bool value);
+ void setDesignable(bool value);
+ void setScriptable(bool value);
+ void setStored(bool value);
+ void setEditable(bool value);
+ void setUser(bool value);
+ void setStdCppSet(bool value);
+ void setEnumOrFlag(bool value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaPropertyBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaPropertyBuilderPrivate *d_func() const;
+};
+
+class QMetaEnumBuilder
+{
+public:
+ QMetaEnumBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+
+ bool isFlag() const;
+ void setIsFlag(bool value);
+
+ int keyCount() const;
+ QByteArray key(int index) const;
+ int value(int index) const;
+
+ int addKey(const QByteArray& name, int value);
+ void removeKey(int index);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaEnumBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaEnumBuilderPrivate *d_func() const;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::AddMembers)
+
+#endif
diff --git a/tests/auto/dynamicobject/tst_qobject.cpp b/tests/auto/dynamicobject/tst_qobject.cpp
new file mode 100644
index 0000000..18805f7
--- /dev/null
+++ b/tests/auto/dynamicobject/tst_qobject.cpp
@@ -0,0 +1,325 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+****************************************************************************/
+
+#define QT3_SUPPORT
+#include <QtTest/QtTest>
+
+
+#include <qcoreapplication.h>
+
+#include <qmetaobject.h>
+
+#include "qobject.h"
+#include "private/qobject_p.h"
+#include "qmetaobjectbuilder.h"
+#include "qdynamicmetaobject.h"
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QObject();
+ virtual ~tst_QObject();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void addSignal();
+ void addSlot();
+ void addProperty();
+ void dynamicProperty();
+};
+
+//===========================================================================
+
+class MyDynamicMetaObject : public QDynamicMetaObject
+{
+public:
+ MyDynamicMetaObject(const QMetaObject *base);
+
+ int createProperty(const QObject *object, const char *, const char *);
+
+ virtual void callSlot(QObject *object, int id, const QList<QVariant> &args);
+
+ virtual void writeProperty(QObject *, int id, const QVariant &value) {
+ props[property(id).name()] = value;
+ }
+
+ virtual QVariant readProperty(QObject *, int id) const {
+ return props[property(id).name()];
+ }
+
+ QString calledSlot;
+ QString string;
+
+private:
+ QMap<QString,QVariant> props;
+};
+
+MyDynamicMetaObject::MyDynamicMetaObject(const QMetaObject *_base)
+ : QDynamicMetaObject(_base)
+{
+}
+
+void MyDynamicMetaObject::callSlot(QObject *object, int id, const QList<QVariant> &args)
+{
+ calledSlot = method(id).signature();
+ qDebug() << "Handled slot" << id << calledSlot << args;
+ if (calledSlot == "string(QString)") {
+ string = args[0].toString();
+ }
+}
+
+int MyDynamicMetaObject::createProperty(const QObject *, const char *name, const char *type)
+{
+ qDebug() << "createProperty" << name;
+ if (name == QString("dynamicProp")) {
+ addProperty(name, type);
+ int id = indexOfProperty(name);
+ return id;
+ }
+
+ return -1;
+}
+
+//===========================================================================
+
+class MyDynamicObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyDynamicObject();
+
+ void addSignal(const char *sigName) {
+ dynamicMeta->addSignal(sigName);
+ }
+
+ void addSignal(const char *sigName, const QList<QByteArray> &parameterNames) {
+ dynamicMeta->addSignal(sigName, parameterNames);
+ }
+
+ void emitSignal(const char *sigName) {
+ int idx = dynamicMeta->indexOfSignal(sigName);
+ if (idx >= 0)
+ dynamicMeta->activate(this, idx, 0);
+ }
+
+ void emitSignal(const char *sigName, QGenericArgument val0
+ , QGenericArgument val1=QGenericArgument(0)
+ , QGenericArgument val2=QGenericArgument(0)
+ , QGenericArgument val3=QGenericArgument(0)
+ , QGenericArgument val4=QGenericArgument(0)
+ , QGenericArgument val5=QGenericArgument(0)
+ , QGenericArgument val6=QGenericArgument(0)
+ , QGenericArgument val7=QGenericArgument(0))
+ {
+ int idx = dynamicMeta->indexOfSignal(sigName);
+ if (idx >= 0) {
+ QGenericReturnArgument rv;
+ dynamicMeta->method(idx).invoke(this, Qt::DirectConnection, rv,
+ val0, val1, val2, val3, val4, val5, val6, val7);
+ }
+ }
+
+ void addSlot(const char *slotName) {
+ dynamicMeta->addSlot(slotName);
+ }
+
+ void addSlot(const char *slotName, const QList<QByteArray> &parameterNames) {
+ dynamicMeta->addSlot(slotName, parameterNames);
+ }
+
+ void addProperty(const char *name, const char *type, const char *notifier) {
+ dynamicMeta->addProperty(name, type, notifier);
+ }
+
+ QString calledSlot() const { return dynamicMeta->calledSlot; }
+
+ void emitNormalSignal() { emit normalSignal(); }
+
+ MyDynamicMetaObject *dynamicMeta;
+
+public slots:
+ void normalSlot() {}
+
+signals:
+ void normalSignal();
+
+};
+
+MyDynamicObject::MyDynamicObject()
+ : QObject()
+{
+ dynamicMeta = new MyDynamicMetaObject(&staticMetaObject);
+ setDynamicMetaObject(dynamicMeta);
+}
+
+//===========================================================================
+
+class TestObject : public QObject
+{
+ Q_OBJECT
+public:
+ TestObject() : slot1Called(false), slot2Called(false) {}
+
+ void emitSignal() { emit triggered(); }
+ void setText(const QString &str) { emit textChanged(str); }
+
+ bool slot1Called;
+ bool slot2Called;
+ QString string;
+
+public slots:
+ void slot1() {
+ slot1Called = true;
+ qDebug() << "Called slot1()";
+ }
+
+ void slot2() {
+ slot2Called = true;
+ qDebug() << "Called slot2()";
+ }
+
+ void slotString(QString str) {
+ string = str;
+ qDebug() << "Called slotString()" << str;
+ }
+
+signals:
+ void triggered();
+ void textChanged(QString);
+};
+
+
+tst_QObject::tst_QObject()
+{
+
+}
+
+tst_QObject::~tst_QObject()
+{
+
+}
+
+void tst_QObject::initTestCase()
+{
+}
+
+void tst_QObject::cleanupTestCase()
+{
+}
+
+void tst_QObject::init()
+{
+}
+
+void tst_QObject::cleanup()
+{
+}
+
+void tst_QObject::addSignal()
+{
+ MyDynamicObject myObj;
+ myObj.addSignal("testSignal()");
+
+ TestObject testObj;
+
+ connect(&myObj, SIGNAL(testSignal()), &testObj, SLOT(slot1()));
+ connect(&myObj, SIGNAL(normalSignal()), &testObj, SLOT(slot2()));
+
+ myObj.emitSignal("testSignal()");
+
+ QVERIFY(testObj.slot1Called);
+ QVERIFY(!testObj.slot2Called);
+
+ testObj.slot1Called = false;
+
+ myObj.emitNormalSignal();
+
+ QVERIFY(!testObj.slot1Called);
+ QVERIFY(testObj.slot2Called);
+
+ // With parameter
+ myObj.addSignal("stringSignal(QString)");
+ connect(&myObj, SIGNAL(stringSignal(QString)), &testObj, SLOT(slotString(QString)));
+
+ QString param("Hello");
+ myObj.emitSignal("stringSignal(QString)", Q_ARG(QString, param));
+
+ QCOMPARE(testObj.string, QString("Hello"));
+}
+
+void tst_QObject::addSlot()
+{
+ MyDynamicObject myObj;
+ myObj.addSlot("testSlot1()");
+ myObj.addSignal("testSignal()");
+ myObj.addSlot("testSlot()");
+
+ TestObject testObj;
+
+ connect(&testObj, SIGNAL(triggered()), &myObj, SLOT(testSlot()));
+ connect(&testObj, SIGNAL(triggered()), &myObj, SIGNAL(testSignal())); // signal chaining
+ connect(&myObj, SIGNAL(testSignal()), &testObj, SLOT(slot1()));
+
+ testObj.emitSignal();
+
+ QCOMPARE(myObj.calledSlot(), QString("testSlot()"));
+ QVERIFY(testObj.slot1Called);
+
+ // Verify parameter type and name
+ myObj.addSlot("string(QString)", QList<QByteArray>() << "name");
+ int idx = myObj.metaObject()->indexOfSlot("string(QString)");
+ QVERIFY(idx > 0);
+ QMetaMethod method = myObj.metaObject()->method(idx);
+ QVERIFY(method.parameterTypes()[0] == "QString");
+ QVERIFY(method.parameterNames()[0] == "name");
+
+ connect(&testObj, SIGNAL(textChanged(QString)), &myObj, SLOT(string(QString)));
+ testObj.setText("Hello");
+ QCOMPARE(myObj.dynamicMeta->string, QString("Hello"));
+}
+
+void tst_QObject::addProperty()
+{
+ MyDynamicObject myObj;
+ myObj.addSignal("propChanged()");
+ myObj.addProperty("myProp", QVariant::typeToName(QVariant::String), "propChanged()");
+
+ myObj.setProperty("myProp", QString("hello"));
+ qDebug() << "property value" << myObj.property("myProp").toString();
+ QCOMPARE(myObj.property("myProp").toString(), QString("hello"));
+
+ TestObject testObj;
+ connect(&myObj, SIGNAL(propChanged()), &testObj, SLOT(slot1()));
+ myObj.setProperty("myProp", QString("there"));
+
+ QCOMPARE(myObj.property("myProp").toString(), QString("there"));
+ QVERIFY(testObj.slot1Called);
+}
+
+void tst_QObject::dynamicProperty()
+{
+ MyDynamicObject myObj;
+
+ myObj.setProperty("dynamicProp", QString("hello"));
+ qDebug() << "property value" << myObj.property("dynamicProp").toString();
+ QCOMPARE(myObj.property("dynamicProp").toString(), QString("hello"));
+}
+
+QTEST_MAIN(tst_QObject)
+#include "tst_qobject.moc"
diff --git a/tests/auto/math3d/math3d.pro b/tests/auto/math3d/math3d.pro
new file mode 100644
index 0000000..d6189ef
--- /dev/null
+++ b/tests/auto/math3d/math3d.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = qmatrixnxn qquaternion qvectornd
diff --git a/tests/auto/math3d/qmatrixnxn/qmatrixnxn.pro b/tests/auto/math3d/qmatrixnxn/qmatrixnxn.pro
new file mode 100644
index 0000000..40c6cc0
--- /dev/null
+++ b/tests/auto/math3d/qmatrixnxn/qmatrixnxn.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+VPATH += ../shared
+INCLUDEPATH += ../shared
+HEADERS += math3dincludes.h
+SOURCES += tst_qmatrixnxn.cpp
diff --git a/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
new file mode 100644
index 0000000..bb510fc
--- /dev/null
+++ b/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
@@ -0,0 +1,3185 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/qmath.h>
+#include "math3dincludes.h"
+
+class tst_QMatrix : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QMatrix() {}
+ ~tst_QMatrix() {}
+
+private slots:
+ void create2x2();
+ void create3x3();
+ void create4x4();
+ void create4x3();
+
+ void isIdentity2x2();
+ void isIdentity3x3();
+ void isIdentity4x4();
+ void isIdentity4x3();
+
+ void compare2x2();
+ void compare3x3();
+ void compare4x4();
+ void compare4x3();
+
+ void transposed2x2();
+ void transposed3x3();
+ void transposed4x4();
+ void transposed4x3();
+
+ void add2x2_data();
+ void add2x2();
+ void add3x3_data();
+ void add3x3();
+ void add4x4_data();
+ void add4x4();
+ void add4x3_data();
+ void add4x3();
+
+ void subtract2x2_data();
+ void subtract2x2();
+ void subtract3x3_data();
+ void subtract3x3();
+ void subtract4x4_data();
+ void subtract4x4();
+ void subtract4x3_data();
+ void subtract4x3();
+
+ void multiply2x2_data();
+ void multiply2x2();
+ void multiply3x3_data();
+ void multiply3x3();
+ void multiply4x4_data();
+ void multiply4x4();
+ void multiply4x3_data();
+ void multiply4x3();
+
+ void multiplyFactor2x2_data();
+ void multiplyFactor2x2();
+ void multiplyFactor3x3_data();
+ void multiplyFactor3x3();
+ void multiplyFactor4x4_data();
+ void multiplyFactor4x4();
+ void multiplyFactor4x3_data();
+ void multiplyFactor4x3();
+
+ void divideFactor2x2_data();
+ void divideFactor2x2();
+ void divideFactor3x3_data();
+ void divideFactor3x3();
+ void divideFactor4x4_data();
+ void divideFactor4x4();
+ void divideFactor4x3_data();
+ void divideFactor4x3();
+
+ void negate2x2_data();
+ void negate2x2();
+ void negate3x3_data();
+ void negate3x3();
+ void negate4x4_data();
+ void negate4x4();
+ void negate4x3_data();
+ void negate4x3();
+
+ void inverted4x4_data();
+ void inverted4x4();
+
+ void orthonormalInverse4x4();
+
+ void scale4x4_data();
+ void scale4x4();
+
+ void translate4x4_data();
+ void translate4x4();
+
+ void rotate4x4_data();
+ void rotate4x4();
+
+ void normalMatrix_data();
+ void normalMatrix();
+
+ void optimizedTransforms();
+
+ void ortho();
+ void frustum();
+ void perspective();
+ void flipCoordinates();
+
+ void convertGeneric();
+
+ void extractAxisRotation_data();
+ void extractAxisRotation();
+
+ void extractTranslation_data();
+ void extractTranslation();
+
+ void inferSpecialType_data();
+ void inferSpecialType();
+
+ void columnsAndRows();
+
+ void convertQMatrix();
+ void convertQTransform();
+
+ void fill();
+
+private:
+ static void setMatrix(QMatrix2x2& m, const qreal *values);
+ static void setMatrixFixed(QMatrix2x2& m, const qreal *values);
+ static bool isSame(const QMatrix2x2& m, const qreal *values);
+ static bool isIdentity(const QMatrix2x2& m);
+
+ static void setMatrix(QMatrix3x3& m, const qreal *values);
+ static void setMatrixFixed(QMatrix3x3& m, const qreal *values);
+ static bool isSame(const QMatrix3x3& m, const qreal *values);
+ static bool isIdentity(const QMatrix3x3& m);
+
+ static void setMatrix(QMatrix4x4& m, const qreal *values);
+ static void setMatrixFixed(QMatrix4x4& m, const qreal *values);
+ static bool isSame(const QMatrix4x4& m, const qreal *values);
+ static bool isIdentity(const QMatrix4x4& m);
+
+ static void setMatrix(QMatrix4x3& m, const qreal *values);
+ static void setMatrixFixed(QMatrix4x3& m, const qreal *values);
+ static bool isSame(const QMatrix4x3& m, const qreal *values);
+ static bool isIdentity(const QMatrix4x3& m);
+};
+
+static const qreal nullValues2[] =
+ {0.0f, 0.0f,
+ 0.0f, 0.0f};
+
+static qreal const identityValues2[16] =
+ {1.0f, 0.0f,
+ 0.0f, 1.0f};
+
+static const qreal doubleIdentity2[] =
+ {2.0f, 0.0f,
+ 0.0f, 2.0f};
+
+static qreal const uniqueValues2[16] =
+ {1.0f, 2.0f,
+ 5.0f, 6.0f};
+
+static qreal const transposedValues2[16] =
+ {1.0f, 5.0f,
+ 2.0f, 6.0f};
+
+static const qreal nullValues3[] =
+ {0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f};
+
+static qreal const identityValues3[16] =
+ {1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f};
+
+static const qreal doubleIdentity3[] =
+ {2.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f, 0.0f,
+ 0.0f, 0.0f, 2.0f};
+
+static qreal const uniqueValues3[16] =
+ {1.0f, 2.0f, 3.0f,
+ 5.0f, 6.0f, 7.0f,
+ 9.0f, 10.0f, 11.0f};
+
+static qreal const transposedValues3[16] =
+ {1.0f, 5.0f, 9.0f,
+ 2.0f, 6.0f, 10.0f,
+ 3.0f, 7.0f, 11.0f};
+
+static const qreal nullValues4[] =
+ {0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f};
+
+static qreal const identityValues4[16] =
+ {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+
+static const qreal doubleIdentity4[] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 2.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 2.0f};
+
+static qreal const uniqueValues4[16] =
+ {1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f,
+ 13.0f, 14.0f, 15.0f, 16.0f};
+
+static qreal const transposedValues4[16] =
+ {1.0f, 5.0f, 9.0f, 13.0f,
+ 2.0f, 6.0f, 10.0f, 14.0f,
+ 3.0f, 7.0f, 11.0f, 15.0f,
+ 4.0f, 8.0f, 12.0f, 16.0f};
+
+static const qreal nullValues4x3[] =
+ {0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f};
+
+static qreal const identityValues4x3[12] =
+ {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f};
+
+static qreal const doubleIdentity4x3[12] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 2.0f, 0.0f};
+
+static qreal const uniqueValues4x3[12] =
+ {1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f};
+
+static qreal const transposedValues3x4[12] =
+ {1.0f, 5.0f, 9.0f,
+ 2.0f, 6.0f, 10.0f,
+ 3.0f, 7.0f, 11.0f,
+ 4.0f, 8.0f, 12.0f};
+
+// Set a matrix to a specified array of values, which are assumed
+// to be in row-major order. This sets the values using floating-point.
+void tst_QMatrix::setMatrix(QMatrix2x2& m, const qreal *values)
+{
+ for (int row = 0; row < 2; ++row)
+ for (int col = 0; col < 2; ++col)
+ m(row, col) = values[row * 2 + col];
+}
+void tst_QMatrix::setMatrix(QMatrix3x3& m, const qreal *values)
+{
+ for (int row = 0; row < 3; ++row)
+ for (int col = 0; col < 3; ++col)
+ m(row, col) = values[row * 3 + col];
+}
+void tst_QMatrix::setMatrix(QMatrix4x4& m, const qreal *values)
+{
+ for (int row = 0; row < 4; ++row)
+ for (int col = 0; col < 4; ++col)
+ m(row, col) = values[row * 4 + col];
+}
+void tst_QMatrix::setMatrix(QMatrix4x3& m, const qreal *values)
+{
+ for (int row = 0; row < 3; ++row)
+ for (int col = 0; col < 4; ++col)
+ m(row, col) = values[row * 4 + col];
+}
+
+// Set a matrix to a specified array of values, which are assumed
+// to be in row-major order. This sets the values using fixed-point.
+void tst_QMatrix::setMatrixFixed(QMatrix2x2& m, const qreal *values)
+{
+ float *data = m.data();
+ for (int row = 0; row < 2; ++row) {
+ for (int col = 0; col < 2; ++col) {
+ data[row + col * 2] = values[row * 2 + col];
+ }
+ }
+}
+void tst_QMatrix::setMatrixFixed(QMatrix3x3& m, const qreal *values)
+{
+ float *data = m.data();
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 3; ++col) {
+ data[row + col * 3] = values[row * 3 + col];
+ }
+ }
+}
+void tst_QMatrix::setMatrixFixed(QMatrix4x4& m, const qreal *values)
+{
+ float *data = m.data();
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ data[row + col * 4] = values[row * 4 + col];
+ }
+ }
+}
+void tst_QMatrix::setMatrixFixed(QMatrix4x3& m, const qreal *values)
+{
+ float *data = m.data();
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ data[row + col * 3] = values[row * 4 + col];
+ }
+ }
+}
+
+// qFuzzyCompare isn't quite "fuzzy" enough to handle conversion
+// to fixed-point and back again. So create "fuzzier" compares.
+static bool fuzzyCompare(float x, float y, qreal epsilon = 0.001)
+{
+ float diff = x - y;
+ if (diff < 0.0f)
+ diff = -diff;
+ return (diff < epsilon);
+}
+
+static bool fuzzyCompare(const QVector3D &v1, const QVector3D &v2, qreal epsilon = 0.001)
+{
+ if (!fuzzyCompare(v1.x(), v2.x(), epsilon))
+ return false;
+ if (!fuzzyCompare(v1.y(), v2.y(), epsilon))
+ return false;
+ if (!fuzzyCompare(v1.z(), v2.z(), epsilon))
+ return false;
+ return true;
+}
+
+static bool matrixFuzzyCompare(const QMatrix4x4 &m1, const QMatrix4x4 &m2)
+{
+ bool ret = true;
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ ret = ret && fuzzyCompare(m1(i, j), m2(i, j));
+ }
+ }
+
+ return ret;
+}
+
+// Determine if a matrix is the same as a specified array of values.
+// The values are assumed to be specified in row-major order.
+bool tst_QMatrix::isSame(const QMatrix2x2& m, const qreal *values)
+{
+ const float *mv = m.constData();
+ for (int row = 0; row < 2; ++row) {
+ for (int col = 0; col < 2; ++col) {
+ // Check the values using the operator() function.
+ if (!fuzzyCompare((float)(m(row, col)), (float)(values[row * 2 + col]))) {
+ qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 2 + col];
+ return false;
+ }
+
+ // Check the values using direct access, which verifies that the values
+ // are stored internally in column-major order.
+ if (!fuzzyCompare((float)(mv[col * 2 + row]), (float)(values[row * 2 + col]))) {
+ qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 2 + row] << "expected =" << values[row * 2 + col];
+ return false;
+ }
+ }
+ }
+ return true;
+}
+bool tst_QMatrix::isSame(const QMatrix3x3& m, const qreal *values)
+{
+ const float *mv = m.constData();
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 3; ++col) {
+ // Check the values using the operator() access function.
+ if (!fuzzyCompare((float)(m(row, col)), (float)(values[row * 3 + col]))) {
+ qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 3 + col];
+ return false;
+ }
+
+ // Check the values using direct access, which verifies that the values
+ // are stored internally in column-major order.
+ if (!fuzzyCompare((float)(mv[col * 3 + row]), (float)(values[row * 3 + col]))) {
+ qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 3 + row] << "expected =" << values[row * 3 + col];
+ return false;
+ }
+ }
+ }
+ return true;
+}
+bool tst_QMatrix::isSame(const QMatrix4x4& m, const qreal *values)
+{
+ const float *mv = m.constData();
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ // Check the values using the operator() access function.
+ if (!fuzzyCompare((float)(m(row, col)), (float)(values[row * 4 + col]))) {
+ qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 4 + col];
+ return false;
+ }
+
+ // Check the values using direct access, which verifies that the values
+ // are stored internally in column-major order.
+ if (!fuzzyCompare((float)(mv[col * 4 + row]), (float)(values[row * 4 + col]))) {
+ qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 4 + row] << "expected =" << values[row * 4 + col];
+ return false;
+ }
+ }
+ }
+ return true;
+}
+bool tst_QMatrix::isSame(const QMatrix4x3& m, const qreal *values)
+{
+ const float *mv = m.constData();
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ // Check the values using the operator() access function.
+ if (!fuzzyCompare((float)(m(row, col)), (float)(values[row * 4 + col]))) {
+ qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 4 + col];
+ return false;
+ }
+
+ // Check the values using direct access, which verifies that the values
+ // are stored internally in column-major order.
+ if (!fuzzyCompare((float)(mv[col * 3 + row]), (float)(values[row * 4 + col]))) {
+ qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 3 + row] << "expected =" << values[row * 4 + col];
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// Determine if a matrix is the identity.
+bool tst_QMatrix::isIdentity(const QMatrix2x2& m)
+{
+ return isSame(m, identityValues2);
+}
+bool tst_QMatrix::isIdentity(const QMatrix3x3& m)
+{
+ return isSame(m, identityValues3);
+}
+bool tst_QMatrix::isIdentity(const QMatrix4x4& m)
+{
+ return isSame(m, identityValues4);
+}
+bool tst_QMatrix::isIdentity(const QMatrix4x3& m)
+{
+ return isSame(m, identityValues4x3);
+}
+
+// Test the creation of QMatrix2x2 objects in various ways:
+// construct, copy, and modify.
+void tst_QMatrix::create2x2()
+{
+ QMatrix2x2 m1;
+ QVERIFY(isIdentity(m1));
+ QVERIFY(m1.isIdentity());
+
+ QMatrix2x2 m2;
+ setMatrix(m2, uniqueValues2);
+ QVERIFY(isSame(m2, uniqueValues2));
+ QVERIFY(!m2.isIdentity());
+
+ QMatrix2x2 m3;
+ setMatrixFixed(m3, uniqueValues2);
+ QVERIFY(isSame(m3, uniqueValues2));
+
+ QMatrix2x2 m4(m3);
+ QVERIFY(isSame(m4, uniqueValues2));
+
+ QMatrix2x2 m5;
+ m5 = m3;
+ QVERIFY(isSame(m5, uniqueValues2));
+
+ m5.setIdentity();
+ QVERIFY(isIdentity(m5));
+
+ QMatrix2x2 m6(uniqueValues2);
+ QVERIFY(isSame(m6, uniqueValues2));
+ qreal vals[4];
+ m6.toValueArray(vals);
+ for (int index = 0; index < 4; ++index)
+ QCOMPARE((float)(vals[index]), (float)(uniqueValues2[index]));
+}
+
+// Test the creation of QMatrix3x3 objects in various ways:
+// construct, copy, and modify.
+void tst_QMatrix::create3x3()
+{
+ QMatrix3x3 m1;
+ QVERIFY(isIdentity(m1));
+ QVERIFY(m1.isIdentity());
+
+ QMatrix3x3 m2;
+ setMatrix(m2, uniqueValues3);
+ QVERIFY(isSame(m2, uniqueValues3));
+ QVERIFY(!m2.isIdentity());
+
+ QMatrix3x3 m3;
+ setMatrixFixed(m3, uniqueValues3);
+ QVERIFY(isSame(m3, uniqueValues3));
+
+ QMatrix3x3 m4(m3);
+ QVERIFY(isSame(m4, uniqueValues3));
+
+ QMatrix3x3 m5;
+ m5 = m3;
+ QVERIFY(isSame(m5, uniqueValues3));
+
+ m5.setIdentity();
+ QVERIFY(isIdentity(m5));
+
+ QMatrix3x3 m6(uniqueValues3);
+ QVERIFY(isSame(m6, uniqueValues3));
+ qreal vals[9];
+ m6.toValueArray(vals);
+ for (int index = 0; index < 9; ++index)
+ QCOMPARE((float)(vals[index]), (float)(uniqueValues3[index]));
+}
+
+// Test the creation of QMatrix4x4 objects in various ways:
+// construct, copy, and modify.
+void tst_QMatrix::create4x4()
+{
+ QMatrix4x4 m1;
+ QVERIFY(isIdentity(m1));
+ QVERIFY(m1.isIdentity());
+
+ QMatrix4x4 m2;
+ setMatrix(m2, uniqueValues4);
+ QVERIFY(isSame(m2, uniqueValues4));
+ QVERIFY(!m2.isIdentity());
+
+ QMatrix4x4 m3;
+ setMatrixFixed(m3, uniqueValues4);
+ QVERIFY(isSame(m3, uniqueValues4));
+
+ QMatrix4x4 m4(m3);
+ QVERIFY(isSame(m4, uniqueValues4));
+
+ QMatrix4x4 m5;
+ m5 = m3;
+ QVERIFY(isSame(m5, uniqueValues4));
+
+ m5.setIdentity();
+ QVERIFY(isIdentity(m5));
+
+ QMatrix4x4 m6(uniqueValues4);
+ QVERIFY(isSame(m6, uniqueValues4));
+ qreal vals[16];
+ m6.toValueArray(vals);
+ for (int index = 0; index < 16; ++index)
+ QCOMPARE((float)(vals[index]), (float)(uniqueValues4[index]));
+
+ QMatrix4x4 m8
+ (uniqueValues4[0], uniqueValues4[1], uniqueValues4[2], uniqueValues4[3],
+ uniqueValues4[4], uniqueValues4[5], uniqueValues4[6], uniqueValues4[7],
+ uniqueValues4[8], uniqueValues4[9], uniqueValues4[10], uniqueValues4[11],
+ uniqueValues4[12], uniqueValues4[13], uniqueValues4[14], uniqueValues4[15]);
+ QVERIFY(isSame(m8, uniqueValues4));
+}
+
+// Test the creation of QMatrix4x3 objects in various ways:
+// construct, copy, and modify.
+void tst_QMatrix::create4x3()
+{
+ QMatrix4x3 m1;
+ QVERIFY(isIdentity(m1));
+ QVERIFY(m1.isIdentity());
+
+ QMatrix4x3 m2;
+ setMatrix(m2, uniqueValues4x3);
+ QVERIFY(isSame(m2, uniqueValues4x3));
+ QVERIFY(!m2.isIdentity());
+
+ QMatrix4x3 m3;
+ setMatrixFixed(m3, uniqueValues4x3);
+ QVERIFY(isSame(m3, uniqueValues4x3));
+
+ QMatrix4x3 m4(m3);
+ QVERIFY(isSame(m4, uniqueValues4x3));
+
+ QMatrix4x3 m5;
+ m5 = m3;
+ QVERIFY(isSame(m5, uniqueValues4x3));
+
+ m5.setIdentity();
+ QVERIFY(isIdentity(m5));
+
+ QMatrix4x3 m6(uniqueValues4x3);
+ QVERIFY(isSame(m6, uniqueValues4x3));
+ qreal vals[12];
+ m6.toValueArray(vals);
+ for (int index = 0; index < 12; ++index)
+ QCOMPARE((float)(vals[index]), (float)(uniqueValues4x3[index]));
+}
+
+// Test isIdentity() for 2x2 matrices.
+void tst_QMatrix::isIdentity2x2()
+{
+ for (int i = 0; i < 2 * 2; ++i) {
+ QMatrix2x2 m;
+ QVERIFY(m.isIdentity());
+ m.data()[i] = 42.0f;
+ QVERIFY(!m.isIdentity());
+ }
+}
+
+// Test isIdentity() for 3x3 matrices.
+void tst_QMatrix::isIdentity3x3()
+{
+ for (int i = 0; i < 3 * 3; ++i) {
+ QMatrix3x3 m;
+ QVERIFY(m.isIdentity());
+ m.data()[i] = 42.0f;
+ QVERIFY(!m.isIdentity());
+ }
+}
+
+// Test isIdentity() for 4x4 matrices.
+void tst_QMatrix::isIdentity4x4()
+{
+ for (int i = 0; i < 4 * 4; ++i) {
+ QMatrix4x4 m;
+ QVERIFY(m.isIdentity());
+ m.data()[i] = 42.0f;
+ QVERIFY(!m.isIdentity());
+ }
+
+ // Force the "Identity" flag bit to be lost and check again.
+ QMatrix4x4 m2;
+ m2.data()[0] = 1.0f;
+ QVERIFY(m2.isIdentity());
+}
+
+// Test isIdentity() for 4x3 matrices.
+void tst_QMatrix::isIdentity4x3()
+{
+ for (int i = 0; i < 4 * 3; ++i) {
+ QMatrix4x3 m;
+ QVERIFY(m.isIdentity());
+ m.data()[i] = 42.0f;
+ QVERIFY(!m.isIdentity());
+ }
+}
+
+// Test 2x2 matrix comparisons.
+void tst_QMatrix::compare2x2()
+{
+ QMatrix2x2 m1(uniqueValues2);
+ QMatrix2x2 m2(uniqueValues2);
+ QMatrix2x2 m3(transposedValues2);
+
+ QVERIFY(m1 == m2);
+ QVERIFY(!(m1 != m2));
+ QVERIFY(m1 != m3);
+ QVERIFY(!(m1 == m3));
+}
+
+// Test 3x3 matrix comparisons.
+void tst_QMatrix::compare3x3()
+{
+ QMatrix3x3 m1(uniqueValues3);
+ QMatrix3x3 m2(uniqueValues3);
+ QMatrix3x3 m3(transposedValues3);
+
+ QVERIFY(m1 == m2);
+ QVERIFY(!(m1 != m2));
+ QVERIFY(m1 != m3);
+ QVERIFY(!(m1 == m3));
+}
+
+// Test 4x4 matrix comparisons.
+void tst_QMatrix::compare4x4()
+{
+ QMatrix4x4 m1(uniqueValues4);
+ QMatrix4x4 m2(uniqueValues4);
+ QMatrix4x4 m3(transposedValues4);
+
+ QVERIFY(m1 == m2);
+ QVERIFY(!(m1 != m2));
+ QVERIFY(m1 != m3);
+ QVERIFY(!(m1 == m3));
+}
+
+// Test 4x3 matrix comparisons.
+void tst_QMatrix::compare4x3()
+{
+ QMatrix4x3 m1(uniqueValues4x3);
+ QMatrix4x3 m2(uniqueValues4x3);
+ QMatrix4x3 m3(transposedValues3x4);
+
+ QVERIFY(m1 == m2);
+ QVERIFY(!(m1 != m2));
+ QVERIFY(m1 != m3);
+ QVERIFY(!(m1 == m3));
+}
+
+// Test matrix 2x2 transpose operations.
+void tst_QMatrix::transposed2x2()
+{
+ // Transposing the identity should result in the identity.
+ QMatrix2x2 m1;
+ QMatrix2x2 m2 = m1.transposed();
+ QVERIFY(isIdentity(m2));
+
+ // Transpose a more interesting matrix that allows us to track
+ // exactly where each source element ends up.
+ QMatrix2x2 m3(uniqueValues2);
+ QMatrix2x2 m4 = m3.transposed();
+ QVERIFY(isSame(m4, transposedValues2));
+
+ // Transpose in-place, just to check that the compiler is sane.
+ m3 = m3.transposed();
+ QVERIFY(isSame(m3, transposedValues2));
+}
+
+// Test matrix 3x3 transpose operations.
+void tst_QMatrix::transposed3x3()
+{
+ // Transposing the identity should result in the identity.
+ QMatrix3x3 m1;
+ QMatrix3x3 m2 = m1.transposed();
+ QVERIFY(isIdentity(m2));
+
+ // Transpose a more interesting matrix that allows us to track
+ // exactly where each source element ends up.
+ QMatrix3x3 m3(uniqueValues3);
+ QMatrix3x3 m4 = m3.transposed();
+ QVERIFY(isSame(m4, transposedValues3));
+
+ // Transpose in-place, just to check that the compiler is sane.
+ m3 = m3.transposed();
+ QVERIFY(isSame(m3, transposedValues3));
+}
+
+// Test matrix 4x4 transpose operations.
+void tst_QMatrix::transposed4x4()
+{
+ // Transposing the identity should result in the identity.
+ QMatrix4x4 m1;
+ QMatrix4x4 m2 = m1.transposed();
+ QVERIFY(isIdentity(m2));
+
+ // Transpose a more interesting matrix that allows us to track
+ // exactly where each source element ends up.
+ QMatrix4x4 m3(uniqueValues4);
+ QMatrix4x4 m4 = m3.transposed();
+ QVERIFY(isSame(m4, transposedValues4));
+
+ // Transpose in-place, just to check that the compiler is sane.
+ m3 = m3.transposed();
+ QVERIFY(isSame(m3, transposedValues4));
+}
+
+// Test matrix 4x3 transpose operations.
+void tst_QMatrix::transposed4x3()
+{
+ QMatrix4x3 m3(uniqueValues4x3);
+ QMatrix3x4 m4 = m3.transposed();
+ qreal values[12];
+ m4.toValueArray(values);
+ for (int index = 0; index < 12; ++index)
+ QCOMPARE(values[index], transposedValues3x4[index]);
+}
+
+// Test matrix addition for 2x2 matrices.
+void tst_QMatrix::add2x2_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues2 << (void *)nullValues2 << (void *)nullValues2;
+
+ QTest::newRow("identity/null")
+ << (void *)identityValues2 << (void *)nullValues2 << (void *)identityValues2;
+
+ QTest::newRow("identity/identity")
+ << (void *)identityValues2 << (void *)identityValues2 << (void *)doubleIdentity2;
+
+ static qreal const sumValues[16] =
+ {2.0f, 7.0f,
+ 7.0f, 12.0f};
+ QTest::newRow("unique")
+ << (void *)uniqueValues2 << (void *)transposedValues2 << (void *)sumValues;
+}
+void tst_QMatrix::add2x2()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix2x2 m1((const qreal *)m1Values);
+ QMatrix2x2 m2((const qreal *)m2Values);
+
+ QMatrix2x2 m4(m1);
+ m4 += m2;
+ QVERIFY(isSame(m4, (const qreal *)m3Values));
+
+ QMatrix2x2 m5;
+ m5 = m1 + m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix addition for 3x3 matrices.
+void tst_QMatrix::add3x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues3 << (void *)nullValues3 << (void *)nullValues3;
+
+ QTest::newRow("identity/null")
+ << (void *)identityValues3 << (void *)nullValues3 << (void *)identityValues3;
+
+ QTest::newRow("identity/identity")
+ << (void *)identityValues3 << (void *)identityValues3 << (void *)doubleIdentity3;
+
+ static qreal const sumValues[16] =
+ {2.0f, 7.0f, 12.0f,
+ 7.0f, 12.0f, 17.0f,
+ 12.0f, 17.0f, 22.0f};
+ QTest::newRow("unique")
+ << (void *)uniqueValues3 << (void *)transposedValues3 << (void *)sumValues;
+}
+void tst_QMatrix::add3x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix3x3 m1((const qreal *)m1Values);
+ QMatrix3x3 m2((const qreal *)m2Values);
+
+ QMatrix3x3 m4(m1);
+ m4 += m2;
+ QVERIFY(isSame(m4, (const qreal *)m3Values));
+
+ QMatrix3x3 m5;
+ m5 = m1 + m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix addition for 4x4 matrices.
+void tst_QMatrix::add4x4_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4 << (void *)nullValues4 << (void *)nullValues4;
+
+ QTest::newRow("identity/null")
+ << (void *)identityValues4 << (void *)nullValues4 << (void *)identityValues4;
+
+ QTest::newRow("identity/identity")
+ << (void *)identityValues4 << (void *)identityValues4 << (void *)doubleIdentity4;
+
+ static qreal const sumValues[16] =
+ {2.0f, 7.0f, 12.0f, 17.0f,
+ 7.0f, 12.0f, 17.0f, 22.0f,
+ 12.0f, 17.0f, 22.0f, 27.0f,
+ 17.0f, 22.0f, 27.0f, 32.0f};
+ QTest::newRow("unique")
+ << (void *)uniqueValues4 << (void *)transposedValues4 << (void *)sumValues;
+}
+void tst_QMatrix::add4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x4 m1((const qreal *)m1Values);
+ QMatrix4x4 m2((const qreal *)m2Values);
+
+ QMatrix4x4 m4(m1);
+ m4 += m2;
+ QVERIFY(isSame(m4, (const qreal *)m3Values));
+
+ QMatrix4x4 m5;
+ m5 = m1 + m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix addition for 4x3 matrices.
+void tst_QMatrix::add4x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4x3 << (void *)nullValues4x3 << (void *)nullValues4x3;
+
+ QTest::newRow("identity/null")
+ << (void *)identityValues4x3 << (void *)nullValues4x3 << (void *)identityValues4x3;
+
+ QTest::newRow("identity/identity")
+ << (void *)identityValues4x3 << (void *)identityValues4x3 << (void *)doubleIdentity4x3;
+
+ static qreal const sumValues[16] =
+ {2.0f, 7.0f, 12.0f, 6.0f,
+ 11.0f, 16.0f, 10.0f, 15.0f,
+ 20.0f, 14.0f, 19.0f, 24.0f};
+ QTest::newRow("unique")
+ << (void *)uniqueValues4x3 << (void *)transposedValues3x4 << (void *)sumValues;
+}
+void tst_QMatrix::add4x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x3 m1((const qreal *)m1Values);
+ QMatrix4x3 m2((const qreal *)m2Values);
+
+ QMatrix4x3 m4(m1);
+ m4 += m2;
+ QVERIFY(isSame(m4, (const qreal *)m3Values));
+
+ QMatrix4x3 m5;
+ m5 = m1 + m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix subtraction for 2x2 matrices.
+void tst_QMatrix::subtract2x2_data()
+{
+ // Use the same test cases as the add test.
+ add2x2_data();
+}
+void tst_QMatrix::subtract2x2()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix2x2 m1((const qreal *)m1Values);
+ QMatrix2x2 m2((const qreal *)m2Values);
+ QMatrix2x2 m3((const qreal *)m3Values);
+
+ QMatrix2x2 m4(m3);
+ m4 -= m1;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix2x2 m5;
+ m5 = m3 - m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+
+ QMatrix2x2 m6(m3);
+ m6 -= m2;
+ QVERIFY(isSame(m6, (const qreal *)m1Values));
+
+ QMatrix2x2 m7;
+ m7 = m3 - m2;
+ QVERIFY(isSame(m7, (const qreal *)m1Values));
+}
+
+// Test matrix subtraction for 3x3 matrices.
+void tst_QMatrix::subtract3x3_data()
+{
+ // Use the same test cases as the add test.
+ add3x3_data();
+}
+void tst_QMatrix::subtract3x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix3x3 m1((const qreal *)m1Values);
+ QMatrix3x3 m2((const qreal *)m2Values);
+ QMatrix3x3 m3((const qreal *)m3Values);
+
+ QMatrix3x3 m4(m3);
+ m4 -= m1;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix3x3 m5;
+ m5 = m3 - m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+
+ QMatrix3x3 m6(m3);
+ m6 -= m2;
+ QVERIFY(isSame(m6, (const qreal *)m1Values));
+
+ QMatrix3x3 m7;
+ m7 = m3 - m2;
+ QVERIFY(isSame(m7, (const qreal *)m1Values));
+}
+
+// Test matrix subtraction for 4x4 matrices.
+void tst_QMatrix::subtract4x4_data()
+{
+ // Use the same test cases as the add test.
+ add4x4_data();
+}
+void tst_QMatrix::subtract4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x4 m1((const qreal *)m1Values);
+ QMatrix4x4 m2((const qreal *)m2Values);
+ QMatrix4x4 m3((const qreal *)m3Values);
+
+ QMatrix4x4 m4(m3);
+ m4 -= m1;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix4x4 m5;
+ m5 = m3 - m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+
+ QMatrix4x4 m6(m3);
+ m6 -= m2;
+ QVERIFY(isSame(m6, (const qreal *)m1Values));
+
+ QMatrix4x4 m7;
+ m7 = m3 - m2;
+ QVERIFY(isSame(m7, (const qreal *)m1Values));
+}
+
+// Test matrix subtraction for 4x3 matrices.
+void tst_QMatrix::subtract4x3_data()
+{
+ // Use the same test cases as the add test.
+ add4x3_data();
+}
+void tst_QMatrix::subtract4x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x3 m1((const qreal *)m1Values);
+ QMatrix4x3 m2((const qreal *)m2Values);
+ QMatrix4x3 m3((const qreal *)m3Values);
+
+ QMatrix4x3 m4(m3);
+ m4 -= m1;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix4x3 m5;
+ m5 = m3 - m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+
+ QMatrix4x3 m6(m3);
+ m6 -= m2;
+ QVERIFY(isSame(m6, (const qreal *)m1Values));
+
+ QMatrix4x3 m7;
+ m7 = m3 - m2;
+ QVERIFY(isSame(m7, (const qreal *)m1Values));
+}
+
+// Test matrix multiplication for 2x2 matrices.
+void tst_QMatrix::multiply2x2_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues2 << (void *)nullValues2 << (void *)nullValues2;
+
+ QTest::newRow("null/unique")
+ << (void *)nullValues2 << (void *)uniqueValues2 << (void *)nullValues2;
+
+ QTest::newRow("unique/null")
+ << (void *)uniqueValues2 << (void *)nullValues2 << (void *)nullValues2;
+
+ QTest::newRow("unique/identity")
+ << (void *)uniqueValues2 << (void *)identityValues2 << (void *)uniqueValues2;
+
+ QTest::newRow("identity/unique")
+ << (void *)identityValues2 << (void *)uniqueValues2 << (void *)uniqueValues2;
+
+ static qreal uniqueResult[4];
+ for (int row = 0; row < 2; ++row) {
+ for (int col = 0; col < 2; ++col) {
+ qreal sum = 0.0f;
+ for (int j = 0; j < 2; ++j)
+ sum += uniqueValues2[row * 2 + j] * transposedValues2[j * 2 + col];
+ uniqueResult[row * 2 + col] = sum;
+ }
+ }
+
+ QTest::newRow("unique/transposed")
+ << (void *)uniqueValues2 << (void *)transposedValues2 << (void *)uniqueResult;
+}
+void tst_QMatrix::multiply2x2()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix2x2 m1((const qreal *)m1Values);
+ QMatrix2x2 m2((const qreal *)m2Values);
+
+ QMatrix2x2 m5;
+ m5 = m1 * m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix multiplication for 3x3 matrices.
+void tst_QMatrix::multiply3x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues3 << (void *)nullValues3 << (void *)nullValues3;
+
+ QTest::newRow("null/unique")
+ << (void *)nullValues3 << (void *)uniqueValues3 << (void *)nullValues3;
+
+ QTest::newRow("unique/null")
+ << (void *)uniqueValues3 << (void *)nullValues3 << (void *)nullValues3;
+
+ QTest::newRow("unique/identity")
+ << (void *)uniqueValues3 << (void *)identityValues3 << (void *)uniqueValues3;
+
+ QTest::newRow("identity/unique")
+ << (void *)identityValues3 << (void *)uniqueValues3 << (void *)uniqueValues3;
+
+ static qreal uniqueResult[9];
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 3; ++col) {
+ qreal sum = 0.0f;
+ for (int j = 0; j < 3; ++j)
+ sum += uniqueValues3[row * 3 + j] * transposedValues3[j * 3 + col];
+ uniqueResult[row * 3 + col] = sum;
+ }
+ }
+
+ QTest::newRow("unique/transposed")
+ << (void *)uniqueValues3 << (void *)transposedValues3 << (void *)uniqueResult;
+}
+void tst_QMatrix::multiply3x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix3x3 m1((const qreal *)m1Values);
+ QMatrix3x3 m2((const qreal *)m2Values);
+
+ QMatrix3x3 m5;
+ m5 = m1 * m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix multiplication for 4x4 matrices.
+void tst_QMatrix::multiply4x4_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4 << (void *)nullValues4 << (void *)nullValues4;
+
+ QTest::newRow("null/unique")
+ << (void *)nullValues4 << (void *)uniqueValues4 << (void *)nullValues4;
+
+ QTest::newRow("unique/null")
+ << (void *)uniqueValues4 << (void *)nullValues4 << (void *)nullValues4;
+
+ QTest::newRow("unique/identity")
+ << (void *)uniqueValues4 << (void *)identityValues4 << (void *)uniqueValues4;
+
+ QTest::newRow("identity/unique")
+ << (void *)identityValues4 << (void *)uniqueValues4 << (void *)uniqueValues4;
+
+ static qreal uniqueResult[16];
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ qreal sum = 0.0f;
+ for (int j = 0; j < 4; ++j)
+ sum += uniqueValues4[row * 4 + j] * transposedValues4[j * 4 + col];
+ uniqueResult[row * 4 + col] = sum;
+ }
+ }
+
+ QTest::newRow("unique/transposed")
+ << (void *)uniqueValues4 << (void *)transposedValues4 << (void *)uniqueResult;
+}
+void tst_QMatrix::multiply4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x4 m1((const qreal *)m1Values);
+ QMatrix4x4 m2((const qreal *)m2Values);
+
+ QMatrix4x4 m4;
+ m4 = m1;
+ m4 *= m2;
+ QVERIFY(isSame(m4, (const qreal *)m3Values));
+
+ QMatrix4x4 m5;
+ m5 = m1 * m2;
+ QVERIFY(isSame(m5, (const qreal *)m3Values));
+}
+
+// Test matrix multiplication for 4x3 matrices.
+void tst_QMatrix::multiply4x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<void *>("m3Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4x3 << (void *)nullValues4x3 << (void *)nullValues3;
+
+ QTest::newRow("null/unique")
+ << (void *)nullValues4x3 << (void *)uniqueValues4x3 << (void *)nullValues3;
+
+ QTest::newRow("unique/null")
+ << (void *)uniqueValues4x3 << (void *)nullValues4x3 << (void *)nullValues3;
+
+ static qreal uniqueResult[9];
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 3; ++col) {
+ qreal sum = 0.0f;
+ for (int j = 0; j < 4; ++j)
+ sum += uniqueValues4x3[row * 4 + j] * transposedValues3x4[j * 3 + col];
+ uniqueResult[row * 3 + col] = sum;
+ }
+ }
+
+ QTest::newRow("unique/transposed")
+ << (void *)uniqueValues4x3 << (void *)transposedValues3x4 << (void *)uniqueResult;
+}
+void tst_QMatrix::multiply4x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(void *, m3Values);
+
+ QMatrix4x3 m1((const qreal *)m1Values);
+ QMatrix3x4 m2((const qreal *)m2Values);
+
+ QGenericMatrix<3, 3, qreal, float> m4;
+ m4 = m1 * m2;
+ qreal values[9];
+ m4.toValueArray(values);
+ for (int index = 0; index < 9; ++index)
+ QCOMPARE(values[index], ((const qreal *)m3Values)[index]);
+}
+
+// Test matrix multiplication by a factor for 2x2 matrices.
+void tst_QMatrix::multiplyFactor2x2_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<void *>("m2Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues2 << (qreal)1.0f << (void *)nullValues2;
+
+ QTest::newRow("double identity")
+ << (void *)identityValues2 << (qreal)2.0f << (void *)doubleIdentity2;
+
+ static qreal const values[16] =
+ {1.0f, 2.0f,
+ 5.0f, 6.0f};
+ static qreal const doubleValues[16] =
+ {2.0f, 4.0f,
+ 10.0f, 12.0f};
+ static qreal const negDoubleValues[16] =
+ {-2.0f, -4.0f,
+ -10.0f, -12.0f};
+
+ QTest::newRow("unique")
+ << (void *)values << (qreal)2.0f << (void *)doubleValues;
+
+ QTest::newRow("neg")
+ << (void *)values << (qreal)-2.0f << (void *)negDoubleValues;
+
+ QTest::newRow("zero")
+ << (void *)values << (qreal)0.0f << (void *)nullValues4;
+}
+void tst_QMatrix::multiplyFactor2x2()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ QMatrix2x2 m1((const qreal *)m1Values);
+
+ QMatrix2x2 m3;
+ m3 = m1;
+ m3 *= factor;
+ QVERIFY(isSame(m3, (const qreal *)m2Values));
+
+ QMatrix2x2 m4;
+ m4 = m1 * factor;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix2x2 m5;
+ m5 = factor * m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+}
+
+// Test matrix multiplication by a factor for 3x3 matrices.
+void tst_QMatrix::multiplyFactor3x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<void *>("m2Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues3 << (qreal)1.0f << (void *)nullValues3;
+
+ QTest::newRow("double identity")
+ << (void *)identityValues3 << (qreal)2.0f << (void *)doubleIdentity3;
+
+ static qreal const values[16] =
+ {1.0f, 2.0f, 3.0f,
+ 5.0f, 6.0f, 7.0f,
+ 9.0f, 10.0f, 11.0f};
+ static qreal const doubleValues[16] =
+ {2.0f, 4.0f, 6.0f,
+ 10.0f, 12.0f, 14.0f,
+ 18.0f, 20.0f, 22.0f};
+ static qreal const negDoubleValues[16] =
+ {-2.0f, -4.0f, -6.0f,
+ -10.0f, -12.0f, -14.0f,
+ -18.0f, -20.0f, -22.0f};
+
+ QTest::newRow("unique")
+ << (void *)values << (qreal)2.0f << (void *)doubleValues;
+
+ QTest::newRow("neg")
+ << (void *)values << (qreal)-2.0f << (void *)negDoubleValues;
+
+ QTest::newRow("zero")
+ << (void *)values << (qreal)0.0f << (void *)nullValues4;
+}
+void tst_QMatrix::multiplyFactor3x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ QMatrix3x3 m1((const qreal *)m1Values);
+
+ QMatrix3x3 m3;
+ m3 = m1;
+ m3 *= factor;
+ QVERIFY(isSame(m3, (const qreal *)m2Values));
+
+ QMatrix3x3 m4;
+ m4 = m1 * factor;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix3x3 m5;
+ m5 = factor * m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+}
+
+// Test matrix multiplication by a factor for 4x4 matrices.
+void tst_QMatrix::multiplyFactor4x4_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<void *>("m2Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4 << (qreal)1.0f << (void *)nullValues4;
+
+ QTest::newRow("double identity")
+ << (void *)identityValues4 << (qreal)2.0f << (void *)doubleIdentity4;
+
+ static qreal const values[16] =
+ {1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f,
+ 13.0f, 14.0f, 15.0f, 16.0f};
+ static qreal const doubleValues[16] =
+ {2.0f, 4.0f, 6.0f, 8.0f,
+ 10.0f, 12.0f, 14.0f, 16.0f,
+ 18.0f, 20.0f, 22.0f, 24.0f,
+ 26.0f, 28.0f, 30.0f, 32.0f};
+ static qreal const negDoubleValues[16] =
+ {-2.0f, -4.0f, -6.0f, -8.0f,
+ -10.0f, -12.0f, -14.0f, -16.0f,
+ -18.0f, -20.0f, -22.0f, -24.0f,
+ -26.0f, -28.0f, -30.0f, -32.0f};
+
+ QTest::newRow("unique")
+ << (void *)values << (qreal)2.0f << (void *)doubleValues;
+
+ QTest::newRow("neg")
+ << (void *)values << (qreal)-2.0f << (void *)negDoubleValues;
+
+ QTest::newRow("zero")
+ << (void *)values << (qreal)0.0f << (void *)nullValues4;
+}
+void tst_QMatrix::multiplyFactor4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ QMatrix4x4 m1((const qreal *)m1Values);
+
+ QMatrix4x4 m3;
+ m3 = m1;
+ m3 *= factor;
+ QVERIFY(isSame(m3, (const qreal *)m2Values));
+
+ QMatrix4x4 m4;
+ m4 = m1 * factor;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix4x4 m5;
+ m5 = factor * m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+}
+
+// Test matrix multiplication by a factor for 4x3 matrices.
+void tst_QMatrix::multiplyFactor4x3_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<void *>("m2Values");
+
+ QTest::newRow("null")
+ << (void *)nullValues4x3 << (qreal)1.0f << (void *)nullValues4x3;
+
+ QTest::newRow("double identity")
+ << (void *)identityValues4x3 << (qreal)2.0f << (void *)doubleIdentity4x3;
+
+ static qreal const values[12] =
+ {1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f};
+ static qreal const doubleValues[12] =
+ {2.0f, 4.0f, 6.0f, 8.0f,
+ 10.0f, 12.0f, 14.0f, 16.0f,
+ 18.0f, 20.0f, 22.0f, 24.0f};
+ static qreal const negDoubleValues[12] =
+ {-2.0f, -4.0f, -6.0f, -8.0f,
+ -10.0f, -12.0f, -14.0f, -16.0f,
+ -18.0f, -20.0f, -22.0f, -24.0f};
+
+ QTest::newRow("unique")
+ << (void *)values << (qreal)2.0f << (void *)doubleValues;
+
+ QTest::newRow("neg")
+ << (void *)values << (qreal)-2.0f << (void *)negDoubleValues;
+
+ QTest::newRow("zero")
+ << (void *)values << (qreal)0.0f << (void *)nullValues4x3;
+}
+void tst_QMatrix::multiplyFactor4x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ QMatrix4x3 m1((const qreal *)m1Values);
+
+ QMatrix4x3 m3;
+ m3 = m1;
+ m3 *= factor;
+ QVERIFY(isSame(m3, (const qreal *)m2Values));
+
+ QMatrix4x3 m4;
+ m4 = m1 * factor;
+ QVERIFY(isSame(m4, (const qreal *)m2Values));
+
+ QMatrix4x3 m5;
+ m5 = factor * m1;
+ QVERIFY(isSame(m5, (const qreal *)m2Values));
+}
+
+// Test matrix division by a factor for 2x2 matrices.
+void tst_QMatrix::divideFactor2x2_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor2x2_data();
+}
+void tst_QMatrix::divideFactor2x2()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ if (factor == 0.0f)
+ return;
+
+ QMatrix2x2 m2((const qreal *)m2Values);
+
+ QMatrix2x2 m3;
+ m3 = m2;
+ m3 /= factor;
+ QVERIFY(isSame(m3, (const qreal *)m1Values));
+
+ QMatrix2x2 m4;
+ m4 = m2 / factor;
+ QVERIFY(isSame(m4, (const qreal *)m1Values));
+}
+
+// Test matrix division by a factor for 3x3 matrices.
+void tst_QMatrix::divideFactor3x3_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor3x3_data();
+}
+void tst_QMatrix::divideFactor3x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ if (factor == 0.0f)
+ return;
+
+ QMatrix3x3 m2((const qreal *)m2Values);
+
+ QMatrix3x3 m3;
+ m3 = m2;
+ m3 /= factor;
+ QVERIFY(isSame(m3, (const qreal *)m1Values));
+
+ QMatrix3x3 m4;
+ m4 = m2 / factor;
+ QVERIFY(isSame(m4, (const qreal *)m1Values));
+}
+
+// Test matrix division by a factor for 4x4 matrices.
+void tst_QMatrix::divideFactor4x4_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor4x4_data();
+}
+void tst_QMatrix::divideFactor4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ if (factor == 0.0f)
+ return;
+
+ QMatrix4x4 m2((const qreal *)m2Values);
+
+ QMatrix4x4 m3;
+ m3 = m2;
+ m3 /= factor;
+ QVERIFY(isSame(m3, (const qreal *)m1Values));
+
+ QMatrix4x4 m4;
+ m4 = m2 / factor;
+ QVERIFY(isSame(m4, (const qreal *)m1Values));
+}
+
+// Test matrix division by a factor for 4x3 matrices.
+void tst_QMatrix::divideFactor4x3_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor4x3_data();
+}
+void tst_QMatrix::divideFactor4x3()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(qreal, factor);
+ QFETCH(void *, m2Values);
+
+ if (factor == 0.0f)
+ return;
+
+ QMatrix4x3 m2((const qreal *)m2Values);
+
+ QMatrix4x3 m3;
+ m3 = m2;
+ m3 /= factor;
+ QVERIFY(isSame(m3, (const qreal *)m1Values));
+
+ QMatrix4x3 m4;
+ m4 = m2 / factor;
+ QVERIFY(isSame(m4, (const qreal *)m1Values));
+}
+
+// Test matrix negation for 2x2 matrices.
+void tst_QMatrix::negate2x2_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor2x2_data();
+}
+void tst_QMatrix::negate2x2()
+{
+ QFETCH(void *, m1Values);
+
+ const qreal *values = (const qreal *)m1Values;
+
+ QMatrix2x2 m1(values);
+
+ qreal negated[4];
+ for (int index = 0; index < 4; ++index)
+ negated[index] = -values[index];
+
+ QMatrix2x2 m2;
+ m2 = -m1;
+ QVERIFY(isSame(m2, negated));
+}
+
+// Test matrix negation for 3x3 matrices.
+void tst_QMatrix::negate3x3_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor3x3_data();
+}
+void tst_QMatrix::negate3x3()
+{
+ QFETCH(void *, m1Values);
+
+ const qreal *values = (const qreal *)m1Values;
+
+ QMatrix3x3 m1(values);
+
+ qreal negated[9];
+ for (int index = 0; index < 9; ++index)
+ negated[index] = -values[index];
+
+ QMatrix3x3 m2;
+ m2 = -m1;
+ QVERIFY(isSame(m2, negated));
+}
+
+// Test matrix negation for 4x4 matrices.
+void tst_QMatrix::negate4x4_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor4x4_data();
+}
+void tst_QMatrix::negate4x4()
+{
+ QFETCH(void *, m1Values);
+
+ const qreal *values = (const qreal *)m1Values;
+
+ QMatrix4x4 m1(values);
+
+ qreal negated[16];
+ for (int index = 0; index < 16; ++index)
+ negated[index] = -values[index];
+
+ QMatrix4x4 m2;
+ m2 = -m1;
+ QVERIFY(isSame(m2, negated));
+}
+
+// Test matrix negation for 4x3 matrices.
+void tst_QMatrix::negate4x3_data()
+{
+ // Use the same test cases as the multiplyFactor test.
+ multiplyFactor4x3_data();
+}
+void tst_QMatrix::negate4x3()
+{
+ QFETCH(void *, m1Values);
+
+ const qreal *values = (const qreal *)m1Values;
+
+ QMatrix4x3 m1(values);
+
+ qreal negated[12];
+ for (int index = 0; index < 12; ++index)
+ negated[index] = -values[index];
+
+ QMatrix4x3 m2;
+ m2 = -m1;
+ QVERIFY(isSame(m2, negated));
+}
+
+// Matrix inverted. This is a more straight-forward implementation
+// of the algorithm at http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q24
+// than the optimized version in the QMatrix4x4 code. Hopefully it is
+// easier to verify that this version is the same as the reference.
+
+struct Matrix3
+{
+ qreal v[9];
+};
+struct Matrix4
+{
+ qreal v[16];
+};
+
+static qreal m3Determinant(const Matrix3& m)
+{
+ return m.v[0] * (m.v[4] * m.v[8] - m.v[7] * m.v[5]) -
+ m.v[1] * (m.v[3] * m.v[8] - m.v[6] * m.v[5]) +
+ m.v[2] * (m.v[3] * m.v[7] - m.v[6] * m.v[4]);
+}
+
+static bool m3Inverse(const Matrix3& min, Matrix3& mout)
+{
+ qreal det = m3Determinant(min);
+ if (det == 0.0f)
+ return false;
+ mout.v[0] = (min.v[4] * min.v[8] - min.v[5] * min.v[7]) / det;
+ mout.v[1] = -(min.v[1] * min.v[8] - min.v[2] * min.v[7]) / det;
+ mout.v[2] = (min.v[1] * min.v[5] - min.v[4] * min.v[2]) / det;
+ mout.v[3] = -(min.v[3] * min.v[8] - min.v[5] * min.v[6]) / det;
+ mout.v[4] = (min.v[0] * min.v[8] - min.v[6] * min.v[2]) / det;
+ mout.v[5] = -(min.v[0] * min.v[5] - min.v[3] * min.v[2]) / det;
+ mout.v[6] = (min.v[3] * min.v[7] - min.v[6] * min.v[4]) / det;
+ mout.v[7] = -(min.v[0] * min.v[7] - min.v[6] * min.v[1]) / det;
+ mout.v[8] = (min.v[0] * min.v[4] - min.v[1] * min.v[3]) / det;
+ return true;
+}
+
+static void m3Transpose(Matrix3& m)
+{
+ qSwap(m.v[1], m.v[3]);
+ qSwap(m.v[2], m.v[6]);
+ qSwap(m.v[5], m.v[7]);
+}
+
+static void m4Submatrix(const Matrix4& min, Matrix3& mout, int i, int j)
+{
+ for (int di = 0; di < 3; ++di) {
+ for (int dj = 0; dj < 3; ++dj) {
+ int si = di + ((di >= i) ? 1 : 0);
+ int sj = dj + ((dj >= j) ? 1 : 0);
+ mout.v[di * 3 + dj] = min.v[si * 4 + sj];
+ }
+ }
+}
+
+static qreal m4Determinant(const Matrix4& m)
+{
+ qreal det;
+ qreal result = 0.0f;
+ qreal i = 1.0f;
+ Matrix3 msub;
+ for (int n = 0; n < 4; ++n, i *= -1.0f) {
+ m4Submatrix(m, msub, 0, n);
+ det = m3Determinant(msub);
+ result += m.v[n] * det * i;
+ }
+ return result;
+}
+
+static void m4Inverse(const Matrix4& min, Matrix4& mout)
+{
+ qreal det = m4Determinant(min);
+ Matrix3 msub;
+ for (int i = 0; i < 4; ++i) {
+ for (int j = 0; j < 4; ++j) {
+ qreal sign = 1.0f - ((i + j) % 2) * 2.0f;
+ m4Submatrix(min, msub, i, j);
+ mout.v[i + j * 4] = (m3Determinant(msub) * sign) / det;
+ }
+ }
+}
+
+// Test matrix inverted for 4x4 matrices.
+void tst_QMatrix::inverted4x4_data()
+{
+ QTest::addColumn<void *>("m1Values");
+ QTest::addColumn<void *>("m2Values");
+ QTest::addColumn<bool>("invertible");
+
+ QTest::newRow("null")
+ << (void *)nullValues4 << (void *)identityValues4 << false;
+
+ QTest::newRow("identity")
+ << (void *)identityValues4 << (void *)identityValues4 << true;
+
+ QTest::newRow("unique")
+ << (void *)uniqueValues4 << (void *)identityValues4 << false;
+
+ static Matrix4 const invertible = {
+ {5.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 6.0f, 0.0f, 3.0f,
+ 0.0f, 0.0f, 7.0f, 4.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f}
+ };
+ static Matrix4 inverted;
+ m4Inverse(invertible, inverted);
+
+ QTest::newRow("invertible")
+ << (void *)invertible.v << (void *)inverted.v << true;
+
+ static Matrix4 const translate = {
+ {1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 1.0f, 0.0f, 3.0f,
+ 0.0f, 0.0f, 1.0f, 4.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f}
+ };
+ static Matrix4 const inverseTranslate = {
+ {1.0f, 0.0f, 0.0f, -2.0f,
+ 0.0f, 1.0f, 0.0f, -3.0f,
+ 0.0f, 0.0f, 1.0f, -4.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f}
+ };
+
+ QTest::newRow("translate")
+ << (void *)translate.v << (void *)inverseTranslate.v << true;
+}
+void tst_QMatrix::inverted4x4()
+{
+ QFETCH(void *, m1Values);
+ QFETCH(void *, m2Values);
+ QFETCH(bool, invertible);
+
+ QMatrix4x4 m1((const qreal *)m1Values);
+
+ if (invertible)
+ QVERIFY(m1.determinant() != 0.0f);
+ else
+ QVERIFY(m1.determinant() == 0.0f);
+
+ Matrix4 m1alt;
+ memcpy(m1alt.v, (const qreal *)m1Values, sizeof(m1alt.v));
+
+ QCOMPARE((float)(m1.determinant()), (float)(m4Determinant(m1alt)));
+
+ QMatrix4x4 m2;
+ bool inv;
+ m2 = m1.inverted(&inv);
+ QVERIFY(isSame(m2, (const qreal *)m2Values));
+
+ if (invertible) {
+ QVERIFY(inv);
+
+ Matrix4 m2alt;
+ m4Inverse(m1alt, m2alt);
+ QVERIFY(isSame(m2, m2alt.v));
+
+ QMatrix4x4 m3;
+ m3 = m1 * m2;
+ QVERIFY(isIdentity(m3));
+
+ QMatrix4x4 m4;
+ m4 = m2 * m1;
+ QVERIFY(isIdentity(m4));
+ } else {
+ QVERIFY(!inv);
+ }
+
+ // Test again, after inferring the special matrix type.
+ m1.inferSpecialType();
+ m2 = m1.inverted(&inv);
+ QVERIFY(isSame(m2, (const qreal *)m2Values));
+ QCOMPARE(inv, invertible);
+}
+
+void tst_QMatrix::orthonormalInverse4x4()
+{
+ QMatrix4x4 m1;
+ QVERIFY(matrixFuzzyCompare(m1.inverted(), m1));
+
+ QMatrix4x4 m2;
+ m2.rotate(45.0, 1.0, 0.0, 0.0);
+ m2.translate(10.0, 0.0, 0.0);
+
+ // Use inferSpecialType() to drop the internal flags that
+ // mark the matrix as orthonormal. This will force inverted()
+ // to compute m3.inverted() the long way. We can then compare
+ // the result to what the faster algorithm produces on m2.
+ QMatrix4x4 m3 = m2;
+ m3.inferSpecialType();
+ bool invertible;
+ QVERIFY(matrixFuzzyCompare(m2.inverted(&invertible), m3.inverted()));
+ QVERIFY(invertible);
+
+ QMatrix4x4 m4;
+ m4.rotate(45.0, 0.0, 1.0, 0.0);
+ QMatrix4x4 m5 = m4;
+ m5.inferSpecialType();
+ QVERIFY(matrixFuzzyCompare(m4.inverted(), m5.inverted()));
+
+ QMatrix4x4 m6;
+ m1.rotate(88, 0.0, 0.0, 1.0);
+ m1.translate(-20.0, 20.0, 15.0);
+ m1.rotate(25, 1.0, 0.0, 0.0);
+ QMatrix4x4 m7 = m6;
+ m7.inferSpecialType();
+ QVERIFY(matrixFuzzyCompare(m6.inverted(), m7.inverted()));
+}
+
+// Test the generation and use of 4x4 scale matrices.
+void tst_QMatrix::scale4x4_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<void *>("resultValues");
+
+ static const qreal nullScale[] =
+ {0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (void *)nullScale;
+
+ QTest::newRow("identity")
+ << (qreal)1.0f << (qreal)1.0f << (qreal)1.0f << (void *)identityValues4;
+
+ static const qreal doubleScale[] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 2.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("double")
+ << (qreal)2.0f << (qreal)2.0f << (qreal)2.0f << (void *)doubleScale;
+
+ static const qreal complexScale[] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 11.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, -6.5f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("complex")
+ << (qreal)2.0f << (qreal)11.0f << (qreal)-6.5f << (void *)complexScale;
+}
+void tst_QMatrix::scale4x4()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(void *, resultValues);
+
+ QMatrix4x4 result((const qreal *)resultValues);
+
+ QMatrix4x4 m1;
+ m1.scale(QVector3D(x, y, z));
+ QVERIFY(isSame(m1, (const qreal *)resultValues));
+
+ QMatrix4x4 m2;
+ m2.scale(x, y, z);
+ QVERIFY(isSame(m2, (const qreal *)resultValues));
+
+ QVector3D v1(2.0f, 3.0f, -4.0f);
+ QVector3D v2 = m1 * v1;
+ QCOMPARE(v2.x(), (qreal)(2.0f * x));
+ QCOMPARE(v2.y(), (qreal)(3.0f * y));
+ QCOMPARE(v2.z(), (qreal)(-4.0f * z));
+
+ v2 = v1 * m1;
+ QCOMPARE(v2.x(), (qreal)(2.0f * x));
+ QCOMPARE(v2.y(), (qreal)(3.0f * y));
+ QCOMPARE(v2.z(), (qreal)(-4.0f * z));
+
+ QVector4D v3(2.0f, 3.0f, -4.0f, 34.0f);
+ QVector4D v4 = m1 * v3;
+ QCOMPARE(v4.x(), (qreal)(2.0f * x));
+ QCOMPARE(v4.y(), (qreal)(3.0f * y));
+ QCOMPARE(v4.z(), (qreal)(-4.0f * z));
+ QCOMPARE(v4.w(), (qreal)34.0f);
+
+ v4 = v3 * m1;
+ QCOMPARE(v4.x(), (qreal)(2.0f * x));
+ QCOMPARE(v4.y(), (qreal)(3.0f * y));
+ QCOMPARE(v4.z(), (qreal)(-4.0f * z));
+ QCOMPARE(v4.w(), (qreal)34.0f);
+
+ QPoint p1(2, 3);
+ QPoint p2 = m1 * p1;
+ QCOMPARE(p2.x(), (int)(2.0f * x));
+ QCOMPARE(p2.y(), (int)(3.0f * y));
+
+ p2 = p1 * m1;
+ QCOMPARE(p2.x(), (int)(2.0f * x));
+ QCOMPARE(p2.y(), (int)(3.0f * y));
+
+ QPointF p3(2.0f, 3.0f);
+ QPointF p4 = m1 * p3;
+ QCOMPARE(p4.x(), (qreal)(2.0f * x));
+ QCOMPARE(p4.y(), (qreal)(3.0f * y));
+
+ p4 = p3 * m1;
+ QCOMPARE(p4.x(), (qreal)(2.0f * x));
+ QCOMPARE(p4.y(), (qreal)(3.0f * y));
+
+ QMatrix4x4 m3(uniqueValues4);
+ QMatrix4x4 m4(m3);
+ m4.scale(x, y, z);
+ QVERIFY(m4 == m3 * m1);
+
+ if (x == y && y == z) {
+ QMatrix4x4 m5;
+ m5.scale(x);
+ QVERIFY(isSame(m5, (const qreal *)resultValues));
+ }
+
+ // Test coverage when the special matrix type is unknown.
+
+ QMatrix4x4 m6;
+ m6(0, 0) = 1.0f;
+ m6.scale(QVector3D(x, y, z));
+ QVERIFY(isSame(m6, (const qreal *)resultValues));
+
+ QMatrix4x4 m7;
+ m7(0, 0) = 1.0f;
+ m7.scale(x, y, z);
+ QVERIFY(isSame(m7, (const qreal *)resultValues));
+
+ if (x == y && y == z) {
+ QMatrix4x4 m8;
+ m8(0, 0) = 1.0f;
+ m8.scale(x);
+ QVERIFY(isSame(m8, (const qreal *)resultValues));
+
+ m8.inferSpecialType();
+ m8.scale(1.0f);
+ QVERIFY(isSame(m8, (const qreal *)resultValues));
+
+ QMatrix4x4 m9;
+ m9.translate(0.0f, 0.0f, 0.0f);
+ m9.scale(x);
+ QVERIFY(isSame(m9, (const qreal *)resultValues));
+ }
+}
+
+// Test the generation and use of 4x4 translation matrices.
+void tst_QMatrix::translate4x4_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<void *>("resultValues");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (void *)identityValues4;
+
+ static const qreal identityTranslate[] =
+ {1.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 1.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f, 1.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("identity")
+ << (qreal)1.0f << (qreal)1.0f << (qreal)1.0f << (void *)identityTranslate;
+
+ static const qreal complexTranslate[] =
+ {1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 1.0f, 0.0f, 11.0f,
+ 0.0f, 0.0f, 1.0f, -6.5f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("complex")
+ << (qreal)2.0f << (qreal)11.0f << (qreal)-6.5f << (void *)complexTranslate;
+}
+void tst_QMatrix::translate4x4()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(void *, resultValues);
+
+ QMatrix4x4 result((const qreal *)resultValues);
+
+ QMatrix4x4 m1;
+ m1.translate(QVector3D(x, y, z));
+ QVERIFY(isSame(m1, (const qreal *)resultValues));
+
+ QMatrix4x4 m2;
+ m2.translate(x, y, z);
+ QVERIFY(isSame(m2, (const qreal *)resultValues));
+
+ QVector3D v1(2.0f, 3.0f, -4.0f);
+ QVector3D v2 = m1 * v1;
+ QCOMPARE(v2.x(), (qreal)(2.0f + x));
+ QCOMPARE(v2.y(), (qreal)(3.0f + y));
+ QCOMPARE(v2.z(), (qreal)(-4.0f + z));
+
+ QVector4D v3(2.0f, 3.0f, -4.0f, 1.0f);
+ QVector4D v4 = m1 * v3;
+ QCOMPARE(v4.x(), (qreal)(2.0f + x));
+ QCOMPARE(v4.y(), (qreal)(3.0f + y));
+ QCOMPARE(v4.z(), (qreal)(-4.0f + z));
+ QCOMPARE(v4.w(), (qreal)1.0f);
+
+ QVector4D v5(2.0f, 3.0f, -4.0f, 34.0f);
+ QVector4D v6 = m1 * v5;
+ QCOMPARE(v6.x(), (qreal)(2.0f + x * 34.0f));
+ QCOMPARE(v6.y(), (qreal)(3.0f + y * 34.0f));
+ QCOMPARE(v6.z(), (qreal)(-4.0f + z * 34.0f));
+ QCOMPARE(v6.w(), (qreal)34.0f);
+
+ QPoint p1(2, 3);
+ QPoint p2 = m1 * p1;
+ QCOMPARE(p2.x(), (int)(2.0f + x));
+ QCOMPARE(p2.y(), (int)(3.0f + y));
+
+ QPointF p3(2.0f, 3.0f);
+ QPointF p4 = m1 * p3;
+ QCOMPARE(p4.x(), (qreal)(2.0f + x));
+ QCOMPARE(p4.y(), (qreal)(3.0f + y));
+
+ QMatrix4x4 m3(uniqueValues4);
+ QMatrix4x4 m4(m3);
+ m4.translate(x, y, z);
+ QVERIFY(m4 == m3 * m1);
+}
+
+// Test the generation and use of 4x4 rotation matrices.
+void tst_QMatrix::rotate4x4_data()
+{
+ QTest::addColumn<qreal>("angle");
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<void *>("resultValues");
+
+ static const qreal nullRotate[] =
+ {0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("null")
+ << (qreal)90.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (void *)nullRotate;
+
+ static const qreal noRotate[] =
+ {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("zerodegrees")
+ << (qreal)0.0f
+ << (qreal)2.0f << (qreal)3.0f << (qreal)-4.0f
+ << (void *)noRotate;
+
+ static const qreal xRotate[] =
+ {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, -1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("xrotate")
+ << (qreal)90.0f
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (void *)xRotate;
+
+ static const qreal xRotateNeg[] =
+ {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("-xrotate")
+ << (qreal)90.0f
+ << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f
+ << (void *)xRotateNeg;
+
+ static const qreal yRotate[] =
+ {0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("yrotate")
+ << (qreal)90.0f
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (void *)yRotate;
+
+ static const qreal yRotateNeg[] =
+ {0.0f, 0.0f, -1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("-yrotate")
+ << (qreal)90.0f
+ << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f
+ << (void *)yRotateNeg;
+
+ static const qreal zRotate[] =
+ {0.0f, -1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("zrotate")
+ << (qreal)90.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (void *)zRotate;
+
+ static const qreal zRotateNeg[] =
+ {0.0f, 1.0f, 0.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("-zrotate")
+ << (qreal)90.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f
+ << (void *)zRotateNeg;
+
+ // Algorithm from http://en.wikipedia.org/wiki/Rotation_matrix.
+ // Deliberately different from the one in the code for cross-checking.
+ static qreal complexRotate[16];
+ qreal x = 1.0f;
+ qreal y = 2.0f;
+ qreal z = -6.0f;
+ qreal angle = -45.0f;
+ qreal c = qCos(angle * M_PI / 180.0f);
+ qreal s = qSin(angle * M_PI / 180.0f);
+ qreal len = qSqrt(x * x + y * y + z * z);
+ qreal xu = x / len;
+ qreal yu = y / len;
+ qreal zu = z / len;
+ complexRotate[0] = (qreal)((1 - xu * xu) * c + xu * xu);
+ complexRotate[1] = (qreal)(-zu * s - xu * yu * c + xu * yu);
+ complexRotate[2] = (qreal)(yu * s - xu * zu * c + xu * zu);
+ complexRotate[3] = 0;
+ complexRotate[4] = (qreal)(zu * s - xu * yu * c + xu * yu);
+ complexRotate[5] = (qreal)((1 - yu * yu) * c + yu * yu);
+ complexRotate[6] = (qreal)(-xu * s - yu * zu * c + yu * zu);
+ complexRotate[7] = 0;
+ complexRotate[8] = (qreal)(-yu * s - xu * zu * c + xu * zu);
+ complexRotate[9] = (qreal)(xu * s - yu * zu * c + yu * zu);
+ complexRotate[10] = (qreal)((1 - zu * zu) * c + zu * zu);
+ complexRotate[11] = 0;
+ complexRotate[12] = 0;
+ complexRotate[13] = 0;
+ complexRotate[14] = 0;
+ complexRotate[15] = 1;
+
+ QTest::newRow("complex")
+ << (qreal)angle
+ << (qreal)x << (qreal)y << (qreal)z
+ << (void *)complexRotate;
+}
+void tst_QMatrix::rotate4x4()
+{
+ QFETCH(qreal, angle);
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(void *, resultValues);
+
+ QMatrix4x4 m1;
+ m1.rotate(angle, QVector3D(x, y, z));
+ QVERIFY(isSame(m1, (const qreal *)resultValues));
+
+ QMatrix4x4 m2;
+ m2.rotate(angle, x, y, z);
+ QVERIFY(isSame(m2, (const qreal *)resultValues));
+
+ QMatrix4x4 m3(uniqueValues4);
+ QMatrix4x4 m4(m3);
+ m4.rotate(angle, x, y, z);
+ QVERIFY(matrixFuzzyCompare(m4, m3 * m1));
+
+ // Null vectors don't make sense for quaternion rotations.
+ if (x != 0 || y != 0 || z != 0) {
+ QMatrix4x4 m5;
+ m5.rotate(QQuaternion::fromAxisAndAngle(QVector3D(x, y, z), angle));
+ QVERIFY(isSame(m5, (const qreal *)resultValues));
+ }
+
+#define ROTATE4(xin,yin,zin,win,xout,yout,zout,wout) \
+ do { \
+ xout = ((const qreal *)resultValues)[0] * xin + \
+ ((const qreal *)resultValues)[1] * yin + \
+ ((const qreal *)resultValues)[2] * zin + \
+ ((const qreal *)resultValues)[3] * win; \
+ yout = ((const qreal *)resultValues)[4] * xin + \
+ ((const qreal *)resultValues)[5] * yin + \
+ ((const qreal *)resultValues)[6] * zin + \
+ ((const qreal *)resultValues)[7] * win; \
+ zout = ((const qreal *)resultValues)[8] * xin + \
+ ((const qreal *)resultValues)[9] * yin + \
+ ((const qreal *)resultValues)[10] * zin + \
+ ((const qreal *)resultValues)[11] * win; \
+ wout = ((const qreal *)resultValues)[12] * xin + \
+ ((const qreal *)resultValues)[13] * yin + \
+ ((const qreal *)resultValues)[14] * zin + \
+ ((const qreal *)resultValues)[15] * win; \
+ } while (0)
+
+ // Rotate various test vectors using the straight-forward approach.
+ qreal v1x, v1y, v1z, v1w;
+ ROTATE4(2.0f, 3.0f, -4.0f, 1.0f, v1x, v1y, v1z, v1w);
+ v1x /= v1w;
+ v1y /= v1w;
+ v1z /= v1w;
+ qreal v3x, v3y, v3z, v3w;
+ ROTATE4(2.0f, 3.0f, -4.0f, 1.0f, v3x, v3y, v3z, v3w);
+ qreal v5x, v5y, v5z, v5w;
+ ROTATE4(2.0f, 3.0f, -4.0f, 34.0f, v5x, v5y, v5z, v5w);
+ qreal p1x, p1y, p1z, p1w;
+ ROTATE4(2.0f, 3.0f, 0.0f, 1.0f, p1x, p1y, p1z, p1w);
+ p1x /= p1w;
+ p1y /= p1w;
+ p1z /= p1w;
+
+ QVector3D v1(2.0f, 3.0f, -4.0f);
+ QVector3D v2 = m1 * v1;
+ QVERIFY(fuzzyCompare(v2.x(), v1x));
+ QVERIFY(fuzzyCompare(v2.y(), v1y));
+ QVERIFY(fuzzyCompare(v2.z(), v1z));
+
+ QVector4D v3(2.0f, 3.0f, -4.0f, 1.0f);
+ QVector4D v4 = m1 * v3;
+ QVERIFY(fuzzyCompare(v4.x(), v3x));
+ QVERIFY(fuzzyCompare(v4.y(), v3y));
+ QVERIFY(fuzzyCompare(v4.z(), v3z));
+ QVERIFY(fuzzyCompare(v4.w(), v3w));
+
+ QVector4D v5(2.0f, 3.0f, -4.0f, 34.0f);
+ QVector4D v6 = m1 * v5;
+ QVERIFY(fuzzyCompare(v6.x(), v5x));
+ QVERIFY(fuzzyCompare(v6.y(), v5y));
+ QVERIFY(fuzzyCompare(v6.z(), v5z));
+ QVERIFY(fuzzyCompare(v6.w(), v5w));
+
+ QPoint p1(2, 3);
+ QPoint p2 = m1 * p1;
+ QCOMPARE(p2.x(), qRound(p1x));
+ QCOMPARE(p2.y(), qRound(p1y));
+
+ QPointF p3(2.0f, 3.0f);
+ QPointF p4 = m1 * p3;
+ QVERIFY(fuzzyCompare((float)(p4.x()), p1x));
+ QVERIFY(fuzzyCompare((float)(p4.y()), p1y));
+
+ if (x != 0 || y != 0 || z != 0) {
+ QQuaternion q = QQuaternion::fromAxisAndAngle(QVector3D(x, y, z), angle);
+ QVector3D vq = q.rotateVector(v1);
+ QVERIFY(fuzzyCompare(vq.x(), v1x));
+ QVERIFY(fuzzyCompare(vq.y(), v1y));
+ QVERIFY(fuzzyCompare(vq.z(), v1z));
+ }
+}
+
+static bool isSame(const QMatrix3x3& m1, const Matrix3& m2)
+{
+ for (int row = 0; row < 3; ++row) {
+ for (int col = 0; col < 3; ++col) {
+ if (!fuzzyCompare(m1(row, col), m2.v[row * 3 + col]))
+ return false;
+ }
+ }
+ return true;
+}
+
+// Test the computation of normal matrices from 4x4 transformation matrices.
+void tst_QMatrix::normalMatrix_data()
+{
+ QTest::addColumn<void *>("mValues");
+
+ QTest::newRow("identity")
+ << (void *)identityValues4;
+ QTest::newRow("unique")
+ << (void *)uniqueValues4; // Not invertible because determinant == 0.
+
+ static qreal const translateValues[16] =
+ {1.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 1.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 1.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const scaleValues[16] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 7.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 9.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const bothValues[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const nullScaleValues1[16] =
+ {0.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const nullScaleValues2[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 0.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const nullScaleValues3[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 0.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+
+ QTest::newRow("translate") << (void *)translateValues;
+ QTest::newRow("scale") << (void *)scaleValues;
+ QTest::newRow("both") << (void *)bothValues;
+ QTest::newRow("null scale 1") << (void *)nullScaleValues1;
+ QTest::newRow("null scale 2") << (void *)nullScaleValues2;
+ QTest::newRow("null scale 3") << (void *)nullScaleValues3;
+}
+void tst_QMatrix::normalMatrix()
+{
+ QFETCH(void *, mValues);
+ const qreal *values = (const qreal *)mValues;
+
+ // Compute the expected answer the long way.
+ Matrix3 min;
+ Matrix3 answer;
+ min.v[0] = values[0];
+ min.v[1] = values[1];
+ min.v[2] = values[2];
+ min.v[3] = values[4];
+ min.v[4] = values[5];
+ min.v[5] = values[6];
+ min.v[6] = values[8];
+ min.v[7] = values[9];
+ min.v[8] = values[10];
+ bool invertible = m3Inverse(min, answer);
+ m3Transpose(answer);
+
+ // Perform the test.
+ QMatrix4x4 m1(values);
+ QMatrix3x3 n1 = m1.normalMatrix();
+
+ if (invertible)
+ QVERIFY(::isSame(n1, answer));
+ else
+ QVERIFY(isIdentity(n1));
+
+ // Perform the test again, after inferring special matrix types.
+ // This tests the optimized paths in the normalMatrix() function.
+ m1.inferSpecialType();
+ n1 = m1.normalMatrix();
+
+ if (invertible)
+ QVERIFY(::isSame(n1, answer));
+ else
+ QVERIFY(isIdentity(n1));
+}
+
+// Test optimized transformations on 4x4 matrices.
+void tst_QMatrix::optimizedTransforms()
+{
+ static qreal const translateValues[16] =
+ {1.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 1.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 1.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const translateDoubleValues[16] =
+ {1.0f, 0.0f, 0.0f, 8.0f,
+ 0.0f, 1.0f, 0.0f, 10.0f,
+ 0.0f, 0.0f, 1.0f, -6.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const scaleValues[16] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 7.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 9.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const scaleDoubleValues[16] =
+ {4.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 49.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 81.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const bothValues[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const bothReverseValues[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f * 2.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f * 7.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f * 9.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const bothThenTranslateValues[16] =
+ {2.0f, 0.0f, 0.0f, 4.0f + 2.0f * 4.0f,
+ 0.0f, 7.0f, 0.0f, 5.0f + 7.0f * 5.0f,
+ 0.0f, 0.0f, 9.0f, -3.0f + 9.0f * -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ static qreal const bothThenScaleValues[16] =
+ {4.0f, 0.0f, 0.0f, 4.0f,
+ 0.0f, 49.0f, 0.0f, 5.0f,
+ 0.0f, 0.0f, 81.0f, -3.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+
+ QMatrix4x4 translate(translateValues);
+ QMatrix4x4 scale(scaleValues);
+ QMatrix4x4 both(bothValues);
+
+ QMatrix4x4 m1;
+ m1.translate(4.0f, 5.0f, -3.0f);
+ QVERIFY(isSame(m1, translateValues));
+ m1.translate(4.0f, 5.0f, -3.0f);
+ QVERIFY(isSame(m1, translateDoubleValues));
+
+ QMatrix4x4 m2;
+ m2.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ QVERIFY(isSame(m2, translateValues));
+ m2.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ QVERIFY(isSame(m2, translateDoubleValues));
+
+ QMatrix4x4 m3;
+ m3.scale(2.0f, 7.0f, 9.0f);
+ QVERIFY(isSame(m3, scaleValues));
+ m3.scale(2.0f, 7.0f, 9.0f);
+ QVERIFY(isSame(m3, scaleDoubleValues));
+
+ QMatrix4x4 m4;
+ m4.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ QVERIFY(isSame(m4, scaleValues));
+ m4.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ QVERIFY(isSame(m4, scaleDoubleValues));
+
+ QMatrix4x4 m5;
+ m5.translate(4.0f, 5.0f, -3.0f);
+ m5.scale(2.0f, 7.0f, 9.0f);
+ QVERIFY(isSame(m5, bothValues));
+ m5.translate(4.0f, 5.0f, -3.0f);
+ QVERIFY(isSame(m5, bothThenTranslateValues));
+
+ QMatrix4x4 m6;
+ m6.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ m6.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ QVERIFY(isSame(m6, bothValues));
+ m6.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ QVERIFY(isSame(m6, bothThenTranslateValues));
+
+ QMatrix4x4 m7;
+ m7.scale(2.0f, 7.0f, 9.0f);
+ m7.translate(4.0f, 5.0f, -3.0f);
+ QVERIFY(isSame(m7, bothReverseValues));
+
+ QMatrix4x4 m8;
+ m8.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ m8.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ QVERIFY(isSame(m8, bothReverseValues));
+
+ QMatrix4x4 m9;
+ m9.translate(4.0f, 5.0f, -3.0f);
+ m9.scale(2.0f, 7.0f, 9.0f);
+ QVERIFY(isSame(m9, bothValues));
+ m9.scale(2.0f, 7.0f, 9.0f);
+ QVERIFY(isSame(m9, bothThenScaleValues));
+
+ QMatrix4x4 m10;
+ m10.translate(QVector3D(4.0f, 5.0f, -3.0f));
+ m10.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ QVERIFY(isSame(m10, bothValues));
+ m10.scale(QVector3D(2.0f, 7.0f, 9.0f));
+ QVERIFY(isSame(m10, bothThenScaleValues));
+}
+
+// Test orthographic projections.
+void tst_QMatrix::ortho()
+{
+ QMatrix4x4 m1;
+ m1.ortho(QRect(0, 0, 300, 150));
+ QPointF p1 = m1 * QPointF(0, 0);
+ QPointF p2 = m1 * QPointF(300, 0);
+ QPointF p3 = m1 * QPointF(0, 150);
+ QPointF p4 = m1 * QPointF(300, 150);
+ QVector3D p5 = m1 * QVector3D(300, 150, 1);
+ QVERIFY(fuzzyCompare(p1.x(), -1.0));
+ QVERIFY(fuzzyCompare(p1.y(), 1.0));
+ QVERIFY(fuzzyCompare(p2.x(), 1.0));
+ QVERIFY(fuzzyCompare(p2.y(), 1.0));
+ QVERIFY(fuzzyCompare(p3.x(), -1.0));
+ QVERIFY(fuzzyCompare(p3.y(), -1.0));
+ QVERIFY(fuzzyCompare(p4.x(), 1.0));
+ QVERIFY(fuzzyCompare(p4.y(), -1.0));
+ QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0));
+ QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0));
+ QVERIFY(fuzzyCompare(p5.z(), (qreal)-1.0));
+
+ QMatrix4x4 m2;
+ m2.ortho(QRectF(0, 0, 300, 150));
+ p1 = m2 * QPointF(0, 0);
+ p2 = m2 * QPointF(300, 0);
+ p3 = m2 * QPointF(0, 150);
+ p4 = m2 * QPointF(300, 150);
+ p5 = m2 * QVector3D(300, 150, 1);
+ QVERIFY(fuzzyCompare(p1.x(), -1.0));
+ QVERIFY(fuzzyCompare(p1.y(), 1.0));
+ QVERIFY(fuzzyCompare(p2.x(), 1.0));
+ QVERIFY(fuzzyCompare(p2.y(), 1.0));
+ QVERIFY(fuzzyCompare(p3.x(), -1.0));
+ QVERIFY(fuzzyCompare(p3.y(), -1.0));
+ QVERIFY(fuzzyCompare(p4.x(), 1.0));
+ QVERIFY(fuzzyCompare(p4.y(), -1.0));
+ QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0));
+ QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0));
+ QVERIFY(fuzzyCompare(p5.z(), (qreal)-1.0));
+
+ QMatrix4x4 m3;
+ m3.ortho(0, 300, 150, 0, -1, 1);
+ p1 = m3 * QPointF(0, 0);
+ p2 = m3 * QPointF(300, 0);
+ p3 = m3 * QPointF(0, 150);
+ p4 = m3 * QPointF(300, 150);
+ p5 = m3 * QVector3D(300, 150, 1);
+ QVERIFY(fuzzyCompare(p1.x(), -1.0));
+ QVERIFY(fuzzyCompare(p1.y(), 1.0));
+ QVERIFY(fuzzyCompare(p2.x(), 1.0));
+ QVERIFY(fuzzyCompare(p2.y(), 1.0));
+ QVERIFY(fuzzyCompare(p3.x(), -1.0));
+ QVERIFY(fuzzyCompare(p3.y(), -1.0));
+ QVERIFY(fuzzyCompare(p4.x(), 1.0));
+ QVERIFY(fuzzyCompare(p4.y(), -1.0));
+ QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0));
+ QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0));
+ QVERIFY(fuzzyCompare(p5.z(), (qreal)-1.0));
+
+ QMatrix4x4 m4;
+ m4.ortho(0, 300, 150, 0, -2, 3);
+ p1 = m4 * QPointF(0, 0);
+ p2 = m4 * QPointF(300, 0);
+ p3 = m4 * QPointF(0, 150);
+ p4 = m4 * QPointF(300, 150);
+ p5 = m4 * QVector3D(300, 150, 1);
+ QVERIFY(fuzzyCompare(p1.x(), -1.0));
+ QVERIFY(fuzzyCompare(p1.y(), 1.0));
+ QVERIFY(fuzzyCompare(p2.x(), 1.0));
+ QVERIFY(fuzzyCompare(p2.y(), 1.0));
+ QVERIFY(fuzzyCompare(p3.x(), -1.0));
+ QVERIFY(fuzzyCompare(p3.y(), -1.0));
+ QVERIFY(fuzzyCompare(p4.x(), 1.0));
+ QVERIFY(fuzzyCompare(p4.y(), -1.0));
+ QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0));
+ QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0));
+ QVERIFY(fuzzyCompare(p5.z(), (qreal)-0.6));
+
+ // An empty view volume should leave the matrix alone.
+ QMatrix4x4 m5;
+ m5.ortho(0, 0, 150, 0, -2, 3);
+ QVERIFY(m5.isIdentity());
+ m5.ortho(0, 300, 150, 150, -2, 3);
+ QVERIFY(m5.isIdentity());
+ m5.ortho(0, 300, 150, 0, 2, 2);
+ QVERIFY(m5.isIdentity());
+}
+
+// Test perspective frustum projections.
+void tst_QMatrix::frustum()
+{
+ QMatrix4x4 m1;
+ m1.frustum(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
+ QVector3D p1 = m1 * QVector3D(-1.0f, -1.0f, 1.0f);
+ QVector3D p2 = m1 * QVector3D(1.0f, -1.0f, 1.0f);
+ QVector3D p3 = m1 * QVector3D(-1.0f, 1.0f, 1.0f);
+ QVector3D p4 = m1 * QVector3D(1.0f, 1.0f, 1.0f);
+ QVector3D p5 = m1 * QVector3D(0.0f, 0.0f, 2.0f);
+ QVERIFY(fuzzyCompare(p1.x(), -1.0f));
+ QVERIFY(fuzzyCompare(p1.y(), -1.0f));
+ QVERIFY(fuzzyCompare(p1.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p2.x(), 1.0f));
+ QVERIFY(fuzzyCompare(p2.y(), -1.0f));
+ QVERIFY(fuzzyCompare(p2.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p3.x(), -1.0f));
+ QVERIFY(fuzzyCompare(p3.y(), 1.0f));
+ QVERIFY(fuzzyCompare(p3.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p4.x(), 1.0f));
+ QVERIFY(fuzzyCompare(p4.y(), 1.0f));
+ QVERIFY(fuzzyCompare(p4.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p5.x(), 0.0f));
+ QVERIFY(fuzzyCompare(p5.y(), 0.0f));
+ QVERIFY(fuzzyCompare(p5.z(), -0.5f));
+
+ // An empty view volume should leave the matrix alone.
+ QMatrix4x4 m5;
+ m5.frustum(0, 0, 150, 0, -2, 3);
+ QVERIFY(m5.isIdentity());
+ m5.frustum(0, 300, 150, 150, -2, 3);
+ QVERIFY(m5.isIdentity());
+ m5.frustum(0, 300, 150, 0, 2, 2);
+ QVERIFY(m5.isIdentity());
+}
+
+// Test perspective field-of-view projections.
+void tst_QMatrix::perspective()
+{
+ QMatrix4x4 m1;
+ m1.perspective(45.0f, 1.0f, -1.0f, 1.0f);
+ QVector3D p1 = m1 * QVector3D(-1.0f, -1.0f, 1.0f);
+ QVector3D p2 = m1 * QVector3D(1.0f, -1.0f, 1.0f);
+ QVector3D p3 = m1 * QVector3D(-1.0f, 1.0f, 1.0f);
+ QVector3D p4 = m1 * QVector3D(1.0f, 1.0f, 1.0f);
+ QVector3D p5 = m1 * QVector3D(0.0f, 0.0f, 2.0f);
+ QVERIFY(fuzzyCompare(p1.x(), 2.41421));
+ QVERIFY(fuzzyCompare(p1.y(), 2.41421));
+ QVERIFY(fuzzyCompare(p1.z(), -1));
+ QVERIFY(fuzzyCompare(p2.x(), -2.41421));
+ QVERIFY(fuzzyCompare(p2.y(), 2.41421));
+ QVERIFY(fuzzyCompare(p2.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p3.x(), 2.41421));
+ QVERIFY(fuzzyCompare(p3.y(), -2.41421));
+ QVERIFY(fuzzyCompare(p3.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p4.x(), -2.41421));
+ QVERIFY(fuzzyCompare(p4.y(), -2.41421));
+ QVERIFY(fuzzyCompare(p4.z(), -1.0f));
+ QVERIFY(fuzzyCompare(p5.x(), 0.0f));
+ QVERIFY(fuzzyCompare(p5.y(), 0.0f));
+ QVERIFY(fuzzyCompare(p5.z(), -0.5f));
+
+ // An empty view volume should leave the matrix alone.
+ QMatrix4x4 m5;
+ m5.perspective(45.0f, 1.0f, 0.0f, 0.0f);
+ QVERIFY(m5.isIdentity());
+ m5.perspective(45.0f, 0.0f, -1.0f, 1.0f);
+ QVERIFY(m5.isIdentity());
+ m5.perspective(0.0f, 1.0f, -1.0f, 1.0f);
+ QVERIFY(m5.isIdentity());
+}
+
+// Test left-handed vs right-handed coordinate flipping.
+void tst_QMatrix::flipCoordinates()
+{
+ QMatrix4x4 m1;
+ m1.flipCoordinates();
+ QVector3D p1 = m1 * QVector3D(2, 3, 4);
+ QVERIFY(p1 == QVector3D(2, -3, -4));
+
+ QMatrix4x4 m2;
+ m2.scale(2.0f, 3.0f, 1.0f);
+ m2.flipCoordinates();
+ QVector3D p2 = m2 * QVector3D(2, 3, 4);
+ QVERIFY(p2 == QVector3D(4, -9, -4));
+
+ QMatrix4x4 m3;
+ m3.translate(2.0f, 3.0f, 1.0f);
+ m3.flipCoordinates();
+ QVector3D p3 = m3 * QVector3D(2, 3, 4);
+ QVERIFY(p3 == QVector3D(4, 0, -3));
+
+ QMatrix4x4 m4;
+ m4.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+ m4.flipCoordinates();
+ QVector3D p4 = m4 * QVector3D(2, 3, 4);
+ QVERIFY(p4 == QVector3D(3, 2, -4));
+}
+
+// Test conversion of generic matrices to and from the non-generic types.
+void tst_QMatrix::convertGeneric()
+{
+ QMatrix4x3 m1(uniqueValues4x3);
+
+ static qreal const unique4x4[16] = {
+ 1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+#if !defined(QT_NO_MEMBER_TEMPLATES)
+ QMatrix4x4 m4(m1);
+ QVERIFY(isSame(m4, unique4x4));
+#endif
+ QMatrix4x4 m5 = qGenericMatrixToMatrix4x4(m1);
+ QVERIFY(isSame(m5, unique4x4));
+
+ static qreal const conv4x4[12] = {
+ 1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f
+ };
+ QMatrix4x4 m9(uniqueValues4);
+#if !defined(QT_NO_MEMBER_TEMPLATES)
+ QMatrix4x3 m10 = m9.toGenericMatrix<4, 3>();
+ QVERIFY(isSame(m10, conv4x4));
+#endif
+
+ QMatrix4x3 m11 = qGenericMatrixFromMatrix4x4<4, 3>(m9);
+ QVERIFY(isSame(m11, conv4x4));
+}
+
+void tst_QMatrix::extractAxisRotation_data()
+{
+ QTest::addColumn<float>("x");
+ QTest::addColumn<float>("y");
+ QTest::addColumn<float>("z");
+ QTest::addColumn<float>("angle");
+
+ QTest::newRow("1, 0, 0, 0 deg") << 1.0f << 0.0f << 0.0f << 0.0f;
+ QTest::newRow("1, 0, 0, 90 deg") << 1.0f << 0.0f << 0.0f << 90.0f;
+ QTest::newRow("1, 0, 0, 270 deg") << 1.0f << 0.0f << 0.0f << 270.0f;
+ QTest::newRow("1, 0, 0, 45 deg") << 1.0f << 0.0f << 0.0f << 45.0f;
+ QTest::newRow("1, 0, 0, 120 deg") << 1.0f << 0.0f << 0.0f << 120.0f;
+ QTest::newRow("1, 0, 0, 300 deg") << 1.0f << 0.0f << 0.0f << 300.0f;
+
+ QTest::newRow("0, 1, 0, 90 deg") << 0.0f << 1.0f << 0.0f << 90.0f;
+ QTest::newRow("0, 1, 0, 270 deg") << 0.0f << 1.0f << 0.0f << 270.0f;
+ QTest::newRow("0, 1, 0, 45 deg") << 0.0f << 1.0f << 0.0f << 45.0f;
+ QTest::newRow("0, 1, 0, 120 deg") << 0.0f << 1.0f << 0.0f << 120.0f;
+ QTest::newRow("0, 1, 0, 300 deg") << 0.0f << 1.0f << 0.0f << 300.0f;
+
+ QTest::newRow("0, 0, 1, 90 deg") << 0.0f << 0.0f << 1.0f << 90.0f;
+ QTest::newRow("0, 0, 1, 270 deg") << 0.0f << 0.0f << 1.0f << 270.0f;
+ QTest::newRow("0, 0, 1, 45 deg") << 0.0f << 0.0f << 1.0f << 45.0f;
+ QTest::newRow("0, 0, 1, 120 deg") << 0.0f << 0.0f << 1.0f << 120.0f;
+ QTest::newRow("0, 0, 1, 300 deg") << 0.0f << 0.0f << 1.0f << 300.0f;
+
+ QTest::newRow("1, 1, 1, 90 deg") << 1.0f << 1.0f << 1.0f << 90.0f;
+ QTest::newRow("1, 1, 1, 270 deg") << 1.0f << 1.0f << 1.0f << 270.0f;
+ QTest::newRow("1, 1, 1, 45 deg") << 1.0f << 1.0f << 1.0f << 45.0f;
+ QTest::newRow("1, 1, 1, 120 deg") << 1.0f << 1.0f << 1.0f << 120.0f;
+ QTest::newRow("1, 1, 1, 300 deg") << 1.0f << 1.0f << 1.0f << 300.0f;
+}
+
+void tst_QMatrix::extractAxisRotation()
+{
+ QFETCH(float, x);
+ QFETCH(float, y);
+ QFETCH(float, z);
+ QFETCH(float, angle);
+
+ QMatrix4x4 m;
+ QVector3D origAxis(x, y, z);
+
+ m.rotate(angle, x, y, z);
+
+ origAxis.normalize();
+ QVector3D extractedAxis;
+ qreal extractedAngle;
+
+ m.extractAxisRotation(extractedAngle, extractedAxis);
+
+ qreal epsilon = 0.001;
+
+ if (angle > 180) {
+ QVERIFY(fuzzyCompare(360.0f - angle, extractedAngle, epsilon));
+ QVERIFY(fuzzyCompare(extractedAxis, -origAxis, epsilon));
+ } else {
+ QVERIFY(fuzzyCompare(angle, extractedAngle, epsilon));
+ QVERIFY(fuzzyCompare(extractedAxis, origAxis, epsilon));
+ }
+}
+
+void tst_QMatrix::extractTranslation_data()
+{
+ QTest::addColumn<QMatrix4x4>("rotation");
+ QTest::addColumn<float>("x");
+ QTest::addColumn<float>("y");
+ QTest::addColumn<float>("z");
+
+ static QMatrix4x4 m1;
+
+ QTest::newRow("identity, 100, 50, 25")
+ << m1 << 100.0f << 50.0f << 250.0f;
+
+ m1.rotate(45.0, 1.0, 0.0, 0.0);
+ QTest::newRow("rotX 45 + 100, 50, 25") << m1 << 100.0f << 50.0f << 25.0f;
+
+ m1.setIdentity();
+ m1.rotate(45.0, 0.0, 1.0, 0.0);
+ QTest::newRow("rotY 45 + 100, 50, 25") << m1 << 100.0f << 50.0f << 25.0f;
+
+ m1.setIdentity();
+ m1.rotate(75, 0.0, 0.0, 1.0);
+ m1.rotate(25, 1.0, 0.0, 0.0);
+ m1.rotate(45, 0.0, 1.0, 0.0);
+ QTest::newRow("rotZ 75, rotX 25, rotY 45, 100, 50, 25") << m1 << 100.0f << 50.0f << 25.0f;
+}
+
+void tst_QMatrix::extractTranslation()
+{
+ QFETCH(QMatrix4x4, rotation);
+ QFETCH(float, x);
+ QFETCH(float, y);
+ QFETCH(float, z);
+
+ rotation.translate(x, y, z);
+
+ QVector3D vec = rotation.extractTranslation();
+
+ qreal epsilon = 0.001;
+
+ QVERIFY(fuzzyCompare(vec.x(), x, epsilon));
+ QVERIFY(fuzzyCompare(vec.y(), y, epsilon));
+ QVERIFY(fuzzyCompare(vec.z(), z, epsilon));
+
+ // Have to be careful with numbers here, it is really easy to blow away
+ // the precision of a fixed pointer number, especially when doing distance
+ // formula for vector normalization
+
+ QMatrix4x4 lookAt;
+ QVector3D eye(1.5f, -2.5f, 2.5f);
+ lookAt.lookAt(eye,
+ QVector3D(10.0f, 10.0f, 10.0f),
+ QVector3D(0.0f, 1.0f, 0.0f));
+
+ QVector3D extEye = lookAt.extractTranslation();
+
+ QVERIFY(fuzzyCompare(eye.x(), -extEye.x(), epsilon));
+ QVERIFY(fuzzyCompare(eye.y(), -extEye.y(), epsilon));
+ QVERIFY(fuzzyCompare(eye.z(), -extEye.z(), epsilon));
+}
+
+// Copy of "flagBits" in qmatrix4x4.h.
+enum {
+ Identity = 0x0001, // Identity matrix
+ General = 0x0002, // General matrix, unknown contents
+ Translation = 0x0004, // Contains a simple translation
+ Scale = 0x0008, // Contains a simple scale
+ Rotation = 0x0010 // Contains a simple rotation
+};
+
+// Structure that allows direct access to "flagBits" for testing.
+struct Matrix4x4
+{
+ float m[4][4];
+ int flagBits;
+};
+
+// Test the inferring of special matrix types.
+void tst_QMatrix::inferSpecialType_data()
+{
+ QTest::addColumn<void *>("mValues");
+ QTest::addColumn<int>("flagBits");
+
+ QTest::newRow("null")
+ << (void *)nullValues4 << (int)General;
+ QTest::newRow("identity")
+ << (void *)identityValues4 << (int)Identity;
+ QTest::newRow("unique")
+ << (void *)uniqueValues4 << (int)General;
+
+ static qreal scaleValues[16] = {
+ 2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 3.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 4.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("scale")
+ << (void *)scaleValues << (int)Scale;
+
+ static qreal translateValues[16] = {
+ 1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 1.0f, 0.0f, 3.0f,
+ 0.0f, 0.0f, 1.0f, 4.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("scale")
+ << (void *)translateValues << (int)Translation;
+
+ static qreal bothValues[16] = {
+ 1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 4.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("both")
+ << (void *)bothValues << (int)(Scale | Translation);
+
+ static qreal belowValues[16] = {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 4.0f, 0.0f, 0.0f, 1.0f
+ };
+ QTest::newRow("below")
+ << (void *)belowValues << (int)General;
+}
+void tst_QMatrix::inferSpecialType()
+{
+ QFETCH(void *, mValues);
+ QFETCH(int, flagBits);
+
+ QMatrix4x4 m((const qreal *)mValues);
+ m.inferSpecialType();
+
+ QCOMPARE(reinterpret_cast<Matrix4x4 *>(&m)->flagBits, flagBits);
+}
+
+void tst_QMatrix::columnsAndRows()
+{
+ QMatrix4x4 m1(uniqueValues4);
+
+ QVERIFY(m1.column(0) == QVector4D(1, 5, 9, 13));
+ QVERIFY(m1.column(1) == QVector4D(2, 6, 10, 14));
+ QVERIFY(m1.column(2) == QVector4D(3, 7, 11, 15));
+ QVERIFY(m1.column(3) == QVector4D(4, 8, 12, 16));
+
+ QVERIFY(m1.row(0) == QVector4D(1, 2, 3, 4));
+ QVERIFY(m1.row(1) == QVector4D(5, 6, 7, 8));
+ QVERIFY(m1.row(2) == QVector4D(9, 10, 11, 12));
+ QVERIFY(m1.row(3) == QVector4D(13, 14, 15, 16));
+
+ m1.setColumn(0, QVector4D(-1, -5, -9, -13));
+ m1.setColumn(1, QVector4D(-2, -6, -10, -14));
+ m1.setColumn(2, QVector4D(-3, -7, -11, -15));
+ m1.setColumn(3, QVector4D(-4, -8, -12, -16));
+
+ QVERIFY(m1.column(0) == QVector4D(-1, -5, -9, -13));
+ QVERIFY(m1.column(1) == QVector4D(-2, -6, -10, -14));
+ QVERIFY(m1.column(2) == QVector4D(-3, -7, -11, -15));
+ QVERIFY(m1.column(3) == QVector4D(-4, -8, -12, -16));
+
+ QVERIFY(m1.row(0) == QVector4D(-1, -2, -3, -4));
+ QVERIFY(m1.row(1) == QVector4D(-5, -6, -7, -8));
+ QVERIFY(m1.row(2) == QVector4D(-9, -10, -11, -12));
+ QVERIFY(m1.row(3) == QVector4D(-13, -14, -15, -16));
+
+ m1.setRow(0, QVector4D(1, 5, 9, 13));
+ m1.setRow(1, QVector4D(2, 6, 10, 14));
+ m1.setRow(2, QVector4D(3, 7, 11, 15));
+ m1.setRow(3, QVector4D(4, 8, 12, 16));
+
+ QVERIFY(m1.column(0) == QVector4D(1, 2, 3, 4));
+ QVERIFY(m1.column(1) == QVector4D(5, 6, 7, 8));
+ QVERIFY(m1.column(2) == QVector4D(9, 10, 11, 12));
+ QVERIFY(m1.column(3) == QVector4D(13, 14, 15, 16));
+
+ QVERIFY(m1.row(0) == QVector4D(1, 5, 9, 13));
+ QVERIFY(m1.row(1) == QVector4D(2, 6, 10, 14));
+ QVERIFY(m1.row(2) == QVector4D(3, 7, 11, 15));
+ QVERIFY(m1.row(3) == QVector4D(4, 8, 12, 16));
+}
+
+// Test converting QMatrix objects into QMatrix4x4 and then
+// checking that transformations in the original perform the
+// equivalent transformations in the new matrix.
+void tst_QMatrix::convertQMatrix()
+{
+ QMatrix m1;
+ m1.translate(-3.5, 2.0);
+ QPointF p1 = m1.map(QPointF(100.0, 150.0));
+ QCOMPARE(p1.x(), 100.0 - 3.5);
+ QCOMPARE(p1.y(), 150.0 + 2.0);
+
+ QMatrix4x4 m2(m1);
+ QPointF p2 = m2 * QPointF(100.0, 150.0);
+ QCOMPARE((double)p2.x(), 100.0 - 3.5);
+ QCOMPARE((double)p2.y(), 150.0 + 2.0);
+ QVERIFY(m1 == m2.toAffine());
+
+ QMatrix m3;
+ m3.scale(1.5, -2.0);
+ QPointF p3 = m3.map(QPointF(100.0, 150.0));
+ QCOMPARE(p3.x(), 1.5 * 100.0);
+ QCOMPARE(p3.y(), -2.0 * 150.0);
+
+ QMatrix4x4 m4(m3);
+ QPointF p4 = m4 * QPointF(100.0, 150.0);
+ QCOMPARE((double)p4.x(), 1.5 * 100.0);
+ QCOMPARE((double)p4.y(), -2.0 * 150.0);
+ QVERIFY(m3 == m4.toAffine());
+
+ QMatrix m5;
+ m5.rotate(45.0);
+ QPointF p5 = m5.map(QPointF(100.0, 150.0));
+
+ QMatrix4x4 m6(m5);
+ QPointF p6 = m6 * QPointF(100.0, 150.0);
+ QVERIFY(fuzzyCompare(p5.x(), p6.x(), 0.005));
+ QVERIFY(fuzzyCompare(p5.y(), p6.y(), 0.005));
+
+ QMatrix m7 = m6.toAffine();
+ QVERIFY(fuzzyCompare(m5.m11(), m7.m11()));
+ QVERIFY(fuzzyCompare(m5.m12(), m7.m12()));
+ QVERIFY(fuzzyCompare(m5.m21(), m7.m21()));
+ QVERIFY(fuzzyCompare(m5.m22(), m7.m22()));
+ QVERIFY(fuzzyCompare(m5.dx(), m7.dx()));
+ QVERIFY(fuzzyCompare(m5.dy(), m7.dy()));
+}
+
+// Test converting QTransform objects into QMatrix4x4 and then
+// checking that transformations in the original perform the
+// equivalent transformations in the new matrix.
+void tst_QMatrix::convertQTransform()
+{
+ QTransform m1;
+ m1.translate(-3.5, 2.0);
+ QPointF p1 = m1.map(QPointF(100.0, 150.0));
+ QCOMPARE(p1.x(), 100.0 - 3.5);
+ QCOMPARE(p1.y(), 150.0 + 2.0);
+
+ QMatrix4x4 m2(m1);
+ QPointF p2 = m2 * QPointF(100.0, 150.0);
+ QCOMPARE((double)p2.x(), 100.0 - 3.5);
+ QCOMPARE((double)p2.y(), 150.0 + 2.0);
+ QVERIFY(m1 == m2.toTransform());
+
+ QTransform m3;
+ m3.scale(1.5, -2.0);
+ QPointF p3 = m3.map(QPointF(100.0, 150.0));
+ QCOMPARE(p3.x(), 1.5 * 100.0);
+ QCOMPARE(p3.y(), -2.0 * 150.0);
+
+ QMatrix4x4 m4(m3);
+ QPointF p4 = m4 * QPointF(100.0, 150.0);
+ QCOMPARE((double)p4.x(), 1.5 * 100.0);
+ QCOMPARE((double)p4.y(), -2.0 * 150.0);
+ QVERIFY(m3 == m4.toTransform());
+
+ QTransform m5;
+ m5.rotate(45.0);
+ QPointF p5 = m5.map(QPointF(100.0, 150.0));
+
+ QMatrix4x4 m6(m5);
+ QPointF p6 = m6 * QPointF(100.0, 150.0);
+ QVERIFY(fuzzyCompare(p5.x(), p6.x(), 0.005));
+ QVERIFY(fuzzyCompare(p5.y(), p6.y(), 0.005));
+
+ QTransform m7 = m6.toTransform();
+ QVERIFY(fuzzyCompare(m5.m11(), m7.m11()));
+ QVERIFY(fuzzyCompare(m5.m12(), m7.m12()));
+ QVERIFY(fuzzyCompare(m5.m21(), m7.m21()));
+ QVERIFY(fuzzyCompare(m5.m22(), m7.m22()));
+ QVERIFY(fuzzyCompare(m5.dx(), m7.dx()));
+ QVERIFY(fuzzyCompare(m5.dy(), m7.dy()));
+ QVERIFY(fuzzyCompare(m5.m13(), m7.m13()));
+ QVERIFY(fuzzyCompare(m5.m23(), m7.m23()));
+ QVERIFY(fuzzyCompare(m5.m33(), m7.m33()));
+}
+
+// Test filling matrices with specific values.
+void tst_QMatrix::fill()
+{
+ QMatrix4x4 m1;
+ m1.fill(0.0f);
+ QVERIFY(isSame(m1, nullValues4));
+
+ static const qreal fillValues4[] =
+ {2.5f, 2.5f, 2.5f, 2.5f,
+ 2.5f, 2.5f, 2.5f, 2.5f,
+ 2.5f, 2.5f, 2.5f, 2.5f,
+ 2.5f, 2.5f, 2.5f, 2.5f};
+ m1.fill(2.5f);
+ QVERIFY(isSame(m1, fillValues4));
+
+ QMatrix4x3 m2;
+ m2.fill(0.0f);
+ QVERIFY(isSame(m2, nullValues4x3));
+
+ static const qreal fillValues4x3[] =
+ {2.5f, 2.5f, 2.5f, 2.5f,
+ 2.5f, 2.5f, 2.5f, 2.5f,
+ 2.5f, 2.5f, 2.5f, 2.5f};
+ m2.fill(2.5f);
+ QVERIFY(isSame(m2, fillValues4x3));
+}
+
+QTEST_APPLESS_MAIN(tst_QMatrix)
+
+#include "tst_qmatrixnxn.moc"
diff --git a/tests/auto/math3d/qquaternion/qquaternion.pro b/tests/auto/math3d/qquaternion/qquaternion.pro
new file mode 100644
index 0000000..eea84f0
--- /dev/null
+++ b/tests/auto/math3d/qquaternion/qquaternion.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+VPATH += ../shared
+INCLUDEPATH += ../shared
+HEADERS += math3dincludes.h
+SOURCES += tst_qquaternion.cpp
diff --git a/tests/auto/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/math3d/qquaternion/tst_qquaternion.cpp
new file mode 100644
index 0000000..f25f858
--- /dev/null
+++ b/tests/auto/math3d/qquaternion/tst_qquaternion.cpp
@@ -0,0 +1,830 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/qmath.h>
+#include "math3dincludes.h"
+
+class tst_QQuaternion : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QQuaternion() {}
+ ~tst_QQuaternion() {}
+
+private slots:
+ void create();
+
+ void length_data();
+ void length();
+
+ void normalized_data();
+ void normalized();
+
+ void normalize_data();
+ void normalize();
+
+ void compare();
+
+ void add_data();
+ void add();
+
+ void subtract_data();
+ void subtract();
+
+ void multiply_data();
+ void multiply();
+
+ void multiplyFactor_data();
+ void multiplyFactor();
+
+ void divide_data();
+ void divide();
+
+ void negate_data();
+ void negate();
+
+ void conjugate_data();
+ void conjugate();
+
+ void fromAxisAndAngle_data();
+ void fromAxisAndAngle();
+
+ void slerp_data();
+ void slerp();
+
+ void nlerp_data();
+ void nlerp();
+};
+
+// qFuzzyCompare isn't quite "fuzzy" enough to handle conversion
+// to fixed-point and back again. So create "fuzzier" compares.
+static bool fuzzyCompare(float x, float y)
+{
+ float diff = x - y;
+ if (diff < 0.0f)
+ diff = -diff;
+ return (diff < 0.001);
+}
+
+// Test the creation of QQuaternion objects in various ways:
+// construct, copy, and modify.
+void tst_QQuaternion::create()
+{
+ QQuaternion identity;
+ QCOMPARE(identity.x(), (qreal)0.0f);
+ QCOMPARE(identity.y(), (qreal)0.0f);
+ QCOMPARE(identity.z(), (qreal)0.0f);
+ QCOMPARE(identity.scalar(), (qreal)1.0f);
+ QVERIFY(identity.isIdentity());
+
+ QQuaternion v1(34.0f, 1.0f, 2.5f, -89.25f);
+ QCOMPARE(v1.x(), (qreal)1.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.scalar(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ QQuaternion v1i(34, 1, 2, -89);
+ QCOMPARE(v1i.x(), (qreal)1.0f);
+ QCOMPARE(v1i.y(), (qreal)2.0f);
+ QCOMPARE(v1i.z(), (qreal)-89.0f);
+ QCOMPARE(v1i.scalar(), (qreal)34.0f);
+ QVERIFY(!v1i.isNull());
+
+ QQuaternion v2(v1);
+ QCOMPARE(v2.x(), (qreal)1.0f);
+ QCOMPARE(v2.y(), (qreal)2.5f);
+ QCOMPARE(v2.z(), (qreal)-89.25f);
+ QCOMPARE(v2.scalar(), (qreal)34.0f);
+ QVERIFY(!v2.isNull());
+
+ QQuaternion v4;
+ QCOMPARE(v4.x(), (qreal)0.0f);
+ QCOMPARE(v4.y(), (qreal)0.0f);
+ QCOMPARE(v4.z(), (qreal)0.0f);
+ QCOMPARE(v4.scalar(), (qreal)1.0f);
+ QVERIFY(v4.isIdentity());
+ v4 = v1;
+ QCOMPARE(v4.x(), (qreal)1.0f);
+ QCOMPARE(v4.y(), (qreal)2.5f);
+ QCOMPARE(v4.z(), (qreal)-89.25f);
+ QCOMPARE(v4.scalar(), (qreal)34.0f);
+ QVERIFY(!v4.isNull());
+
+ QQuaternion v9(34, QVector3D(1.0f, 2.5f, -89.25f));
+ QCOMPARE(v9.x(), (qreal)1.0f);
+ QCOMPARE(v9.y(), (qreal)2.5f);
+ QCOMPARE(v9.z(), (qreal)-89.25f);
+ QCOMPARE(v9.scalar(), (qreal)34.0f);
+ QVERIFY(!v9.isNull());
+
+ v1.setX(3.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.scalar(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setY(10.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.scalar(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setZ(15.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)15.5f);
+ QCOMPARE(v1.scalar(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setScalar(6.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)15.5f);
+ QCOMPARE(v1.scalar(), (qreal)6.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setVector(2.0f, 6.5f, -1.25f);
+ QCOMPARE(v1.x(), (qreal)2.0f);
+ QCOMPARE(v1.y(), (qreal)6.5f);
+ QCOMPARE(v1.z(), (qreal)-1.25f);
+ QCOMPARE(v1.scalar(), (qreal)6.0f);
+ QVERIFY(!v1.isNull());
+ QVERIFY(v1.vector() == QVector3D(2.0f, 6.5f, -1.25f));
+
+ v1.setVector(QVector3D(-2.0f, -6.5f, 1.25f));
+ QCOMPARE(v1.x(), (qreal)-2.0f);
+ QCOMPARE(v1.y(), (qreal)-6.5f);
+ QCOMPARE(v1.z(), (qreal)1.25f);
+ QCOMPARE(v1.scalar(), (qreal)6.0f);
+ QVERIFY(!v1.isNull());
+ QVERIFY(v1.vector() == QVector3D(-2.0f, -6.5f, 1.25f));
+
+ v1.setX(0.0f);
+ v1.setY(0.0f);
+ v1.setZ(0.0f);
+ v1.setScalar(0.0f);
+ QCOMPARE(v1.x(), (qreal)0.0f);
+ QCOMPARE(v1.y(), (qreal)0.0f);
+ QCOMPARE(v1.z(), (qreal)0.0f);
+ QCOMPARE(v1.scalar(), (qreal)0.0f);
+ QVERIFY(v1.isNull());
+
+ QVector4D v10 = v9.toVector4D();
+ QCOMPARE(v10.x(), (qreal)1.0f);
+ QCOMPARE(v10.y(), (qreal)2.5f);
+ QCOMPARE(v10.z(), (qreal)-89.25f);
+ QCOMPARE(v10.w(), (qreal)34.0f);
+}
+
+// Test length computation for quaternions.
+void tst_QQuaternion::length_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<qreal>("w");
+ QTest::addColumn<qreal>("len");
+
+ QTest::newRow("null") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+ QTest::newRow("1x") << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1y") << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1z") << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1w") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)1.0f;
+ QTest::newRow("-1x") << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1y") << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1z") << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1w") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f << (qreal)1.0f;
+ QTest::newRow("two") << (qreal)2.0f << (qreal)-2.0f << (qreal)2.0f << (qreal)2.0f << (qreal)qSqrt(16.0f);
+}
+void tst_QQuaternion::length()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+ QFETCH(qreal, len);
+
+ QQuaternion v(w, x, y, z);
+ QCOMPARE((float)(v.length()), (float)len);
+ QCOMPARE((float)(v.lengthSquared()), (float)(x * x + y * y + z * z + w * w));
+}
+
+// Test the unit vector conversion for quaternions.
+void tst_QQuaternion::normalized_data()
+{
+ // Use the same test data as the length test.
+ length_data();
+}
+void tst_QQuaternion::normalized()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+ QFETCH(qreal, len);
+
+ QQuaternion v(w, x, y, z);
+ QQuaternion u = v.normalized();
+ if (v.isNull())
+ QVERIFY(u.isNull());
+ else
+ QCOMPARE((float)(u.length()), (float)1.0f);
+ QCOMPARE((float)(u.x() * len), (float)(v.x()));
+ QCOMPARE((float)(u.y() * len), (float)(v.y()));
+ QCOMPARE((float)(u.z() * len), (float)(v.z()));
+ QCOMPARE((float)(u.scalar() * len), (float)(v.scalar()));
+}
+
+// Test the unit vector conversion for quaternions.
+void tst_QQuaternion::normalize_data()
+{
+ // Use the same test data as the length test.
+ length_data();
+}
+void tst_QQuaternion::normalize()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+
+ QQuaternion v(w, x, y, z);
+ bool isNull = v.isNull();
+ v.normalize();
+ if (isNull)
+ QVERIFY(v.isNull());
+ else
+ QCOMPARE((float)(v.length()), (float)1.0f);
+}
+
+// Test the comparison operators for quaternions.
+void tst_QQuaternion::compare()
+{
+ QQuaternion v1(8, 1, 2, 4);
+ QQuaternion v2(8, 1, 2, 4);
+ QQuaternion v3(8, 3, 2, 4);
+ QQuaternion v4(8, 1, 3, 4);
+ QQuaternion v5(8, 1, 2, 3);
+ QQuaternion v6(3, 1, 2, 4);
+
+ QVERIFY(v1 == v2);
+ QVERIFY(v1 != v3);
+ QVERIFY(v1 != v4);
+ QVERIFY(v1 != v5);
+ QVERIFY(v1 != v6);
+}
+
+// Test addition for quaternions.
+void tst_QQuaternion::add_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("w3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)3.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)3.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)3.0f << (qreal)0.0f;
+
+ QTest::newRow("wonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)3.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f << (qreal)8.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)-6.0f << (qreal)9.0f
+ << (qreal)5.0f << (qreal)7.0f << (qreal)-3.0f << (qreal)17.0f;
+}
+void tst_QQuaternion::add()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, w3);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(w2, x2, y2, z2);
+ QQuaternion v3(w3, x3, y3, z3);
+
+ QVERIFY((v1 + v2) == v3);
+
+ QQuaternion v4(v1);
+ v4 += v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() + v2.x());
+ QCOMPARE(v4.y(), v1.y() + v2.y());
+ QCOMPARE(v4.z(), v1.z() + v2.z());
+ QCOMPARE(v4.scalar(), v1.scalar() + v2.scalar());
+}
+
+// Test subtraction for quaternions.
+void tst_QQuaternion::subtract_data()
+{
+ // Use the same test data as the add test.
+ add_data();
+}
+void tst_QQuaternion::subtract()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, w3);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(w2, x2, y2, z2);
+ QQuaternion v3(w3, x3, y3, z3);
+
+ QVERIFY((v3 - v1) == v2);
+ QVERIFY((v3 - v2) == v1);
+
+ QQuaternion v4(v3);
+ v4 -= v1;
+ QVERIFY(v4 == v2);
+
+ QCOMPARE(v4.x(), v3.x() - v1.x());
+ QCOMPARE(v4.y(), v3.y() - v1.y());
+ QCOMPARE(v4.z(), v3.z() - v1.z());
+ QCOMPARE(v4.scalar(), v3.scalar() - v1.scalar());
+
+ QQuaternion v5(v3);
+ v5 -= v2;
+ QVERIFY(v5 == v1);
+
+ QCOMPARE(v5.x(), v3.x() - v2.x());
+ QCOMPARE(v5.y(), v3.y() - v2.y());
+ QCOMPARE(v5.z(), v3.z() - v2.z());
+ QCOMPARE(v5.scalar(), v3.scalar() - v2.scalar());
+}
+
+// Test quaternion multiplication.
+void tst_QQuaternion::multiply_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("unitvec")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)1.0f;
+
+ QTest::newRow("complex")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f << (qreal)7.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)6.0f << (qreal)8.0f;
+}
+void tst_QQuaternion::multiply()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+
+ QQuaternion q1(w1, x1, y1, z1);
+ QQuaternion q2(w2, x2, y2, z2);
+
+ // Use the simple algorithm at:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q53
+ // to calculate the answer we expect to get.
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ qreal scalar = w1 * w2 - QVector3D::dotProduct(v1, v2);
+ QVector3D vector = w1 * v2 + w2 * v1 + QVector3D::crossProduct(v1, v2);
+ QQuaternion result(scalar, vector);
+
+ QVERIFY((q1 * q2) == result);
+}
+
+// Test multiplication by a factor for quaternions.
+void tst_QQuaternion::multiplyFactor_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)100.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("wonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)4.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)4.0f << (qreal)-6.0f << (qreal)8.0f;
+
+ QTest::newRow("allzero")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)4.0f
+ << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+}
+void tst_QQuaternion::multiplyFactor()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(w2, x2, y2, z2);
+
+ QVERIFY((v1 * factor) == v2);
+ QVERIFY((factor * v1) == v2);
+
+ QQuaternion v3(v1);
+ v3 *= factor;
+ QVERIFY(v3 == v2);
+
+ QCOMPARE(v3.x(), v1.x() * factor);
+ QCOMPARE(v3.y(), v1.y() * factor);
+ QCOMPARE(v3.z(), v1.z() * factor);
+ QCOMPARE(v3.scalar(), v1.scalar() * factor);
+}
+
+// Test division by a factor for quaternions.
+void tst_QQuaternion::divide_data()
+{
+ // Use the same test data as the multiply test.
+ multiplyFactor_data();
+}
+void tst_QQuaternion::divide()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(w2, x2, y2, z2);
+
+ if (factor == (qreal)0.0f)
+ return;
+
+ QVERIFY((v2 / factor) == v1);
+
+ QQuaternion v3(v2);
+ v3 /= factor;
+ QVERIFY(v3 == v1);
+
+ QCOMPARE(v3.x(), v2.x() / factor);
+ QCOMPARE(v3.y(), v2.y() / factor);
+ QCOMPARE(v3.z(), v2.z() / factor);
+ QCOMPARE(v3.scalar(), v2.scalar() / factor);
+}
+
+// Test negation for quaternions.
+void tst_QQuaternion::negate_data()
+{
+ // Use the same test data as the add test.
+ add_data();
+}
+void tst_QQuaternion::negate()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(-w1, -x1, -y1, -z1);
+
+ QVERIFY(-v1 == v2);
+}
+
+// Test quaternion conjugate calculations.
+void tst_QQuaternion::conjugate_data()
+{
+ // Use the same test data as the add test.
+ add_data();
+}
+void tst_QQuaternion::conjugate()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+
+ QQuaternion v1(w1, x1, y1, z1);
+ QQuaternion v2(w1, -x1, -y1, -z1);
+
+ QVERIFY(v1.conjugate() == v2);
+}
+
+// Test quaternion creation from an axis and an angle.
+void tst_QQuaternion::fromAxisAndAngle_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("angle");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)90.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)180.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)270.0f;
+
+ QTest::newRow("complex")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)45.0f;
+}
+void tst_QQuaternion::fromAxisAndAngle()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, angle);
+
+ // Use a straight-forward implementation of the algorithm at:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56
+ // to calculate the answer we expect to get.
+ QVector3D vector = QVector3D(x1, y1, z1).normalized();
+ qreal sin_a = qSin((angle * M_PI / 180.0) / 2.0);
+ qreal cos_a = qCos((angle * M_PI / 180.0) / 2.0);
+ QQuaternion result((qreal)cos_a,
+ (qreal)(vector.x() * sin_a),
+ (qreal)(vector.y() * sin_a),
+ (qreal)(vector.z() * sin_a));
+ result = result.normalized();
+
+ QQuaternion answer = QQuaternion::fromAxisAndAngle(QVector3D(x1, y1, z1), angle);
+ QVERIFY(fuzzyCompare(answer.x(), result.x()));
+ QVERIFY(fuzzyCompare(answer.y(), result.y()));
+ QVERIFY(fuzzyCompare(answer.z(), result.z()));
+ QVERIFY(fuzzyCompare(answer.scalar(), result.scalar()));
+
+ answer = QQuaternion::fromAxisAndAngle(x1, y1, z1, angle);
+ QVERIFY(fuzzyCompare(answer.x(), result.x()));
+ QVERIFY(fuzzyCompare(answer.y(), result.y()));
+ QVERIFY(fuzzyCompare(answer.z(), result.z()));
+ QVERIFY(fuzzyCompare(answer.scalar(), result.scalar()));
+}
+
+// Test spherical interpolation of quaternions.
+void tst_QQuaternion::slerp_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("angle1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("angle2");
+ QTest::addColumn<qreal>("t");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("angle3");
+
+ QTest::newRow("first")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f
+ << (qreal)0.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f;
+ QTest::newRow("first2")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f
+ << (qreal)-0.5f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f;
+ QTest::newRow("second")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f
+ << (qreal)1.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f;
+ QTest::newRow("second2")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f
+ << (qreal)1.5f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f;
+ QTest::newRow("middle")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)90.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)180.0f
+ << (qreal)0.5f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)135.0f;
+ QTest::newRow("wide angle")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)0.0f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)270.0f
+ << (qreal)0.5f
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)-45.0f;
+}
+void tst_QQuaternion::slerp()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, angle1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, angle2);
+ QFETCH(qreal, t);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, angle3);
+
+ QQuaternion q1 = QQuaternion::fromAxisAndAngle(x1, y1, z1, angle1);
+ QQuaternion q2 = QQuaternion::fromAxisAndAngle(x2, y2, z2, angle2);
+ QQuaternion q3 = QQuaternion::fromAxisAndAngle(x3, y3, z3, angle3);
+
+ QQuaternion result = QQuaternion::slerp(q1, q2, t);
+
+ QVERIFY(fuzzyCompare(result.x(), q3.x()));
+ QVERIFY(fuzzyCompare(result.y(), q3.y()));
+ QVERIFY(fuzzyCompare(result.z(), q3.z()));
+ QVERIFY(fuzzyCompare(result.scalar(), q3.scalar()));
+}
+
+// Test normalized linear interpolation of quaternions.
+void tst_QQuaternion::nlerp_data()
+{
+ slerp_data();
+}
+void tst_QQuaternion::nlerp()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, angle1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, angle2);
+ QFETCH(qreal, t);
+
+ QQuaternion q1 = QQuaternion::fromAxisAndAngle(x1, y1, z1, angle1);
+ QQuaternion q2 = QQuaternion::fromAxisAndAngle(x2, y2, z2, angle2);
+
+ QQuaternion result = QQuaternion::nlerp(q1, q2, t);
+
+ qreal resultx, resulty, resultz, resultscalar;
+ if (t <= 0.0f) {
+ resultx = q1.x();
+ resulty = q1.y();
+ resultz = q1.z();
+ resultscalar = q1.scalar();
+ } else if (t >= 1.0f) {
+ resultx = q2.x();
+ resulty = q2.y();
+ resultz = q2.z();
+ resultscalar = q2.scalar();
+ } else if (qAbs(angle1 - angle2) <= 180.f) {
+ resultx = q1.x() * (1 - t) + q2.x() * t;
+ resulty = q1.y() * (1 - t) + q2.y() * t;
+ resultz = q1.z() * (1 - t) + q2.z() * t;
+ resultscalar = q1.scalar() * (1 - t) + q2.scalar() * t;
+ } else {
+ // Angle greater than 180 degrees: negate q2.
+ resultx = q1.x() * (1 - t) - q2.x() * t;
+ resulty = q1.y() * (1 - t) - q2.y() * t;
+ resultz = q1.z() * (1 - t) - q2.z() * t;
+ resultscalar = q1.scalar() * (1 - t) - q2.scalar() * t;
+ }
+
+ QQuaternion q3 = QQuaternion(resultscalar, resultx, resulty, resultz).normalized();
+
+ QVERIFY(fuzzyCompare(result.x(), q3.x()));
+ QVERIFY(fuzzyCompare(result.y(), q3.y()));
+ QVERIFY(fuzzyCompare(result.z(), q3.z()));
+ QVERIFY(fuzzyCompare(result.scalar(), q3.scalar()));
+}
+
+QTEST_APPLESS_MAIN(tst_QQuaternion)
+
+#include "tst_qquaternion.moc"
diff --git a/tests/auto/math3d/qvectornd/qvectornd.pro b/tests/auto/math3d/qvectornd/qvectornd.pro
new file mode 100644
index 0000000..0981637
--- /dev/null
+++ b/tests/auto/math3d/qvectornd/qvectornd.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+VPATH += ../shared
+INCLUDEPATH += ../shared
+HEADERS += math3dincludes.h
+SOURCES += tst_qvectornd.cpp
diff --git a/tests/auto/math3d/qvectornd/tst_qvectornd.cpp b/tests/auto/math3d/qvectornd/tst_qvectornd.cpp
new file mode 100644
index 0000000..a092fb0
--- /dev/null
+++ b/tests/auto/math3d/qvectornd/tst_qvectornd.cpp
@@ -0,0 +1,2045 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/qmath.h>
+#include "math3dincludes.h"
+
+class tst_QVector : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QVector() {}
+ ~tst_QVector() {}
+
+private slots:
+ void create2();
+ void create3();
+ void create4();
+
+ void length2_data();
+ void length2();
+ void length3_data();
+ void length3();
+ void length4_data();
+ void length4();
+
+ void normalized2_data();
+ void normalized2();
+ void normalized3_data();
+ void normalized3();
+ void normalized4_data();
+ void normalized4();
+
+ void normalize2_data();
+ void normalize2();
+ void normalize3_data();
+ void normalize3();
+ void normalize4_data();
+ void normalize4();
+
+ void compare2();
+ void compare3();
+ void compare4();
+
+ void add2_data();
+ void add2();
+ void add3_data();
+ void add3();
+ void add4_data();
+ void add4();
+
+ void subtract2_data();
+ void subtract2();
+ void subtract3_data();
+ void subtract3();
+ void subtract4_data();
+ void subtract4();
+
+ void multiply2_data();
+ void multiply2();
+ void multiply3_data();
+ void multiply3();
+ void multiply4_data();
+ void multiply4();
+
+ void multiplyFactor2_data();
+ void multiplyFactor2();
+ void multiplyFactor3_data();
+ void multiplyFactor3();
+ void multiplyFactor4_data();
+ void multiplyFactor4();
+
+ void divide2_data();
+ void divide2();
+ void divide3_data();
+ void divide3();
+ void divide4_data();
+ void divide4();
+
+ void negate2_data();
+ void negate2();
+ void negate3_data();
+ void negate3();
+ void negate4_data();
+ void negate4();
+
+ void crossProduct_data();
+ void crossProduct();
+ void normal_data();
+ void normal();
+ void distanceToPlane_data();
+ void distanceToPlane();
+ void distanceToLine_data();
+ void distanceToLine();
+
+ void dotProduct2_data();
+ void dotProduct2();
+ void dotProduct3_data();
+ void dotProduct3();
+ void dotProduct4_data();
+ void dotProduct4();
+};
+
+// qFuzzyCompare isn't quite "fuzzy" enough to handle conversion
+// to fixed-point and back again. So create "fuzzier" compares.
+static bool fuzzyCompare(float x, float y)
+{
+ float diff = x - y;
+ if (diff < 0.0f)
+ diff = -diff;
+ return (diff < 0.001);
+}
+
+// Test the creation of QVector2D objects in various ways:
+// construct, copy, and modify.
+void tst_QVector::create2()
+{
+ QVector2D null;
+ QCOMPARE(null.x(), (qreal)0.0f);
+ QCOMPARE(null.y(), (qreal)0.0f);
+ QVERIFY(null.isNull());
+
+ QVector2D v1(1.0f, 2.5f);
+ QCOMPARE(v1.x(), (qreal)1.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QVERIFY(!v1.isNull());
+
+ QVector2D v1i(1, 2);
+ QCOMPARE(v1i.x(), (qreal)1.0f);
+ QCOMPARE(v1i.y(), (qreal)2.0f);
+ QVERIFY(!v1i.isNull());
+
+ QVector2D v2(v1);
+ QCOMPARE(v2.x(), (qreal)1.0f);
+ QCOMPARE(v2.y(), (qreal)2.5f);
+ QVERIFY(!v2.isNull());
+
+ QVector2D v4;
+ QCOMPARE(v4.x(), (qreal)0.0f);
+ QCOMPARE(v4.y(), (qreal)0.0f);
+ QVERIFY(v4.isNull());
+ v4 = v1;
+ QCOMPARE(v4.x(), (qreal)1.0f);
+ QCOMPARE(v4.y(), (qreal)2.5f);
+ QVERIFY(!v4.isNull());
+
+ QVector2D v5(QPoint(1, 2));
+ QCOMPARE(v5.x(), (qreal)1.0f);
+ QCOMPARE(v5.y(), (qreal)2.0f);
+ QVERIFY(!v5.isNull());
+
+ QVector2D v6(QPointF(1, 2.5));
+ QCOMPARE(v6.x(), (qreal)1.0f);
+ QCOMPARE(v6.y(), (qreal)2.5f);
+ QVERIFY(!v6.isNull());
+
+ QVector2D v7(QVector3D(1.0f, 2.5f, 54.25f));
+ QCOMPARE(v7.x(), (qreal)1.0f);
+ QCOMPARE(v7.y(), (qreal)2.5f);
+ QVERIFY(!v6.isNull());
+
+ QVector2D v8(QVector4D(1.0f, 2.5f, 54.25f, 34.0f));
+ QCOMPARE(v8.x(), (qreal)1.0f);
+ QCOMPARE(v8.y(), (qreal)2.5f);
+ QVERIFY(!v6.isNull());
+
+ v1.setX(3.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QVERIFY(!v1.isNull());
+
+ v1.setY(10.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QVERIFY(!v1.isNull());
+
+ v1.setX(0.0f);
+ v1.setY(0.0f);
+ QCOMPARE(v1.x(), (qreal)0.0f);
+ QCOMPARE(v1.y(), (qreal)0.0f);
+ QVERIFY(v1.isNull());
+
+ QPoint p1 = v8.toPoint();
+ QCOMPARE(p1.x(), 1);
+ QCOMPARE(p1.y(), 3);
+
+ QPointF p2 = v8.toPointF();
+ QCOMPARE((qreal)p2.x(), (qreal)1.0f);
+ QCOMPARE((qreal)p2.y(), (qreal)2.5f);
+
+ QVector3D v9 = v8.toVector3D();
+ QCOMPARE(v9.x(), (qreal)1.0f);
+ QCOMPARE(v9.y(), (qreal)2.5f);
+ QCOMPARE(v9.z(), (qreal)0.0f);
+
+ QVector4D v10 = v8.toVector4D();
+ QCOMPARE(v10.x(), (qreal)1.0f);
+ QCOMPARE(v10.y(), (qreal)2.5f);
+ QCOMPARE(v10.z(), (qreal)0.0f);
+ QCOMPARE(v10.w(), (qreal)0.0f);
+}
+
+// Test the creation of QVector3D objects in various ways:
+// construct, copy, and modify.
+void tst_QVector::create3()
+{
+ QVector3D null;
+ QCOMPARE(null.x(), (qreal)0.0f);
+ QCOMPARE(null.y(), (qreal)0.0f);
+ QCOMPARE(null.z(), (qreal)0.0f);
+ QVERIFY(null.isNull());
+
+ QVector3D v1(1.0f, 2.5f, -89.25f);
+ QCOMPARE(v1.x(), (qreal)1.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QVERIFY(!v1.isNull());
+
+ QVector3D v1i(1, 2, -89);
+ QCOMPARE(v1i.x(), (qreal)1.0f);
+ QCOMPARE(v1i.y(), (qreal)2.0f);
+ QCOMPARE(v1i.z(), (qreal)-89.0f);
+ QVERIFY(!v1i.isNull());
+
+ QVector3D v2(v1);
+ QCOMPARE(v2.x(), (qreal)1.0f);
+ QCOMPARE(v2.y(), (qreal)2.5f);
+ QCOMPARE(v2.z(), (qreal)-89.25f);
+ QVERIFY(!v2.isNull());
+
+ QVector3D v3(1.0f, 2.5f, 0.0f);
+ QCOMPARE(v3.x(), (qreal)1.0f);
+ QCOMPARE(v3.y(), (qreal)2.5f);
+ QCOMPARE(v3.z(), (qreal)0.0f);
+ QVERIFY(!v3.isNull());
+
+ QVector3D v3i(1, 2, 0);
+ QCOMPARE(v3i.x(), (qreal)1.0f);
+ QCOMPARE(v3i.y(), (qreal)2.0f);
+ QCOMPARE(v3i.z(), (qreal)0.0f);
+ QVERIFY(!v3i.isNull());
+
+ QVector3D v4;
+ QCOMPARE(v4.x(), (qreal)0.0f);
+ QCOMPARE(v4.y(), (qreal)0.0f);
+ QCOMPARE(v4.z(), (qreal)0.0f);
+ QVERIFY(v4.isNull());
+ v4 = v1;
+ QCOMPARE(v4.x(), (qreal)1.0f);
+ QCOMPARE(v4.y(), (qreal)2.5f);
+ QCOMPARE(v4.z(), (qreal)-89.25f);
+ QVERIFY(!v4.isNull());
+
+ QVector3D v5(QPoint(1, 2));
+ QCOMPARE(v5.x(), (qreal)1.0f);
+ QCOMPARE(v5.y(), (qreal)2.0f);
+ QCOMPARE(v5.z(), (qreal)0.0f);
+ QVERIFY(!v5.isNull());
+
+ QVector3D v6(QPointF(1, 2.5));
+ QCOMPARE(v6.x(), (qreal)1.0f);
+ QCOMPARE(v6.y(), (qreal)2.5f);
+ QCOMPARE(v6.z(), (qreal)0.0f);
+ QVERIFY(!v6.isNull());
+
+ QVector3D v7(QVector2D(1.0f, 2.5f));
+ QCOMPARE(v7.x(), (qreal)1.0f);
+ QCOMPARE(v7.y(), (qreal)2.5f);
+ QCOMPARE(v7.z(), (qreal)0.0f);
+ QVERIFY(!v7.isNull());
+
+ QVector3D v8(QVector2D(1.0f, 2.5f), 54.25f);
+ QCOMPARE(v8.x(), (qreal)1.0f);
+ QCOMPARE(v8.y(), (qreal)2.5f);
+ QCOMPARE(v8.z(), (qreal)54.25f);
+ QVERIFY(!v8.isNull());
+
+ QVector3D v9(QVector4D(1.0f, 2.5f, 54.25f, 34.0f));
+ QCOMPARE(v9.x(), (qreal)1.0f);
+ QCOMPARE(v9.y(), (qreal)2.5f);
+ QCOMPARE(v9.z(), (qreal)54.25f);
+ QVERIFY(!v9.isNull());
+
+ v1.setX(3.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QVERIFY(!v1.isNull());
+
+ v1.setY(10.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QVERIFY(!v1.isNull());
+
+ v1.setZ(15.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)15.5f);
+ QVERIFY(!v1.isNull());
+
+ v1.setX(0.0f);
+ v1.setY(0.0f);
+ v1.setZ(0.0f);
+ QCOMPARE(v1.x(), (qreal)0.0f);
+ QCOMPARE(v1.y(), (qreal)0.0f);
+ QCOMPARE(v1.z(), (qreal)0.0f);
+ QVERIFY(v1.isNull());
+
+ QPoint p1 = v8.toPoint();
+ QCOMPARE(p1.x(), 1);
+ QCOMPARE(p1.y(), 3);
+
+ QPointF p2 = v8.toPointF();
+ QCOMPARE((qreal)p2.x(), (qreal)1.0f);
+ QCOMPARE((qreal)p2.y(), (qreal)2.5f);
+
+ QVector2D v10 = v8.toVector2D();
+ QCOMPARE(v10.x(), (qreal)1.0f);
+ QCOMPARE(v10.y(), (qreal)2.5f);
+
+ QVector4D v11 = v8.toVector4D();
+ QCOMPARE(v11.x(), (qreal)1.0f);
+ QCOMPARE(v11.y(), (qreal)2.5f);
+ QCOMPARE(v11.z(), (qreal)54.25f);
+ QCOMPARE(v11.w(), (qreal)0.0f);
+}
+
+// Test the creation of QVector4D objects in various ways:
+// construct, copy, and modify.
+void tst_QVector::create4()
+{
+ QVector4D null;
+ QCOMPARE(null.x(), (qreal)0.0f);
+ QCOMPARE(null.y(), (qreal)0.0f);
+ QCOMPARE(null.z(), (qreal)0.0f);
+ QCOMPARE(null.w(), (qreal)0.0f);
+ QVERIFY(null.isNull());
+
+ QVector4D v1(1.0f, 2.5f, -89.25f, 34.0f);
+ QCOMPARE(v1.x(), (qreal)1.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.w(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ QVector4D v1i(1, 2, -89, 34);
+ QCOMPARE(v1i.x(), (qreal)1.0f);
+ QCOMPARE(v1i.y(), (qreal)2.0f);
+ QCOMPARE(v1i.z(), (qreal)-89.0f);
+ QCOMPARE(v1i.w(), (qreal)34.0f);
+ QVERIFY(!v1i.isNull());
+
+ QVector4D v2(v1);
+ QCOMPARE(v2.x(), (qreal)1.0f);
+ QCOMPARE(v2.y(), (qreal)2.5f);
+ QCOMPARE(v2.z(), (qreal)-89.25f);
+ QCOMPARE(v2.w(), (qreal)34.0f);
+ QVERIFY(!v2.isNull());
+
+ QVector4D v3(1.0f, 2.5f, 0.0f, 0.0f);
+ QCOMPARE(v3.x(), (qreal)1.0f);
+ QCOMPARE(v3.y(), (qreal)2.5f);
+ QCOMPARE(v3.z(), (qreal)0.0f);
+ QCOMPARE(v3.w(), (qreal)0.0f);
+ QVERIFY(!v3.isNull());
+
+ QVector4D v3i(1, 2, 0, 0);
+ QCOMPARE(v3i.x(), (qreal)1.0f);
+ QCOMPARE(v3i.y(), (qreal)2.0f);
+ QCOMPARE(v3i.z(), (qreal)0.0f);
+ QCOMPARE(v3i.w(), (qreal)0.0f);
+ QVERIFY(!v3i.isNull());
+
+ QVector4D v3b(1.0f, 2.5f, -89.25f, 0.0f);
+ QCOMPARE(v3b.x(), (qreal)1.0f);
+ QCOMPARE(v3b.y(), (qreal)2.5f);
+ QCOMPARE(v3b.z(), (qreal)-89.25f);
+ QCOMPARE(v3b.w(), (qreal)0.0f);
+ QVERIFY(!v3b.isNull());
+
+ QVector4D v3bi(1, 2, -89, 0);
+ QCOMPARE(v3bi.x(), (qreal)1.0f);
+ QCOMPARE(v3bi.y(), (qreal)2.0f);
+ QCOMPARE(v3bi.z(), (qreal)-89.0f);
+ QCOMPARE(v3bi.w(), (qreal)0.0f);
+ QVERIFY(!v3bi.isNull());
+
+ QVector4D v4;
+ QCOMPARE(v4.x(), (qreal)0.0f);
+ QCOMPARE(v4.y(), (qreal)0.0f);
+ QCOMPARE(v4.z(), (qreal)0.0f);
+ QCOMPARE(v4.w(), (qreal)0.0f);
+ QVERIFY(v4.isNull());
+ v4 = v1;
+ QCOMPARE(v4.x(), (qreal)1.0f);
+ QCOMPARE(v4.y(), (qreal)2.5f);
+ QCOMPARE(v4.z(), (qreal)-89.25f);
+ QCOMPARE(v4.w(), (qreal)34.0f);
+ QVERIFY(!v4.isNull());
+
+ QVector4D v5(QPoint(1, 2));
+ QCOMPARE(v5.x(), (qreal)1.0f);
+ QCOMPARE(v5.y(), (qreal)2.0f);
+ QCOMPARE(v5.z(), (qreal)0.0f);
+ QCOMPARE(v5.w(), (qreal)0.0f);
+ QVERIFY(!v5.isNull());
+
+ QVector4D v6(QPointF(1, 2.5));
+ QCOMPARE(v6.x(), (qreal)1.0f);
+ QCOMPARE(v6.y(), (qreal)2.5f);
+ QCOMPARE(v6.z(), (qreal)0.0f);
+ QCOMPARE(v6.w(), (qreal)0.0f);
+ QVERIFY(!v6.isNull());
+
+ QVector4D v7(QVector2D(1.0f, 2.5f));
+ QCOMPARE(v7.x(), (qreal)1.0f);
+ QCOMPARE(v7.y(), (qreal)2.5f);
+ QCOMPARE(v7.z(), (qreal)0.0f);
+ QCOMPARE(v7.w(), (qreal)0.0f);
+ QVERIFY(!v7.isNull());
+
+ QVector4D v8(QVector3D(1.0f, 2.5f, -89.25f));
+ QCOMPARE(v8.x(), (qreal)1.0f);
+ QCOMPARE(v8.y(), (qreal)2.5f);
+ QCOMPARE(v8.z(), (qreal)-89.25f);
+ QCOMPARE(v8.w(), (qreal)0.0f);
+ QVERIFY(!v8.isNull());
+
+ QVector4D v9(QVector3D(1.0f, 2.5f, -89.25f), 34);
+ QCOMPARE(v9.x(), (qreal)1.0f);
+ QCOMPARE(v9.y(), (qreal)2.5f);
+ QCOMPARE(v9.z(), (qreal)-89.25f);
+ QCOMPARE(v9.w(), (qreal)34.0f);
+ QVERIFY(!v9.isNull());
+
+ QVector4D v10(QVector2D(1.0f, 2.5f), 23.5f, -8);
+ QCOMPARE(v10.x(), (qreal)1.0f);
+ QCOMPARE(v10.y(), (qreal)2.5f);
+ QCOMPARE(v10.z(), (qreal)23.5f);
+ QCOMPARE(v10.w(), (qreal)-8.0f);
+ QVERIFY(!v10.isNull());
+
+ v1.setX(3.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)2.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.w(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setY(10.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)-89.25f);
+ QCOMPARE(v1.w(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setZ(15.5f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)15.5f);
+ QCOMPARE(v1.w(), (qreal)34.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setW(6.0f);
+ QCOMPARE(v1.x(), (qreal)3.0f);
+ QCOMPARE(v1.y(), (qreal)10.5f);
+ QCOMPARE(v1.z(), (qreal)15.5f);
+ QCOMPARE(v1.w(), (qreal)6.0f);
+ QVERIFY(!v1.isNull());
+
+ v1.setX(0.0f);
+ v1.setY(0.0f);
+ v1.setZ(0.0f);
+ v1.setW(0.0f);
+ QCOMPARE(v1.x(), (qreal)0.0f);
+ QCOMPARE(v1.y(), (qreal)0.0f);
+ QCOMPARE(v1.z(), (qreal)0.0f);
+ QCOMPARE(v1.w(), (qreal)0.0f);
+ QVERIFY(v1.isNull());
+
+ QPoint p1 = v8.toPoint();
+ QCOMPARE(p1.x(), 1);
+ QCOMPARE(p1.y(), 3);
+
+ QPointF p2 = v8.toPointF();
+ QCOMPARE((qreal)p2.x(), (qreal)1.0f);
+ QCOMPARE((qreal)p2.y(), (qreal)2.5f);
+
+ QVector2D v11 = v8.toVector2D();
+ QCOMPARE(v11.x(), (qreal)1.0f);
+ QCOMPARE(v11.y(), (qreal)2.5f);
+
+ QVector3D v12 = v8.toVector3D();
+ QCOMPARE(v12.x(), (qreal)1.0f);
+ QCOMPARE(v12.y(), (qreal)2.5f);
+ QCOMPARE(v12.z(), (qreal)-89.25f);
+
+ QVector2D v13 = v9.toVector2DAffine();
+ QVERIFY(fuzzyCompare(v13.x(), (qreal)(1.0f / 34.0f)));
+ QVERIFY(fuzzyCompare(v13.y(), (qreal)(2.5f / 34.0f)));
+
+ QVector4D zerow(1.0f, 2.0f, 3.0f, 0.0f);
+ v13 = zerow.toVector2DAffine();
+ QVERIFY(v13.isNull());
+
+ QVector3D v14 = v9.toVector3DAffine();
+ QVERIFY(fuzzyCompare(v14.x(), (qreal)(1.0f / 34.0f)));
+ QVERIFY(fuzzyCompare(v14.y(), (qreal)(2.5f / 34.0f)));
+ QVERIFY(fuzzyCompare(v14.z(), (qreal)(-89.25f / 34.0f)));
+
+ v14 = zerow.toVector3DAffine();
+ QVERIFY(v14.isNull());
+}
+
+// Test vector length computation for 2D vectors.
+void tst_QVector::length2_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("len");
+
+ QTest::newRow("null") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+ QTest::newRow("1x") << (qreal)1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1y") << (qreal)0.0f << (qreal)1.0f << (qreal)1.0f;
+ QTest::newRow("-1x") << (qreal)-1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1y") << (qreal)0.0f << (qreal)-1.0f << (qreal)1.0f;
+ QTest::newRow("two") << (qreal)2.0f << (qreal)-2.0f << (qreal)qSqrt(8.0f);
+}
+void tst_QVector::length2()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, len);
+
+ QVector2D v(x, y);
+ QCOMPARE((float)(v.length()), (float)len);
+ QCOMPARE((float)(v.lengthSquared()), (float)(x * x + y * y));
+}
+
+// Test vector length computation for 3D vectors.
+void tst_QVector::length3_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<qreal>("len");
+
+ QTest::newRow("null") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+ QTest::newRow("1x") << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1y") << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1z") << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)1.0f;
+ QTest::newRow("-1x") << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1y") << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1z") << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f << (qreal)1.0f;
+ QTest::newRow("two") << (qreal)2.0f << (qreal)-2.0f << (qreal)2.0f << (qreal)qSqrt(12.0f);
+}
+void tst_QVector::length3()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, len);
+
+ QVector3D v(x, y, z);
+ QCOMPARE((float)(v.length()), (float)len);
+ QCOMPARE((float)(v.lengthSquared()), (float)(x * x + y * y + z * z));
+}
+
+// Test vector length computation for 4D vectors.
+void tst_QVector::length4_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("z");
+ QTest::addColumn<qreal>("w");
+ QTest::addColumn<qreal>("len");
+
+ QTest::newRow("null") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+ QTest::newRow("1x") << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1y") << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1z") << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("1w") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)1.0f;
+ QTest::newRow("-1x") << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1y") << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1z") << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f << (qreal)1.0f;
+ QTest::newRow("-1w") << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f << (qreal)1.0f;
+ QTest::newRow("two") << (qreal)2.0f << (qreal)-2.0f << (qreal)2.0f << (qreal)2.0f << (qreal)qSqrt(16.0f);
+}
+void tst_QVector::length4()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+ QFETCH(qreal, len);
+
+ QVector4D v(x, y, z, w);
+ QCOMPARE((float)(v.length()), (float)len);
+ QCOMPARE((float)(v.lengthSquared()), (float)(x * x + y * y + z * z + w * w));
+}
+
+// Test the unit vector conversion for 2D vectors.
+void tst_QVector::normalized2_data()
+{
+ // Use the same test data as the length test.
+ length2_data();
+}
+void tst_QVector::normalized2()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, len);
+
+ QVector2D v(x, y);
+ QVector2D u = v.normalized();
+ if (v.isNull())
+ QVERIFY(u.isNull());
+ else
+ QCOMPARE((float)(u.length()), (float)1.0f);
+ QCOMPARE((float)(u.x() * len), (float)(v.x()));
+ QCOMPARE((float)(u.y() * len), (float)(v.y()));
+}
+
+// Test the unit vector conversion for 3D vectors.
+void tst_QVector::normalized3_data()
+{
+ // Use the same test data as the length test.
+ length3_data();
+}
+void tst_QVector::normalized3()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, len);
+
+ QVector3D v(x, y, z);
+ QVector3D u = v.normalized();
+ if (v.isNull())
+ QVERIFY(u.isNull());
+ else
+ QCOMPARE((float)(u.length()), (float)1.0f);
+ QCOMPARE((float)(u.x() * len), (float)(v.x()));
+ QCOMPARE((float)(u.y() * len), (float)(v.y()));
+ QCOMPARE((float)(u.z() * len), (float)(v.z()));
+}
+
+// Test the unit vector conversion for 4D vectors.
+void tst_QVector::normalized4_data()
+{
+ // Use the same test data as the length test.
+ length4_data();
+}
+void tst_QVector::normalized4()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+ QFETCH(qreal, len);
+
+ QVector4D v(x, y, z, w);
+ QVector4D u = v.normalized();
+ if (v.isNull())
+ QVERIFY(u.isNull());
+ else
+ QCOMPARE((float)(u.length()), (float)1.0f);
+ QCOMPARE((float)(u.x() * len), (float)(v.x()));
+ QCOMPARE((float)(u.y() * len), (float)(v.y()));
+ QCOMPARE((float)(u.z() * len), (float)(v.z()));
+ QCOMPARE((float)(u.w() * len), (float)(v.w()));
+}
+
+// Test the unit vector conversion for 2D vectors.
+void tst_QVector::normalize2_data()
+{
+ // Use the same test data as the length test.
+ length2_data();
+}
+void tst_QVector::normalize2()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+
+ QVector2D v(x, y);
+ bool isNull = v.isNull();
+ v.normalize();
+ if (isNull)
+ QVERIFY(v.isNull());
+ else
+ QCOMPARE((float)(v.length()), (float)1.0f);
+}
+
+// Test the unit vector conversion for 3D vectors.
+void tst_QVector::normalize3_data()
+{
+ // Use the same test data as the length test.
+ length3_data();
+}
+void tst_QVector::normalize3()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+
+ QVector3D v(x, y, z);
+ bool isNull = v.isNull();
+ v.normalize();
+ if (isNull)
+ QVERIFY(v.isNull());
+ else
+ QCOMPARE((float)(v.length()), (float)1.0f);
+}
+
+// Test the unit vector conversion for 4D vectors.
+void tst_QVector::normalize4_data()
+{
+ // Use the same test data as the length test.
+ length4_data();
+}
+void tst_QVector::normalize4()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, z);
+ QFETCH(qreal, w);
+
+ QVector4D v(x, y, z, w);
+ bool isNull = v.isNull();
+ v.normalize();
+ if (isNull)
+ QVERIFY(v.isNull());
+ else
+ QCOMPARE((float)(v.length()), (float)1.0f);
+}
+
+// Test the comparison operators for 2D vectors.
+void tst_QVector::compare2()
+{
+ QVector2D v1(1, 2);
+ QVector2D v2(1, 2);
+ QVector2D v3(3, 2);
+ QVector2D v4(1, 3);
+
+ QVERIFY(v1 == v2);
+ QVERIFY(v1 != v3);
+ QVERIFY(v1 != v4);
+}
+
+// Test the comparison operators for 3D vectors.
+void tst_QVector::compare3()
+{
+ QVector3D v1(1, 2, 4);
+ QVector3D v2(1, 2, 4);
+ QVector3D v3(3, 2, 4);
+ QVector3D v4(1, 3, 4);
+ QVector3D v5(1, 2, 3);
+
+ QVERIFY(v1 == v2);
+ QVERIFY(v1 != v3);
+ QVERIFY(v1 != v4);
+ QVERIFY(v1 != v5);
+}
+
+// Test the comparison operators for 4D vectors.
+void tst_QVector::compare4()
+{
+ QVector4D v1(1, 2, 4, 8);
+ QVector4D v2(1, 2, 4, 8);
+ QVector4D v3(3, 2, 4, 8);
+ QVector4D v4(1, 3, 4, 8);
+ QVector4D v5(1, 2, 3, 8);
+ QVector4D v6(1, 2, 4, 3);
+
+ QVERIFY(v1 == v2);
+ QVERIFY(v1 != v3);
+ QVERIFY(v1 != v4);
+ QVERIFY(v1 != v5);
+ QVERIFY(v1 != v6);
+}
+
+// Test vector addition for 2D vectors.
+void tst_QVector::add2_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f
+ << (qreal)3.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)3.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f
+ << (qreal)4.0f << (qreal)5.0f
+ << (qreal)5.0f << (qreal)7.0f;
+}
+void tst_QVector::add2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+ QVector2D v3(x3, y3);
+
+ QVERIFY((v1 + v2) == v3);
+
+ QVector2D v4(v1);
+ v4 += v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() + v2.x());
+ QCOMPARE(v4.y(), v1.y() + v2.y());
+}
+
+// Test vector addition for 3D vectors.
+void tst_QVector::add3_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)3.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)3.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)3.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)-6.0f
+ << (qreal)5.0f << (qreal)7.0f << (qreal)-3.0f;
+}
+void tst_QVector::add3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QVERIFY((v1 + v2) == v3);
+
+ QVector3D v4(v1);
+ v4 += v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() + v2.x());
+ QCOMPARE(v4.y(), v1.y() + v2.y());
+ QCOMPARE(v4.z(), v1.z() + v2.z());
+}
+
+// Test vector addition for 4D vectors.
+void tst_QVector::add4_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("w3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)3.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)3.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)3.0f << (qreal)0.0f;
+
+ QTest::newRow("wonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)3.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f << (qreal)8.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)-6.0f << (qreal)9.0f
+ << (qreal)5.0f << (qreal)7.0f << (qreal)-3.0f << (qreal)17.0f;
+}
+void tst_QVector::add4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, w3);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+ QVector4D v3(x3, y3, z3, w3);
+
+ QVERIFY((v1 + v2) == v3);
+
+ QVector4D v4(v1);
+ v4 += v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() + v2.x());
+ QCOMPARE(v4.y(), v1.y() + v2.y());
+ QCOMPARE(v4.z(), v1.z() + v2.z());
+ QCOMPARE(v4.w(), v1.w() + v2.w());
+}
+
+// Test vector subtraction for 2D vectors.
+void tst_QVector::subtract2_data()
+{
+ // Use the same test data as the add test.
+ add2_data();
+}
+void tst_QVector::subtract2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+ QVector2D v3(x3, y3);
+
+ QVERIFY((v3 - v1) == v2);
+ QVERIFY((v3 - v2) == v1);
+
+ QVector2D v4(v3);
+ v4 -= v1;
+ QVERIFY(v4 == v2);
+
+ QCOMPARE(v4.x(), v3.x() - v1.x());
+ QCOMPARE(v4.y(), v3.y() - v1.y());
+
+ QVector2D v5(v3);
+ v5 -= v2;
+ QVERIFY(v5 == v1);
+
+ QCOMPARE(v5.x(), v3.x() - v2.x());
+ QCOMPARE(v5.y(), v3.y() - v2.y());
+}
+
+// Test vector subtraction for 3D vectors.
+void tst_QVector::subtract3_data()
+{
+ // Use the same test data as the add test.
+ add3_data();
+}
+void tst_QVector::subtract3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QVERIFY((v3 - v1) == v2);
+ QVERIFY((v3 - v2) == v1);
+
+ QVector3D v4(v3);
+ v4 -= v1;
+ QVERIFY(v4 == v2);
+
+ QCOMPARE(v4.x(), v3.x() - v1.x());
+ QCOMPARE(v4.y(), v3.y() - v1.y());
+ QCOMPARE(v4.z(), v3.z() - v1.z());
+
+ QVector3D v5(v3);
+ v5 -= v2;
+ QVERIFY(v5 == v1);
+
+ QCOMPARE(v5.x(), v3.x() - v2.x());
+ QCOMPARE(v5.y(), v3.y() - v2.y());
+ QCOMPARE(v5.z(), v3.z() - v2.z());
+}
+
+// Test vector subtraction for 4D vectors.
+void tst_QVector::subtract4_data()
+{
+ // Use the same test data as the add test.
+ add4_data();
+}
+void tst_QVector::subtract4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, w3);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+ QVector4D v3(x3, y3, z3, w3);
+
+ QVERIFY((v3 - v1) == v2);
+ QVERIFY((v3 - v2) == v1);
+
+ QVector4D v4(v3);
+ v4 -= v1;
+ QVERIFY(v4 == v2);
+
+ QCOMPARE(v4.x(), v3.x() - v1.x());
+ QCOMPARE(v4.y(), v3.y() - v1.y());
+ QCOMPARE(v4.z(), v3.z() - v1.z());
+ QCOMPARE(v4.w(), v3.w() - v1.w());
+
+ QVector4D v5(v3);
+ v5 -= v2;
+ QVERIFY(v5 == v1);
+
+ QCOMPARE(v5.x(), v3.x() - v2.x());
+ QCOMPARE(v5.y(), v3.y() - v2.y());
+ QCOMPARE(v5.z(), v3.z() - v2.z());
+ QCOMPARE(v5.w(), v3.w() - v2.w());
+}
+
+// Test component-wise vector multiplication for 2D vectors.
+void tst_QVector::multiply2_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f
+ << (qreal)4.0f << (qreal)5.0f
+ << (qreal)4.0f << (qreal)10.0f;
+}
+void tst_QVector::multiply2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+ QVector2D v3(x3, y3);
+
+ QVERIFY((v1 * v2) == v3);
+
+ QVector2D v4(v1);
+ v4 *= v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() * v2.x());
+ QCOMPARE(v4.y(), v1.y() * v2.y());
+}
+
+// Test component-wise vector multiplication for 3D vectors.
+void tst_QVector::multiply3_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)-6.0f
+ << (qreal)4.0f << (qreal)10.0f << (qreal)-18.0f;
+}
+void tst_QVector::multiply3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QVERIFY((v1 * v2) == v3);
+
+ QVector3D v4(v1);
+ v4 *= v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() * v2.x());
+ QCOMPARE(v4.y(), v1.y() * v2.y());
+ QCOMPARE(v4.z(), v1.z() * v2.z());
+}
+
+// Test component-wise vector multiplication for 4D vectors.
+void tst_QVector::multiply4_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("w3");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("wonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f << (qreal)8.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)-6.0f << (qreal)9.0f
+ << (qreal)4.0f << (qreal)10.0f << (qreal)-18.0f << (qreal)72.0f;
+}
+void tst_QVector::multiply4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, w3);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+ QVector4D v3(x3, y3, z3, w3);
+
+ QVERIFY((v1 * v2) == v3);
+
+ QVector4D v4(v1);
+ v4 *= v2;
+ QVERIFY(v4 == v3);
+
+ QCOMPARE(v4.x(), v1.x() * v2.x());
+ QCOMPARE(v4.y(), v1.y() * v2.y());
+ QCOMPARE(v4.z(), v1.z() * v2.z());
+ QCOMPARE(v4.w(), v1.w() * v2.w());
+}
+
+// Test vector multiplication by a factor for 2D vectors.
+void tst_QVector::multiplyFactor2_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)100.0f
+ << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)4.0f;
+
+ QTest::newRow("allzero")
+ << (qreal)1.0f << (qreal)2.0f
+ << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f;
+}
+void tst_QVector::multiplyFactor2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+
+ QVERIFY((v1 * factor) == v2);
+ QVERIFY((factor * v1) == v2);
+
+ QVector2D v3(v1);
+ v3 *= factor;
+ QVERIFY(v3 == v2);
+
+ QCOMPARE(v3.x(), v1.x() * factor);
+ QCOMPARE(v3.y(), v1.y() * factor);
+}
+
+// Test vector multiplication by a factor for 3D vectors.
+void tst_QVector::multiplyFactor3_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)100.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)4.0f << (qreal)-6.0f;
+
+ QTest::newRow("allzero")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f
+ << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+}
+void tst_QVector::multiplyFactor3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+
+ QVERIFY((v1 * factor) == v2);
+ QVERIFY((factor * v1) == v2);
+
+ QVector3D v3(v1);
+ v3 *= factor;
+ QVERIFY(v3 == v2);
+
+ QCOMPARE(v3.x(), v1.x() * factor);
+ QCOMPARE(v3.y(), v1.y() * factor);
+ QCOMPARE(v3.z(), v1.z() * factor);
+}
+
+// Test vector multiplication by a factor for 4D vectors.
+void tst_QVector::multiplyFactor4_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("factor");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)100.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("xonly")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("yonly")
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f << (qreal)0.0f;
+
+ QTest::newRow("zonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f;
+
+ QTest::newRow("wonly")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)2.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f;
+
+ QTest::newRow("all")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)4.0f
+ << (qreal)2.0f
+ << (qreal)2.0f << (qreal)4.0f << (qreal)-6.0f << (qreal)8.0f;
+
+ QTest::newRow("allzero")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)-3.0f << (qreal)4.0f
+ << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+}
+void tst_QVector::multiplyFactor4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+
+ QVERIFY((v1 * factor) == v2);
+ QVERIFY((factor * v1) == v2);
+
+ QVector4D v3(v1);
+ v3 *= factor;
+ QVERIFY(v3 == v2);
+
+ QCOMPARE(v3.x(), v1.x() * factor);
+ QCOMPARE(v3.y(), v1.y() * factor);
+ QCOMPARE(v3.z(), v1.z() * factor);
+ QCOMPARE(v3.w(), v1.w() * factor);
+}
+
+// Test vector division by a factor for 2D vectors.
+void tst_QVector::divide2_data()
+{
+ // Use the same test data as the multiply test.
+ multiplyFactor2_data();
+}
+void tst_QVector::divide2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+
+ if (factor == (qreal)0.0f)
+ return;
+
+ QVERIFY((v2 / factor) == v1);
+
+ QVector2D v3(v2);
+ v3 /= factor;
+ QVERIFY(v3 == v1);
+
+ QCOMPARE(v3.x(), v2.x() / factor);
+ QCOMPARE(v3.y(), v2.y() / factor);
+}
+
+// Test vector division by a factor for 3D vectors.
+void tst_QVector::divide3_data()
+{
+ // Use the same test data as the multiply test.
+ multiplyFactor3_data();
+}
+void tst_QVector::divide3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+
+ if (factor == (qreal)0.0f)
+ return;
+
+ QVERIFY((v2 / factor) == v1);
+
+ QVector3D v3(v2);
+ v3 /= factor;
+ QVERIFY(v3 == v1);
+
+ QCOMPARE(v3.x(), v2.x() / factor);
+ QCOMPARE(v3.y(), v2.y() / factor);
+ QCOMPARE(v3.z(), v2.z() / factor);
+}
+
+// Test vector division by a factor for 4D vectors.
+void tst_QVector::divide4_data()
+{
+ // Use the same test data as the multiply test.
+ multiplyFactor4_data();
+}
+void tst_QVector::divide4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, factor);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+
+ if (factor == (qreal)0.0f)
+ return;
+
+ QVERIFY((v2 / factor) == v1);
+
+ QVector4D v3(v2);
+ v3 /= factor;
+ QVERIFY(v3 == v1);
+
+ QCOMPARE(v3.x(), v2.x() / factor);
+ QCOMPARE(v3.y(), v2.y() / factor);
+ QCOMPARE(v3.z(), v2.z() / factor);
+ QCOMPARE(v3.w(), v2.w() / factor);
+}
+
+// Test vector negation for 2D vectors.
+void tst_QVector::negate2_data()
+{
+ // Use the same test data as the add test.
+ add2_data();
+}
+void tst_QVector::negate2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(-x1, -y1);
+
+ QVERIFY(-v1 == v2);
+}
+
+// Test vector negation for 3D vectors.
+void tst_QVector::negate3_data()
+{
+ // Use the same test data as the add test.
+ add3_data();
+}
+void tst_QVector::negate3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(-x1, -y1, -z1);
+
+ QVERIFY(-v1 == v2);
+}
+
+// Test vector negation for 4D vectors.
+void tst_QVector::negate4_data()
+{
+ // Use the same test data as the add test.
+ add4_data();
+}
+void tst_QVector::negate4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(-x1, -y1, -z1, -w1);
+
+ QVERIFY(-v1 == v2);
+}
+
+// Test the computation of vector cross-products.
+void tst_QVector::crossProduct_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("x3");
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("dot");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("unitvec")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("complex")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)6.0f
+ << (qreal)-3.0f << (qreal)6.0f << (qreal)-3.0f
+ << (qreal)32.0f;
+}
+void tst_QVector::crossProduct()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QVector3D v4 = QVector3D::crossProduct(v1, v2);
+ QVERIFY(v4 == v3);
+
+ // Compute the cross-product long-hand and check again.
+ qreal xres = y1 * z2 - z1 * y2;
+ qreal yres = z1 * x2 - x1 * z2;
+ qreal zres = x1 * y2 - y1 * x2;
+
+ QCOMPARE(v4.x(), xres);
+ QCOMPARE(v4.y(), yres);
+ QCOMPARE(v4.z(), zres);
+}
+
+// Test the computation of normals.
+void tst_QVector::normal_data()
+{
+ // Use the same test data as the crossProduct test.
+ crossProduct_data();
+}
+void tst_QVector::normal()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QVERIFY(QVector3D::normal(v1, v2) == v3.normalized());
+ QVERIFY(QVector3D::normal(QVector3D(), v1, v2) == v3.normalized());
+
+ QVector3D point(1.0f, 2.0f, 3.0f);
+ QVERIFY(QVector3D::normal(point, v1 + point, v2 + point) == v3.normalized());
+}
+
+// Test distance to plane calculations.
+void tst_QVector::distanceToPlane_data()
+{
+ QTest::addColumn<qreal>("x1"); // Point on plane
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("x2"); // Normal to plane
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("x3"); // Point to test for distance
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("x4"); // Second point on plane
+ QTest::addColumn<qreal>("y4");
+ QTest::addColumn<qreal>("z4");
+ QTest::addColumn<qreal>("x5"); // Third point on plane
+ QTest::addColumn<qreal>("y5");
+ QTest::addColumn<qreal>("z5");
+ QTest::addColumn<qreal>("distance");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("above")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)2.0f
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)2.0f;
+
+ QTest::newRow("below")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)-1.0f << (qreal)1.0f << (qreal)-2.0f
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)2.0f << (qreal)0.0f
+ << (qreal)-2.0f;
+}
+void tst_QVector::distanceToPlane()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, x4);
+ QFETCH(qreal, y4);
+ QFETCH(qreal, z4);
+ QFETCH(qreal, x5);
+ QFETCH(qreal, y5);
+ QFETCH(qreal, z5);
+ QFETCH(qreal, distance);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+ QVector3D v4(x4, y4, z4);
+ QVector3D v5(x5, y5, z5);
+
+ QCOMPARE(v3.distanceToPlane(v1, v2), distance);
+ QCOMPARE(v3.distanceToPlane(v1, v4, v5), distance);
+}
+
+// Test distance to line calculations.
+void tst_QVector::distanceToLine_data()
+{
+ QTest::addColumn<qreal>("x1"); // Point on line
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("x2"); // Direction of the line
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("x3"); // Point to test for distance
+ QTest::addColumn<qreal>("y3");
+ QTest::addColumn<qreal>("z3");
+ QTest::addColumn<qreal>("distance");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("on line")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)5.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("off line")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)1.0f;
+
+ QTest::newRow("off line 2")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f << (qreal)-2.0f << (qreal)0.0f
+ << (qreal)2.0f;
+
+ QTest::newRow("points")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)5.0f << (qreal)0.0f
+ << (qreal)5.0f;
+}
+void tst_QVector::distanceToLine()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, distance);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+ QVector3D v3(x3, y3, z3);
+
+ QCOMPARE(v3.distanceToLine(v1, v2), distance);
+}
+
+// Test the computation of dot products for 2D vectors.
+void tst_QVector::dotProduct2_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("dot");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("unitvec")
+ << (qreal)1.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)1.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("complex")
+ << (qreal)1.0f << (qreal)2.0f
+ << (qreal)4.0f << (qreal)5.0f
+ << (qreal)14.0f;
+}
+void tst_QVector::dotProduct2()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, dot);
+
+ QVector2D v1(x1, y1);
+ QVector2D v2(x2, y2);
+
+ QVERIFY(QVector2D::dotProduct(v1, v2) == dot);
+
+ // Compute the dot-product long-hand and check again.
+ qreal d = x1 * x2 + y1 * y2;
+
+ QCOMPARE(QVector2D::dotProduct(v1, v2), d);
+}
+
+// Test the computation of dot products for 3D vectors.
+void tst_QVector::dotProduct3_data()
+{
+ // Use the same test data as the crossProduct test.
+ crossProduct_data();
+}
+void tst_QVector::dotProduct3()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, x3);
+ QFETCH(qreal, y3);
+ QFETCH(qreal, z3);
+ QFETCH(qreal, dot);
+
+ Q_UNUSED(x3);
+ Q_UNUSED(y3);
+ Q_UNUSED(z3);
+
+ QVector3D v1(x1, y1, z1);
+ QVector3D v2(x2, y2, z2);
+
+ QVERIFY(QVector3D::dotProduct(v1, v2) == dot);
+
+ // Compute the dot-product long-hand and check again.
+ qreal d = x1 * x2 + y1 * y2 + z1 * z2;
+
+ QCOMPARE(QVector3D::dotProduct(v1, v2), d);
+}
+
+// Test the computation of dot products for 4D vectors.
+void tst_QVector::dotProduct4_data()
+{
+ QTest::addColumn<qreal>("x1");
+ QTest::addColumn<qreal>("y1");
+ QTest::addColumn<qreal>("z1");
+ QTest::addColumn<qreal>("w1");
+ QTest::addColumn<qreal>("x2");
+ QTest::addColumn<qreal>("y2");
+ QTest::addColumn<qreal>("z2");
+ QTest::addColumn<qreal>("w2");
+ QTest::addColumn<qreal>("dot");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("unitvec")
+ << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f
+ << (qreal)0.0f;
+
+ QTest::newRow("complex")
+ << (qreal)1.0f << (qreal)2.0f << (qreal)3.0f << (qreal)4.0f
+ << (qreal)4.0f << (qreal)5.0f << (qreal)6.0f << (qreal)7.0f
+ << (qreal)60.0f;
+}
+void tst_QVector::dotProduct4()
+{
+ QFETCH(qreal, x1);
+ QFETCH(qreal, y1);
+ QFETCH(qreal, z1);
+ QFETCH(qreal, w1);
+ QFETCH(qreal, x2);
+ QFETCH(qreal, y2);
+ QFETCH(qreal, z2);
+ QFETCH(qreal, w2);
+ QFETCH(qreal, dot);
+
+ QVector4D v1(x1, y1, z1, w1);
+ QVector4D v2(x2, y2, z2, w2);
+
+ QVERIFY(QVector4D::dotProduct(v1, v2) == dot);
+
+ // Compute the dot-product long-hand and check again.
+ qreal d = x1 * x2 + y1 * y2 + z1 * z2 + w1 * w2;
+
+ QCOMPARE(QVector4D::dotProduct(v1, v2), d);
+}
+
+QTEST_APPLESS_MAIN(tst_QVector)
+
+#include "tst_qvectornd.moc"
diff --git a/tests/auto/math3d/shared/math3dincludes.h b/tests/auto/math3d/shared/math3dincludes.h
new file mode 100644
index 0000000..1ac0c08
--- /dev/null
+++ b/tests/auto/math3d/shared/math3dincludes.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MATH3DINCLUDES_H
+#define MATH3DINCLUDES_H
+
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qgenericmatrix.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qquaternion.h>
+
+#endif
diff --git a/tests/auto/q3filedialog/tst_q3filedialog.cpp b/tests/auto/q3filedialog/tst_q3filedialog.cpp
index 74e2894..03e1c7e 100644
--- a/tests/auto/q3filedialog/tst_q3filedialog.cpp
+++ b/tests/auto/q3filedialog/tst_q3filedialog.cpp
@@ -115,13 +115,15 @@ void tst_Q3FileDialog::getSetCheck()
obj1.setPreviewMode(Q3FileDialog::PreviewMode(Q3FileDialog::NoPreview));
QCOMPARE(obj1.previewMode(), Q3FileDialog::PreviewMode(Q3FileDialog::NoPreview));
- // Note: Q3FileDialog does not update the previewMode read-state until the
- // user has actually started navigating to a file that has a functioning
- // preview.
+ obj1.setContentsPreviewEnabled(true);
+ obj1.setInfoPreviewEnabled(false);
obj1.setPreviewMode(Q3FileDialog::PreviewMode(Q3FileDialog::Contents));
- QCOMPARE(obj1.previewMode(), Q3FileDialog::PreviewMode(Q3FileDialog::NoPreview));
+ QCOMPARE(obj1.previewMode(), Q3FileDialog::PreviewMode(Q3FileDialog::Contents));
+
+ obj1.setInfoPreviewEnabled(true);
+ obj1.setContentsPreviewEnabled(false);
obj1.setPreviewMode(Q3FileDialog::PreviewMode(Q3FileDialog::Info));
- QCOMPARE(obj1.previewMode(), Q3FileDialog::PreviewMode(Q3FileDialog::NoPreview));
+ QCOMPARE(obj1.previewMode(), Q3FileDialog::PreviewMode(Q3FileDialog::Info));
}
QTEST_MAIN(tst_Q3FileDialog)
diff --git a/tests/auto/q3tabdialog/tst_q3tabdialog.cpp b/tests/auto/q3tabdialog/tst_q3tabdialog.cpp
index 6de68fa..214cb11 100644
--- a/tests/auto/q3tabdialog/tst_q3tabdialog.cpp
+++ b/tests/auto/q3tabdialog/tst_q3tabdialog.cpp
@@ -60,6 +60,7 @@ public:
private slots:
void getSetCheck();
+ void task245918_show();
};
tst_Q3TabDialog::tst_Q3TabDialog()
@@ -95,5 +96,32 @@ void tst_Q3TabDialog::getSetCheck()
delete var1;
}
+class task245918_Dialog : public Q3TabDialog
+{
+ Q_OBJECT
+public:
+ task245918_Dialog()
+ {
+ QTimer::singleShot(100, this, SLOT(closeWhenVisible()));
+ }
+
+ private slots:
+ void closeWhenVisible()
+ {
+ if (isVisible())
+ accept();
+ else
+ QTimer::singleShot(100, this, SLOT(closeWhenVisible()));
+ }
+};
+
+void tst_Q3TabDialog::task245918_show()
+{
+ task245918_Dialog dialog;
+ QSignalSpy spy(&dialog, SIGNAL(aboutToShow()));
+ dialog.exec();
+ QCOMPARE(spy.count(), 1);
+}
+
QTEST_MAIN(tst_Q3TabDialog)
#include "tst_q3tabdialog.moc"
diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp
index dc52416..df770b3 100644
--- a/tests/auto/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp
@@ -4046,7 +4046,7 @@ void tst_QAccessibility::accelerators()
window->show();
QAccessibleInterface *accLineEdit = QAccessible::queryAccessibleInterface(le);
- QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString(QKeySequence(Qt::ALT) + QLatin1String("L")));
+ QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString() + QLatin1String("L"));
label->setText(tr("Q &"));
QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString());
label->setText(tr("Q &&"));
@@ -4054,11 +4054,11 @@ void tst_QAccessibility::accelerators()
label->setText(tr("Q && A"));
QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString());
label->setText(tr("Q &&&A"));
- QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString(QKeySequence(Qt::ALT) + QLatin1String("A")));
+ QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString() + QLatin1String("A"));
label->setText(tr("Q &&A"));
QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString());
label->setText(tr("Q &A&B"));
- QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QString(QKeySequence(Qt::ALT) + QLatin1String("A")));
+ QCOMPARE(accLineEdit->text(QAccessible::Accelerator, 0), QKeySequence(Qt::ALT).toString() + QLatin1String("A"));
#if defined(Q_WS_X11)
qt_x11_wait_for_window_manager(window);
diff --git a/tests/auto/qaction/tst_qaction.cpp b/tests/auto/qaction/tst_qaction.cpp
index 34f2dfd..1b73f06 100644
--- a/tests/auto/qaction/tst_qaction.cpp
+++ b/tests/auto/qaction/tst_qaction.cpp
@@ -46,6 +46,7 @@
#include <qevent.h>
#include <qaction.h>
#include <qmenu.h>
+#include <qlineedit.h>
//TESTED_CLASS=
//TESTED_FILES=
@@ -74,7 +75,10 @@ private slots:
void setStandardKeys();
void alternateShortcuts();
void enabledVisibleInteraction();
+ void invisibleActionWithComplexShortcut();
void task200823_tooltip();
+ void task229128TriggeredSignalWithoutActiongroup();
+ void task229128TriggeredSignalWhenInActiongroup();
private:
int m_lastEventType;
@@ -109,7 +113,7 @@ class MyWidget : public QWidget
{
Q_OBJECT
public:
- MyWidget(tst_QAction *tst, QWidget *parent=0) : QWidget(parent) { this->tst = tst; }
+ MyWidget(tst_QAction *tst, QWidget *parent = 0) : QWidget(parent) { this->tst = tst; }
protected:
virtual void actionEvent(QActionEvent *e) { tst->updateState(e); }
@@ -141,7 +145,7 @@ void tst_QAction::initTestCase()
void tst_QAction::cleanupTestCase()
{
QWidget *testWidget = m_tstWidget;
- if ( testWidget ) {
+ if (testWidget) {
testWidget->hide();
delete testWidget;
}
@@ -189,7 +193,7 @@ void tst_QAction::updateState(QActionEvent *e)
{
if (!e) {
m_lastEventType = 0;
- m_lastAction = 0;
+ m_lastAction = 0;
} else {
m_lastEventType = (int)e->type();
m_lastAction = e->action();
@@ -249,12 +253,12 @@ void tst_QAction::alternateShortcuts()
{
//test the alternate shortcuts (by adding more than 1 shortcut)
- QWidget *wid=m_tstWidget;
+ QWidget *wid = m_tstWidget;
{
QAction act(wid);
wid->addAction(&act);
- QList<QKeySequence> shlist= QList<QKeySequence>() << QKeySequence("CTRL+P") <<QKeySequence("CTRL+A");
+ QList<QKeySequence> shlist = QList<QKeySequence>() << QKeySequence("CTRL+P") << QKeySequence("CTRL+A");
act.setShortcuts(shlist);
QSignalSpy spy(&act, SIGNAL(triggered()));
@@ -322,5 +326,77 @@ void tst_QAction::task200823_tooltip()
QCOMPARE(action->toolTip(), ref);
}
+void tst_QAction::task229128TriggeredSignalWithoutActiongroup()
+{
+ // test without a group
+ QAction *actionWithoutGroup = new QAction("Test", qApp);
+ QSignalSpy spyWithoutGroup(actionWithoutGroup, SIGNAL(triggered(bool)));
+ QCOMPARE(spyWithoutGroup.count(), 0);
+ actionWithoutGroup->trigger();
+ // signal should be emitted
+ QCOMPARE(spyWithoutGroup.count(), 1);
+
+ // it is now a checkable checked action
+ actionWithoutGroup->setCheckable(true);
+ actionWithoutGroup->setChecked(true);
+ spyWithoutGroup.clear();
+ QCOMPARE(spyWithoutGroup.count(), 0);
+ actionWithoutGroup->trigger();
+ // signal should be emitted
+ QCOMPARE(spyWithoutGroup.count(), 1);
+}
+
+void tst_QAction::task229128TriggeredSignalWhenInActiongroup()
+{
+ QActionGroup ag(0);
+ QAction *action = new QAction("Test", &ag);
+ QAction *checkedAction = new QAction("Test 2", &ag);
+ ag.addAction(action);
+ action->setCheckable(true);
+ ag.addAction(checkedAction);
+ checkedAction->setCheckable(true);
+ checkedAction->setChecked(true);
+
+ QSignalSpy actionSpy(checkedAction, SIGNAL(triggered(bool)));
+ QSignalSpy actionGroupSpy(&ag, SIGNAL(triggered(QAction *)));
+ QCOMPARE(actionGroupSpy.count(), 0);
+ QCOMPARE(actionSpy.count(), 0);
+ checkedAction->trigger();
+ // check that both the group and the action have emitted the signal
+ QCOMPARE(actionGroupSpy.count(), 1);
+ QCOMPARE(actionSpy.count(), 1);
+}
+
+void tst_QAction::invisibleActionWithComplexShortcut()
+{
+ QAction action(0);
+ action.setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E, Qt::Key_1));
+
+ QLineEdit edit;
+ edit.addAction(&action);
+ edit.show();
+ QTest::qWait(100);
+
+ QSignalSpy spy(&action, SIGNAL(triggered()));
+
+ action.setVisible(true);
+ QTest::keyPress(&edit, Qt::Key_E, Qt::ControlModifier);
+ QTest::keyRelease(&edit, Qt::Key_E, Qt::ControlModifier);
+ QTest::keyPress(&edit, Qt::Key_1, Qt::NoModifier);
+ QTest::keyRelease(&edit, Qt::Key_1, Qt::NoModifier);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(edit.text(), QLatin1String(""));
+
+ edit.clear();
+ spy.clear();
+ action.setVisible(false);
+ QTest::keyPress(&edit, Qt::Key_E, Qt::ControlModifier);
+ QTest::keyRelease(&edit, Qt::Key_E, Qt::ControlModifier);
+ QTest::keyPress(&edit, Qt::Key_1, Qt::NoModifier);
+ QTest::keyRelease(&edit, Qt::Key_1, Qt::NoModifier);
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(edit.text(), QLatin1String("1"));
+}
+
QTEST_MAIN(tst_QAction)
#include "tst_qaction.moc"
diff --git a/tests/auto/qfiledialog/tst_qfiledialog.cpp b/tests/auto/qfiledialog/tst_qfiledialog.cpp
index 695bfe7..13b13d6 100644
--- a/tests/auto/qfiledialog/tst_qfiledialog.cpp
+++ b/tests/auto/qfiledialog/tst_qfiledialog.cpp
@@ -157,6 +157,8 @@ private slots:
void task228844_ensurePreviousSorting();
void task239706_editableFilterCombo();
void task218353_relativePaths();
+ void task251321_sideBarHiddenEntries();
+ void task251341_sideBarRemoveEntries();
private:
QByteArray userSettings;
@@ -1852,5 +1854,119 @@ void tst_QFiledialog::task218353_relativePaths()
appDir.rmdir("test");
}
+void tst_QFiledialog::task251321_sideBarHiddenEntries()
+{
+ QNonNativeFileDialog fd;
+
+ QDir current = QDir::currentPath();
+ current.mkdir(".hidden");
+ QDir hiddenDir = QDir(".hidden");
+ hiddenDir.mkdir("subdir");
+ QDir hiddenSubDir = QDir(".hidden/subdir");
+ hiddenSubDir.mkdir("happy");
+ hiddenSubDir.mkdir("happy2");
+
+ QList<QUrl> urls;
+ urls << QUrl::fromLocalFile(hiddenSubDir.absolutePath());
+ fd.setSidebarUrls(urls);
+ fd.show();
+ QTest::qWait(250);
+
+ QSidebar *sidebar = qFindChild<QSidebar*>(&fd, "sidebar");
+ sidebar->setFocus();
+ sidebar->selectUrl(QUrl::fromLocalFile(hiddenSubDir.absolutePath()));
+ QTest::mouseClick(sidebar->viewport(), Qt::LeftButton, 0, sidebar->visualRect(sidebar->model()->index(0, 0)).center());
+ QTest::qWait(250);
+
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ QCOMPARE(model->rowCount(model->index(hiddenSubDir.absolutePath())), 2);
+
+ hiddenSubDir.rmdir("happy2");
+ hiddenSubDir.rmdir("happy");
+ hiddenDir.rmdir("subdir");
+ current.rmdir(".hidden");
+}
+
+class MyQSideBar : public QSidebar
+{
+public :
+ MyQSideBar(QWidget *parent = 0) : QSidebar(parent)
+ {}
+
+ void removeSelection() {
+ QList<QModelIndex> idxs = selectionModel()->selectedIndexes();
+ QList<QPersistentModelIndex> indexes;
+ for (int i = 0; i < idxs.count(); i++)
+ indexes.append(idxs.at(i));
+
+ for (int i = 0; i < indexes.count(); ++i)
+ if (!indexes.at(i).data(Qt::UserRole + 1).toUrl().path().isEmpty())
+ model()->removeRow(indexes.at(i).row());
+ }
+};
+
+void tst_QFiledialog::task251341_sideBarRemoveEntries()
+{
+ QNonNativeFileDialog fd;
+
+ QDir current = QDir::currentPath();
+ current.mkdir("testDir");
+ QDir testSubDir = QDir("testDir");
+
+ QList<QUrl> urls;
+ urls << QUrl::fromLocalFile(testSubDir.absolutePath());
+ urls << QUrl::fromLocalFile("NotFound");
+ fd.setSidebarUrls(urls);
+ fd.show();
+ QTest::qWait(250);
+
+ QSidebar *sidebar = qFindChild<QSidebar*>(&fd, "sidebar");
+ sidebar->setFocus();
+ //We enter in the first bookmark
+ sidebar->selectUrl(QUrl::fromLocalFile(testSubDir.absolutePath()));
+ QTest::mouseClick(sidebar->viewport(), Qt::LeftButton, 0, sidebar->visualRect(sidebar->model()->index(0, 0)).center());
+ QTest::qWait(250);
+
+ QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
+ //There is no file
+ QCOMPARE(model->rowCount(model->index(testSubDir.absolutePath())), 0);
+ //Icon is not enabled QUrlModel::EnabledRole
+ QVariant value = sidebar->model()->index(0, 0).data(Qt::UserRole + 2);
+ QCOMPARE(qvariant_cast<bool>(value), true);
+
+ sidebar->setFocus();
+ //We enter in the second bookmark which is invalid
+ sidebar->selectUrl(QUrl::fromLocalFile("NotFound"));
+ QTest::mouseClick(sidebar->viewport(), Qt::LeftButton, 0, sidebar->visualRect(sidebar->model()->index(1, 0)).center());
+ QTest::qWait(250);
+
+ //We fallback to root because the entry in the bookmark is invalid
+ QCOMPARE(model->rowCount(model->index("NotFound")), model->rowCount(model->index(model->rootPath())));
+ //Icon is not enabled QUrlModel::EnabledRole
+ value = sidebar->model()->index(1, 0).data(Qt::UserRole + 2);
+ QCOMPARE(qvariant_cast<bool>(value), false);
+
+ MyQSideBar mySideBar;
+ mySideBar.init(model, urls);
+ mySideBar.show();
+ mySideBar.selectUrl(QUrl::fromLocalFile(testSubDir.absolutePath()));
+ QTest::qWait(1000);
+ mySideBar.removeSelection();
+
+ //We remove the first entry
+ QList<QUrl> expected;
+ expected << QUrl::fromLocalFile("NotFound");
+ QCOMPARE(mySideBar.urls(), expected);
+
+ mySideBar.selectUrl(QUrl::fromLocalFile("NotFound"));
+ mySideBar.removeSelection();
+
+ //We remove the second entry
+ expected.clear();
+ QCOMPARE(mySideBar.urls(), expected);
+
+ current.rmdir("testDir");
+}
+
QTEST_MAIN(tst_QFiledialog)
#include "tst_qfiledialog.moc"
diff --git a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp
index 826d278..59d57ce 100644
--- a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp
+++ b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp
@@ -45,6 +45,7 @@
#include <QFileIconProvider>
#include "../../shared/util.h"
#include <QTime>
+#include <QStyle>
#include <QtGlobal>
//TESTED_CLASS=
@@ -284,6 +285,33 @@ void tst_QFileSystemModel::readOnly()
QVERIFY(model->flags(model->index(file.fileName())) & Qt::ItemIsEditable);
}
+class CustomFileIconProvider : public QFileIconProvider
+{
+public:
+ CustomFileIconProvider() : QFileIconProvider() {
+ mb = qApp->style()->standardIcon(QStyle::SP_MessageBoxCritical);
+ dvd = qApp->style()->standardIcon(QStyle::SP_DriveDVDIcon);
+ }
+
+ virtual QIcon icon(const QFileInfo &info) const
+ {
+ if (info.isDir())
+ return mb;
+
+ return QFileIconProvider::icon(info);
+ }
+ virtual QIcon icon(IconType type) const
+ {
+ if (type == QFileIconProvider::Folder)
+ return dvd;
+
+ return QFileIconProvider::icon(type);
+ }
+private:
+ QIcon mb;
+ QIcon dvd;
+};
+
void tst_QFileSystemModel::iconProvider()
{
QVERIFY(model->iconProvider());
@@ -292,6 +320,19 @@ void tst_QFileSystemModel::iconProvider()
QCOMPARE(model->iconProvider(), p);
model->setIconProvider(0);
delete p;
+
+ QFileSystemModel *myModel = new QFileSystemModel();
+ myModel->setRootPath(QDir::homePath());
+ //Let's wait to populate the model
+ QTest::qWait(250);
+ //We change the provider, icons must me updated
+ CustomFileIconProvider *custom = new CustomFileIconProvider();
+ myModel->setIconProvider(custom);
+
+ QPixmap mb = qApp->style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(50, 50);
+ QCOMPARE(myModel->fileIcon(myModel->index(QDir::homePath())).pixmap(50, 50), mb);
+ delete myModel;
+ delete custom;
}
bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount, const QStringList &initial_dirs, const QString &dir)
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index 5565aa6..57e441b 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -122,6 +122,7 @@ private slots:
void construction();
void constructionWithParent();
void destruction();
+ void deleteChildItem();
void scene();
void parentItem();
void setParentItem();
@@ -214,6 +215,7 @@ private slots:
void tabChangesFocus();
void tabChangesFocus_data();
void cacheMode();
+ void updateCachedItemAfterMove();
// task specific tests below me
void task141694_textItemEnsureVisible();
@@ -510,6 +512,29 @@ void tst_QGraphicsItem::destruction()
QCOMPARE(itemDeleted, 59);
}
QCOMPARE(itemDeleted, 109);
+ {
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsRectItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ parent->setVisible(false);
+ scene->addItem(parent);
+ QCOMPARE(child->parentItem(), parent);
+ delete scene;
+ QCOMPARE(itemDeleted, 110);
+ }
+}
+
+void tst_QGraphicsItem::deleteChildItem()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *rect = scene.addRect(QRectF());
+ QGraphicsItem *child1 = new QGraphicsRectItem(rect);
+ QGraphicsItem *child2 = new QGraphicsRectItem(rect);
+ QGraphicsItem *child3 = new QGraphicsRectItem(rect);
+ delete child1;
+ child2->setParentItem(0);
+ delete child2;
}
void tst_QGraphicsItem::scene()
@@ -3093,150 +3118,134 @@ protected:
void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
{ ++counter; }
};
+
void tst_QGraphicsItem::handlesChildEvents()
{
- ChildEventTester *item2_level2 = new ChildEventTester(QRectF(0, 0, 25, 25));
- ChildEventTester *item1_level1 = new ChildEventTester(QRectF(0, 0, 50, 50));
- ChildEventTester *item_level0 = new ChildEventTester(QRectF(0, 0, 100, 100));
- ChildEventTester *item1_level2 = new ChildEventTester(QRectF(0, 0, 25, 25));
- ChildEventTester *item2_level1 = new ChildEventTester(QRectF(0, 0, 50, 50));
-
- item_level0->setBrush(QBrush(Qt::blue));
- item1_level1->setBrush(QBrush(Qt::red));
- item2_level1->setBrush(QBrush(Qt::yellow));
- item1_level2->setBrush(QBrush(Qt::green));
- item2_level2->setBrush(QBrush(Qt::gray));
- item1_level1->setPos(50, 0);
- item2_level1->setPos(50, 50);
- item1_level2->setPos(25, 0);
- item2_level2->setPos(25, 25);
- item1_level1->setParentItem(item_level0);
- item2_level1->setParentItem(item_level0);
- item1_level2->setParentItem(item1_level1);
- item2_level2->setParentItem(item1_level1);
+ ChildEventTester *blue = new ChildEventTester(QRectF(0, 0, 100, 100));
+ ChildEventTester *red = new ChildEventTester(QRectF(0, 0, 50, 50));
+ ChildEventTester *green = new ChildEventTester(QRectF(0, 0, 25, 25));
+ ChildEventTester *gray = new ChildEventTester(QRectF(0, 0, 25, 25));
+ ChildEventTester *yellow = new ChildEventTester(QRectF(0, 0, 50, 50));
+
+ blue->setBrush(QBrush(Qt::blue));
+ red->setBrush(QBrush(Qt::red));
+ yellow->setBrush(QBrush(Qt::yellow));
+ green->setBrush(QBrush(Qt::green));
+ gray->setBrush(QBrush(Qt::gray));
+ red->setPos(50, 0);
+ yellow->setPos(50, 50);
+ green->setPos(25, 0);
+ gray->setPos(25, 25);
+ red->setParentItem(blue);
+ yellow->setParentItem(blue);
+ green->setParentItem(red);
+ gray->setParentItem(red);
QGraphicsScene scene;
- scene.addItem(item_level0);
-
- // Pull out the items, closest item first
- QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect());
- QCOMPARE(items.at(4), (QGraphicsItem *)item_level0);
- if (item1_level1 < item2_level1) {
- QCOMPARE(items.at(3), (QGraphicsItem *)item1_level1);
- if (item1_level2 < item2_level2) {
- QCOMPARE(items.at(2), (QGraphicsItem *)item1_level2);
- QCOMPARE(items.at(1), (QGraphicsItem *)item2_level2);
- } else {
- QCOMPARE(items.at(2), (QGraphicsItem *)item2_level2);
- QCOMPARE(items.at(1), (QGraphicsItem *)item1_level2);
- }
- QCOMPARE(items.at(0), (QGraphicsItem *)item2_level1);
- } else {
- QCOMPARE(items.at(3), (QGraphicsItem *)item2_level1);
- QCOMPARE(items.at(2), (QGraphicsItem *)item1_level1);
- if (item1_level2 < item2_level2) {
- QCOMPARE(items.at(1), (QGraphicsItem *)item1_level2);
- QCOMPARE(items.at(0), (QGraphicsItem *)item2_level2);
- } else {
- QCOMPARE(items.at(1), (QGraphicsItem *)item2_level2);
- QCOMPARE(items.at(0), (QGraphicsItem *)item1_level2);
- }
- }
+ scene.addItem(blue);
QGraphicsView view(&scene);
view.show();
QTest::qWait(1000);
- QCOMPARE(item_level0->counter, 0);
+ // Pull out the items, closest item first
+ QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect());
+ QCOMPARE(items.at(0), (QGraphicsItem *)yellow);
+ QCOMPARE(items.at(1), (QGraphicsItem *)gray);
+ QCOMPARE(items.at(2), (QGraphicsItem *)green);
+ QCOMPARE(items.at(3), (QGraphicsItem *)red);
+ QCOMPARE(items.at(4), (QGraphicsItem *)blue);
+
+ QCOMPARE(blue->counter, 0);
// Send events to the toplevel item
QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
pressEvent.setButton(Qt::LeftButton);
- pressEvent.setScenePos(item_level0->mapToScene(5, 5));
+ pressEvent.setScenePos(blue->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
releaseEvent.setButton(Qt::LeftButton);
- releaseEvent.setScenePos(item_level0->mapToScene(5, 5));
+ releaseEvent.setScenePos(blue->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 2);
+ QCOMPARE(blue->counter, 2);
// Send events to a level1 item
- pressEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ pressEvent.setScenePos(red->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 2);
- QCOMPARE(item1_level1->counter, 2);
+ QCOMPARE(blue->counter, 2);
+ QCOMPARE(red->counter, 2);
// Send events to a level2 item
- pressEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ pressEvent.setScenePos(green->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 2);
- QCOMPARE(item1_level1->counter, 2);
- QCOMPARE(item1_level2->counter, 2);
+ QCOMPARE(blue->counter, 2);
+ QCOMPARE(red->counter, 2);
+ QCOMPARE(green->counter, 2);
- item_level0->setHandlesChildEvents(true);
+ blue->setHandlesChildEvents(true);
// Send events to a level1 item
- pressEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ pressEvent.setScenePos(red->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 4);
- QCOMPARE(item1_level1->counter, 2);
+ QCOMPARE(blue->counter, 4);
+ QCOMPARE(red->counter, 2);
// Send events to a level2 item
- pressEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ pressEvent.setScenePos(green->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 6);
- QCOMPARE(item1_level1->counter, 2);
- QCOMPARE(item1_level2->counter, 2);
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 2);
+ QCOMPARE(green->counter, 2);
- item_level0->setHandlesChildEvents(false);
+ blue->setHandlesChildEvents(false);
// Send events to a level1 item
- pressEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ pressEvent.setScenePos(red->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 6);
- QCOMPARE(item1_level1->counter, 4);
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 4);
// Send events to a level2 item
- pressEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ pressEvent.setScenePos(green->mapToScene(5, 5));
pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
- releaseEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
QApplication::sendEvent(&scene, &pressEvent);
QApplication::sendEvent(&scene, &releaseEvent);
- QCOMPARE(item_level0->counter, 6);
- QCOMPARE(item1_level1->counter, 4);
- QCOMPARE(item1_level2->counter, 4);
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 4);
+ QCOMPARE(green->counter, 4);
}
void tst_QGraphicsItem::handlesChildEvents2()
@@ -3654,6 +3663,8 @@ void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem()
class ItemChangeTester : public QGraphicsRectItem
{
public:
+ ItemChangeTester(){}
+ ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent) {}
QVariant itemChangeReturnValue;
QGraphicsScene *itemSceneChangeTargetScene;
@@ -3830,6 +3841,20 @@ void tst_QGraphicsItem::itemChange()
QCOMPARE(tester.pos(), QPointF(42, 0));
}
{
+ // ItemZValueChange / ItemZValueHasChanged
+ tester.itemChangeReturnValue = qreal(2.0);
+ tester.setZValue(1.0);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemZValueChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemZValueHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.0)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
+ QCOMPARE(tester.zValue(), qreal(2.0));
+ }
+ {
// ItemFlagsChange
tester.itemChangeReturnValue = QGraphicsItem::ItemIsSelectable;
tester.setFlag(QGraphicsItem::ItemIsSelectable, false);
@@ -3928,6 +3953,39 @@ void tst_QGraphicsItem::itemChange()
QCOMPARE(tester.changes.size(), ++changeCount);
QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildRemovedChange);
QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
+
+ // ItemChildRemovedChange 1
+ ItemChangeTester *test = new ItemChangeTester;
+ test->itemSceneChangeTargetScene = 0;
+ int count = 0;
+ QGraphicsScene *scene = new QGraphicsScene;
+ scene->addItem(test);
+ count = test->changes.size();
+ //We test here the fact that when a child is deleted the parent receive only one ItemChildRemovedChange
+ QGraphicsRectItem *child = new QGraphicsRectItem(test);
+ //We received ItemChildAddedChange
+ QCOMPARE(test->changes.size(), ++count);
+ QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildAddedChange);
+ delete child;
+ child = 0;
+ QCOMPARE(test->changes.size(), ++count);
+ QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
+
+ ItemChangeTester *childTester = new ItemChangeTester(test);
+ //Changes contains all sceneHasChanged and so on, we don't want to test that
+ int childCount = childTester->changes.size();
+ //We received ItemChildAddedChange
+ QCOMPARE(test->changes.size(), ++count);
+ child = new QGraphicsRectItem(childTester);
+ //We received ItemChildAddedChange
+ QCOMPARE(childTester->changes.size(), ++childCount);
+ QCOMPARE(childTester->changes.last(), QGraphicsItem::ItemChildAddedChange);
+ //Delete the child of the top level with all its children
+ delete childTester;
+ //Only one removal
+ QCOMPARE(test->changes.size(), ++count);
+ QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
+ delete scene;
}
{
// ItemChildRemovedChange 2
@@ -4605,7 +4663,7 @@ void tst_QGraphicsItem::itemClipsChildrenToShape2()
QPainter painter(&image);
scene.render(&painter);
painter.end();
-
+
QCOMPARE(image.pixel(5, 5), QColor(0, 0, 255).rgba());
QCOMPARE(image.pixel(5, 10), QRgb(0));
QCOMPARE(image.pixel(10, 5), QRgb(0));
@@ -5262,7 +5320,7 @@ void tst_QGraphicsItem::task240400_clickOnTextItem()
QVERIFY(selectable ? item->isSelected() : !item->isSelected());
- //
+ //
if (textFlags & Qt::TextEditorInteraction)
QVERIFY(item->textCursor().columnNumber() > column);
else
@@ -5308,7 +5366,7 @@ void tst_QGraphicsItem::task243707_addChildBeforeParent()
// inconsistent internal state that can cause a crash. This test shows
// one such crash.
QGraphicsScene scene;
- QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsWidget *widget = new QGraphicsWidget;
QGraphicsWidget *widget2 = new QGraphicsWidget(widget);
scene.addItem(widget2);
QVERIFY(!widget2->parentItem());
@@ -5424,7 +5482,7 @@ void tst_QGraphicsItem::itemTransform_unrelated()
QCOMPARE(stranger1->itemTransform(stranger2).map(QPointF(10, 10)), QPointF(10, 10));
QCOMPARE(stranger2->itemTransform(stranger1).map(QPointF(10, 10)), QPointF(10, 10));
}
-
+
void tst_QGraphicsItem::opacity_data()
{
QTest::addColumn<qreal>("p_opacity");
@@ -5633,7 +5691,7 @@ void tst_QGraphicsItem::nestedClipping()
l1->setData(0, "l1");
l2->setData(0, "l2");
l3->setData(0, "l3");
-
+
QGraphicsView view(&scene);
view.show();
#ifdef Q_WS_X11
@@ -5661,7 +5719,7 @@ void tst_QGraphicsItem::nestedClipping()
QCOMPARE(image.pixel(80, 130), qRgba(255, 255, 0, 255));
QCOMPARE(image.pixel(92, 105), qRgba(0, 255, 0, 255));
QCOMPARE(image.pixel(105, 105), qRgba(0, 0, 255, 255));
-#if 0
+#if 0
// Enable this to compare if the test starts failing.
image.save("nestedClipping_reference.png");
#endif
@@ -5803,7 +5861,7 @@ void tst_QGraphicsItem::tabChangesFocus_data()
void tst_QGraphicsItem::tabChangesFocus()
{
QFETCH(bool, tabChangesFocus);
-
+
QGraphicsScene scene;
QGraphicsTextItem *item = scene.addText("Hello");
item->setTabChangesFocus(tabChangesFocus);
@@ -6038,5 +6096,46 @@ void tst_QGraphicsItem::cacheMode()
QCOMPARE(testerChild2->repaints, 6);
}
+void tst_QGraphicsItem::updateCachedItemAfterMove()
+{
+ // A simple item that uses ItemCoordinateCache
+ EventTester *tester = new EventTester;
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+
+ // Add to a scene, show in a view, ensure it's painted and reset its
+ // repaint counter.
+ QGraphicsScene scene;
+ scene.addItem(tester);
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(125);
+ tester->repaints = 0;
+
+ // Move the item, should not cause repaints
+ tester->setPos(10, 0);
+ QTest::qWait(125);
+ QCOMPARE(tester->repaints, 0);
+
+ // Move then update, should cause one repaint
+ tester->setPos(20, 0);
+ tester->update();
+ QTest::qWait(125);
+ QCOMPARE(tester->repaints, 1);
+
+ // Hiding the item doesn't cause a repaint
+ tester->hide();
+ QTest::qWait(125);
+ QCOMPARE(tester->repaints, 1);
+
+ // Moving a hidden item doesn't cause a repaint
+ tester->setPos(30, 0);
+ tester->update();
+ QTest::qWait(125);
+ QCOMPARE(tester->repaints, 1);
+}
+
QTEST_MAIN(tst_QGraphicsItem)
#include "tst_qgraphicsitem.moc"
diff --git a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index b99f111..d856024 100644
--- a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
+++ b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -175,6 +175,9 @@ private slots:
void bypassGraphicsProxyWidget_data();
void bypassGraphicsProxyWidget();
void dragDrop();
+ void windowFlags_data();
+ void windowFlags();
+ void comboboxWindowFlags();
};
// Subclass that exposes the protected functions.
@@ -3153,6 +3156,67 @@ void tst_QGraphicsProxyWidget::dragDrop()
QCOMPARE(edit->text(), QString("hei"));
}
+void tst_QGraphicsProxyWidget::windowFlags_data()
+{
+ QTest::addColumn<int>("proxyFlags");
+ QTest::addColumn<int>("widgetFlags");
+ QTest::addColumn<int>("resultingProxyFlags");
+ QTest::addColumn<int>("resultingWidgetFlags");
+
+ QTest::newRow("proxy(0) widget(0)") << 0 << 0 << 0 << int(Qt::Window);
+ QTest::newRow("proxy(window)") << int(Qt::Window) << 0 << int(Qt::Window) << int(Qt::Window);
+ QTest::newRow("proxy(window) widget(window)") << int(Qt::Window) << int(Qt::Window) << int(Qt::Window) << int(Qt::Window);
+ QTest::newRow("proxy(0) widget(window)") << int(0) << int(Qt::Window) << int(0) << int(Qt::Window);
+}
+
+void tst_QGraphicsProxyWidget::windowFlags()
+{
+ QFETCH(int, proxyFlags);
+ QFETCH(int, widgetFlags);
+ QFETCH(int, resultingProxyFlags);
+ QFETCH(int, resultingWidgetFlags);
+ Qt::WindowFlags proxyWFlags = Qt::WindowFlags(proxyFlags);
+ Qt::WindowFlags widgetWFlags = Qt::WindowFlags(widgetFlags);
+ Qt::WindowFlags resultingProxyWFlags = Qt::WindowFlags(resultingProxyFlags);
+ Qt::WindowFlags resultingWidgetWFlags = Qt::WindowFlags(resultingWidgetFlags);
+
+ QGraphicsProxyWidget proxy(0, proxyWFlags);
+ QVERIFY((proxy.windowFlags() & proxyWFlags) == proxyWFlags);
+
+ QWidget *widget = new QWidget(0, widgetWFlags);
+ QVERIFY((widget->windowFlags() & widgetWFlags) == widgetWFlags);
+
+ proxy.setWidget(widget);
+
+ if (resultingProxyFlags == 0)
+ QVERIFY(!proxy.windowFlags());
+ else
+ QVERIFY((proxy.windowFlags() & resultingProxyWFlags) == resultingProxyWFlags);
+ QVERIFY((widget->windowFlags() & resultingWidgetWFlags) == resultingWidgetWFlags);
+}
+
+void tst_QGraphicsProxyWidget::comboboxWindowFlags()
+{
+ QComboBox *comboBox = new QComboBox;
+ comboBox->addItem("Item 1");
+ comboBox->addItem("Item 2");
+ comboBox->addItem("Item 3");
+ QWidget *embedWidget = comboBox;
+
+ QGraphicsScene scene;
+ QGraphicsProxyWidget *proxy = scene.addWidget(embedWidget);
+ proxy->setWindowFlags(Qt::Window);
+ QVERIFY(embedWidget->isWindow());
+ QVERIFY(proxy->isWindow());
+
+ comboBox->showPopup();
+
+ QCOMPARE(proxy->childItems().size(), 1);
+ QGraphicsItem *popupProxy = proxy->childItems().first();
+ QVERIFY(popupProxy->isWindow());
+ QVERIFY((static_cast<QGraphicsWidget *>(popupProxy)->windowFlags() & Qt::Popup) == Qt::Popup);
+}
+
QTEST_MAIN(tst_QGraphicsProxyWidget)
#include "tst_qgraphicsproxywidget.moc"
diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
index b5af115..ca88afc 100644
--- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
@@ -72,6 +72,7 @@ Q_DECLARE_METATYPE(QList<QRectF>)
Q_DECLARE_METATYPE(QMatrix)
Q_DECLARE_METATYPE(QPainterPath)
Q_DECLARE_METATYPE(QPointF)
+Q_DECLARE_METATYPE(QPolygonF)
Q_DECLARE_METATYPE(QRectF)
Q_DECLARE_METATYPE(Qt::ScrollBarPolicy)
@@ -159,6 +160,7 @@ private slots:
void itemAt2();
void mapToScene();
void mapToScenePoint();
+ void mapToSceneRect_data();
void mapToSceneRect();
void mapToScenePoly();
void mapToScenePath();
@@ -187,6 +189,7 @@ private slots:
void scrollAfterResize_data();
void scrollAfterResize();
void centerOnDirtyItem();
+ void mouseTracking();
// task specific tests below me
void task172231_untransformableItems();
@@ -1611,23 +1614,51 @@ void tst_QGraphicsView::mapToScenePoint()
view.mapToScene(center) + QPointF(0, -10));
}
+void tst_QGraphicsView::mapToSceneRect_data()
+{
+ QTest::addColumn<QRect>("viewRect");
+ QTest::addColumn<QPolygonF>("scenePoly");
+ QTest::addColumn<qreal>("rotation");
+
+ QTest::newRow("nil") << QRect() << QPolygonF() << qreal(0);
+ QTest::newRow("0, 0, 1, 1") << QRect(0, 0, 1, 1) << QPolygonF(QRectF(0, 0, 1, 1)) << qreal(0);
+ QTest::newRow("0, 0, 10, 10") << QRect(0, 0, 10, 10) << QPolygonF(QRectF(0, 0, 10, 10)) << qreal(0);
+ QTest::newRow("nil") << QRect() << QPolygonF() << qreal(90);
+ QPolygonF p;
+ p << QPointF(0, 0) << QPointF(0, -1) << QPointF(1, -1) << QPointF(1, 0) << QPointF(0, 0);
+ QTest::newRow("0, 0, 1, 1") << QRect(0, 0, 1, 1)
+ << p
+ << qreal(90);
+ p.clear();
+ p << QPointF(0, 0) << QPointF(0, -10) << QPointF(10, -10) << QPointF(10, 0) << QPointF(0, 0);
+ QTest::newRow("0, 0, 10, 10") << QRect(0, 0, 10, 10)
+ << p
+ << qreal(90);
+}
+
void tst_QGraphicsView::mapToSceneRect()
{
- QGraphicsScene scene;
+ QFETCH(QRect, viewRect);
+ QFETCH(QPolygonF, scenePoly);
+ QFETCH(qreal, rotation);
+
+ QGraphicsScene scene(-1000, -1000, 2000, 2000);
+ scene.addRect(25, -25, 50, 50);
QGraphicsView view(&scene);
- view.rotate(90);
- view.setFixedSize(117, 117);
+ view.setFrameStyle(0);
+ view.setAlignment(Qt::AlignTop | Qt::AlignLeft);
+ view.setFixedSize(200, 200);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ view.setResizeAnchor(QGraphicsView::NoAnchor);
view.show();
- QPoint center = view.viewport()->rect().center();
- QRect rect(center + QPoint(10, 0), QSize(10, 10));
- QPolygonF poly;
- poly << view.mapToScene(rect.topLeft());
- poly << view.mapToScene(rect.topRight());
- poly << view.mapToScene(rect.bottomRight());
- poly << view.mapToScene(rect.bottomLeft());
+ view.rotate(rotation);
+
+ QPolygonF poly = view.mapToScene(viewRect);
+ if (!poly.isEmpty())
+ poly << poly[0];
- QCOMPARE(view.mapToScene(rect), poly);
+ QCOMPARE(poly, scenePoly);
}
void tst_QGraphicsView::mapToScenePoly()
@@ -2511,7 +2542,8 @@ void tst_QGraphicsView::replayMouseMove()
// One mouse event should be translated into one scene event.
for (int i = 0; i < 3; ++i) {
- sendMouseMove(view.viewport(), view.viewport()->rect().center());
+ sendMouseMove(view.viewport(), view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::MouseButtons(Qt::LeftButton));
QCOMPARE(viewSpy.count(), i + 1);
QCOMPARE(sceneSpy.count(), i + 1);
}
@@ -2701,6 +2733,7 @@ void tst_QGraphicsView::task186827_deleteReplayedItem()
MouseMoveCounter view;
view.setScene(&scene);
view.show();
+ view.viewport()->setMouseTracking(true);
#ifdef Q_WS_X11
qt_x11_wait_for_window_manager(&view);
#endif
@@ -3044,5 +3077,101 @@ void tst_QGraphicsView::centerOnDirtyItem()
QCOMPARE(before, after);
}
+void tst_QGraphicsView::mouseTracking()
+{
+ // Mouse tracking should only be automatically enabled if items either accept hover events
+ // or have a cursor set. We never disable mouse tracking if it is already enabled.
+
+ { // Make sure mouse tracking is disabled by default.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+ }
+
+ { // Make sure we don't disable mouse tracking in setupViewport/setScene.
+ QGraphicsView view;
+ QWidget *viewport = new QWidget;
+ viewport->setMouseTracking(true);
+ view.setViewport(viewport);
+ QVERIFY(viewport->hasMouseTracking());
+
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ view.setScene(&scene);
+ QVERIFY(viewport->hasMouseTracking());
+ }
+
+ // Make sure we enable mouse tracking when having items that accept hover events.
+ {
+ // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setAcceptHoverEvents(true);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setAcceptHoverEvents(true);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // QGraphicsWidget implicitly accepts hover if it has window decoration.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ scene.addItem(widget);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+ // Enable window decoraton.
+ widget->setWindowFlags(Qt::Window | Qt::WindowTitleHint);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ // Make sure we enable mouse tracking when having items with a cursor set.
+ {
+ // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setCursor(Qt::CrossCursor);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setCursor(Qt::CrossCursor);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ // Make sure we propagate mouse tracking to all views.
+ {
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view1(&scene);
+ QGraphicsView view2(&scene);
+ QGraphicsView view3(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setCursor(Qt::CrossCursor);
+ scene.addItem(item);
+
+ QVERIFY(view1.viewport()->hasMouseTracking());
+ QVERIFY(view2.viewport()->hasMouseTracking());
+ QVERIFY(view3.viewport()->hasMouseTracking());
+ }
+}
+
QTEST_MAIN(tst_QGraphicsView)
#include "tst_qgraphicsview.moc"
diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
index f25a079..56737c3 100644
--- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -146,6 +146,11 @@ private slots:
void setSizes();
void closePopupOnOutsideClick();
void defaultSize();
+ void explicitMouseGrabber();
+ void implicitMouseGrabber();
+ void popupMouseGrabber();
+ void windowFlags_data();
+ void windowFlags();
// Task fixes
void task236127_bspTreeIndexFails();
@@ -1732,6 +1737,10 @@ void tst_QGraphicsWidget::task236127_bspTreeIndexFails()
widget->resize(10, 10);
widget2->resize(10, 10);
widget2->setZValue(1);
+ QCOMPARE(widget2->zValue(), qreal(1));
+ QCOMPARE(widget->zValue(), qreal(0));
+ widget->setData(0, "widget");
+ widget2->setData(0, "widget2");
QGraphicsScene scene;
scene.addItem(widget);
@@ -1742,7 +1751,7 @@ void tst_QGraphicsWidget::task236127_bspTreeIndexFails()
#ifdef Q_WS_X11
qt_x11_wait_for_window_manager(&view);
#endif
- QTest::qWait(50);
+ QTest::qWait(100);
QVERIFY(!scene.itemAt(25, 25));
widget->setGeometry(0, 112, 360, 528);
@@ -1780,6 +1789,382 @@ void tst_QGraphicsWidget::defaultSize()
}
+void tst_QGraphicsWidget::explicitMouseGrabber()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
+ EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
+
+ // Grab without scene
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::grabMouse: cannot grab mouse without scene");
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::ungrabMouse: cannot ungrab mouse without scene");
+ widget->ungrabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 0);
+
+ // Add to scene
+ QGraphicsScene scene;
+ scene.addItem(widget);
+
+ // Ungrab while not grabber
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::ungrabMouse: not a mouse grabber");
+ widget->ungrabMouse();
+
+ // Simple grab with scene
+ QVERIFY(!scene.mouseGrabberItem());
+ widget->grabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ widget->ungrabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+
+ // Grab while grabbing
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::grabMouse: already a mouse grabber");
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+ widget->ungrabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+
+ // Add two more widgets to the scene
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ scene.addItem(widget2);
+ EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
+ EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
+ QGraphicsWidget *widget3 = new QGraphicsWidget;
+ scene.addItem(widget3);
+ EventSpy widget3GrabEventSpy(widget3, QEvent::GrabMouse);
+ EventSpy widget3UngrabEventSpy(widget3, QEvent::UngrabMouse);
+
+ widget->setData(0, "widget");
+ widget2->setData(0, "widget2");
+ widget3->setData(0, "widget3");
+
+ // Simple nested grabbing
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ widget2->grabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 3);
+ QCOMPARE(widget2GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget3->grabMouse();
+ QCOMPARE(widget2UngrabEventSpy.count(), 1);
+ QCOMPARE(widget3GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+ widget3->ungrabMouse();
+ QCOMPARE(widget3UngrabEventSpy.count(), 1);
+ QCOMPARE(widget2GrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget2->ungrabMouse();
+ QCOMPARE(widget2UngrabEventSpy.count(), 2);
+ QCOMPARE(widgetGrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ widget->ungrabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Out of order ungrab
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 5);
+ widget2->grabMouse();
+ QCOMPARE(widget2GrabEventSpy.count(), 3);
+ widget3->grabMouse();
+ QCOMPARE(widget3GrabEventSpy.count(), 2);
+ widget2->ungrabMouse();
+ QCOMPARE(widget3UngrabEventSpy.count(), 2);
+ QCOMPARE(widget2UngrabEventSpy.count(), 4);
+ QCOMPARE(widgetGrabEventSpy.count(), 6);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+}
+
+void tst_QGraphicsWidget::implicitMouseGrabber()
+{
+ QGraphicsScene scene;
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ widget->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget->resize(200, 200);
+ EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
+ EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
+ scene.addItem(widget);
+
+ QVERIFY(!scene.mouseGrabberItem());
+
+ // Click on an item, see if gain and lose implicit mouse grab.
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+
+ // Click on an item that already grabs the mouse. Shouldn't have any effect.
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+ widget->ungrabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Implicit mouse grabber tries to explicitly grab the mouse
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ widget->grabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ widget->ungrabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ QCOMPARE(widgetUngrabEventSpy.count(), 3);
+
+ // Arrival of a new widget
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ widget2->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget2->resize(200, 200);
+ widget2->setPos(205, 0);
+ EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
+ EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
+ scene.addItem(widget2);
+
+ // Implicit grab while there's an explicit grab is not possible.
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 4);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(250, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 4);
+ QCOMPARE(widget2GrabEventSpy.count(), 0);
+ QCOMPARE(widget2UngrabEventSpy.count(), 0);
+
+ scene.removeItem(widget);
+ QCOMPARE(widgetUngrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsWidget::popupMouseGrabber()
+{
+ QGraphicsScene scene;
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Popup);
+ widget->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget->resize(200, 200);
+ EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
+ EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
+
+ // Simply adding a visible popup to the scene immediately grabs the mouse.
+ scene.addItem(widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+
+ // Hiding it loses the grab again.
+ widget->hide();
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Showing it grabs the mosue again
+ widget->show();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+
+ // Add two popups
+ QGraphicsWidget *widget2 = new QGraphicsWidget(0, Qt::Popup);
+ widget2->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget2->resize(200, 200);
+ EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
+ EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
+ QGraphicsWidget *widget3 = new QGraphicsWidget(0, Qt::Popup);
+ widget3->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget3->resize(200, 200);
+ EventSpy widget3GrabEventSpy(widget3, QEvent::GrabMouse);
+ EventSpy widget3UngrabEventSpy(widget3, QEvent::UngrabMouse);
+
+ // Adding to the scene grabs
+ scene.addItem(widget2);
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ QCOMPARE(widget2GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+
+ // Adding to the scene grabs again
+ scene.addItem(widget3);
+ QCOMPARE(widget2UngrabEventSpy.count(), 1);
+ QCOMPARE(widget3GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+
+ // Hiding the topmost widget causes widget 2 to regain grab.
+ widget3->hide();
+ QCOMPARE(widget2GrabEventSpy.count(), 2);
+ QCOMPARE(widget3UngrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget3->show();
+ QCOMPARE(widget2UngrabEventSpy.count(), 2);
+ QCOMPARE(widget3GrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+
+ // Clicking outside the popup still causes it to close (despite that it's
+ // an explicit mouse grabber).
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(500, 500)); // outside
+ qApp->sendEvent(&scene, &event);
+ }
+ QVERIFY(!widget3->isVisible());
+ QCOMPARE(widget3UngrabEventSpy.count(), 2);
+ QCOMPARE(widget2GrabEventSpy.count(), 3);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ QVERIFY(widget2->isVisible());
+ QVERIFY(widget->isVisible());
+ widget3->show();
+ QCOMPARE(widget3GrabEventSpy.count(), 3);
+ QCOMPARE(widget2UngrabEventSpy.count(), 3);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+
+ // This is something of a curiosity. What happens if you call
+ // ungrabMouse() on a popup? The answer is - it loses the grab. If you
+ // hide and show the popup again, it will regain the grab.
+ widget3->ungrabMouse();
+ QCOMPARE(widget3UngrabEventSpy.count(), 3);
+ QCOMPARE(widget2GrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget3->hide();
+ widget3->show();
+ QCOMPARE(widget3GrabEventSpy.count(), 4);
+ QCOMPARE(widget2UngrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+}
+
+void tst_QGraphicsWidget::windowFlags_data()
+{
+ QTest::addColumn<int>("inputFlags");
+ QTest::addColumn<int>("outputFlags");
+
+ QTest::newRow("nil") << 0 << 0;
+
+ // Window types
+ QTest::newRow("Qt::Window") << int(Qt::Window)
+ << int(Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
+ QTest::newRow("Qt::SubWindow") << int(Qt::SubWindow)
+ << int(Qt::SubWindow | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
+ QTest::newRow("Qt::Dialog") << int(Qt::Dialog)
+ << int(Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowContextHelpButtonHint);
+ QTest::newRow("Qt::Sheet") << int(Qt::Sheet)
+ << int(Qt::Sheet | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowContextHelpButtonHint);
+ QTest::newRow("Qt::Tool") << int(Qt::Tool)
+ << int(Qt::Tool | Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
+
+ // Custom window flags
+ QTest::newRow("Qt::FramelessWindowHint") << int(Qt::FramelessWindowHint)
+ << int(Qt::FramelessWindowHint);
+ QTest::newRow("Qt::CustomizeWindowHint") << int(Qt::CustomizeWindowHint)
+ << int(Qt::CustomizeWindowHint);
+}
+
+void tst_QGraphicsWidget::windowFlags()
+{
+ QFETCH(int, inputFlags);
+ QFETCH(int, outputFlags);
+
+ // Construct with flags set already
+ QGraphicsWidget widget(0, Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget.windowFlags(), Qt::WindowFlags(outputFlags));
+
+ // Set flags after construction
+ QGraphicsWidget widget2;
+ widget2.setWindowFlags(Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget2.windowFlags(), Qt::WindowFlags(outputFlags));
+
+ // Reset flags
+ widget2.setWindowFlags(0);
+ QVERIFY(!widget2.windowFlags());
+
+ // Set flags back again
+ widget2.setWindowFlags(Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget2.windowFlags(), Qt::WindowFlags(outputFlags));
+
+ // Construct with custom flags set already
+ QGraphicsWidget widget3(0, Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+ QCOMPARE(widget3.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+
+ // Set custom flags after construction
+ QGraphicsWidget widget4;
+ widget4.setWindowFlags(Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+ QCOMPARE(widget4.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+
+ // Reset flags
+ widget4.setWindowFlags(0);
+ QVERIFY(!widget4.windowFlags());
+
+ // Set custom flags back again
+ widget4.setWindowFlags(Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+ QCOMPARE(widget4.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+
+ QGraphicsWidget *widget5 = new QGraphicsWidget;
+ widget5->setWindowFlags(Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget5->windowFlags(), Qt::WindowFlags(outputFlags));
+ QGraphicsWidget window(0, Qt::Window);
+ widget5->setParentItem(&window);
+ QCOMPARE(widget5->windowFlags(), Qt::WindowFlags(outputFlags));
+}
+
class ProxyStyle : public QCommonStyle
{
public:
diff --git a/tests/auto/qheaderview/tst_qheaderview.cpp b/tests/auto/qheaderview/tst_qheaderview.cpp
index 0867e48..6478854 100644
--- a/tests/auto/qheaderview/tst_qheaderview.cpp
+++ b/tests/auto/qheaderview/tst_qheaderview.cpp
@@ -187,6 +187,7 @@ private slots:
void emptySectionSpan();
void task236450_hidden_data();
void task236450_hidden();
+ void task248050_hideRow();
protected:
QHeaderView *view;
@@ -1919,5 +1920,28 @@ void tst_QHeaderView::task236450_hidden()
}
+void tst_QHeaderView::task248050_hideRow()
+{
+ //this is the sequence of events that make the task fail
+ protected_QHeaderView header(Qt::Vertical);
+ QStandardItemModel model(0, 1);
+ header.setStretchLastSection(false);
+ header.setDefaultSectionSize(17);
+ header.setModel(&model);
+ header.doItemsLayout();
+
+ model.setRowCount(3);
+
+ QCOMPARE(header.sectionPosition(2), 17*2);
+
+ header.hideSection(1);
+ QCOMPARE(header.sectionPosition(2), 17);
+
+ QTest::qWait(100);
+ //the size of the section shouldn't have changed
+ QCOMPARE(header.sectionPosition(2), 17);
+}
+
+
QTEST_MAIN(tst_QHeaderView)
#include "tst_qheaderview.moc"
diff --git a/tests/auto/qlineedit/tst_qlineedit.cpp b/tests/auto/qlineedit/tst_qlineedit.cpp
index 34a64c8..ea1f79f 100644
--- a/tests/auto/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/qlineedit/tst_qlineedit.cpp
@@ -257,6 +257,7 @@ private slots:
void task233101_cursorPosAfterInputMethod_data();
void task233101_cursorPosAfterInputMethod();
void task241436_passwordEchoOnEditRestoreEchoMode();
+ void task248948_redoRemovedSelection();
protected slots:
#ifdef QT3_SUPPORT
@@ -3483,5 +3484,17 @@ void tst_QLineEdit::task241436_passwordEchoOnEditRestoreEchoMode()
testWidget->setEchoMode(QLineEdit::Normal);
}
+void tst_QLineEdit::task248948_redoRemovedSelection()
+{
+ testWidget->setText("a");
+ testWidget->selectAll();
+ QTest::keyPress(testWidget, Qt::Key_Delete);
+ testWidget->undo();
+ testWidget->redo();
+ QTest::keyPress(testWidget, 'a');
+ QTest::keyPress(testWidget, 'b');
+ QCOMPARE(testWidget->text(), QLatin1String("ab"));
+}
+
QTEST_MAIN(tst_QLineEdit)
#include "tst_qlineedit.moc"
diff --git a/tests/auto/qmake/testdata/bundle-spaces/some-file b/tests/auto/qmake/testdata/bundle-spaces/some-file
index 9975dba..e69de29 100644
--- a/tests/auto/qmake/testdata/bundle-spaces/some-file
+++ b/tests/auto/qmake/testdata/bundle-spaces/some-file
@@ -1,6 +0,0 @@
-all:
- C:\git\qt-kinetic-animations\bin\qmake qdir.pro -o Makefile -spec win32-msvc2008
- nmake -f Makefile
-first: all
-qmake:
- C:\git\qt-kinetic-animations\bin\qmake qdir.pro -o Makefile -spec win32-msvc2008
diff --git a/tests/auto/qmenu/tst_qmenu.cpp b/tests/auto/qmenu/tst_qmenu.cpp
index a86b754..5b6e54c 100644
--- a/tests/auto/qmenu/tst_qmenu.cpp
+++ b/tests/auto/qmenu/tst_qmenu.cpp
@@ -684,7 +684,7 @@ void tst_QMenu::task250673_activeMutliColumnSubMenuPosition()
class MyMenu : public QMenu
{
public:
- friend class tst_QMenu;
+ int columnCount() const { return QMenu::columnCount(); }
};
QMenu sub;
diff --git a/tests/auto/qpainterpath/tst_qpainterpath.cpp b/tests/auto/qpainterpath/tst_qpainterpath.cpp
index 3d77f5e..38fb8d7 100644
--- a/tests/auto/qpainterpath/tst_qpainterpath.cpp
+++ b/tests/auto/qpainterpath/tst_qpainterpath.cpp
@@ -107,6 +107,8 @@ private slots:
void operators();
void connectPathDuplicatePoint();
+
+ void translate();
};
// Testing get/set functions
@@ -1167,6 +1169,44 @@ void tst_QPainterPath::connectPathDuplicatePoint()
QCOMPARE(c, a);
}
+void tst_QPainterPath::translate()
+{
+ QPainterPath path;
+
+ // Path with no elements.
+ QCOMPARE(path.currentPosition(), QPointF());
+ path.translate(50.5, 50.5);
+ QCOMPARE(path.currentPosition(), QPointF());
+ QCOMPARE(path.translated(50.5, 50.5).currentPosition(), QPointF());
+
+ // path.isEmpty(), but we have one MoveTo element that should be translated.
+ path.moveTo(50, 50);
+ QCOMPARE(path.currentPosition(), QPointF(50, 50));
+ path.translate(99.9, 99.9);
+ QCOMPARE(path.currentPosition(), QPointF(149.9, 149.9));
+ path.translate(-99.9, -99.9);
+ QCOMPARE(path.currentPosition(), QPointF(50, 50));
+ QCOMPARE(path.translated(-50, -50).currentPosition(), QPointF(0, 0));
+
+ // Complex path.
+ QRegion shape(100, 100, 300, 200, QRegion::Ellipse);
+ shape -= QRect(225, 175, 50, 50);
+ QPainterPath complexPath;
+ complexPath.addRegion(shape);
+ QVector<QPointF> untranslatedElements;
+ for (int i = 0; i < complexPath.elementCount(); ++i)
+ untranslatedElements.append(QPointF(complexPath.elementAt(i)));
+
+ const QPainterPath untranslatedComplexPath(complexPath);
+ const QPointF offset(100, 100);
+ complexPath.translate(offset);
+
+ for (int i = 0; i < complexPath.elementCount(); ++i)
+ QCOMPARE(QPointF(complexPath.elementAt(i)) - offset, untranslatedElements.at(i));
+
+ QCOMPARE(complexPath.translated(-offset), untranslatedComplexPath);
+}
+
QTEST_APPLESS_MAIN(tst_QPainterPath)
#include "tst_qpainterpath.moc"
diff --git a/tests/auto/qpicture/tst_qpicture.cpp b/tests/auto/qpicture/tst_qpicture.cpp
index 954be23..dfa61c7 100644
--- a/tests/auto/qpicture/tst_qpicture.cpp
+++ b/tests/auto/qpicture/tst_qpicture.cpp
@@ -47,6 +47,7 @@
#include <qimage.h>
#include <qdesktopwidget.h>
#include <qapplication.h>
+#include <limits.h>
//TESTED_CLASS=
//TESTED_FILES=
@@ -66,6 +67,9 @@ private slots:
void operator_lt_lt();
void save_restore();
+
+ void boundaryValues_data();
+ void boundaryValues();
};
// Testing get/set functions
@@ -234,5 +238,39 @@ void tst_QPicture::save_restore()
QVERIFY( pix1.toImage() == pix2.toImage() );
}
+void tst_QPicture::boundaryValues_data()
+{
+ QTest::addColumn<int>("x");
+ QTest::addColumn<int>("y");
+ QTest::newRow("max x") << INT_MAX << 50;
+ QTest::newRow("max y") << 50 << INT_MAX;
+ QTest::newRow("max x and y") << INT_MAX << INT_MAX;
+
+ QTest::newRow("min x") << INT_MIN << 50;
+ QTest::newRow("min y") << 50 << INT_MIN;
+ QTest::newRow("min x and y") << INT_MIN << INT_MIN;
+
+ QTest::newRow("min x, max y") << INT_MIN << INT_MAX;
+ QTest::newRow("max x, min y") << INT_MAX << INT_MIN;
+
+}
+
+void tst_QPicture::boundaryValues()
+{
+ QPicture picture;
+
+ QPainter painter;
+ painter.begin(&picture);
+
+ QFETCH(int, x);
+ QFETCH(int, y);
+ painter.drawPoint(QPoint(x, y));
+
+ painter.end();
+
+
+}
+
+
QTEST_MAIN(tst_QPicture)
#include "tst_qpicture.moc"
diff --git a/tests/auto/qpixmap/images/designer.png b/tests/auto/qpixmap/images/designer.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/designer.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png b/tests/auto/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png
new file mode 100644
index 0000000..a4a1924
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_-10_dy_-10_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png b/tests/auto/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png
new file mode 100644
index 0000000..1506af5
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_-10_dy_-10_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_-10_dy_0_50_50_100_100.png b/tests/auto/qpixmap/images/dx_-10_dy_0_50_50_100_100.png
new file mode 100644
index 0000000..8500ab1
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_-10_dy_0_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_-10_dy_0_x_y_w_h.png b/tests/auto/qpixmap/images/dx_-10_dy_0_x_y_w_h.png
new file mode 100644
index 0000000..2145c61
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_-10_dy_0_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png b/tests/auto/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_-128_dy_-128_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_-128_dy_0_x_y_w_h.png b/tests/auto/qpixmap/images/dx_-128_dy_0_x_y_w_h.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_-128_dy_0_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_0_dy_-10_50_50_100_100.png b/tests/auto/qpixmap/images/dx_0_dy_-10_50_50_100_100.png
new file mode 100644
index 0000000..728ee79
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_0_dy_-10_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_0_dy_-10_x_y_w_h.png b/tests/auto/qpixmap/images/dx_0_dy_-10_x_y_w_h.png
new file mode 100644
index 0000000..e9d5850
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_0_dy_-10_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_0_dy_-128_x_y_w_h.png b/tests/auto/qpixmap/images/dx_0_dy_-128_x_y_w_h.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_0_dy_-128_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_0_dy_0_50_50_100_100.png b/tests/auto/qpixmap/images/dx_0_dy_0_50_50_100_100.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_0_dy_0_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_0_dy_0_null.png b/tests/auto/qpixmap/images/dx_0_dy_0_null.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_0_dy_0_null.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_0_dy_0_x_y_w_h.png b/tests/auto/qpixmap/images/dx_0_dy_0_x_y_w_h.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_0_dy_0_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_0_dy_10_50_50_100_100.png b/tests/auto/qpixmap/images/dx_0_dy_10_50_50_100_100.png
new file mode 100644
index 0000000..7c09b17
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_0_dy_10_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_0_dy_10_x_y_w_h.png b/tests/auto/qpixmap/images/dx_0_dy_10_x_y_w_h.png
new file mode 100644
index 0000000..70a6340
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_0_dy_10_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_0_dy_128_x_y_w_h.png b/tests/auto/qpixmap/images/dx_0_dy_128_x_y_w_h.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_0_dy_128_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_0_dy_1_null.png b/tests/auto/qpixmap/images/dx_0_dy_1_null.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_0_dy_1_null.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_10_dy_0_50_50_100_100.png b/tests/auto/qpixmap/images/dx_10_dy_0_50_50_100_100.png
new file mode 100644
index 0000000..85abada
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_10_dy_0_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_10_dy_0_x_y_w_h.png b/tests/auto/qpixmap/images/dx_10_dy_0_x_y_w_h.png
new file mode 100644
index 0000000..3e03450
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_10_dy_0_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_10_dy_10_50_50_100_100.png b/tests/auto/qpixmap/images/dx_10_dy_10_50_50_100_100.png
new file mode 100644
index 0000000..315fbe0
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_10_dy_10_50_50_100_100.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_10_dy_10_x_y_w_h.png b/tests/auto/qpixmap/images/dx_10_dy_10_x_y_w_h.png
new file mode 100644
index 0000000..d91dc71
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_10_dy_10_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_128_dy_0_x_y_w_h.png b/tests/auto/qpixmap/images/dx_128_dy_0_x_y_w_h.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_128_dy_0_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_128_dy_128_64_64_128_128.png b/tests/auto/qpixmap/images/dx_128_dy_128_64_64_128_128.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_128_dy_128_64_64_128_128.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_128_dy_128_x_y_w_h.png b/tests/auto/qpixmap/images/dx_128_dy_128_x_y_w_h.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_128_dy_128_x_y_w_h.png
Binary files differ
diff --git a/tests/auto/qpixmap/images/dx_1_dy_0_null.png b/tests/auto/qpixmap/images/dx_1_dy_0_null.png
new file mode 100644
index 0000000..bca471d
--- /dev/null
+++ b/tests/auto/qpixmap/images/dx_1_dy_0_null.png
Binary files differ
diff --git a/tests/auto/qpixmap/qpixmap.pro b/tests/auto/qpixmap/qpixmap.pro
index e5dace4..70be4be 100644
--- a/tests/auto/qpixmap/qpixmap.pro
+++ b/tests/auto/qpixmap/qpixmap.pro
@@ -13,5 +13,4 @@ wince*: {
win32:LIBS += -lgdi32 -luser32
}
-
-
+RESOURCES += qpixmap.qrc
diff --git a/tests/auto/qpixmap/qpixmap.qrc b/tests/auto/qpixmap/qpixmap.qrc
new file mode 100644
index 0000000..99fde61
--- /dev/null
+++ b/tests/auto/qpixmap/qpixmap.qrc
@@ -0,0 +1,29 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>images/designer.png</file>
+ <file>images/dx_0_dy_0_50_50_100_100.png</file>
+ <file>images/dx_0_dy_0_null.png</file>
+ <file>images/dx_0_dy_0_x_y_w_h.png</file>
+ <file>images/dx_0_dy_-10_50_50_100_100.png</file>
+ <file>images/dx_0_dy_10_50_50_100_100.png</file>
+ <file>images/dx_0_dy_-10_x_y_w_h.png</file>
+ <file>images/dx_0_dy_10_x_y_w_h.png</file>
+ <file>images/dx_0_dy_-128_x_y_w_h.png</file>
+ <file>images/dx_0_dy_128_x_y_w_h.png</file>
+ <file>images/dx_0_dy_1_null.png</file>
+ <file>images/dx_-10_dy_0_50_50_100_100.png</file>
+ <file>images/dx_10_dy_0_50_50_100_100.png</file>
+ <file>images/dx_-10_dy_0_x_y_w_h.png</file>
+ <file>images/dx_10_dy_0_x_y_w_h.png</file>
+ <file>images/dx_-10_dy_-10_50_50_100_100.png</file>
+ <file>images/dx_10_dy_10_50_50_100_100.png</file>
+ <file>images/dx_-10_dy_-10_x_y_w_h.png</file>
+ <file>images/dx_10_dy_10_x_y_w_h.png</file>
+ <file>images/dx_-128_dy_0_x_y_w_h.png</file>
+ <file>images/dx_128_dy_0_x_y_w_h.png</file>
+ <file>images/dx_128_dy_128_64_64_128_128.png</file>
+ <file>images/dx_-128_dy_-128_x_y_w_h.png</file>
+ <file>images/dx_128_dy_128_x_y_w_h.png</file>
+ <file>images/dx_1_dy_0_null.png</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp
index ba117d8..8a6b63b 100644
--- a/tests/auto/qpixmap/tst_qpixmap.cpp
+++ b/tests/auto/qpixmap/tst_qpixmap.cpp
@@ -88,6 +88,9 @@ private slots:
void testMetrics();
+ void scroll_data();
+ void scroll();
+
void fill_data();
void fill();
void fill_transparent();
@@ -302,6 +305,99 @@ void tst_QPixmap::convertFromImage()
QVERIFY( pixmapsAreEqual(&pix, &res) );
}
+void tst_QPixmap::scroll_data()
+{
+ QTest::addColumn<QImage>("input");
+ QTest::addColumn<int>("dx");
+ QTest::addColumn<int>("dy");
+ QTest::addColumn<QRect>("rect");
+ QTest::addColumn<QRegion>("exposed");
+ QTest::addColumn<bool>("newPix");
+
+ QImage input(":/images/designer.png");
+
+ // Noop tests
+ QTest::newRow("null") << QImage() << 0 << 0 << QRect() << QRegion() << false;
+ QTest::newRow("dx_0_dy_0_null") << input << 0 << 0 << QRect() << QRegion() << false;
+ QTest::newRow("dx_1_dy_0_null") << input << 1 << 0 << QRect() << QRegion() << false;
+ QTest::newRow("dx_0_dy_1_null") << input << 0 << 1 << QRect() << QRegion() << false;
+ QTest::newRow("dx_0_dy_0_x_y_w_h") << input << 0 << 0 << input.rect() << QRegion() << false;
+
+ QRegion r;
+ // Scroll whole pixmap
+ r = QRegion(); r += QRect(0, 0, 128, 10);
+ QTest::newRow("dx_0_dy_10_x_y_w_h") << input << 0 << 10 << input.rect() << r << true;
+ r = QRegion(); r += QRect(0, 0, 10, 128);
+ QTest::newRow("dx_10_dy_0_x_y_w_h") << input << 10 << 0 << input.rect() << r << true;
+ r = QRegion(); r += QRect(0, 0, 128, 10); r += QRect(0, 10, 10, 118);
+ QTest::newRow("dx_10_dy_10_x_y_w_h") << input << 10 << 10 << input.rect() << r << true;
+ r = QRegion(); r += QRect(118, 0, 10, 128);
+ QTest::newRow("dx_-10_dy_0_x_y_w_h") << input << -10 << 0 << input.rect() << r << true;
+ r = QRegion(); r += QRect(0, 118, 128, 10);
+ QTest::newRow("dx_0_dy_-10_x_y_w_h") << input << 0 << -10 << input.rect() << r << true;
+ r = QRegion(); r += QRect(118, 0, 10, 118); r += QRect(0, 118, 128, 10);
+ QTest::newRow("dx_-10_dy_-10_x_y_w_h") << input << -10 << -10 << input.rect() << r << true;
+
+ // Scroll part of pixmap
+ QTest::newRow("dx_0_dy_0_50_50_100_100") << input << 0 << 0 << QRect(50, 50, 100, 100) << QRegion() << false;
+ r = QRegion(); r += QRect(50, 50, 10, 78);
+ QTest::newRow("dx_10_dy_0_50_50_100_100") << input << 10 << 0 << QRect(50, 50, 100, 100) << r << true;
+ r = QRegion(); r += QRect(50, 50, 78, 10);
+ QTest::newRow("dx_0_dy_10_50_50_100_100") << input << 0 << 10 << QRect(50, 50, 100, 100) << r << true;
+ r = QRegion(); r += QRect(50, 50, 78, 10); r += QRect(50, 60, 10, 68);
+ QTest::newRow("dx_10_dy_10_50_50_100_100") << input << 10 << 10 << QRect(50, 50, 100, 100) << r << true;
+ r = QRegion(); r += QRect(118, 50, 10, 78);
+ QTest::newRow("dx_-10_dy_0_50_50_100_100") << input << -10 << 0 << QRect(50, 50, 100, 100) << r << true;
+ r = QRegion(); r += QRect(50, 118, 78, 10);
+ QTest::newRow("dx_0_dy_-10_50_50_100_100") << input << 0 << -10 << QRect(50, 50, 100, 100) << r << true;
+ r = QRegion(); r += QRect(118, 50, 10, 68); r += QRect(50, 118, 78, 10);
+ QTest::newRow("dx_-10_dy_-10_50_50_100_100") << input << -10 << -10 << QRect(50, 50, 100, 100) << r << true;
+
+ // Scroll away the whole pixmap
+ r = input.rect();
+ QTest::newRow("dx_128_dy_0_x_y_w_h") << input << 128 << 0 << input.rect() << r << false;
+ QTest::newRow("dx_0_dy_128_x_y_w_h") << input << 0 << 128 << input.rect() << r << false;
+ QTest::newRow("dx_128_dy_128_x_y_w_h") << input << 128 << 128 << input.rect() << r << false;
+ QTest::newRow("dx_-128_dy_0_x_y_w_h") << input << -128 << 0 << input.rect() << r << false;
+ QTest::newRow("dx_0_dy_-128_x_y_w_h") << input << 0 << -128 << input.rect() << r << false;
+ QTest::newRow("dx_-128_dy_-128_x_y_w_h") << input << -128 << -128 << input.rect() << r << false;
+
+ // Scroll away part of the pixmap
+ r = QRegion(); r += QRect(64, 64, 64, 64);
+ QTest::newRow("dx_128_dy_128_64_64_128_128") << input << 128 << 128 << QRect(64, 64, 128, 128) << r << false;
+}
+
+void tst_QPixmap::scroll()
+{
+ QFETCH(QImage, input);
+ QFETCH(int, dx);
+ QFETCH(int, dy);
+ QFETCH(QRect, rect);
+ QFETCH(QRegion, exposed);
+ QFETCH(bool, newPix);
+
+ QPixmap pixmap(input);
+ QRegion exp;
+ qint64 oldKey = pixmap.cacheKey();
+ pixmap.scroll(dx, dy, rect, &exp);
+ if (!newPix)
+ QCOMPARE(pixmap.cacheKey(), oldKey);
+ else
+ QVERIFY(pixmap.cacheKey() != oldKey);
+
+#if 0
+ // Remember to add to resources.
+ QString fileName = QString("images/%1.png").arg(QTest::currentDataTag());
+ pixmap.toImage().save(fileName);
+#else
+ QString fileName = QString(":/images/%1.png").arg(QTest::currentDataTag());
+#endif
+ QImage output(fileName);
+ QVERIFY(input.isNull() == output.isNull());
+ QCOMPARE(pixmap.toImage(), output);
+ QCOMPARE(exp, exposed);
+}
+
void tst_QPixmap::fill_data()
{
QTest::addColumn<uint>("pixel");
diff --git a/tests/auto/qpoint/tst_qpoint.cpp b/tests/auto/qpoint/tst_qpoint.cpp
index 67fefa8..16d55fc 100644
--- a/tests/auto/qpoint/tst_qpoint.cpp
+++ b/tests/auto/qpoint/tst_qpoint.cpp
@@ -60,6 +60,8 @@ public:
private slots:
void getSetCheck();
void division();
+
+ void manhattanLength();
};
tst_QPoint::tst_QPoint()
@@ -70,6 +72,24 @@ tst_QPoint::~tst_QPoint()
{
}
+
+
+void tst_QPoint::manhattanLength()
+{
+ {
+ QPoint p(10, 20);
+ QCOMPARE(p.manhattanLength(), 30);
+ }
+ {
+ QPointF p(10., 20.);
+ QCOMPARE(p.manhattanLength(), 30.);
+ }
+ {
+ QPointF p(10.1, 20.2);
+ QCOMPARE(p.manhattanLength(), 30.3);
+ }
+}
+
// Testing get/set functions
void tst_QPoint::getSetCheck()
{
diff --git a/tests/auto/qprocess/qprocess.pro b/tests/auto/qprocess/qprocess.pro
index 4600f02..ed59f10 100644
--- a/tests/auto/qprocess/qprocess.pro
+++ b/tests/auto/qprocess/qprocess.pro
@@ -3,6 +3,7 @@ SUBDIRS = testProcessCrash \
testProcessEcho \
testProcessEcho2 \
testProcessEcho3 \
+ testProcessEnvironment \
testProcessLoopback \
testProcessNormal \
testProcessOutput \
diff --git a/tests/auto/qprocess/testProcessEnvironment/main.cpp b/tests/auto/qprocess/testProcessEnvironment/main.cpp
new file mode 100644
index 0000000..b5e75bc
--- /dev/null
+++ b/tests/auto/qprocess/testProcessEnvironment/main.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+#if defined(_WIN32_WCE)
+ // no environment in Windows CE
+ return 0;
+#else
+ if (argc == 1)
+ return 1;
+
+ char *env = getenv(argv[1]);
+ if (env) {
+ printf("%s", env);
+ return 0;
+ }
+ return 1;
+#endif
+}
diff --git a/tests/auto/qprocess/testProcessEnvironment/testProcessEnvironment.pro b/tests/auto/qprocess/testProcessEnvironment/testProcessEnvironment.pro
new file mode 100644
index 0000000..14ddae5
--- /dev/null
+++ b/tests/auto/qprocess/testProcessEnvironment/testProcessEnvironment.pro
@@ -0,0 +1,12 @@
+SOURCES = main.cpp
+CONFIG -= qt
+CONFIG += console
+DESTDIR = ./
+
+mac {
+ CONFIG -= app_bundle
+}
+
+# no install rule for application used by test
+INSTALLS =
+
diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp
index 801cce8..ba034ee 100644
--- a/tests/auto/qprocess/tst_qprocess.cpp
+++ b/tests/auto/qprocess/tst_qprocess.cpp
@@ -124,6 +124,8 @@ private slots:
void spaceArgsTest_data();
void spaceArgsTest();
void exitCodeTest();
+ void setEnvironment_data();
+ void setEnvironment();
void systemEnvironment();
void spaceInName();
void lockupsInStartDetached();
@@ -1615,13 +1617,117 @@ void tst_QProcess::removeFileWhileProcessIsRunning()
}
//-----------------------------------------------------------------------------
+void tst_QProcess::setEnvironment_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<QString>("value");
+
+ QTest::newRow("setting-empty") << "tst_QProcess" << "";
+ QTest::newRow("setting") << "tst_QProcess" << "value";
+
+#ifdef Q_OS_WIN
+ QTest::newRow("unsetting") << "PROMPT" << QString();
+ QTest::newRow("overriding") << "PROMPT" << "value";
+#else
+ QTest::newRow("unsetting") << "PATH" << QString();
+ QTest::newRow("overriding") << "PATH" << "value";
+#endif
+}
+
+void tst_QProcess::setEnvironment()
+{
+#if !defined (Q_OS_WINCE)
+ // there is no concept of system variables on Windows CE as there is no console
+
+ // make sure our environment variables are correct
+ QVERIFY(qgetenv("tst_QProcess").isEmpty());
+ QVERIFY(!qgetenv("PATH").isEmpty());
+#ifdef Q_OS_WIN
+ QVERIFY(!qgetenv("PROMPT").isEmpty());
+#endif
+
+ QFETCH(QString, name);
+ QFETCH(QString, value);
+ QString executable = QDir::currentPath() + "/testProcessEnvironment/testProcessEnvironment";
+
+ {
+ QProcess process;
+ QStringList environment = QProcess::systemEnvironment();
+ if (value.isNull()) {
+ int pos;
+ QRegExp rx(name + "=.*");
+#ifdef Q_OS_WIN
+ rx.setCaseSensitivity(Qt::CaseInsensitive);
+#endif
+ while ((pos = environment.indexOf(rx)) != -1)
+ environment.removeAt(pos);
+ } else {
+ environment.append(name + '=' + value);
+ }
+ process.setEnvironment(environment);
+ process.start(executable, QStringList() << name);
+
+ QVERIFY(process.waitForFinished());
+ if (value.isNull())
+ QCOMPARE(process.exitCode(), 1);
+ else if (!value.isEmpty())
+ QCOMPARE(process.exitCode(), 0);
+
+ QCOMPARE(process.readAll(), value.toLocal8Bit());
+ }
+
+ // re-do the test but set the environment twice, to make sure
+ // that the latter addition overrides
+ // this test doesn't make sense in unsetting
+ if (!value.isNull()) {
+ QProcess process;
+ QStringList environment = QProcess::systemEnvironment();
+ environment.prepend(name + "=This is not the right value");
+ environment.append(name + '=' + value);
+ process.setEnvironment(environment);
+ process.start(executable, QStringList() << name);
+
+ QVERIFY(process.waitForFinished());
+ if (!value.isEmpty())
+ QCOMPARE(process.exitCode(), 0);
+
+ QCOMPARE(process.readAll(), value.toLocal8Bit());
+ }
+
+ // use the hash variant now
+ {
+ QProcess process;
+ QHash<QString, QString> environment = QProcess::systemEnvironmentHash();
+ if (value.isNull())
+ environment.remove(name);
+ else
+ environment.insert(name, value);
+ process.setEnvironmentHash(environment);
+ process.start(executable, QStringList() << name);
+
+ QVERIFY(process.waitForFinished());
+ if (value.isNull())
+ QCOMPARE(process.exitCode(), 1);
+ else if (!value.isEmpty())
+ QCOMPARE(process.exitCode(), 0);
+
+ QCOMPARE(process.readAll(), value.toLocal8Bit());
+ }
+#endif
+}
+//-----------------------------------------------------------------------------
void tst_QProcess::systemEnvironment()
{
#if defined (Q_OS_WINCE)
// there is no concept of system variables on Windows CE as there is no console
QVERIFY(QProcess::systemEnvironment().isEmpty());
+ QVERIFY(QProcess::systemEnvironmentHash().isEmpty());
#else
QVERIFY(!QProcess::systemEnvironment().isEmpty());
+ QVERIFY(!QProcess::systemEnvironmentHash().isEmpty());
+
+ QVERIFY(QProcess::systemEnvironmentHash().contains("PATH"));
+ QVERIFY(!QProcess::systemEnvironment().filter(QRegExp("^PATH=", Qt::CaseInsensitive)).isEmpty());
#endif
}
diff --git a/tests/auto/qset/tst_qset.cpp b/tests/auto/qset/tst_qset.cpp
index 5601656..41e6ebd 100644
--- a/tests/auto/qset/tst_qset.cpp
+++ b/tests/auto/qset/tst_qset.cpp
@@ -74,6 +74,7 @@ private slots:
void clear();
void remove();
void contains();
+ void containsSet();
void begin();
void end();
void insert();
@@ -347,6 +348,40 @@ void tst_QSet::contains()
}
}
+void tst_QSet::containsSet()
+{
+ QSet<QString> set1;
+ QSet<QString> set2;
+
+ // empty set contains the empty set
+ QVERIFY(set1.contains(set2));
+
+ for (int i = 0; i < 500; ++i) {
+ set1.insert(QString::number(i));
+ set2.insert(QString::number(i));
+ }
+ QVERIFY(set1.contains(set2));
+
+ set2.remove(QString::number(19));
+ set2.remove(QString::number(82));
+ set2.remove(QString::number(7));
+ QVERIFY(set1.contains(set2));
+
+ set1.remove(QString::number(23));
+ QVERIFY(!set1.contains(set2));
+
+ // filled set contains the empty set as well
+ QSet<QString> set3;
+ QVERIFY(set1.contains(set3));
+
+ // the empty set doesn't contain a filled set
+ QVERIFY(!set3.contains(set1));
+
+ // verify const signature
+ const QSet<QString> set4;
+ QVERIFY(set3.contains(set4));
+}
+
void tst_QSet::begin()
{
QSet<int> set1;
diff --git a/tests/auto/qshortcut/tst_qshortcut.cpp b/tests/auto/qshortcut/tst_qshortcut.cpp
index 69ebf74..cd80204 100644
--- a/tests/auto/qshortcut/tst_qshortcut.cpp
+++ b/tests/auto/qshortcut/tst_qshortcut.cpp
@@ -987,17 +987,16 @@ void tst_QShortcut::keypressConsumption()
cut1->setEnabled(false);
cut2->setEnabled(false);
- // Make sure keypresses is passed on, since all multiple keysequences
- // with Ctrl+I are disabled
+ edit->clear();
sendKeyEvents(edit, Qt::CTRL + Qt::Key_I, 0); // Send key to edit
QCOMPARE( currentResult, NoResult );
QCOMPARE( ambigResult, NoResult );
- QVERIFY(edit->toPlainText().endsWith("<Ctrl+I>"));
+ QVERIFY(edit->toPlainText().isEmpty());
sendKeyEvents(edit, Qt::Key_A, 'a'); // Send key to edit
QCOMPARE( currentResult, NoResult );
QCOMPARE( ambigResult, NoResult );
- QVERIFY(edit->toPlainText().endsWith("<Ctrl+I>a"));
+ QVERIFY(edit->toPlainText().isEmpty());
clearAllShortcuts();
}
diff --git a/tests/auto/qsplitter/qsplitter.pro b/tests/auto/qsplitter/qsplitter.pro
index 99f27b4..a7ff0a6 100644
--- a/tests/auto/qsplitter/qsplitter.pro
+++ b/tests/auto/qsplitter/qsplitter.pro
@@ -8,4 +8,7 @@ wince*: {
addFiles.sources = extradata.txt setSizes3.dat
addFiles.path = .
DEPLOYMENT += addFiles
+ DEFINES += SRCDIR=\\\"./\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
}
diff --git a/tests/auto/qsplitter/tst_qsplitter.cpp b/tests/auto/qsplitter/tst_qsplitter.cpp
index b463f7f..33404e4 100644
--- a/tests/auto/qsplitter/tst_qsplitter.cpp
+++ b/tests/auto/qsplitter/tst_qsplitter.cpp
@@ -213,7 +213,7 @@ void tst_QSplitter::setSizes3_data()
QTest::addColumn<IntList>("collapsibleStates");
QTest::addColumn<bool>("childrenCollapse");
- QFile file("setSizes3.dat");
+ QFile file(SRCDIR "setSizes3.dat");
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Can't open file, reason:" << file.errorString();
return;
diff --git a/tests/auto/qsqldatabase/tst_databases.h b/tests/auto/qsqldatabase/tst_databases.h
index 611077f..ef51285 100644
--- a/tests/auto/qsqldatabase/tst_databases.h
+++ b/tests/auto/qsqldatabase/tst_databases.h
@@ -217,7 +217,7 @@ public:
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 3309, "CLIENT_COMPRESS=1;CLIENT_SSL=1" ); // MySQL 5.0.18 Linux
// addDb( "QMYSQL3", "testdb", "troll", "trond", "iceblink.nokia.troll.no" ); // MySQL 5.0.13 Windows
// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "mysql4-nokia.trolltech.com.au" ); // MySQL 4.1.22-2.el4 linux
-// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "mysql5-nokia.trolltech.com.au" ); // MySQL 5.0.45-7.el5 linux
+// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "mysql5-nokia.trolltech.com.au" ); // MySQL 5.0.45-7.el5 linux
// addDb( "QPSQL7", "testdb", "troll", "trond", "horsehead.nokia.troll.no" ); // V7.2 NOT SUPPORTED!
// addDb( "QPSQL7", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 5434 ); // V7.2 NOT SUPPORTED! Multi-byte
@@ -238,14 +238,15 @@ public:
// addDb( "QIBASE", "/opt/firebird/databases/testdb.fdb", "testuser", "Ee4Gabf6_", "firebird2-nokia.trolltech.com.au" ); // Firebird 2.1.1
// use in-memory database to prevent local files
- addDb("QSQLITE", ":memory:");
-// addDb( "QSQLITE", QDir::toNativeSeparators(QDir::tempPath()+"/foo.db") );
+// addDb("QSQLITE", ":memory:");
+ addDb( "QSQLITE", QDir::toNativeSeparators(QDir::tempPath()+"/foo.db") );
// addDb( "QSQLITE2", QDir::toNativeSeparators(QDir::tempPath()+"/foo2.db") );
// addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=iceblink.nokia.troll.no\\ICEBLINK", "troll", "trond", "" );
// addDb( "QODBC3", "DRIVER={SQL Native Client};SERVER=silence.nokia.troll.no\\SQLEXPRESS", "troll", "trond", "" );
-// addDb( "QODBC", "DRIVER={MySQL ODBC 3.51 Driver};SERVER=mysql5-nokia.trolltech.com.au;DATABASE=testdb", "testuser", "Ee4Gabf6_", "" );
-// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=horsehead.nokia.troll.no;DATABASE=testdb;PORT=4101;UID=troll;PWD=trondk", "troll", "trondk", "" );
+// addDb( "QODBC", "DRIVER={MySQL ODBC 3.51 Driver};SERVER=mysql5-nokia.trolltech.com.au;DATABASE=testdb", "testuser", "Ee4Gabf6_", "" );
+// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=horsehead.nokia.troll.no;DATABASE=testdb;PORT=4101;UID=troll;PWD=trondk", "troll", "trondk", "" );
+// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=silence.nokia.troll.no;DATABASE=testdb;PORT=2392;UID=troll;PWD=trond", "troll", "trond", "" );
}
@@ -312,17 +313,21 @@ public:
QSqlQuery q( db );
QStringList dbtables=db.tables();
- foreach(QString tableName, tableNames)
+ foreach(const QString &tableName, tableNames)
{
wasDropped = true;
QString table=tableName;
if ( db.driver()->isIdentifierEscaped(table, QSqlDriver::TableName))
table = db.driver()->stripDelimiters(table, QSqlDriver::TableName);
- if ( dbtables.contains( table, Qt::CaseSensitive ) )
- wasDropped = q.exec( "drop table " + tableName);
- else if ( dbtables.contains( table, Qt::CaseInsensitive ) )
- wasDropped = q.exec( "drop table " + tableName);
+ foreach(const QString dbtablesName, dbtables) {
+ if(dbtablesName.toUpper() == table.toUpper()) {
+ dbtables.removeAll(dbtablesName);
+ wasDropped = q.exec("drop table " + db.driver()->escapeIdentifier( dbtablesName, QSqlDriver::TableName ));
+ if(!wasDropped)
+ wasDropped = q.exec("drop table " + dbtablesName);
+ }
+ }
if ( !wasDropped )
qWarning() << dbToString(db) << "unable to drop table" << tableName << ':' << q.lastError().text() << "tables:" << dbtables;
@@ -396,12 +401,26 @@ public:
static QByteArray printError( const QSqlError& err )
{
- return QString( "'" + err.driverText() + "' || '" + err.databaseText() + "'" ).toLocal8Bit();
+ QString result;
+ if(err.number() > 0)
+ result += '(' + QString::number(err.number()) + ") ";
+ result += '\'';
+ if(!err.driverText().isEmpty())
+ result += err.driverText() + "' || '";
+ result += err.databaseText() + "'";
+ return result.toLocal8Bit();
}
static QByteArray printError( const QSqlError& err, const QSqlDatabase& db )
{
- return QString( dbToString(db) + ": '" + err.driverText() + "' || '" + err.databaseText() + "'" ).toLocal8Bit();
+ QString result(dbToString(db) + ": ");
+ if(err.number() > 0)
+ result += '(' + QString::number(err.number()) + ") ";
+ result += '\'';
+ if(!err.driverText().isEmpty())
+ result += err.driverText() + "' || '";
+ result += err.databaseText() + "'";
+ return result.toLocal8Bit();
}
static bool isSqlServer( QSqlDatabase db )
diff --git a/tests/auto/qsslsocket/tst_qsslsocket.cpp b/tests/auto/qsslsocket/tst_qsslsocket.cpp
index 4f98624..b9725fd 100644
--- a/tests/auto/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/qsslsocket/tst_qsslsocket.cpp
@@ -133,6 +133,7 @@ private slots:
void addCaCertificates2();
void ciphers();
void connectToHostEncrypted();
+ void connectToHostEncryptedWithVerificationPeerName();
void sessionCipher();
void flush();
void isEncrypted();
@@ -597,6 +598,32 @@ void tst_QSslSocket::connectToHostEncrypted()
QVERIFY(socket->waitForDisconnected());
}
+void tst_QSslSocket::connectToHostEncryptedWithVerificationPeerName()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ this->socket = socket;
+
+ socket->addCaCertificates(QLatin1String("certs/qt-test-server-cacert.pem"));
+#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
+ connect(&socket, SIGNAL(sslErrors(QList<QSslError>)),
+ this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
+#endif
+
+ // connect to the server with its local name, but use the full name for verification.
+ socket->connectToHostEncrypted(QtNetworkSettings::serverLocalName(), 443, QtNetworkSettings::serverName());
+
+ // This should pass unconditionally when using fluke's CA certificate.
+ QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
+
+ socket->disconnectFromHost();
+ QVERIFY(socket->waitForDisconnected());
+
+ QCOMPARE(socket->mode(), QSslSocket::SslClientMode);
+}
+
void tst_QSslSocket::sessionCipher()
{
if (!QSslSocket::supportsSsl())
diff --git a/tests/auto/qtabbar/tst_qtabbar.cpp b/tests/auto/qtabbar/tst_qtabbar.cpp
index 433eb86..31722de 100644
--- a/tests/auto/qtabbar/tst_qtabbar.cpp
+++ b/tests/auto/qtabbar/tst_qtabbar.cpp
@@ -92,6 +92,8 @@ private slots:
void moveTab_data();
void moveTab();
+
+ void task251184_removeTab();
};
// Testing get/set functions
@@ -503,5 +505,35 @@ void tst_QTabBar::moveTab()
bar.callMoveTab(from, to);
}
+
+class MyTabBar : public QTabBar
+{
+ Q_OBJECT
+public slots:
+ void onCurrentChanged()
+ {
+ //we just want this to be done once
+ disconnect(this, SIGNAL(currentChanged(int)), this, SLOT(onCurrentChanged()));
+ removeTab(0);
+ }
+};
+
+void tst_QTabBar::task251184_removeTab()
+{
+ MyTabBar bar;
+ bar.addTab("bar1");
+ bar.addTab("bar2");
+ QCOMPARE(bar.count(), 2);
+ QCOMPARE(bar.currentIndex(), 0);
+
+ bar.connect(&bar, SIGNAL(currentChanged(int)), SLOT(onCurrentChanged()));
+ bar.setCurrentIndex(1);
+
+ QCOMPARE(bar.count(), 1);
+ QCOMPARE(bar.currentIndex(), 0);
+ QCOMPARE(bar.tabText(bar.currentIndex()), QString("bar2"));
+}
+
+
QTEST_MAIN(tst_QTabBar)
#include "tst_qtabbar.moc"
diff --git a/tests/auto/qtableview/tst_qtableview.cpp b/tests/auto/qtableview/tst_qtableview.cpp
index a9b41d8..9595155 100644
--- a/tests/auto/qtableview/tst_qtableview.cpp
+++ b/tests/auto/qtableview/tst_qtableview.cpp
@@ -2540,6 +2540,7 @@ void tst_QTableView::span_data()
<< 2 << 1
<< false;
+ /* This makes no sens.
QTest::newRow("top left 2x0")
<< 10 << 10
<< -1 << -1
@@ -2554,7 +2555,7 @@ void tst_QTableView::span_data()
<< 0 << 0
<< 0 << 2
<< 0 << 2
- << false;
+ << false;*/
QTest::newRow("invalid 2x2")
<< 10 << 10
@@ -2628,7 +2629,7 @@ void tst_QTableView::span()
view.hideRow(hiddenRow);
view.hideColumn(hiddenColumn);
view.show();
-
+
QCOMPARE(view.rowSpan(row, column), expectedRowSpan);
QCOMPARE(view.columnSpan(row, column), expectedColumnSpan);
diff --git a/tests/auto/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
index 6edaee3..46f5f0c 100644
--- a/tests/auto/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
+++ b/tests/auto/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
@@ -2309,7 +2309,7 @@ void tst_QTextDocumentFragment::html_tbody()
QVERIFY(table);
QCOMPARE(table->columns(), 1);
QCOMPARE(table->rows(), 2);
- QVERIFY(table->format().headerRowCount(), 1);
+ QCOMPARE(table->format().headerRowCount(), 1);
QCOMPARE(table->cellAt(0, 0).firstCursorPosition().block().text(), QString("First Cell"));
QCOMPARE(table->cellAt(1, 0).firstCursorPosition().block().text(), QString("Second Cell"));
}
diff --git a/tests/auto/qtoolbutton/tst_qtoolbutton.cpp b/tests/auto/qtoolbutton/tst_qtoolbutton.cpp
index 2c0a0cb..1dbf99b 100644
--- a/tests/auto/qtoolbutton/tst_qtoolbutton.cpp
+++ b/tests/auto/qtoolbutton/tst_qtoolbutton.cpp
@@ -65,6 +65,7 @@ private slots:
void getSetCheck();
void triggered();
void task230994_iconSize();
+ void task176137_autoRepeatOfAction();
protected slots:
void sendMouseClick();
@@ -179,6 +180,25 @@ void tst_QToolButton::task230994_iconSize()
QVERIFY(option.iconSize.isValid());
}
+void tst_QToolButton::task176137_autoRepeatOfAction()
+{
+ QAction action(0);
+ QToolButton tb;
+ tb.setDefaultAction (&action);
+ tb.show();
+ QSignalSpy spy(&action,SIGNAL(triggered()));
+ QTest::mousePress ( &tb, Qt::LeftButton);
+ QTest::mouseRelease ( &tb, Qt::LeftButton, 0, QPoint (), 2000);
+ QCOMPARE(spy.count(),1);
+
+ // try again with auto repeat
+ tb.setAutoRepeat (true);
+ QSignalSpy repeatSpy(&action,SIGNAL(triggered())); // new spy
+ QTest::mousePress ( &tb, Qt::LeftButton);
+ QTest::mouseRelease ( &tb, Qt::LeftButton, 0, QPoint (), 2000);
+ QCOMPARE (repeatSpy.count(), (2000 - tb.autoRepeatDelay()) / tb.autoRepeatInterval() + 1);
+}
+
void tst_QToolButton::sendMouseClick()
{
diff --git a/tests/auto/qtreeview/tst_qtreeview.cpp b/tests/auto/qtreeview/tst_qtreeview.cpp
index 655ea4e..37cb5b0 100644
--- a/tests/auto/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/qtreeview/tst_qtreeview.cpp
@@ -225,6 +225,7 @@ private slots:
void task238873_avoidAutoReopening();
void task244304_clickOnDecoration();
void task246536_scrollbarsNotWorking();
+ void task250683_wrongSectionSize();
};
class QtTestModel: public QAbstractItemModel
@@ -3272,5 +3273,22 @@ void tst_QTreeView::task246536_scrollbarsNotWorking()
QVERIFY(o.count > 0);
}
+
+void tst_QTreeView::task250683_wrongSectionSize()
+{
+ QDirModel model;
+ QTreeView treeView;
+ treeView.header()->setResizeMode(QHeaderView::ResizeToContents);
+ treeView.setModel(&model);
+ treeView.setColumnHidden(2, true);
+ treeView.setColumnHidden(3, true);
+
+ treeView.show();
+ QTest::qWait(100);
+
+ QCOMPARE(treeView.header()->sectionSize(0) + treeView.header()->sectionSize(1), treeView.viewport()->width());
+}
+
+
QTEST_MAIN(tst_QTreeView)
#include "tst_qtreeview.moc"
diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp
index a052034..9547c8f 100644
--- a/tests/auto/qwidget/tst_qwidget.cpp
+++ b/tests/auto/qwidget/tst_qwidget.cpp
@@ -1544,6 +1544,10 @@ void tst_QWidget::focusChainOnReparent()
QCOMPARE(w, expectedOriginalChain[i]);
w = w->nextInFocusChain();
}
+ for (int i = 7; i >= 0; --i) {
+ w = w->previousInFocusChain();
+ QCOMPARE(w, expectedOriginalChain[i]);
+ }
QWidget window2;
child2->setParent(&window2);
@@ -1554,6 +1558,10 @@ void tst_QWidget::focusChainOnReparent()
QCOMPARE(w, expectedNewChain[i]);
w = w->nextInFocusChain();
}
+ for (int i = 4; i >= 0; --i) {
+ w = w->previousInFocusChain();
+ QCOMPARE(w, expectedNewChain[i]);
+ }
QWidget *expectedOldChain[5] = {&window, child1, child3, child4, &window};
w = &window;
@@ -1561,6 +1569,10 @@ void tst_QWidget::focusChainOnReparent()
QCOMPARE(w, expectedOldChain[i]);
w = w->nextInFocusChain();
}
+ for (int i = 4; i >= 0; --i) {
+ w = w->previousInFocusChain();
+ QCOMPARE(w, expectedOldChain[i]);
+ }
}
@@ -5775,6 +5787,35 @@ void tst_QWidget::setToolTip()
widget.setToolTip(QString());
QCOMPARE(widget.toolTip(), QString());
QCOMPARE(spy.count(), 2);
+
+
+
+ for (int pass = 0; pass < 2; ++pass) {
+ QWidget *popup = new QWidget(0, Qt::Popup);
+ popup->resize(150, 50);
+ QFrame *frame = new QFrame(popup);
+ frame->setGeometry(0, 0, 50, 50);
+ frame->setFrameStyle(QFrame::Box | QFrame::Plain);
+ EventSpy spy1(frame, QEvent::ToolTip);
+ EventSpy spy2(popup, QEvent::ToolTip);
+ frame->setMouseTracking(pass == 0 ? false : true);
+ frame->setToolTip(QLatin1String("TOOLTIP FRAME"));
+ popup->setToolTip(QLatin1String("TOOLTIP POPUP"));
+ popup->show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(popup);
+#endif
+ QTest::qWait(100);
+ QTest::mouseMove(frame);
+ QTest::qWait(900); // delay is 700
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 0);
+ if (pass == 0)
+ QTest::qWait(2200); // delay is 2000
+ QTest::mouseMove(popup);
+ delete popup;
+ }
}
void tst_QWidget::testWindowIconChangeEventPropagation()
diff --git a/tests/auto/selftests/badxml/badxml.pro b/tests/auto/selftests/badxml/badxml.pro
new file mode 100644
index 0000000..323791a
--- /dev/null
+++ b/tests/auto/selftests/badxml/badxml.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+
+SOURCES += tst_badxml.cpp
+QT = core
+
+mac:CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+!win32:CONFIG += debug
+
+TARGET = badxml
+
diff --git a/tests/auto/selftests/badxml/tst_badxml.cpp b/tests/auto/selftests/badxml/tst_badxml.cpp
new file mode 100644
index 0000000..6b2e4c4
--- /dev/null
+++ b/tests/auto/selftests/badxml/tst_badxml.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtCore>
+#include <QtTest/QtTest>
+
+/*
+ This test makes a testlog containing lots of characters which have a special meaning in
+ XML, with the purpose of exposing bugs in testlib's XML output code.
+*/
+class tst_BadXml : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void badDataTag() const;
+ void badDataTag_data() const;
+
+ void badMessage() const;
+ void badMessage_data() const;
+
+public:
+ static QList<QByteArray> const& badStrings();
+};
+
+/*
+ Custom metaobject to make it possible to change class name at runtime.
+*/
+class EmptyClass : public tst_BadXml
+{ Q_OBJECT };
+
+class tst_BadXmlSub : public tst_BadXml
+{
+public:
+ const QMetaObject* metaObject() const;
+
+ static char const* className;
+};
+char const* tst_BadXmlSub::className = "tst_BadXml";
+
+const QMetaObject* tst_BadXmlSub::metaObject() const
+{
+ const QMetaObject& empty = EmptyClass::staticMetaObject;
+ static QMetaObject mo = {
+ { empty.d.superdata, empty.d.stringdata, empty.d.data, empty.d.extradata }
+ };
+ static char currentClassName[1024];
+ qstrcpy(currentClassName, className);
+ int len = qstrlen(className);
+ currentClassName[len] = 0;
+ currentClassName[len+1] = 0;
+
+ mo.d.stringdata = currentClassName;
+
+ return &mo;
+}
+
+/*
+ Outputs incidents and benchmark results with the current data tag set to a bad string.
+*/
+void tst_BadXml::badDataTag() const
+{
+ qDebug("a message");
+
+ QBENCHMARK {
+ }
+
+ QFAIL("a failure");
+}
+
+void tst_BadXml::badDataTag_data() const
+{
+ QTest::addColumn<int>("dummy");
+
+ foreach (char const* str, badStrings()) {
+ QTest::newRow(str) << 0;
+ }
+}
+
+/*
+ Outputs a message containing a bad string.
+*/
+void tst_BadXml::badMessage() const
+{
+ QFETCH(QByteArray, message);
+ qDebug("%s", message.constData());
+}
+
+void tst_BadXml::badMessage_data() const
+{
+ QTest::addColumn<QByteArray>("message");
+
+ int i = 0;
+ foreach (QByteArray const& str, badStrings()) {
+ QTest::newRow(qPrintable(QString::fromLatin1("string %1").arg(i++))) << str;
+ }
+}
+
+/*
+ Returns a list of strings likely to expose bugs in XML output code.
+*/
+QList<QByteArray> const& tst_BadXml::badStrings()
+{
+ static QList<QByteArray> out;
+ if (out.isEmpty()) {
+ out << "end cdata ]]> text ]]> more text";
+ out << "quotes \" text\" more text";
+ out << "xml close > open < tags < text";
+ out << "all > \" mixed ]]> up > \" in < the ]]> hopes < of triggering \"< ]]> bugs";
+ }
+ return out;
+}
+
+int main(int argc, char** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ /*
+ tst_selftests can't handle multiple XML documents in a single testrun, so we'll
+ decide before we begin which of our "bad strings" we want to use for our testcase
+ name.
+ */
+ int badstring = -1;
+ QVector<char const*> args;
+ for (int i = 0; i < argc; ++i) {
+ if (!strcmp(argv[i], "-badstring")) {
+ bool ok = false;
+ if (i < argc-1) {
+ badstring = QByteArray(argv[i+1]).toInt(&ok);
+ ++i;
+ }
+ if (!ok) {
+ qFatal("Bad `-badstring' option");
+ }
+ }
+ else {
+ args << argv[i];
+ }
+ }
+ /*
+ We just want testlib to output a benchmark result, we don't actually care about the value,
+ so just do one iteration to save time.
+ */
+ args << "-iterations" << "1";
+
+ if (badstring == -1) {
+ tst_BadXml test;
+ return QTest::qExec(&test, args.count(), const_cast<char**>(args.data()));
+ }
+
+ QList<QByteArray> badstrings = tst_BadXml::badStrings();
+ if (badstring >= badstrings.count())
+ qFatal("`-badstring %d' is out of range", badstring);
+
+ tst_BadXmlSub test;
+ test.className = badstrings[badstring].constData();
+ return QTest::qExec(&test, args.count(), const_cast<char**>(args.data()));
+}
+
+#include "tst_badxml.moc"
diff --git a/tests/auto/selftests/expected_skip.txt b/tests/auto/selftests/expected_skip.txt
index ba41e67..88c0426 100644
--- a/tests/auto/selftests/expected_skip.txt
+++ b/tests/auto/selftests/expected_skip.txt
@@ -1,13 +1,13 @@
********* Start testing of tst_Skip *********
-Config: Using QTest library 4.3.0, Qt 4.3.0
+Config: Using QTest library 4.6.0, Qt 4.6.0
PASS : tst_Skip::initTestCase()
SKIP : tst_Skip::test() skipping all
- Loc: [/home/fenglich/dev/qt-4.3/tests/auto/selftests/skip/tst_skip.cpp(35)]
+ Loc: [/home/rmcgover/depot/qt-git/mainline/tests/auto/selftests/skip/tst_skip.cpp(68)]
SKIP : tst_Skip::emptytest() skipping all
- Loc: [/home/fenglich/dev/qt-4.3/tests/auto/selftests/skip/tst_skip.cpp(45)]
+ Loc: [/home/rmcgover/depot/qt-git/mainline/tests/auto/selftests/skip/tst_skip.cpp(78)]
SKIP : tst_Skip::singleSkip(local 1) skipping one
- Loc: [/home/fenglich/dev/qt-4.3/tests/auto/selftests/skip/tst_skip.cpp(64)]
-this line should only be reached once (true)
+ Loc: [/home/rmcgover/depot/qt-git/mainline/tests/auto/selftests/skip/tst_skip.cpp(97)]
+QDEBUG : tst_Skip::singleSkip(local 2) this line should only be reached once (true)
PASS : tst_Skip::singleSkip()
PASS : tst_Skip::cleanupTestCase()
Totals: 3 passed, 0 failed, 3 skipped
diff --git a/tests/auto/selftests/expected_xunit.txt b/tests/auto/selftests/expected_xunit.txt
new file mode 100644
index 0000000..0f7e70a
--- /dev/null
+++ b/tests/auto/selftests/expected_xunit.txt
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite errors="3" failures="2" tests="6" name="tst_Xunit">
+ <properties>
+ <property value="4.6.0" name="QTestVersion"/>
+ <property value="4.6.0" name="QtVersion"/>
+ </properties>
+ <testcase result="pass" name="initTestCase"/>
+ <testcase result="pass" name="testFunc1">
+ <error message="just a QWARN() !" type="warn"/>
+ </testcase>
+ <testcase result="fail" name="testFunc2">
+ <error message="a qDebug() call!" type="qdebug"/>
+ <failure message="Compared values are not the same
+ Actual (2): 2
+ Expected (3): 3" result="fail"/>
+ </testcase>
+ <testcase name="testFunc3">
+ <error message="skipping this function!" type="skip"/>
+ </testcase>
+ <testcase result="fail" name="testFunc4">
+ <failure message="a forced failure!" result="fail"/>
+ </testcase>
+ <testcase result="pass" name="cleanupTestCase"/>
+</testsuite>
diff --git a/tests/auto/selftests/selftests.pro b/tests/auto/selftests/selftests.pro
index 2fa1d50..ca69afa 100644
--- a/tests/auto/selftests/selftests.pro
+++ b/tests/auto/selftests/selftests.pro
@@ -5,7 +5,7 @@ SUBDIRS = subtest test warnings maxwarnings cmptest globaldata skipglobal skip \
skipinit skipinitdata datetime singleskip assert waitwithoutgui differentexec \
exception qexecstringlist datatable commandlinedata\
benchlibwalltime benchlibcallgrind benchlibeventcounter benchlibtickcounter \
- benchliboptions
+ benchliboptions xunit badxml
INSTALLS =
diff --git a/tests/auto/selftests/selftests.qrc b/tests/auto/selftests/selftests.qrc
index 125619e..d57ff29 100644
--- a/tests/auto/selftests/selftests.qrc
+++ b/tests/auto/selftests/selftests.qrc
@@ -34,5 +34,6 @@
<file>expected_benchlibeventcounter.txt</file>
<file>expected_benchliboptions.txt</file>
<file>expected_benchlibtickcounter.txt</file>
+ <file>expected_xunit.txt</file>
</qresource>
</RCC>
diff --git a/tests/auto/selftests/skip/tst_skip.cpp b/tests/auto/selftests/skip/tst_skip.cpp
index b1a3936..437cf62 100644
--- a/tests/auto/selftests/skip/tst_skip.cpp
+++ b/tests/auto/selftests/skip/tst_skip.cpp
@@ -70,7 +70,7 @@ void tst_Skip::test_data()
void tst_Skip::test()
{
- printf("this line should never be reached, since we skip in the _data function\n");
+ qDebug("this line should never be reached, since we skip in the _data function");
}
void tst_Skip::emptytest_data()
@@ -80,7 +80,7 @@ void tst_Skip::emptytest_data()
void tst_Skip::emptytest()
{
- printf("this line should never be reached, since we skip in the _data function\n");
+ qDebug("this line should never be reached, since we skip in the _data function");
}
void tst_Skip::singleSkip_data()
@@ -95,7 +95,7 @@ void tst_Skip::singleSkip()
QFETCH(bool, booll);
if (!booll)
QSKIP("skipping one", SkipSingle);
- printf("this line should only be reached once (%s)\n", booll ? "true" : "false");
+ qDebug("this line should only be reached once (%s)", booll ? "true" : "false");
}
QTEST_MAIN(tst_Skip)
diff --git a/tests/auto/selftests/tst_selftests.cpp b/tests/auto/selftests/tst_selftests.cpp
index 103fd79..aa1048b 100644
--- a/tests/auto/selftests/tst_selftests.cpp
+++ b/tests/auto/selftests/tst_selftests.cpp
@@ -54,9 +54,13 @@ private slots:
void runSubTest();
void checkXML() const;
void checkXML_data();
+ void checkXunitxml() const;
+ void checkXunitxml_data();
private:
QStringList m_checkXMLBlacklist;
+ QStringList m_checkXunitBlacklist;
+ void doRunSubTest(QString &subdir, QStringList &arguments );
};
struct BenchmarkResult
@@ -186,17 +190,16 @@ void tst_Selftests::runSubTest_data()
QTest::newRow("benchlibtickcounter") << "benchlibtickcounter" << QStringList("-tickcounter");
#endif
+ QTest::newRow("xunit") << "xunit" << QStringList("-xunitxml");
+
}
-void tst_Selftests::runSubTest()
+void tst_Selftests::doRunSubTest(QString &subdir, QStringList &arguments )
{
- QFETCH(QString, subdir);
- QFETCH(QStringList, arguments);
-
QProcess proc;
proc.setEnvironment(QStringList(""));
proc.start(subdir + "/" + subdir, arguments);
- QVERIFY(proc.waitForFinished());
+ QVERIFY2(proc.waitForFinished(), qPrintable(proc.errorString()));
const QByteArray out(proc.readAllStandardOutput());
const QByteArray err(proc.readAllStandardError());
@@ -206,8 +209,8 @@ void tst_Selftests::runSubTest()
#if defined(Q_OS_WIN)
if(subdir != QLatin1String("exception") && subdir != QLatin1String("fetchbogus"))
#endif
- QVERIFY2(err.isEmpty(), err.constData());
-
+ if(subdir != QLatin1String("xunit"))
+ QVERIFY2(err.isEmpty(), err.constData());
QList<QByteArray> res = splitLines(out);
QList<QByteArray> exp = expectedResult(subdir);
@@ -255,8 +258,8 @@ void tst_Selftests::runSubTest()
{
if(output != expected && qstrcmp(QTest::currentDataTag(), "subtest") == 0)
{
- /* The floating point formatting differs between platforms, so let's just skip it. */
- continue;
+ /* The floating point formatting differs between platforms, so let's just skip it. */
+ continue;
}
else {
/*
@@ -284,6 +287,14 @@ void tst_Selftests::runSubTest()
}
}
+void tst_Selftests::runSubTest()
+{
+ QFETCH(QString, subdir);
+ QFETCH(QStringList, arguments);
+
+ doRunSubTest(subdir, arguments);
+}
+
void tst_Selftests::initTestCase()
{
m_checkXMLBlacklist.append("crashes"); // This test crashes
@@ -295,6 +306,14 @@ void tst_Selftests::initTestCase()
m_checkXMLBlacklist.append("differentexec");
m_checkXMLBlacklist.append("qexecstringlist");
m_checkXMLBlacklist.append("benchliboptions");
+
+ m_checkXunitBlacklist = m_checkXMLBlacklist;
+ m_checkXunitBlacklist.append("benchlibwalltime");
+ m_checkXunitBlacklist.append("benchlibeventcounter");
+ m_checkXunitBlacklist.append("benchlibcallgrind");
+ m_checkXunitBlacklist.append("subtest");
+ m_checkXunitBlacklist.append("globaldata");
+ m_checkXunitBlacklist.append("warnings");
}
void tst_Selftests::checkXML() const
@@ -306,6 +325,45 @@ void tst_Selftests::checkXML() const
return;
arguments.prepend("-xml");
+ arguments.prepend("-flush");
+
+ QProcess proc;
+ proc.setEnvironment(QStringList(""));
+ proc.start(subdir + "/" + subdir, arguments);
+ QVERIFY(proc.waitForFinished());
+
+ QByteArray out(proc.readAllStandardOutput());
+ QByteArray err(proc.readAllStandardError());
+
+ /* Some platforms decides to output a message for uncaught exceptions. For instance,
+ * this is what windows platforms says:
+ * "This application has requested the Runtime to terminate it in an unusual way.
+ * Please contact the application's support team for more information." */
+ if(subdir != QLatin1String("exception") && subdir != QLatin1String("fetchbogus"))
+ QVERIFY2(err.isEmpty(), err.constData());
+
+ QXmlStreamReader reader(out);
+
+ while(!reader.atEnd())
+ reader.readNext();
+
+ QVERIFY2(!reader.error(), qPrintable(QString("line %1, col %2: %3")
+ .arg(reader.lineNumber())
+ .arg(reader.columnNumber())
+ .arg(reader.errorString())
+ ));
+}
+
+void tst_Selftests::checkXunitxml() const
+{
+ QFETCH(QString, subdir);
+ QFETCH(QStringList, arguments);
+
+ if(m_checkXunitBlacklist.contains(subdir))
+ return;
+
+ arguments.prepend("-xunitxml");
+ arguments.prepend("-flush");
QProcess proc;
proc.setEnvironment(QStringList(""));
@@ -315,6 +373,8 @@ void tst_Selftests::checkXML() const
QByteArray out(proc.readAllStandardOutput());
QByteArray err(proc.readAllStandardError());
+// qDebug()<<out;
+
/* Some platforms decides to output a message for uncaught exceptions. For instance,
* this is what windows platforms says:
* "This application has requested the Runtime to terminate it in an unusual way.
@@ -327,12 +387,26 @@ void tst_Selftests::checkXML() const
while(!reader.atEnd())
reader.readNext();
- QVERIFY(!reader.error());
+ QVERIFY2(!reader.error(), qPrintable(QString("line %1, col %2: %3")
+ .arg(reader.lineNumber())
+ .arg(reader.columnNumber())
+ .arg(reader.errorString())
+ ));
+}
+
+void tst_Selftests::checkXunitxml_data()
+{
+ checkXML_data();
}
void tst_Selftests::checkXML_data()
{
runSubTest_data();
+ QTest::newRow("badxml 1") << "badxml" << QStringList();
+ QTest::newRow("badxml 2") << "badxml" << (QStringList() << "-badstring" << "0");
+ QTest::newRow("badxml 3") << "badxml" << (QStringList() << "-badstring" << "1");
+ QTest::newRow("badxml 4") << "badxml" << (QStringList() << "-badstring" << "2");
+ QTest::newRow("badxml 5") << "badxml" << (QStringList() << "-badstring" << "3");
}
/* Parse line into the BenchmarkResult it represents. */
diff --git a/tests/auto/selftests/xunit/tst_xunit b/tests/auto/selftests/xunit/tst_xunit
new file mode 100755
index 0000000..31d03a8
--- /dev/null
+++ b/tests/auto/selftests/xunit/tst_xunit
Binary files differ
diff --git a/tests/auto/selftests/xunit/tst_xunit.cpp b/tests/auto/selftests/xunit/tst_xunit.cpp
new file mode 100644
index 0000000..d0b585f
--- /dev/null
+++ b/tests/auto/selftests/xunit/tst_xunit.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+class tst_Xunit : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_Xunit();
+
+private slots:
+ void testFunc1();
+ void testFunc2();
+ void testFunc3();
+ void testFunc4();
+};
+
+tst_Xunit::tst_Xunit()
+{
+}
+
+void tst_Xunit::testFunc1()
+{
+ QWARN("just a QWARN() !");
+ QCOMPARE(1,1);
+}
+
+void tst_Xunit::testFunc2()
+{
+ qDebug("a qDebug() call!");
+ QCOMPARE(2, 3);
+}
+
+void tst_Xunit::testFunc3()
+{
+ QSKIP("skipping this function!", SkipAll);
+}
+
+void tst_Xunit::testFunc4()
+{
+ QFAIL("a forced failure!");
+}
+
+
+QTEST_APPLESS_MAIN(tst_Xunit)
+#include "tst_xunit.moc"
diff --git a/tests/auto/selftests/xunit/xunit.pro b/tests/auto/selftests/xunit/xunit.pro
new file mode 100644
index 0000000..81ca157
--- /dev/null
+++ b/tests/auto/selftests/xunit/xunit.pro
@@ -0,0 +1,15 @@
+load(qttest_p4)
+SOURCES += tst_xunit.cpp
+
+wince*: {
+ addImages.sources = images/*
+ addImages.path = images
+ DEPLOYMENT += addImages
+ DEFINES += SRCDIR=\\\".\\\"
+} else {
+ contains(QT_CONFIG, qt3support): QT += qt3support
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+}
+
+TARGET = xunit
+
diff --git a/tests/auto/uiloader/baseline/css_splitter.ui b/tests/auto/uiloader/baseline/css_splitter.ui
new file mode 100644
index 0000000..99dbc18
--- /dev/null
+++ b/tests/auto/uiloader/baseline/css_splitter.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>424</width>
+ <height>364</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"> QSplitter::handle:vertical {
+ image: url(images/splitter_horizontal.png);
+ }
+
+ QSplitter::handle:horizontal {
+ image: url(images/splitter_vertical.png);
+ }
+
+#big_splitter::handle { background-color: blue; border: 3px dashed green; height:50px; }
+
+
+ QSplitter::handle:hover {
+ background-color: qlineargradient(spread:repeat, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 0, 0, 255), stop:0.17 rgba(255, 0, 0, 255), stop:0.18 rgba(255, 255, 255, 255), stop:0.210212 rgba(255, 255, 255, 255), stop:0.220212 rgba(0, 16, 255, 255), stop:0.279897 rgba(0, 16, 255, 255), stop:0.289897 rgba(255, 255, 255, 255), stop:0.32 rgba(255, 255, 255, 255), stop:0.33 rgba(255, 0, 0, 255), stop:1 rgba(255, 0, 0, 255))
+ }
+
+ QSplitter::handle:pressed {
+ background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(9, 41, 4, 255), stop:0.085 rgba(2, 79, 0, 255), stop:0.19 rgba(50, 147, 22, 255), stop:0.275 rgba(236, 191, 49, 255), stop:0.39 rgba(243, 61, 34, 255), stop:0.555 rgba(135, 81, 60, 255), stop:0.667 rgba(121, 75, 255, 255), stop:0.825 rgba(164, 255, 244, 255), stop:0.885 rgba(104, 222, 71, 255), stop:1 rgba(93, 128, 0, 255));
+ }</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QSplitter" name="splitter_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QSplitter" name="big_splitter">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <widget class="QTextEdit" name="textEdit"/>
+ <widget class="QTextEdit" name="textEdit_5"/>
+ <widget class="QTextEdit" name="textEdit_4"/>
+ </widget>
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <widget class="QTextEdit" name="textEdit_2"/>
+ <widget class="QTextEdit" name="textEdit_3"/>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>