summaryrefslogtreecommitdiffstats
path: root/src/H5Ocont.c
Commit message (Expand)AuthorAgeFilesLines
* [svn-r18595] Description:Quincey Koziol2010-04-201-1/+1
* [svn-r18571] Description:Quincey Koziol2010-04-151-4/+5
* [svn-r16473] Purpose: fix problems related to 'self-referential' attributesNeil Fortner2009-02-121-4/+4
* [svn-r15510] Description:Quincey Koziol2008-08-211-1/+1
* [svn-r15458] Purpose: Modify the library to take the proper action when files...inactive/jpeg_converterNeil Fortner2008-08-111-2/+3
* [svn-r13753] Description:Quincey Koziol2007-05-141-5/+5
* [svn-r13253] Updated all C and C++ style source code files with the THG copyr...Albert Cheng2007-02-071-2/+3
* [svn-r13240] Description:Quincey Koziol2007-02-051-2/+2
* [svn-r13232] Description:Quincey Koziol2007-02-041-26/+19
* [svn-r13176] Description:Quincey Koziol2007-01-231-4/+3
* [svn-r13155] Description:Quincey Koziol2007-01-191-0/+2
* [svn-r13143] Refactoring.James Laird2007-01-161-0/+1
* [svn-r12902] Checkin of Shared Object Header Message work.James Laird2006-11-131-53/+2
* [svn-r12771] Description:Quincey Koziol2006-10-171-12/+16
* [svn-r12767] Description:Quincey Koziol2006-10-161-6/+8
* [svn-r12440] Purpose:Quincey Koziol2006-06-271-4/+4
* [svn-r12439] Purpose:Quincey Koziol2006-06-261-2/+2
* [svn-r12189] Purpose:Quincey Koziol2006-04-011-4/+4
* [svn-r11758] Purpose:Quincey Koziol2005-12-041-2/+3
* [svn-r11712] Purpose:Quincey Koziol2005-11-151-11/+42
* [svn-r11686] Purpose:Quincey Koziol2005-11-071-1/+53
* [svn-r11384] Purpose:Quincey Koziol2005-09-121-2/+37
* [svn-r11245] Purpose:Quincey Koziol2005-08-131-1/+1
* [svn-r9857] Purpose: MaintenanceElena Pourmal2005-01-221-1/+0
* [svn-r9537] Purpose:Quincey Koziol2004-11-171-2/+35
* [svn-r8731] Purpose:Quincey Koziol2004-06-231-12/+5
* [svn-r7538] Purpose:Quincey Koziol2003-10-051-0/+1
* [svn-r6659] Purpose:Quincey Koziol2003-04-141-2/+3
* [svn-r6411] Purpose:Quincey Koziol2003-02-171-5/+17
* [svn-r6398] Purpose:Quincey Koziol2003-02-121-2/+2
* [svn-r6387] Purpose:Quincey Koziol2003-02-101-4/+4
* [svn-r6266] Purpose:Quincey Koziol2003-01-101-3/+3
* [svn-r5867] Purpose:Quincey Koziol2002-08-091-2/+6
* [svn-r5842] Purpose:Quincey Koziol2002-08-081-5/+10
* [svn-r5471] Purpose:Quincey Koziol2002-05-291-3/+3
* [svn-r4355] Purpose:Quincey Koziol2001-08-141-3/+3
* [svn-r3781] Purpose:Bill Wendling2001-04-051-6/+6
* [svn-r2652] Purpose:Quincey Koziol2000-10-101-2/+3
* [svn-r2073] Added free-list code to the library and took out the older "tempo...Quincey Koziol2000-04-041-0/+1
* [svn-r1548] Changes since 19990727Robb Matzke1999-07-281-12/+10
* [svn-r1184] Changes since 19990402Robb Matzke1999-04-151-2/+2
* [svn-r936] Changes since 19981119Robb Matzke1998-11-211-1/+1
* [svn-r925] Changes since 19981116Robb Matzke1998-11-181-4/+4
* [svn-r797] Changed comments from returning "SUCCEED/FAIL" to "non-negative/ne...Quincey Koziol1998-10-261-6/+2
* [svn-r435] ./INSTALLRobb Matzke1998-06-231-1/+4
* [svn-r407] ./src/H5A.cRobb Matzke1998-06-041-13/+14
* [svn-r338] Changes since 19980407Robb Matzke1998-04-081-3/+3
* [svn-r335] Changes since 19980330Robb Matzke1998-04-031-8/+7
* [svn-r230] Changes were actually made by Robb. I am commiting them for himAlbert Cheng1998-02-091-19/+17
* [svn-r157] Reformatted code with indent...Quincey Koziol1998-01-161-104/+103
ight'>39
-rw-r--r--tests/auto/qlocalsocket/tst_qlocalsocket.cpp27
-rw-r--r--tests/auto/qmake/testdata/bundle-spaces/some-file6
-rw-r--r--tests/auto/qmake/tst_qmake.cpp3
-rw-r--r--tests/auto/qmap/tst_qmap.cpp17
-rw-r--r--tests/auto/qnetworkreply/tst_qnetworkreply.cpp663
-rw-r--r--tests/auto/qobject/tst_qobject.cpp108
-rw-r--r--tests/auto/qobjectrace/tst_qobjectrace.cpp24
-rw-r--r--tests/auto/qpainter/tst_qpainter.cpp24
-rw-r--r--tests/auto/qpainterpath/tst_qpainterpath.cpp40
-rw-r--r--tests/auto/qparallelanimationgroup/qparallelanimationgroup.pro5
-rw-r--r--tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp834
-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.pro1
-rw-r--r--tests/auto/qpixmap/qpixmap.qrc29
-rw-r--r--tests/auto/qpixmap/tst_qpixmap.cpp197
-rw-r--r--tests/auto/qpixmapcache/tst_qpixmapcache.cpp266
-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/qpropertyanimation/qpropertyanimation.pro5
-rw-r--r--tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp958
-rw-r--r--tests/auto/qringbuffer/qringbuffer.pro6
-rw-r--r--tests/auto/qringbuffer/tst_qringbuffer.cpp200
-rw-r--r--tests/auto/qscriptengine/tst_qscriptengine.cpp14
-rw-r--r--tests/auto/qscriptqobject/tst_qscriptqobject.cpp95
-rw-r--r--tests/auto/qscriptvalue/tst_qscriptvalue.cpp21
-rw-r--r--tests/auto/qsequentialanimationgroup/qsequentialanimationgroup.pro5
-rw-r--r--tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp1649
-rw-r--r--tests/auto/qset/tst_qset.cpp35
-rw-r--r--tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp109
-rw-r--r--tests/auto/qspinbox/tst_qspinbox.cpp6
-rw-r--r--tests/auto/qsplitter/qsplitter.pro3
-rw-r--r--tests/auto/qsplitter/tst_qsplitter.cpp2
-rw-r--r--tests/auto/qsslsocket/tst_qsslsocket.cpp29
-rw-r--r--tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp49
-rw-r--r--tests/auto/qstate/qstate.pro5
-rw-r--r--tests/auto/qstate/tst_qstate.cpp340
-rw-r--r--tests/auto/qstatemachine/qstatemachine.pro4
-rw-r--r--tests/auto/qstatemachine/tst_qstatemachine.cpp3758
-rw-r--r--tests/auto/qstringbuilder/qstringbuilder.pro5
-rw-r--r--tests/auto/qstringbuilder/scenario1.cpp1
-rw-r--r--tests/auto/qstringbuilder/scenario1.pro8
-rw-r--r--tests/auto/qstringbuilder/scenario2.cpp1
-rw-r--r--tests/auto/qstringbuilder/scenario2.pro7
-rw-r--r--tests/auto/qstringbuilder/scenario3.cpp1
-rw-r--r--tests/auto/qstringbuilder/scenario3.pro7
-rw-r--r--tests/auto/qstringbuilder/scenario4.cpp1
-rw-r--r--tests/auto/qstringbuilder/scenario4.pro7
-rw-r--r--tests/auto/qstringbuilder/tst_qstringbuilder.cpp147
-rw-r--r--tests/auto/qstyle/tst_qstyle.cpp42
-rw-r--r--tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp54
-rw-r--r--tests/auto/qtableview/tst_qtableview.cpp5
-rw-r--r--tests/auto/qtextcodec/test/test.pro6
-rw-r--r--tests/auto/qtextcodec/tst_qtextcodec.cpp125
-rw-r--r--tests/auto/qtextdocument/tst_qtextdocument.cpp50
-rw-r--r--tests/auto/qtextodfwriter/tst_qtextodfwriter.cpp2
-rw-r--r--tests/auto/qtextstream/tst_qtextstream.cpp21
-rw-r--r--tests/auto/qtoolbutton/tst_qtoolbutton.cpp20
-rw-r--r--tests/auto/qtransform/tst_qtransform.cpp7
-rw-r--r--tests/auto/qtreeview/tst_qtreeview.cpp129
-rw-r--r--tests/auto/qtreewidget/tst_qtreewidget.cpp24
-rw-r--r--tests/auto/qvariant/tst_qvariant.cpp64
-rw-r--r--tests/auto/qwidget/tst_qwidget.cpp152
-rw-r--r--tests/auto/selftests/badxml/badxml.pro11
-rw-r--r--tests/auto/selftests/badxml/tst_badxml.cpp206
-rw-r--r--tests/auto/selftests/expected_skip.txt8
-rw-r--r--tests/auto/selftests/expected_xunit.txt40
-rw-r--r--tests/auto/selftests/selftests.pro2
-rw-r--r--tests/auto/selftests/selftests.qrc1
-rw-r--r--tests/auto/selftests/tst_selftests.cpp99
-rwxr-xr-xtests/auto/selftests/xunit/tst_xunitbin0 -> 11624 bytes-rw-r--r--tests/auto/selftests/xunit/tst_xunit.cpp115
-rw-r--r--tests/auto/selftests/xunit/xunit.pro15
-rwxr-xr-xtests/auto/test.pl2
-rw-r--r--tests/auto/uiloader/baseline/css_borderimage.ui125
-rw-r--r--tests/auto/uiloader/baseline/css_borderimage_allwidgets.ui210
-rw-r--r--tests/auto/uiloader/baseline/css_splitter.ui63
-rw-r--r--tests/auto/uiloader/baseline/css_task255849_downarrow.ui144
-rw-r--r--tests/auto/uiloader/baseline/images/arrow-down.pngbin0 -> 1006 bytes-rw-r--r--tests/auto/uiloader/baseline/images/arrow-up.pngbin0 -> 927 bytes-rw-r--r--tests/auto/uiloader/baseline/images/borderimage.pngbin0 -> 1672 bytes-rw-r--r--tests/auto/uiloader/baseline/images/splitter_horizontal.pngbin0 -> 199 bytes-rw-r--r--tests/auto/uiloader/baseline/images/splitter_vertical.pngbin0 -> 193 bytes
161 files changed, 22130 insertions, 529 deletions
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 178351b..19d7924 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -77,6 +77,7 @@ SUBDIRS += _networkselftest \
qaction \
qactiongroup \
qalgorithms \
+ qanimationgroup \
qapplication \
qatomicint \
qatomicpointer \
@@ -141,9 +142,17 @@ SUBDIRS += _networkselftest \
qglobal \
qgraphicsitem \
qgraphicsitemanimation \
+ qgraphicslayout \
+ qgraphicslayoutitem \
+ qgraphicslinearlayout \
+ qgraphicsobject \
+ qgraphicspixmapitem \
+ qgraphicspolygonitem \
+ qgraphicsproxywidget \
qgraphicsscene \
qgraphicsview \
- qgridlayout \
+ qgraphicswidget \
+ qgridlayout \
qgroupbox \
qguivariant \
qhash \
@@ -211,10 +220,12 @@ SUBDIRS += _networkselftest \
qnumeric \
qobject \
qobjectrace \
+ qcontiguouscache \
qpaintengine \
qpainter \
qpainterpath \
qpalette \
+ qparallelanimationgroup \
qpathclipper \
qpen \
qpicture \
@@ -230,6 +241,7 @@ SUBDIRS += _networkselftest \
qprocess \
qprogressbar \
qprogressdialog \
+ qpropertyanimation \
qpushbutton \
qscopedpointer \
qqueue \
@@ -241,6 +253,7 @@ SUBDIRS += _networkselftest \
qregexpvalidator \
qregion \
qresourceengine \
+ qringbuffer \
qscriptable \
qscriptclass \
qscriptcontext \
@@ -257,6 +270,7 @@ SUBDIRS += _networkselftest \
qscrollarea \
qsemaphore \
qsharedpointer \
+ qsequentialanimationgroup \
qset \
qsettings \
qshortcut \
@@ -290,6 +304,8 @@ SUBDIRS += _networkselftest \
qstackedwidget \
qstandarditem \
qstandarditemmodel \
+ qstate \
+ qstatemachine \
qstatusbar \
qstl \
qstring \
@@ -434,3 +450,4 @@ contains(QT_CONFIG, webkit): SUBDIRS += \
qwebframe \
qwebpage
+SUBDIRS += math3d
diff --git a/tests/auto/bic/bic.pro b/tests/auto/bic/bic.pro
index a168d77..82711c9 100644
--- a/tests/auto/bic/bic.pro
+++ b/tests/auto/bic/bic.pro
@@ -2,3 +2,9 @@ load(qttest_p4)
SOURCES += tst_bic.cpp qbic.cpp
QT = core
+wince*:{
+ DEFINES += SRCDIR=\\\"\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
+
diff --git a/tests/auto/bic/tst_bic.cpp b/tests/auto/bic/tst_bic.cpp
index 181c275..8bc8d4f 100644
--- a/tests/auto/bic/tst_bic.cpp
+++ b/tests/auto/bic/tst_bic.cpp
@@ -165,30 +165,30 @@ void tst_Bic::sizesAndVTables_data()
#if defined Q_OS_LINUX && defined Q_WS_X11
# if defined(__powerpc__) && !defined(__powerpc64__)
- archFileName400 = "data/%1.4.0.0.linux-gcc-ppc32.txt";
- archFileName410 = "data/%1.4.1.0.linux-gcc-ppc32.txt";
- archFileName420 = "data/%1.4.2.0.linux-gcc-ppc32.txt";
+ archFileName400 = SRCDIR "data/%1.4.0.0.linux-gcc-ppc32.txt";
+ archFileName410 = SRCDIR "data/%1.4.1.0.linux-gcc-ppc32.txt";
+ archFileName420 = SRCDIR "data/%1.4.2.0.linux-gcc-ppc32.txt";
# elif defined(__amd64__)
- archFileName400 = "data/%1.4.0.0.linux-gcc-amd64.txt";
+ archFileName400 = SRCDIR "data/%1.4.0.0.linux-gcc-amd64.txt";
# elif defined(__i386__)
- archFileName400 = "data/%1.4.0.0.linux-gcc-ia32.txt";
- archFileName410 = "data/%1.4.1.0.linux-gcc-ia32.txt";
- archFileName420 = "data/%1.4.2.0.linux-gcc-ia32.txt";
- archFileName430 = "data/%1.4.3.0.linux-gcc-ia32.txt";
+ archFileName400 = SRCDIR "data/%1.4.0.0.linux-gcc-ia32.txt";
+ archFileName410 = SRCDIR "data/%1.4.1.0.linux-gcc-ia32.txt";
+ archFileName420 = SRCDIR "data/%1.4.2.0.linux-gcc-ia32.txt";
+ archFileName430 = SRCDIR "data/%1.4.3.0.linux-gcc-ia32.txt";
# endif
#elif defined Q_OS_AIX
if (sizeof(void*) == 4)
- archFileName400 = "data/%1.4.0.0.aix-gcc-power32.txt";
+ archFileName400 = SRCDIR "data/%1.4.0.0.aix-gcc-power32.txt";
#elif defined Q_OS_MAC && defined(__powerpc__)
- archFileName400 = "data/%1.4.0.0.macx-gcc-ppc32.txt";
- archFileName410 = "data/%1.4.1.0.macx-gcc-ppc32.txt";
- archFileName420 = "data/%1.4.2.0.macx-gcc-ppc32.txt";
+ archFileName400 = SRCDIR "data/%1.4.0.0.macx-gcc-ppc32.txt";
+ archFileName410 = SRCDIR "data/%1.4.1.0.macx-gcc-ppc32.txt";
+ archFileName420 = SRCDIR "data/%1.4.2.0.macx-gcc-ppc32.txt";
#elif defined Q_OS_MAC && defined(__i386__)
- archFileName410 = "data/%1.4.1.0.macx-gcc-ia32.txt";
- archFileName420 = "data/%1.4.2.0.macx-gcc-ia32.txt";
+ archFileName410 = SRCDIR "data/%1.4.1.0.macx-gcc-ia32.txt";
+ archFileName420 = SRCDIR "data/%1.4.2.0.macx-gcc-ia32.txt";
#elif defined Q_OS_WIN && defined Q_CC_GNU
- archFileName410 = "data/%1.4.1.0.win32-gcc-ia32.txt";
- archFileName420 = "data/%1.4.2.0.win32-gcc-ia32.txt";
+ archFileName410 = SRCDIR "data/%1.4.1.0.win32-gcc-ia32.txt";
+ archFileName420 = SRCDIR "data/%1.4.2.0.win32-gcc-ia32.txt";
#endif
if (archFileName400.isEmpty() && archFileName410.isEmpty()
@@ -293,6 +293,7 @@ void tst_Bic::sizesAndVTables()
bool isFailed = false;
+ qDebug() << oldLib.arg(libName);
if (oldLib.isEmpty() || !QFile::exists(oldLib.arg(libName)))
QSKIP("No platform spec found for this platform/version.", SkipSingle);
diff --git a/tests/auto/headers/tst_headers.cpp b/tests/auto/headers/tst_headers.cpp
index 607d655..7e32deb 100644
--- a/tests/auto/headers/tst_headers.cpp
+++ b/tests/auto/headers/tst_headers.cpp
@@ -135,6 +135,9 @@ void tst_Headers::licenseCheck()
QByteArray data = f.readAll();
QStringList content = QString::fromLocal8Bit(data.replace('\r',"")).split("\n");
+ if (content.first().contains("generated"))
+ content.takeFirst();
+
QVERIFY(licensePattern.exactMatch(content.at(7)) ||
licensePattern.exactMatch(content.at(4)));
QString licenseType = licensePattern.cap(1);
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..dd3e396
--- /dev/null
+++ b/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
@@ -0,0 +1,3339 @@
+/****************************************************************************
+**
+** 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 <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();
+
+ void mapRect_data();
+ void mapRect();
+
+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;
+
+ static const qreal complexScale2D[] =
+ {2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -11.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("complex2D")
+ << (qreal)2.0f << (qreal)-11.0f << (qreal)1.0f << (void *)complexScale2D;
+}
+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));
+
+ if (z == 1.0f) {
+ QMatrix4x4 m2b;
+ m2b.scale(x, y);
+ QVERIFY(m2b == m2);
+ }
+
+ 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));
+ }
+
+ if (z == 1.0f) {
+ QMatrix4x4 m4b(m3);
+ m4b.scale(x, y);
+ QVERIFY(m4b == m4);
+ }
+
+ // 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;
+
+ static const qreal complexTranslate2D[] =
+ {1.0f, 0.0f, 0.0f, 2.0f,
+ 0.0f, 1.0f, 0.0f, -11.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ QTest::newRow("complex2D")
+ << (qreal)2.0f << (qreal)-11.0f << (qreal)0.0f << (void *)complexTranslate2D;
+}
+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));
+
+ if (z == 0.0f) {
+ QMatrix4x4 m2b;
+ m2b.translate(x, y);
+ QVERIFY(m2b == m2);
+ }
+
+ 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);
+
+ if (z == 0.0f) {
+ QMatrix4x4 m4b(m3);
+ m4b.translate(x, y);
+ QVERIFY(m4b == m4);
+ }
+}
+
+// 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));
+}
+
+// Test the mapRect() function for QRect and QRectF.
+void tst_QMatrix::mapRect_data()
+{
+ QTest::addColumn<qreal>("x");
+ QTest::addColumn<qreal>("y");
+ QTest::addColumn<qreal>("width");
+ QTest::addColumn<qreal>("height");
+
+ QTest::newRow("null")
+ << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f;
+ QTest::newRow("rect")
+ << (qreal)1.0f << (qreal)-20.5f << (qreal)100.0f << (qreal)63.75f;
+}
+void tst_QMatrix::mapRect()
+{
+ QFETCH(qreal, x);
+ QFETCH(qreal, y);
+ QFETCH(qreal, width);
+ QFETCH(qreal, height);
+
+ QRectF rect(x, y, width, height);
+ QRect recti(qRound(x), qRound(y), qRound(width), qRound(height));
+
+ QMatrix4x4 m1;
+ QVERIFY(m1.mapRect(rect) == rect);
+ QVERIFY(m1.mapRect(recti) == recti);
+
+ QMatrix4x4 m2;
+ m2.translate(-100.5f, 64.0f);
+ QRectF translated = rect.translated(-100.5f, 64.0f);
+ QRect translatedi = QRect(qRound(recti.x() - 100.5f), recti.y() + 64,
+ recti.width(), recti.height());
+ QVERIFY(m2.mapRect(rect) == translated);
+ QVERIFY(m2.mapRect(recti) == translatedi);
+
+ QMatrix4x4 m3;
+ m3.scale(-100.5f, 64.0f);
+ qreal scalex = x * -100.5f;
+ qreal scaley = y * 64.0f;
+ qreal scalewid = width * -100.5f;
+ qreal scaleht = height * 64.0f;
+ if (scalewid < 0.0f) {
+ scalewid = -scalewid;
+ scalex -= scalewid;
+ }
+ if (scaleht < 0.0f) {
+ scaleht = -scaleht;
+ scaley -= scaleht;
+ }
+ QRectF scaled(scalex, scaley, scalewid, scaleht);
+ QVERIFY(m3.mapRect(rect) == scaled);
+ scalex = recti.x() * -100.5f;
+ scaley = recti.y() * 64.0f;
+ scalewid = recti.width() * -100.5f;
+ scaleht = recti.height() * 64.0f;
+ if (scalewid < 0.0f) {
+ scalewid = -scalewid;
+ scalex -= scalewid;
+ }
+ if (scaleht < 0.0f) {
+ scaleht = -scaleht;
+ scaley -= scaleht;
+ }
+ QRect scaledi(qRound(scalex), qRound(scaley),
+ qRound(scalewid), qRound(scaleht));
+ QVERIFY(m3.mapRect(recti) == scaledi);
+
+ QMatrix4x4 m4;
+ m4.translate(-100.5f, 64.0f);
+ m4.scale(-2.5f, 4.0f);
+ qreal transx1 = x * -2.5f - 100.5f;
+ qreal transy1 = y * 4.0f + 64.0f;
+ qreal transx2 = (x + width) * -2.5f - 100.5f;
+ qreal transy2 = (y + height) * 4.0f + 64.0f;
+ if (transx1 > transx2)
+ qSwap(transx1, transx2);
+ if (transy1 > transy2)
+ qSwap(transy1, transy2);
+ QRectF trans(transx1, transy1, transx2 - transx1, transy2 - transy1);
+ QVERIFY(m4.mapRect(rect) == trans);
+ transx1 = recti.x() * -2.5f - 100.5f;
+ transy1 = recti.y() * 4.0f + 64.0f;
+ transx2 = (recti.x() + recti.width()) * -2.5f - 100.5f;
+ transy2 = (recti.y() + recti.height()) * 4.0f + 64.0f;
+ if (transx1 > transx2)
+ qSwap(transx1, transx2);
+ if (transy1 > transy2)
+ qSwap(transy1, transy2);
+ QRect transi(qRound(transx1), qRound(transy1),
+ qRound(transx2) - qRound(transx1),
+ qRound(transy2) - qRound(transy1));
+ QVERIFY(m4.mapRect(recti) == transi);
+
+ m4.rotate(45.0f, 0.0f, 0.0f, 1.0f);
+
+ QTransform t4;
+ t4.translate(-100.5f, 64.0f);
+ t4.scale(-2.5f, 4.0f);
+ t4.rotate(45.0f);
+ QRectF mr = m4.mapRect(rect);
+ QRectF tr = t4.mapRect(rect);
+ QVERIFY(fuzzyCompare(mr.x(), tr.x()));
+ QVERIFY(fuzzyCompare(mr.y(), tr.y()));
+ QVERIFY(fuzzyCompare(mr.width(), tr.width()));
+ QVERIFY(fuzzyCompare(mr.height(), tr.height()));
+
+ QRect mri = m4.mapRect(recti);
+ QRect tri = t4.mapRect(recti);
+ QVERIFY(mri == tri);
+}
+
+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..5d70e4d
--- /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 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>
+#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..f7d2411
--- /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 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>
+#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..a77090b
--- /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 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$
+**
+****************************************************************************/
+
+#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/qaction/tst_qaction.cpp b/tests/auto/qaction/tst_qaction.cpp
index 265932d..f9f6f51 100644
--- a/tests/auto/qaction/tst_qaction.cpp
+++ b/tests/auto/qaction/tst_qaction.cpp
@@ -75,6 +75,8 @@ private slots:
void alternateShortcuts();
void enabledVisibleInteraction();
void task200823_tooltip();
+ void task229128TriggeredSignalWithoutActiongroup();
+ void task229128TriggeredSignalWhenInActiongroup();
private:
int m_lastEventType;
@@ -109,7 +111,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 +143,7 @@ void tst_QAction::initTestCase()
void tst_QAction::cleanupTestCase()
{
QWidget *testWidget = m_tstWidget;
- if ( testWidget ) {
+ if (testWidget) {
testWidget->hide();
delete testWidget;
}
@@ -189,7 +191,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 +251,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 +324,46 @@ 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);
+}
+
QTEST_MAIN(tst_QAction)
#include "tst_qaction.moc"
diff --git a/tests/auto/qanimationgroup/qanimationgroup.pro b/tests/auto/qanimationgroup/qanimationgroup.pro
new file mode 100644
index 0000000..97d33dd
--- /dev/null
+++ b/tests/auto/qanimationgroup/qanimationgroup.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT = core gui
+SOURCES += tst_qanimationgroup.cpp
+
+
diff --git a/tests/auto/qanimationgroup/tst_qanimationgroup.cpp b/tests/auto/qanimationgroup/tst_qanimationgroup.cpp
new file mode 100644
index 0000000..2952a39
--- /dev/null
+++ b/tests/auto/qanimationgroup/tst_qanimationgroup.cpp
@@ -0,0 +1,413 @@
+/****************************************************************************
+**
+** 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 <QtTest/QtTest>
+
+#include <QtCore/qanimationgroup.h>
+#include <QtCore/qsequentialanimationgroup.h>
+#include <QtCore/qparallelanimationgroup.h>
+
+//TESTED_CLASS=QAnimationGroup
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QAbstractAnimation::State)
+
+class tst_QAnimationGroup : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QAnimationGroup();
+ virtual ~tst_QAnimationGroup();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private slots:
+ void construction();
+ void emptyGroup();
+ void setCurrentTime();
+ void statesAndSignals();
+ void setParentAutoAdd();
+ void beginNestedGroup();
+ void addChildTwice();
+ void loopWithoutStartValue();
+};
+
+tst_QAnimationGroup::tst_QAnimationGroup()
+{
+}
+
+tst_QAnimationGroup::~tst_QAnimationGroup()
+{
+}
+
+void tst_QAnimationGroup::init()
+{
+ qRegisterMetaType<QAbstractAnimation::State>("QAbstractAnimation::State");
+}
+
+void tst_QAnimationGroup::cleanup()
+{
+}
+
+void tst_QAnimationGroup::construction()
+{
+ QSequentialAnimationGroup animationgroup;
+}
+
+class AnimationObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+public:
+ AnimationObject(int startValue = 0)
+ : v(startValue)
+ { }
+
+ int value() const { return v; }
+ void setValue(int value) { v = value; }
+
+ int v;
+};
+
+class TestAnimation : public QVariantAnimation
+{
+ Q_OBJECT
+public:
+ virtual void updateCurrentValue(const QVariant &value) { Q_UNUSED(value)};
+ virtual void updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+ {
+ Q_UNUSED(oldState)
+ Q_UNUSED(newState)
+ };
+};
+
+class UncontrolledAnimation : public QPropertyAnimation
+{
+ Q_OBJECT
+public:
+ UncontrolledAnimation(QObject *target, const QByteArray &propertyName, QObject *parent = 0)
+ : QPropertyAnimation(target, propertyName, parent), id(0)
+ {
+ setDuration(250);
+ }
+
+ int duration() const { return -1; /* not time driven */ }
+
+protected:
+ void timerEvent(QTimerEvent *event)
+ {
+ if (event->timerId() == id)
+ stop();
+ }
+
+ void updateRunning(bool running)
+ {
+ if (running) {
+ id = startTimer(500);
+ } else {
+ killTimer(id);
+ id = 0;
+ }
+ }
+
+private:
+ int id;
+};
+
+void tst_QAnimationGroup::emptyGroup()
+{
+ QSequentialAnimationGroup group;
+ QSignalSpy groupStateChangedSpy(&group, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ group.start();
+
+ QCOMPARE(groupStateChangedSpy.count(), 2);
+
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(groupStateChangedSpy.at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(groupStateChangedSpy.at(1).at(1)),
+ QAnimationGroup::Stopped);
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+
+ QTest::ignoreMessage(QtWarningMsg, "QAbstractAnimation::pause: Cannot pause a stopped animation");
+ group.pause();
+
+ QCOMPARE(groupStateChangedSpy.count(), 2);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+
+ group.start();
+
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(groupStateChangedSpy.at(2).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(groupStateChangedSpy.at(3).at(1)),
+ QAnimationGroup::Stopped);
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+
+ group.stop();
+
+ QCOMPARE(groupStateChangedSpy.count(), 4);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+}
+
+void tst_QAnimationGroup::setCurrentTime()
+{
+ AnimationObject s_o1;
+ AnimationObject s_o2;
+ AnimationObject s_o3;
+ AnimationObject p_o1;
+ AnimationObject p_o2;
+ AnimationObject p_o3;
+ AnimationObject t_o1;
+ AnimationObject t_o2;
+
+ // sequence operating on same object/property
+ QSequentialAnimationGroup *sequence = new QSequentialAnimationGroup();
+ QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ a2_s_o1->setLoopCount(3);
+ sequence->addAnimation(a1_s_o1);
+ sequence->addAnimation(a2_s_o1);
+ sequence->addAnimation(a3_s_o1);
+
+ // sequence operating on different object/properties
+ QAnimationGroup *sequence2 = new QSequentialAnimationGroup();
+ QVariantAnimation *a1_s_o2 = new QPropertyAnimation(&s_o2, "value");
+ QVariantAnimation *a1_s_o3 = new QPropertyAnimation(&s_o3, "value");
+ sequence2->addAnimation(a1_s_o2);
+ sequence2->addAnimation(a1_s_o3);
+
+ // parallel operating on different object/properties
+ QAnimationGroup *parallel = new QParallelAnimationGroup();
+ QVariantAnimation *a1_p_o1 = new QPropertyAnimation(&p_o1, "value");
+ QVariantAnimation *a1_p_o2 = new QPropertyAnimation(&p_o2, "value");
+ QVariantAnimation *a1_p_o3 = new QPropertyAnimation(&p_o3, "value");
+ a1_p_o2->setLoopCount(3);
+ parallel->addAnimation(a1_p_o1);
+ parallel->addAnimation(a1_p_o2);
+ parallel->addAnimation(a1_p_o3);
+
+ UncontrolledAnimation *notTimeDriven = new UncontrolledAnimation(&t_o1, "value");
+ QCOMPARE(notTimeDriven->totalDuration(), -1);
+
+ QVariantAnimation *loopsForever = new QPropertyAnimation(&t_o2, "value");
+ loopsForever->setLoopCount(-1);
+ QCOMPARE(loopsForever->totalDuration(), -1);
+
+ QParallelAnimationGroup group;
+ group.addAnimation(sequence);
+ group.addAnimation(sequence2);
+ group.addAnimation(parallel);
+ group.addAnimation(notTimeDriven);
+ group.addAnimation(loopsForever);
+
+ // Current time = 1
+ group.setCurrentTime(1);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(sequence2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(parallel->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_p_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_p_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_p_o3->state(), QAnimationGroup::Stopped);
+ QCOMPARE(notTimeDriven->state(), QAnimationGroup::Stopped);
+ QCOMPARE(loopsForever->state(), QAnimationGroup::Stopped);
+
+ QCOMPARE(group.currentTime(), 1);
+ QCOMPARE(sequence->currentTime(), 1);
+ QCOMPARE(a1_s_o1->currentTime(), 1);
+ QCOMPARE(a2_s_o1->currentTime(), 0);
+ QCOMPARE(a3_s_o1->currentTime(), 0);
+ QCOMPARE(a1_s_o2->currentTime(), 1);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+ QCOMPARE(a1_p_o1->currentTime(), 1);
+ QCOMPARE(a1_p_o2->currentTime(), 1);
+ QCOMPARE(a1_p_o3->currentTime(), 1);
+ QCOMPARE(notTimeDriven->currentTime(), 1);
+ QCOMPARE(loopsForever->currentTime(), 1);
+
+ // Current time = 250
+ group.setCurrentTime(250);
+ QCOMPARE(group.currentTime(), 250);
+ QCOMPARE(sequence->currentTime(), 250);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 0);
+ QCOMPARE(a3_s_o1->currentTime(), 0);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+ QCOMPARE(a1_p_o1->currentTime(), 250);
+ QCOMPARE(a1_p_o2->currentTime(), 0);
+ QCOMPARE(a1_p_o2->currentLoop(), 1);
+ QCOMPARE(a1_p_o3->currentTime(), 250);
+ QCOMPARE(notTimeDriven->currentTime(), 250);
+ QCOMPARE(loopsForever->currentTime(), 0);
+ QCOMPARE(loopsForever->currentLoop(), 1);
+ QCOMPARE(sequence->currentAnimation(), a2_s_o1);
+
+ // Current time = 251
+ group.setCurrentTime(251);
+ QCOMPARE(group.currentTime(), 251);
+ QCOMPARE(sequence->currentTime(), 251);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 1);
+ QCOMPARE(a2_s_o1->currentLoop(), 0);
+ QCOMPARE(a3_s_o1->currentTime(), 0);
+ QCOMPARE(sequence2->currentTime(), 251);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(a1_s_o3->currentTime(), 1);
+ QCOMPARE(a1_p_o1->currentTime(), 250);
+ QCOMPARE(a1_p_o2->currentTime(), 1);
+ QCOMPARE(a1_p_o2->currentLoop(), 1);
+ QCOMPARE(a1_p_o3->currentTime(), 250);
+ QCOMPARE(notTimeDriven->currentTime(), 251);
+ QCOMPARE(loopsForever->currentTime(), 1);
+ QCOMPARE(sequence->currentAnimation(), a2_s_o1);
+}
+
+void tst_QAnimationGroup::statesAndSignals()
+{
+}
+
+void tst_QAnimationGroup::setParentAutoAdd()
+{
+ QParallelAnimationGroup group;
+ QVariantAnimation *animation = new QPropertyAnimation(&group);
+ QCOMPARE(animation->group(), &group);
+}
+
+void tst_QAnimationGroup::beginNestedGroup()
+{
+ QAnimationGroup *subGroup;
+ QAnimationGroup *parent = new QParallelAnimationGroup();
+
+ for (int i = 0; i < 10; ++i) {
+ if (i & 1)
+ subGroup = new QParallelAnimationGroup(parent);
+ else
+ subGroup = new QSequentialAnimationGroup(parent);
+
+ QCOMPARE(parent->animationCount(), 1);
+ QAnimationGroup *child = static_cast<QAnimationGroup *>(parent->animationAt(0));
+
+ QCOMPARE(child->parent(), static_cast<QObject *>(parent));
+ if (i & 1)
+ QVERIFY(qobject_cast<QParallelAnimationGroup *> (child));
+ else
+ QVERIFY(qobject_cast<QSequentialAnimationGroup *> (child));
+
+ parent = child;
+ }
+}
+
+void tst_QAnimationGroup::addChildTwice()
+{
+ QPropertyAnimation *subGroup;
+ QPropertyAnimation *subGroup2;
+ QAnimationGroup *parent = new QSequentialAnimationGroup();
+
+ subGroup = new QPropertyAnimation();
+ subGroup->setParent(parent);
+ parent->addAnimation(subGroup);
+ QCOMPARE(parent->animationCount(), 1);
+
+ parent->clearAnimations();
+
+ QCOMPARE(parent->animationCount(), 0);
+
+ // adding the same item twice to a group will remove the item from its current position
+ // and append it to the end
+ subGroup = new QPropertyAnimation(parent);
+ subGroup2 = new QPropertyAnimation(parent);
+
+ QCOMPARE(parent->animationCount(), 2);
+ QCOMPARE(parent->animationAt(0), subGroup);
+ QCOMPARE(parent->animationAt(1), subGroup2);
+
+ parent->addAnimation(subGroup);
+
+ QCOMPARE(parent->animationCount(), 2);
+ QCOMPARE(parent->animationAt(0), subGroup2);
+ QCOMPARE(parent->animationAt(1), subGroup);
+
+ delete parent;
+}
+
+void tst_QAnimationGroup::loopWithoutStartValue()
+{
+ QAnimationGroup *parent = new QSequentialAnimationGroup();
+ QObject o;
+ o.setProperty("ole", 0);
+ QCOMPARE(o.property("ole").toInt(), 0);
+
+ QPropertyAnimation anim1(&o, "ole");
+ anim1.setEndValue(-50);
+ anim1.setDuration(100);
+
+ QPropertyAnimation anim2(&o, "ole");
+ anim2.setEndValue(50);
+ anim2.setDuration(100);
+
+ parent->addAnimation(&anim1);
+ parent->addAnimation(&anim2);
+
+ parent->setLoopCount(-1);
+ parent->start();
+
+ QVERIFY(anim1.startValue().isNull());
+ QCOMPARE(anim1.currentValue().toInt(), 0);
+ QCOMPARE(parent->currentLoop(), 0);
+
+ parent->setCurrentTime(200);
+ QCOMPARE(parent->currentLoop(), 1);
+ QCOMPARE(anim1.currentValue().toInt(), 50);
+ parent->stop();
+}
+
+QTEST_MAIN(tst_QAnimationGroup)
+#include "tst_qanimationgroup.moc"
diff --git a/tests/auto/qbrush/tst_qbrush.cpp b/tests/auto/qbrush/tst_qbrush.cpp
index 11f715a..7ef930f 100644
--- a/tests/auto/qbrush/tst_qbrush.cpp
+++ b/tests/auto/qbrush/tst_qbrush.cpp
@@ -44,6 +44,7 @@
#include "qbrush.h"
#include <QPainter>
+#include <QBitmap>
#include <qdebug.h>
@@ -76,6 +77,7 @@ private slots:
void textures();
void nullBrush();
+ void isOpaque();
};
Q_DECLARE_METATYPE(QBrush)
@@ -379,5 +381,14 @@ void tst_QBrush::nullBrush()
QCOMPARE(brush.color(), QColor(100,0,0));
}
+void tst_QBrush::isOpaque()
+{
+ QBitmap bm(8, 8);
+ bm.fill(Qt::black);
+
+ QBrush brush(bm);
+ QVERIFY(!brush.isOpaque());
+}
+
QTEST_MAIN(tst_QBrush)
#include "tst_qbrush.moc"
diff --git a/tests/auto/qbuttongroup/tst_qbuttongroup.cpp b/tests/auto/qbuttongroup/tst_qbuttongroup.cpp
index 15cca56..4bb414c 100644
--- a/tests/auto/qbuttongroup/tst_qbuttongroup.cpp
+++ b/tests/auto/qbuttongroup/tst_qbuttongroup.cpp
@@ -92,11 +92,15 @@ private slots:
void exclusive();
void exclusiveWithActions();
void testSignals();
-
void checkedButton();
void task106609();
+ // fixed for Qt 4.6.0
+#if QT_VERSION >= 0x040600
+ void autoIncrementId();
+#endif
+
void task209485_removeFromGroupInEventHandler_data();
void task209485_removeFromGroupInEventHandler();
};
@@ -329,13 +333,19 @@ void tst_QButtonGroup::testSignals()
QCOMPARE(clickedSpy.count(), 1);
QCOMPARE(clickedIdSpy.count(), 1);
- QVERIFY(clickedIdSpy.takeFirst().at(0).toInt() == -1);
+
+ int expectedId = -1;
+#if QT_VERSION >= 0x040600
+ expectedId = -2;
+#endif
+
+ QVERIFY(clickedIdSpy.takeFirst().at(0).toInt() == expectedId);
QCOMPARE(pressedSpy.count(), 1);
QCOMPARE(pressedIdSpy.count(), 1);
- QVERIFY(pressedIdSpy.takeFirst().at(0).toInt() == -1);
+ QVERIFY(pressedIdSpy.takeFirst().at(0).toInt() == expectedId);
QCOMPARE(releasedSpy.count(), 1);
QCOMPARE(releasedIdSpy.count(), 1);
- QVERIFY(releasedIdSpy.takeFirst().at(0).toInt() == -1);
+ QVERIFY(releasedIdSpy.takeFirst().at(0).toInt() == expectedId);
clickedSpy.clear();
clickedIdSpy.clear();
@@ -483,5 +493,36 @@ void tst_QButtonGroup::task209485_removeFromGroupInEventHandler()
QCOMPARE(spy1.count() + spy2.count(), signalCount);
}
+#if QT_VERSION >= 0x040600
+void tst_QButtonGroup::autoIncrementId()
+{
+ QDialog dlg(0);
+ QButtonGroup *buttons = new QButtonGroup(&dlg);
+ QVBoxLayout *vbox = new QVBoxLayout(&dlg);
+
+ QRadioButton *radio1 = new QRadioButton(&dlg);
+ radio1->setText("radio1");
+ QRadioButton *radio2 = new QRadioButton(&dlg);
+ radio2->setText("radio2");
+ QRadioButton *radio3 = new QRadioButton(&dlg);
+ radio3->setText("radio3");
+
+ buttons->addButton(radio1);
+ vbox->addWidget(radio1);
+ buttons->addButton(radio2);
+ vbox->addWidget(radio2);
+ buttons->addButton(radio3);
+ vbox->addWidget(radio3);
+
+ radio1->setChecked(true);
+
+ QVERIFY(buttons->id(radio1) == -2);
+ QVERIFY(buttons->id(radio2) == -3);
+ QVERIFY(buttons->id(radio3) == -4);
+
+ dlg.show();
+}
+#endif
+
QTEST_MAIN(tst_QButtonGroup)
#include "tst_qbuttongroup.moc"
diff --git a/tests/auto/qcombobox/tst_qcombobox.cpp b/tests/auto/qcombobox/tst_qcombobox.cpp
index 4973d4f..d47de61 100644
--- a/tests/auto/qcombobox/tst_qcombobox.cpp
+++ b/tests/auto/qcombobox/tst_qcombobox.cpp
@@ -2200,8 +2200,8 @@ void tst_QComboBox::noScrollbar()
{
QTableWidget *table = new QTableWidget(2,2);
QComboBox comboBox;
- comboBox.setView(table);
comboBox.setModel(table->model());
+ comboBox.setView(table);
comboBox.show();
QTest::qWait(100);
comboBox.resize(200, comboBox.height());
diff --git a/tests/auto/qcontiguouscache/qcontiguouscache.pro b/tests/auto/qcontiguouscache/qcontiguouscache.pro
new file mode 100644
index 0000000..618efed
--- /dev/null
+++ b/tests/auto/qcontiguouscache/qcontiguouscache.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+
+QT = core
+
+SOURCES += tst_qcontiguouscache.cpp
+
+
+
diff --git a/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp
new file mode 100644
index 0000000..6d59390
--- /dev/null
+++ b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp
@@ -0,0 +1,479 @@
+/****************************************************************************
+**
+** 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 <QObject>
+#include <QTest>
+#include <QCache>
+#include <QContiguousCache>
+
+#include <QDebug>
+#include <stdio.h>
+
+class tst_QContiguousCache : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QContiguousCache() {}
+ virtual ~tst_QContiguousCache() {}
+private slots:
+ void empty();
+ void append_data();
+ void append();
+
+ void prepend_data();
+ void prepend();
+
+ void asScrollingList();
+
+ void complexType();
+
+ void operatorAt();
+
+ void cacheBenchmark();
+ void contiguousCacheBenchmark();
+
+ void setCapacity();
+};
+
+QTEST_MAIN(tst_QContiguousCache)
+
+void tst_QContiguousCache::empty()
+{
+ QContiguousCache<int> c(10);
+ QCOMPARE(c.capacity(), 10);
+ QCOMPARE(c.count(), 0);
+ QVERIFY(c.isEmpty());
+ c.append(1);
+ QCOMPARE(c.count(), 1);
+ QVERIFY(!c.isEmpty());
+ c.clear();
+ QCOMPARE(c.capacity(), 10);
+ QCOMPARE(c.count(), 0);
+ QVERIFY(c.isEmpty());
+ c.prepend(1);
+ QCOMPARE(c.count(), 1);
+ QVERIFY(!c.isEmpty());
+ c.clear();
+ QCOMPARE(c.count(), 0);
+ QVERIFY(c.isEmpty());
+ QCOMPARE(c.capacity(), 10);
+}
+
+void tst_QContiguousCache::append_data()
+{
+ QTest::addColumn<int>("start");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<int>("cacheSize");
+ QTest::addColumn<bool>("invalidIndexes");
+
+ QTest::newRow("0+30[10]") << 0 << 30 << 10 << false;
+ QTest::newRow("300+30[10]") << 300 << 30 << 10 << false;
+ QTest::newRow("MAX-10+30[10]") << INT_MAX-10 << 30 << 10 << true;
+}
+
+void tst_QContiguousCache::append()
+{
+ QFETCH(int, start);
+ QFETCH(int, count);
+ QFETCH(int, cacheSize);
+ QFETCH(bool, invalidIndexes);
+
+ int i, j;
+ QContiguousCache<int> c(cacheSize);
+
+ i = 1;
+ QCOMPARE(c.available(), cacheSize);
+ if (start == 0)
+ c.append(i++);
+ else
+ c.insert(start, i++);
+ while (i < count) {
+ c.append(i);
+ QCOMPARE(c.available(), qMax(0, cacheSize - i));
+ QCOMPARE(c.first(), qMax(1, i-cacheSize+1));
+ QCOMPARE(c.last(), i);
+ QCOMPARE(c.count(), qMin(i, cacheSize));
+ QCOMPARE(c.isFull(), i >= cacheSize);
+ i++;
+ }
+
+ QCOMPARE(c.areIndexesValid(), !invalidIndexes);
+ if (invalidIndexes)
+ c.normalizeIndexes();
+ QVERIFY(c.areIndexesValid());
+
+ // test taking from end until empty.
+ for (j = 0; j < cacheSize; j++, i--) {
+ QCOMPARE(c.takeLast(), i-1);
+ QCOMPARE(c.count(), cacheSize-j-1);
+ QCOMPARE(c.available(), j+1);
+ QVERIFY(!c.isFull());
+ QCOMPARE(c.isEmpty(), j==cacheSize-1);
+ }
+
+}
+
+void tst_QContiguousCache::prepend_data()
+{
+ QTest::addColumn<int>("start");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<int>("cacheSize");
+ QTest::addColumn<bool>("invalidIndexes");
+
+ QTest::newRow("30-30[10]") << 30 << 30 << 10 << false;
+ QTest::newRow("300-30[10]") << 300 << 30 << 10 << false;
+ QTest::newRow("10-30[10]") << 10 << 30 << 10 << true;
+}
+
+void tst_QContiguousCache::prepend()
+{
+ QFETCH(int, start);
+ QFETCH(int, count);
+ QFETCH(int, cacheSize);
+ QFETCH(bool, invalidIndexes);
+
+ int i, j;
+ QContiguousCache<int> c(cacheSize);
+
+ i = 1;
+ QCOMPARE(c.available(), cacheSize);
+ c.insert(start, i++);
+ while(i < count) {
+ c.prepend(i);
+ QCOMPARE(c.available(), qMax(0, cacheSize - i));
+ QCOMPARE(c.last(), qMax(1, i-cacheSize+1));
+ QCOMPARE(c.first(), i);
+ QCOMPARE(c.count(), qMin(i, cacheSize));
+ QCOMPARE(c.isFull(), i >= cacheSize);
+ i++;
+ }
+
+ QCOMPARE(c.areIndexesValid(), !invalidIndexes);
+ if (invalidIndexes)
+ c.normalizeIndexes();
+ QVERIFY(c.areIndexesValid());
+
+ // test taking from start until empty.
+ for (j = 0; j < cacheSize; j++, i--) {
+ QCOMPARE(c.takeFirst(), i-1);
+ QCOMPARE(c.count(), cacheSize-j-1);
+ QCOMPARE(c.available(), j+1);
+ QVERIFY(!c.isFull());
+ QCOMPARE(c.isEmpty(), j==cacheSize-1);
+ }
+}
+
+void tst_QContiguousCache::asScrollingList()
+{
+ int i;
+ QContiguousCache<int> c(10);
+
+ // Once allocated QContiguousCache should not
+ // allocate any additional memory for non
+ // complex data types.
+ QBENCHMARK {
+ // simulate scrolling in a list of items;
+ for(i = 0; i < 10; ++i) {
+ QCOMPARE(c.available(), 10-i);
+ c.append(i);
+ }
+
+ QCOMPARE(c.firstIndex(), 0);
+ QCOMPARE(c.lastIndex(), 9);
+ QCOMPARE(c.first(), 0);
+ QCOMPARE(c.last(), 9);
+ QVERIFY(!c.containsIndex(-1));
+ QVERIFY(!c.containsIndex(10));
+ QCOMPARE(c.available(), 0);
+
+ for (i = 0; i < 10; ++i) {
+ QVERIFY(c.containsIndex(i));
+ QCOMPARE(c.at(i), i);
+ QCOMPARE(c[i], i);
+ QCOMPARE(((const QContiguousCache<int>)c)[i], i);
+ }
+
+ for (i = 10; i < 30; ++i)
+ c.append(i);
+
+ QCOMPARE(c.firstIndex(), 20);
+ QCOMPARE(c.lastIndex(), 29);
+ QCOMPARE(c.first(), 20);
+ QCOMPARE(c.last(), 29);
+ QVERIFY(!c.containsIndex(19));
+ QVERIFY(!c.containsIndex(30));
+ QCOMPARE(c.available(), 0);
+
+ for (i = 20; i < 30; ++i) {
+ QVERIFY(c.containsIndex(i));
+ QCOMPARE(c.at(i), i);
+ QCOMPARE(c[i], i);
+ QCOMPARE(((const QContiguousCache<int> )c)[i], i);
+ }
+
+ for (i = 19; i >= 10; --i)
+ c.prepend(i);
+
+ QCOMPARE(c.firstIndex(), 10);
+ QCOMPARE(c.lastIndex(), 19);
+ QCOMPARE(c.first(), 10);
+ QCOMPARE(c.last(), 19);
+ QVERIFY(!c.containsIndex(9));
+ QVERIFY(!c.containsIndex(20));
+ QCOMPARE(c.available(), 0);
+
+ for (i = 10; i < 20; ++i) {
+ QVERIFY(c.containsIndex(i));
+ QCOMPARE(c.at(i), i);
+ QCOMPARE(c[i], i);
+ QCOMPARE(((const QContiguousCache<int> )c)[i], i);
+ }
+
+ for (i = 200; i < 220; ++i)
+ c.insert(i, i);
+
+ QCOMPARE(c.firstIndex(), 210);
+ QCOMPARE(c.lastIndex(), 219);
+ QCOMPARE(c.first(), 210);
+ QCOMPARE(c.last(), 219);
+ QVERIFY(!c.containsIndex(209));
+ QVERIFY(!c.containsIndex(300));
+ QCOMPARE(c.available(), 0);
+
+ for (i = 210; i < 220; ++i) {
+ QVERIFY(c.containsIndex(i));
+ QCOMPARE(c.at(i), i);
+ QCOMPARE(c[i], i);
+ QCOMPARE(((const QContiguousCache<int> )c)[i], i);
+ }
+ c.clear(); // needed to reset benchmark
+ }
+
+ // from a specific bug that was encountered. 100 to 299 cached, attempted to cache 250 - 205 via insert, failed.
+ // bug was that item at 150 would instead be item that should have been inserted at 250
+ c.setCapacity(200);
+ for(i = 100; i < 300; ++i)
+ c.insert(i, i);
+ for (i = 250; i <= 306; ++i)
+ c.insert(i, 1000+i);
+ for (i = 107; i <= 306; ++i) {
+ QVERIFY(c.containsIndex(i));
+ QCOMPARE(c.at(i), i < 250 ? i : 1000+i);
+ }
+}
+
+struct RefCountingClassData
+{
+ QBasicAtomicInt ref;
+ static RefCountingClassData shared_null;
+};
+
+RefCountingClassData RefCountingClassData::shared_null = {
+ Q_BASIC_ATOMIC_INITIALIZER(1)
+};
+
+class RefCountingClass
+{
+public:
+ RefCountingClass() : d(&RefCountingClassData::shared_null) { d->ref.ref(); }
+
+ RefCountingClass(const RefCountingClass &other)
+ {
+ d = other.d;
+ d->ref.ref();
+ }
+
+ ~RefCountingClass()
+ {
+ if (!d->ref.deref())
+ delete d;
+ }
+
+ RefCountingClass &operator=(const RefCountingClass &other)
+ {
+ if (!d->ref.deref())
+ delete d;
+ d = other.d;
+ d->ref.ref();
+ return *this;
+ }
+
+ int refCount() const { return d->ref; }
+private:
+ RefCountingClassData *d;
+};
+
+void tst_QContiguousCache::complexType()
+{
+ RefCountingClass original;
+
+ QContiguousCache<RefCountingClass> contiguousCache(10);
+ contiguousCache.append(original);
+ QCOMPARE(original.refCount(), 3);
+ contiguousCache.removeFirst();
+ QCOMPARE(original.refCount(), 2); // shared null, 'original'.
+ contiguousCache.append(original);
+ QCOMPARE(original.refCount(), 3);
+ contiguousCache.clear();
+ QCOMPARE(original.refCount(), 2);
+
+ for(int i = 0; i < 100; ++i)
+ contiguousCache.insert(i, original);
+
+ QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in contiguousCache.
+
+ contiguousCache.clear();
+ QCOMPARE(original.refCount(), 2);
+ for (int i = 0; i < 100; i++)
+ contiguousCache.append(original);
+
+ QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in contiguousCache.
+ contiguousCache.clear();
+ QCOMPARE(original.refCount(), 2);
+
+ for (int i = 0; i < 100; i++)
+ contiguousCache.prepend(original);
+
+ QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in contiguousCache.
+ contiguousCache.clear();
+ QCOMPARE(original.refCount(), 2);
+
+ for (int i = 0; i < 100; i++)
+ contiguousCache.append(original);
+
+ contiguousCache.takeLast();
+ QCOMPARE(original.refCount(), 11);
+
+ contiguousCache.takeFirst();
+ QCOMPARE(original.refCount(), 10);
+}
+
+void tst_QContiguousCache::operatorAt()
+{
+ RefCountingClass original;
+ QContiguousCache<RefCountingClass> contiguousCache(10);
+
+ for (int i = 25; i < 35; ++i)
+ contiguousCache[i] = original;
+
+ QCOMPARE(original.refCount(), 12); // shared null, orig, items in cache
+
+ // verify const access does not copy items.
+ const QContiguousCache<RefCountingClass> copy(contiguousCache);
+ for (int i = 25; i < 35; ++i)
+ QCOMPARE(copy[i].refCount(), 12);
+
+ // verify modifying the original increments ref count (e.g. does a detach)
+ contiguousCache[25] = original;
+ QCOMPARE(original.refCount(), 22);
+}
+
+/*
+ Benchmarks must be near identical in tasks to be fair.
+ QCache uses pointers to ints as its a requirement of QCache,
+ whereas QContiguousCache doesn't support pointers (won't free them).
+ Given the ability to use simple data types is a benefit, its
+ fair. Although this obviously must take into account we are
+ testing QContiguousCache use cases here, QCache has its own
+ areas where it is the more sensible class to use.
+*/
+void tst_QContiguousCache::cacheBenchmark()
+{
+ QBENCHMARK {
+ QCache<int, int> cache;
+ cache.setMaxCost(100);
+
+ for (int i = 0; i < 1000; i++)
+ cache.insert(i, new int(i));
+ }
+}
+
+void tst_QContiguousCache::contiguousCacheBenchmark()
+{
+ QBENCHMARK {
+ QContiguousCache<int> contiguousCache(100);
+ for (int i = 0; i < 1000; i++)
+ contiguousCache.insert(i, i);
+ }
+}
+
+void tst_QContiguousCache::setCapacity()
+{
+ int i;
+ QContiguousCache<int> contiguousCache(100);
+ for (i = 280; i < 310; ++i)
+ contiguousCache.insert(i, i);
+ QCOMPARE(contiguousCache.capacity(), 100);
+ QCOMPARE(contiguousCache.count(), 30);
+ QCOMPARE(contiguousCache.firstIndex(), 280);
+ QCOMPARE(contiguousCache.lastIndex(), 309);
+
+ for (i = contiguousCache.firstIndex(); i <= contiguousCache.lastIndex(); ++i) {
+ QVERIFY(contiguousCache.containsIndex(i));
+ QCOMPARE(contiguousCache.at(i), i);
+ }
+
+ contiguousCache.setCapacity(150);
+
+ QCOMPARE(contiguousCache.capacity(), 150);
+ QCOMPARE(contiguousCache.count(), 30);
+ QCOMPARE(contiguousCache.firstIndex(), 280);
+ QCOMPARE(contiguousCache.lastIndex(), 309);
+
+ for (i = contiguousCache.firstIndex(); i <= contiguousCache.lastIndex(); ++i) {
+ QVERIFY(contiguousCache.containsIndex(i));
+ QCOMPARE(contiguousCache.at(i), i);
+ }
+
+ contiguousCache.setCapacity(20);
+
+ QCOMPARE(contiguousCache.capacity(), 20);
+ QCOMPARE(contiguousCache.count(), 20);
+ QCOMPARE(contiguousCache.firstIndex(), 290);
+ QCOMPARE(contiguousCache.lastIndex(), 309);
+
+ for (i = contiguousCache.firstIndex(); i <= contiguousCache.lastIndex(); ++i) {
+ QVERIFY(contiguousCache.containsIndex(i));
+ QCOMPARE(contiguousCache.at(i), i);
+ }
+}
+
+#include "tst_qcontiguouscache.moc"
diff --git a/tests/auto/qcssparser/tst_cssparser.cpp b/tests/auto/qcssparser/tst_cssparser.cpp
index 17df9a2..80f62a4 100644
--- a/tests/auto/qcssparser/tst_cssparser.cpp
+++ b/tests/auto/qcssparser/tst_cssparser.cpp
@@ -114,11 +114,52 @@ void tst_CssParser::scanner_data()
}
}
+
+static char *tokenName(QCss::TokenType t)
+{
+ switch (t) {
+ case QCss::NONE: return "NONE";
+ case QCss::S: return "S";
+ case QCss::CDO: return "CDO";
+ case QCss::CDC: return "CDC";
+ case QCss::INCLUDES: return "INCLUDES";
+ case QCss::DASHMATCH: return "DASHMATCH";
+ case QCss::LBRACE: return "LBRACE";
+ case QCss::PLUS: return "PLUS";
+ case QCss::GREATER: return "GREATER";
+ case QCss::COMMA: return "COMMA";
+ case QCss::STRING: return "STRING";
+ case QCss::INVALID: return "INVALID";
+ case QCss::IDENT: return "IDENT";
+ case QCss::HASH: return "HASH";
+ case QCss::ATKEYWORD_SYM: return "ATKEYWORD_SYM";
+ case QCss::EXCLAMATION_SYM: return "EXCLAMATION_SYM";
+ case QCss::LENGTH: return "LENGTH";
+ case QCss::PERCENTAGE: return "PERCENTAGE";
+ case QCss::NUMBER: return "NUMBER";
+ case QCss::FUNCTION: return "FUNCTION";
+ case QCss::COLON: return "COLON";
+ case QCss::SEMICOLON: return "SEMICOLON";
+ case QCss::RBRACE: return "RBRACE";
+ case QCss::SLASH: return "SLASH";
+ case QCss::MINUS: return "MINUS";
+ case QCss::DOT: return "DOT";
+ case QCss::STAR: return "STAR";
+ case QCss::LBRACKET: return "LBRACKET";
+ case QCss::RBRACKET: return "RBRACKET";
+ case QCss::EQUAL: return "EQUAL";
+ case QCss::LPAREN: return "LPAREN";
+ case QCss::RPAREN: return "RPAREN";
+ case QCss::OR: return "OR";
+ }
+ return "";
+}
+
static void debug(const QVector<QCss::Symbol> &symbols, int index = -1)
{
qDebug() << "all symbols:";
for (int i = 0; i < symbols.count(); ++i)
- qDebug() << "(" << i << "); Token:" << QCss::Scanner::tokenName(symbols.at(i).token) << "; Lexem:" << symbols.at(i).lexem();
+ qDebug() << "(" << i << "); Token:" << tokenName(symbols.at(i).token) << "; Lexem:" << symbols.at(i).lexem();
if (index != -1)
qDebug() << "failure at index" << index;
}
@@ -160,7 +201,7 @@ void tst_CssParser::scanner()
QCOMPARE(l.count(), 2);
const QString expectedToken = l.at(0);
const QString expectedLexem = l.at(1);
- QString actualToken = QString::fromLatin1(QCss::Scanner::tokenName(symbols.at(i).token));
+ QString actualToken = QString::fromLatin1(tokenName(symbols.at(i).token));
if (actualToken != expectedToken) {
debug(symbols, i);
QCOMPARE(actualToken, expectedToken);
diff --git a/tests/auto/qeasingcurve/qeasingcurve.pro b/tests/auto/qeasingcurve/qeasingcurve.pro
new file mode 100644
index 0000000..2b66081
--- /dev/null
+++ b/tests/auto/qeasingcurve/qeasingcurve.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT = core
+SOURCES += tst_qeasingcurve.cpp
diff --git a/tests/auto/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/qeasingcurve/tst_qeasingcurve.cpp
new file mode 100644
index 0000000..b25cdc7
--- /dev/null
+++ b/tests/auto/qeasingcurve/tst_qeasingcurve.cpp
@@ -0,0 +1,493 @@
+/****************************************************************************
+**
+** 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 <QtTest/QtTest>
+
+#if QT_VERSION < 0x040200
+QTEST_NOOP_MAIN
+#else
+
+#include <qeasingcurve.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QEasingCurve : public QObject {
+ Q_OBJECT
+
+public:
+ tst_QEasingCurve();
+ virtual ~tst_QEasingCurve();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private slots:
+ void type();
+ void propertyDefaults();
+ void valueForProgress_data();
+ void valueForProgress();
+ void setCustomType();
+ void operators();
+
+protected:
+};
+
+tst_QEasingCurve::tst_QEasingCurve()
+{
+}
+
+tst_QEasingCurve::~tst_QEasingCurve()
+{
+}
+
+void tst_QEasingCurve::init()
+{
+}
+
+void tst_QEasingCurve::cleanup()
+{
+}
+#include <qdebug.h>
+
+void tst_QEasingCurve::type()
+{
+ {
+ QEasingCurve curve(QEasingCurve::Linear);
+ QCOMPARE(curve.period(), 0.3);
+ QCOMPARE(curve.amplitude(), 1.0);
+
+ curve.setPeriod(5);
+ curve.setAmplitude(3);
+ QCOMPARE(curve.period(), 5.0);
+ QCOMPARE(curve.amplitude(), 3.0);
+
+ curve.setType(QEasingCurve::InElastic);
+ QCOMPARE(curve.period(), 5.0);
+ QCOMPARE(curve.amplitude(), 3.0);
+ }
+
+ {
+ QEasingCurve curve(QEasingCurve::InElastic);
+ QCOMPARE(curve.period(), 0.3);
+ QCOMPARE(curve.amplitude(), 1.0);
+ curve.setAmplitude(2);
+ QCOMPARE(curve.type(), QEasingCurve::InElastic);
+ curve.setType(QEasingCurve::Linear);
+ }
+
+ {
+ // check bounaries
+ QEasingCurve curve(QEasingCurve::InCubic);
+ QTest::ignoreMessage(QtWarningMsg, "QEasingCurve: Invalid curve type 9999");
+ curve.setType((QEasingCurve::Type)9999);
+ QCOMPARE(curve.type(), QEasingCurve::InCubic);
+ QTest::ignoreMessage(QtWarningMsg, "QEasingCurve: Invalid curve type -9999");
+ curve.setType((QEasingCurve::Type)-9999);
+ QCOMPARE(curve.type(), QEasingCurve::InCubic);
+ QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QEasingCurve: Invalid curve type %1")
+ .arg(QEasingCurve::NCurveTypes).toLatin1().constData());
+ curve.setType(QEasingCurve::NCurveTypes);
+ QCOMPARE(curve.type(), QEasingCurve::InCubic);
+ QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QEasingCurve: Invalid curve type %1")
+ .arg(QEasingCurve::Custom).toLatin1().constData());
+ curve.setType(QEasingCurve::Custom);
+ QCOMPARE(curve.type(), QEasingCurve::InCubic);
+ QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QEasingCurve: Invalid curve type %1")
+ .arg(-1).toLatin1().constData());
+ curve.setType((QEasingCurve::Type)-1);
+ QCOMPARE(curve.type(), QEasingCurve::InCubic);
+ curve.setType(QEasingCurve::Linear);
+ QCOMPARE(curve.type(), QEasingCurve::Linear);
+ curve.setType(QEasingCurve::CosineCurve);
+ QCOMPARE(curve.type(), QEasingCurve::CosineCurve);
+ }
+}
+
+void tst_QEasingCurve::propertyDefaults()
+{
+ {
+ // checks if the defaults are correct, but also demonstrates a weakness with the API.
+ QEasingCurve curve(QEasingCurve::InElastic);
+ QCOMPARE(curve.period(), 0.3);
+ QCOMPARE(curve.amplitude(), 1.0);
+ QCOMPARE(curve.overshoot(), qreal(1.70158f));
+ curve.setType(QEasingCurve::InBounce);
+ QCOMPARE(curve.period(), 0.3);
+ QCOMPARE(curve.amplitude(), 1.0);
+ QCOMPARE(curve.overshoot(), qreal(1.70158f));
+ curve.setType(QEasingCurve::Linear);
+ QCOMPARE(curve.period(), 0.3);
+ QCOMPARE(curve.amplitude(), 1.0);
+ QCOMPARE(curve.overshoot(), qreal(1.70158f));
+ curve.setType(QEasingCurve::InElastic);
+ QCOMPARE(curve.period(), 0.3);
+ QCOMPARE(curve.amplitude(), 1.0);
+ QCOMPARE(curve.overshoot(), qreal(1.70158f));
+ curve.setPeriod(0.4);
+ curve.setAmplitude(0.6);
+ curve.setOvershoot(1.0);
+ curve.setType(QEasingCurve::Linear);
+ QCOMPARE(curve.period(), 0.4);
+ QCOMPARE(curve.amplitude(), 0.6);
+ QCOMPARE(curve.overshoot(), 1.0);
+ curve.setType(QEasingCurve::InElastic);
+ QCOMPARE(curve.period(), 0.4);
+ QCOMPARE(curve.amplitude(), 0.6);
+ QCOMPARE(curve.overshoot(), 1.0);
+ }
+}
+
+typedef QList<int> IntList;
+typedef QList<qreal> RealList;
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(RealList)
+
+void tst_QEasingCurve::valueForProgress_data()
+{
+ QTest::addColumn<int>("type");
+ QTest::addColumn<IntList>("at");
+ QTest::addColumn<RealList>("expected");
+ // automatically generated.
+ // note that values are scaled from range [0,1] to range [0, 100] in order to store them as
+ // integer values and avoid fp inaccuracies
+ QTest::newRow("Linear") << int(QEasingCurve::Linear)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.1 << 0.2 << 0.3 << 0.4 << 0.5 << 0.6 << 0.7 << 0.8 << 0.9 << 1);
+
+ QTest::newRow("InQuad") << int(QEasingCurve::InQuad)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.01 << 0.04 << 0.09 << 0.16 << 0.25 << 0.36 << 0.49 << 0.64 << 0.81 << 1);
+
+ QTest::newRow("OutQuad") << int(QEasingCurve::OutQuad)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.19 << 0.36 << 0.51 << 0.64 << 0.75 << 0.84 << 0.91 << 0.96 << 0.99 << 1);
+
+ QTest::newRow("InOutQuad") << int(QEasingCurve::InOutQuad)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.02 << 0.08 << 0.18 << 0.32 << 0.5 << 0.68 << 0.82 << 0.92 << 0.98 << 1);
+
+ QTest::newRow("OutInQuad") << int(QEasingCurve::OutInQuad)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.18 << 0.32 << 0.42 << 0.48 << 0.5 << 0.52 << 0.58 << 0.68 << 0.82 << 1);
+
+ QTest::newRow("InCubic") << int(QEasingCurve::InCubic)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.001 << 0.008 << 0.027 << 0.064 << 0.125 << 0.216 << 0.343 << 0.512 << 0.729 << 1);
+
+ QTest::newRow("OutCubic") << int(QEasingCurve::OutCubic)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.271 << 0.488 << 0.657 << 0.784 << 0.875 << 0.936 << 0.973 << 0.992 << 0.999 << 1);
+
+ QTest::newRow("InOutCubic") << int(QEasingCurve::InOutCubic)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.004 << 0.032 << 0.108 << 0.256 << 0.5 << 0.744 << 0.892 << 0.968 << 0.996 << 1);
+
+ QTest::newRow("OutInCubic") << int(QEasingCurve::OutInCubic)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.244 << 0.392 << 0.468 << 0.496 << 0.5 << 0.504 << 0.532 << 0.608 << 0.756 << 1);
+
+ QTest::newRow("InQuart") << int(QEasingCurve::InQuart)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.0001 << 0.0016 << 0.0081 << 0.0256 << 0.0625 << 0.1296 << 0.2401 << 0.4096 << 0.6561 << 1);
+
+ QTest::newRow("OutQuart") << int(QEasingCurve::OutQuart)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.3439 << 0.5904 << 0.7599 << 0.8704 << 0.9375 << 0.9744 << 0.9919 << 0.9984 << 0.9999 << 1);
+
+ QTest::newRow("InOutQuart") << int(QEasingCurve::InOutQuart)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.0008 << 0.0128 << 0.0648 << 0.2048 << 0.5 << 0.7952 << 0.9352 << 0.9872 << 0.9992 << 1);
+
+ QTest::newRow("OutInQuart") << int(QEasingCurve::OutInQuart)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.2952 << 0.4352 << 0.4872 << 0.4992 << 0.5 << 0.5008 << 0.5128 << 0.5648 << 0.7048 << 1);
+
+ QTest::newRow("InQuint") << int(QEasingCurve::InQuint)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 1e-05 << 0.00032 << 0.00243 << 0.01024 << 0.03125 << 0.07776 << 0.1681 << 0.3277 << 0.5905 << 1);
+
+ QTest::newRow("OutQuint") << int(QEasingCurve::OutQuint)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.4095 << 0.6723 << 0.8319 << 0.9222 << 0.9688 << 0.9898 << 0.9976 << 0.9997 << 1 << 1);
+
+ QTest::newRow("InOutQuint") << int(QEasingCurve::InOutQuint)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.00016 << 0.00512 << 0.03888 << 0.1638 << 0.5 << 0.8362 << 0.9611 << 0.9949 << 0.9998 << 1);
+
+ QTest::newRow("OutInQuint") << int(QEasingCurve::OutInQuint)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.3362 << 0.4611 << 0.4949 << 0.4998 << 0.5 << 0.5002 << 0.5051 << 0.5389 << 0.6638 << 1);
+
+ QTest::newRow("InSine") << int(QEasingCurve::InSine)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.01231 << 0.04894 << 0.109 << 0.191 << 0.2929 << 0.4122 << 0.546 << 0.691 << 0.8436 << 1);
+
+ QTest::newRow("OutSine") << int(QEasingCurve::OutSine)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.1564 << 0.309 << 0.454 << 0.5878 << 0.7071 << 0.809 << 0.891 << 0.9511 << 0.9877 << 1);
+
+ QTest::newRow("InOutSine") << int(QEasingCurve::InOutSine)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.02447 << 0.09549 << 0.2061 << 0.3455 << 0.5 << 0.6545 << 0.7939 << 0.9045 << 0.9755 << 1);
+
+ QTest::newRow("OutInSine") << int(QEasingCurve::OutInSine)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.1545 << 0.2939 << 0.4045 << 0.4755 << 0.5 << 0.5245 << 0.5955 << 0.7061 << 0.8455 << 1);
+
+ QTest::newRow("InExpo") << int(QEasingCurve::InExpo)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.0009531 << 0.002906 << 0.006812 << 0.01462 << 0.03025 << 0.0615 << 0.124 << 0.249 << 0.499 << 1);
+
+ QTest::newRow("OutExpo") << int(QEasingCurve::OutExpo)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.5005 << 0.7507 << 0.8759 << 0.9384 << 0.9697 << 0.9854 << 0.9932 << 0.9971 << 0.999 << 1);
+
+ QTest::newRow("InOutExpo") << int(QEasingCurve::InOutExpo)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.001453 << 0.007312 << 0.03075 << 0.1245 << 0.5002 << 0.8754 << 0.9692 << 0.9927 << 0.9985 << 1);
+
+ QTest::newRow("OutInExpo") << int(QEasingCurve::OutInExpo)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.3754 << 0.4692 << 0.4927 << 0.4985 << 0.5 << 0.5015 << 0.5073 << 0.5308 << 0.6245 << 1);
+
+ QTest::newRow("InCirc") << int(QEasingCurve::InCirc)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.005013 << 0.0202 << 0.04606 << 0.08348 << 0.134 << 0.2 << 0.2859 << 0.4 << 0.5641 << 1);
+
+ QTest::newRow("OutCirc") << int(QEasingCurve::OutCirc)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.4359 << 0.6 << 0.7141 << 0.8 << 0.866 << 0.9165 << 0.9539 << 0.9798 << 0.995 << 1);
+
+ QTest::newRow("InOutCirc") << int(QEasingCurve::InOutCirc)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.0101 << 0.04174 << 0.1 << 0.2 << 0.5 << 0.8 << 0.9 << 0.9583 << 0.9899 << 1);
+
+ QTest::newRow("OutInCirc") << int(QEasingCurve::OutInCirc)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.3 << 0.4 << 0.4583 << 0.4899 << 0.5 << 0.5101 << 0.5417 << 0.6 << 0.7 << 1);
+
+ QTest::newRow("InElastic") << int(QEasingCurve::InElastic)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.001953 << -0.001953 << -0.003906 << 0.01562 << -0.01562 << -0.03125 << 0.125 << -0.125 << -0.25 << 1);
+
+ QTest::newRow("OutElastic") << int(QEasingCurve::OutElastic)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 1.25 << 1.125 << 0.875 << 1.031 << 1.016 << 0.9844 << 1.004 << 1.002 << 0.998 << 1);
+
+ QTest::newRow("InOutElastic") << int(QEasingCurve::InOutElastic)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << -0.0009766 << 0.007812 << -0.01563 << -0.0625 << 0.5 << 1.062 << 1.016 << 0.9922 << 1.001 << 1);
+
+ QTest::newRow("OutInElastic") << int(QEasingCurve::OutInElastic)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.375 << 0.5625 << 0.4922 << 0.498 << 0.5 << 0.4961 << 0.5078 << 0.5313 << 0.25 << 1);
+
+ QTest::newRow("InBack") << int(QEasingCurve::InBack)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << -0.01431 << -0.04645 << -0.0802 << -0.09935 << -0.0877 << -0.02903 << 0.09287 << 0.2942 << 0.5912 << 1);
+
+ QTest::newRow("OutBack") << int(QEasingCurve::OutBack)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.4088 << 0.7058 << 0.9071 << 1.029 << 1.088 << 1.099 << 1.08 << 1.046 << 1.014 << 1);
+
+ QTest::newRow("InOutBack") << int(QEasingCurve::InOutBack)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << -0.03752 << -0.09256 << -0.07883 << 0.08993 << 0.5 << 0.9101 << 1.079 << 1.093 << 1.038 << 1);
+
+ QTest::newRow("OutInBack") << int(QEasingCurve::OutInBack)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.3529 << 0.5145 << 0.5497 << 0.5232 << 0.5 << 0.4768 << 0.4503 << 0.4855 << 0.6471 << 1);
+
+ QTest::newRow("InBounce") << int(QEasingCurve::InBounce)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.01188 << 0.06 << 0.06937 << 0.2275 << 0.2344 << 0.09 << 0.3194 << 0.6975 << 0.9244 << 1);
+
+ QTest::newRow("OutBounce") << int(QEasingCurve::OutBounce)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.07563 << 0.3025 << 0.6806 << 0.91 << 0.7656 << 0.7725 << 0.9306 << 0.94 << 0.9881 << 1);
+
+ QTest::newRow("InOutBounce") << int(QEasingCurve::InOutBounce)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.03 << 0.1138 << 0.045 << 0.3488 << 0.5 << 0.6512 << 0.955 << 0.8862 << 0.97 << 1);
+
+ QTest::newRow("OutInBounce") << int(QEasingCurve::OutInBounce)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.1513 << 0.41 << 0.2725 << 0.44 << 0.5 << 0.56 << 0.7275 << 0.59 << 0.8488 << 1);
+
+ QTest::newRow("InCurve") << int(QEasingCurve::InCurve)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.02447 << 0.1059 << 0.2343 << 0.3727 << 0.5 << 0.6055 << 0.7 << 0.8 << 0.9 << 1);
+
+ QTest::newRow("OutCurve") << int(QEasingCurve::OutCurve)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.1 << 0.2 << 0.3 << 0.3945 << 0.5 << 0.6273 << 0.7657 << 0.8941 << 0.9755 << 1);
+
+ QTest::newRow("SineCurve") << int(QEasingCurve::SineCurve)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0 << 0.09549 << 0.3455 << 0.6545 << 0.9045 << 1 << 0.9045 << 0.6545 << 0.3455 << 0.09549 << 0);
+
+ QTest::newRow("CosineCurve") << int(QEasingCurve::CosineCurve)
+ << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100)
+ << (RealList() << 0.5 << 0.7939 << 0.9755 << 0.9755 << 0.7939 << 0.5 << 0.2061 << 0.02447 << 0.02447 << 0.2061 << 0.5);
+
+}
+
+
+void tst_QEasingCurve::valueForProgress()
+{
+#if 0
+ // used to generate data tables...
+ QFile out;
+ out.open(stdout, QIODevice::WriteOnly);
+ for (int c = QEasingCurve::Linear; c < QEasingCurve::NCurveTypes - 1; ++c) {
+ QEasingCurve curve((QEasingCurve::Type)c);
+ QMetaObject mo = QEasingCurve::staticMetaObject;
+ QString strCurve = QLatin1String(mo.enumerator(mo.indexOfEnumerator("Type")).key(c));
+ QString strInputs;
+ QString strOutputs;
+
+ for (int t = 0; t <= 100; t+= 10) {
+ qreal ease = curve.valueForProgress(t/qreal(100));
+ strInputs += QString::fromAscii(" << %1").arg(t);
+ strOutputs += " << " + QString().setNum(ease, 'g', 4);
+ }
+ QString str = QString::fromAscii(" QTest::newRow(\"%1\") << int(QEasingCurve::%2)\n"
+ " << (IntList() %3)\n"
+ " << (RealList()%4);\n\n")
+ .arg(strCurve)
+ .arg(strCurve)
+ .arg(strInputs)
+ .arg(strOutputs);
+ out.write(str.toLatin1().constData());
+ }
+ out.close();
+ exit(1);
+#else
+ QFETCH(int, type);
+ QFETCH(IntList, at);
+ QFETCH(RealList, expected);
+
+ QEasingCurve curve((QEasingCurve::Type)type);
+ for (int i = 0; i < at.count(); ++i) {
+ qreal ease = curve.valueForProgress(at.at(i)/qreal(100));
+ // converting ease to 4 precision qreal to match the generated samples
+ qreal easeConv = qreal(QString().setNum(ease, 'g', 4).toDouble());
+ qreal ex = expected.at(i);
+
+ // the least significant digit it is still subject to rounding errors
+ qreal error = easeConv - ex;
+ // accept the potential rounding error in the least significant digit
+ QVERIFY(error <= 0.00001 );
+ }
+#endif
+}
+
+static qreal discreteEase(qreal progress)
+{
+ return qFloor(progress * 10) / qreal(10.0);
+}
+
+void tst_QEasingCurve::setCustomType()
+{
+ QEasingCurve curve;
+ curve.setCustomType(&discreteEase);
+ QCOMPARE(curve.type(), QEasingCurve::Custom);
+ QCOMPARE(curve.valueForProgress(0.0), 0.0);
+ QCOMPARE(curve.valueForProgress(0.05), 0.0);
+ QCOMPARE(curve.valueForProgress(0.10), 0.1);
+ QCOMPARE(curve.valueForProgress(0.15), 0.1);
+ QCOMPARE(curve.valueForProgress(0.20), 0.2);
+ QCOMPARE(curve.valueForProgress(0.25), 0.2);
+ QCOMPARE(curve.valueForProgress(0.30), 0.3);
+ QCOMPARE(curve.valueForProgress(0.35), 0.3);
+ QCOMPARE(curve.valueForProgress(0.999999), 0.9);
+
+ curve.setType(QEasingCurve::Linear);
+ QCOMPARE(curve.type(), QEasingCurve::Linear);
+ QCOMPARE(curve.valueForProgress(0.0), 0.0);
+ QCOMPARE(curve.valueForProgress(0.1), 0.1);
+ QCOMPARE(curve.valueForProgress(0.5), 0.5);
+ QCOMPARE(curve.valueForProgress(0.99), 0.99);
+}
+
+void tst_QEasingCurve::operators()
+{
+ // operator=
+ QEasingCurve curve;
+ QEasingCurve curve2;
+ curve.setCustomType(&discreteEase);
+ curve2 = curve;
+ QCOMPARE(curve2.type(), QEasingCurve::Custom);
+ QCOMPARE(curve2.valueForProgress(0.0), 0.0);
+ QCOMPARE(curve2.valueForProgress(0.05), 0.0);
+ QCOMPARE(curve2.valueForProgress(0.15), 0.1);
+ QCOMPARE(curve2.valueForProgress(0.25), 0.2);
+ QCOMPARE(curve2.valueForProgress(0.35), 0.3);
+ QCOMPARE(curve2.valueForProgress(0.999999), 0.9);
+
+ // operator==
+ curve.setType(QEasingCurve::InBack);
+ curve2 = curve;
+ curve2.setOvershoot(qreal(1.70158f));
+ QCOMPARE(curve.overshoot(), curve2.overshoot());
+ QVERIFY(curve2 == curve);
+
+ curve.setOvershoot(3.0);
+ QVERIFY(curve2 != curve);
+ curve2.setOvershoot(3.0);
+ QVERIFY(curve2 == curve);
+
+ curve2.setType(QEasingCurve::Linear);
+ QCOMPARE(curve.overshoot(), curve2.overshoot());
+ QVERIFY(curve2 != curve);
+ curve2.setType(QEasingCurve::InBack);
+ QCOMPARE(curve.overshoot(), curve2.overshoot());
+ QVERIFY(curve2 == curve);
+}
+
+
+QTEST_MAIN(tst_QEasingCurve)
+#include "tst_qeasingcurve.moc"
+
+#endif //QT_VERSION
diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp
index 597343f..4bd6232 100644
--- a/tests/auto/qfile/tst_qfile.cpp
+++ b/tests/auto/qfile/tst_qfile.cpp
@@ -126,6 +126,7 @@ private slots:
void permissions();
void setPermissions();
void copy();
+ void copyAfterFail();
void copyRemovesTemporaryFile() const;
void copyShouldntOverwrite();
void copyFallback();
@@ -227,8 +228,15 @@ void tst_QFile::cleanup()
// for renameFallback()
QFile::remove("file-rename-destination.txt");
+ // for copyAfterFail()
+ QFile::remove("file-to-be-copied.txt");
+ QFile::remove("existing-file.txt");
+ QFile::remove("copied-file-1.txt");
+ QFile::remove("copied-file-2.txt");
+
// for renameMultiple()
QFile::remove("file-to-be-renamed.txt");
+ QFile::remove("existing-file.txt");
QFile::remove("file-renamed-once.txt");
QFile::remove("file-renamed-twice.txt");
}
@@ -904,6 +912,39 @@ void tst_QFile::copy()
QFile::copy(QDir::currentPath(), QDir::currentPath() + QLatin1String("/test2"));
}
+void tst_QFile::copyAfterFail()
+{
+ QFile file1("file-to-be-copied.txt");
+ QFile file2("existing-file.txt");
+
+ QVERIFY(file1.open(QIODevice::ReadWrite) && "(test-precondition)");
+ QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)");
+ QVERIFY(!QFile::exists("copied-file-1.txt") && "(test-precondition)");
+ QVERIFY(!QFile::exists("copied-file-2.txt") && "(test-precondition)");
+
+ QVERIFY(!file1.copy("existing-file.txt"));
+ QCOMPARE(file1.error(), QFile::CopyError);
+
+ QVERIFY(file1.copy("copied-file-1.txt"));
+ QVERIFY(!file1.isOpen());
+ QCOMPARE(file1.error(), QFile::NoError);
+
+ QVERIFY(!file1.copy("existing-file.txt"));
+ QCOMPARE(file1.error(), QFile::CopyError);
+
+ QVERIFY(file1.copy("copied-file-2.txt"));
+ QVERIFY(!file1.isOpen());
+ QCOMPARE(file1.error(), QFile::NoError);
+
+ QVERIFY(QFile::exists("copied-file-1.txt"));
+ QVERIFY(QFile::exists("copied-file-2.txt"));
+
+ QVERIFY(QFile::remove("file-to-be-copied.txt") && "(test-cleanup)");
+ QVERIFY(QFile::remove("existing-file.txt") && "(test-cleanup)");
+ QVERIFY(QFile::remove("copied-file-1.txt") && "(test-cleanup)");
+ QVERIFY(QFile::remove("copied-file-2.txt") && "(test-cleanup)");
+}
+
void tst_QFile::copyRemovesTemporaryFile() const
{
const QString newName(QLatin1String("copyRemovesTemporaryFile"));
@@ -2152,24 +2193,42 @@ void tst_QFile::renameMultiple()
{
// create the file if it doesn't exist
QFile file("file-to-be-renamed.txt");
+ QFile file2("existing-file.txt");
QVERIFY(file.open(QIODevice::ReadWrite) && "(test-precondition)");
+ QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)");
// any stale files from previous test failures?
QFile::remove("file-renamed-once.txt");
QFile::remove("file-renamed-twice.txt");
// begin testing
+ QVERIFY(QFile::exists("existing-file.txt"));
+ QVERIFY(!file.rename("existing-file.txt"));
+ QCOMPARE(file.error(), QFile::RenameError);
+ QCOMPARE(file.fileName(), QString("file-to-be-renamed.txt"));
+
QVERIFY(file.rename("file-renamed-once.txt"));
+ QVERIFY(!file.isOpen());
QCOMPARE(file.fileName(), QString("file-renamed-once.txt"));
+
+ QVERIFY(QFile::exists("existing-file.txt"));
+ QVERIFY(!file.rename("existing-file.txt"));
+ QCOMPARE(file.error(), QFile::RenameError);
+ QCOMPARE(file.fileName(), QString("file-renamed-once.txt"));
+
QVERIFY(file.rename("file-renamed-twice.txt"));
+ QVERIFY(!file.isOpen());
QCOMPARE(file.fileName(), QString("file-renamed-twice.txt"));
+ QVERIFY(QFile::exists("existing-file.txt"));
QVERIFY(!QFile::exists("file-to-be-renamed.txt"));
QVERIFY(!QFile::exists("file-renamed-once.txt"));
QVERIFY(QFile::exists("file-renamed-twice.txt"));
file.remove();
+ file2.remove();
QVERIFY(!QFile::exists("file-renamed-twice.txt"));
+ QVERIFY(!QFile::exists("existing-file.txt"));
}
void tst_QFile::appendAndRead()
diff --git a/tests/auto/qfileinfo/tst_qfileinfo.cpp b/tests/auto/qfileinfo/tst_qfileinfo.cpp
index cc31029..763c266 100644
--- a/tests/auto/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp
@@ -61,6 +61,7 @@
#include <qdebug.h>
#include "../network-settings.h"
+#include <private/qfileinfo_p.h>
//TESTED_CLASS=
//TESTED_FILES=
@@ -75,6 +76,9 @@ public:
private slots:
void getSetCheck();
+
+ void copy();
+
void isFile_data();
void isFile();
@@ -179,6 +183,58 @@ void tst_QFileInfo::getSetCheck()
QCOMPARE(true, obj1.caching());
}
+static QFileInfoPrivate* getPrivate(QFileInfo &info)
+{
+ return (*reinterpret_cast<QFileInfoPrivate**>(&info));
+}
+
+void tst_QFileInfo::copy()
+{
+ QTemporaryFile *t;
+ t = new QTemporaryFile;
+ t->open();
+ QFileInfo info(t->fileName());
+ QVERIFY(info.exists());
+
+ //copy constructor
+ QFileInfo info2(info);
+ QFileInfoPrivate *privateInfo = getPrivate(info);
+ QFileInfoPrivate *privateInfo2 = getPrivate(info2);
+ QCOMPARE(privateInfo->data, privateInfo2->data);
+
+ //operator =
+ QFileInfo info3 = info;
+ QFileInfoPrivate *privateInfo3 = getPrivate(info3);
+ QCOMPARE(privateInfo->data, privateInfo3->data);
+ QCOMPARE(privateInfo2->data, privateInfo3->data);
+
+ //refreshing info3 will detach it
+ QFile file(info.absoluteFilePath());
+ QVERIFY(file.open(QFile::WriteOnly));
+ QCOMPARE(file.write("JAJAJAA"), qint64(7));
+ file.flush();
+
+ QTest::qWait(250);
+#if defined(Q_OS_WIN) || defined(Q_OS_WINCE)
+ if (QSysInfo::windowsVersion() & QSysInfo::WV_VISTA ||
+ QSysInfo::windowsVersion() & QSysInfo::WV_CE_based)
+ file.close();
+#endif
+#if defined(Q_OS_WINCE)
+ // On Windows CE we need to close the file.
+ // Otherwise the content will be cached and not
+ // flushed to the storage, although we flushed it
+ // manually!!! CE has interim cache, we cannot influence.
+ QTest::qWait(5000);
+#endif
+ info3.refresh();
+ QVERIFY(privateInfo->data != privateInfo3->data);
+ QVERIFY(privateInfo2->data != privateInfo3->data);
+ QCOMPARE(privateInfo->data, privateInfo2->data);
+
+
+}
+
tst_QFileInfo::tst_QFileInfo()
{
Q_SET_DEFAULT_IAP
diff --git a/tests/auto/qformlayout/tst_qformlayout.cpp b/tests/auto/qformlayout/tst_qformlayout.cpp
index c4c6f70..242974d 100644
--- a/tests/auto/qformlayout/tst_qformlayout.cpp
+++ b/tests/auto/qformlayout/tst_qformlayout.cpp
@@ -125,6 +125,7 @@ private slots:
Qt::Orientations expandingDirections() const;
*/
+ void fieldMinimumSize();
};
tst_QFormLayout::tst_QFormLayout()
@@ -905,6 +906,35 @@ void tst_QFormLayout::layoutAlone()
QTest::qWait(500);
}
+
+void tst_QFormLayout::fieldMinimumSize()
+{
+ //check that the field with is bigger than its minimumSizeHint for any size of the widget
+ // even if the label with is not fixed
+ QWidget w;
+ QFormLayout layout;
+ layout.setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+ w.setLayout(&layout);
+ QLabel label1("Here is a strange test case");
+ label1.setWordWrap(true);
+ QLabel label2("Here is another label");
+ label2.setWordWrap(true);
+ QLabel shortLabel("short");
+ QLabel longLabel("Quite long label");
+ layout.addRow(&label1, &shortLabel);
+ layout.addRow(&label2, &longLabel);
+ w.show();
+ int width = w.size().width() + 9;
+
+ do {
+ w.resize(width, w.size().height());
+ layout.activate();
+ QVERIFY(shortLabel.size().width() >= shortLabel.minimumSizeHint().width());
+ QVERIFY(longLabel.size().width() >= longLabel.minimumSizeHint().width());
+ width -= 3;
+ } while(width >= w.minimumSizeHint().width());
+}
+
QTEST_MAIN(tst_QFormLayout)
#include "tst_qformlayout.moc"
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index 34a6ab1..d2a059a 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -44,6 +44,7 @@
#include <private/qtextcontrol_p.h>
#include <private/qgraphicsitem_p.h>
+#include <QStyleOptionGraphicsItem>
#include <QAbstractTextDocumentLayout>
#include <QBitmap>
#include <QCursor>
@@ -121,6 +122,7 @@ private slots:
void construction();
void constructionWithParent();
void destruction();
+ void deleteChildItem();
void scene();
void parentItem();
void setParentItem();
@@ -170,6 +172,7 @@ private slots:
void boundingRects2();
void sceneBoundingRect();
void childrenBoundingRect();
+ void childrenBoundingRectTransformed();
void group();
void setGroup();
void nestedGroups();
@@ -207,6 +210,7 @@ private slots:
void opacity_data();
void opacity();
void opacity2();
+ void opacityZeroUpdates();
void itemStacksBehindParent();
void nestedClipping();
void nestedClippingTransforms();
@@ -217,6 +221,14 @@ private slots:
void updateCachedItemAfterMove();
void deviceTransform_data();
void deviceTransform();
+ void update();
+ void setTransformProperties_data();
+ void setTransformProperties();
+ void itemUsesExtendedStyleOption();
+ void itemSendsGeometryChanges();
+ void moveItem();
+ void sorting_data();
+ void sorting();
// task specific tests below me
void task141694_textItemEnsureVisible();
@@ -227,6 +239,9 @@ private slots:
void task240400_clickOnTextItem();
void task243707_addChildBeforeParent();
void task197802_childrenVisibility();
+
+private:
+ QList<QGraphicsItem *> paintedItems;
};
void tst_QGraphicsItem::init()
@@ -246,50 +261,59 @@ void tst_QGraphicsItem::construction()
QCOMPARE(int(item->type()), int(QGraphicsEllipseItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsEllipseItem *>(item), (QGraphicsEllipseItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 1:
item = new QGraphicsLineItem;
QCOMPARE(int(item->type()), int(QGraphicsLineItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 2:
item = new QGraphicsPathItem;
QCOMPARE(int(item->type()), int(QGraphicsPathItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsPathItem *>(item), (QGraphicsPathItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 3:
item = new QGraphicsPixmapItem;
QCOMPARE(int(item->type()), int(QGraphicsPixmapItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsPixmapItem *>(item), (QGraphicsPixmapItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 4:
item = new QGraphicsPolygonItem;
QCOMPARE(int(item->type()), int(QGraphicsPolygonItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsPolygonItem *>(item), (QGraphicsPolygonItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 5:
item = new QGraphicsRectItem;
QCOMPARE(int(item->type()), int(QGraphicsRectItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)0);
+ QCOMPARE(item->flags(), 0);
break;
case 6:
- default:
item = new QGraphicsTextItem;
QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type));
QCOMPARE(qgraphicsitem_cast<QGraphicsTextItem *>(item), (QGraphicsTextItem *)item);
QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ // This is the only item that uses an extended style option.
+ QCOMPARE(item->flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
+ break;
+ default:
+ qFatal("You broke the logic, please fix!");
break;
}
QCOMPARE(item->scene(), (QGraphicsScene *)0);
QCOMPARE(item->parentItem(), (QGraphicsItem *)0);
QVERIFY(item->children().isEmpty());
- QCOMPARE(item->flags(), 0);
QVERIFY(item->isVisible());
QVERIFY(item->isEnabled());
QVERIFY(!item->isSelected());
@@ -514,6 +538,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()
@@ -1754,15 +1801,15 @@ void tst_QGraphicsItem::setMatrix()
QCOMPARE(rlist.at(2), unrotatedRect); // From post-update (update current state)
}
-static QList<QGraphicsItem *> paintedItems;
+static QList<QGraphicsItem *> _paintedItems;
class PainterItem : public QGraphicsItem
{
protected:
QRectF boundingRect() const
{ return QRectF(-10, -10, 20, 20); }
- void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
- { paintedItems << this; }
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ { _paintedItems << this; painter->fillRect(boundingRect(), Qt::red); }
};
void tst_QGraphicsItem::zValue()
@@ -1794,10 +1841,10 @@ void tst_QGraphicsItem::zValue()
QApplication::sendPostedEvents(); //glib workaround
#endif
- QVERIFY(!paintedItems.isEmpty());
- QVERIFY((paintedItems.size() % 4) == 0);
+ QVERIFY(!_paintedItems.isEmpty());
+ QVERIFY((_paintedItems.size() % 4) == 0);
for (int i = 0; i < 3; ++i)
- QVERIFY(paintedItems.at(i)->zValue() < paintedItems.at(i + 1)->zValue());
+ QVERIFY(_paintedItems.at(i)->zValue() < _paintedItems.at(i + 1)->zValue());
}
void tst_QGraphicsItem::shape()
@@ -2896,9 +2943,57 @@ void tst_QGraphicsItem::childrenBoundingRect()
childChild->setParentItem(child);
childChild->setPos(500, 500);
child->rotate(90);
+
+
+ scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red));;
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWait(5000);
+
QCOMPARE(parent->childrenBoundingRect(), QRectF(-500, -100, 600, 800));
}
+void tst_QGraphicsItem::childrenBoundingRectTransformed()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
+ rect2->setParentItem(rect);
+ rect3->setParentItem(rect2);
+ rect4->setParentItem(rect3);
+ rect5->setParentItem(rect4);
+
+ rect2->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect2->setPos(25, 25);
+ rect3->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect3->setPos(25, 25);
+ rect4->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect4->setPos(25, 25);
+ rect5->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect5->setPos(25, 25);
+
+ QRectF subTreeRect = rect->childrenBoundingRect();
+ QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
+ QCOMPARE(subTreeRect.top(), qreal(75.0));
+ QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
+ QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
+
+ rect->rotate(45);
+ rect2->rotate(-45);
+ rect3->rotate(45);
+ rect4->rotate(-45);
+ rect5->rotate(45);
+
+ subTreeRect = rect->childrenBoundingRect();
+ QCOMPARE(rect->childrenBoundingRect(), QRectF(-100, 75, 275, 250));
+}
+
void tst_QGraphicsItem::group()
{
QGraphicsScene scene;
@@ -3097,150 +3192,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()
@@ -3658,8 +3737,20 @@ void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem()
class ItemChangeTester : public QGraphicsRectItem
{
public:
- ItemChangeTester(){}
- ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent) {}
+ ItemChangeTester()
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+ ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent)
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+
+ void clear()
+ {
+ itemChangeReturnValue = QVariant();
+ itemSceneChangeTargetScene = 0;
+ changes.clear();
+ values.clear();
+ oldValues.clear();
+ }
+
QVariant itemChangeReturnValue;
QGraphicsScene *itemSceneChangeTargetScene;
@@ -3836,6 +3927,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);
@@ -3846,7 +3951,8 @@ void tst_QGraphicsItem::itemChange()
QCOMPARE(tester.changes.size(), changeCount);
QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemFlagsChange);
QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemFlagsHaveChanged);
- QCOMPARE(tester.values.at(tester.values.size() - 2), qVariantFromValue<quint32>(QGraphicsItem::ItemIsSelectable));
+ QVariant expectedFlags = qVariantFromValue<quint32>(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
+ QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags);
QCOMPARE(tester.values.at(tester.values.size() - 1), qVariantFromValue<quint32>(QGraphicsItem::ItemIsSelectable));
}
{
@@ -4644,7 +4750,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));
@@ -5301,7 +5407,7 @@ void tst_QGraphicsItem::task240400_clickOnTextItem()
QVERIFY(selectable ? item->isSelected() : !item->isSelected());
- //
+ //
if (textFlags & Qt::TextEditorInteraction)
QVERIFY(item->textCursor().columnNumber() > column);
else
@@ -5498,7 +5604,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");
@@ -5693,19 +5799,84 @@ void tst_QGraphicsItem::opacity2()
QCOMPARE(grandChild->repaints, 0);
}
+void tst_QGraphicsItem::opacityZeroUpdates()
+{
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+
+ child->setPos(10, 10);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ class MyGraphicsView : public QGraphicsView
+ { public:
+ int repaints;
+ QRegion paintedRegion;
+ MyGraphicsView(QGraphicsScene *scene) : QGraphicsView(scene), repaints(0) {}
+ void paintEvent(QPaintEvent *e)
+ {
+ ++repaints;
+ paintedRegion += e->region();
+ QGraphicsView::paintEvent(e);
+ }
+ void reset() { repaints = 0; paintedRegion = QRegion(); }
+ };
+
+ MyGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(250);
+
+ view.reset();
+ parent->setOpacity(0.0);
+
+ QTest::qWait(200);
+
+ // transforming items bounding rect to view coordinates
+ const QRect childDeviceBoundingRect = child->deviceTransform(view.viewportTransform())
+ .mapRect(child->boundingRect()).toRect();
+ const QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
+ .mapRect(parent->boundingRect()).toRect();
+
+ QRegion expectedRegion = parentDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+ expectedRegion += childDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+
+ QCOMPARE(view.paintedRegion, expectedRegion);
+}
+
+class StacksBehindParentHelper : public QGraphicsRectItem
+{
+public:
+ StacksBehindParentHelper(QList<QGraphicsItem *> *paintedItems, const QRectF &rect, QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(rect, parent), paintedItems(paintedItems)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ paintedItems->append(this);
+ }
+
+private:
+ QList<QGraphicsItem *> *paintedItems;
+};
+
void tst_QGraphicsItem::itemStacksBehindParent()
{
- QGraphicsRectItem *parent1 = new QGraphicsRectItem(QRectF(0, 0, 100, 50));
- QGraphicsRectItem *child11 = new QGraphicsRectItem(QRectF(-10, 10, 50, 50), parent1);
- QGraphicsRectItem *grandChild111 = new QGraphicsRectItem(QRectF(-20, 20, 50, 50), child11);
- QGraphicsRectItem *child12 = new QGraphicsRectItem(QRectF(60, 10, 50, 50), parent1);
- QGraphicsRectItem *grandChild121 = new QGraphicsRectItem(QRectF(70, 20, 50, 50), child12);
+ StacksBehindParentHelper *parent1 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
+ StacksBehindParentHelper *child11 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent1);
+ StacksBehindParentHelper *grandChild111 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child11);
+ StacksBehindParentHelper *child12 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent1);
+ StacksBehindParentHelper *grandChild121 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child12);
- QGraphicsRectItem *parent2 = new QGraphicsRectItem(QRectF(0, 0, 100, 50));
- QGraphicsRectItem *child21 = new QGraphicsRectItem(QRectF(-10, 10, 50, 50), parent2);
- QGraphicsRectItem *grandChild211 = new QGraphicsRectItem(QRectF(-20, 20, 50, 50), child21);
- QGraphicsRectItem *child22 = new QGraphicsRectItem(QRectF(60, 10, 50, 50), parent2);
- QGraphicsRectItem *grandChild221 = new QGraphicsRectItem(QRectF(70, 20, 50, 50), child22);
+ StacksBehindParentHelper *parent2 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
+ StacksBehindParentHelper *child21 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent2);
+ StacksBehindParentHelper *grandChild211 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child21);
+ StacksBehindParentHelper *child22 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent2);
+ StacksBehindParentHelper *grandChild221 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child22);
parent1->setData(0, "parent1");
child11->setData(0, "child11");
@@ -5727,25 +5898,57 @@ void tst_QGraphicsItem::itemStacksBehindParent()
scene.addItem(parent1);
scene.addItem(parent2);
+ paintedItems.clear();
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(250);
+
QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
<< grandChild111 << child11
<< grandChild121 << child12 << parent1
<< grandChild211 << child21
<< grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << parent1 << child12 << grandChild121
+ << child11 << grandChild111);
child11->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ scene.update();
+ paintedItems.clear();
+ QTest::qWait(250);
+
QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
<< grandChild121 << child12 << parent1
<< grandChild111 << child11
<< grandChild211 << child21
<< grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << child11 << grandChild111
+ << parent1 << child12 << grandChild121);
child12->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ paintedItems.clear();
+ scene.update();
+ QTest::qWait(250);
+
QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
<< parent1 << grandChild111 << child11
<< grandChild121 << child12
<< grandChild211 << child21
<< grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << child12 << grandChild121
+ << child11 << grandChild111 << parent1);
}
class ClippingAndTransformsScene : public QGraphicsScene
@@ -5792,8 +5995,9 @@ void tst_QGraphicsItem::nestedClipping()
l1->setData(0, "l1");
l2->setData(0, "l2");
l3->setData(0, "l3");
-
+
QGraphicsView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::IndirectPainting);
view.show();
#ifdef Q_WS_X11
qt_x11_wait_for_window_manager(&view);
@@ -5820,7 +6024,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
@@ -5962,7 +6166,7 @@ void tst_QGraphicsItem::tabChangesFocus_data()
void tst_QGraphicsItem::tabChangesFocus()
{
QFETCH(bool, tabChangesFocus);
-
+
QGraphicsScene scene;
QGraphicsTextItem *item = scene.addText("Hello");
item->setTabChangesFocus(tabChangesFocus);
@@ -6346,5 +6550,486 @@ void tst_QGraphicsItem::deviceTransform()
QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3);
}
+class MyGraphicsView : public QGraphicsView
+{
+public:
+ int repaints;
+ QRegion paintedRegion;
+ MyGraphicsView(QGraphicsScene *scene) : QGraphicsView(scene), repaints(0) {}
+ void paintEvent(QPaintEvent *e)
+ {
+ paintedRegion += e->region();
+ ++repaints;
+ QGraphicsView::paintEvent(e);
+ }
+ void reset() { repaints = 0; paintedRegion = QRegion(); }
+};
+
+void tst_QGraphicsItem::update()
+{
+ QGraphicsScene scene;
+ MyGraphicsView view(&scene);
+
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ EventTester *item = new EventTester;
+ scene.addItem(item);
+ QTest::qWait(100); // Make sure all pending updates are processed.
+ item->repaints = 0;
+
+ item->update(); // Item marked as dirty
+ scene.update(); // Entire scene marked as dirty
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+
+ // Make sure the dirty state from the previous update is reset so that
+ // the item don't think it is already dirty and discards this update.
+ item->update();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 2);
+
+ // Make sure a partial update doesn't cause a full update to be discarded.
+ view.reset();
+ item->repaints = 0;
+ item->update(QRectF(0, 0, 5, 5));
+ item->update();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
+ .mapRect(item->boundingRect()).toRect();
+ const QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ // Make sure update requests outside the bounding rect are discarded.
+ view.reset();
+ item->repaints = 0;
+ item->update(-15, -15, 5, 5); // Item's brect: (-10, -10, 20, 20)
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 0);
+}
+
+void tst_QGraphicsItem::setTransformProperties_data()
+{
+ QTest::addColumn<QPointF>("origin");
+ QTest::addColumn<qreal>("rotationX");
+ QTest::addColumn<qreal>("rotationY");
+ QTest::addColumn<qreal>("rotationZ");
+ QTest::addColumn<qreal>("scaleX");
+ QTest::addColumn<qreal>("scaleY");
+ QTest::addColumn<qreal>("shearX");
+ QTest::addColumn<qreal>("shearY");
+
+ QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0);
+
+ QTest::newRow("rotationZ") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(42.2)
+ << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0);
+
+ QTest::newRow("rotationXY") << QPointF() << qreal(12.5) << qreal(53.6) << qreal(0.0)
+ << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0);
+
+ QTest::newRow("rotationXYZ") << QPointF() << qreal(-25) << qreal(12) << qreal(556)
+ << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0);
+
+ QTest::newRow("rotationXYZ dicentred") << QPointF(-53, 25.2)
+ << qreal(-2578.2) << qreal(4565.2) << qreal(56)
+ << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0);
+
+ QTest::newRow("Scale") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << qreal(6) << qreal(0.5) << qreal(0.0) << qreal(0.0);
+
+ QTest::newRow("Shear") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << qreal(1.0) << qreal(1.0) << qreal(2.2) << qreal(0.5);
+
+ QTest::newRow("Scale and Shear") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << qreal(5.2) << qreal(2.1) << qreal(5.2) << qreal(5.5);
+
+ QTest::newRow("Everything") << QPointF() << qreal(41) << qreal(-23) << qreal(0.56)
+ << qreal(8.2) << qreal(-0.2) << qreal(-12) << qreal(-0.8);
+
+ QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196) << qreal(-1260)
+ << qreal(4) << qreal(2) << qreal(2.56) << qreal(0.8);
+}
+
+/**
+ * the normal QCOMPARE doesn't work because it doesn't use qFuzzyCompare
+ */
+#define QCOMPARE_TRANSFORM(X1, X2) QVERIFY(((X1)*(X2).inverted()).isIdentity())
+
+void tst_QGraphicsItem::setTransformProperties()
+{
+ QFETCH(QPointF,origin);
+ QFETCH(qreal,rotationX);
+ QFETCH(qreal,rotationY);
+ QFETCH(qreal,rotationZ);
+ QFETCH(qreal,scaleX);
+ QFETCH(qreal,scaleY);
+ QFETCH(qreal,shearX);
+ QFETCH(qreal,shearY);
+
+ QTransform result;
+ result.translate(origin.x(), origin.y());
+ result.rotate(rotationX, Qt::XAxis);
+ result.rotate(rotationY, Qt::YAxis);
+ result.rotate(rotationZ, Qt::ZAxis);
+ result.shear(shearX, shearY);
+ result.scale(scaleX, scaleY);
+ result.translate(-origin.x(), -origin.y());
+
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ scene.addItem(item);
+
+ item->setRotation(rotationX, rotationY, rotationZ);
+ item->setScale(scaleX, scaleY);
+ item->setShear(shearX, shearY);
+ item->setTransformOrigin(origin);
+
+ QCOMPARE(item->xRotation(), rotationX);
+ QCOMPARE(item->yRotation(), rotationY);
+ QCOMPARE(item->zRotation(), rotationZ);
+ QCOMPARE(item->xScale(), scaleX);
+ QCOMPARE(item->yScale(), scaleY);
+ QCOMPARE(item->horizontalShear(), shearX);
+ QCOMPARE(item->verticalShear(), shearY);
+ QCOMPARE(item->transformOrigin(), origin);
+
+ QCOMPARE(QTransform(), item->transform());
+ QCOMPARE(result, item->sceneTransform());
+
+ //-----------------------------------------------------------------
+ //Change the rotation Z
+ item->setZRotation(45);
+ QTransform result2;
+ result2.translate(origin.x(), origin.y());
+ result2.rotate(rotationX, Qt::XAxis);
+ result2.rotate(rotationY, Qt::YAxis);
+ result2.rotate(45, Qt::ZAxis);
+ result2.shear(shearX, shearY);
+ result2.scale(scaleX, scaleY);
+ result2.translate(-origin.x(), -origin.y());
+
+ QCOMPARE(item->xRotation(), rotationX);
+ QCOMPARE(item->yRotation(), rotationY);
+ QCOMPARE(item->zRotation(), 45.0);
+ QCOMPARE(item->xScale(), scaleX);
+ QCOMPARE(item->yScale(), scaleY);
+ QCOMPARE(item->horizontalShear(), shearX);
+ QCOMPARE(item->verticalShear(), shearY);
+ QCOMPARE(item->transformOrigin(), origin);
+
+ QCOMPARE(QTransform(), item->transform());
+ QCOMPARE(result2, item->sceneTransform());
+
+ //-----------------------------------------------------------------
+ // calling setTransform() and setPos shoukld change the sceneTransform
+ item->setTransform(result);
+ item->setPos(100, -150.5);
+
+ QCOMPARE(item->xRotation(), rotationX);
+ QCOMPARE(item->yRotation(), rotationY);
+ QCOMPARE(item->zRotation(), 45.0);
+ QCOMPARE(item->xScale(), scaleX);
+ QCOMPARE(item->yScale(), scaleY);
+ QCOMPARE(item->horizontalShear(), shearX);
+ QCOMPARE(item->verticalShear(), shearY);
+ QCOMPARE(item->transformOrigin(), origin);
+ QCOMPARE(result, item->transform());
+
+ QTransform result3;
+
+ result3.translate(origin.x(), origin.y());
+ result3 = result * result3;
+ result3.rotate(rotationX, Qt::XAxis);
+ result3.rotate(rotationY, Qt::YAxis);
+ result3.rotate(45, Qt::ZAxis);
+ result3.shear(shearX, shearY);
+ result3.scale(scaleX, scaleY);
+ result3.translate(-origin.x(), -origin.y());
+
+ result3 *= QTransform::fromTranslate(100, -150.5); //the pos;
+
+ QCOMPARE(result3, item->sceneTransform());
+
+ //-----------------------------------------------------
+ // setting the propertiees should be the same as setting a transform
+ {//with center origin on the matrix
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item1);
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item2);
+
+ item1->setPos(12.3, -5);
+ item2->setPos(12.3, -5);
+ item1->setRotation(rotationX, rotationY, rotationZ);
+ item1->setScale(scaleX, scaleY);
+ item1->setShear(shearX, shearY);
+ item1->setTransformOrigin(origin);
+
+ item2->setTransform(result);
+
+ QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform());
+
+ QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform());
+ QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform());
+ }
+
+ {//with center origin on the item
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item1);
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item2);
+
+ item1->setPos(12.3, -5);
+ item2->setPos(12.3, -5);
+ item1->setTransformOrigin(origin);
+ item2->setTransformOrigin(origin);
+
+ item1->setRotation(rotationX, rotationY, rotationZ);
+ item1->setScale(scaleX, scaleY);
+ item1->setShear(shearX, shearY);
+
+ QTransform tr;
+ tr.rotate(rotationX, Qt::XAxis);
+ tr.rotate(rotationY, Qt::YAxis);
+ tr.rotate(rotationZ, Qt::ZAxis);
+ tr.shear(shearX, shearY);
+ tr.scale(scaleX, scaleY);
+
+ item2->setTransform(tr);
+
+ QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform());
+
+ QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform());
+ QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform());
+ }
+}
+
+class MyStyleOptionTester : public QGraphicsRectItem
+{
+public:
+ MyStyleOptionTester(const QRectF &rect)
+ : QGraphicsRectItem(rect), startTrack(false)
+ {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
+ {
+ if (startTrack) {
+ //Doesn't use the extended style option so the exposed rect is the boundingRect
+ if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) {
+ QCOMPARE(option->exposedRect, boundingRect());
+ } else {
+ QVERIFY(option->exposedRect != QRect());
+ QVERIFY(option->exposedRect != boundingRect());
+ }
+ }
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+ bool startTrack;
+};
+
+void tst_QGraphicsItem::itemUsesExtendedStyleOption()
+{
+ QGraphicsScene scene(0, 0, 300, 300);
+ QGraphicsPixmapItem item;
+ item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+ QCOMPARE(item.flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
+ item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false);
+ QCOMPARE(item.flags(), 0);
+
+ //We now test the content of the style option
+ MyStyleOptionTester *rect = new MyStyleOptionTester(QRect(0, 0, 100, 100));
+ scene.addItem(rect);
+ rect->setPos(200, 200);
+ QGraphicsView view(&scene);
+ QTest::qWait(500);
+ rect->startTrack = true;
+ rect->update(10, 10, 10, 10);
+ QTest::qWait(125);
+ rect->startTrack = false;
+ rect->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+ QVERIFY((rect->flags() & QGraphicsItem::ItemUsesExtendedStyleOption));
+ QTest::qWait(125);
+ rect->startTrack = true;
+ rect->update(10, 10, 10, 10);
+ QTest::qWait(125);
+}
+
+void tst_QGraphicsItem::itemSendsGeometryChanges()
+{
+ ItemChangeTester item;
+ item.setFlags(0);
+ item.clear();
+
+ QTransform x = QTransform().rotate(45);
+ QPointF pos(10, 10);
+ qreal o(0.5);
+ item.setTransform(x);
+ item.setPos(pos);
+ QCOMPARE(item.transform(), x);
+ QCOMPARE(item.pos(), pos);
+ QCOMPARE(item.changes.size(), 0);
+
+ item.setOpacity(o);
+ QCOMPARE(item.changes.size(), 2); // opacity
+
+ item.setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ QCOMPARE(item.changes.size(), 4); // flags
+ item.setTransform(QTransform());
+ item.setPos(QPointF());
+ QCOMPARE(item.changes.size(), 8); // transform + pos
+ QCOMPARE(item.transform(), QTransform());
+ QCOMPARE(item.pos(), QPointF());
+ QCOMPARE(item.opacity(), o);
+
+ QCOMPARE(item.changes, QList<QGraphicsItem::GraphicsItemChange>()
+ << QGraphicsItem::ItemOpacityChange
+ << QGraphicsItem::ItemOpacityHasChanged
+ << QGraphicsItem::ItemFlagsChange
+ << QGraphicsItem::ItemFlagsHaveChanged
+ << QGraphicsItem::ItemTransformChange
+ << QGraphicsItem::ItemTransformHasChanged
+ << QGraphicsItem::ItemPositionChange
+ << QGraphicsItem::ItemPositionHasChanged);
+}
+
+// Make sure we update moved items correctly.
+void tst_QGraphicsItem::moveItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-50, -50, 200, 200);
+
+ MyGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+ EventTester *grandChild = new EventTester(child);
+
+#define RESET_COUNTERS \
+ parent->repaints = 0; \
+ child->repaints = 0; \
+ grandChild->repaints = 0; \
+ view.reset();
+
+ scene.addItem(parent);
+ QTest::qWait(100);
+
+ RESET_COUNTERS
+
+ // Item's boundingRect: (-10, -10, 20, 20).
+ QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
+ .mapRect(parent->boundingRect()).toRect()
+ .adjusted(-2, -2, 2, 2); // Adjusted for antialiasing.
+
+ parent->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QRegion expectedParentRegion = parentDeviceBoundingRect; // old position
+ parentDeviceBoundingRect.translate(20, 20);
+ expectedParentRegion += parentDeviceBoundingRect; // new position
+ QCOMPARE(view.paintedRegion, expectedParentRegion);
+
+ RESET_COUNTERS
+
+ child->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRegion expectedChildRegion = expectedParentRegion.translated(20, 20);
+ QCOMPARE(view.paintedRegion, expectedChildRegion);
+
+ RESET_COUNTERS
+
+ grandChild->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRegion expectedGrandChildRegion = expectedParentRegion.translated(40, 40);
+ QCOMPARE(view.paintedRegion, expectedGrandChildRegion);
+
+ RESET_COUNTERS
+
+ parent->translate(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ expectedParentRegion.translate(20, 20);
+ expectedParentRegion += expectedChildRegion.translated(20, 20);
+ expectedParentRegion += expectedGrandChildRegion.translated(20, 20);
+ QCOMPARE(view.paintedRegion, expectedParentRegion);
+}
+
+void tst_QGraphicsItem::sorting_data()
+{
+ QTest::addColumn<int>("index");
+
+ QTest::newRow("NoIndex") << int(QGraphicsScene::NoIndex);
+ QTest::newRow("BspTreeIndex") << int(QGraphicsScene::BspTreeIndex);
+}
+
+void tst_QGraphicsItem::sorting()
+{
+ _paintedItems.clear();
+
+ QGraphicsScene scene;
+ QGraphicsItem *grid[100][100];
+ for (int x = 0; x < 100; ++x) {
+ for (int y = 0; y < 100; ++y) {
+ PainterItem *item = new PainterItem;
+ item->setPos(x * 25, y * 25);
+ item->setData(0, QString("%1x%2").arg(x).arg(y));
+ grid[x][y] = item;
+ scene.addItem(item);
+ }
+ }
+
+ PainterItem *item1 = new PainterItem;
+ PainterItem *item2 = new PainterItem;
+ item1->setData(0, "item1");
+ item2->setData(0, "item2");
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ QGraphicsView view(&scene);
+ view.setResizeAnchor(QGraphicsView::NoAnchor);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ view.resize(100, 100);
+ view.setFrameStyle(0);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ _paintedItems.clear();
+
+ view.viewport()->repaint();
+
+ QCOMPARE(_paintedItems, QList<QGraphicsItem *>()
+ << grid[0][0] << grid[0][1] << grid[0][2] << grid[0][3]
+ << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3]
+ << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3]
+ << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3]
+ << item1 << item2);
+}
+
QTEST_MAIN(tst_QGraphicsItem)
#include "tst_qgraphicsitem.moc"
diff --git a/tests/auto/qgraphicsobject/qgraphicsobject.pro b/tests/auto/qgraphicsobject/qgraphicsobject.pro
new file mode 100644
index 0000000..965b319
--- /dev/null
+++ b/tests/auto/qgraphicsobject/qgraphicsobject.pro
@@ -0,0 +1,2 @@
+load(qttest_p4)
+SOURCES += tst_qgraphicsobject.cpp
diff --git a/tests/auto/qgraphicsobject/tst_qgraphicsobject.cpp b/tests/auto/qgraphicsobject/tst_qgraphicsobject.cpp
new file mode 100644
index 0000000..eb12c48
--- /dev/null
+++ b/tests/auto/qgraphicsobject/tst_qgraphicsobject.cpp
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** 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 <QtTest/QtTest>
+#include <qgraphicsitem.h>
+#include <qgraphicsscene.h>
+#include <qgraphicssceneevent.h>
+#include <qgraphicsview.h>
+#include <qstyleoption.h>
+#include "../../shared/util.h"
+
+class tst_QGraphicsObject : public QObject {
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void pos();
+ void x();
+ void y();
+ void z();
+ void opacity();
+ void enabled();
+ void visible();
+};
+
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsObject::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsObject::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsObject::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsObject::cleanup()
+{
+}
+
+
+class MyGraphicsObject : public QGraphicsObject
+{
+public:
+ MyGraphicsObject() : QGraphicsObject() {}
+ virtual QRectF boundingRect() const { return QRectF(); }
+ virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
+};
+
+void tst_QGraphicsObject::pos()
+{
+ MyGraphicsObject object;
+ QSignalSpy xSpy(&object, SIGNAL(xChanged()));
+ QSignalSpy ySpy(&object, SIGNAL(yChanged()));
+ QVERIFY(object.pos() == QPointF(0, 0));
+ object.setPos(10, 10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 1);
+
+ QVERIFY(object.pos() == QPointF(10,10));
+
+ object.setPos(10, 10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 1);
+
+ object.setProperty("pos", QPointF(0, 0));
+ QCOMPARE(xSpy.count(), 2);
+ QCOMPARE(ySpy.count(), 2);
+ QVERIFY(object.property("pos") == QPointF(0,0));
+
+ object.setProperty("pos", QPointF(10, 0));
+ QCOMPARE(xSpy.count(), 3);
+ QCOMPARE(ySpy.count(), 2);
+ QVERIFY(object.property("pos") == QPointF(10,0));
+
+ object.setProperty("pos", QPointF(10, 10));
+ QCOMPARE(xSpy.count(), 3);
+ QCOMPARE(ySpy.count(), 3);
+ QVERIFY(object.property("pos") == QPointF(10, 10));
+}
+
+void tst_QGraphicsObject::x()
+{
+ MyGraphicsObject object;
+ QSignalSpy xSpy(&object, SIGNAL(xChanged()));
+ QSignalSpy ySpy(&object, SIGNAL(yChanged()));
+ QVERIFY(object.pos() == QPointF(0, 0));
+ object.setX(10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 0);
+
+ QVERIFY(object.pos() == QPointF(10, 0));
+ QVERIFY(object.x() == 10);
+
+ object.setX(10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 0);
+
+ object.setProperty("x", 0);
+ QCOMPARE(xSpy.count(), 2);
+ QCOMPARE(ySpy.count(), 0);
+ QVERIFY(object.property("x") == 0);
+}
+
+void tst_QGraphicsObject::y()
+{
+ MyGraphicsObject object;
+ QSignalSpy xSpy(&object, SIGNAL(xChanged()));
+ QSignalSpy ySpy(&object, SIGNAL(yChanged()));
+ QVERIFY(object.pos() == QPointF(0, 0));
+ object.setY(10);
+ QCOMPARE(xSpy.count(), 0);
+ QCOMPARE(ySpy.count(), 1);
+
+ QVERIFY(object.pos() == QPointF(0, 10));
+ QVERIFY(object.y() == 10);
+
+ object.setY(10);
+ QCOMPARE(xSpy.count(), 0);
+ QCOMPARE(ySpy.count(), 1);
+
+ object.setProperty("y", 0);
+ QCOMPARE(xSpy.count(), 0);
+ QCOMPARE(ySpy.count(), 2);
+ QVERIFY(object.property("y") == 0);
+}
+
+void tst_QGraphicsObject::z()
+{
+ MyGraphicsObject object;
+ QSignalSpy zSpy(&object, SIGNAL(zChanged()));
+ QVERIFY(object.zValue() == 0);
+ object.setZValue(10);
+ QCOMPARE(zSpy.count(), 1);
+
+ QVERIFY(object.zValue() == 10);
+
+ object.setZValue(10);
+ QCOMPARE(zSpy.count(), 1);
+
+ object.setProperty("z", 0);
+ QCOMPARE(zSpy.count(), 2);
+ QVERIFY(object.property("z") == 0);
+}
+
+void tst_QGraphicsObject::opacity()
+{
+ MyGraphicsObject object;
+ QSignalSpy spy(&object, SIGNAL(opacityChanged()));
+ QVERIFY(object.opacity() == 1.);
+ object.setOpacity(0);
+ QCOMPARE(spy.count(), 1);
+
+ QVERIFY(object.opacity() == 0.);
+
+ object.setOpacity(0);
+ QCOMPARE(spy.count(), 1);
+
+ object.setProperty("opacity", .5);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(object.property("opacity") == .5);
+}
+
+void tst_QGraphicsObject::enabled()
+{
+ MyGraphicsObject object;
+ QSignalSpy spy(&object, SIGNAL(enabledChanged()));
+ QVERIFY(object.isEnabled() == true);
+ object.setEnabled(false);
+ QCOMPARE(spy.count(), 1);
+
+ QVERIFY(object.isEnabled() == false);
+
+ object.setEnabled(false);
+ QCOMPARE(spy.count(), 1);
+
+ object.setProperty("enabled", true);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(object.property("enabled") == true);
+}
+
+void tst_QGraphicsObject::visible()
+{
+ MyGraphicsObject object;
+ QSignalSpy spy(&object, SIGNAL(visibleChanged()));
+ QVERIFY(object.isVisible() == true);
+ object.setVisible(false);
+ QCOMPARE(spy.count(), 1);
+
+ QVERIFY(object.isVisible() == false);
+
+ object.setVisible(false);
+ QCOMPARE(spy.count(), 1);
+
+ object.setProperty("visible", true);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(object.property("visible") == true);
+}
+
+
+QTEST_MAIN(tst_QGraphicsObject)
+#include "tst_qgraphicsobject.moc"
+
diff --git a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index b99f111..fa0e035 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.
@@ -1484,7 +1487,7 @@ void tst_QGraphicsProxyWidget::scrollUpdate()
QVector<QRect>() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10));
QCOMPARE(widget->npaints, 2);
QCOMPARE(widget->paintEventRegion.rects(),
- QVector<QRect>() << QRect(0, 0, 200, 13) << QRect(0, 13, 103, 10));
+ QVector<QRect>() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10));
}
void tst_QGraphicsProxyWidget::setWidget_simple()
@@ -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/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp
index d020c10..b71bbbb 100644
--- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp
+++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp
@@ -282,7 +282,9 @@ void tst_QGraphicsScene::sceneRect()
QCOMPARE(scene.sceneRect(), QRectF());
QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
+ qApp->processEvents();
item->setPos(-5, -5);
+ qApp->processEvents();
QCOMPARE(scene.itemAt(0, 0), item);
QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
@@ -1325,8 +1327,9 @@ void tst_QGraphicsScene::removeItem()
scene.removeItem(hoverItem);
hoverItem->setAcceptsHoverEvents(false);
scene.addItem(hoverItem);
- qApp->processEvents(); // update
- qApp->processEvents(); // draw
+ qApp->processEvents(); // <- delayed update is called
+ qApp->processEvents(); // <- scene schedules pending update
+ qApp->processEvents(); // <- pending update is sent to view
QVERIFY(!hoverItem->isHovered);
}
@@ -2722,6 +2725,7 @@ void tst_QGraphicsScene::update()
QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100);
scene.addItem(rect);
+ qApp->processEvents();
rect->setPos(-100, -100);
// This function forces indexing
diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
index ddc2074..c8dfba1 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();
@@ -186,7 +188,13 @@ private slots:
void embeddedViews();
void scrollAfterResize_data();
void scrollAfterResize();
+ void moveItemWhileScrolling_data();
+ void moveItemWhileScrolling();
void centerOnDirtyItem();
+ void mouseTracking();
+ void mouseTracking2();
+ void render();
+ void exposeRegion();
// task specific tests below me
void task172231_untransformableItems();
@@ -1612,23 +1620,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);
- QCOMPARE(view.mapToScene(rect), poly);
+ QPolygonF poly = view.mapToScene(viewRect);
+ if (!poly.isEmpty())
+ poly << poly[0];
+
+ QCOMPARE(poly, scenePoly);
}
void tst_QGraphicsView::mapToScenePoly()
@@ -2343,7 +2379,7 @@ public:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *viewport)
{
- lastLod = option->levelOfDetail;
+ lastLod = option->levelOfDetailFromTransform(painter->worldTransform());
QGraphicsRectItem::paint(painter, option, viewport);
}
@@ -2497,6 +2533,8 @@ void tst_QGraphicsView::acceptMousePressEvent()
scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable);
+ qApp->processEvents(); // ensure scene rect is updated
+
QApplication::sendEvent(view.viewport(), &event);
QVERIFY(view.accepted);
}
@@ -2516,7 +2554,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);
}
@@ -2706,6 +2745,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
@@ -3012,6 +3052,67 @@ void tst_QGraphicsView::scrollAfterResize()
QCOMPARE(view.viewportTransform(), x3);
}
+void tst_QGraphicsView::moveItemWhileScrolling_data()
+{
+ QTest::addColumn<bool>("adjustForAntialiasing");
+
+ QTest::newRow("no adjust") << false;
+ QTest::newRow("adjust") << true;
+}
+
+void tst_QGraphicsView::moveItemWhileScrolling()
+{
+ QFETCH(bool, adjustForAntialiasing);
+
+ class MoveItemScrollView : public QGraphicsView
+ {
+ public:
+ MoveItemScrollView()
+ {
+ setScene(new QGraphicsScene(0, 0, 1000, 1000));
+ rect = scene()->addRect(0, 0, 10, 10);
+ rect->setPos(50, 50);
+ }
+ QRegion lastPaintedRegion;
+ QGraphicsItem *rect;
+ protected:
+ void paintEvent(QPaintEvent *event)
+ {
+ lastPaintedRegion = event->region();
+ QGraphicsView::paintEvent(event);
+ }
+ };
+
+ MoveItemScrollView view;
+ view.setFrameStyle(0);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setResizeAnchor(QGraphicsView::NoAnchor);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ if (!adjustForAntialiasing)
+ view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
+ view.show();
+ view.resize(200, 200);
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ view.lastPaintedRegion = QRegion();
+ view.horizontalScrollBar()->setValue(view.horizontalScrollBar()->value() + 10);
+ view.rect->moveBy(0, 10);
+ QTest::qWait(100);
+
+ QRegion expectedRegion;
+ expectedRegion += QRect(0, 0, 200, 200);
+ expectedRegion -= QRect(0, 0, 190, 200);
+ int a = adjustForAntialiasing ? 2 : 1;
+ expectedRegion += QRect(40, 50, 10, 10).adjusted(-a, -a, a, a);
+ expectedRegion += QRect(40, 60, 10, 10).adjusted(-a, -a, a, a);
+
+ QCOMPARE(view.lastPaintedRegion, expectedRegion);
+}
+
void tst_QGraphicsView::centerOnDirtyItem()
{
QGraphicsView view;
@@ -3049,6 +3150,217 @@ 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());
+ }
+}
+
+void tst_QGraphicsView::mouseTracking2()
+{
+ // Make sure mouse move events propagates to the scene when
+ // mouse tracking is explicitly enabled on the view,
+ // even when all items ignore hover events / use default cursor.
+
+ QGraphicsScene scene;
+ scene.addRect(0, 0, 100, 100);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(200);
+
+ QVERIFY(!view.viewport()->hasMouseTracking());
+ view.viewport()->setMouseTracking(true); // Explicitly enable mouse tracking.
+ QVERIFY(view.viewport()->hasMouseTracking());
+
+ EventSpy spy(&scene, QEvent::GraphicsSceneMouseMove);
+ QCOMPARE(spy.count(), 0);
+ sendMouseMove(view.viewport(), view.viewport()->rect().center());
+ QCOMPARE(spy.count(), 1);
+}
+
+class RenderTester : public QGraphicsRectItem
+{
+public:
+ RenderTester(const QRectF &rect)
+ : QGraphicsRectItem(rect), paints(0)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ ++paints;
+ }
+
+ int paints;
+};
+
+void tst_QGraphicsView::render()
+{
+ // ### This test can be much more thorough - see QGraphicsScene::render.
+ QGraphicsScene scene;
+ RenderTester *r1 = new RenderTester(QRectF(0, 0, 50, 50));
+ RenderTester *r2 = new RenderTester(QRectF(50, 50, 50, 50));
+ RenderTester *r3 = new RenderTester(QRectF(0, 50, 50, 50));
+ RenderTester *r4 = new RenderTester(QRectF(50, 0, 50, 50));
+ scene.addItem(r1);
+ scene.addItem(r2);
+ scene.addItem(r3);
+ scene.addItem(r4);
+
+ QGraphicsView view(&scene);
+ view.setFrameStyle(0);
+ view.resize(200, 200);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(200);
+
+ QCOMPARE(r1->paints, 1);
+ QCOMPARE(r2->paints, 1);
+ QCOMPARE(r3->paints, 1);
+ QCOMPARE(r4->paints, 1);
+
+ QPixmap pix(200, 200);
+ pix.fill(Qt::transparent);
+ QPainter painter(&pix);
+ view.render(&painter);
+ painter.end();
+
+ QCOMPARE(r1->paints, 2);
+ QCOMPARE(r2->paints, 2);
+ QCOMPARE(r3->paints, 2);
+ QCOMPARE(r4->paints, 2);
+}
+
+void tst_QGraphicsView::exposeRegion()
+{
+ RenderTester *item = new RenderTester(QRectF(0, 0, 20, 20));
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ CustomView view;
+ view.setScene(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(125);
+
+ item->paints = 0;
+ view.lastUpdateRegions.clear();
+
+ // Update a small area in the viewport's topLeft() and bottomRight().
+ // (the boundingRect() of this area covers the entire viewport).
+ QWidget *viewport = view.viewport();
+ QRegion expectedExposeRegion = QRect(0, 0, 5, 5);
+ expectedExposeRegion += QRect(viewport->rect().bottomRight() - QPoint(5, 5), QSize(5, 5));
+ viewport->update(expectedExposeRegion);
+ qApp->processEvents();
+
+ // Make sure it triggers correct repaint on the view.
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ QCOMPARE(view.lastUpdateRegions.at(0), expectedExposeRegion);
+
+ // Make sure the item didn't get any repaints.
+ QCOMPARE(item->paints, 0);
+}
+
void tst_QGraphicsView::task253415_reconnectUpdateSceneOnSceneChanged()
{
QGraphicsView view;
diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
index 1917357..00f3155 100644
--- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -148,7 +148,14 @@ private slots:
void setSizes();
void closePopupOnOutsideClick();
void defaultSize();
+ void explicitMouseGrabber();
+ void implicitMouseGrabber();
+ void doubleClickAfterExplicitMouseGrab();
+ void popupMouseGrabber();
+ void windowFlags_data();
+ void windowFlags();
void shortcutsDeletion();
+ void painterStateProtectionOnWindowFrame();
// Task fixes
void task236127_bspTreeIndexFails();
@@ -1736,6 +1743,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);
@@ -1746,7 +1757,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);
@@ -1784,6 +1795,480 @@ 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);
+}
+
+class GrabOnPressItem : public QGraphicsRectItem
+{
+public:
+ GrabOnPressItem(const QRectF &rect)
+ : QGraphicsRectItem(rect),
+ npress(0), nrelease(0), ndoubleClick(0),
+ ngrab(0), nungrab(0)
+ {
+ }
+ int npress;
+ int nrelease;
+ int ndoubleClick;
+ int ngrab;
+ int nungrab;
+protected:
+ bool sceneEvent(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::GrabMouse:
+ ++ngrab;
+ break;
+ case QEvent::UngrabMouse:
+ ++nungrab;
+ break;
+ default:
+ break;
+ }
+ return QGraphicsRectItem::sceneEvent(event);
+ }
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *)
+ {
+ grabMouse();
+ ++npress;
+ }
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+ {
+ ungrabMouse();
+ ++nrelease;
+ }
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
+ {
+ ++ndoubleClick;
+ }
+};
+
+void tst_QGraphicsWidget::doubleClickAfterExplicitMouseGrab()
+{
+ QGraphicsScene scene;
+ GrabOnPressItem *item = new GrabOnPressItem(QRectF(0, 0, 100, 100));
+ scene.addItem(item);
+
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ QCOMPARE(item->npress, 1);
+ QCOMPARE(item->ngrab, 1);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(0);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(item->nrelease, 1);
+ QCOMPARE(item->nungrab, 1);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseDoubleClick);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ QCOMPARE(item->ndoubleClick, 1);
+ QCOMPARE(item->ngrab, 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(0);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(item->nrelease, 2);
+ QCOMPARE(item->nungrab, 2);
+}
+
+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));
+}
+
void tst_QGraphicsWidget::shortcutsDeletion()
{
QGraphicsWidget *widget = new QGraphicsWidget;
@@ -1798,6 +2283,41 @@ void tst_QGraphicsWidget::shortcutsDeletion()
delete widget;
}
+class MessUpPainterWidget : public QGraphicsWidget
+{
+public:
+ MessUpPainterWidget(QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0)
+ : QGraphicsWidget(parent, wFlags)
+ {}
+
+ void paintWindowFrame(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QCOMPARE(painter->opacity(), 1.0);
+ painter->setOpacity(0.0);
+ QGraphicsWidget::paintWindowFrame(painter, option, widget);
+ }
+ void paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QCOMPARE(painter->opacity(), 1.0);
+ painter->drawRect(0, 0, 100, 100);
+ QGraphicsWidget::paint(painter, option, widget);
+ }
+
+};
+
+void tst_QGraphicsWidget::painterStateProtectionOnWindowFrame()
+{
+ MessUpPainterWidget *widget = new MessUpPainterWidget(0, Qt::Window);
+ QGraphicsScene scene(0, 0, 300, 300);
+ QGraphicsView view(&scene);
+ scene.addItem(widget);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(500);
+}
+
class ProxyStyle : public QCommonStyle
{
public:
diff --git a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
index 98f9d20..c11cac5 100644
--- a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
+++ b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
@@ -42,6 +42,7 @@
#include <QtTest/QtTest>
#include "private/qhttpnetworkconnection_p.h"
+#include "private/qnoncontiguousbytedevice_p.h"
#include <QAuthenticator>
#include "../network-settings.h"
@@ -311,8 +312,8 @@ void tst_QHttpNetworkConnection::put()
QHttpNetworkRequest request(protocol + host + path, QHttpNetworkRequest::Put);
QByteArray array = data.toLatin1();
- QBuffer buffer(&array);
- request.setData(&buffer);
+ QNonContiguousByteDevice *bd = QNonContiguousByteDeviceFactory::create(&array);
+ request.setUploadByteDevice(bd);
finishedCalled = false;
finishedWithErrorCalled = false;
@@ -401,8 +402,8 @@ void tst_QHttpNetworkConnection::post()
QHttpNetworkRequest request(protocol + host + path, QHttpNetworkRequest::Post);
QByteArray array = data.toLatin1();
- QBuffer buffer(&array);
- request.setData(&buffer);
+ QNonContiguousByteDevice *bd = QNonContiguousByteDeviceFactory::create(&array);
+ request.setUploadByteDevice(bd);
QHttpNetworkReply *reply = connection.sendRequest(request);
diff --git a/tests/auto/qimage/images/image.tif b/tests/auto/qimage/images/image.tif
new file mode 100644
index 0000000..ee0637c
--- /dev/null
+++ b/tests/auto/qimage/images/image.tif
Binary files differ
diff --git a/tests/auto/qimage/tst_qimage.cpp b/tests/auto/qimage/tst_qimage.cpp
index b6be5e6..1aaba50 100644
--- a/tests/auto/qimage/tst_qimage.cpp
+++ b/tests/auto/qimage/tst_qimage.cpp
@@ -135,6 +135,8 @@ private slots:
void nullSize();
void premultipliedAlphaConsistency();
+
+ void compareIndexed();
};
tst_QImage::tst_QImage()
@@ -281,6 +283,9 @@ void tst_QImage::formatHandlersInput_data()
QTest::newRow("PPM") << "PPM" << prefix + "image.ppm";
QTest::newRow("XBM") << "XBM" << prefix + "image.xbm";
QTest::newRow("XPM") << "XPM" << prefix + "image.xpm";
+#if defined QTEST_HAVE_TIFF
+ QTest::newRow("TIFF") << "TIFF" << prefix + "image.tif";
+#endif
}
void tst_QImage::formatHandlersInput()
@@ -1767,5 +1772,31 @@ void tst_QImage::premultipliedAlphaConsistency()
}
}
+void tst_QImage::compareIndexed()
+{
+ QImage img(256, 1, QImage::Format_Indexed8);
+
+ QVector<QRgb> colorTable(256);
+ for (int i = 0; i < 256; ++i)
+ colorTable[i] = qRgb(i, i, i);
+ img.setColorTable(colorTable);
+
+ for (int i = 0; i < 256; ++i) {
+ img.setPixel(i, 0, i);
+ }
+
+ QImage imgInverted(256, 1, QImage::Format_Indexed8);
+ QVector<QRgb> invertedColorTable(256);
+ for (int i = 0; i < 256; ++i)
+ invertedColorTable[255-i] = qRgb(i, i, i);
+ imgInverted.setColorTable(invertedColorTable);
+
+ for (int i = 0; i < 256; ++i) {
+ imgInverted.setPixel(i, 0, (255-i));
+ }
+
+ QCOMPARE(img, imgInverted);
+}
+
QTEST_MAIN(tst_QImage)
#include "tst_qimage.moc"
diff --git a/tests/auto/qimagereader/baseline/35floppy.ico b/tests/auto/qimagereader/baseline/35floppy.ico
new file mode 100644
index 0000000..59fd37e
--- /dev/null
+++ b/tests/auto/qimagereader/baseline/35floppy.ico
Binary files differ
diff --git a/tests/auto/qimagereader/baseline/kde_favicon.ico b/tests/auto/qimagereader/baseline/kde_favicon.ico
new file mode 100644
index 0000000..15bcdbb
--- /dev/null
+++ b/tests/auto/qimagereader/baseline/kde_favicon.ico
Binary files differ
diff --git a/tests/auto/qimagereader/baseline/semitransparent.ico b/tests/auto/qimagereader/baseline/semitransparent.ico
new file mode 100644
index 0000000..dd23de9
--- /dev/null
+++ b/tests/auto/qimagereader/baseline/semitransparent.ico
Binary files differ
diff --git a/tests/auto/qimagereader/images/image_100dpi.tif b/tests/auto/qimagereader/images/image_100dpi.tif
new file mode 100644
index 0000000..fcf3cd8
--- /dev/null
+++ b/tests/auto/qimagereader/images/image_100dpi.tif
Binary files differ
diff --git a/tests/auto/qimagereader/qimagereader.pro b/tests/auto/qimagereader/qimagereader.pro
index 4925498..44a0ddc 100644
--- a/tests/auto/qimagereader/qimagereader.pro
+++ b/tests/auto/qimagereader/qimagereader.pro
@@ -3,6 +3,7 @@ SOURCES += tst_qimagereader.cpp
MOC_DIR=tmp
QT += network
RESOURCES += qimagereader.qrc
+DEFINES += SRCDIR=\\\"$$PWD\\\"
!contains(QT_CONFIG, no-gif):DEFINES += QTEST_HAVE_GIF
!contains(QT_CONFIG, no-jpeg):DEFINES += QTEST_HAVE_JPEG
@@ -22,6 +23,7 @@ wince*: {
imagePlugins.path = imageformats
DEPLOYMENT += images imagePlugins
+ DEFINES += SRCDIR=\\\".\\\"
}
symbian*: {
diff --git a/tests/auto/qimagereader/qimagereader.qrc b/tests/auto/qimagereader/qimagereader.qrc
index 13ce582..c6b963b 100644
--- a/tests/auto/qimagereader/qimagereader.qrc
+++ b/tests/auto/qimagereader/qimagereader.qrc
@@ -30,6 +30,7 @@
<file>images/image.pgm</file>
<file>images/image.png</file>
<file>images/image.ppm</file>
+ <file>images/image_100dpi.tif</file>
<file>images/kollada.png</file>
<file>images/marble.xpm</file>
<file>images/namedcolors.xpm</file>
diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp
index 3da79f3..fafa35e 100644
--- a/tests/auto/qimagereader/tst_qimagereader.cpp
+++ b/tests/auto/qimagereader/tst_qimagereader.cpp
@@ -153,8 +153,16 @@ private slots:
void autoDetectImageFormat();
void fileNameProbing();
+
+ void pixelCompareWithBaseline_data();
+ void pixelCompareWithBaseline();
+
+ void task255627_setNullScaledSize_data();
+ void task255627_setNullScaledSize();
};
+static const QLatin1String prefix(SRCDIR "/images/");
+
// Testing get/set functions
void tst_QImageReader::getSetCheck()
{
@@ -229,7 +237,7 @@ void tst_QImageReader::readImage()
QFETCH(QByteArray, format);
for (int i = 0; i < 2; ++i) {
- QImageReader io("images/" + fileName, i ? QByteArray() : format);
+ QImageReader io(prefix + fileName, i ? QByteArray() : format);
if (success) {
if (!io.supportsAnimation())
QVERIFY(io.imageCount() > 0);
@@ -245,16 +253,16 @@ void tst_QImageReader::readImage()
QVERIFY2(!image.isNull(), io.errorString().toLatin1().constData());
// No format
- QImageReader io2("images/" + fileName);
+ QImageReader io2(prefix + fileName);
QVERIFY2(!io2.read().isNull(), io.errorString().toLatin1().constData());
// No extension, no format
- QImageReader io3("images/" + fileName.left(fileName.lastIndexOf(QLatin1Char('.'))));
+ QImageReader io3(prefix + fileName.left(fileName.lastIndexOf(QLatin1Char('.'))));
QVERIFY2(!io3.read().isNull(), io.errorString().toLatin1().constData());
// Read into \a image2
QImage image2;
- QImageReader image2Reader("images/" + fileName, i ? QByteArray() : format);
+ QImageReader image2Reader(prefix + fileName, i ? QByteArray() : format);
QCOMPARE(image2Reader.format(), format);
QVERIFY(image2Reader.read(&image2));
if (image2Reader.canRead()) {
@@ -278,8 +286,8 @@ void tst_QImageReader::readImage()
void tst_QImageReader::jpegRgbCmyk()
{
- QImage image1(QLatin1String("images/YCbCr_cmyk.jpg"));
- QImage image2(QLatin1String("images/YCbCr_cmyk.png"));
+ QImage image1(prefix + QLatin1String("YCbCr_cmyk.jpg"));
+ QImage image2(prefix + QLatin1String("YCbCr_cmyk.png"));
QCOMPARE(image1, image2);
}
@@ -290,24 +298,24 @@ void tst_QImageReader::setScaledSize_data()
QTest::addColumn<QSize>("newSize");
QTest::addColumn<QByteArray>("format");
- QTest::newRow("BMP: colorful") << "images/colorful" << QSize(200, 200) << QByteArray("bmp");
- QTest::newRow("BMP: font") << "images/font" << QSize(200, 200) << QByteArray("bmp");
- QTest::newRow("XPM: marble") << "images/marble" << QSize(200, 200) << QByteArray("xpm");
- QTest::newRow("PNG: kollada") << "images/kollada" << QSize(200, 200) << QByteArray("png");
- QTest::newRow("PPM: teapot") << "images/teapot" << QSize(200, 200) << QByteArray("ppm");
- QTest::newRow("PPM: runners") << "images/runners.ppm" << QSize(400, 400) << QByteArray("ppm");
- QTest::newRow("PPM: test") << "images/test.ppm" << QSize(10, 10) << QByteArray("ppm");
- QTest::newRow("XBM: gnus") << "images/gnus" << QSize(200, 200) << QByteArray("xbm");
+ QTest::newRow("BMP: colorful") << "colorful" << QSize(200, 200) << QByteArray("bmp");
+ QTest::newRow("BMP: font") << "font" << QSize(200, 200) << QByteArray("bmp");
+ QTest::newRow("XPM: marble") << "marble" << QSize(200, 200) << QByteArray("xpm");
+ QTest::newRow("PNG: kollada") << "kollada" << QSize(200, 200) << QByteArray("png");
+ QTest::newRow("PPM: teapot") << "teapot" << QSize(200, 200) << QByteArray("ppm");
+ QTest::newRow("PPM: runners") << "runners.ppm" << QSize(400, 400) << QByteArray("ppm");
+ QTest::newRow("PPM: test") << "test.ppm" << QSize(10, 10) << QByteArray("ppm");
+ QTest::newRow("XBM: gnus") << "gnus" << QSize(200, 200) << QByteArray("xbm");
#ifdef QTEST_HAVE_JPEG
- QTest::newRow("JPEG: beavis") << "images/beavis" << QSize(200, 200) << QByteArray("jpeg");
+ QTest::newRow("JPEG: beavis") << "beavis" << QSize(200, 200) << QByteArray("jpeg");
#endif // QTEST_HAVE_JPEG
#ifdef QTEST_HAVE_GIF
- QTest::newRow("GIF: earth") << "images/earth" << QSize(200, 200) << QByteArray("gif");
- QTest::newRow("GIF: trolltech") << "images/trolltech" << QSize(200, 200) << QByteArray("gif");
+ QTest::newRow("GIF: earth") << "earth" << QSize(200, 200) << QByteArray("gif");
+ QTest::newRow("GIF: trolltech") << "trolltech" << QSize(200, 200) << QByteArray("gif");
#endif // QTEST_HAVE_GIF
#ifdef QTEST_HAVE_MNG
- QTest::newRow("MNG: ball") << "images/ball" << QSize(200, 200) << QByteArray("mng");
- QTest::newRow("MNG: fire") << "images/fire" << QSize(200, 200) << QByteArray("mng");
+ QTest::newRow("MNG: ball") << "ball" << QSize(200, 200) << QByteArray("mng");
+ QTest::newRow("MNG: fire") << "fire" << QSize(200, 200) << QByteArray("mng");
#endif // QTEST_HAVE_MNG
}
@@ -320,7 +328,7 @@ void tst_QImageReader::setScaledSize()
if (!format.isEmpty() && !QImageReader::supportedImageFormats().contains(format))
QSKIP("Qt does not support reading the \"" + format + "\" format", SkipSingle);
- QImageReader reader(fileName);
+ QImageReader reader(prefix + fileName);
reader.setScaledSize(newSize);
QImage image = reader.read();
QVERIFY(!image.isNull());
@@ -328,30 +336,53 @@ void tst_QImageReader::setScaledSize()
QCOMPARE(image.size(), newSize);
}
+void tst_QImageReader::task255627_setNullScaledSize_data()
+{
+ setScaledSize_data();
+}
+
+void tst_QImageReader::task255627_setNullScaledSize()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+
+ if (!format.isEmpty() && !QImageReader::supportedImageFormats().contains(format))
+ QSKIP("Qt does not support reading the \"" + format + "\" format", SkipSingle);
+
+ QImageReader reader(prefix + fileName);
+
+ // set a null size
+ reader.setScaledSize(QSize(0, 0));
+ reader.setQuality(0);
+ QImage image = reader.read();
+ QVERIFY(image.isNull());
+ QCOMPARE(image.size(), QSize(0, 0));
+}
+
void tst_QImageReader::setClipRect_data()
{
QTest::addColumn<QString>("fileName");
QTest::addColumn<QRect>("newRect");
QTest::addColumn<QByteArray>("format");
- QTest::newRow("BMP: colorful") << "images/colorful" << QRect(0, 0, 50, 50) << QByteArray("bmp");
- QTest::newRow("BMP: font") << "images/font" << QRect(0, 0, 50, 50) << QByteArray("bmp");
- QTest::newRow("BMP: 4bpp uncompressed") << "images/tst7.bmp" << QRect(0, 0, 31, 31) << QByteArray("bmp");
- QTest::newRow("XPM: marble") << "images/marble" << QRect(0, 0, 50, 50) << QByteArray("xpm");
- QTest::newRow("PNG: kollada") << "images/kollada" << QRect(0, 0, 50, 50) << QByteArray("png");
- QTest::newRow("PPM: teapot") << "images/teapot" << QRect(0, 0, 50, 50) << QByteArray("ppm");
- QTest::newRow("PPM: runners") << "images/runners.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
- QTest::newRow("PPM: test") << "images/test.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
- QTest::newRow("XBM: gnus") << "images/gnus" << QRect(0, 0, 50, 50) << QByteArray("xbm");
+ QTest::newRow("BMP: colorful") << "colorful" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("BMP: font") << "font" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("BMP: 4bpp uncompressed") << "tst7.bmp" << QRect(0, 0, 31, 31) << QByteArray("bmp");
+ QTest::newRow("XPM: marble") << "marble" << QRect(0, 0, 50, 50) << QByteArray("xpm");
+ QTest::newRow("PNG: kollada") << "kollada" << QRect(0, 0, 50, 50) << QByteArray("png");
+ QTest::newRow("PPM: teapot") << "teapot" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("PPM: runners") << "runners.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("PPM: test") << "test.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("XBM: gnus") << "gnus" << QRect(0, 0, 50, 50) << QByteArray("xbm");
#ifdef QTEST_HAVE_JPEG
- QTest::newRow("JPEG: beavis") << "images/beavis" << QRect(0, 0, 50, 50) << QByteArray("jpeg");
+ QTest::newRow("JPEG: beavis") << "beavis" << QRect(0, 0, 50, 50) << QByteArray("jpeg");
#endif // QTEST_HAVE_JPEG
#ifdef QTEST_HAVE_GIF
- QTest::newRow("GIF: earth") << "images/earth" << QRect(0, 0, 50, 50) << QByteArray("gif");
- QTest::newRow("GIF: trolltech") << "images/trolltech" << QRect(0, 0, 50, 50) << QByteArray("gif");
+ QTest::newRow("GIF: earth") << "earth" << QRect(0, 0, 50, 50) << QByteArray("gif");
+ QTest::newRow("GIF: trolltech") << "trolltech" << QRect(0, 0, 50, 50) << QByteArray("gif");
#endif // QTEST_HAVE_GIF
#ifdef QTEST_HAVE_MNG
- QTest::newRow("MNG: ball") << "images/ball" << QRect(0, 0, 50, 50) << QByteArray("mng");
- QTest::newRow("MNG: fire") << "images/fire" << QRect(0, 0, 50, 50) << QByteArray("mng");
+ QTest::newRow("MNG: ball") << "ball" << QRect(0, 0, 50, 50) << QByteArray("mng");
+ QTest::newRow("MNG: fire") << "fire" << QRect(0, 0, 50, 50) << QByteArray("mng");
#endif // QTEST_HAVE_MNG
}
@@ -364,13 +395,13 @@ void tst_QImageReader::setClipRect()
if (!format.isEmpty() && !QImageReader::supportedImageFormats().contains(format))
QSKIP("Qt does not support reading the \"" + format + "\" format", SkipSingle);
- QImageReader reader(fileName);
+ QImageReader reader(prefix + fileName);
reader.setClipRect(newRect);
QImage image = reader.read();
QVERIFY(!image.isNull());
QCOMPARE(image.rect(), newRect);
- QImageReader originalReader(fileName);
+ QImageReader originalReader(prefix + fileName);
QImage originalImage = originalReader.read();
QCOMPARE(originalImage.copy(newRect), image);
}
@@ -381,24 +412,24 @@ void tst_QImageReader::setScaledClipRect_data()
QTest::addColumn<QRect>("newRect");
QTest::addColumn<QByteArray>("format");
- QTest::newRow("BMP: colorful") << "images/colorful" << QRect(0, 0, 50, 50) << QByteArray("bmp");
- QTest::newRow("BMP: font") << "images/font" << QRect(0, 0, 50, 50) << QByteArray("bmp");
- QTest::newRow("XPM: marble") << "images/marble" << QRect(0, 0, 50, 50) << QByteArray("xpm");
- QTest::newRow("PNG: kollada") << "images/kollada" << QRect(0, 0, 50, 50) << QByteArray("png");
- QTest::newRow("PPM: teapot") << "images/teapot" << QRect(0, 0, 50, 50) << QByteArray("ppm");
- QTest::newRow("PPM: runners") << "images/runners.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
- QTest::newRow("PPM: test") << "images/test.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
- QTest::newRow("XBM: gnus") << "images/gnus" << QRect(0, 0, 50, 50) << QByteArray("xbm");
+ QTest::newRow("BMP: colorful") << "colorful" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("BMP: font") << "font" << QRect(0, 0, 50, 50) << QByteArray("bmp");
+ QTest::newRow("XPM: marble") << "marble" << QRect(0, 0, 50, 50) << QByteArray("xpm");
+ QTest::newRow("PNG: kollada") << "kollada" << QRect(0, 0, 50, 50) << QByteArray("png");
+ QTest::newRow("PPM: teapot") << "teapot" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("PPM: runners") << "runners.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("PPM: test") << "test.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
+ QTest::newRow("XBM: gnus") << "gnus" << QRect(0, 0, 50, 50) << QByteArray("xbm");
#ifdef QTEST_HAVE_JPEG
- QTest::newRow("JPEG: beavis") << "images/beavis" << QRect(0, 0, 50, 50) << QByteArray("jpeg");
+ QTest::newRow("JPEG: beavis") << "beavis" << QRect(0, 0, 50, 50) << QByteArray("jpeg");
#endif // QTEST_HAVE_JPEG
#ifdef QTEST_HAVE_GIF
- QTest::newRow("GIF: earth") << "images/earth" << QRect(0, 0, 50, 50) << QByteArray("gif");
- QTest::newRow("GIF: trolltech") << "images/trolltech" << QRect(0, 0, 50, 50) << QByteArray("gif");
+ QTest::newRow("GIF: earth") << "earth" << QRect(0, 0, 50, 50) << QByteArray("gif");
+ QTest::newRow("GIF: trolltech") << "trolltech" << QRect(0, 0, 50, 50) << QByteArray("gif");
#endif // QTEST_HAVE_GIF
#ifdef QTEST_HAVE_MNG
- QTest::newRow("MNG: ball") << "images/ball" << QRect(0, 0, 50, 50) << QByteArray("mng");
- QTest::newRow("MNG: fire") << "images/fire" << QRect(0, 0, 50, 50) << QByteArray("mng");
+ QTest::newRow("MNG: ball") << "ball" << QRect(0, 0, 50, 50) << QByteArray("mng");
+ QTest::newRow("MNG: fire") << "fire" << QRect(0, 0, 50, 50) << QByteArray("mng");
#endif // QTEST_HAVE_MNG
}
@@ -411,14 +442,14 @@ void tst_QImageReader::setScaledClipRect()
if (!format.isEmpty() && !QImageReader::supportedImageFormats().contains(format))
QSKIP("Qt does not support reading the \"" + format + "\" format", SkipSingle);
- QImageReader reader(fileName);
+ QImageReader reader(prefix + fileName);
reader.setScaledSize(QSize(300, 300));
reader.setScaledClipRect(newRect);
QImage image = reader.read();
QVERIFY(!image.isNull());
QCOMPARE(image.rect(), newRect);
- QImageReader originalReader(fileName);
+ QImageReader originalReader(prefix + fileName);
originalReader.setScaledSize(QSize(300, 300));
QImage originalImage = originalReader.read();
QCOMPARE(originalImage.copy(newRect), image);
@@ -430,29 +461,29 @@ void tst_QImageReader::imageFormat_data()
QTest::addColumn<QByteArray>("format");
QTest::addColumn<QImage::Format>("imageFormat");
- QTest::newRow("pbm") << QString("images/image.pbm") << QByteArray("pbm") << QImage::Format_Mono;
- QTest::newRow("pgm") << QString("images/image.pgm") << QByteArray("pgm") << QImage::Format_Indexed8;
- QTest::newRow("ppm-1") << QString("images/image.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
- QTest::newRow("ppm-2") << QString("images/teapot.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
- QTest::newRow("ppm-3") << QString("images/runners.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
- QTest::newRow("ppm-4") << QString("images/test.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
+ QTest::newRow("pbm") << QString("image.pbm") << QByteArray("pbm") << QImage::Format_Mono;
+ QTest::newRow("pgm") << QString("image.pgm") << QByteArray("pgm") << QImage::Format_Indexed8;
+ QTest::newRow("ppm-1") << QString("image.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
+ QTest::newRow("ppm-2") << QString("teapot.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
+ QTest::newRow("ppm-3") << QString("runners.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
+ QTest::newRow("ppm-4") << QString("test.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
#ifdef QTEST_HAVE_JPEG
- QTest::newRow("jpeg-1") << QString("images/beavis.jpg") << QByteArray("jpeg") << QImage::Format_Indexed8;
- QTest::newRow("jpeg-2") << QString("images/YCbCr_cmyk.jpg") << QByteArray("jpeg") << QImage::Format_RGB32;
- QTest::newRow("jpeg-3") << QString("images/YCbCr_rgb.jpg") << QByteArray("jpeg") << QImage::Format_RGB32;
+ QTest::newRow("jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg") << QImage::Format_Indexed8;
+ QTest::newRow("jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg") << QImage::Format_RGB32;
+ QTest::newRow("jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg") << QImage::Format_RGB32;
#endif
#if defined QTEST_HAVE_GIF
- QTest::newRow("gif-1") << QString("images/earth.gif") << QByteArray("gif") << QImage::Format_Invalid;
- QTest::newRow("gif-2") << QString("images/trolltech.gif") << QByteArray("gif") << QImage::Format_Invalid;
+ QTest::newRow("gif-1") << QString("earth.gif") << QByteArray("gif") << QImage::Format_Invalid;
+ QTest::newRow("gif-2") << QString("trolltech.gif") << QByteArray("gif") << QImage::Format_Invalid;
#endif
- QTest::newRow("xbm") << QString("images/gnus.xbm") << QByteArray("xbm") << QImage::Format_MonoLSB;
- QTest::newRow("xpm") << QString("images/marble.xpm") << QByteArray("xpm") << QImage::Format_Indexed8;
- QTest::newRow("bmp-1") << QString("images/colorful.bmp") << QByteArray("bmp") << QImage::Format_Indexed8;
- QTest::newRow("bmp-2") << QString("images/font.bmp") << QByteArray("bmp") << QImage::Format_Indexed8;
- QTest::newRow("png") << QString("images/kollada.png") << QByteArray("png") << QImage::Format_ARGB32;
- QTest::newRow("png-2") << QString("images/YCbCr_cmyk.png") << QByteArray("png") << QImage::Format_RGB32;
- QTest::newRow("mng-1") << QString("images/ball.mng") << QByteArray("mng") << QImage::Format_Invalid;
- QTest::newRow("mng-2") << QString("images/fire.mng") << QByteArray("mng") << QImage::Format_Invalid;
+ QTest::newRow("xbm") << QString("gnus.xbm") << QByteArray("xbm") << QImage::Format_MonoLSB;
+ QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm") << QImage::Format_Indexed8;
+ QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp") << QImage::Format_Indexed8;
+ QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp") << QImage::Format_Indexed8;
+ QTest::newRow("png") << QString("kollada.png") << QByteArray("png") << QImage::Format_ARGB32;
+ QTest::newRow("png-2") << QString("YCbCr_cmyk.png") << QByteArray("png") << QImage::Format_RGB32;
+ QTest::newRow("mng-1") << QString("ball.mng") << QByteArray("mng") << QImage::Format_Invalid;
+ QTest::newRow("mng-2") << QString("fire.mng") << QByteArray("mng") << QImage::Format_Invalid;
}
void tst_QImageReader::imageFormat()
@@ -460,7 +491,8 @@ void tst_QImageReader::imageFormat()
QFETCH(QString, fileName);
QFETCH(QByteArray, format);
QFETCH(QImage::Format, imageFormat);
- if (QImageReader::imageFormat(fileName).isEmpty()) {
+
+ if (QImageReader::imageFormat(prefix + fileName).isEmpty()) {
if (QByteArray("jpeg") == format)
#ifndef QTEST_HAVE_JPEG
return;
@@ -475,31 +507,31 @@ void tst_QImageReader::imageFormat()
#endif // !QTEST_HAVE_MNG
QSKIP(("Qt does not support the " + format + " format.").constData(), SkipSingle);
} else {
- QCOMPARE(QImageReader::imageFormat(fileName), format);
+ QCOMPARE(QImageReader::imageFormat(prefix + fileName), format);
}
- QImageReader reader(fileName);
+ QImageReader reader(prefix + fileName);
QCOMPARE(reader.imageFormat(), imageFormat);
}
void tst_QImageReader::blackXPM()
{
- QImage image(QLatin1String("images/black.xpm"));
- QImage image2(QLatin1String("images/black.png"));
+ QImage image(prefix + QLatin1String("black.xpm"));
+ QImage image2(prefix + QLatin1String("black.png"));
QCOMPARE(image.pixel(25, 25), qRgb(190, 190, 190));
QCOMPARE(image.pixel(25, 25), image2.pixel(25, 25));
}
void tst_QImageReader::transparentXPM()
{
- QImage image(QLatin1String("images/nontransparent.xpm"));
- QImage image2(QLatin1String("images/transparent.xpm"));
+ QImage image(prefix + QLatin1String("nontransparent.xpm"));
+ QImage image2(prefix + QLatin1String("transparent.xpm"));
QCOMPARE(image.format(), QImage::Format_RGB32);
QCOMPARE(image2.format(), QImage::Format_ARGB32);
}
void tst_QImageReader::multiWordNamedColorXPM()
{
- QImage image(QLatin1String("images/namedcolors.xpm"));
+ QImage image(prefix + QLatin1String("namedcolors.xpm"));
QCOMPARE(image.pixel(0, 0), qRgb(102, 139, 139)); // pale turquoise 4
QCOMPARE(image.pixel(0, 1), qRgb(250, 250, 210)); // light golden rod yellow
QCOMPARE(image.pixel(0, 2), qRgb(255, 250, 205)); // lemon chiffon
@@ -590,7 +622,7 @@ void tst_QImageReader::supportsAnimation()
{
QFETCH(QString, fileName);
QFETCH(bool, success);
- QImageReader io("images/" + fileName);
+ QImageReader io(prefix + fileName);
QCOMPARE(io.supportsAnimation(), success);
}
@@ -603,7 +635,7 @@ void tst_QImageReader::sizeBeforeRead()
{
QFETCH(QString, fileName);
QFETCH(QByteArray, format);
- QImageReader reader(fileName);
+ QImageReader reader(prefix + fileName);
QVERIFY(reader.canRead());
if (format == "mng") {
QCOMPARE(reader.size(), QSize());
@@ -641,7 +673,7 @@ void tst_QImageReader::imageFormatBeforeRead()
void tst_QImageReader::gifHandlerBugs()
{
{
- QImageReader io("images/trolltech.gif");
+ QImageReader io(prefix + "trolltech.gif");
QVERIFY(io.loopCount() != 1);
int count=0;
for (; io.canRead(); io.read(), ++count) ;
@@ -650,8 +682,8 @@ void tst_QImageReader::gifHandlerBugs()
// Task 95166
{
- QImageReader io1("images/bat1.gif");
- QImageReader io2("images/bat2.gif");
+ QImageReader io1(prefix + "bat1.gif");
+ QImageReader io2(prefix + "bat2.gif");
QVERIFY(io1.canRead());
QVERIFY(io2.canRead());
QImage im1 = io1.read();
@@ -663,8 +695,8 @@ void tst_QImageReader::gifHandlerBugs()
// Task 9994
{
- QImageReader io1("images/noclearcode.gif");
- QImageReader io2("images/noclearcode.bmp");
+ QImageReader io1(prefix + "noclearcode.gif");
+ QImageReader io2(prefix + "noclearcode.bmp");
QVERIFY(io1.canRead()); QVERIFY(io2.canRead());
QImage im1 = io1.read(); QImage im2 = io2.read();
QVERIFY(!im1.isNull()); QVERIFY(!im2.isNull());
@@ -728,29 +760,29 @@ void tst_QImageReader::readFromDevice_data()
QTest::addColumn<QString>("fileName");
QTest::addColumn<QByteArray>("format");
- QTest::newRow("pbm") << QString("images/image.pbm") << QByteArray("pbm");
- QTest::newRow("pgm") << QString("images/image.pgm") << QByteArray("pgm");
- QTest::newRow("ppm-1") << QString("images/image.ppm") << QByteArray("ppm");
- QTest::newRow("ppm-2") << QString("images/teapot.ppm") << QByteArray("ppm");
- QTest::newRow("ppm-3") << QString("images/teapot.ppm") << QByteArray("ppm");
- QTest::newRow("ppm-4") << QString("images/runners.ppm") << QByteArray("ppm");
+ QTest::newRow("pbm") << QString("image.pbm") << QByteArray("pbm");
+ QTest::newRow("pgm") << QString("image.pgm") << QByteArray("pgm");
+ QTest::newRow("ppm-1") << QString("image.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-2") << QString("teapot.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-3") << QString("teapot.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-4") << QString("runners.ppm") << QByteArray("ppm");
#ifdef QTEST_HAVE_JPEG
- QTest::newRow("jpeg-1") << QString("images/beavis.jpg") << QByteArray("jpeg");
- QTest::newRow("jpeg-2") << QString("images/YCbCr_cmyk.jpg") << QByteArray("jpeg");
- QTest::newRow("jpeg-3") << QString("images/YCbCr_rgb.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg");
#endif // QTEST_HAVE_JPEG
#ifdef QTEST_HAVE_GIF
- QTest::newRow("gif-1") << QString("images/earth.gif") << QByteArray("gif");
- QTest::newRow("gif-2") << QString("images/trolltech.gif") << QByteArray("gif");
+ QTest::newRow("gif-1") << QString("earth.gif") << QByteArray("gif");
+ QTest::newRow("gif-2") << QString("trolltech.gif") << QByteArray("gif");
#endif // QTEST_HAVE_GIF
- QTest::newRow("xbm") << QString("images/gnus.xbm") << QByteArray("xbm");
- QTest::newRow("xpm") << QString("images/marble.xpm") << QByteArray("xpm");
- QTest::newRow("bmp-1") << QString("images/colorful.bmp") << QByteArray("bmp");
- QTest::newRow("bmp-2") << QString("images/font.bmp") << QByteArray("bmp");
- QTest::newRow("png") << QString("images/kollada.png") << QByteArray("png");
+ QTest::newRow("xbm") << QString("gnus.xbm") << QByteArray("xbm");
+ QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm");
+ QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp");
+ QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp");
+ QTest::newRow("png") << QString("kollada.png") << QByteArray("png");
#ifdef QTEST_HAVE_MNG
- QTest::newRow("mng-1") << QString("images/ball.mng") << QByteArray("mng");
- QTest::newRow("mng-2") << QString("images/fire.mng") << QByteArray("mng");
+ QTest::newRow("mng-1") << QString("ball.mng") << QByteArray("mng");
+ QTest::newRow("mng-2") << QString("fire.mng") << QByteArray("mng");
#endif // QTEST_HAVE_MNG
}
@@ -761,9 +793,9 @@ void tst_QImageReader::readFromDevice()
#ifdef Q_OS_SYMBIAN
QSKIP("Symbian local sockets are not working", SkipAll);
#endif
- QImage expectedImage(fileName, format);
+ QImage expectedImage(prefix + fileName, format);
- QFile file(fileName);
+ QFile file(prefix + fileName);
QVERIFY(file.open(QFile::ReadOnly));
QByteArray imageData = file.readAll();
QVERIFY(!imageData.isEmpty());
@@ -812,26 +844,26 @@ void tst_QImageReader::readFromFileAfterJunk_data()
QTest::addColumn<QString>("fileName");
QTest::addColumn<QByteArray>("format");
- QTest::newRow("pbm") << QString("images/image.pbm") << QByteArray("pbm");
- QTest::newRow("pgm") << QString("images/image.pgm") << QByteArray("pgm");
- QTest::newRow("ppm-1") << QString("images/image.ppm") << QByteArray("ppm");
- QTest::newRow("ppm-2") << QString("images/teapot.ppm") << QByteArray("ppm");
- QTest::newRow("ppm-3") << QString("images/teapot.ppm") << QByteArray("ppm");
- QTest::newRow("ppm-4") << QString("images/runners.ppm") << QByteArray("ppm");
+ QTest::newRow("pbm") << QString("image.pbm") << QByteArray("pbm");
+ QTest::newRow("pgm") << QString("image.pgm") << QByteArray("pgm");
+ QTest::newRow("ppm-1") << QString("image.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-2") << QString("teapot.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-3") << QString("teapot.ppm") << QByteArray("ppm");
+ QTest::newRow("ppm-4") << QString("runners.ppm") << QByteArray("ppm");
#ifdef QTEST_HAVE_JPEG
- QTest::newRow("jpeg-1") << QString("images/beavis.jpg") << QByteArray("jpeg");
- QTest::newRow("jpeg-2") << QString("images/YCbCr_cmyk.jpg") << QByteArray("jpeg");
- QTest::newRow("jpeg-3") << QString("images/YCbCr_rgb.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg");
+ QTest::newRow("jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg");
#endif
#if defined QTEST_HAVE_GIF
// QTest::newRow("gif-1") << QString("images/earth.gif") << QByteArray("gif");
// QTest::newRow("gif-2") << QString("images/trolltech.gif") << QByteArray("gif");
#endif
- QTest::newRow("xbm") << QString("images/gnus.xbm") << QByteArray("xbm");
- QTest::newRow("xpm") << QString("images/marble.xpm") << QByteArray("xpm");
- QTest::newRow("bmp-1") << QString("images/colorful.bmp") << QByteArray("bmp");
- QTest::newRow("bmp-2") << QString("images/font.bmp") << QByteArray("bmp");
- QTest::newRow("png") << QString("images/kollada.png") << QByteArray("png");
+ QTest::newRow("xbm") << QString("gnus.xbm") << QByteArray("xbm");
+ QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm");
+ QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp");
+ QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp");
+ QTest::newRow("png") << QString("kollada.png") << QByteArray("png");
// QTest::newRow("mng-1") << QString("images/ball.mng") << QByteArray("mng");
// QTest::newRow("mng-2") << QString("images/fire.mng") << QByteArray("mng");
}
@@ -850,7 +882,7 @@ void tst_QImageReader::readFromFileAfterJunk()
QFile junkFile("junk");
QVERIFY(junkFile.open(QFile::WriteOnly));
- QFile imageFile(fileName);
+ QFile imageFile(prefix + fileName);
QVERIFY(imageFile.open(QFile::ReadOnly));
QByteArray imageData = imageFile.readAll();
QVERIFY(!imageData.isNull());
@@ -868,7 +900,7 @@ void tst_QImageReader::readFromFileAfterJunk()
for (int i = 0; i < iterations; ++i) {
QImageWriter writer(&junkFile, format);
junkFile.write("deadbeef", 9);
- QVERIFY(writer.write(QImage(fileName)));
+ QVERIFY(writer.write(QImage(prefix + fileName)));
}
}
junkFile.close();
@@ -902,8 +934,8 @@ void tst_QImageReader::description_data()
willem["Software"] = "Created on a NeXTstation color using \"pnmtopng\".";
willem["Disclaimer"] = "Freeware.";
- QTest::newRow("PNG") << QString("images/pngwithtext.png") << willem;
- QTest::newRow("PNG Compressed") << QString("images/pngwithcompressedtext.png") << willem;
+ QTest::newRow("PNG") << QString("pngwithtext.png") << willem;
+ QTest::newRow("PNG Compressed") << QString("pngwithcompressedtext.png") << willem;
}
void tst_QImageReader::description()
@@ -912,9 +944,9 @@ void tst_QImageReader::description()
QFETCH(QStringMap, description);
// Sanity check
- QVERIFY(!QImage(fileName).isNull());
+ QVERIFY(!QImage(prefix + fileName).isNull());
- QImageReader reader(fileName);
+ QImageReader reader(prefix + fileName);
foreach (QString key, description.keys())
QCOMPARE(reader.text(key), description.value(key));
@@ -939,143 +971,143 @@ void tst_QImageReader::readFromResources_data()
QTest::addColumn<QSize>("size");
QTest::addColumn<QString>("message");
- QTest::newRow("images/corrupt.bmp") << QString("images/corrupt.bmp")
+ QTest::newRow("corrupt.bmp") << QString("corrupt.bmp")
<< QByteArray("bmp") << QSize(0, 0)
<< QString("");
- QTest::newRow("images/negativeheight.bmp") << QString("images/negativeheight.bmp")
+ QTest::newRow("negativeheight.bmp") << QString("negativeheight.bmp")
<< QByteArray("bmp") << QSize(127, 64)
<< QString("");
- QTest::newRow("images/font.bmp") << QString("images/font.bmp")
+ QTest::newRow("font.bmp") << QString("font.bmp")
<< QByteArray("bmp") << QSize(240, 8)
<< QString("");
- QTest::newRow("images/noclearcode.bmp") << QString("images/noclearcode.bmp")
+ QTest::newRow("noclearcode.bmp") << QString("noclearcode.bmp")
<< QByteArray("bmp") << QSize(29, 18)
<< QString("");
- QTest::newRow("images/colorful.bmp") << QString("images/colorful.bmp")
+ QTest::newRow("colorful.bmp") << QString("colorful.bmp")
<< QByteArray("bmp") << QSize(320, 200)
<< QString("");
- QTest::newRow("images/16bpp.bmp") << QString("images/16bpp.bmp")
+ QTest::newRow("16bpp.bmp") << QString("16bpp.bmp")
<< QByteArray("bmp") << QSize(320, 240)
<< QString("");
- QTest::newRow("images/crash-signed-char.bmp") << QString("images/crash-signed-char.bmp")
+ QTest::newRow("crash-signed-char.bmp") << QString("crash-signed-char.bmp")
<< QByteArray("bmp") << QSize(360, 280)
<< QString("");
- QTest::newRow("images/4bpp-rle.bmp") << QString("images/4bpp-rle.bmp")
+ QTest::newRow("4bpp-rle.bmp") << QString("4bpp-rle.bmp")
<< QByteArray("bmp") << QSize(640, 480)
<< QString("");
#ifdef QTEST_HAVE_GIF
- QTest::newRow("images/corrupt.gif") << QString("images/corrupt.gif")
+ QTest::newRow("corrupt.gif") << QString("corrupt.gif")
<< QByteArray("gif") << QSize(0, 0)
<< QString("");
- QTest::newRow("images/trolltech.gif") << QString("images/trolltech.gif")
+ QTest::newRow("trolltech.gif") << QString("trolltech.gif")
<< QByteArray("gif") << QSize(128, 64)
<< QString("");
- QTest::newRow("images/noclearcode.gif") << QString("images/noclearcode.gif")
+ QTest::newRow("noclearcode.gif") << QString("noclearcode.gif")
<< QByteArray("gif") << QSize(29, 18)
<< QString("");
- QTest::newRow("images/earth.gif") << QString("images/earth.gif")
+ QTest::newRow("earth.gif") << QString("earth.gif")
<< QByteArray("gif") << QSize(320, 200)
<< QString("");
- QTest::newRow("images/bat1.gif") << QString("images/bat1.gif")
+ QTest::newRow("bat1.gif") << QString("bat1.gif")
<< QByteArray("gif") << QSize(32, 32)
<< QString("");
- QTest::newRow("images/bat2.gif") << QString("images/bat2.gif")
+ QTest::newRow("bat2.gif") << QString("bat2.gif")
<< QByteArray("gif") << QSize(32, 32)
<< QString("");
#endif
#ifdef QTEST_HAVE_JPEG
- QTest::newRow("images/corrupt.jpg") << QString("images/corrupt.jpg")
+ QTest::newRow("corrupt.jpg") << QString("corrupt.jpg")
<< QByteArray("jpg") << QSize(0, 0)
<< QString("JPEG datastream contains no image");
- QTest::newRow("images/beavis.jpg") << QString("images/beavis.jpg")
+ QTest::newRow("beavis.jpg") << QString("beavis.jpg")
<< QByteArray("jpg") << QSize(350, 350)
<< QString("");
- QTest::newRow("images/YCbCr_cmyk.jpg") << QString("images/YCbCr_cmyk.jpg")
+ QTest::newRow("YCbCr_cmyk.jpg") << QString("YCbCr_cmyk.jpg")
<< QByteArray("jpg") << QSize(75, 50)
<< QString("");
- QTest::newRow("images/YCbCr_rgb.jpg") << QString("images/YCbCr_rgb.jpg")
+ QTest::newRow("YCbCr_rgb.jpg") << QString("YCbCr_rgb.jpg")
<< QByteArray("jpg") << QSize(75, 50)
<< QString("");
#endif
#ifdef QTEST_HAVE_MNG
- QTest::newRow("images/corrupt.mng") << QString("images/corrupt.mng")
+ QTest::newRow("corrupt.mng") << QString("corrupt.mng")
<< QByteArray("mng") << QSize(0, 0)
<< QString("MNG error 901: Application signalled I/O error; chunk IHDR; subcode 0:0");
- QTest::newRow("images/fire.mng") << QString("images/fire.mng")
+ QTest::newRow("fire.mng") << QString("fire.mng")
<< QByteArray("mng") << QSize(30, 60)
<< QString("");
- QTest::newRow("images/ball.mng") << QString("images/ball.mng")
+ QTest::newRow("ball.mng") << QString("ball.mng")
<< QByteArray("mng") << QSize(32, 32)
<< QString("");
#endif
- QTest::newRow("images/image.pbm") << QString("images/image.pbm")
+ QTest::newRow("image.pbm") << QString("image.pbm")
<< QByteArray("pbm") << QSize(16, 6)
<< QString("");
- QTest::newRow("images/image.pgm") << QString("images/image.pgm")
+ QTest::newRow("image.pgm") << QString("image.pgm")
<< QByteArray("pgm") << QSize(24, 7)
<< QString("");
- QTest::newRow("images/corrupt.png") << QString("images/corrupt.png")
+ QTest::newRow("corrupt.png") << QString("corrupt.png")
<< QByteArray("png") << QSize(0, 0)
<< QString("");
- QTest::newRow("images/away.png") << QString("images/away.png")
+ QTest::newRow("away.png") << QString("away.png")
<< QByteArray("png") << QSize(16, 16)
<< QString("");
- QTest::newRow("images/image.png") << QString("images/image.png")
+ QTest::newRow("image.png") << QString("image.png")
<< QByteArray("png") << QSize(22, 22)
<< QString("");
- QTest::newRow("images/pngwithcompressedtext.png") << QString("images/pngwithcompressedtext.png")
+ QTest::newRow("pngwithcompressedtext.png") << QString("pngwithcompressedtext.png")
<< QByteArray("png") << QSize(32, 32)
<< QString("");
- QTest::newRow("images/pngwithtext.png") << QString("images/pngwithtext.png")
+ QTest::newRow("pngwithtext.png") << QString("pngwithtext.png")
<< QByteArray("png") << QSize(32, 32)
<< QString("");
- QTest::newRow("images/kollada.png") << QString("images/kollada.png")
+ QTest::newRow("kollada.png") << QString("kollada.png")
<< QByteArray("png") << QSize(436, 160)
<< QString("");
- QTest::newRow("images/black.png") << QString("images/black.png")
+ QTest::newRow("black.png") << QString("black.png")
<< QByteArray("png") << QSize(48, 48)
<< QString("");
- QTest::newRow("images/YCbCr_cmyk.png") << QString("images/YCbCr_cmyk.png")
+ QTest::newRow("YCbCr_cmyk.png") << QString("YCbCr_cmyk.png")
<< QByteArray("png") << QSize(75, 50)
<< QString("");
- QTest::newRow("images/teapot.ppm") << QString("images/teapot.ppm")
+ QTest::newRow("teapot.ppm") << QString("teapot.ppm")
<< QByteArray("ppm") << QSize(256, 256)
<< QString("");
- QTest::newRow("images/image.ppm") << QString("images/image.ppm")
+ QTest::newRow("image.ppm") << QString("image.ppm")
<< QByteArray("ppm") << QSize(4, 4)
<< QString("");
- QTest::newRow("images/runners.ppm") << QString("images/runners.ppm")
+ QTest::newRow("runners.ppm") << QString("runners.ppm")
<< QByteArray("ppm") << QSize(400, 400)
<< QString("");
- QTest::newRow("images/test.ppm") << QString("images/test.ppm")
+ QTest::newRow("test.ppm") << QString("test.ppm")
<< QByteArray("ppm") << QSize(10, 10)
<< QString("");
-// QTest::newRow("images/corrupt.xbm") << QString("images/corrupt.xbm") << QByteArray("xbm") << QSize(0, 0);
- QTest::newRow("images/gnus.xbm") << QString("images/gnus.xbm")
+// QTest::newRow("corrupt.xbm") << QString("corrupt.xbm") << QByteArray("xbm") << QSize(0, 0);
+ QTest::newRow("gnus.xbm") << QString("gnus.xbm")
<< QByteArray("xbm") << QSize(271, 273)
<< QString("");
- QTest::newRow("images/corrupt-colors.xpm") << QString("images/corrupt-colors.xpm")
+ QTest::newRow("corrupt-colors.xpm") << QString("corrupt-colors.xpm")
<< QByteArray("xpm") << QSize(0, 0)
<< QString("QImage: XPM color specification is missing: bla9an.n#x");
- QTest::newRow("images/corrupt-pixels.xpm") << QString("images/corrupt-pixels.xpm")
+ QTest::newRow("corrupt-pixels.xpm") << QString("corrupt-pixels.xpm")
<< QByteArray("xpm") << QSize(0, 0)
<< QString("QImage: XPM pixels missing on image line 3");
- QTest::newRow("images/marble.xpm") << QString("images/marble.xpm")
+ QTest::newRow("marble.xpm") << QString("marble.xpm")
<< QByteArray("xpm") << QSize(240, 240)
<< QString("");
- QTest::newRow("images/test.xpm") << QString("images/test.xpm")
+ QTest::newRow("test.xpm") << QString("test.xpm")
<< QByteArray("xpm") << QSize(256, 256)
<< QString("");
- QTest::newRow("images/black.xpm") << QString("images/black.xpm")
+ QTest::newRow("black.xpm") << QString("black.xpm")
<< QByteArray("xpm") << QSize(48, 48)
<< QString("");
- QTest::newRow("images/namedcolors.xpm") << QString("images/namedcolors.xpm")
+ QTest::newRow("namedcolors.xpm") << QString("namedcolors.xpm")
<< QByteArray("xpm") << QSize(8, 8)
<< QString("");
- QTest::newRow("images/nontransparent.xpm") << QString("images/nontransparent.xpm")
+ QTest::newRow("nontransparent.xpm") << QString("nontransparent.xpm")
<< QByteArray("xpm") << QSize(8, 8)
<< QString("");
- QTest::newRow("images/transparent.xpm") << QString("images/transparent.xpm")
+ QTest::newRow("transparent.xpm") << QString("transparent.xpm")
<< QByteArray("xpm") << QSize(8, 8)
<< QString("");
}
@@ -1086,9 +1118,8 @@ void tst_QImageReader::readFromResources()
QFETCH(QByteArray, format);
QFETCH(QSize, size);
QFETCH(QString, message);
-
for (int i = 0; i < 2; ++i) {
- QString file = i ? (":/" + fileName) : fileName;
+ QString file = i ? (":/images/" + fileName) : (prefix + fileName);
{
// suppress warnings if we expect them
if (!message.isEmpty()) {
@@ -1152,7 +1183,7 @@ void tst_QImageReader::readFromResources()
QTest::ignoreMessage(QtWarningMsg, message.toLatin1());
QTest::ignoreMessage(QtWarningMsg, message.toLatin1());
}
- QCOMPARE(QImageReader(fileName).read(), QImageReader(":/" + fileName).read());
+ QCOMPARE(QImageReader(prefix + fileName).read(), QImageReader(":/images/" + fileName).read());
}
void tst_QImageReader::readCorruptImage_data()
@@ -1161,25 +1192,25 @@ void tst_QImageReader::readCorruptImage_data()
QTest::addColumn<bool>("shouldFail");
QTest::addColumn<QString>("message");
#if defined QTEST_HAVE_JPEG
- QTest::newRow("corrupt jpeg") << QString("images/corrupt.jpg") << true
+ QTest::newRow("corrupt jpeg") << QString("corrupt.jpg") << true
<< QString("JPEG datastream contains no image");
#endif
#if defined QTEST_HAVE_GIF
- QTest::newRow("corrupt gif") << QString("images/corrupt.gif") << true << QString("");
+ QTest::newRow("corrupt gif") << QString("corrupt.gif") << true << QString("");
#endif
#ifdef QTEST_HAVE_MNG
- QTest::newRow("corrupt mng") << QString("images/corrupt.mng") << true
+ QTest::newRow("corrupt mng") << QString("corrupt.mng") << true
<< QString("MNG error 901: Application signalled I/O error; chunk IHDR; subcode 0:0");
#endif
- QTest::newRow("corrupt png") << QString("images/corrupt.png") << true << QString("");
- QTest::newRow("corrupt bmp") << QString("images/corrupt.bmp") << true << QString("");
- QTest::newRow("corrupt xpm (colors)") << QString("images/corrupt-colors.xpm") << true
+ QTest::newRow("corrupt png") << QString("corrupt.png") << true << QString("");
+ QTest::newRow("corrupt bmp") << QString("corrupt.bmp") << true << QString("");
+ QTest::newRow("corrupt xpm (colors)") << QString("corrupt-colors.xpm") << true
<< QString("QImage: XPM color specification is missing: bla9an.n#x");
- QTest::newRow("corrupt xpm (pixels)") << QString("images/corrupt-pixels.xpm") << true
+ QTest::newRow("corrupt xpm (pixels)") << QString("corrupt-pixels.xpm") << true
<< QString("QImage: XPM pixels missing on image line 3");
- QTest::newRow("corrupt xbm") << QString("images/corrupt.xbm") << false << QString("");
+ QTest::newRow("corrupt xbm") << QString("corrupt.xbm") << false << QString("");
#if defined QTEST_HAVE_TIFF
- QTest::newRow("corrupt tiff") << QString("images/corrupt-data.tif") << true << QString("");
+ QTest::newRow("corrupt tiff") << QString("corrupt-data.tif") << true << QString("");
#endif
}
@@ -1188,16 +1219,17 @@ void tst_QImageReader::readCorruptImage()
QFETCH(QString, fileName);
QFETCH(bool, shouldFail);
QFETCH(QString, message);
+
if (!message.isEmpty())
QTest::ignoreMessage(QtWarningMsg, message.toLatin1());
- QImageReader reader(fileName);
+ QImageReader reader(prefix + fileName);
QVERIFY(reader.canRead());
QCOMPARE(reader.read().isNull(), shouldFail);
}
void tst_QImageReader::readCorruptBmp()
{
- QCOMPARE(QImage("images/tst7.bmp").convertToFormat(QImage::Format_ARGB32_Premultiplied), QImage("images/tst7.png").convertToFormat(QImage::Format_ARGB32_Premultiplied));
+ QCOMPARE(QImage("tst7.bmp").convertToFormat(QImage::Format_ARGB32_Premultiplied), QImage("images/tst7.png").convertToFormat(QImage::Format_ARGB32_Premultiplied));
}
void tst_QImageReader::supportsOption_data()
@@ -1205,7 +1237,7 @@ void tst_QImageReader::supportsOption_data()
QTest::addColumn<QString>("fileName");
QTest::addColumn<QIntList>("options");
- QTest::newRow("png") << QString("images/black.png")
+ QTest::newRow("png") << QString("black.png")
<< (QIntList() << QImageIOHandler::Gamma
<< QImageIOHandler::Description
<< QImageIOHandler::Quality
@@ -1233,7 +1265,7 @@ void tst_QImageReader::supportsOption()
<< QImageIOHandler::Animation
<< QImageIOHandler::BackgroundColor;
- QImageReader reader(fileName);
+ QImageReader reader(prefix + fileName);
for (int i = 0; i < options.size(); ++i) {
QVERIFY(reader.supportsOption(QImageIOHandler::ImageOption(options.at(i))));
allOptions.remove(QImageIOHandler::ImageOption(options.at(i)));
@@ -1249,14 +1281,14 @@ void tst_QImageReader::tiffCompression_data()
QTest::addColumn<QString>("uncompressedFile");
QTest::addColumn<QString>("compressedFile");
- QTest::newRow("TIFF: adobedeflate") << "images/rgba_nocompression_littleendian.tif"
- << "images/rgba_adobedeflate_littleendian.tif";
- QTest::newRow("TIFF: lzw") << "images/rgba_nocompression_littleendian.tif"
- << "images/rgba_lzw_littleendian.tif";
- QTest::newRow("TIFF: packbits") << "images/rgba_nocompression_littleendian.tif"
- << "images/rgba_packbits_littleendian.tif";
- QTest::newRow("TIFF: zipdeflate") << "images/rgba_nocompression_littleendian.tif"
- << "images/rgba_zipdeflate_littleendian.tif";
+ QTest::newRow("TIFF: adobedeflate") << "rgba_nocompression_littleendian.tif"
+ << "rgba_adobedeflate_littleendian.tif";
+ QTest::newRow("TIFF: lzw") << "rgba_nocompression_littleendian.tif"
+ << "rgba_lzw_littleendian.tif";
+ QTest::newRow("TIFF: packbits") << "rgba_nocompression_littleendian.tif"
+ << "rgba_packbits_littleendian.tif";
+ QTest::newRow("TIFF: zipdeflate") << "rgba_nocompression_littleendian.tif"
+ << "rgba_zipdeflate_littleendian.tif";
}
void tst_QImageReader::tiffCompression()
@@ -1264,16 +1296,16 @@ void tst_QImageReader::tiffCompression()
QFETCH(QString, uncompressedFile);
QFETCH(QString, compressedFile);
- QImage uncompressedImage(uncompressedFile);
- QImage compressedImage(compressedFile);
+ QImage uncompressedImage(prefix + uncompressedFile);
+ QImage compressedImage(prefix + compressedFile);
QCOMPARE(uncompressedImage, compressedImage);
}
void tst_QImageReader::tiffEndianness()
{
- QImage littleEndian("images/rgba_nocompression_littleendian.tif");
- QImage bigEndian("images/rgba_nocompression_bigendian.tif");
+ QImage littleEndian(prefix + "rgba_nocompression_littleendian.tif");
+ QImage bigEndian(prefix + "rgba_nocompression_bigendian.tif");
QCOMPARE(littleEndian, bigEndian);
}
@@ -1285,8 +1317,10 @@ void tst_QImageReader::dotsPerMeter_data()
QTest::addColumn<QString>("fileName");
QTest::addColumn<int>("expectedDotsPerMeterX");
QTest::addColumn<int>("expectedDotsPerMeterY");
-
- QTest::newRow("TIFF: 72 dpi") << "images/rgba_nocompression_littleendian.tif" << qRound(72 * (100 / 2.54)) << qRound(72 * (100 / 2.54));
+#if defined QTEST_HAVE_TIFF
+ QTest::newRow("TIFF: 72 dpi") << ("rgba_nocompression_littleendian.tif") << qRound(72 * (100 / 2.54)) << qRound(72 * (100 / 2.54));
+ QTest::newRow("TIFF: 100 dpi") << ("image_100dpi.tif") << qRound(100 * (100 / 2.54)) << qRound(100 * (100 / 2.54));
+#endif
}
void tst_QImageReader::dotsPerMeter()
@@ -1295,7 +1329,7 @@ void tst_QImageReader::dotsPerMeter()
QFETCH(int, expectedDotsPerMeterX);
QFETCH(int, expectedDotsPerMeterY);
- QImage image(fileName);
+ QImage image(prefix + fileName);
QCOMPARE(image.dotsPerMeterX(), expectedDotsPerMeterX);
QCOMPARE(image.dotsPerMeterY(), expectedDotsPerMeterY);
@@ -1306,8 +1340,10 @@ void tst_QImageReader::physicalDpi_data()
QTest::addColumn<QString>("fileName");
QTest::addColumn<int>("expectedPhysicalDpiX");
QTest::addColumn<int>("expectedPhysicalDpiY");
-
- QTest::newRow("TIFF: 72 dpi") << "images/rgba_nocompression_littleendian.tif" << 72 << 72;
+#if defined QTEST_HAVE_TIFF
+ QTest::newRow("TIFF: 72 dpi") << "rgba_nocompression_littleendian.tif" << 72 << 72;
+ QTest::newRow("TIFF: 100 dpi") << "image_100dpi.tif" << 100 << 100;
+#endif
}
void tst_QImageReader::physicalDpi()
@@ -1316,7 +1352,7 @@ void tst_QImageReader::physicalDpi()
QFETCH(int, expectedPhysicalDpiX);
QFETCH(int, expectedPhysicalDpiY);
- QImage image(fileName);
+ QImage image(prefix + fileName);
QCOMPARE(image.physicalDpiX(), expectedPhysicalDpiX);
QCOMPARE(image.physicalDpiY(), expectedPhysicalDpiY);
@@ -1327,7 +1363,7 @@ void tst_QImageReader::autoDetectImageFormat()
// Assume PNG is supported :-)
{
// Disables file name extension probing
- QImageReader reader("images/kollada");
+ QImageReader reader(prefix + "kollada");
reader.setAutoDetectImageFormat(false);
QVERIFY(!reader.canRead());
QVERIFY(reader.read().isNull());
@@ -1337,7 +1373,7 @@ void tst_QImageReader::autoDetectImageFormat()
}
{
// Disables detection based on suffix
- QImageReader reader("images/kollada.png");
+ QImageReader reader(prefix + "kollada.png");
reader.setAutoDetectImageFormat(false);
QVERIFY(!reader.canRead());
QVERIFY(reader.read().isNull());
@@ -1347,7 +1383,7 @@ void tst_QImageReader::autoDetectImageFormat()
}
{
// Disables detection based on content
- QImageReader reader("images/kollada-noext");
+ QImageReader reader(prefix + "kollada-noext");
reader.setAutoDetectImageFormat(false);
QVERIFY(!reader.canRead());
QVERIFY(reader.read().isNull());
@@ -1370,5 +1406,32 @@ void tst_QImageReader::fileNameProbing()
QCOMPARE(r.fileName(), name);
}
+void tst_QImageReader::pixelCompareWithBaseline_data()
+{
+ QTest::addColumn<QString>("fileName");
+
+ QTest::newRow("floppy (16px,32px - 16 colors)") << "35floppy.ico";
+ QTest::newRow("semitransparent") << "semitransparent.ico";
+ QTest::newRow("slightlybroken") << "kde_favicon.ico";
+}
+
+void tst_QImageReader::pixelCompareWithBaseline()
+{
+ QFETCH(QString, fileName);
+
+ QImage icoImg;
+ // might fail if the plugin does not exist, which is ok.
+ if (icoImg.load(QString::fromAscii("images/%1").arg(fileName))) {
+ QString baselineFileName = QString::fromAscii("baseline/%1").arg(fileName);
+#if 0
+ icoImg.save(baselineFileName);
+#else
+ QImage baseImg;
+ QVERIFY(baseImg.load(baselineFileName));
+ QCOMPARE(baseImg, icoImg);
+#endif
+ }
+}
+
QTEST_MAIN(tst_QImageReader)
#include "tst_qimagereader.moc"
diff --git a/tests/auto/qimagewriter/tst_qimagewriter.cpp b/tests/auto/qimagewriter/tst_qimagewriter.cpp
index 4688881..8a6c377 100644
--- a/tests/auto/qimagewriter/tst_qimagewriter.cpp
+++ b/tests/auto/qimagewriter/tst_qimagewriter.cpp
@@ -62,6 +62,7 @@ Q_DECLARE_METATYPE(QStringMap)
Q_DECLARE_METATYPE(QIntList)
Q_DECLARE_METATYPE(QImageWriter::ImageWriterError)
Q_DECLARE_METATYPE(QIODevice *)
+Q_DECLARE_METATYPE(QImage::Format)
//TESTED_FILES=
@@ -85,6 +86,9 @@ private slots:
void writeImage2();
void supportedFormats();
+ void readWriteNonDestructive_data();
+ void readWriteNonDestructive();
+
#if defined QTEST_HAVE_TIFF
void largeTiff();
#endif
@@ -100,6 +104,9 @@ private slots:
void saveWithNoFormat_data();
void saveWithNoFormat();
+ void resolution_data();
+ void resolution();
+
void saveToTemporaryFile();
};
#ifdef Q_OS_SYMBIAN
@@ -167,7 +174,7 @@ tst_QImageWriter::tst_QImageWriter()
tst_QImageWriter::~tst_QImageWriter()
{
- QDir dir("images");
+ QDir dir(prefix);
QStringList filesToDelete = dir.entryList(QStringList() << "gen-*" , QDir::NoDotAndDotDot | QDir::Files);
foreach( QString file, filesToDelete) {
QFile::remove(dir.absoluteFilePath(file));
@@ -380,6 +387,28 @@ void tst_QImageWriter::supportedFormats()
QCOMPARE(formatSet.size(), formats.size());
}
+void tst_QImageWriter::readWriteNonDestructive_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+ QTest::addColumn<QImage::Format>("expectedFormat");
+ QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono;
+ QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8;
+ QTest::newRow("tiff rgb32") << QImage::Format_ARGB32 << QImage::Format_ARGB32;
+}
+
+void tst_QImageWriter::readWriteNonDestructive()
+{
+ QFETCH(QImage::Format, format);
+ QFETCH(QImage::Format, expectedFormat);
+ QImage image = QImage(prefix + "colorful.bmp").convertToFormat(format);
+ QVERIFY(image.save(prefix + "gen-readWriteNonDestructive.tiff"));
+
+ QImage image2 = QImage(prefix + "gen-readWriteNonDestructive.tiff");
+ QImage::Format readFormat = image2.format();
+ QCOMPARE(readFormat, expectedFormat);
+ QCOMPARE(image, image2);
+}
+
void tst_QImageWriter::setDescription_data()
{
QTest::addColumn<QString>("fileName");
@@ -449,13 +478,13 @@ void tst_QImageWriter::supportsOption_data()
QTest::addColumn<QString>("fileName");
QTest::addColumn<QIntList>("options");
- QTest::newRow("png") << QString(prefix + "gen-black.png")
+ QTest::newRow("png") << QString("gen-black.png")
<< (QIntList() << QImageIOHandler::Gamma
<< QImageIOHandler::Description
<< QImageIOHandler::Quality
<< QImageIOHandler::Size);
#if defined QTEST_HAVE_TIFF
- QTest::newRow("tiff") << QString("images/gen-black.tiff")
+ QTest::newRow("tiff") << QString("gen-black.tiff")
<< (QIntList() << QImageIOHandler::Size
<< QImageIOHandler::CompressionRatio);
#endif
@@ -482,7 +511,7 @@ void tst_QImageWriter::supportsOption()
<< QImageIOHandler::Animation
<< QImageIOHandler::BackgroundColor;
- QImageWriter writer(fileName);
+ QImageWriter writer(prefix + fileName);
for (int i = 0; i < options.size(); ++i) {
QVERIFY(writer.supportsOption(QImageIOHandler::ImageOption(options.at(i))));
allOptions.remove(QImageIOHandler::ImageOption(options.at(i)));
@@ -537,6 +566,39 @@ void tst_QImageWriter::saveWithNoFormat()
QVERIFY2(!outImage.isNull(), qPrintable(reader.errorString()));
}
+void tst_QImageWriter::resolution_data()
+{
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<int>("expectedDotsPerMeterX");
+ QTest::addColumn<int>("expectedDotsPerMeterY");
+#if defined QTEST_HAVE_TIFF
+ QTest::newRow("TIFF: 100 dpi") << ("image_100dpi.tif") << qRound(100 * (100 / 2.54)) << qRound(100 * (100 / 2.54));
+ QTest::newRow("TIFF: 50 dpi") << ("image_50dpi.tif") << qRound(50 * (100 / 2.54)) << qRound(50 * (100 / 2.54));
+ QTest::newRow("TIFF: 300 dot per meter") << ("image_300dpm.tif") << 300 << 300;
+#endif
+}
+
+void tst_QImageWriter::resolution()
+{
+ QFETCH(QString, filename);
+ QFETCH(int, expectedDotsPerMeterX);
+ QFETCH(int, expectedDotsPerMeterY);
+
+ QImage image(prefix + QLatin1String("colorful.bmp"));
+ image.setDotsPerMeterX(expectedDotsPerMeterX);
+ image.setDotsPerMeterY(expectedDotsPerMeterY);
+ const QString generatedFilepath = prefix + "gen-" + filename;
+ {
+ QImageWriter writer(generatedFilepath);
+ QVERIFY(writer.write(image));
+ }
+ QImageReader reader(generatedFilepath);
+ const QImage generatedImage = reader.read();
+
+ QCOMPARE(expectedDotsPerMeterX, generatedImage.dotsPerMeterX());
+ QCOMPARE(expectedDotsPerMeterY, generatedImage.dotsPerMeterY());
+}
+
void tst_QImageWriter::saveToTemporaryFile()
{
QImage image(prefix + "kollada.png");
diff --git a/tests/auto/qinputdialog/tst_qinputdialog.cpp b/tests/auto/qinputdialog/tst_qinputdialog.cpp
index 0f763fc..c635381 100644
--- a/tests/auto/qinputdialog/tst_qinputdialog.cpp
+++ b/tests/auto/qinputdialog/tst_qinputdialog.cpp
@@ -67,6 +67,7 @@ private slots:
void getInteger();
void getDouble_data();
void getDouble();
+ void task255502getDouble();
void getText_data();
void getText();
void getItem_data();
@@ -318,6 +319,20 @@ void tst_QInputDialog::getDouble()
delete parent;
}
+void tst_QInputDialog::task255502getDouble()
+{
+ parent = new QWidget;
+ testFunc = &tst_QInputDialog::testFuncGetDouble;
+ startTimer(0);
+ bool ok = false;
+ const double value = 0.001;
+ const double result =
+ QInputDialog::getDouble(parent, "", "", value, -1, 1, 4, &ok);
+ QVERIFY(ok);
+ QCOMPARE(result, value);
+ delete parent;
+}
+
void tst_QInputDialog::getText_data()
{
QTest::addColumn<QString>("text");
diff --git a/tests/auto/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/qitemdelegate/tst_qitemdelegate.cpp
index 955760a..f940942 100644
--- a/tests/auto/qitemdelegate/tst_qitemdelegate.cpp
+++ b/tests/auto/qitemdelegate/tst_qitemdelegate.cpp
@@ -1034,7 +1034,7 @@ void tst_QItemDelegate::editorEvent()
option.rect = rect;
option.state |= QStyle::State_Enabled;
- const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1;
+ const int checkMargin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1;
QPoint pos = inCheck ? qApp->style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &option, 0).center() + QPoint(checkMargin, 0) : QPoint(200,200);
QEvent *event = new QMouseEvent((QEvent::Type)type,
@@ -1057,7 +1057,7 @@ void tst_QItemDelegate::enterKey_data()
QTest::addColumn<int>("widget");
QTest::addColumn<int>("key");
QTest::addColumn<bool>("expectedFocus");
-
+
QTest::newRow("lineedit enter") << 1 << int(Qt::Key_Enter) << false;
QTest::newRow("textedit enter") << 2 << int(Qt::Key_Enter) << true;
QTest::newRow("plaintextedit enter") << 3 << int(Qt::Key_Enter) << true;
@@ -1071,17 +1071,17 @@ void tst_QItemDelegate::enterKey()
QFETCH(int, widget);
QFETCH(int, key);
QFETCH(bool, expectedFocus);
-
+
QStandardItemModel model;
model.appendRow(new QStandardItem());
-
+
QListView view;
view.setModel(&model);
view.show();
QApplication::setActiveWindow(&view);
view.setFocus();
QTest::qWait(30);
-
+
struct TestDelegate : public QItemDelegate
{
int widgetType;
@@ -1089,7 +1089,7 @@ void tst_QItemDelegate::enterKey()
{
QWidget *editor = 0;
switch(widgetType) {
- case 1:
+ case 1:
editor = new QLineEdit(parent);
break;
case 2:
@@ -1103,27 +1103,27 @@ void tst_QItemDelegate::enterKey()
return editor;
}
} delegate;
-
+
delegate.widgetType = widget;
-
+
view.setItemDelegate(&delegate);
QModelIndex index = model.index(0, 0);
view.setCurrentIndex(index); // the editor will only selectAll on the current index
view.edit(index);
QTest::qWait(30);
-
+
QList<QWidget*> lineEditors = qFindChildren<QWidget *>(view.viewport(), QString::fromLatin1("TheEditor"));
QCOMPARE(lineEditors.count(), 1);
-
+
QPointer<QWidget> editor = lineEditors.at(0);
QCOMPARE(editor->hasFocus(), true);
-
+
QTest::keyClick(editor, Qt::Key(key));
QApplication::processEvents();
if (widget == 2 || widget == 3) {
QVERIFY(!editor.isNull());
- QCOMPARE(editor->hasFocus(), expectedFocus);
+ QCOMPARE(editor && editor->hasFocus(), expectedFocus);
}
}
diff --git a/tests/auto/qlineedit/tst_qlineedit.cpp b/tests/auto/qlineedit/tst_qlineedit.cpp
index d900518..73f4f13 100644
--- a/tests/auto/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/qlineedit/tst_qlineedit.cpp
@@ -258,6 +258,7 @@ private slots:
void task233101_cursorPosAfterInputMethod_data();
void task233101_cursorPosAfterInputMethod();
void task241436_passwordEchoOnEditRestoreEchoMode();
+ void task248948_redoRemovedSelection();
protected slots:
#ifdef QT3_SUPPORT
@@ -3485,5 +3486,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/qlistview/tst_qlistview.cpp b/tests/auto/qlistview/tst_qlistview.cpp
index db11447..b65fb81 100644
--- a/tests/auto/qlistview/tst_qlistview.cpp
+++ b/tests/auto/qlistview/tst_qlistview.cpp
@@ -54,6 +54,7 @@
#include <math.h>
#include <QtGui/QScrollBar>
#include <QtGui/QDialog>
+#include <QtGui/QStyledItemDelegate>
#if defined(Q_OS_WIN) || defined(Q_OS_WINCE)
#include <windows.h>
#endif
@@ -108,6 +109,9 @@ private slots:
void task228566_infiniteRelayout();
void task248430_crashWith0SizedItem();
void task250446_scrollChanged();
+ void task196118_visualRegionForSelection();
+ void task254449_draggingItemToNegativeCoordinates();
+ void keyboardSearch();
};
// Testing get/set functions
@@ -1557,6 +1561,102 @@ void tst_QListView::task250446_scrollChanged()
QCOMPARE(view.currentIndex(), index);
}
+void tst_QListView::task196118_visualRegionForSelection()
+{
+ class MyListView : public QListView
+ {
+ public:
+ QRegion visualRegionForSelection() const
+ { return QListView::visualRegionForSelection( selectionModel()->selection()); }
+ } view;
+
+ QStandardItemModel model;
+ QStandardItem top1("top1");
+ QStandardItem sub1("sub1");
+ top1.appendRow(QList<QStandardItem*>() << &sub1);
+ model.appendColumn(QList<QStandardItem*>() << &top1);
+ view.setModel(&model);
+ view.setRootIndex(top1.index());
+
+ view.selectionModel()->select(top1.index(), QItemSelectionModel::Select);
+
+ QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1);
+ QVERIFY(view.visualRegionForSelection().isEmpty());
+}
+
+void tst_QListView::task254449_draggingItemToNegativeCoordinates()
+{
+ //we'll check that the items are painted correctly
+ class MyListView : public QListView
+ {
+ public:
+ void setPositionForIndex(const QPoint &position, const QModelIndex &index)
+ { QListView::setPositionForIndex(position, index); }
+
+ } list;
+
+ QStandardItemModel model(1,1);
+ QModelIndex index = model.index(0,0);
+ model.setData(index, QLatin1String("foo"));
+ list.setModel(&model);
+ list.setViewMode(QListView::IconMode);
+ list.show();
+ QTest::qWait(200); //makes sure the layout is done
+
+ const QPoint topLeft(-6, 0);
+
+
+ list.setPositionForIndex(topLeft, index);
+
+ class MyItemDelegate : public QStyledItemDelegate
+ {
+ public:
+ MyItemDelegate() : numPaints(0) { }
+ void paint(QPainter *painter,
+ const QStyleOptionViewItem &option, const QModelIndex &index) const
+ {
+ numPaints++;
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+
+ mutable int numPaints;
+ } delegate;
+
+ list.setItemDelegate(&delegate);
+
+ //we'll make sure the item is repainted
+ delegate.numPaints = 0;
+ list.viewport()->repaint();
+
+ QCOMPARE(list.visualRect(index).topLeft(), topLeft);
+ QCOMPARE(delegate.numPaints, 1);
+}
+
+
+void tst_QListView::keyboardSearch()
+{
+ QStringList items;
+ items << "AB" << "AC" << "BA" << "BB" << "BD" << "KAFEINE" << "KONQUEROR" << "KOPETE" << "KOOKA" << "OKULAR";
+ QStringListModel model(items);
+
+ QListView view;
+ view.setModel(&model);
+ view.show();
+ QTest::qWait(30);
+// QCOMPARE(view.currentIndex() , model.index(0,0));
+
+ QTest::keyClick(&view, Qt::Key_K);
+ QTest::qWait(10);
+ QCOMPARE(view.currentIndex() , model.index(5,0)); //KAFEINE
+
+ QTest::keyClick(&view, Qt::Key_O);
+ QTest::qWait(10);
+ QCOMPARE(view.currentIndex() , model.index(6,0)); //KONQUEROR
+
+ QTest::keyClick(&view, Qt::Key_N);
+ QTest::qWait(10);
+ QCOMPARE(view.currentIndex() , model.index(6,0)); //KONQUEROR
+}
QTEST_MAIN(tst_QListView)
#include "tst_qlistview.moc"
diff --git a/tests/auto/qlistwidget/tst_qlistwidget.cpp b/tests/auto/qlistwidget/tst_qlistwidget.cpp
index 8d15aa4..8468cf3 100644
--- a/tests/auto/qlistwidget/tst_qlistwidget.cpp
+++ b/tests/auto/qlistwidget/tst_qlistwidget.cpp
@@ -883,31 +883,46 @@ void tst_QListWidget::itemStreaming()
void tst_QListWidget::sortItems_data()
{
QTest::addColumn<int>("order");
- QTest::addColumn<QStringList>("initialList");
- QTest::addColumn<QStringList>("expectedList");
+ QTest::addColumn<QVariantList>("initialList");
+ QTest::addColumn<QVariantList>("expectedList");
QTest::addColumn<IntList>("expectedRows");
- QTest::newRow("ascending order")
+ QTest::newRow("ascending strings")
<< static_cast<int>(Qt::AscendingOrder)
- << (QStringList() << "c" << "d" << "a" << "b")
- << (QStringList() << "a" << "b" << "c" << "d")
+ << (QVariantList() << QString("c") << QString("d") << QString("a") << QString("b"))
+ << (QVariantList() << QString("a") << QString("b") << QString("c") << QString("d"))
<< (IntList() << 2 << 3 << 0 << 1);
- QTest::newRow("descending order")
+ QTest::newRow("descending strings")
<< static_cast<int>(Qt::DescendingOrder)
- << (QStringList() << "c" << "d" << "a" << "b")
- << (QStringList() << "d" << "c" << "b" << "a")
+ << (QVariantList() << QString("c") << QString("d") << QString("a") << QString("b"))
+ << (QVariantList() << QString("d") << QString("c") << QString("b") << QString("a"))
<< (IntList() << 1 << 0 << 3 << 2);
+
+ QTest::newRow("ascending numbers")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QVariantList() << 1 << 11 << 2 << 22)
+ << (QVariantList() << 1 << 2 << 11 << 22)
+ << (IntList() << 0 << 2 << 1 << 3);
+
+ QTest::newRow("descending numbers")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QVariantList() << 1 << 11 << 2 << 22)
+ << (QVariantList() << 22 << 11 << 2 << 1)
+ << (IntList() << 3 << 1 << 2 << 0);
}
void tst_QListWidget::sortItems()
{
QFETCH(int, order);
- QFETCH(QStringList, initialList);
- QFETCH(QStringList, expectedList);
+ QFETCH(QVariantList, initialList);
+ QFETCH(QVariantList, expectedList);
QFETCH(IntList, expectedRows);
- testWidget->addItems(initialList);
+ foreach (const QVariant &data, initialList) {
+ QListWidgetItem *item = new QListWidgetItem(testWidget);
+ item->setData(Qt::DisplayRole, data);
+ }
QAbstractItemModel *model = testWidget->model();
QList<QPersistentModelIndex> persistent;
@@ -918,7 +933,7 @@ void tst_QListWidget::sortItems()
QCOMPARE(testWidget->count(), expectedList.count());
for (int i = 0; i < testWidget->count(); ++i)
- QCOMPARE(testWidget->item(i)->text(), expectedList.at(i));
+ QCOMPARE(testWidget->item(i)->text(), expectedList.at(i).toString());
for (int k = 0; k < testWidget->count(); ++k)
QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
diff --git a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp
index a8aab19..4a7124b 100644
--- a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp
+++ b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp
@@ -108,6 +108,8 @@ private slots:
void recycleServer();
+ void multiConnect();
+
void debug();
#ifdef Q_OS_SYMBIAN
@@ -899,6 +901,31 @@ void tst_QLocalSocket::recycleServer()
QVERIFY(server.nextPendingConnection() != 0);
}
+void tst_QLocalSocket::multiConnect()
+{
+ QLocalServer server;
+ QLocalSocket client1;
+ QLocalSocket client2;
+ QLocalSocket client3;
+
+ QVERIFY(server.listen("multiconnect"));
+
+ client1.connectToServer("multiconnect");
+ client2.connectToServer("multiconnect");
+ client3.connectToServer("multiconnect");
+
+ QVERIFY(client1.waitForConnected(201));
+ QVERIFY(client2.waitForConnected(202));
+ QVERIFY(client3.waitForConnected(203));
+
+ QVERIFY(server.waitForNewConnection(201));
+ QVERIFY(server.nextPendingConnection() != 0);
+ QVERIFY(server.waitForNewConnection(202));
+ QVERIFY(server.nextPendingConnection() != 0);
+ QVERIFY(server.waitForNewConnection(203));
+ QVERIFY(server.nextPendingConnection() != 0);
+}
+
void tst_QLocalSocket::debug()
{
// Make sure this compiles
diff --git a/tests/auto/qmake/testdata/bundle-spaces/some-file b/tests/auto/qmake/testdata/bundle-spaces/some-file
index e69de29..9975dba 100644
--- a/tests/auto/qmake/testdata/bundle-spaces/some-file
+++ b/tests/auto/qmake/testdata/bundle-spaces/some-file
@@ -0,0 +1,6 @@
+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/qmake/tst_qmake.cpp b/tests/auto/qmake/tst_qmake.cpp
index 1178c81..1ba81bd 100644
--- a/tests/auto/qmake/tst_qmake.cpp
+++ b/tests/auto/qmake/tst_qmake.cpp
@@ -39,13 +39,14 @@
**
****************************************************************************/
+#include <QtTest/QtTest>
+
#if !defined(QMAKE_CROSS_COMPILED)
#include "testcompiler.h"
#include <QObject>
#include <QDir>
-#include <QtTest/QtTest>
class tst_qmake : public QObject
{
diff --git a/tests/auto/qmap/tst_qmap.cpp b/tests/auto/qmap/tst_qmap.cpp
index 99efc80..68ac8d6 100644
--- a/tests/auto/qmap/tst_qmap.cpp
+++ b/tests/auto/qmap/tst_qmap.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#define QT_STRICT_ITERATORS
#include <QtTest/QtTest>
#include <QDebug>
@@ -400,7 +401,7 @@ void tst_QMap::operator_eq()
QVERIFY(a == b);
QVERIFY(!(a != b));
-
+
a.insert(1,1);
b.insert(1,1);
QVERIFY(a == b);
@@ -422,7 +423,7 @@ void tst_QMap::operator_eq()
b.insert(-1, -1);
QVERIFY(a != b);
- QVERIFY(!(a == b));
+ QVERIFY(!(a == b));
}
{
@@ -468,7 +469,7 @@ void tst_QMap::operator_eq()
b.insert("willy", 1);
QVERIFY(a != b);
QVERIFY(!(a == b));
- }
+ }
}
void tst_QMap::empty()
@@ -523,9 +524,9 @@ void tst_QMap::find()
map1.insertMulti(4, compareString);
}
- QMap<int, QString>::const_iterator it=map1.find(4);
+ QMap<int, QString>::const_iterator it=map1.constFind(4);
- for(i = 9; i > 2 && it != map1.end() && it.key() == 4; --i) {
+ for(i = 9; i > 2 && it != map1.constEnd() && it.key() == 4; --i) {
compareString = testString.arg(i);
QVERIFY(it.value() == compareString);
++it;
@@ -546,9 +547,9 @@ void tst_QMap::constFind()
map1.insert(1,"Mensch");
map1.insert(1,"Mayer");
map1.insert(2,"Hej");
-
+
QVERIFY(map1.constFind(4) == map1.constEnd());
-
+
QVERIFY(map1.constFind(1).value() == "Mayer");
QVERIFY(map1.constFind(2).value() == "Hej");
@@ -677,7 +678,7 @@ void tst_QMap::iterators()
cstlIt--;
QVERIFY(cstlIt.value() == "Teststring 3");
- for(cstlIt = map.begin(), i = 1; cstlIt != map.constEnd(), i < 100; ++cstlIt, ++i)
+ for(cstlIt = map.constBegin(), i = 1; cstlIt != map.constEnd(), i < 100; ++cstlIt, ++i)
QVERIFY(cstlIt.value() == testString.arg(i));
//Java-Style iterators
diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
index b4e596f..81072ed 100644
--- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
@@ -52,6 +52,7 @@
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QLocalSocket>
#include <QtNetwork/QLocalServer>
+#include <QtNetwork/QHostInfo>
#include <QtNetwork/QFtp>
#include <QtNetwork/qauthenticator.h>
#include <QtNetwork/qnetworkaccessmanager.h>
@@ -99,6 +100,15 @@ class tst_QNetworkReply: public QObject
{
Q_OBJECT
+ struct ProxyData {
+ ProxyData(const QNetworkProxy &p, const QByteArray &t, bool auth)
+ : tag(t), proxy(p), requiresAuthentication(auth)
+ { }
+ QByteArray tag;
+ QNetworkProxy proxy;
+ bool requiresAuthentication;
+ };
+
QEventLoop *loop;
enum RunSimpleRequestReturn { Timeout = 0, Success, Failure };
int returnCode;
@@ -107,6 +117,7 @@ class tst_QNetworkReply: public QObject
QString wronlyFileName;
#endif
QString uniqueExtension;
+ QList<ProxyData> proxies;
QNetworkAccessManager manager;
MyCookieJar *cookieJar;
#ifndef QT_NO_OPENSSL
@@ -159,6 +170,10 @@ private Q_SLOTS:
void putToHttp();
void postToHttp_data();
void postToHttp();
+ void deleteFromHttp_data();
+ void deleteFromHttp();
+ void putGetDeleteGetFromHttp_data();
+ void putGetDeleteGetFromHttp();
void ioGetFromData_data();
void ioGetFromData();
@@ -201,11 +216,20 @@ private Q_SLOTS:
void ioPutToHttpFromFile();
void ioPostToHttpFromFile_data();
void ioPostToHttpFromFile();
+ void ioPostToHttpFromSocket_data();
+ void ioPostToHttpFromSocket();
+ void ioPostToHttpFromMiddleOfFileToEnd();
+ void ioPostToHttpFromMiddleOfFileFiveBytes();
+ void ioPostToHttpFromMiddleOfQBufferFiveBytes();
+ void ioPostToHttpNoBufferFlag();
+ void ioPostToHttpUploadProgress();
+ void ioPostToHttpEmtpyUploadProgress();
void rateControl_data();
void rateControl();
void downloadPerformance();
void uploadPerformance();
+ void httpUploadPerformance();
void performanceControlRate();
void downloadProgress_data();
@@ -228,6 +252,8 @@ private Q_SLOTS:
void proxyChange();
void authorizationError_data();
void authorizationError();
+
+ void httpConnectionCount();
};
QT_BEGIN_NAMESPACE
@@ -377,6 +403,63 @@ public slots:
}
};
+class FixedSizeDataGenerator : public QIODevice
+{
+ Q_OBJECT
+ enum { Idle, Started, Stopped } state;
+public:
+ FixedSizeDataGenerator(qint64 size) : state(Idle)
+ { open(ReadOnly | Unbuffered);
+ toBeGeneratedTotalCount = toBeGeneratedCount = size;
+ }
+
+ virtual qint64 bytesAvailable() const
+ {
+ return state == Started ? toBeGeneratedCount + QIODevice::bytesAvailable() : 0;
+ }
+
+ virtual bool isSequential() const{
+ return false;
+ }
+
+ virtual bool reset() const{
+ return false;
+ }
+
+ qint64 size() const {
+ return toBeGeneratedTotalCount;
+ }
+
+public slots:
+ void start() { state = Started; emit readyRead(); }
+
+protected:
+ virtual qint64 readData(char *data, qint64 maxlen)
+ {
+ memset(data, '@', maxlen);
+
+ if (toBeGeneratedCount <= 0) {
+ return -1;
+ }
+
+ qint64 n = qMin(maxlen, toBeGeneratedCount);
+ toBeGeneratedCount -= n;
+
+ if (toBeGeneratedCount <= 0) {
+ // make sure this is a queued connection!
+ emit readChannelFinished();
+ }
+
+ return n;
+ }
+ virtual qint64 writeData(const char *, qint64)
+ { return -1; }
+
+ qint64 toBeGeneratedCount;
+ qint64 toBeGeneratedTotalCount;
+};
+
+
class DataGenerator: public QIODevice
{
Q_OBJECT
@@ -397,6 +480,7 @@ protected:
{
if (state == Stopped)
return -1; // EOF
+
// return as many bytes as are wanted
memset(data, '@', maxlen);
return maxlen;
@@ -405,6 +489,8 @@ protected:
{ return -1; }
};
+
+
class SocketPair: public QObject
{
Q_OBJECT
@@ -650,7 +736,7 @@ protected:
return;
transferRate = totalBytes * 1000 / timer.elapsed();
- qDebug() << "receive rate:" << (transferRate / 1024) << "kB/s in"
+ qDebug() << "TimedSender::run" << "receive rate:" << (transferRate / 1024) << "kB/s in"
<< timer.elapsed() << "ms";
}
@@ -664,12 +750,13 @@ protected:
class ThreadedDataReader: public QThread
{
Q_OBJECT
+ // used to make the constructor only return after the tcp server started listening
QSemaphore ready;
QTcpSocket *client;
int timeout;
int port;
public:
- int transferRate;
+ qint64 transferRate;
ThreadedDataReader()
: port(-1), transferRate(-1)
{
@@ -697,12 +784,65 @@ protected:
QTime timer;
timer.start();
eventLoop.exec();
+ qint64 elapsed = timer.elapsed();
+
+ transferRate = reader.totalBytes * 1000 / elapsed;
+ qDebug() << "ThreadedDataReader::run" << "send rate:" << (transferRate / 1024) << "kB/s in" << elapsed << "msec";
+ }
+};
+
+class ThreadedDataReaderHttpServer: public QThread
+{
+ Q_OBJECT
+ // used to make the constructor only return after the tcp server started listening
+ QSemaphore ready;
+ QTcpSocket *client;
+ int timeout;
+ int port;
+public:
+ qint64 transferRate;
+ ThreadedDataReaderHttpServer()
+ : port(-1), transferRate(-1)
+ {
+ start();
+ ready.acquire();
+ }
+
+ inline int serverPort() const { return port; }
+
+protected:
+ void run()
+ {
+ QTcpServer server;
+ server.listen();
+ port = server.serverPort();
+ ready.release();
+
+ server.waitForNewConnection(-1);
+ client = server.nextPendingConnection();
+ client->write("HTTP/1.0 200 OK\r\n");
+ client->write("Content-length: 0\r\n");
+ client->write("\r\n");
+ client->flush();
+
+ QCoreApplication::processEvents();
+
+ QEventLoop eventLoop;
+ DataReader reader(client, false);
+ QObject::connect(client, SIGNAL(disconnected()), &eventLoop, SLOT(quit()));
+
+ QTime timer;
+ timer.start();
+ eventLoop.exec();
+ qint64 elapsed = timer.elapsed();
- transferRate = reader.totalBytes * 1000 / timer.elapsed();
- qDebug() << "send rate:" << (transferRate / 1024) << "kB/s";
+ transferRate = reader.totalBytes * 1000 / elapsed;
+ qDebug() << "ThreadedDataReaderHttpServer::run" << "send rate:" << (transferRate / 1024) << "kB/s in" << elapsed << "msec";
}
};
+
+
tst_QNetworkReply::tst_QNetworkReply()
{
Q_SET_DEFAULT_IAP
@@ -714,13 +854,32 @@ tst_QNetworkReply::tst_QNetworkReply()
uniqueExtension = QString("%1%2").arg((qulonglong)this).arg(rand());
#endif
cookieJar = new MyCookieJar;
- manager.setCookieJar(cookieJar);
+ manager.setCookieJar(cookieJar);
+
+ QHostInfo hostInfo = QHostInfo::fromName(QtNetworkSettings::serverName());
+
+ proxies << ProxyData(QNetworkProxy::NoProxy, "", false);
+
+ if (hostInfo.error() == QHostInfo::NoError && !hostInfo.addresses().isEmpty()) {
+ QString proxyserver = hostInfo.addresses().first().toString();
+ proxies << ProxyData(QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3128), "+proxy", false)
+ << ProxyData(QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3129), "+proxyauth", true)
+ // currently unsupported
+ // << ProxyData(QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3130), "+proxyauth-ntlm", true);
+ << ProxyData(QNetworkProxy(QNetworkProxy::Socks5Proxy, proxyserver, 1080), "+socks", false)
+ << ProxyData(QNetworkProxy(QNetworkProxy::Socks5Proxy, proxyserver, 1081), "+socksauth", true);
+ } else {
+ printf("==================================================================\n");
+ printf("Proxy could not be looked up. No proxy will be used while testing!\n");
+ printf("==================================================================\n");
+ }
}
tst_QNetworkReply::~tst_QNetworkReply()
{
}
+
void tst_QNetworkReply::authenticationRequired(QNetworkReply*, QAuthenticator* auth)
{
auth->setUser("httptest");
@@ -772,6 +931,10 @@ QString tst_QNetworkReply::runSimpleRequest(QNetworkAccessManager::Operation op,
reply = manager.post(request, data);
break;
+ case QNetworkAccessManager::DeleteOperation:
+ reply = manager.deleteResource(request);
+ break;
+
default:
Q_ASSERT_X(false, "tst_QNetworkReply", "Invalid/unknown operation requested");
}
@@ -1347,6 +1510,97 @@ void tst_QNetworkReply::postToHttp()
QCOMPARE(uploadedData, md5sum.toHex());
}
+void tst_QNetworkReply::deleteFromHttp_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<int>("resultCode");
+ QTest::addColumn<QNetworkReply::NetworkError>("error");
+
+ // for status codes to expect, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
+
+ QTest::newRow("405-method-not-allowed") << QUrl("http://" + QtNetworkSettings::serverName() + "/index.html") << 405 << QNetworkReply::ContentOperationNotPermittedError;
+ QTest::newRow("200-ok") << QUrl("http://" + QtNetworkSettings::serverName() + "/cgi-bin/http-delete.cgi?200-ok") << 200 << QNetworkReply::NoError;
+ QTest::newRow("202-accepted") << QUrl("http://" + QtNetworkSettings::serverName() + "/cgi-bin/http-delete.cgi?202-accepted") << 202 << QNetworkReply::NoError;
+ QTest::newRow("204-no-content") << QUrl("http://" + QtNetworkSettings::serverName() + "/cgi-bin/http-delete.cgi?204-no-content") << 204 << QNetworkReply::NoError;
+ QTest::newRow("404-not-found") << QUrl("http://" + QtNetworkSettings::serverName() + "/cgi-bin/http-delete.cgi?404-not-found") << 404 << QNetworkReply::ContentNotFoundError;
+}
+
+void tst_QNetworkReply::deleteFromHttp()
+{
+ QFETCH(QUrl, url);
+ QFETCH(int, resultCode);
+ QFETCH(QNetworkReply::NetworkError, error);
+ QNetworkRequest request(url);
+ QNetworkReplyPtr reply;
+ runSimpleRequest(QNetworkAccessManager::DeleteOperation, request, reply, 0);
+ QCOMPARE(reply->url(), url);
+ QCOMPARE(reply->error(), error);
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), resultCode);
+}
+
+void tst_QNetworkReply::putGetDeleteGetFromHttp_data()
+{
+ QTest::addColumn<QUrl>("putUrl");
+ QTest::addColumn<int>("putResultCode");
+ QTest::addColumn<QNetworkReply::NetworkError>("putError");
+ QTest::addColumn<QUrl>("deleteUrl");
+ QTest::addColumn<int>("deleteResultCode");
+ QTest::addColumn<QNetworkReply::NetworkError>("deleteError");
+ QTest::addColumn<QUrl>("get2Url");
+ QTest::addColumn<int>("get2ResultCode");
+ QTest::addColumn<QNetworkReply::NetworkError>("get2Error");
+
+ QUrl url("http://" + QtNetworkSettings::serverName());
+ url.setPath(QString("/dav/qnetworkaccess-putToHttp-%1-%2")
+ .arg(QTest::currentDataTag())
+ .arg(uniqueExtension));
+
+ // first use case: put, get (to check it is there), delete, get (to check it is not there anymore)
+ QTest::newRow("success") << url << 201 << QNetworkReply::NoError << url << 204 << QNetworkReply::NoError << url << 404 << QNetworkReply::ContentNotFoundError;
+
+ QUrl wrongUrl("http://" + QtNetworkSettings::serverName());
+ wrongUrl.setPath(QString("/dav/qnetworkaccess-thisURLisNotAvailable"));
+
+ // second use case: put, get (to check it is there), delete wrong URL, get (to check it is still there)
+ QTest::newRow("delete-error") << url << 201 << QNetworkReply::NoError << wrongUrl << 404 << QNetworkReply::ContentNotFoundError << url << 200 << QNetworkReply::NoError;
+
+}
+
+void tst_QNetworkReply::putGetDeleteGetFromHttp()
+{
+ QFETCH(QUrl, putUrl);
+ QFETCH(int, putResultCode);
+ QFETCH(QNetworkReply::NetworkError, putError);
+ QFETCH(QUrl, deleteUrl);
+ QFETCH(int, deleteResultCode);
+ QFETCH(QNetworkReply::NetworkError, deleteError);
+ QFETCH(QUrl, get2Url);
+ QFETCH(int, get2ResultCode);
+ QFETCH(QNetworkReply::NetworkError, get2Error);
+
+ QNetworkRequest putRequest(putUrl);
+ QNetworkRequest deleteRequest(deleteUrl);
+ QNetworkRequest get2Request(get2Url);
+ QNetworkReplyPtr reply;
+
+ RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PutOperation, putRequest, reply, 0));
+ QCOMPARE(reply->error(), putError);
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), putResultCode);
+
+ runSimpleRequest(QNetworkAccessManager::GetOperation, putRequest, reply, 0);
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+
+ runSimpleRequest(QNetworkAccessManager::DeleteOperation, deleteRequest, reply, 0);
+ QCOMPARE(reply->error(), deleteError);
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), deleteResultCode);
+
+ runSimpleRequest(QNetworkAccessManager::GetOperation, get2Request, reply, 0);
+ QCOMPARE(reply->error(), get2Error);
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), get2ResultCode);
+
+}
+
void tst_QNetworkReply::ioGetFromData_data()
{
QTest::addColumn<QString>("urlStr");
@@ -2552,6 +2806,320 @@ void tst_QNetworkReply::ioPostToHttpFromFile()
QCOMPARE(reply->readAll().trimmed(), md5sum(sourceFile.readAll()).toHex());
}
+void tst_QNetworkReply::ioPostToHttpFromSocket_data()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<QByteArray>("md5sum");
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QNetworkProxy>("proxy");
+ QTest::addColumn<int>("authenticationRequiredCount");
+ QTest::addColumn<int>("proxyAuthenticationRequiredCount");
+
+ for (int i = 0; i < proxies.count(); ++i)
+ for (int auth = 0; auth < 2; ++auth) {
+ QUrl url;
+ if (auth)
+ url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi";
+ else
+ url = "http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi";
+
+ QNetworkProxy proxy = proxies.at(i).proxy;
+ QByteArray testsuffix = QByteArray(auth ? "+auth" : "") + proxies.at(i).tag;
+ int proxyauthcount = proxies.at(i).requiresAuthentication;
+
+ QByteArray data;
+ data = "";
+ QTest::newRow("empty" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount;
+
+ data = "This is a normal message.";
+ QTest::newRow("generic" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount;
+
+ data = "This is a message to show that Qt rocks!\r\n\n";
+ QTest::newRow("small" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount;
+
+ data = QByteArray("abcd\0\1\2\abcd",12);
+ QTest::newRow("with-nul" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount;
+
+ data = QByteArray(4097, '\4');
+ QTest::newRow("4k+1" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount;
+
+ data = QByteArray(128*1024+1, '\177');
+ QTest::newRow("128k+1" + testsuffix) << data << md5sum(data) << url << proxy << auth << proxyauthcount;
+ }
+}
+
+void tst_QNetworkReply::ioPostToHttpFromSocket()
+{
+ qRegisterMetaType<QNetworkProxy>(); // for QSignalSpy
+ qRegisterMetaType<QAuthenticator *>();
+ qRegisterMetaType<QNetworkReply *>();
+
+ QFETCH(QByteArray, data);
+ QFETCH(QUrl, url);
+ QFETCH(QNetworkProxy, proxy);
+ SocketPair socketpair;
+ socketpair.create();
+ QVERIFY(socketpair.endPoints[0] && socketpair.endPoints[1]);
+
+ socketpair.endPoints[0]->write(data);
+
+ QNetworkRequest request(url);
+ manager.setProxy(proxy);
+ QNetworkReplyPtr reply = manager.post(QNetworkRequest(url), socketpair.endPoints[1]);
+ socketpair.endPoints[0]->close();
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ connect(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+ connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
+ SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
+
+ QSignalSpy authenticationRequiredSpy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)));
+ QSignalSpy proxyAuthenticationRequiredSpy(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ disconnect(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+ disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
+ this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QCOMPARE(reply->url(), url);
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ // verify that the HTTP status code is 200 Ok
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+
+ QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex());
+
+ QTEST(authenticationRequiredSpy.count(), "authenticationRequiredCount");
+ QTEST(proxyAuthenticationRequiredSpy.count(), "proxyAuthenticationRequiredCount");
+ }
+
+// this tests checks if rewinding the POST-data to some place in the middle
+// worked.
+void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileToEnd()
+{
+ QFile sourceFile(SRCDIR "/rfc3252.txt");
+ QVERIFY(sourceFile.open(QIODevice::ReadOnly));
+ // seeking to the middle
+ sourceFile.seek(sourceFile.size() / 2);
+
+ QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi";
+ QNetworkRequest request(url);
+ QNetworkReplyPtr reply = manager.post(QNetworkRequest(url), &sourceFile);
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
+ SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
+
+ QTestEventLoop::instance().enterLoop(2);
+ disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
+ this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ // compare half data
+ sourceFile.seek(sourceFile.size() / 2);
+ QByteArray data = sourceFile.readAll();
+ QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex());
+}
+
+void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileFiveBytes()
+{
+ QFile sourceFile(SRCDIR "/rfc3252.txt");
+ QVERIFY(sourceFile.open(QIODevice::ReadOnly));
+ // seeking to the middle
+ sourceFile.seek(sourceFile.size() / 2);
+
+ QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi";
+ QNetworkRequest request(url);
+ // only send 5 bytes
+ request.setHeader(QNetworkRequest::ContentLengthHeader, 5);
+ QVERIFY(request.header(QNetworkRequest::ContentLengthHeader).isValid());
+ QNetworkReplyPtr reply = manager.post(request, &sourceFile);
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
+ SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
+
+ QTestEventLoop::instance().enterLoop(2);
+ disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
+ this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ // compare half data
+ sourceFile.seek(sourceFile.size() / 2);
+ QByteArray data = sourceFile.read(5);
+ QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex());
+}
+
+void tst_QNetworkReply::ioPostToHttpFromMiddleOfQBufferFiveBytes()
+{
+ // test needed since a QBuffer goes with a different codepath than the QFile
+ // tested in ioPostToHttpFromMiddleOfFileFiveBytes
+ QBuffer uploadBuffer;
+ uploadBuffer.open(QIODevice::ReadWrite);
+ uploadBuffer.write("1234567890");
+ uploadBuffer.seek(5);
+
+ QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi";
+ QNetworkRequest request(url);
+ QNetworkReplyPtr reply = manager.post(request, &uploadBuffer);
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
+ SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
+
+ QTestEventLoop::instance().enterLoop(2);
+ disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
+ this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ // compare half data
+ uploadBuffer.seek(5);
+ QByteArray data = uploadBuffer.read(5);
+ QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex());
+}
+
+
+void tst_QNetworkReply::ioPostToHttpNoBufferFlag()
+{
+ QByteArray data = QByteArray("daaaaaaataaaaaaa");
+ // create a sequential QIODevice by feeding the data into a local TCP server
+ SocketPair socketpair;
+ socketpair.create();
+ QVERIFY(socketpair.endPoints[0] && socketpair.endPoints[1]);
+ socketpair.endPoints[0]->write(data);
+
+ QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi";
+ QNetworkRequest request(url);
+ // disallow buffering
+ request.setAttribute(QNetworkRequest::DoNotBufferUploadDataAttribute, true);
+ request.setHeader(QNetworkRequest::ContentLengthHeader, data.size());
+ QNetworkReplyPtr reply = manager.post(request, socketpair.endPoints[1]);
+ socketpair.endPoints[0]->close();
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
+ SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
+
+ QTestEventLoop::instance().enterLoop(2);
+ disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
+ this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
+
+ // verify: error code is QNetworkReply::ContentReSendError
+ QCOMPARE(reply->error(), QNetworkReply::ContentReSendError);
+}
+
+
+void tst_QNetworkReply::ioPostToHttpUploadProgress()
+{
+ QFile sourceFile(SRCDIR "/bigfile");
+ QVERIFY(sourceFile.open(QIODevice::ReadOnly));
+
+ // emulate a minimal http server
+ QTcpServer server;
+ server.listen(QHostAddress(QHostAddress::LocalHost), 0);
+
+ // create the request
+ QUrl url = QUrl(QString("http://127.0.0.1:%1/").arg(server.serverPort()));
+ QNetworkRequest request(url);
+ QNetworkReplyPtr reply = manager.post(request, &sourceFile);
+ QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64)));
+ connect(&server, SIGNAL(newConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ // get the request started and the incoming socket connected
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QTcpSocket *incomingSocket = server.nextPendingConnection();
+ QVERIFY(incomingSocket);
+ disconnect(&server, SIGNAL(newConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ incomingSocket->setReadBufferSize(1*1024);
+ QTestEventLoop::instance().enterLoop(2);
+ // some progress should have been made
+ QList<QVariant> args = spy.last();
+ QVERIFY(!args.isEmpty());
+ QVERIFY(args.at(0).toLongLong() > 0);
+
+ incomingSocket->setReadBufferSize(32*1024);
+ incomingSocket->read(16*1024);
+ QTestEventLoop::instance().enterLoop(2);
+ // some more progress than before
+ QList<QVariant> args2 = spy.last();
+ QVERIFY(!args2.isEmpty());
+ QVERIFY(args2.at(0).toLongLong() > args.at(0).toLongLong());
+
+ // set the read buffer to unlimited
+ incomingSocket->setReadBufferSize(0);
+ QTestEventLoop::instance().enterLoop(10);
+ // progress should be finished
+ QList<QVariant> args3 = spy.last();
+ QVERIFY(!args3.isEmpty());
+ QVERIFY(args3.at(0).toLongLong() > args2.at(0).toLongLong());
+ QCOMPARE(args3.at(0).toLongLong(), args3.at(1).toLongLong());
+ QCOMPARE(args3.at(0).toLongLong(), sourceFile.size());
+
+ // after sending this, the QNAM should emit finished()
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ incomingSocket->write("HTTP/1.0 200 OK\r\n");
+ incomingSocket->write("Content-Length: 0\r\n");
+ incomingSocket->write("\r\n");
+ QTestEventLoop::instance().enterLoop(10);
+ // not timeouted -> finished() was emitted
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ incomingSocket->close();
+ server.close();
+}
+
+void tst_QNetworkReply::ioPostToHttpEmtpyUploadProgress()
+{
+ QByteArray ba;
+ ba.resize(0);
+ QBuffer buffer(&ba,0);
+ QVERIFY(buffer.open(QIODevice::ReadOnly));
+
+ // emulate a minimal http server
+ QTcpServer server;
+ server.listen(QHostAddress(QHostAddress::LocalHost), 0);
+
+ // create the request
+ QUrl url = QUrl(QString("http://127.0.0.1:%1/").arg(server.serverPort()));
+ QNetworkRequest request(url);
+ QNetworkReplyPtr reply = manager.post(request, &buffer);
+ QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64)));
+ connect(&server, SIGNAL(newConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+
+ // get the request started and the incoming socket connected
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QTcpSocket *incomingSocket = server.nextPendingConnection();
+ QVERIFY(incomingSocket);
+
+ // after sending this, the QNAM should emit finished()
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ incomingSocket->write("HTTP/1.0 200 OK\r\n");
+ incomingSocket->write("Content-Length: 0\r\n");
+ incomingSocket->write("\r\n");
+ incomingSocket->flush();
+ QTestEventLoop::instance().enterLoop(10);
+ // not timeouted -> finished() was emitted
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ // final check: only 1 uploadProgress has been emitted
+ QVERIFY(spy.length() == 1);
+ QList<QVariant> args = spy.last();
+ QVERIFY(!args.isEmpty());
+ QCOMPARE(args.at(0).toLongLong(), buffer.size());
+ QCOMPARE(args.at(0).toLongLong(), buffer.size());
+
+ incomingSocket->close();
+ server.close();
+}
+
+
void tst_QNetworkReply::rateControl_data()
{
QTest::addColumn<int>("rate");
@@ -2588,8 +3156,8 @@ void tst_QNetworkReply::rateControl()
QTestEventLoop::instance().enterLoop(40);
int elapsedTime = loopTime.elapsed();
- qDebug() << "send rate:" << sender.transferRate;
- qDebug() << "receive rate:" << reader.totalBytesRead * 1000 / elapsedTime
+ qDebug() << "tst_QNetworkReply::rateControl" << "send rate:" << sender.transferRate;
+ qDebug() << "tst_QNetworkReply::rateControl" << "receive rate:" << reader.totalBytesRead * 1000 / elapsedTime
<< "(it received" << reader.totalBytesRead << "bytes in" << elapsedTime << "ms)";
sender.wait();
@@ -2622,23 +3190,54 @@ void tst_QNetworkReply::downloadPerformance()
sender.wait();
qint64 receivedBytes = reader.totalBytes;
- qDebug() << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and"
+ qDebug() << "tst_QNetworkReply::downloadPerformance" << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and"
<< elapsedTime << "ms";
}
void tst_QNetworkReply::uploadPerformance()
{
- ThreadedDataReader reader;
- DataGenerator generator;
- QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1");
- QNetworkReplyPtr reply = manager.put(request, &generator);
+ ThreadedDataReader reader;
+ DataGenerator generator;
- connect(&reader, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
- QTimer::singleShot(5000, &generator, SLOT(stop()));
- generator.start();
- QTestEventLoop::instance().enterLoop(40);
+
+ QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1");
+ QNetworkReplyPtr reply = manager.put(request, &generator);
+ generator.start();
+ connect(&reader, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+ QTimer::singleShot(5000, &generator, SLOT(stop()));
+
+ QTestEventLoop::instance().enterLoop(10);
+ QVERIFY(!QTestEventLoop::instance().timeout());
}
+void tst_QNetworkReply::httpUploadPerformance()
+{
+ enum {UploadSize = 1000*1024*1024}; // 1000 MB
+ ThreadedDataReaderHttpServer reader;
+ FixedSizeDataGenerator generator(UploadSize);
+
+ QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1"));
+ request.setHeader(QNetworkRequest::ContentLengthHeader,UploadSize);
+
+ QNetworkReplyPtr reply = manager.put(request, &generator);
+
+ connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
+
+ QTime time;
+ generator.start();
+ time.start();
+ QTestEventLoop::instance().enterLoop(40);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ qint64 elapsed = time.elapsed();
+ qWarning() << "tst_QNetworkReply::httpUploadPerformance" << elapsed << "msec, "
+ << ((UploadSize/1024.0)/(elapsed/1000.0)) << " kB/sec";
+
+ reader.exit();
+ reader.wait(3000);
+}
+
+
void tst_QNetworkReply::performanceControlRate()
{
// this is a control comparison for the other two above
@@ -2659,7 +3258,7 @@ void tst_QNetworkReply::performanceControlRate()
sender.wait();
qint64 receivedBytes = reader.totalBytes;
- qDebug() << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and"
+ qDebug() << "tst_QNetworkReply::performanceControlRate" << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and"
<< elapsedTime << "ms";
}
@@ -2696,6 +3295,7 @@ void tst_QNetworkReply::downloadProgress()
QByteArray data(128, 'a');
QTcpSocket *sender = server.nextPendingConnection();
+ QVERIFY(sender);
QFETCH(int, loopCount);
for (int i = 1; i <= loopCount; ++i) {
@@ -3137,5 +3737,34 @@ void tst_QNetworkReply::authorizationError()
QCOMPARE(QString(reply->readAll()), httpBody);
}
+void tst_QNetworkReply::httpConnectionCount()
+{
+ QTcpServer server;
+ QVERIFY(server.listen());
+ QCoreApplication::instance()->processEvents();
+
+ for (int i = 0; i < 10; i++) {
+ QNetworkRequest request (QUrl("http://127.0.0.1:" + QString::number(server.serverPort()) + "/" + QString::number(i)));
+ QNetworkReply* reply = manager.get(request);
+ reply->setParent(this);
+ }
+
+ int pendingConnectionCount = 0;
+ QTime time;
+ time.start();
+
+ while(pendingConnectionCount != 6) {
+ QCoreApplication::instance()->processEvents();
+ while (server.nextPendingConnection())
+ pendingConnectionCount++;
+
+ // at max. wait 10 sec
+ if (time.elapsed() > 10000)
+ break;
+ }
+
+ QCOMPARE(pendingConnectionCount, 6);
+}
+
QTEST_MAIN(tst_QNetworkReply)
#include "tst_qnetworkreply.moc"
diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp
index ada4fcb..b7bc732 100644
--- a/tests/auto/qobject/tst_qobject.cpp
+++ b/tests/auto/qobject/tst_qobject.cpp
@@ -106,6 +106,7 @@ private slots:
void childDeletesItsSibling();
void dynamicProperties();
void floatProperty();
+ void qrealProperty();
void property();
void recursiveSignalEmission();
void blockingQueuedConnection();
@@ -116,6 +117,7 @@ private slots:
void dumpObjectInfo();
void connectToSender();
void qobjectConstCast();
+ void uniqConnection();
protected:
};
@@ -204,12 +206,20 @@ public:
sequence_slot3 = 0;
sequence_slot2 = 0;
sequence_slot1 = 0;
+ count_slot1 = 0;
+ count_slot2 = 0;
+ count_slot3 = 0;
+ count_slot4 = 0;
}
int sequence_slot1;
int sequence_slot2;
int sequence_slot3;
int sequence_slot4;
+ int count_slot1;
+ int count_slot2;
+ int count_slot3;
+ int count_slot4;
bool called(int slot) {
switch (slot) {
@@ -224,10 +234,10 @@ public:
static int sequence;
public slots:
- void slot1() { sequence_slot1 = ++sequence; }
- void slot2() { sequence_slot2 = ++sequence; }
- void slot3() { sequence_slot3 = ++sequence; }
- void slot4() { sequence_slot4 = ++sequence; }
+ void slot1() { sequence_slot1 = ++sequence; count_slot1++; }
+ void slot2() { sequence_slot2 = ++sequence; count_slot2++; }
+ void slot3() { sequence_slot3 = ++sequence; count_slot3++; }
+ void slot4() { sequence_slot4 = ++sequence; count_slot4++; }
};
@@ -1104,6 +1114,7 @@ class PropertyObject : public QObject
Q_PROPERTY(QVariant variant READ variant WRITE setVariant)
Q_PROPERTY(CustomType* custom READ custom WRITE setCustom)
Q_PROPERTY(float myFloat READ myFloat WRITE setMyFloat)
+ Q_PROPERTY(qreal myQReal READ myQReal WRITE setMyQReal)
public:
enum Alpha {
@@ -1139,6 +1150,9 @@ public:
void setMyFloat(float value) { m_float = value; }
inline float myFloat() const { return m_float; }
+ void setMyQReal(qreal value) { m_qreal = value; }
+ qreal myQReal() const { return m_qreal; }
+
private:
Alpha m_alpha;
Priority m_priority;
@@ -1147,6 +1161,7 @@ private:
QVariant m_variant;
CustomType *m_custom;
float m_float;
+ qreal m_qreal;
};
Q_DECLARE_METATYPE(PropertyObject::Priority)
@@ -2349,6 +2364,27 @@ void tst_QObject::floatProperty()
QVERIFY(qVariantValue<float>(v) == 128.0f);
}
+void tst_QObject::qrealProperty()
+{
+ PropertyObject obj;
+ const int idx = obj.metaObject()->indexOfProperty("myQReal");
+ QVERIFY(idx > 0);
+ QMetaProperty prop = obj.metaObject()->property(idx);
+ QVERIFY(prop.isValid());
+ QVERIFY(prop.type() == uint(QMetaType::type("qreal")));
+ QVERIFY(!prop.write(&obj, QVariant("Hello")));
+
+ QVERIFY(prop.write(&obj, qVariantFromValue(128.0f)));
+ QVariant v = prop.read(&obj);
+ QCOMPARE(v.userType(), qMetaTypeId<qreal>());
+ QVERIFY(qVariantValue<qreal>(v) == 128.0);
+
+ QVERIFY(prop.write(&obj, qVariantFromValue(double(127))));
+ v = prop.read(&obj);
+ QCOMPARE(v.userType(), qMetaTypeId<qreal>());
+ QVERIFY(qVariantValue<qreal>(v) == 127.0);
+}
+
class DynamicPropertyObject : public PropertyObject
{
public:
@@ -2796,5 +2832,69 @@ void tst_QObject::qobjectConstCast()
QVERIFY(qobject_cast<const FooObject *>(cptr));
}
+void tst_QObject::uniqConnection()
+{
+ SenderObject *s = new SenderObject;
+ ReceiverObject *r1 = new ReceiverObject;
+ ReceiverObject *r2 = new ReceiverObject;
+ r1->reset();
+ r2->reset();
+ ReceiverObject::sequence = 0;
+
+ QVERIFY( connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) , Qt::UniqueConnection) );
+ QVERIFY( connect( s, SIGNAL( signal1() ), r2, SLOT( slot1() ) , Qt::UniqueConnection) );
+ QVERIFY( connect( s, SIGNAL( signal1() ), r1, SLOT( slot3() ) , Qt::UniqueConnection) );
+ QVERIFY( connect( s, SIGNAL( signal3() ), r1, SLOT( slot3() ) , Qt::UniqueConnection) );
+
+ s->emitSignal1();
+ s->emitSignal2();
+ s->emitSignal3();
+ s->emitSignal4();
+
+ QCOMPARE( r1->count_slot1, 1 );
+ QCOMPARE( r1->count_slot2, 0 );
+ QCOMPARE( r1->count_slot3, 2 );
+ QCOMPARE( r1->count_slot4, 0 );
+ QCOMPARE( r2->count_slot1, 1 );
+ QCOMPARE( r2->count_slot2, 0 );
+ QCOMPARE( r2->count_slot3, 0 );
+ QCOMPARE( r2->count_slot4, 0 );
+ QCOMPARE( r1->sequence_slot1, 1 );
+ QCOMPARE( r2->sequence_slot1, 2 );
+ QCOMPARE( r1->sequence_slot3, 4 );
+
+ r1->reset();
+ r2->reset();
+ ReceiverObject::sequence = 0;
+
+ QVERIFY( connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) , Qt::UniqueConnection) );
+ QVERIFY( connect( s, SIGNAL( signal4() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
+ QVERIFY(!connect( s, SIGNAL( signal4() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
+ QVERIFY( connect( s, SIGNAL( signal1() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
+ QVERIFY(!connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) , Qt::UniqueConnection) );
+
+ s->emitSignal4();
+ QCOMPARE( r1->count_slot4, 1 );
+ QCOMPARE( r2->count_slot4, 1 );
+ QCOMPARE( r1->sequence_slot4, 1 );
+ QCOMPARE( r2->sequence_slot4, 2 );
+
+ r1->reset();
+ r2->reset();
+ ReceiverObject::sequence = 0;
+
+ connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) );
+
+ s->emitSignal4();
+ QCOMPARE( r1->count_slot4, 2 );
+ QCOMPARE( r2->count_slot4, 1 );
+ QCOMPARE( r1->sequence_slot4, 3 );
+ QCOMPARE( r2->sequence_slot4, 2 );
+
+ delete s;
+ delete r1;
+ delete r2;
+}
+
QTEST_MAIN(tst_QObject)
#include "tst_qobject.moc"
diff --git a/tests/auto/qobjectrace/tst_qobjectrace.cpp b/tests/auto/qobjectrace/tst_qobjectrace.cpp
index fcfd528..aa80534 100644
--- a/tests/auto/qobjectrace/tst_qobjectrace.cpp
+++ b/tests/auto/qobjectrace/tst_qobjectrace.cpp
@@ -43,6 +43,7 @@
#include <QtCore>
#include <QtTest/QtTest>
+
enum { OneMinute = 60 * 1000, TwoMinutes = OneMinute * 2 };
class tst_QObjectRace: public QObject
@@ -70,12 +71,18 @@ public:
public slots:
void theSlot()
{
- enum { step = 1000 };
+ enum { step = 35 };
if ((++count % step) == 0) {
QThread *nextThread = threads.at((count / step) % threads.size());
moveToThread(nextThread);
}
}
+
+ void destroSlot() {
+ emit theSignal();
+ }
+signals:
+ void theSignal();
};
class RaceThread : public QThread
@@ -120,6 +127,10 @@ private slots:
if (stopWatch.elapsed() >= OneMinute / 2)
#endif
quit();
+
+ QObject o;
+ connect(&o, SIGNAL(destroyed()) , object, SLOT(destroSlot()));
+ connect(object, SIGNAL(destroyed()) , &o, SLOT(deleteLater()));
}
};
@@ -138,10 +149,17 @@ void tst_QObjectRace::moveToThreadRace()
for (int i = 0; i < ThreadCount; ++i)
threads[i]->start();
- QVERIFY(threads[0]->wait(TwoMinutes));
+
+ while(!threads[0]->isFinished()) {
+ QPointer<RaceObject> foo (object);
+ QObject o;
+ connect(&o, SIGNAL(destroyed()) , object, SLOT(destroSlot()));
+ connect(object, SIGNAL(destroyed()) , &o, SLOT(deleteLater()));
+ QTest::qWait(10);
+ }
// the other threads should finish pretty quickly now
for (int i = 1; i < ThreadCount; ++i)
- QVERIFY(threads[i]->wait(30000));
+ QVERIFY(threads[i]->wait(300));
for (int i = 0; i < ThreadCount; ++i)
delete threads[i];
diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp
index 740cfb1..1fad8b5 100644
--- a/tests/auto/qpainter/tst_qpainter.cpp
+++ b/tests/auto/qpainter/tst_qpainter.cpp
@@ -231,6 +231,7 @@ private slots:
void extendedBlendModes();
void zeroOpacity();
+ void clippingBug();
private:
void fillData();
@@ -4197,5 +4198,28 @@ void tst_QPainter::zeroOpacity()
QCOMPARE(target.pixel(0, 0), 0xff000000);
}
+void tst_QPainter::clippingBug()
+{
+ QImage img(32, 32, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+
+ QImage expected = img;
+ QPainter p(&expected);
+ p.fillRect(1, 1, 30, 30, Qt::red);
+ p.end();
+
+ QPainterPath path;
+ path.addRect(1, 1, 30, 30);
+ path.addRect(1, 1, 30, 30);
+ path.addRect(1, 1, 30, 30);
+
+ p.begin(&img);
+ p.setClipPath(path);
+ p.fillRect(0, 0, 32, 32, Qt::red);
+ p.end();
+
+ QCOMPARE(img, expected);
+}
+
QTEST_MAIN(tst_QPainter)
#include "tst_qpainter.moc"
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/qparallelanimationgroup/qparallelanimationgroup.pro b/tests/auto/qparallelanimationgroup/qparallelanimationgroup.pro
new file mode 100644
index 0000000..f2cacd3
--- /dev/null
+++ b/tests/auto/qparallelanimationgroup/qparallelanimationgroup.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT = core gui
+SOURCES += tst_qparallelanimationgroup.cpp
+
+
diff --git a/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp b/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp
new file mode 100644
index 0000000..f2ab57a
--- /dev/null
+++ b/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp
@@ -0,0 +1,834 @@
+/****************************************************************************
+**
+** 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 <QtTest/QtTest>
+
+#include <QtCore/qparallelanimationgroup.h>
+
+//TESTED_CLASS=QParallelAnimationGroup
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QAbstractAnimation::State)
+
+class tst_QParallelAnimationGroup : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QParallelAnimationGroup();
+ virtual ~tst_QParallelAnimationGroup();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private slots:
+ void construction();
+ void setCurrentTime();
+ void clearGroup();
+ void propagateGroupUpdateToChildren();
+ void updateChildrenWithRunningGroup();
+ void deleteChildrenWithRunningGroup();
+ void startChildrenWithStoppedGroup();
+ void stopGroupWithRunningChild();
+ void startGroupWithRunningChild();
+ void zeroDurationAnimation();
+ void stopUncontrolledAnimations();
+ void loopCount_data();
+ void loopCount();
+ void autoAdd();
+};
+
+tst_QParallelAnimationGroup::tst_QParallelAnimationGroup()
+{
+}
+
+tst_QParallelAnimationGroup::~tst_QParallelAnimationGroup()
+{
+}
+
+void tst_QParallelAnimationGroup::init()
+{
+ qRegisterMetaType<QAbstractAnimation::State>("QAbstractAnimation::State");
+}
+
+void tst_QParallelAnimationGroup::cleanup()
+{
+}
+
+void tst_QParallelAnimationGroup::construction()
+{
+ QParallelAnimationGroup animationgroup;
+}
+
+class AnimationObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+public:
+ AnimationObject(int startValue = 0)
+ : v(startValue)
+ { }
+
+ int value() const { return v; }
+ void setValue(int value) { v = value; }
+
+ int v;
+};
+
+class TestAnimation : public QVariantAnimation
+{
+ Q_OBJECT
+public:
+ virtual void updateCurrentValue(const QVariant &value) { Q_UNUSED(value)};
+ virtual void updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+ {
+ Q_UNUSED(oldState)
+ Q_UNUSED(newState)
+ };
+};
+
+class TestAnimation2 : public QVariantAnimation
+{
+ Q_OBJECT
+public:
+ TestAnimation2(QAbstractAnimation *animation) : QVariantAnimation(animation) {}
+ TestAnimation2(int duration, QAbstractAnimation *animation) : QVariantAnimation(animation), m_duration(duration) {}
+
+ virtual void updateCurrentValue(const QVariant &value) { Q_UNUSED(value)};
+ virtual void updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+ {
+ Q_UNUSED(oldState)
+ Q_UNUSED(newState)
+ };
+
+ virtual int duration() const {
+ return m_duration;
+ }
+private:
+ int m_duration;
+};
+
+class UncontrolledAnimation : public QPropertyAnimation
+{
+ Q_OBJECT
+public:
+ UncontrolledAnimation(QObject *target, const QByteArray &propertyName, QObject *parent = 0)
+ : QPropertyAnimation(target, propertyName, parent), id(0)
+ {
+ setDuration(250);
+ }
+
+ int duration() const { return -1; /* not time driven */ }
+
+protected:
+ void timerEvent(QTimerEvent *event)
+ {
+ if (event->timerId() == id)
+ stop();
+ }
+
+ void updateRunning(bool running)
+ {
+ if (running) {
+ id = startTimer(500);
+ } else {
+ killTimer(id);
+ id = 0;
+ }
+ }
+
+private:
+ int id;
+};
+
+void tst_QParallelAnimationGroup::setCurrentTime()
+{
+ AnimationObject p_o1;
+ AnimationObject p_o2;
+ AnimationObject p_o3;
+ AnimationObject t_o1;
+ AnimationObject t_o2;
+
+ // parallel operating on different object/properties
+ QAnimationGroup *parallel = new QParallelAnimationGroup();
+ QVariantAnimation *a1_p_o1 = new QPropertyAnimation(&p_o1, "value");
+ QVariantAnimation *a1_p_o2 = new QPropertyAnimation(&p_o2, "value");
+ QVariantAnimation *a1_p_o3 = new QPropertyAnimation(&p_o3, "value");
+ a1_p_o2->setLoopCount(3);
+ parallel->addAnimation(a1_p_o1);
+ parallel->addAnimation(a1_p_o2);
+ parallel->addAnimation(a1_p_o3);
+
+ UncontrolledAnimation *notTimeDriven = new UncontrolledAnimation(&t_o1, "value");
+ QCOMPARE(notTimeDriven->totalDuration(), -1);
+
+ QVariantAnimation *loopsForever = new QPropertyAnimation(&t_o2, "value");
+ loopsForever->setLoopCount(-1);
+ QCOMPARE(loopsForever->totalDuration(), -1);
+
+ QParallelAnimationGroup group;
+ group.addAnimation(parallel);
+ group.addAnimation(notTimeDriven);
+ group.addAnimation(loopsForever);
+
+ // Current time = 1
+ group.setCurrentTime(1);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(parallel->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_p_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_p_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_p_o3->state(), QAnimationGroup::Stopped);
+ QCOMPARE(notTimeDriven->state(), QAnimationGroup::Stopped);
+ QCOMPARE(loopsForever->state(), QAnimationGroup::Stopped);
+
+ QCOMPARE(group.currentTime(), 1);
+ QCOMPARE(a1_p_o1->currentTime(), 1);
+ QCOMPARE(a1_p_o2->currentTime(), 1);
+ QCOMPARE(a1_p_o3->currentTime(), 1);
+ QCOMPARE(notTimeDriven->currentTime(), 1);
+ QCOMPARE(loopsForever->currentTime(), 1);
+
+ // Current time = 250
+ group.setCurrentTime(250);
+ QCOMPARE(group.currentTime(), 250);
+ QCOMPARE(a1_p_o1->currentTime(), 250);
+ QCOMPARE(a1_p_o2->currentTime(), 0);
+ QCOMPARE(a1_p_o2->currentLoop(), 1);
+ QCOMPARE(a1_p_o3->currentTime(), 250);
+ QCOMPARE(notTimeDriven->currentTime(), 250);
+ QCOMPARE(loopsForever->currentTime(), 0);
+ QCOMPARE(loopsForever->currentLoop(), 1);
+
+ // Current time = 251
+ group.setCurrentTime(251);
+ QCOMPARE(group.currentTime(), 251);
+ QCOMPARE(a1_p_o1->currentTime(), 250);
+ QCOMPARE(a1_p_o2->currentTime(), 1);
+ QCOMPARE(a1_p_o2->currentLoop(), 1);
+ QCOMPARE(a1_p_o3->currentTime(), 250);
+ QCOMPARE(notTimeDriven->currentTime(), 251);
+ QCOMPARE(loopsForever->currentTime(), 1);
+}
+
+void tst_QParallelAnimationGroup::clearGroup()
+{
+ QParallelAnimationGroup group;
+
+ for (int i = 0; i < 10; ++i) {
+ new QParallelAnimationGroup(&group);
+ }
+
+ QCOMPARE(group.animationCount(), 10);
+
+ int count = group.animationCount();
+ QPointer<QAbstractAnimation> *children = new QPointer<QAbstractAnimation>[count];
+ for (int i = 0; i < count; ++i) {
+ QVERIFY(group.animationAt(i) != 0);
+ children[i] = group.animationAt(i);
+ }
+
+ group.clearAnimations();
+ QCOMPARE(group.animationCount(), 0);
+ QCOMPARE(group.currentTime(), 0);
+ for (int i = 0; i < count; ++i)
+ QCOMPARE(children[i], QPointer<QAbstractAnimation>());
+
+ delete[] children;
+}
+
+void tst_QParallelAnimationGroup::propagateGroupUpdateToChildren()
+{
+ // this test verifies if group state changes are updating its children correctly
+ QParallelAnimationGroup group;
+
+ QObject o;
+ o.setProperty("ole", 42);
+ QCOMPARE(o.property("ole").toInt(), 42);
+
+ QPropertyAnimation anim1(&o, "ole");
+ anim1.setEndValue(43);
+ anim1.setDuration(100);
+ QVERIFY(!anim1.currentValue().isValid());
+ QCOMPARE(anim1.currentValue().toInt(), 0);
+ QCOMPARE(o.property("ole").toInt(), 42);
+
+ TestAnimation anim2;
+ anim2.setStartValue(0);
+ anim2.setEndValue(100);
+ anim2.setDuration(200);
+
+ QVERIFY(anim2.currentValue().isValid());
+ QCOMPARE(anim2.currentValue().toInt(), 0);
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+
+ group.addAnimation(&anim1);
+ group.addAnimation(&anim2);
+
+ group.start();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim1.state(), QAnimationGroup::Running);
+ QCOMPARE(anim2.state(), QAnimationGroup::Running);
+
+ group.pause();
+
+ QCOMPARE(group.state(), QAnimationGroup::Paused);
+ QCOMPARE(anim1.state(), QAnimationGroup::Paused);
+ QCOMPARE(anim2.state(), QAnimationGroup::Paused);
+
+ group.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+}
+
+void tst_QParallelAnimationGroup::updateChildrenWithRunningGroup()
+{
+ // assert that its possible to modify a child's state directly while their group is running
+ QParallelAnimationGroup group;
+
+ TestAnimation anim;
+ anim.setStartValue(0);
+ anim.setEndValue(100);
+ anim.setDuration(200);
+
+ QSignalSpy groupStateChangedSpy(&group, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy childStateChangedSpy(&anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ QCOMPARE(groupStateChangedSpy.count(), 0);
+ QCOMPARE(childStateChangedSpy.count(), 0);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim.state(), QAnimationGroup::Stopped);
+
+ group.addAnimation(&anim);
+
+ group.start();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim.state(), QAnimationGroup::Running);
+
+ QCOMPARE(groupStateChangedSpy.count(), 1);
+ QCOMPARE(childStateChangedSpy.count(), 1);
+
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(groupStateChangedSpy.at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(childStateChangedSpy.at(0).at(1)),
+ QAnimationGroup::Running);
+
+ // starting directly a running child will not have any effect
+ anim.start();
+
+ QCOMPARE(groupStateChangedSpy.count(), 1);
+ QCOMPARE(childStateChangedSpy.count(), 1);
+
+ anim.pause();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim.state(), QAnimationGroup::Paused);
+
+ // in the animation stops directly, the group will still be running
+ anim.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim.state(), QAnimationGroup::Stopped);
+}
+
+void tst_QParallelAnimationGroup::deleteChildrenWithRunningGroup()
+{
+ // test if children can be activated when their group is stopped
+ QParallelAnimationGroup group;
+
+ QVariantAnimation *anim1 = new TestAnimation;
+ anim1->setStartValue(0);
+ anim1->setEndValue(100);
+ anim1->setDuration(200);
+ group.addAnimation(anim1);
+
+ QCOMPARE(group.duration(), anim1->duration());
+
+ group.start();
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim1->state(), QAnimationGroup::Running);
+
+ QTest::qWait(50);
+ QVERIFY(group.currentTime() > 0);
+
+ delete anim1;
+ QVERIFY(group.animationCount() == 0);
+ QCOMPARE(group.duration(), 0);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(group.currentTime(), 0); //that's the invariant
+}
+
+void tst_QParallelAnimationGroup::startChildrenWithStoppedGroup()
+{
+ // test if children can be activated when their group is stopped
+ QParallelAnimationGroup group;
+
+ TestAnimation anim1;
+ anim1.setStartValue(0);
+ anim1.setEndValue(100);
+ anim1.setDuration(200);
+
+ TestAnimation anim2;
+ anim2.setStartValue(0);
+ anim2.setEndValue(100);
+ anim2.setDuration(200);
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+
+ group.addAnimation(&anim1);
+ group.addAnimation(&anim2);
+
+ group.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+
+ anim1.start();
+ anim2.start();
+ anim2.pause();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Running);
+ QCOMPARE(anim2.state(), QAnimationGroup::Paused);
+}
+
+void tst_QParallelAnimationGroup::stopGroupWithRunningChild()
+{
+ // children that started independently will not be affected by a group stop
+ QParallelAnimationGroup group;
+
+ TestAnimation anim1;
+ anim1.setStartValue(0);
+ anim1.setEndValue(100);
+ anim1.setDuration(200);
+
+ TestAnimation anim2;
+ anim2.setStartValue(0);
+ anim2.setEndValue(100);
+ anim2.setDuration(200);
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+
+ group.addAnimation(&anim1);
+ group.addAnimation(&anim2);
+
+ anim1.start();
+ anim2.start();
+ anim2.pause();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Running);
+ QCOMPARE(anim2.state(), QAnimationGroup::Paused);
+
+ group.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Running);
+ QCOMPARE(anim2.state(), QAnimationGroup::Paused);
+
+ anim1.stop();
+ anim2.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+}
+
+void tst_QParallelAnimationGroup::startGroupWithRunningChild()
+{
+ // as the group has precedence over its children, starting a group will restart all the children
+ QParallelAnimationGroup group;
+
+ TestAnimation anim1;
+ anim1.setStartValue(0);
+ anim1.setEndValue(100);
+ anim1.setDuration(200);
+
+ TestAnimation anim2;
+ anim2.setStartValue(0);
+ anim2.setEndValue(100);
+ anim2.setDuration(200);
+
+ QSignalSpy stateChangedSpy1(&anim1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy stateChangedSpy2(&anim2, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ QCOMPARE(stateChangedSpy1.count(), 0);
+ QCOMPARE(stateChangedSpy2.count(), 0);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+
+ group.addAnimation(&anim1);
+ group.addAnimation(&anim2);
+
+ anim1.start();
+ anim2.start();
+ anim2.pause();
+
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy1.at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy2.at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy2.at(1).at(1)),
+ QAnimationGroup::Paused);
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Running);
+ QCOMPARE(anim2.state(), QAnimationGroup::Paused);
+
+ group.start();
+
+ QCOMPARE(stateChangedSpy1.count(), 3);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy1.at(1).at(1)),
+ QAnimationGroup::Stopped);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy1.at(2).at(1)),
+ QAnimationGroup::Running);
+
+ QCOMPARE(stateChangedSpy2.count(), 4);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy2.at(2).at(1)),
+ QAnimationGroup::Stopped);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy2.at(3).at(1)),
+ QAnimationGroup::Running);
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim1.state(), QAnimationGroup::Running);
+ QCOMPARE(anim2.state(), QAnimationGroup::Running);
+}
+
+void tst_QParallelAnimationGroup::zeroDurationAnimation()
+{
+ QParallelAnimationGroup group;
+
+ TestAnimation anim1;
+ anim1.setStartValue(0);
+ anim1.setEndValue(100);
+ anim1.setDuration(0);
+
+ TestAnimation anim2;
+ anim2.setStartValue(0);
+ anim2.setEndValue(100);
+ anim2.setDuration(100);
+
+ QSignalSpy stateChangedSpy1(&anim1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy finishedSpy1(&anim1, SIGNAL(finished()));
+
+ QSignalSpy stateChangedSpy2(&anim2, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy finishedSpy2(&anim2, SIGNAL(finished()));
+
+ group.addAnimation(&anim1);
+ group.addAnimation(&anim2);
+ QCOMPARE(stateChangedSpy1.count(), 0);
+ group.start();
+ QCOMPARE(stateChangedSpy1.count(), 2);
+ QCOMPARE(finishedSpy1.count(), 1);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy1.at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy1.at(1).at(1)),
+ QAnimationGroup::Stopped);
+
+ QCOMPARE(stateChangedSpy2.count(), 1);
+ QCOMPARE(finishedSpy2.count(), 0);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy1.at(0).at(1)),
+ QAnimationGroup::Running);
+
+
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Running);
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+
+
+ group.stop();
+ group.setLoopCount(4);
+ stateChangedSpy1.clear();
+ stateChangedSpy2.clear();
+
+ group.start();
+ QCOMPARE(stateChangedSpy1.count(), 2);
+ QCOMPARE(stateChangedSpy2.count(), 1);
+ group.setCurrentTime(50);
+ QCOMPARE(stateChangedSpy1.count(), 2);
+ QCOMPARE(stateChangedSpy2.count(), 1);
+ group.setCurrentTime(150);
+ QCOMPARE(stateChangedSpy1.count(), 4);
+ QCOMPARE(stateChangedSpy2.count(), 3);
+ group.setCurrentTime(50);
+ QCOMPARE(stateChangedSpy1.count(), 6);
+ QCOMPARE(stateChangedSpy2.count(), 5);
+
+}
+
+void tst_QParallelAnimationGroup::stopUncontrolledAnimations()
+{
+ QParallelAnimationGroup group;
+
+ TestAnimation anim1;
+ anim1.setStartValue(0);
+ anim1.setEndValue(100);
+ anim1.setDuration(0);
+
+ AnimationObject o1;
+ UncontrolledAnimation notTimeDriven(&o1, "value");
+ QCOMPARE(notTimeDriven.totalDuration(), -1);
+
+ TestAnimation loopsForever;
+ loopsForever.setStartValue(0);
+ loopsForever.setEndValue(100);
+ loopsForever.setDuration(100);
+ loopsForever.setLoopCount(-1);
+
+ QSignalSpy stateChangedSpy(&anim1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ group.addAnimation(&anim1);
+ group.addAnimation(&notTimeDriven);
+ group.addAnimation(&loopsForever);
+
+ group.start();
+
+ QCOMPARE(stateChangedSpy.count(), 2);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy.at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy.at(1).at(1)),
+ QAnimationGroup::Stopped);
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(notTimeDriven.state(), QAnimationGroup::Running);
+ QCOMPARE(loopsForever.state(), QAnimationGroup::Running);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+
+ notTimeDriven.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(notTimeDriven.state(), QAnimationGroup::Stopped);
+ QCOMPARE(loopsForever.state(), QAnimationGroup::Running);
+
+ loopsForever.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(notTimeDriven.state(), QAnimationGroup::Stopped);
+ QCOMPARE(loopsForever.state(), QAnimationGroup::Stopped);
+}
+
+struct AnimState {
+ AnimState(int time = -1) : time(time), state(-1) {}
+ AnimState(int time, int state) : time(time), state(state) {}
+ int time;
+ int state;
+};
+
+#define Running QAbstractAnimation::Running
+#define Stopped QAbstractAnimation::Stopped
+
+Q_DECLARE_METATYPE(AnimState)
+void tst_QParallelAnimationGroup::loopCount_data()
+{
+ QTest::addColumn<bool>("directionBackward");
+ QTest::addColumn<int>("setLoopCount");
+ QTest::addColumn<int>("initialGroupTime");
+ QTest::addColumn<int>("currentGroupTime");
+ QTest::addColumn<AnimState>("expected1");
+ QTest::addColumn<AnimState>("expected2");
+ QTest::addColumn<AnimState>("expected3");
+
+ // D U R A T I O N
+ // 100 60*2 0
+ // direction = Forward
+ QTest::newRow("50") << false << 3 << 0 << 50 << AnimState( 50, Running) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("100") << false << 3 << 0 << 100 << AnimState(100 ) << AnimState( 40, Running) << AnimState( 0, Stopped);
+ QTest::newRow("110") << false << 3 << 0 << 110 << AnimState(100, Stopped) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("120") << false << 3 << 0 << 120 << AnimState( 0, Running) << AnimState( 0, Running) << AnimState( 0, Stopped);
+
+ QTest::newRow("170") << false << 3 << 0 << 170 << AnimState( 50, Running) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("220") << false << 3 << 0 << 220 << AnimState(100 ) << AnimState( 40, Running) << AnimState( 0, Stopped);
+ QTest::newRow("230") << false << 3 << 0 << 230 << AnimState(100, Stopped) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("240") << false << 3 << 0 << 240 << AnimState( 0, Running) << AnimState( 0, Running) << AnimState( 0, Stopped);
+
+ QTest::newRow("290") << false << 3 << 0 << 290 << AnimState( 50, Running) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("340") << false << 3 << 0 << 340 << AnimState(100 ) << AnimState( 40, Running) << AnimState( 0, Stopped);
+ QTest::newRow("350") << false << 3 << 0 << 350 << AnimState(100, Stopped) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("360") << false << 3 << 0 << 360 << AnimState(100, Stopped) << AnimState( 60 ) << AnimState( 0, Stopped);
+
+ QTest::newRow("410") << false << 3 << 0 << 410 << AnimState(100, Stopped) << AnimState( 60, Stopped) << AnimState( 0, Stopped);
+ QTest::newRow("460") << false << 3 << 0 << 460 << AnimState(100, Stopped) << AnimState( 60, Stopped) << AnimState( 0, Stopped);
+ QTest::newRow("470") << false << 3 << 0 << 470 << AnimState(100, Stopped) << AnimState( 60, Stopped) << AnimState( 0, Stopped);
+ QTest::newRow("480") << false << 3 << 0 << 480 << AnimState(100, Stopped) << AnimState( 60, Stopped) << AnimState( 0, Stopped);
+
+ // direction = Forward, rewind
+ QTest::newRow("120-110") << false << 3 << 120 << 110 << AnimState( 0, Stopped) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("120-50") << false << 3 << 120 << 50 << AnimState( 50, Running) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("120-0") << false << 3 << 120 << 0 << AnimState( 0, Running) << AnimState( 0, Running) << AnimState( 0, Stopped);
+ QTest::newRow("300-110") << false << 3 << 300 << 110 << AnimState( 0, Stopped) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("300-50") << false << 3 << 300 << 50 << AnimState( 50, Running) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("300-0") << false << 3 << 300 << 0 << AnimState( 0, Running) << AnimState( 0, Running) << AnimState( 0, Stopped);
+ QTest::newRow("115-105") << false << 3 << 115 << 105 << AnimState( 42, Stopped) << AnimState( 45, Running) << AnimState( 0, Stopped);
+
+ // direction = Backward
+ QTest::newRow("b120-120") << true << 3 << 120 << 120 << AnimState( 42, Stopped) << AnimState( 60, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b120-110") << true << 3 << 120 << 110 << AnimState( 42, Stopped) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b120-100") << true << 3 << 120 << 100 << AnimState(100, Running) << AnimState( 40, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b120-50") << true << 3 << 120 << 50 << AnimState( 50, Running) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b120-0") << true << 3 << 120 << 0 << AnimState( 0, Stopped) << AnimState( 0, Stopped) << AnimState( 0, Stopped);
+ QTest::newRow("b360-170") << true << 3 << 360 << 170 << AnimState( 50, Running) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b360-220") << true << 3 << 360 << 220 << AnimState(100, Running) << AnimState( 40, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b360-210") << true << 3 << 360 << 210 << AnimState( 90, Running) << AnimState( 30, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b360-120") << true << 3 << 360 << 120 << AnimState( 0, Stopped) << AnimState( 60, Running) << AnimState( 0, Stopped);
+
+ // rewind, direction = Backward
+ QTest::newRow("b50-110") << true << 3 << 50 << 110 << AnimState(100, Stopped) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b50-120") << true << 3 << 50 << 120 << AnimState(100, Stopped) << AnimState( 60, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b50-140") << true << 3 << 50 << 140 << AnimState( 20, Running) << AnimState( 20, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b50-240") << true << 3 << 50 << 240 << AnimState(100, Stopped) << AnimState( 60, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b50-260") << true << 3 << 50 << 260 << AnimState( 20, Running) << AnimState( 20, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b50-350") << true << 3 << 50 << 350 << AnimState(100, Stopped) << AnimState( 50, Running) << AnimState( 0, Stopped);
+
+ // infinite looping
+ QTest::newRow("inf1220") << false << -1 << 0 << 1220 << AnimState( 20, Running) << AnimState( 20, Running) << AnimState( 0, Stopped);
+ QTest::newRow("inf1310") << false << -1 << 0 << 1310 << AnimState( 100, Stopped) << AnimState( 50, Running) << AnimState( 0, Stopped);
+ // infinite looping, direction = Backward (will only loop once)
+ QTest::newRow("b.inf120-120") << true << -1 << 120 << 120 << AnimState( 42, Stopped) << AnimState( 60, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b.inf120-20") << true << -1 << 120 << 20 << AnimState( 20, Running) << AnimState( 20, Running) << AnimState( 0, Stopped);
+ QTest::newRow("b.inf120-110") << true << -1 << 120 << 110 << AnimState( 42, Stopped) << AnimState( 50, Running) << AnimState( 0, Stopped);
+
+
+}
+
+void tst_QParallelAnimationGroup::loopCount()
+{
+ QFETCH(bool, directionBackward);
+ QFETCH(int, setLoopCount);
+ QFETCH(int, initialGroupTime);
+ QFETCH(int, currentGroupTime);
+ QFETCH(AnimState, expected1);
+ QFETCH(AnimState, expected2);
+ QFETCH(AnimState, expected3);
+
+ QParallelAnimationGroup group;
+
+ TestAnimation anim1;
+ anim1.setStartValue(0);
+ anim1.setEndValue(100);
+ anim1.setDuration(100);
+
+ TestAnimation anim2;
+ anim2.setStartValue(0);
+ anim2.setEndValue(100);
+ anim2.setDuration(60); //total 120
+ anim2.setLoopCount(2);
+
+ TestAnimation anim3;
+ anim3.setStartValue(0);
+ anim3.setEndValue(100);
+ anim3.setDuration(0);
+
+ group.addAnimation(&anim1);
+ group.addAnimation(&anim2);
+ group.addAnimation(&anim3);
+
+ group.setLoopCount(setLoopCount);
+ if (initialGroupTime >= 0)
+ group.setCurrentTime(initialGroupTime);
+ if (directionBackward)
+ group.setDirection(QAbstractAnimation::Backward);
+
+ group.start();
+ if (initialGroupTime >= 0)
+ group.setCurrentTime(initialGroupTime);
+
+ anim1.setCurrentTime(42); // 42 is "untouched"
+ anim2.setCurrentTime(42);
+
+ group.setCurrentTime(currentGroupTime);
+
+ QCOMPARE(anim1.currentTime(), expected1.time);
+ QCOMPARE(anim2.currentTime(), expected2.time);
+ QCOMPARE(anim3.currentTime(), expected3.time);
+
+ if (expected1.state >=0)
+ QCOMPARE(int(anim1.state()), expected1.state);
+ if (expected2.state >=0)
+ QCOMPARE(int(anim2.state()), expected2.state);
+ if (expected3.state >=0)
+ QCOMPARE(int(anim3.state()), expected3.state);
+
+}
+
+void tst_QParallelAnimationGroup::autoAdd()
+{
+ QParallelAnimationGroup group;
+ QCOMPARE(group.duration(), 0);
+ TestAnimation2 *test = new TestAnimation2(250, &group); // 0, duration = 250;
+ QCOMPARE(test->group(), &group);
+ QCOMPARE(test->duration(), 250);
+ QCOMPARE(group.duration(), 250);
+
+ test = new TestAnimation2(750, &group); // 1
+ QCOMPARE(test->group(), &group);
+ QCOMPARE(group.duration(), 750);
+ test = new TestAnimation2(500, &group); // 2
+ QCOMPARE(test->group(), &group);
+ QCOMPARE(group.duration(), 750);
+
+ delete group.animationAt(1); // remove the one with duration = 750
+ QCOMPARE(group.duration(), 500);
+
+ delete group.animationAt(1); // remove the one with duration = 500
+ QCOMPARE(group.duration(), 250);
+
+ test = static_cast<TestAnimation2*>(group.animationAt(0));
+ test->setParent(0); // remove the last one (with duration = 250)
+ QCOMPARE(test->group(), static_cast<QAnimationGroup*>(0));
+ QCOMPARE(group.duration(), 0);
+}
+
+QTEST_MAIN(tst_QParallelAnimationGroup)
+#include "tst_qparallelanimationgroup.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 c992f6e..68d7141 100644
--- a/tests/auto/qpixmap/qpixmap.pro
+++ b/tests/auto/qpixmap/qpixmap.pro
@@ -19,3 +19,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 9f73e34..404b478 100644
--- a/tests/auto/qpixmap/tst_qpixmap.cpp
+++ b/tests/auto/qpixmap/tst_qpixmap.cpp
@@ -48,6 +48,8 @@
#include <qdesktopwidget.h>
#include <qpaintengine.h>
+#include <private/qpixmapdata_p.h>
+
#include <QSet>
#ifdef Q_WS_WIN
@@ -98,6 +100,9 @@ private slots:
void testMetrics();
+ void scroll_data();
+ void scroll();
+
void fill_data();
void fill();
void fill_transparent();
@@ -152,6 +157,38 @@ private slots:
void fromData();
};
+static bool lenientCompare(const QPixmap &actual, const QPixmap &expected)
+{
+ QImage expectedImage = expected.toImage().convertToFormat(QImage::Format_RGB32);
+ QImage actualImage = actual.toImage().convertToFormat(QImage::Format_RGB32);
+
+ if (expectedImage.size() != actualImage.size())
+ return false;
+
+ int size = actual.width() * actual.height();
+
+ QRgb *a = (QRgb *)actualImage.bits();
+ QRgb *e = (QRgb *)expectedImage.bits();
+ for (int i = 0; i < size; ++i) {
+ QColor ca(a[i]);
+ QColor ce(e[i]);
+
+ bool result = true;
+
+ if (qAbs(ca.red() - ce.red()) > 2)
+ result = false;
+ if (qAbs(ca.green() - ce.green()) > 2)
+ result = false;
+ if (qAbs(ca.blue() - ce.blue()) > 2)
+ result = false;
+
+ if (!result)
+ return false;
+ }
+
+ return true;
+}
+
Q_DECLARE_METATYPE(QImage)
Q_DECLARE_METATYPE(QPixmap)
Q_DECLARE_METATYPE(QMatrix)
@@ -214,7 +251,7 @@ void tst_QPixmap::setAlphaChannel()
pixmap.setAlphaChannel(alphaChannel);
#ifdef Q_WS_X11
- if (!pixmap.x11PictureHandle())
+ if (pixmap.pixmapData()->classId() == QPixmapData::X11Class && !pixmap.x11PictureHandle())
QSKIP("Requires XRender support", SkipAll);
#endif
@@ -273,7 +310,7 @@ void tst_QPixmap::fromImage()
const QPixmap pixmap = QPixmap::fromImage(image);
#ifdef Q_WS_X11
- if (!pixmap.x11PictureHandle())
+ if (pixmap.pixmapData()->classId() == QPixmapData::X11Class && !pixmap.x11PictureHandle())
QSKIP("Requires XRender support", SkipAll);
#endif
const QImage result = pixmap.toImage();
@@ -320,6 +357,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 = QPixmap::fromImage(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
+ QPixmap output(fileName);
+ QVERIFY(input.isNull() == output.isNull());
+ QVERIFY(lenientCompare(pixmap, output));
+ QCOMPARE(exp, exposed);
+}
+
void tst_QPixmap::fill_data()
{
QTest::addColumn<uint>("pixel");
@@ -385,7 +515,7 @@ void tst_QPixmap::fill()
pm = QPixmap(400, 400);
#if defined(Q_WS_X11)
- if (!bitmap && !pm.x11PictureHandle())
+ if (!bitmap && pm.pixmapData()->classId() == QPixmapData::X11Class && !pm.x11PictureHandle())
QSKIP("Requires XRender support", SkipSingle);
#endif
@@ -397,7 +527,7 @@ void tst_QPixmap::fill()
QImage image = pm.toImage();
if (bitmap && syscolor) {
int pixelindex = (pixel == Qt::color0) ? 0 : 1;
- QVERIFY(image.pixelIndex(0,0) == pixelindex);
+ QCOMPARE(image.pixelIndex(0,0), pixelindex);
}
QImage::Format format = compareColor.alpha() != 255
? QImage::Format_ARGB32
@@ -415,7 +545,7 @@ void tst_QPixmap::fill_transparent()
{
QPixmap pixmap(10, 10);
#ifdef Q_WS_X11
- if (!pixmap.x11PictureHandle())
+ if (pixmap.pixmapData()->classId() == QPixmapData::X11Class && !pixmap.x11PictureHandle())
QSKIP("Requires XRender support", SkipAll);
#endif
pixmap.fill(Qt::transparent);
@@ -535,7 +665,7 @@ void tst_QPixmap::testMetrics()
QCOMPARE(pixmap.width(), 100);
QCOMPARE(pixmap.height(), 100);
- QCOMPARE(pixmap.depth(), QPixmap::defaultDepth());
+ QVERIFY(pixmap.depth() >= QPixmap::defaultDepth());
QBitmap bitmap(100, 100);
@@ -597,7 +727,11 @@ void tst_QPixmap::drawBitmap()
painter2.setPen(Qt::red);
painter2.drawPixmap(0,0,10,10, bitmap);
painter2.end();
- QCOMPARE(pixmap.toImage().pixel(5,5), QColor(Qt::red).rgb());
+
+ QPixmap expected(10, 10);
+ expected.fill(Qt::red);
+
+ QVERIFY(lenientCompare(pixmap, expected));
}
void tst_QPixmap::grabWidget()
@@ -610,8 +744,7 @@ void tst_QPixmap::grabWidget()
expected.fill(Qt::green);
QPixmap actual = QPixmap::grabWidget(&widget, QRect(64, 64, 64, 64));
-
- QCOMPARE(actual, expected);
+ QVERIFY(lenientCompare(actual, expected));
}
void tst_QPixmap::grabWindow()
@@ -642,7 +775,7 @@ void tst_QPixmap::grabWindow()
QPixmap grabWindowPixmap = QPixmap::grabWindow(child.winId());
QPixmap grabWidgetPixmap = QPixmap::grabWidget(&child);
- QCOMPARE(grabWindowPixmap, grabWidgetPixmap);
+ lenientCompare(grabWindowPixmap, grabWidgetPixmap);
}
void tst_QPixmap::isNull()
@@ -978,10 +1111,10 @@ void tst_QPixmap::copy()
}
QPixmap dest = src.copy(10, 10, 10, 10);
- QImage result = dest.toImage().convertToFormat(QImage::Format_RGB32);
- QImage expected(10, 10, QImage::Format_RGB32);
- expected.fill(0xff0000ff);
- QCOMPARE(result, expected);
+
+ QPixmap expected(10, 10);
+ expected.fill(Qt::blue);
+ QVERIFY(lenientCompare(dest, expected));
}
#ifdef QT3_SUPPORT
@@ -1049,27 +1182,33 @@ void tst_QPixmap::transformed()
}
QPixmap p2(10, 20);
- p2.fill(Qt::red);
{
QPainter p(&p2);
- p.drawRect(0, 0, p2.width() - 1, p2.height() - 1);
+ p.rotate(90);
+ p.drawPixmap(0, -p1.height(), p1);
+ }
+
+ QPixmap p3(20, 10);
+ {
+ QPainter p(&p3);
+ p.rotate(180);
+ p.drawPixmap(-p1.width(), -p1.height(), p1);
+ }
+
+ QPixmap p4(10, 20);
+ {
+ QPainter p(&p4);
+ p.rotate(270);
+ p.drawPixmap(-p1.width(), 0, p1);
}
QPixmap p1_90 = p1.transformed(QTransform().rotate(90));
QPixmap p1_180 = p1.transformed(QTransform().rotate(180));
QPixmap p1_270 = p1.transformed(QTransform().rotate(270));
- QCOMPARE(p1_90.size(), p2.size());
- QCOMPARE(p1_90.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied),
- p2.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied));
-
- QCOMPARE(p1_180.size(), p1.size());
- QCOMPARE(p1_180.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied),
- p1.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied));
-
- QCOMPARE(p1_270.size(), p2.size());
- QCOMPARE(p1_270.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied),
- p2.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied));
+ QVERIFY(lenientCompare(p1_90, p2));
+ QVERIFY(lenientCompare(p1_180, p3));
+ QVERIFY(lenientCompare(p1_270, p4));
}
void tst_QPixmap::transformed2()
@@ -1097,9 +1236,7 @@ void tst_QPixmap::transformed2()
p.drawRect(3, 6, 3, 3);
p.end();
- QCOMPARE(actual.size(), expected.size());
- QCOMPARE(actual.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied),
- expected.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied));
+ QVERIFY(lenientCompare(actual, expected));
}
void tst_QPixmap::fromImage_crash()
diff --git a/tests/auto/qpixmapcache/tst_qpixmapcache.cpp b/tests/auto/qpixmapcache/tst_qpixmapcache.cpp
index 1f515ff..fb5998a 100644
--- a/tests/auto/qpixmapcache/tst_qpixmapcache.cpp
+++ b/tests/auto/qpixmapcache/tst_qpixmapcache.cpp
@@ -44,9 +44,7 @@
#include <qpixmapcache.h>
-
-
-
+#include "../../../src/gui/image/qpixmapcache_p.h"
//TESTED_CLASS=
@@ -68,10 +66,21 @@ private slots:
void setCacheLimit();
void find();
void insert();
+ void replace();
void remove();
void clear();
+ void pixmapKey();
};
+static QPixmapCache::KeyData* getPrivate(QPixmapCache::Key &key)
+{
+ return (*reinterpret_cast<QPixmapCache::KeyData**>(&key));
+}
+
+static QPixmapCache::KeyData** getPrivateRef(QPixmapCache::Key &key)
+{
+ return (reinterpret_cast<QPixmapCache::KeyData**>(&key));
+}
static int originalCacheLimit;
@@ -119,6 +128,72 @@ void tst_QPixmapCache::setCacheLimit()
QVERIFY(QPixmapCache::find("P1") != 0);
delete p1;
+
+ //The int part of the API
+ p1 = new QPixmap(2, 3);
+ QPixmapCache::Key key = QPixmapCache::insert(*p1);
+ QVERIFY(QPixmapCache::find(key, p1) != 0);
+ delete p1;
+
+ QPixmapCache::setCacheLimit(0);
+ QVERIFY(QPixmapCache::find(key, p1) == 0);
+
+ p1 = new QPixmap(2, 3);
+ QPixmapCache::setCacheLimit(1000);
+ QPixmapCache::replace(key, *p1);
+ QVERIFY(QPixmapCache::find(key, p1) == 0);
+
+ delete p1;
+
+ //Let check if keys are released when the pixmap cache is
+ //full or has been flushed.
+ QPixmapCache::clear();
+ p1 = new QPixmap(2, 3);
+ key = QPixmapCache::insert(*p1);
+ QVERIFY(QPixmapCache::find(key, p1) != 0);
+ QPixmapCache::setCacheLimit(0);
+ QVERIFY(QPixmapCache::find(key, p1) == 0);
+ QPixmapCache::setCacheLimit(1000);
+ key = QPixmapCache::insert(*p1);
+ QCOMPARE(getPrivate(key)->isValid, true);
+ QCOMPARE(getPrivate(key)->key, 1);
+
+ delete p1;
+
+ //Let check if removing old entries doesn't let you get
+ // wrong pixmaps
+ QPixmapCache::clear();
+ QPixmap p2;
+ p1 = new QPixmap(2, 3);
+ key = QPixmapCache::insert(*p1);
+ QVERIFY(QPixmapCache::find(key, &p2) != 0);
+ //we flush the cache
+ QPixmapCache::setCacheLimit(0);
+ QPixmapCache::setCacheLimit(1000);
+ QPixmapCache::Key key2 = QPixmapCache::insert(*p1);
+ QCOMPARE(getPrivate(key2)->key, 2);
+ QVERIFY(QPixmapCache::find(key, &p2) == 0);
+ QVERIFY(QPixmapCache::find(key2, &p2) != 0);
+ QCOMPARE(p2, *p1);
+
+ delete p1;
+
+ //Here we simulate the flushing when the app is idle
+ /*QPixmapCache::clear();
+ QPixmapCache::setCacheLimit(originalCacheLimit);
+ p1 = new QPixmap(300, 300);
+ key = QPixmapCache::insert(*p1);
+ QCOMPARE(getPrivate(key)->key, 1);
+ key2 = QPixmapCache::insert(*p1);
+ key2 = QPixmapCache::insert(*p1);
+ QPixmapCache::Key key3 = QPixmapCache::insert(*p1);
+ QTest::qWait(32000);
+ key2 = QPixmapCache::insert(*p1);
+ QCOMPARE(getPrivate(key2)->key, 1);
+ //This old key is not valid anymore after the flush
+ QCOMPARE(getPrivate(key)->isValid, false);
+ QVERIFY(QPixmapCache::find(key, &p2) == 0);
+ delete p1;*/
}
void tst_QPixmapCache::find()
@@ -137,6 +212,28 @@ void tst_QPixmapCache::find()
QPixmap *p3 = QPixmapCache::find("P1");
QVERIFY(p3);
QCOMPARE(p1, *p3);
+
+ //The int part of the API
+ QPixmapCache::Key key = QPixmapCache::insert(p1);
+
+ QVERIFY(QPixmapCache::find(key, &p2));
+ QCOMPARE(p2.width(), 10);
+ QCOMPARE(p2.height(), 10);
+ QCOMPARE(p1, p2);
+
+ QPixmapCache::clear();
+
+ key = QPixmapCache::insert(p1);
+
+ //The int part of the API
+ // make sure it doesn't explode
+ QList<QPixmapCache::Key> keys;
+ for (int i = 0; i < 40000; ++i)
+ QPixmapCache::insert(p1);
+
+ //at that time the first key has been erase because no more place in the cache
+ QVERIFY(QPixmapCache::find(key, &p1) == 0);
+ QCOMPARE(getPrivate(key)->isValid, false);
}
void tst_QPixmapCache::insert()
@@ -152,18 +249,22 @@ void tst_QPixmapCache::insert()
QPixmapCache::insert("0", p1);
// ditto
- for (int j = 0; j < 20000; ++j)
+ for (int j = 0; j < 40000; ++j)
QPixmapCache::insert(QString::number(j), p1);
int num = 0;
- for (int k = 0; k < 20000; ++k) {
+ for (int k = 0; k < 40000; ++k) {
if (QPixmapCache::find(QString::number(k)))
++num;
}
+ if (QPixmapCache::find("0"))
+ ++num;
+
int estimatedNum = (1024 * QPixmapCache::cacheLimit())
/ ((p1.width() * p1.height() * p1.depth()) / 8);
- QVERIFY(estimatedNum - 1 <= num <= estimatedNum + 1);
+
+ QVERIFY(num <= estimatedNum);
QPixmap p3;
QPixmapCache::insert("null", p3);
@@ -176,6 +277,50 @@ void tst_QPixmapCache::insert()
QPixmapCache::insert("custom", c2);
//We have deleted the old pixmap in the cache for the same key
QVERIFY(c1.isDetached());
+
+ //The int part of the API
+ // make sure it doesn't explode
+ QList<QPixmapCache::Key> keys;
+ for (int i = 0; i < 40000; ++i)
+ keys.append(QPixmapCache::insert(p1));
+
+ num = 0;
+ for (int k = 0; k < 40000; ++k) {
+ if (QPixmapCache::find(keys.at(k), &p2))
+ ++num;
+ }
+
+ estimatedNum = (1024 * QPixmapCache::cacheLimit())
+ / ((p1.width() * p1.height() * p1.depth()) / 8);
+ QVERIFY(num <= estimatedNum);
+ QPixmapCache::insert(p3);
+
+}
+
+void tst_QPixmapCache::replace()
+{
+ //The int part of the API
+ QPixmap p1(10, 10);
+ p1.fill(Qt::red);
+
+ QPixmap p2(10, 10);
+ p2.fill(Qt::yellow);
+
+ QPixmapCache::Key key = QPixmapCache::insert(p1);
+
+ QPixmap p3;
+ QVERIFY(QPixmapCache::find(key, &p3) == 1);
+
+ QPixmapCache::replace(key,p2);
+
+ QVERIFY(QPixmapCache::find(key, &p3) == 1);
+
+ QCOMPARE(p3.width(), 10);
+ QCOMPARE(p3.height(), 10);
+ QCOMPARE(p3, p2);
+
+ //Broken keys
+ QCOMPARE(QPixmapCache::replace(QPixmapCache::Key(), p2), false);
}
void tst_QPixmapCache::remove()
@@ -198,6 +343,48 @@ void tst_QPixmapCache::remove()
QPixmapCache::remove("green");
QVERIFY(QPixmapCache::find("green") == 0);
+
+ //The int part of the API
+ QPixmapCache::clear();
+ p1.fill(Qt::red);
+ QPixmapCache::Key key = QPixmapCache::insert(p1);
+ p1.fill(Qt::yellow);
+
+ QVERIFY(QPixmapCache::find(key, &p2));
+ QVERIFY(p1.toImage() != p2.toImage());
+ QVERIFY(p1.toImage() == p1.toImage()); // sanity check
+
+ QPixmapCache::remove(key);
+ QVERIFY(QPixmapCache::find(key, &p1) == 0);
+
+ //Broken key
+ QPixmapCache::remove(QPixmapCache::Key());
+ QVERIFY(QPixmapCache::find(QPixmapCache::Key(), &p1) == 0);
+
+ //Test if keys are release
+ QPixmapCache::clear();
+ key = QPixmapCache::insert(p1);
+ QCOMPARE(getPrivate(key)->key, 1);
+ QPixmapCache::remove(key);
+ key = QPixmapCache::insert(p1);
+ QCOMPARE(getPrivate(key)->key, 1);
+
+ //Test if pixmaps are correctly deleted
+ QPixmapCache::clear();
+ key = QPixmapCache::insert(p1);
+ QCOMPARE(getPrivate(key)->key, 1);
+ QVERIFY(QPixmapCache::find(key, &p1) != 0);
+ QPixmapCache::remove(key);
+ QCOMPARE(p1.isDetached(), true);
+
+ //We mix both part of the API
+ QPixmapCache::clear();
+ p1.fill(Qt::red);
+ QPixmapCache::insert("red", p1);
+ key = QPixmapCache::insert(p1);
+ QPixmapCache::remove(key);
+ QVERIFY(QPixmapCache::find(key, &p1) == 0);
+ QVERIFY(QPixmapCache::find("red") != 0);
}
void tst_QPixmapCache::clear()
@@ -205,12 +392,11 @@ void tst_QPixmapCache::clear()
QPixmap p1(10, 10);
p1.fill(Qt::red);
- for (int i = 0; i < 20000; ++i) {
+ for (int i = 0; i < 20000; ++i)
QVERIFY(QPixmapCache::find("x" + QString::number(i)) == 0);
- }
- for (int j = 0; j < 20000; ++j) {
+
+ for (int j = 0; j < 20000; ++j)
QPixmapCache::insert(QString::number(j), p1);
- }
int num = 0;
for (int k = 0; k < 20000; ++k) {
@@ -221,10 +407,68 @@ void tst_QPixmapCache::clear()
QPixmapCache::clear();
- for (int k = 0; k < 20000; ++k) {
+ for (int k = 0; k < 20000; ++k)
QVERIFY(QPixmapCache::find(QString::number(k)) == 0);
+
+ //The int part of the API
+ QPixmap p2(10, 10);
+ p2.fill(Qt::red);
+
+ QList<QPixmapCache::Key> keys;
+ for (int k = 0; k < 20000; ++k)
+ keys.append(QPixmapCache::insert(p2));
+
+ QPixmapCache::clear();
+
+ for (int k = 0; k < 20000; ++k) {
+ QVERIFY(QPixmapCache::find(keys.at(k), &p1) == 0);
+ QCOMPARE(getPrivate(keys[k])->isValid, false);
}
}
+void tst_QPixmapCache::pixmapKey()
+{
+ QPixmapCache::Key key;
+ //Default constructed keys have no d pointer unless
+ //we use them
+ QVERIFY(!getPrivate(key));
+ //Let's put a d pointer
+ QPixmapCache::KeyData** keyd = getPrivateRef(key);
+ *keyd = new QPixmapCache::KeyData;
+ QCOMPARE(getPrivate(key)->ref, 1);
+ QPixmapCache::Key key2;
+ //Let's put a d pointer
+ QPixmapCache::KeyData** key2d = getPrivateRef(key2);
+ *key2d = new QPixmapCache::KeyData;
+ QCOMPARE(getPrivate(key2)->ref, 1);
+ key = key2;
+ QCOMPARE(getPrivate(key2)->ref, 2);
+ QCOMPARE(getPrivate(key)->ref, 2);
+ QPixmapCache::Key key3;
+ //Let's put a d pointer
+ QPixmapCache::KeyData** key3d = getPrivateRef(key3);
+ *key3d = new QPixmapCache::KeyData;
+ QPixmapCache::Key key4 = key3;
+ QCOMPARE(getPrivate(key3)->ref, 2);
+ QCOMPARE(getPrivate(key4)->ref, 2);
+ key4 = key;
+ QCOMPARE(getPrivate(key4)->ref, 3);
+ QCOMPARE(getPrivate(key3)->ref, 1);
+ QPixmapCache::Key key5(key3);
+ QCOMPARE(getPrivate(key3)->ref, 2);
+ QCOMPARE(getPrivate(key5)->ref, 2);
+
+ //let test default constructed keys
+ QPixmapCache::Key key6;
+ QVERIFY(!getPrivate(key6));
+ QPixmapCache::Key key7;
+ QVERIFY(!getPrivate(key7));
+ key6 = key7;
+ QVERIFY(!getPrivate(key6));
+ QVERIFY(!getPrivate(key7));
+ QPixmapCache::Key key8(key7);
+ QVERIFY(!getPrivate(key8));
+}
+
QTEST_MAIN(tst_QPixmapCache)
#include "tst_qpixmapcache.moc"
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 57d15ad..047828a 100644
--- a/tests/auto/qprocess/qprocess.pro
+++ b/tests/auto/qprocess/qprocess.pro
@@ -4,6 +4,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 8101708..3de98194 100644
--- a/tests/auto/qprocess/tst_qprocess.cpp
+++ b/tests/auto/qprocess/tst_qprocess.cpp
@@ -128,6 +128,8 @@ private slots:
void spaceArgsTest_data();
void spaceArgsTest();
void exitCodeTest();
+ void setEnvironment_data();
+ void setEnvironment();
void systemEnvironment();
void spaceInName();
void lockupsInStartDetached();
@@ -1780,13 +1782,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) || defined(Q_OS_SYMBIAN)
// 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/qpropertyanimation/qpropertyanimation.pro b/tests/auto/qpropertyanimation/qpropertyanimation.pro
new file mode 100644
index 0000000..6d6ddbf
--- /dev/null
+++ b/tests/auto/qpropertyanimation/qpropertyanimation.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT = core gui
+SOURCES += tst_qpropertyanimation.cpp
+
+
diff --git a/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp
new file mode 100644
index 0000000..0aeac91
--- /dev/null
+++ b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp
@@ -0,0 +1,958 @@
+/****************************************************************************
+**
+** 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 <QtTest/QtTest>
+
+#include <QtCore/qpropertyanimation.h>
+#include <QtCore/qvariantanimation.h>
+#include <QtGui/qwidget.h>
+
+//TESTED_CLASS=QPropertyAnimation
+//TESTED_FILES=
+
+class UncontrolledAnimation : public QPropertyAnimation
+{
+ Q_OBJECT
+public:
+ int duration() const { return -1; /* not time driven */ }
+
+protected:
+ void updateCurrentTime(int msecs)
+ {
+ QPropertyAnimation::updateCurrentTime(msecs);
+ if (msecs >= QPropertyAnimation::duration())
+ stop();
+ }
+};
+
+class MyObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal x READ x WRITE setX)
+public:
+ MyObject() : m_x(0) { }
+ qreal x() const { return m_x; }
+ void setX(qreal x) { m_x = x; }
+private:
+ qreal m_x;
+};
+
+class tst_QPropertyAnimation : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QPropertyAnimation();
+ virtual ~tst_QPropertyAnimation();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private slots:
+ void construction();
+ void setCurrentTime_data();
+ void setCurrentTime();
+ void statesAndSignals_data();
+ void statesAndSignals();
+ void deletion1();
+ void deletion2();
+ void deletion3();
+ void duration0();
+ void noStartValue();
+ void noStartValueWithLoop();
+ void startWhenAnotherIsRunning();
+ void easingcurve_data();
+ void easingcurve();
+ void startWithoutStartValue();
+ void playForwardBackward();
+ void interpolated();
+ void setStartEndValues_data();
+ void setStartEndValues();
+ void zeroDurationStart();
+ void operationsInStates_data();
+ void operationsInStates();
+ void oneKeyValue();
+ void updateOnSetKeyValues();
+};
+
+tst_QPropertyAnimation::tst_QPropertyAnimation()
+{
+}
+
+tst_QPropertyAnimation::~tst_QPropertyAnimation()
+{
+}
+
+void tst_QPropertyAnimation::init()
+{
+ qRegisterMetaType<QAbstractAnimation::State>("QAbstractAnimation::State");
+ qRegisterMetaType<QAbstractAnimation::DeletionPolicy>("QAbstractAnimation::DeletionPolicy");
+}
+
+void tst_QPropertyAnimation::cleanup()
+{
+}
+
+class AnimationObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+ Q_PROPERTY(qreal realValue READ realValue WRITE setRealValue)
+public:
+ AnimationObject(int startValue = 0)
+ : v(startValue)
+ { }
+
+ int value() const { return v; }
+ void setValue(int value) { v = value; }
+
+ qreal realValue() const { return rv; }
+ void setRealValue(qreal value) { rv = value; }
+
+ int v;
+ qreal rv;
+};
+
+
+void tst_QPropertyAnimation::construction()
+{
+ QPropertyAnimation panimation;
+}
+
+void tst_QPropertyAnimation::setCurrentTime_data()
+{
+ QTest::addColumn<int>("duration");
+ QTest::addColumn<int>("loopCount");
+ QTest::addColumn<int>("currentTime");
+ QTest::addColumn<int>("testCurrentTime");
+ QTest::addColumn<int>("testCurrentLoop");
+
+ QTest::newRow("-1") << -1 << 1 << 0 << 0 << 0;
+ QTest::newRow("0") << 0 << 1 << 0 << 0 << 0;
+ QTest::newRow("1") << 0 << 1 << 1 << 0 << 0;
+ QTest::newRow("2") << 0 << 2 << 1 << 0 << 0;
+ QTest::newRow("3") << 1 << 1 << 0 << 0 << 0;
+ QTest::newRow("4") << 1 << 1 << 1 << 1 << 0;
+ QTest::newRow("5") << 1 << 2 << 1 << 0 << 1;
+ QTest::newRow("6") << 1 << 2 << 2 << 1 << 1;
+ QTest::newRow("7") << 1 << 2 << 3 << 1 << 1;
+ QTest::newRow("8") << 1 << 3 << 2 << 0 << 2;
+ QTest::newRow("9") << 1 << 3 << 3 << 1 << 2;
+ QTest::newRow("a") << 10 << 1 << 0 << 0 << 0;
+ QTest::newRow("b") << 10 << 1 << 1 << 1 << 0;
+ QTest::newRow("c") << 10 << 1 << 10 << 10 << 0;
+ QTest::newRow("d") << 10 << 2 << 10 << 0 << 1;
+ QTest::newRow("e") << 10 << 2 << 11 << 1 << 1;
+ QTest::newRow("f") << 10 << 2 << 20 << 10 << 1;
+ QTest::newRow("g") << 10 << 2 << 21 << 10 << 1;
+ QTest::newRow("negloop 0") << 10 << -1 << 0 << 0 << 0;
+ QTest::newRow("negloop 1") << 10 << -1 << 10 << 0 << 1;
+ QTest::newRow("negloop 2") << 10 << -1 << 15 << 5 << 1;
+ QTest::newRow("negloop 3") << 10 << -1 << 20 << 0 << 2;
+ QTest::newRow("negloop 4") << 10 << -1 << 30 << 0 << 3;
+}
+
+void tst_QPropertyAnimation::setCurrentTime()
+{
+ QFETCH(int, duration);
+ QFETCH(int, loopCount);
+ QFETCH(int, currentTime);
+ QFETCH(int, testCurrentTime);
+ QFETCH(int, testCurrentLoop);
+
+ QPropertyAnimation animation;
+ if (duration < 0)
+ QTest::ignoreMessage(QtWarningMsg, "QVariantAnimation::setDuration: cannot set a negative duration");
+ animation.setDuration(duration);
+ animation.setLoopCount(loopCount);
+ animation.setCurrentTime(currentTime);
+
+ QCOMPARE(animation.currentTime(), testCurrentTime);
+ QCOMPARE(animation.currentLoop(), testCurrentLoop);
+}
+
+void tst_QPropertyAnimation::statesAndSignals_data()
+{
+ QTest::addColumn<bool>("uncontrolled");
+ QTest::newRow("normal animation") << false;
+ QTest::newRow("animation with undefined duration") << true;
+}
+
+void tst_QPropertyAnimation::statesAndSignals()
+{
+ QFETCH(bool, uncontrolled);
+ QPropertyAnimation *anim = uncontrolled ? new UncontrolledAnimation : new QPropertyAnimation;
+ anim->setDuration(100);
+
+ QSignalSpy finishedSpy(anim, SIGNAL(finished()));
+ QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy currentLoopSpy(anim, SIGNAL(currentLoopChanged(int)));
+
+ anim->setCurrentTime(1);
+ anim->setCurrentTime(100);
+ QCOMPARE(finishedSpy.count(), 0);
+ QCOMPARE(runningSpy.count(), 0);
+ QCOMPARE(currentLoopSpy.count(), 0);
+ QCOMPARE(anim->state(), QAnimationGroup::Stopped);
+
+ anim->setLoopCount(3);
+ anim->setCurrentTime(101);
+
+ if (uncontrolled)
+ QSKIP("Uncontrolled animations don't handle looping", SkipSingle);
+
+ QCOMPARE(currentLoopSpy.count(), 1);
+ QCOMPARE(anim->currentLoop(), 1);
+
+ anim->setCurrentTime(0);
+ QCOMPARE(currentLoopSpy.count(), 2);
+ QCOMPARE(anim->currentLoop(), 0);
+
+ anim->start();
+ QCOMPARE(anim->state(), QAnimationGroup::Running);
+ QCOMPARE(runningSpy.count(), 1); //anim must have started
+ QCOMPARE(anim->currentLoop(), 0);
+ runningSpy.clear();
+
+ anim->stop();
+ QCOMPARE(anim->state(), QAnimationGroup::Stopped);
+ QCOMPARE(runningSpy.count(), 1); //anim must have stopped
+ QCOMPARE(finishedSpy.count(), 0);
+ QCOMPARE(anim->currentTime(), 0);
+ QCOMPARE(anim->currentLoop(), 0);
+ QCOMPARE(currentLoopSpy.count(), 2);
+ runningSpy.clear();
+
+ anim->start();
+ QTest::qWait(1000);
+ QCOMPARE(anim->state(), QAnimationGroup::Stopped);
+ QCOMPARE(runningSpy.count(), 2); //started and stopped again
+ runningSpy.clear();
+ QCOMPARE(finishedSpy.count(), 1);
+ QCOMPARE(anim->currentTime(), 100);
+ QCOMPARE(anim->currentLoop(), 2);
+ QCOMPARE(currentLoopSpy.count(), 4);
+
+ anim->start(); // auto-rewinds
+ QCOMPARE(anim->state(), QAnimationGroup::Running);
+ QCOMPARE(anim->currentTime(), 0);
+ QCOMPARE(anim->currentLoop(), 0);
+ QCOMPARE(currentLoopSpy.count(), 5);
+ QCOMPARE(runningSpy.count(), 1); // anim has started
+ QCOMPARE(finishedSpy.count(), 1);
+ QCOMPARE(anim->currentLoop(), 0);
+ runningSpy.clear();
+
+ QTest::qWait(1000);
+
+ QCOMPARE(currentLoopSpy.count(), 7);
+ QCOMPARE(anim->state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim->currentLoop(), 2);
+ QCOMPARE(runningSpy.count(), 1); // anim has stopped
+ QCOMPARE(finishedSpy.count(), 2);
+ QCOMPARE(anim->currentTime(), 100);
+
+ delete anim;
+}
+
+void tst_QPropertyAnimation::deletion1()
+{
+ QObject *object = new QWidget;
+ QPointer<QPropertyAnimation> anim = new QPropertyAnimation(object, "minimumWidth");
+
+ //test that the animation is deleted correctly depending of the deletion flag passed in start()
+ QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy finishedSpy(anim, SIGNAL(finished()));
+ anim->setStartValue(10);
+ anim->setEndValue(20);
+ anim->setDuration(200);
+ anim->start();
+ QCOMPARE(runningSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 0);
+
+ QVERIFY(anim);
+ QCOMPARE(anim->state(), QAnimationGroup::Running);
+ QTest::qWait(100);
+ QVERIFY(anim);
+ QCOMPARE(anim->state(), QAnimationGroup::Running);
+ QTest::qWait(150);
+ QVERIFY(anim); //The animation should not have been deleted
+ QCOMPARE(anim->state(), QAnimationGroup::Stopped);
+ QCOMPARE(runningSpy.count(), 2);
+ QCOMPARE(finishedSpy.count(), 1);
+
+ anim->start(QVariantAnimation::DeleteWhenStopped);
+ QVERIFY(anim);
+ QCOMPARE(anim->state(), QAnimationGroup::Running);
+ QTest::qWait(100);
+ QVERIFY(anim);
+ QCOMPARE(anim->state(), QAnimationGroup::Running);
+ QTest::qWait(150);
+ QVERIFY(!anim); //The animation must have been deleted
+ QCOMPARE(runningSpy.count(), 4);
+ QCOMPARE(finishedSpy.count(), 2);
+ delete object;
+}
+
+void tst_QPropertyAnimation::deletion2()
+{
+ //test that the animation get deleted if the object is deleted
+ QObject *object = new QWidget;
+ QPointer<QPropertyAnimation> anim = new QPropertyAnimation(object,"minimumWidth");
+ anim->setStartValue(10);
+ anim->setEndValue(20);
+ anim->setDuration(200);
+
+ QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy finishedSpy(anim, SIGNAL(finished()));
+
+ anim->setStartValue(10);
+ anim->setEndValue(20);
+ anim->setDuration(200);
+ anim->start();
+
+ QTest::qWait(50);
+ QVERIFY(anim);
+ QCOMPARE(anim->state(), QAnimationGroup::Running);
+
+ QCOMPARE(runningSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 0);
+
+ //we can't call deletaLater directly because the delete would only happen in the next loop of _this_ event loop
+ QTimer::singleShot(0, object, SLOT(deleteLater()));
+ QTest::qWait(50);
+
+ QVERIFY(anim->targetObject() == 0);
+}
+
+void tst_QPropertyAnimation::deletion3()
+{
+ //test that the stopped signal is emit when the animation is destroyed
+ QObject *object = new QWidget;
+ QPropertyAnimation *anim = new QPropertyAnimation(object,"minimumWidth");
+ anim->setStartValue(10);
+ anim->setEndValue(20);
+ anim->setDuration(200);
+
+ QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy finishedSpy(anim, SIGNAL(finished()));
+ anim->start();
+
+ QTest::qWait(50);
+ QCOMPARE(anim->state(), QAnimationGroup::Running);
+ QCOMPARE(runningSpy.count(), 1);
+ QCOMPARE(finishedSpy.count(), 0);
+ delete anim;
+ QCOMPARE(runningSpy.count(), 2);
+ QCOMPARE(finishedSpy.count(), 0);
+}
+
+void tst_QPropertyAnimation::duration0()
+{
+ QObject o;
+ o.setProperty("ole", 42);
+ QCOMPARE(o.property("ole").toInt(), 42);
+
+ QPropertyAnimation animation(&o, "ole");
+ animation.setEndValue(43);
+ QVERIFY(!animation.currentValue().isValid());
+ QCOMPARE(animation.currentValue().toInt(), 0);
+ QCOMPARE(o.property("ole").toInt(), 42);
+ animation.setDuration(0);
+ animation.start();
+ QCOMPARE(animation.state(), QAnimationGroup::Stopped);
+ QCOMPARE(animation.currentTime(), 0);
+ QCOMPARE(o.property("ole").toInt(), 43);
+}
+
+class StartValueTester : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int ole READ ole WRITE setOle)
+public:
+ StartValueTester() : o(0) { }
+ int ole() const { return o; }
+ void setOle(int v) { o = v; values << v; }
+
+ int o;
+ QList<int> values;
+};
+
+void tst_QPropertyAnimation::noStartValue()
+{
+ StartValueTester o;
+ o.setProperty("ole", 42);
+ o.values.clear();
+
+ QPropertyAnimation a(&o, "ole");
+ a.setEndValue(420);
+ a.setDuration(250);
+ a.start();
+
+ QTest::qWait(300);
+
+ QCOMPARE(o.values.first(), 42);
+ QCOMPARE(o.values.last(), 420);
+}
+
+void tst_QPropertyAnimation::noStartValueWithLoop()
+{
+ StartValueTester o;
+ o.setProperty("ole", 42);
+ o.values.clear();
+
+ QPropertyAnimation a(&o, "ole");
+ a.setEndValue(420);
+ a.setDuration(250);
+ a.setLoopCount(2);
+ a.start();
+
+ a.setCurrentTime(250);
+ QCOMPARE(o.values.first(), 42);
+ QCOMPARE(a.currentValue().toInt(), 42);
+ QCOMPARE(o.values.last(), 42);
+
+ a.setCurrentTime(500);
+ QCOMPARE(a.currentValue().toInt(), 420);
+}
+
+void tst_QPropertyAnimation::startWhenAnotherIsRunning()
+{
+ StartValueTester o;
+ o.setProperty("ole", 42);
+ o.values.clear();
+
+ {
+ //normal case: the animation finishes and is deleted
+ QPointer<QVariantAnimation> anim = new QPropertyAnimation(&o, "ole");
+ QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ anim->start(QVariantAnimation::DeleteWhenStopped);
+ QTest::qWait(anim->duration() + 50);
+ QCOMPARE(runningSpy.count(), 2); //started and then stopped
+ QVERIFY(!anim);
+ }
+
+ {
+ QPointer<QVariantAnimation> anim = new QPropertyAnimation(&o, "ole");
+ QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ anim->start(QVariantAnimation::DeleteWhenStopped);
+ QTest::qWait(anim->duration()/2);
+ QPointer<QVariantAnimation> anim2 = new QPropertyAnimation(&o, "ole");
+ QCOMPARE(runningSpy.count(), 1);
+ QCOMPARE(anim->state(), QVariantAnimation::Running);
+
+ //anim2 will interrupt anim1
+ QMetaObject::invokeMethod(anim2, "start", Qt::QueuedConnection, Q_ARG(QAbstractAnimation::DeletionPolicy, QVariantAnimation::DeleteWhenStopped));
+ QTest::qWait(50);
+ QVERIFY(!anim); //anim should have been deleted
+ QVERIFY(anim2);
+ QTest::qWait(anim2->duration());
+ QVERIFY(!anim2); //anim2 is finished: it should have been deleted by now
+ QVERIFY(!anim);
+ }
+
+}
+
+// copy from easing.cpp in case that function changes definition
+static qreal easeInOutBack(qreal t)
+{
+ qreal s = 1.70158;
+ qreal t_adj = 2.0f * (qreal)t;
+ if (t_adj < 1) {
+ s *= 1.525f;
+ return 1.0/2*(t_adj*t_adj*((s+1)*t_adj - s));
+ } else {
+ t_adj -= 2;
+ s *= 1.525f;
+ return 1.0/2*(t_adj*t_adj*((s+1)*t_adj + s) + 2);
+ }
+}
+
+void tst_QPropertyAnimation::easingcurve_data()
+{
+ QTest::addColumn<int>("currentTime");
+ QTest::addColumn<int>("expectedvalue");
+
+ QTest::newRow("interpolation1") << 0 << 0;
+ QTest::newRow("interpolation2") << 1000 << 1000;
+ QTest::newRow("extrapolationbelow") << 250 << -99;
+ QTest::newRow("extrapolationabove") << 750 << 1099;
+}
+
+void tst_QPropertyAnimation::easingcurve()
+{
+ QFETCH(int, currentTime);
+ QFETCH(int, expectedvalue);
+ QObject o;
+ o.setProperty("ole", 42);
+ QCOMPARE(o.property("ole").toInt(), 42);
+
+ QPropertyAnimation pAnimation(&o, "ole");
+ pAnimation.setStartValue(0);
+ pAnimation.setEndValue(1000);
+ pAnimation.setDuration(1000);
+
+ // this easingcurve assumes that we extrapolate before startValue and after endValue
+ QEasingCurve easingCurve;
+ easingCurve.setCustomType(easeInOutBack);
+ pAnimation.setEasingCurve(easingCurve);
+ pAnimation.start();
+ pAnimation.pause();
+ pAnimation.setCurrentTime(currentTime);
+ QCOMPARE(o.property("ole").toInt(), expectedvalue);
+}
+
+void tst_QPropertyAnimation::startWithoutStartValue()
+{
+ QObject o;
+ o.setProperty("ole", 42);
+ QCOMPARE(o.property("ole").toInt(), 42);
+
+ QPropertyAnimation anim(&o, "ole");
+ anim.setEndValue(100);
+
+ anim.start();
+
+ QTest::qWait(100);
+ int current = anim.currentValue().toInt();
+ //it is somewhere in the animation
+ QVERIFY(current > 42);
+ QVERIFY(current < 100);
+
+ QTest::qWait(200);
+ QCOMPARE(anim.state(), QVariantAnimation::Stopped);
+
+ anim.setEndValue(110);
+ anim.start();
+ current = anim.currentValue().toInt();
+ // the default start value will reevaluate the current property
+ // and set it to the end value of the last iteration
+ QCOMPARE(current, 100);
+ QTest::qWait(100);
+ current = anim.currentValue().toInt();
+ //it is somewhere in the animation
+ QVERIFY(current >= 100);
+ QVERIFY(current <= 110);
+}
+
+void tst_QPropertyAnimation::playForwardBackward()
+{
+ QObject o;
+ o.setProperty("ole", 0);
+ QCOMPARE(o.property("ole").toInt(), 0);
+
+ QPropertyAnimation anim(&o, "ole");
+ anim.setEndValue(100);
+ anim.start();
+ QTest::qWait(anim.duration() + 50);
+ QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
+ QCOMPARE(anim.currentTime(), anim.duration());
+
+ //the animation is at the end
+ anim.setDirection(QVariantAnimation::Backward);
+ anim.start();
+ QCOMPARE(anim.state(), QAbstractAnimation::Running);
+ QTest::qWait(anim.duration() + 50);
+ QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
+ QCOMPARE(anim.currentTime(), 0);
+
+ //the direction is backward
+ //restarting should jump to the end
+ anim.start();
+ QCOMPARE(anim.state(), QAbstractAnimation::Running);
+ QCOMPARE(anim.currentTime(), anim.duration());
+ QTest::qWait(anim.duration() + 50);
+ QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
+ QCOMPARE(anim.currentTime(), 0);
+}
+
+struct Number
+{
+ Number() {}
+ Number(int n)
+ : n(n) {}
+
+ Number(const Number &other)
+ : n(other.n){}
+
+ Number &operator=(const Number &other) {
+ n = other.n;
+ return *this;
+ }
+ bool operator==(const Number &other) const {
+ return n == other.n;
+ }
+
+ int n;
+};
+
+Q_DECLARE_METATYPE(Number)
+Q_DECLARE_METATYPE(QAbstractAnimation::State)
+
+QVariant numberInterpolator(const Number &f, const Number &t, qreal progress)
+{
+ return qVariantFromValue<Number>(Number(f.n + (t.n - f.n)*progress));
+}
+
+QVariant xaxisQPointInterpolator(const QPointF &f, const QPointF &t, qreal progress)
+{
+ return QPointF(f.x() + (t.x() - f.x())*progress, f.y());
+}
+
+void tst_QPropertyAnimation::interpolated()
+{
+ QObject o;
+ o.setProperty("point", QPointF()); //this will avoid warnings
+ o.setProperty("number", qVariantFromValue<Number>(Number(42)));
+ QCOMPARE(qVariantValue<Number>(o.property("number")), Number(42));
+ {
+ qRegisterAnimationInterpolator<Number>(numberInterpolator);
+ QPropertyAnimation anim(&o, "number");
+ anim.setStartValue(qVariantFromValue<Number>(Number(0)));
+ anim.setEndValue(qVariantFromValue<Number>(Number(100)));
+ anim.setDuration(1000);
+ anim.start();
+ anim.pause();
+ anim.setCurrentTime(100);
+ Number t(qVariantValue<Number>(o.property("number")));
+ QCOMPARE(t, Number(10));
+ anim.setCurrentTime(500);
+ QCOMPARE(qVariantValue<Number>(o.property("number")), Number(50));
+ }
+ {
+ qRegisterAnimationInterpolator<QPointF>(xaxisQPointInterpolator);
+ QPropertyAnimation anim(&o, "point");
+ anim.setStartValue(QPointF(0,0));
+ anim.setEndValue(QPointF(100, 100));
+ anim.setDuration(1000);
+ anim.start();
+ anim.pause();
+ anim.setCurrentTime(100);
+ QCOMPARE(o.property("point"), QVariant(QPointF(10, 0)));
+ anim.setCurrentTime(500);
+ QCOMPARE(o.property("point"), QVariant(QPointF(50, 0)));
+ }
+ {
+ // unregister it and see if we get back the default behaviour
+ qRegisterAnimationInterpolator<QPointF>(0);
+ QPropertyAnimation anim(&o, "point");
+ anim.setStartValue(QPointF(0,0));
+ anim.setEndValue(QPointF(100, 100));
+ anim.setDuration(1000);
+ anim.start();
+ anim.pause();
+ anim.setCurrentTime(100);
+ QCOMPARE(o.property("point").toPointF(), QPointF(10, 10));
+ anim.setCurrentTime(500);
+ QCOMPARE(o.property("point").toPointF(), QPointF(50, 50));
+ }
+
+ {
+ // Interpolate a qreal property with a int interpolator
+ AnimationObject o1;
+ o1.setRealValue(42.42);
+ QPropertyAnimation anim(&o1, "realValue");
+ anim.setStartValue(0);
+ anim.setEndValue(100);
+ anim.start();
+ QCOMPARE(o1.realValue(), qreal(0));
+ anim.setCurrentTime(250);
+ QCOMPARE(o1.realValue(), qreal(100));
+ }
+}
+
+Q_DECLARE_METATYPE(QVariant)
+
+void tst_QPropertyAnimation::setStartEndValues_data()
+{
+ QTest::addColumn<QByteArray>("propertyName");
+ QTest::addColumn<QVariant>("initialValue");
+ QTest::addColumn<QVariant>("startValue");
+ QTest::addColumn<QVariant>("endValue");
+
+ QTest::newRow("dynamic property") << QByteArray("ole") << QVariant(42) << QVariant(0) << QVariant(10);
+ QTest::newRow("real property, with unmatching types") << QByteArray("x") << QVariant(42.) << QVariant(0) << QVariant(10.);
+}
+
+void tst_QPropertyAnimation::setStartEndValues()
+{
+ MyObject object;
+ QFETCH(QByteArray, propertyName);
+ QFETCH(QVariant, initialValue);
+ QFETCH(QVariant, startValue);
+ QFETCH(QVariant, endValue);
+
+ //this tests the start value, end value and default start value
+ object.setProperty(propertyName, initialValue);
+ QPropertyAnimation anim(&object, propertyName);
+ QVariantAnimation::KeyValues values;
+ QCOMPARE(anim.keyValues(), values);
+
+ //let's add a start value
+ anim.setStartValue(startValue);
+ values << QVariantAnimation::KeyValue(0, startValue);
+ QCOMPARE(anim.keyValues(), values);
+
+ anim.setEndValue(endValue);
+ values << QVariantAnimation::KeyValue(1, endValue);
+ QCOMPARE(anim.keyValues(), values);
+
+ //now we can play with objects
+ QCOMPARE(object.property(propertyName).toDouble(), initialValue.toDouble());
+ anim.start();
+ QVERIFY(anim.startValue().isValid());
+ QCOMPARE(object.property(propertyName), anim.startValue());
+ anim.setCurrentTime(anim.duration()/2);
+ QCOMPARE(object.property(propertyName).toDouble(), (startValue.toDouble() + endValue.toDouble())/2 ); //just in the middle of the animation
+ anim.setCurrentTime(anim.duration()); //we go to the end of the animation
+ QCOMPARE(anim.state(), QAnimationGroup::Stopped); //it should have stopped
+ QVERIFY(anim.endValue().isValid());
+ QCOMPARE(object.property(propertyName), anim.endValue()); //end of the animations
+
+ //now we remove the explicit start value and test the implicit one
+ anim.stop();
+ object.setProperty(propertyName, initialValue);
+
+ //let's reset the start value
+ values.remove(0);
+ anim.setStartValue(QVariant());
+ QCOMPARE(anim.keyValues(), values);
+ QVERIFY(!anim.startValue().isValid());
+
+ anim.start();
+ QCOMPARE(object.property(propertyName), initialValue);
+ anim.setCurrentTime(anim.duration()/2);
+ QCOMPARE(object.property(propertyName).toDouble(), (initialValue.toDouble() + endValue.toDouble())/2 ); //just in the middle of the animation
+ anim.setCurrentTime(anim.duration()); //we go to the end of the animation
+ QCOMPARE(anim.state(), QAnimationGroup::Stopped); //it should have stopped
+ QVERIFY(anim.endValue().isValid());
+ QCOMPARE(object.property(propertyName), anim.endValue()); //end of the animations
+
+ //now we set back the startValue
+ anim.setStartValue(startValue);
+ QVERIFY(anim.startValue().isValid());
+ anim.start();
+ QCOMPARE(object.property(propertyName), startValue);
+}
+
+void tst_QPropertyAnimation::zeroDurationStart()
+{
+ QPropertyAnimation anim;
+ QSignalSpy spy(&anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ anim.setDuration(0);
+ QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
+ anim.start();
+ //the animation stops immediately
+ QCOMPARE(anim.state(), QAbstractAnimation::Stopped);
+ QCOMPARE(spy.count(), 2);
+
+ //let's check the first state change
+ const QVariantList firstChange = spy.first();
+ //old state
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(firstChange.first()), QAbstractAnimation::Stopped);
+ //new state
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(firstChange.last()), QAbstractAnimation::Running);
+
+ //let's check the first state change
+ const QVariantList secondChange = spy.last();
+ //old state
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(secondChange.first()), QAbstractAnimation::Running);
+ //new state
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(secondChange.last()), QAbstractAnimation::Stopped);
+}
+
+#define Pause 1
+#define Start 2
+#define Resume 3
+#define Stop 4
+
+void tst_QPropertyAnimation::operationsInStates_data()
+{
+ QTest::addColumn<QAbstractAnimation::State>("originState");
+ QTest::addColumn<int>("operation");
+ QTest::addColumn<QString>("expectedWarning");
+ QTest::addColumn<QAbstractAnimation::State>("expectedState");
+
+ QString pauseWarn(QLatin1String("QAbstractAnimation::pause: Cannot pause a stopped animation"));
+ QString resumeWarn(QLatin1String("QAbstractAnimation::resume: Cannot resume an animation that is not paused"));
+
+ QTest::newRow("S-pause") << QAbstractAnimation::Stopped << Pause << pauseWarn << QAbstractAnimation::Stopped;
+ QTest::newRow("S-start") << QAbstractAnimation::Stopped << Start << QString() << QAbstractAnimation::Running;
+ QTest::newRow("S-resume") << QAbstractAnimation::Stopped << Resume << resumeWarn << QAbstractAnimation::Stopped;
+ QTest::newRow("S-stop") << QAbstractAnimation::Stopped << Stop << QString() << QAbstractAnimation::Stopped;
+
+ QTest::newRow("P-pause") << QAbstractAnimation::Paused << Pause << QString() << QAbstractAnimation::Paused;
+ QTest::newRow("P-start") << QAbstractAnimation::Paused << Start << QString() << QAbstractAnimation::Running;
+ QTest::newRow("P-resume") << QAbstractAnimation::Paused << Resume << QString() << QAbstractAnimation::Running;
+ QTest::newRow("P-stop") << QAbstractAnimation::Paused << Stop << QString() << QAbstractAnimation::Stopped;
+
+ QTest::newRow("R-pause") << QAbstractAnimation::Running << Pause << QString() << QAbstractAnimation::Paused;
+ QTest::newRow("R-start") << QAbstractAnimation::Running << Start << QString() << QAbstractAnimation::Running;
+ QTest::newRow("R-resume") << QAbstractAnimation::Running << Resume << resumeWarn << QAbstractAnimation::Running;
+ QTest::newRow("R-stop") << QAbstractAnimation::Running << Stop << QString() << QAbstractAnimation::Stopped;
+}
+
+void tst_QPropertyAnimation::operationsInStates()
+{
+/**
+ * | pause() |start() |resume() |stop()
+ * ----------+------------+-----------+-----------+-------------------+
+ * Stopped | Stopped |Running |Stopped |Stopped |
+ * _| qWarning |restart |qWarning | |
+ * Paused | Paused |Running |Running |Stopped |
+ * _| | | | |
+ * Running | Paused |Running |Running |Stopped |
+ * | |restart |qWarning | |
+ * ----------+------------+-----------+-----------+-------------------+
+**/
+
+ QFETCH(QAbstractAnimation::State, originState);
+ QFETCH(int, operation);
+ QFETCH(QString, expectedWarning);
+ QFETCH(QAbstractAnimation::State, expectedState);
+
+ QObject o;
+ o.setProperty("ole", 42);
+ QPropertyAnimation anim(&o, "ole");
+ QSignalSpy spy(&anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ anim.stop();
+ switch (originState) {
+ case QAbstractAnimation::Stopped:
+ break;
+ case QAbstractAnimation::Paused:
+ anim.start();
+ anim.pause();
+ break;
+ case QAbstractAnimation::Running:
+ anim.start();
+ break;
+ }
+ if (!expectedWarning.isEmpty()) {
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning));
+ }
+ QCOMPARE(anim.state(), originState);
+ switch (operation) {
+ case Pause:
+ anim.pause();
+ break;
+ case Start:
+ anim.start();
+ break;
+ case Resume:
+ anim.resume();
+ break;
+ case Stop:
+ anim.stop();
+ break;
+ }
+
+ QCOMPARE(anim.state(), expectedState);
+}
+#undef Pause
+#undef Start
+#undef Resume
+#undef Stop
+
+void tst_QPropertyAnimation::oneKeyValue()
+{
+ QObject o;
+ o.setProperty("ole", 42);
+ QCOMPARE(o.property("ole").toInt(), 42);
+
+ QPropertyAnimation animation(&o, "ole");
+ animation.setStartValue(43);
+ animation.setEndValue(44);
+ animation.setDuration(100);
+
+ animation.setCurrentTime(0);
+
+ QVERIFY(animation.currentValue().isValid());
+ QCOMPARE(animation.currentValue().toInt(), 43);
+ QCOMPARE(o.property("ole").toInt(), 42);
+
+ // remove the last key value
+ animation.setKeyValueAt(1.0, QVariant());
+
+ // we will neither interpolate, nor update the current value
+ // since there is only one 1 key value defined
+ animation.setCurrentTime(100);
+
+ // the animation should not have been modified
+ QVERIFY(animation.currentValue().isValid());
+ QCOMPARE(animation.currentValue().toInt(), 43);
+ QCOMPARE(o.property("ole").toInt(), 42);
+}
+
+void tst_QPropertyAnimation::updateOnSetKeyValues()
+{
+ QObject o;
+ o.setProperty("ole", 100);
+ QCOMPARE(o.property("ole").toInt(), 100);
+
+ QPropertyAnimation animation(&o, "ole");
+ animation.setStartValue(100);
+ animation.setEndValue(200);
+ animation.setDuration(100);
+
+ animation.setCurrentTime(50);
+ QCOMPARE(animation.currentValue().toInt(), 150);
+ animation.setKeyValueAt(0.0, 300);
+ QCOMPARE(animation.currentValue().toInt(), 250);
+
+ o.setProperty("ole", 100);
+ QPropertyAnimation animation2(&o, "ole");
+ QVariantAnimation::KeyValues kValues;
+ kValues << QVariantAnimation::KeyValue(0.0, 100) << QVariantAnimation::KeyValue(1.0, 200);
+ animation2.setKeyValues(kValues);
+ animation2.setDuration(100);
+ animation2.setCurrentTime(50);
+ QCOMPARE(animation2.currentValue().toInt(), 150);
+
+ kValues.clear();
+ kValues << QVariantAnimation::KeyValue(0.0, 300) << QVariantAnimation::KeyValue(1.0, 200);
+ animation2.setKeyValues(kValues);
+
+ QCOMPARE(animation2.currentValue().toInt(), animation.currentValue().toInt());
+}
+
+QTEST_MAIN(tst_QPropertyAnimation)
+#include "tst_qpropertyanimation.moc"
diff --git a/tests/auto/qringbuffer/qringbuffer.pro b/tests/auto/qringbuffer/qringbuffer.pro
new file mode 100644
index 0000000..91fb0a0
--- /dev/null
+++ b/tests/auto/qringbuffer/qringbuffer.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+SOURCES += tst_qringbuffer.cpp
+
+QT = core
+
+
diff --git a/tests/auto/qringbuffer/tst_qringbuffer.cpp b/tests/auto/qringbuffer/tst_qringbuffer.cpp
new file mode 100644
index 0000000..c741c2e
--- /dev/null
+++ b/tests/auto/qringbuffer/tst_qringbuffer.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** 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 <QtTest/QtTest>
+
+#include <private/qringbuffer_p.h>
+
+class tst_QRingBuffer : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QRingBuffer();
+ virtual ~tst_QRingBuffer();
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+private slots:
+ void readPointerAtPositionWriteRead();
+ void readPointerAtPositionEmptyRead();
+ void readPointerAtPositionWithHead();
+ void readPointerAtPositionReadTooMuch();
+ void sizeWhenEmpty();
+ void sizeWhenReservedAndChopped();
+ void sizeWhenReserved();
+};
+
+tst_QRingBuffer::tst_QRingBuffer()
+{
+}
+
+tst_QRingBuffer::~tst_QRingBuffer()
+{
+}
+
+void tst_QRingBuffer::initTestCase()
+{
+}
+
+void tst_QRingBuffer::cleanupTestCase()
+{
+}
+
+void tst_QRingBuffer::sizeWhenReserved()
+{
+ QRingBuffer ringBuffer;
+ ringBuffer.reserve(5);
+
+ QCOMPARE(ringBuffer.size(), 5);
+}
+
+void tst_QRingBuffer::sizeWhenReservedAndChopped()
+{
+ QRingBuffer ringBuffer;
+ ringBuffer.reserve(31337);
+ ringBuffer.chop(31337);
+
+ QCOMPARE(ringBuffer.size(), 0);
+}
+
+void tst_QRingBuffer::sizeWhenEmpty()
+{
+ QRingBuffer ringBuffer;
+
+ QCOMPARE(ringBuffer.size(), 0);
+}
+
+void tst_QRingBuffer::readPointerAtPositionReadTooMuch()
+{
+ QRingBuffer ringBuffer;
+
+ qint64 length;
+ const char *buf = ringBuffer.readPointerAtPosition(42, length);
+ QVERIFY(buf == 0);
+ QVERIFY(length == 0);
+}
+
+void tst_QRingBuffer::readPointerAtPositionWithHead()
+{
+ QRingBuffer ringBuffer;
+ char *buf = ringBuffer.reserve(4);
+ memcpy (buf, "0123", 4);
+ ringBuffer.free(2);
+
+ // ringBuffer should have stayed the same except
+ // its head it had moved to position 2
+ qint64 length;
+ const char* buf2 = ringBuffer.readPointerAtPosition(0, length);
+
+ QCOMPARE(length, qint64(2));
+ QVERIFY(*buf2 == '2');
+ QVERIFY(*(buf2+1) == '3');
+
+ // advance 2 more, ringBuffer should be empty then
+ ringBuffer.free(2);
+ buf2 = ringBuffer.readPointerAtPosition(0, length);
+ QCOMPARE(length, qint64(0));
+ QVERIFY(buf2 == 0);
+}
+
+void tst_QRingBuffer::readPointerAtPositionEmptyRead()
+{
+ QRingBuffer ringBuffer;
+
+ qint64 length;
+ const char *buf = ringBuffer.readPointerAtPosition(0, length);
+ QVERIFY(buf == 0);
+ QVERIFY(length == 0);
+}
+
+void tst_QRingBuffer::readPointerAtPositionWriteRead()
+{
+ //create some data
+ QBuffer inData;
+ inData.open(QIODevice::ReadWrite);
+ inData.putChar(0x42);
+ inData.putChar(0x23);
+ inData.write("Qt rocks!");
+ for (int i = 0; i < 5000; i++)
+ inData.write(QString("Number %1").arg(i).toUtf8());
+ inData.reset();
+ QVERIFY(inData.size() > 0);
+
+ //put the inData in the QRingBuffer
+ QRingBuffer ringBuffer;
+ qint64 remaining = inData.size();
+ while (remaining > 0) {
+ // write in chunks of 50 bytes
+ // this ensures there will be multiple QByteArrays inside the QRingBuffer
+ // since QRingBuffer is then only using individual arrays of around 4000 bytes
+ qint64 thisWrite = qMin(remaining, qint64(50));
+ char *pos = ringBuffer.reserve(thisWrite);
+ inData.read(pos, thisWrite);
+ remaining -= thisWrite;
+ }
+ // was data put into it?
+ QVERIFY(ringBuffer.size() > 0);
+ QCOMPARE(qint64(ringBuffer.size()), inData.size());
+
+ //read from the QRingBuffer in loop, put back into another QBuffer
+ QBuffer outData;
+ outData.open(QIODevice::ReadWrite);
+ remaining = ringBuffer.size();
+ while (remaining > 0) {
+ qint64 thisRead;
+ // always try to read as much as possible
+ const char *buf = ringBuffer.readPointerAtPosition(ringBuffer.size() - remaining, thisRead);
+ outData.write(buf, thisRead);
+ remaining -= thisRead;
+ }
+ outData.reset();
+
+ QVERIFY(outData.size() > 0);
+
+ // was the data read from the QRingBuffer the same as the one written into it?
+ QCOMPARE(outData.size(), inData.size());
+ QVERIFY(outData.buffer().startsWith(inData.buffer()));
+}
+
+
+QTEST_APPLESS_MAIN(tst_QRingBuffer)
+#include "tst_qringbuffer.moc"
diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp
index cd797d9..bbe11a1 100644
--- a/tests/auto/qscriptengine/tst_qscriptengine.cpp
+++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp
@@ -636,9 +636,21 @@ void tst_QScriptEngine::newQObject()
QScriptValue val = ret.property("objectName");
QVERIFY(val.isString());
}
+ // "promote" variant object to QObject
+ {
+ QScriptValue obj = eng.newVariant(123);
+ QVERIFY(obj.isVariant());
+ QScriptValue originalProto = obj.prototype();
+ QScriptValue ret = eng.newQObject(obj, this);
+ QVERIFY(ret.isQObject());
+ QVERIFY(ret.strictlyEquals(obj));
+ QVERIFY(obj.isQObject());
+ QCOMPARE(ret.toQObject(), (QObject *)this);
+ QVERIFY(ret.prototype().strictlyEquals(originalProto));
+ }
// replace QObject* of existing object
{
- QScriptValue object = eng.newQObject(this);
+ QScriptValue object = eng.newVariant(123);
QScriptValue originalProto = object.prototype();
QObject otherQObject;
QScriptValue ret = eng.newQObject(object, &otherQObject);
diff --git a/tests/auto/qscriptqobject/tst_qscriptqobject.cpp b/tests/auto/qscriptqobject/tst_qscriptqobject.cpp
index 4d3e92d..082c6b7 100644
--- a/tests/auto/qscriptqobject/tst_qscriptqobject.cpp
+++ b/tests/auto/qscriptqobject/tst_qscriptqobject.cpp
@@ -111,6 +111,7 @@ class MyQObject : public QObject
Q_PROPERTY(int readOnlyProperty READ readOnlyProperty)
Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
Q_PROPERTY(CustomType propWithCustomType READ propWithCustomType WRITE setPropWithCustomType)
+ Q_PROPERTY(Policy enumProperty READ enumProperty WRITE setEnumProperty)
Q_ENUMS(Policy Strategy)
Q_FLAGS(Ability)
@@ -148,6 +149,7 @@ public:
m_hiddenValue(456.0),
m_writeOnlyValue(789),
m_readOnlyValue(987),
+ m_enumValue(BarPolicy),
m_qtFunctionInvoked(-1)
{ }
@@ -209,6 +211,11 @@ public:
void setPropWithCustomType(const CustomType &c)
{ m_customType = c; }
+ Policy enumProperty() const
+ { return m_enumValue; }
+ void setEnumProperty(Policy policy)
+ { m_enumValue = policy; }
+
int qtFunctionInvoked() const
{ return m_qtFunctionInvoked; }
@@ -259,8 +266,8 @@ public:
{ m_qtFunctionInvoked = 36; m_actuals << policy; }
Q_INVOKABLE Policy myInvokableReturningEnum()
{ m_qtFunctionInvoked = 37; return BazPolicy; }
- Q_INVOKABLE MyQObject::Policy myInvokableReturningQualifiedEnum()
- { m_qtFunctionInvoked = 38; return BazPolicy; }
+ Q_INVOKABLE MyQObject::Strategy myInvokableReturningQualifiedEnum()
+ { m_qtFunctionInvoked = 38; return BazStrategy; }
Q_INVOKABLE QVector<int> myInvokableReturningVectorOfInt()
{ m_qtFunctionInvoked = 11; return QVector<int>(); }
Q_INVOKABLE void myInvokableWithVectorOfIntArg(const QVector<int> &)
@@ -330,6 +337,10 @@ public:
{ emit mySignalWithDefaultArg(arg); }
void emitMySignalWithDefaultArg()
{ emit mySignalWithDefaultArg(); }
+ void emitMySignalWithVariantArg(const QVariant &arg)
+ { emit mySignalWithVariantArg(arg); }
+ void emitMySignalWithScriptEngineArg(QScriptEngine *arg)
+ { emit mySignalWithScriptEngineArg(arg); }
public Q_SLOTS:
void mySlot()
@@ -392,6 +403,8 @@ Q_SIGNALS:
void myOtherOverloadedSignal(const QString &arg);
void myOtherOverloadedSignal(int arg);
void mySignalWithDefaultArg(int arg = 123);
+ void mySignalWithVariantArg(const QVariant &arg);
+ void mySignalWithScriptEngineArg(QScriptEngine *arg);
protected:
void connectNotify(const char *signal) {
@@ -414,6 +427,7 @@ protected:
int m_readOnlyValue;
QKeySequence m_shortcut;
CustomType m_customType;
+ Policy m_enumValue;
int m_qtFunctionInvoked;
QVariantList m_actuals;
QByteArray m_connectedSignal;
@@ -421,6 +435,7 @@ protected:
};
Q_DECLARE_METATYPE(MyQObject*)
+Q_DECLARE_METATYPE(MyQObject::Policy)
class MyOtherQObject : public MyQObject
{
@@ -534,6 +549,24 @@ static QScriptValue getSetProperty(QScriptContext *ctx, QScriptEngine *)
return ctx->callee().property("value");
}
+static QScriptValue policyToScriptValue(QScriptEngine *engine, const MyQObject::Policy &policy)
+{
+ return qScriptValueFromValue(engine, policy);
+}
+
+static void policyFromScriptValue(const QScriptValue &value, MyQObject::Policy &policy)
+{
+ QString str = value.toString();
+ if (str == QLatin1String("red"))
+ policy = MyQObject::FooPolicy;
+ else if (str == QLatin1String("green"))
+ policy = MyQObject::BarPolicy;
+ else if (str == QLatin1String("blue"))
+ policy = MyQObject::BazPolicy;
+ else
+ policy = (MyQObject::Policy)-1;
+}
+
void tst_QScriptExtQObject::getSetStaticProperty()
{
QCOMPARE(m_engine->evaluate("myObject.noSuchProperty").isUndefined(), true);
@@ -755,6 +788,31 @@ void tst_QScriptExtQObject::getSetStaticProperty()
QScriptValue::ReadOnly);
}
+ // enum property
+ QCOMPARE(m_myObject->enumProperty(), MyQObject::BarPolicy);
+ {
+ QScriptValue val = m_engine->evaluate("myObject.enumProperty");
+ QVERIFY(val.isNumber());
+ QCOMPARE(val.toInt32(), (int)MyQObject::BarPolicy);
+ }
+ m_engine->evaluate("myObject.enumProperty = 2");
+ QCOMPARE(m_myObject->enumProperty(), MyQObject::BazPolicy);
+ m_engine->evaluate("myObject.enumProperty = 'BarPolicy'");
+ QCOMPARE(m_myObject->enumProperty(), MyQObject::BarPolicy);
+ m_engine->evaluate("myObject.enumProperty = 'ScoobyDoo'");
+ // ### ouch! Shouldn't QMetaProperty::write() rather not change the value...?
+ QCOMPARE(m_myObject->enumProperty(), (MyQObject::Policy)-1);
+ // enum property with custom conversion
+ qScriptRegisterMetaType<MyQObject::Policy>(m_engine, policyToScriptValue, policyFromScriptValue);
+ m_engine->evaluate("myObject.enumProperty = 'red'");
+ QCOMPARE(m_myObject->enumProperty(), MyQObject::FooPolicy);
+ m_engine->evaluate("myObject.enumProperty = 'green'");
+ QCOMPARE(m_myObject->enumProperty(), MyQObject::BarPolicy);
+ m_engine->evaluate("myObject.enumProperty = 'blue'");
+ QCOMPARE(m_myObject->enumProperty(), MyQObject::BazPolicy);
+ m_engine->evaluate("myObject.enumProperty = 'nada'");
+ QCOMPARE(m_myObject->enumProperty(), (MyQObject::Policy)-1);
+
// auto-dereferencing of pointers
{
QBrush b = QColor(0xCA, 0xFE, 0xBA, 0xBE);
@@ -1505,6 +1563,29 @@ void tst_QScriptExtQObject::connectAndDisconnect()
m_myObject->emitMyOtherOverloadedSignal(123);
QVERIFY(!m_engine->evaluate("gotSignal").toBoolean());
+ // signal with QVariant arg: argument conversion should work
+ m_myObject->clearConnectedSignal();
+ QVERIFY(m_engine->evaluate("myObject.mySignalWithVariantArg.connect(myHandler)").isUndefined());
+ QCOMPARE(m_myObject->connectedSignal().constData(), SIGNAL(mySignalWithVariantArg(QVariant)));
+ m_engine->evaluate("gotSignal = false");
+ m_myObject->emitMySignalWithVariantArg(123);
+ QCOMPARE(m_engine->evaluate("gotSignal").toBoolean(), true);
+ QCOMPARE(m_engine->evaluate("signalArgs.length").toNumber(), 1.0);
+ QCOMPARE(m_engine->evaluate("signalArgs[0]").toNumber(), 123.0);
+ QVERIFY(m_engine->evaluate("myObject.mySignalWithVariantArg.disconnect(myHandler)").isUndefined());
+
+ // signal with argument type that's unknown to the meta-type system
+ m_myObject->clearConnectedSignal();
+ QVERIFY(m_engine->evaluate("myObject.mySignalWithScriptEngineArg.connect(myHandler)").isUndefined());
+ QCOMPARE(m_myObject->connectedSignal().constData(), SIGNAL(mySignalWithScriptEngineArg(QScriptEngine*)));
+ m_engine->evaluate("gotSignal = false");
+ QTest::ignoreMessage(QtWarningMsg, "QScriptEngine: Unable to handle unregistered datatype 'QScriptEngine*' when invoking handler of signal MyQObject::mySignalWithScriptEngineArg(QScriptEngine*)");
+ m_myObject->emitMySignalWithScriptEngineArg(m_engine);
+ QCOMPARE(m_engine->evaluate("gotSignal").toBoolean(), true);
+ QCOMPARE(m_engine->evaluate("signalArgs.length").toNumber(), 1.0);
+ QVERIFY(m_engine->evaluate("signalArgs[0]").isUndefined());
+ QVERIFY(m_engine->evaluate("myObject.mySignalWithScriptEngineArg.disconnect(myHandler)").isUndefined());
+
// connect(object, function)
m_engine->evaluate("otherObject = { name:'foo' }");
QVERIFY(m_engine->evaluate("myObject.mySignal.connect(otherObject, myHandler)").isUndefined());
@@ -1883,6 +1964,16 @@ void tst_QScriptExtQObject::classEnums()
QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), int(MyQObject::BazPolicy));
m_myObject->resetQtFunctionInvoked();
+ QCOMPARE(m_engine->evaluate("myObject.myInvokableWithEnumArg('BarPolicy')").isUndefined(), true);
+ QCOMPARE(m_myObject->qtFunctionInvoked(), 10);
+ QCOMPARE(m_myObject->qtFunctionActuals().size(), 1);
+ QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), int(MyQObject::BarPolicy));
+
+ m_myObject->resetQtFunctionInvoked();
+ QVERIFY(m_engine->evaluate("myObject.myInvokableWithEnumArg('NoSuchPolicy')").isError());
+ QCOMPARE(m_myObject->qtFunctionInvoked(), -1);
+
+ m_myObject->resetQtFunctionInvoked();
QCOMPARE(m_engine->evaluate("myObject.myInvokableWithQualifiedEnumArg(MyQObject.BazPolicy)").isUndefined(), true);
QCOMPARE(m_myObject->qtFunctionInvoked(), 36);
QCOMPARE(m_myObject->qtFunctionActuals().size(), 1);
diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp
index bf91001..ad1080a 100644
--- a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp
+++ b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp
@@ -1301,6 +1301,27 @@ void tst_QScriptValue::toVariant()
QCOMPARE(str.toVariant(), QVariant(QString("ciao")));
QCOMPARE(qscriptvalue_cast<QVariant>(str), QVariant(QString("ciao")));
}
+
+ // array
+ {
+ QVariantList listIn;
+ listIn << 123 << "hello";
+ QScriptValue array = qScriptValueFromValue(&eng, listIn);
+ QVERIFY(array.isArray());
+ QCOMPARE(array.property("length").toInt32(), 2);
+ QVariant ret = array.toVariant();
+ QCOMPARE(ret.type(), QVariant::List);
+ QVariantList listOut = ret.toList();
+ QCOMPARE(listOut.size(), listIn.size());
+ for (int i = 0; i < listIn.size(); ++i)
+ QVERIFY(listOut.at(i) == listIn.at(i));
+ // round-trip conversion
+ QScriptValue array2 = qScriptValueFromValue(&eng, ret);
+ QVERIFY(array2.isArray());
+ QCOMPARE(array2.property("length").toInt32(), array.property("length").toInt32());
+ for (int i = 0; i < array.property("length").toInt32(); ++i)
+ QVERIFY(array2.property(i).strictlyEquals(array.property(i)));
+ }
}
// unfortunately, this is necessary in order to do qscriptvalue_cast<QPushButton*>(...)
diff --git a/tests/auto/qsequentialanimationgroup/qsequentialanimationgroup.pro b/tests/auto/qsequentialanimationgroup/qsequentialanimationgroup.pro
new file mode 100644
index 0000000..ad861c3
--- /dev/null
+++ b/tests/auto/qsequentialanimationgroup/qsequentialanimationgroup.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT = core gui
+SOURCES += tst_qsequentialanimationgroup.cpp
+
+
diff --git a/tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp b/tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp
new file mode 100644
index 0000000..0631343
--- /dev/null
+++ b/tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp
@@ -0,0 +1,1649 @@
+/****************************************************************************
+**
+** 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 <QtTest/QtTest>
+#include "../../shared/util.h"
+
+#include <QtCore/qanimationgroup.h>
+#include <QtCore/qsequentialanimationgroup.h>
+
+//TESTED_CLASS=QSequentialAnimationGroup
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QAbstractAnimation::State)
+Q_DECLARE_METATYPE(QAbstractAnimation*)
+
+class tst_QSequentialAnimationGroup : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QSequentialAnimationGroup();
+ virtual ~tst_QSequentialAnimationGroup();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private slots:
+ void construction();
+ void setCurrentTime();
+ void setCurrentTimeWithUncontrolledAnimation();
+ void seekingForwards();
+ void seekingBackwards();
+ void pauseAndResume();
+ void restart();
+ void looping();
+ void startDelay();
+ void clearGroup();
+ void groupWithZeroDurationAnimations();
+ void propagateGroupUpdateToChildren();
+ void updateChildrenWithRunningGroup();
+ void deleteChildrenWithRunningGroup();
+ void startChildrenWithStoppedGroup();
+ void stopGroupWithRunningChild();
+ void startGroupWithRunningChild();
+ void zeroDurationAnimation();
+ void stopUncontrolledAnimations();
+ void finishWithUncontrolledAnimation();
+ void addRemoveAnimation();
+ void currentAnimation();
+ void currentAnimationWithZeroDuration();
+ void insertAnimation();
+ void clearAnimations();
+};
+
+tst_QSequentialAnimationGroup::tst_QSequentialAnimationGroup()
+{
+}
+
+tst_QSequentialAnimationGroup::~tst_QSequentialAnimationGroup()
+{
+}
+
+void tst_QSequentialAnimationGroup::init()
+{
+ qRegisterMetaType<QAbstractAnimation::State>("QAbstractAnimation::State");
+ qRegisterMetaType<QAbstractAnimation*>("QAbstractAnimation*");
+}
+
+void tst_QSequentialAnimationGroup::cleanup()
+{
+}
+
+void tst_QSequentialAnimationGroup::construction()
+{
+ QSequentialAnimationGroup animationgroup;
+}
+
+class AnimationObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+public:
+ AnimationObject(int startValue = 0)
+ : v(startValue)
+ { }
+
+ int value() const { return v; }
+ void setValue(int value) { v = value; }
+
+ int v;
+};
+
+class TestAnimation : public QVariantAnimation
+{
+ Q_OBJECT
+public:
+ virtual void updateCurrentValue(const QVariant &value) { Q_UNUSED(value)};
+ virtual void updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+ {
+ Q_UNUSED(oldState)
+ Q_UNUSED(newState)
+ };
+};
+
+class UncontrolledAnimation : public QPropertyAnimation
+{
+ Q_OBJECT
+public:
+ UncontrolledAnimation(QObject *target, const QByteArray &propertyName, QObject *parent = 0)
+ : QPropertyAnimation(target, propertyName, parent)
+ {
+ setDuration(250);
+ }
+
+ int duration() const { return -1; /* not time driven */ }
+
+protected:
+ void updateCurrentTime(int msecs)
+ {
+ QPropertyAnimation::updateCurrentTime(msecs);
+ if (msecs >= QPropertyAnimation::duration())
+ stop();
+ }
+};
+
+void tst_QSequentialAnimationGroup::setCurrentTime()
+{
+ AnimationObject s_o1;
+ AnimationObject s_o2;
+ AnimationObject s_o3;
+
+ // sequence operating on same object/property
+ QAnimationGroup *sequence = new QSequentialAnimationGroup();
+ QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ a2_s_o1->setLoopCount(3);
+ sequence->addAnimation(a1_s_o1);
+ sequence->addAnimation(a2_s_o1);
+ sequence->addAnimation(a3_s_o1);
+
+ // sequence operating on different object/properties
+ QAnimationGroup *sequence2 = new QSequentialAnimationGroup();
+ QVariantAnimation *a1_s_o2 = new QPropertyAnimation(&s_o2, "value");
+ QVariantAnimation *a1_s_o3 = new QPropertyAnimation(&s_o3, "value");
+ sequence2->addAnimation(a1_s_o2);
+ sequence2->addAnimation(a1_s_o3);
+
+ QSequentialAnimationGroup group;
+ group.addAnimation(sequence);
+ group.addAnimation(sequence2);
+
+ // Current time = 1
+ group.setCurrentTime(1);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(sequence2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
+
+ QCOMPARE(group.currentTime(), 1);
+ QCOMPARE(sequence->currentTime(), 1);
+ QCOMPARE(a1_s_o1->currentTime(), 1);
+ QCOMPARE(a2_s_o1->currentTime(), 0);
+ QCOMPARE(a3_s_o1->currentTime(), 0);
+ QCOMPARE(a1_s_o2->currentTime(), 0);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+
+ // Current time = 250
+ group.setCurrentTime(250);
+ QCOMPARE(group.currentTime(), 250);
+ QCOMPARE(sequence->currentTime(), 250);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 0);
+ QCOMPARE(a3_s_o1->currentTime(), 0);
+ QCOMPARE(a1_s_o2->currentTime(), 0);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+
+ // Current time = 251
+ group.setCurrentTime(251);
+ QCOMPARE(group.currentTime(), 251);
+ QCOMPARE(sequence->currentTime(), 251);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 1);
+ QCOMPARE(a2_s_o1->currentLoop(), 0);
+ QCOMPARE(a3_s_o1->currentTime(), 0);
+ QCOMPARE(sequence2->currentTime(), 0);
+ QCOMPARE(a1_s_o2->currentTime(), 0);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+
+ // Current time = 750
+ group.setCurrentTime(750);
+ QCOMPARE(group.currentTime(), 750);
+ QCOMPARE(sequence->currentTime(), 750);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 0);
+ QCOMPARE(a2_s_o1->currentLoop(), 2);
+ QCOMPARE(a3_s_o1->currentTime(), 0);
+ QCOMPARE(sequence2->currentTime(), 0);
+ QCOMPARE(a1_s_o2->currentTime(), 0);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+
+ // Current time = 1000
+ group.setCurrentTime(1000);
+ QCOMPARE(group.currentTime(), 1000);
+ QCOMPARE(sequence->currentTime(), 1000);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 2);
+ QCOMPARE(a3_s_o1->currentTime(), 0);
+ QCOMPARE(sequence2->currentTime(), 0);
+ QCOMPARE(a1_s_o2->currentTime(), 0);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+
+ // Current time = 1010
+ group.setCurrentTime(1010);
+ QCOMPARE(group.currentTime(), 1010);
+ QCOMPARE(sequence->currentTime(), 1010);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 2);
+ QCOMPARE(a3_s_o1->currentTime(), 10);
+ QCOMPARE(sequence2->currentTime(), 0);
+ QCOMPARE(a1_s_o2->currentTime(), 0);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+
+ // Current time = 1250
+ group.setCurrentTime(1250);
+ QCOMPARE(group.currentTime(), 1250);
+ QCOMPARE(sequence->currentTime(), 1250);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 2);
+ QCOMPARE(a3_s_o1->currentTime(), 250);
+ QCOMPARE(sequence2->currentTime(), 0);
+ QCOMPARE(a1_s_o2->currentTime(), 0);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+
+ // Current time = 1500
+ group.setCurrentTime(1500);
+ QCOMPARE(group.currentTime(), 1500);
+ QCOMPARE(sequence->currentTime(), 1250);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 2);
+ QCOMPARE(a3_s_o1->currentTime(), 250);
+ QCOMPARE(sequence2->currentTime(), 250);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+
+ // Current time = 1750
+ group.setCurrentTime(1750);
+ QCOMPARE(group.currentTime(), 1750);
+ QCOMPARE(sequence->currentTime(), 1250);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 2);
+ QCOMPARE(a3_s_o1->currentTime(), 250);
+ QCOMPARE(sequence2->currentTime(), 500);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(a1_s_o3->currentTime(), 250);
+
+ // Current time = 2000
+ group.setCurrentTime(2000);
+ QCOMPARE(group.currentTime(), 1750);
+ QCOMPARE(sequence->currentTime(), 1250);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 2);
+ QCOMPARE(a3_s_o1->currentTime(), 250);
+ QCOMPARE(sequence2->currentTime(), 500);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(a1_s_o3->currentTime(), 250);
+}
+
+void tst_QSequentialAnimationGroup::setCurrentTimeWithUncontrolledAnimation()
+{
+ AnimationObject s_o1;
+ AnimationObject s_o2;
+ AnimationObject t_o1;
+ AnimationObject t_o2;
+
+ // sequence operating on different object/properties
+ QAnimationGroup *sequence = new QSequentialAnimationGroup();
+ QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a1_s_o2 = new QPropertyAnimation(&s_o2, "value");
+ sequence->addAnimation(a1_s_o1);
+ sequence->addAnimation(a1_s_o2);
+
+ UncontrolledAnimation *notTimeDriven = new UncontrolledAnimation(&t_o1, "value");
+ QCOMPARE(notTimeDriven->totalDuration(), -1);
+
+ QVariantAnimation *loopsForever = new QPropertyAnimation(&t_o2, "value");
+ loopsForever->setLoopCount(-1);
+ QCOMPARE(loopsForever->totalDuration(), -1);
+
+ QSequentialAnimationGroup group;
+ group.addAnimation(sequence);
+ group.addAnimation(notTimeDriven);
+ group.addAnimation(loopsForever);
+ group.start();
+ group.pause(); // this allows the group to listen for the finish signal of its children
+
+ // Current time = 1
+ group.setCurrentTime(1);
+ QCOMPARE(group.state(), QAnimationGroup::Paused);
+ QCOMPARE(sequence->state(), QAnimationGroup::Paused);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Paused);
+ QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(notTimeDriven->state(), QAnimationGroup::Stopped);
+ QCOMPARE(loopsForever->state(), QAnimationGroup::Stopped);
+
+ QCOMPARE(group.currentTime(), 1);
+ QCOMPARE(sequence->currentTime(), 1);
+ QCOMPARE(a1_s_o1->currentTime(), 1);
+ QCOMPARE(a1_s_o2->currentTime(), 0);
+ QCOMPARE(notTimeDriven->currentTime(), 0);
+ QCOMPARE(loopsForever->currentTime(), 0);
+
+ // Current time = 250
+ group.setCurrentTime(250);
+ QCOMPARE(group.currentTime(), 250);
+ QCOMPARE(sequence->currentTime(), 250);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a1_s_o2->currentTime(), 0);
+ QCOMPARE(notTimeDriven->currentTime(), 0);
+ QCOMPARE(loopsForever->currentTime(), 0);
+
+ // Current time = 500
+ group.setCurrentTime(500);
+ QCOMPARE(group.currentTime(), 500);
+ QCOMPARE(sequence->currentTime(), 500);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(notTimeDriven->currentTime(), 0);
+ QCOMPARE(loopsForever->currentTime(), 0);
+ QCOMPARE(group.currentAnimation(), notTimeDriven);
+
+ // Current time = 505
+ group.setCurrentTime(505);
+ QCOMPARE(group.currentTime(), 505);
+ QCOMPARE(sequence->currentTime(), 500);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(notTimeDriven->currentTime(), 5);
+ QCOMPARE(loopsForever->currentTime(), 0);
+ QCOMPARE(group.currentAnimation(), notTimeDriven);
+ QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(notTimeDriven->state(), QAnimationGroup::Paused);
+ QCOMPARE(loopsForever->state(), QAnimationGroup::Stopped);
+
+ // Current time = 750 (end of notTimeDriven animation)
+ group.setCurrentTime(750);
+ QCOMPARE(group.currentTime(), 750);
+ QCOMPARE(sequence->currentTime(), 500);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(notTimeDriven->currentTime(), 250);
+ QCOMPARE(loopsForever->currentTime(), 0);
+ QCOMPARE(group.currentAnimation(), loopsForever);
+ QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(notTimeDriven->state(), QAnimationGroup::Stopped);
+ QCOMPARE(loopsForever->state(), QAnimationGroup::Paused);
+
+ // Current time = 800 (as notTimeDriven was finished at 750, loopsforever should still run)
+ group.setCurrentTime(800);
+ QCOMPARE(group.currentTime(), 800);
+ QCOMPARE(group.currentAnimation(), loopsForever);
+ QCOMPARE(sequence->currentTime(), 500);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(notTimeDriven->currentTime(), 250);
+ QCOMPARE(loopsForever->currentTime(), 50);
+
+ loopsForever->stop(); // this should stop the group
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(notTimeDriven->state(), QAnimationGroup::Stopped);
+ QCOMPARE(loopsForever->state(), QAnimationGroup::Stopped);
+}
+
+void tst_QSequentialAnimationGroup::seekingForwards()
+{
+ AnimationObject s_o1;
+ AnimationObject s_o2;
+ AnimationObject s_o3;
+
+ // sequence operating on same object/property
+ QAnimationGroup *sequence = new QSequentialAnimationGroup();
+ QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ a2_s_o1->setLoopCount(3);
+ sequence->addAnimation(a1_s_o1);
+ sequence->addAnimation(a2_s_o1);
+ sequence->addAnimation(a3_s_o1);
+
+ // sequence operating on different object/properties
+ QAnimationGroup *sequence2 = new QSequentialAnimationGroup();
+ QVariantAnimation *a1_s_o2 = new QPropertyAnimation(&s_o2, "value");
+ QVariantAnimation *a1_s_o3 = new QPropertyAnimation(&s_o3, "value");
+ sequence2->addAnimation(a1_s_o2);
+ sequence2->addAnimation(a1_s_o3);
+
+ QSequentialAnimationGroup group;
+ group.addAnimation(sequence);
+ group.addAnimation(sequence2);
+
+ // Current time = 1
+ group.setCurrentTime(1);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(sequence2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o3->state(), QAnimationGroup::Stopped);
+
+ QCOMPARE(group.currentTime(), 1);
+ QCOMPARE(sequence->currentTime(), 1);
+ QCOMPARE(a1_s_o1->currentTime(), 1);
+ QCOMPARE(a2_s_o1->currentTime(), 0);
+ QCOMPARE(a3_s_o1->currentTime(), 0);
+ QCOMPARE(sequence2->currentTime(), 0);
+ QCOMPARE(a1_s_o2->currentTime(), 0);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+
+ // Current time = 1500
+ group.setCurrentTime(1500);
+ QCOMPARE(group.currentTime(), 1500);
+ QCOMPARE(sequence->currentTime(), 1250);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 2);
+ QCOMPARE(a3_s_o1->currentTime(), 250);
+ QCOMPARE(sequence2->currentTime(), 250);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+
+ // this will restart the group
+ group.start();
+ group.pause();
+ QCOMPARE(group.state(), QAnimationGroup::Paused);
+ QCOMPARE(sequence->state(), QAnimationGroup::Paused);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Paused);
+ QCOMPARE(sequence2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o3->state(), QAnimationGroup::Stopped);
+
+ // Current time = 1750
+ group.setCurrentTime(1750);
+ QCOMPARE(group.currentTime(), 1750);
+ QCOMPARE(sequence->currentTime(), 1250);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 2);
+ QCOMPARE(a3_s_o1->currentTime(), 250);
+ QCOMPARE(sequence2->currentTime(), 500);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(a1_s_o3->currentTime(), 250);
+}
+
+void tst_QSequentialAnimationGroup::seekingBackwards()
+{
+ AnimationObject s_o1;
+ AnimationObject s_o2;
+ AnimationObject s_o3;
+
+ // sequence operating on same object/property
+ QAnimationGroup *sequence = new QSequentialAnimationGroup();
+ QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ a2_s_o1->setLoopCount(3);
+ sequence->addAnimation(a1_s_o1);
+ sequence->addAnimation(a2_s_o1);
+ sequence->addAnimation(a3_s_o1);
+
+ // sequence operating on different object/properties
+ QAnimationGroup *sequence2 = new QSequentialAnimationGroup();
+ QVariantAnimation *a1_s_o2 = new QPropertyAnimation(&s_o2, "value");
+ QVariantAnimation *a1_s_o3 = new QPropertyAnimation(&s_o3, "value");
+ sequence2->addAnimation(a1_s_o2);
+ sequence2->addAnimation(a1_s_o3);
+
+ QSequentialAnimationGroup group;
+ group.addAnimation(sequence);
+ group.addAnimation(sequence2);
+
+ group.start();
+
+ // Current time = 1600
+ group.setCurrentTime(1600);
+ QCOMPARE(group.currentTime(), 1600);
+ QCOMPARE(sequence->currentTime(), 1250);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 2);
+ QCOMPARE(a3_s_o1->currentTime(), 250);
+ QCOMPARE(sequence2->currentTime(), 350);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(a1_s_o3->currentTime(), 100);
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(sequence2->state(), QAnimationGroup::Running);
+ QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o3->state(), QAnimationGroup::Running);
+
+ // Seeking backwards, current time = 1
+ group.setCurrentTime(1);
+ QCOMPARE(group.currentTime(), 1);
+ QCOMPARE(sequence->currentTime(), 1);
+ QCOMPARE(a1_s_o1->currentTime(), 1);
+
+ QEXPECT_FAIL("", "rewinding in nested groups is considered as a restart from the children,"
+ "hence they don't reset from their current animation", Continue);
+ QCOMPARE(a2_s_o1->currentTime(), 0);
+ QEXPECT_FAIL("", "rewinding in nested groups is considered as a restart from the children,"
+ "hence they don't reset from their current animation", Continue);
+ QCOMPARE(a2_s_o1->currentLoop(), 0);
+ QEXPECT_FAIL("", "rewinding in nested groups is considered as a restart from the children,"
+ "hence they don't reset from their current animation", Continue);
+ QCOMPARE(a3_s_o1->currentTime(), 0);
+ QCOMPARE(sequence2->currentTime(), 0);
+ QCOMPARE(a1_s_o2->currentTime(), 0);
+ QCOMPARE(a1_s_o3->currentTime(), 0);
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(sequence->state(), QAnimationGroup::Running);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Running);
+ QCOMPARE(sequence2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o3->state(), QAnimationGroup::Stopped);
+
+ // Current time = 2000
+ group.setCurrentTime(2000);
+ QCOMPARE(group.currentTime(), 1750);
+ QCOMPARE(sequence->currentTime(), 1250);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 2);
+ QCOMPARE(a3_s_o1->currentTime(), 250);
+ QCOMPARE(sequence2->currentTime(), 500);
+ QCOMPARE(a1_s_o2->currentTime(), 250);
+ QCOMPARE(a1_s_o3->currentTime(), 250);
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(sequence->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(sequence2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a1_s_o3->state(), QAnimationGroup::Stopped);
+}
+
+typedef QList<QAbstractAnimation::State> StateList;
+
+static bool compareStates(const QSignalSpy& spy, const StateList &expectedStates)
+{
+ bool equals = true;
+ for (int i = 0; i < qMax(expectedStates.count(), spy.count()); ++i) {
+ if (i >= spy.count() || i >= expectedStates.count()) {
+ equals = false;
+ break;
+ }
+ QList<QVariant> args = spy.at(i);
+ QAbstractAnimation::State st = expectedStates.at(i);
+ QAbstractAnimation::State actual = qVariantValue<QAbstractAnimation::State>(args.value(1));
+ if (equals && actual != st) {
+ equals = false;
+ break;
+ }
+ }
+ if (!equals) {
+ const char *stateStrings[] = {"Stopped", "Paused", "Running"};
+ QString e,a;
+ for (int i = 0; i < qMax(expectedStates.count(), spy.count()); ++i) {
+ if (i < expectedStates.count()) {
+ int exp = int(expectedStates.at(i));
+ if (!e.isEmpty())
+ e += QLatin1String(", ");
+ e += QLatin1String(stateStrings[exp]);
+ }
+ if (i < spy.count()) {
+ QList<QVariant> args = spy.at(i);
+ QAbstractAnimation::State actual = qVariantValue<QAbstractAnimation::State>(args.value(1));
+ if (!a.isEmpty())
+ a += QLatin1String(", ");
+ if (int(actual) >= 0 && int(actual) <= 2) {
+ a += QLatin1String(stateStrings[int(actual)]);
+ } else {
+ a += QLatin1String("NaN");
+ }
+ }
+
+ }
+ qDebug("\n"
+ "expected (count == %d): %s\n"
+ "actual (count == %d): %s\n", expectedStates.count(), qPrintable(e), spy.count(), qPrintable(a));
+ }
+ return equals;
+}
+
+void tst_QSequentialAnimationGroup::pauseAndResume()
+{
+ AnimationObject s_o1;
+
+ // sequence operating on same object/property
+ QAnimationGroup *sequence = new QSequentialAnimationGroup();
+ QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ a2_s_o1->setLoopCount(2);
+ sequence->addAnimation(a1_s_o1);
+ sequence->addAnimation(a2_s_o1);
+ sequence->addAnimation(a3_s_o1);
+ sequence->setLoopCount(2);
+
+ QSignalSpy a1StateChangedSpy(a1_s_o1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy seqStateChangedSpy(sequence, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ QSequentialAnimationGroup group;
+ group.addAnimation(sequence);
+
+ group.start();
+ group.pause();
+
+ // Current time = 1751
+ group.setCurrentTime(1751);
+ QCOMPARE(group.currentTime(), 1751);
+ QCOMPARE(sequence->currentTime(), 751);
+ QCOMPARE(sequence->currentLoop(), 1);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 1);
+ QCOMPARE(a3_s_o1->currentLoop(), 0);
+ QCOMPARE(a3_s_o1->currentTime(), 1);
+
+ QCOMPARE(group.state(), QAnimationGroup::Paused);
+ QCOMPARE(sequence->state(), QAnimationGroup::Paused);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a2_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a3_s_o1->state(), QAnimationGroup::Paused);
+
+ QCOMPARE(a1StateChangedSpy.count(), 5); // Running,Paused,Stopped,Running,Stopped
+ QCOMPARE(seqStateChangedSpy.count(), 2); // Running,Paused
+
+ QVERIFY(compareStates(a1StateChangedSpy, (StateList() << QAbstractAnimation::Running
+ << QAbstractAnimation::Paused
+ << QAbstractAnimation::Stopped
+ << QAbstractAnimation::Running
+ << QAbstractAnimation::Stopped)));
+
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(a1StateChangedSpy.at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(a1StateChangedSpy.at(1).at(1)),
+ QAnimationGroup::Paused);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(a1StateChangedSpy.at(2).at(1)),
+ QAnimationGroup::Stopped);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(a1StateChangedSpy.at(3).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(a1StateChangedSpy.at(4).at(1)),
+ QAnimationGroup::Stopped);
+
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(seqStateChangedSpy.at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(seqStateChangedSpy.at(1).at(1)),
+ QAnimationGroup::Paused);
+
+ group.resume();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(sequence->state(), QAnimationGroup::Running);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a2_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a3_s_o1->state(), QAnimationGroup::Running);
+
+ QVERIFY(group.currentTime() >= 1751);
+ QVERIFY(sequence->currentTime() >= 751);
+ QCOMPARE(sequence->currentLoop(), 1);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 1);
+ QCOMPARE(a3_s_o1->currentLoop(), 0);
+ QVERIFY(a3_s_o1->currentTime() >= 1);
+
+ QCOMPARE(seqStateChangedSpy.count(), 3); // Running,Paused,Running
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(seqStateChangedSpy.at(2).at(1)),
+ QAnimationGroup::Running);
+
+ group.pause();
+
+ QCOMPARE(group.state(), QAnimationGroup::Paused);
+ QCOMPARE(sequence->state(), QAnimationGroup::Paused);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a2_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a3_s_o1->state(), QAnimationGroup::Paused);
+
+ QVERIFY(group.currentTime() >= 1751);
+ QVERIFY(sequence->currentTime() >= 751);
+ QCOMPARE(sequence->currentLoop(), 1);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 1);
+ QCOMPARE(a3_s_o1->currentLoop(), 0);
+ QVERIFY(a3_s_o1->currentTime() >= 1);
+
+ QCOMPARE(seqStateChangedSpy.count(), 4); // Running,Paused,Running,Paused
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(seqStateChangedSpy.at(3).at(1)),
+ QAnimationGroup::Paused);
+
+ group.stop();
+
+ QCOMPARE(seqStateChangedSpy.count(), 5); // Running,Paused,Running,Paused,Stopped
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(seqStateChangedSpy.at(4).at(1)),
+ QAnimationGroup::Stopped);
+}
+
+void tst_QSequentialAnimationGroup::restart()
+{
+ AnimationObject s_o1;
+
+ // sequence operating on same object/property
+ QAnimationGroup *sequence = new QSequentialAnimationGroup();
+ QSignalSpy seqCurrentAnimChangedSpy(sequence, SIGNAL(currentAnimationChanged(QAbstractAnimation*)));
+ QSignalSpy seqStateChangedSpy(sequence, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ QVariantAnimation *anims[3];
+ QSignalSpy *animsStateChanged[3];
+
+ for (int i = 0; i < 3; i++) {
+ anims[i] = new QPropertyAnimation(&s_o1, "value");
+ anims[i]->setDuration(100);
+ animsStateChanged[i] = new QSignalSpy(anims[i], SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ }
+
+ anims[1]->setLoopCount(2);
+ sequence->addAnimation(anims[0]);
+ sequence->addAnimation(anims[1]);
+ sequence->addAnimation(anims[2]);
+ sequence->setLoopCount(2);
+
+ QSequentialAnimationGroup group;
+ group.addAnimation(sequence);
+
+ group.start();
+
+ QTest::qWait(500);
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+
+ QTest::qWait(300);
+ QTRY_COMPARE(group.state(), QAnimationGroup::Stopped);
+
+ for (int i = 0; i < 3; i++) {
+ QCOMPARE(animsStateChanged[i]->count(), 4);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(animsStateChanged[i]->at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(animsStateChanged[i]->at(1).at(1)),
+ QAnimationGroup::Stopped);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(animsStateChanged[i]->at(2).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(animsStateChanged[i]->at(3).at(1)),
+ QAnimationGroup::Stopped);
+ }
+
+ QCOMPARE(seqStateChangedSpy.count(), 2);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(seqStateChangedSpy.at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(seqStateChangedSpy.at(1).at(1)),
+ QAnimationGroup::Stopped);
+
+ QCOMPARE(seqCurrentAnimChangedSpy.count(), 6);
+ for(int i=0; i<seqCurrentAnimChangedSpy.count(); i++)
+ QCOMPARE(anims[i%3], qVariantValue<QAbstractAnimation*>(seqCurrentAnimChangedSpy.at(i).at(0)));
+
+ group.start();
+
+ QCOMPARE(animsStateChanged[0]->count(), 5);
+ QCOMPARE(animsStateChanged[1]->count(), 4);
+ QCOMPARE(animsStateChanged[2]->count(), 4);
+ QCOMPARE(seqStateChangedSpy.count(), 3);
+}
+
+void tst_QSequentialAnimationGroup::looping()
+{
+ AnimationObject s_o1;
+ AnimationObject s_o2;
+ AnimationObject s_o3;
+
+ // sequence operating on same object/property
+ QSequentialAnimationGroup *sequence = new QSequentialAnimationGroup();
+ QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value");
+ QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value");
+
+ QSignalSpy a1Spy(a1_s_o1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy a2Spy(a2_s_o1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy a3Spy(a3_s_o1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy seqSpy(sequence, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ a2_s_o1->setLoopCount(2);
+ sequence->addAnimation(a1_s_o1);
+ sequence->addAnimation(a2_s_o1);
+ sequence->addAnimation(a3_s_o1);
+ sequence->setLoopCount(2);
+
+ QSequentialAnimationGroup group;
+ QSignalSpy groupSpy(&group, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ group.addAnimation(sequence);
+ group.setLoopCount(2);
+
+ group.start();
+ group.pause();
+
+ // Current time = 1750
+ group.setCurrentTime(1750);
+ QCOMPARE(group.currentTime(), 1750);
+ QCOMPARE(sequence->currentTime(), 750);
+ QCOMPARE(sequence->currentLoop(), 1);
+ QCOMPARE(a1_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 1);
+ // this animation is at the beginning because it is the current one inside sequence
+ QCOMPARE(a3_s_o1->currentLoop(), 0);
+ QCOMPARE(a3_s_o1->currentTime(), 0);
+ QCOMPARE(sequence->currentAnimation(), a3_s_o1);
+
+ QCOMPARE(group.state(), QAnimationGroup::Paused);
+ QCOMPARE(sequence->state(), QAnimationGroup::Paused);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a2_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a3_s_o1->state(), QAnimationGroup::Paused);
+
+ QCOMPARE(a1Spy.count(), 5); // Running,Paused,Stopped,Running,Stopped
+ QVERIFY(compareStates(a1Spy, (StateList() << QAbstractAnimation::Running
+ << QAbstractAnimation::Paused
+ << QAbstractAnimation::Stopped
+ << QAbstractAnimation::Running
+ << QAbstractAnimation::Stopped)));
+
+ QCOMPARE(a2Spy.count(), 4); // Running,Stopped,Running,Stopped
+ QVERIFY(compareStates(a3Spy, (StateList() << QAbstractAnimation::Running
+ << QAbstractAnimation::Stopped
+ << QAbstractAnimation::Running
+ << QAbstractAnimation::Paused)));
+
+ QCOMPARE(seqSpy.count(), 2); // Running,Paused
+ QCOMPARE(groupSpy.count(), 2); // Running,Paused
+
+ // Looping, current time = duration + 1
+ group.setCurrentTime(group.duration() + 1);
+ QCOMPARE(group.currentTime(), 1);
+ QCOMPARE(group.currentLoop(), 1);
+ QCOMPARE(sequence->currentTime(), 1);
+ QCOMPARE(sequence->currentLoop(), 0);
+ QCOMPARE(a1_s_o1->currentTime(), 1);
+ QCOMPARE(a2_s_o1->currentTime(), 250);
+ QCOMPARE(a2_s_o1->currentLoop(), 1);
+ // this animation is at the end because it was run on the previous loop
+ QCOMPARE(a3_s_o1->currentLoop(), 0);
+ QCOMPARE(a3_s_o1->currentTime(), 250);
+
+ QCOMPARE(group.state(), QAnimationGroup::Paused);
+ QCOMPARE(sequence->state(), QAnimationGroup::Paused);
+ QCOMPARE(a1_s_o1->state(), QAnimationGroup::Paused);
+ QCOMPARE(a2_s_o1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a3_s_o1->state(), QAnimationGroup::Stopped);
+
+ QCOMPARE(a1Spy.count(), 7); // Running,Paused,Stopped,Running,Stopped,Running,Stopped
+ QCOMPARE(a2Spy.count(), 4); // Running, Stopped, Running, Stopped
+ QVERIFY(compareStates(a3Spy, (StateList() << QAbstractAnimation::Running
+ << QAbstractAnimation::Stopped
+ << QAbstractAnimation::Running
+ << QAbstractAnimation::Paused
+ << QAbstractAnimation::Stopped)));
+ QVERIFY(compareStates(seqSpy, (StateList() << QAbstractAnimation::Running
+ << QAbstractAnimation::Paused
+ << QAbstractAnimation::Stopped
+ << QAbstractAnimation::Running
+ << QAbstractAnimation::Paused)));
+ QCOMPARE(groupSpy.count(), 2);
+}
+
+void tst_QSequentialAnimationGroup::startDelay()
+{
+ QSequentialAnimationGroup group;
+ group.addPause(250);
+ group.addPause(125);
+ QCOMPARE(group.totalDuration(), 375);
+
+ QEventLoop loop;
+ QObject::connect(&group, SIGNAL(finished()), &loop, SLOT(quit()));
+
+ QTime time;
+ time.start();
+ group.start();
+ loop.exec();
+
+ QVERIFY(time.elapsed() >= 375);
+ QVERIFY(time.elapsed() < 1000);
+}
+
+void tst_QSequentialAnimationGroup::clearGroup()
+{
+ QSequentialAnimationGroup group;
+
+ for (int i = 0; i < 10; ++i) {
+ QSequentialAnimationGroup *subGroup = new QSequentialAnimationGroup(&group);
+ group.addPause(100);
+ subGroup->addPause(10);
+ }
+
+ QCOMPARE(group.animationCount(), 20);
+
+ int count = group.animationCount();
+ QPointer<QAbstractAnimation> *children = new QPointer<QAbstractAnimation>[count];
+ for (int i = 0; i < count; ++i) {
+ QVERIFY(group.animationAt(i) != 0);
+ children[i] = group.animationAt(i);
+ }
+
+ group.clearAnimations();
+ QCOMPARE(group.animationCount(), 0);
+ QCOMPARE(group.currentTime(), 0);
+ for (int i = 0; i < count; ++i)
+ QCOMPARE(children[i], QPointer<QAbstractAnimation>());
+
+ delete[] children;
+}
+
+void tst_QSequentialAnimationGroup::groupWithZeroDurationAnimations()
+{
+ QObject o;
+ QObject o2;
+
+ o.setProperty("myProperty", 42);
+ o.setProperty("myOtherProperty", 13);
+ o2.setProperty("myProperty", 42);
+ o2.setProperty("myOtherProperty", 13);
+
+ QSequentialAnimationGroup group;
+
+ QVariantAnimation *a1 = new QPropertyAnimation(&o, "myProperty");
+ a1->setDuration(0);
+ a1->setEndValue(43);
+ group.addAnimation(a1);
+
+ //this should just run fine and change nothing
+ group.setCurrentTime(0);
+ QCOMPARE(group.currentAnimation(), a1);
+
+ QVariantAnimation *a2 = new QPropertyAnimation(&o2, "myOtherProperty");
+ a2->setDuration(500);
+ a2->setEndValue(31);
+ group.addAnimation(a2);
+
+ QVariantAnimation *a3 = new QPropertyAnimation(&o, "myProperty");
+ a3->setDuration(0);
+ a3->setEndValue(44);
+ group.addAnimation(a3);
+
+ QVariantAnimation *a4 = new QPropertyAnimation(&o, "myOtherProperty");
+ a4->setDuration(250);
+ a4->setEndValue(75);
+ group.addAnimation(a4);
+
+ QVariantAnimation *a5 = new QPropertyAnimation(&o2, "myProperty");
+ a5->setDuration(0);
+ a5->setEndValue(12);
+ group.addAnimation(a5);
+
+ QCOMPARE(o.property("myProperty").toInt(), 42);
+ QCOMPARE(o.property("myOtherProperty").toInt(), 13);
+ QCOMPARE(o2.property("myProperty").toInt(), 42);
+ QCOMPARE(o2.property("myOtherProperty").toInt(), 13);
+
+
+ group.start();
+
+ QCOMPARE(o.property("myProperty").toInt(), 43);
+ QCOMPARE(o.property("myOtherProperty").toInt(), 13);
+ QCOMPARE(o2.property("myProperty").toInt(), 42);
+ QCOMPARE(o2.property("myOtherProperty").toInt(), 13);
+
+ QTest::qWait(50);
+
+ int o2val = o2.property("myOtherProperty").toInt();
+ QVERIFY(o2val > 13);
+ QVERIFY(o2val < 31);
+ QCOMPARE(o.property("myProperty").toInt(), 43);
+ QCOMPARE(o.property("myOtherProperty").toInt(), 13);
+
+ QTest::qWait(500);
+
+ QCOMPARE(o.property("myProperty").toInt(), 44);
+ QCOMPARE(o2.property("myProperty").toInt(), 42);
+ QCOMPARE(o2.property("myOtherProperty").toInt(), 31);
+ QCOMPARE(a1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a3->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a4->state(), QAnimationGroup::Running);
+ QCOMPARE(a5->state(), QAnimationGroup::Stopped);
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QTest::qWait(500);
+
+ QTRY_COMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(o.property("myProperty").toInt(), 44);
+ QCOMPARE(o.property("myOtherProperty").toInt(), 75);
+ QCOMPARE(o2.property("myProperty").toInt(), 12);
+ QCOMPARE(o2.property("myOtherProperty").toInt(), 31);
+ QCOMPARE(a1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a2->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a3->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a4->state(), QAnimationGroup::Stopped);
+ QCOMPARE(a5->state(), QAnimationGroup::Stopped);
+}
+
+void tst_QSequentialAnimationGroup::propagateGroupUpdateToChildren()
+{
+ // this test verifies if group state changes are updating its children correctly
+ QSequentialAnimationGroup group;
+
+ QObject o;
+ o.setProperty("ole", 42);
+ QCOMPARE(o.property("ole").toInt(), 42);
+
+ QPropertyAnimation anim1(&o, "ole");
+ anim1.setEndValue(43);
+ anim1.setDuration(100);
+ QVERIFY(!anim1.currentValue().isValid());
+ QCOMPARE(anim1.currentValue().toInt(), 0);
+ QCOMPARE(o.property("ole").toInt(), 42);
+
+ TestAnimation anim2;
+ anim2.setStartValue(0);
+ anim2.setEndValue(100);
+ anim2.setDuration(200);
+
+ QVERIFY(anim2.currentValue().isValid());
+ QCOMPARE(anim2.currentValue().toInt(), 0);
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+
+ group.addAnimation(&anim1);
+ group.addAnimation(&anim2);
+
+ group.start();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim1.state(), QAnimationGroup::Running);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+
+ group.pause();
+
+ QCOMPARE(group.state(), QAnimationGroup::Paused);
+ QCOMPARE(anim1.state(), QAnimationGroup::Paused);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+
+ group.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+}
+
+void tst_QSequentialAnimationGroup::updateChildrenWithRunningGroup()
+{
+ // assert that its possible to modify a child's state directly while their group is running
+ QSequentialAnimationGroup group;
+
+ TestAnimation anim;
+ anim.setStartValue(0);
+ anim.setEndValue(100);
+ anim.setDuration(200);
+
+ QSignalSpy groupStateChangedSpy(&group, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy childStateChangedSpy(&anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ QCOMPARE(groupStateChangedSpy.count(), 0);
+ QCOMPARE(childStateChangedSpy.count(), 0);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim.state(), QAnimationGroup::Stopped);
+
+ group.addAnimation(&anim);
+
+ group.start();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim.state(), QAnimationGroup::Running);
+
+ QCOMPARE(groupStateChangedSpy.count(), 1);
+ QCOMPARE(childStateChangedSpy.count(), 1);
+
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(groupStateChangedSpy.at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(childStateChangedSpy.at(0).at(1)),
+ QAnimationGroup::Running);
+
+ // starting directly a running child will not have any effect
+ anim.start();
+
+ QCOMPARE(groupStateChangedSpy.count(), 1);
+ QCOMPARE(childStateChangedSpy.count(), 1);
+
+ anim.pause();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim.state(), QAnimationGroup::Paused);
+
+ // in the animation stops directly, the group will still be running
+ anim.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim.state(), QAnimationGroup::Stopped);
+}
+
+void tst_QSequentialAnimationGroup::deleteChildrenWithRunningGroup()
+{
+ // test if children can be activated when their group is stopped
+ QSequentialAnimationGroup group;
+
+ QVariantAnimation *anim1 = new TestAnimation;
+ anim1->setStartValue(0);
+ anim1->setEndValue(100);
+ anim1->setDuration(200);
+ group.addAnimation(anim1);
+
+ QCOMPARE(group.duration(), anim1->duration());
+
+ group.start();
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim1->state(), QAnimationGroup::Running);
+
+ QTest::qWait(50);
+ QVERIFY(group.currentTime() > 0);
+
+ delete anim1;
+ QCOMPARE(group.animationCount(), 0);
+ QCOMPARE(group.duration(), 0);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(group.currentTime(), 0); //that's the invariant
+}
+
+void tst_QSequentialAnimationGroup::startChildrenWithStoppedGroup()
+{
+ // test if children can be activated when their group is stopped
+ QSequentialAnimationGroup group;
+
+ TestAnimation anim1;
+ anim1.setStartValue(0);
+ anim1.setEndValue(100);
+ anim1.setDuration(200);
+
+ TestAnimation anim2;
+ anim2.setStartValue(0);
+ anim2.setEndValue(100);
+ anim2.setDuration(200);
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+
+ group.addAnimation(&anim1);
+ group.addAnimation(&anim2);
+
+ group.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+
+ anim1.start();
+ anim2.start();
+ anim2.pause();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Running);
+ QCOMPARE(anim2.state(), QAnimationGroup::Paused);
+}
+
+void tst_QSequentialAnimationGroup::stopGroupWithRunningChild()
+{
+ // children that started independently will not be affected by a group stop
+ QSequentialAnimationGroup group;
+
+ TestAnimation anim1;
+ anim1.setStartValue(0);
+ anim1.setEndValue(100);
+ anim1.setDuration(200);
+
+ TestAnimation anim2;
+ anim2.setStartValue(0);
+ anim2.setEndValue(100);
+ anim2.setDuration(200);
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+
+ group.addAnimation(&anim1);
+ group.addAnimation(&anim2);
+
+ anim1.start();
+ anim2.start();
+ anim2.pause();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Running);
+ QCOMPARE(anim2.state(), QAnimationGroup::Paused);
+
+ group.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Running);
+ QCOMPARE(anim2.state(), QAnimationGroup::Paused);
+
+ anim1.stop();
+ anim2.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2.state(), QAnimationGroup::Stopped);
+}
+
+void tst_QSequentialAnimationGroup::startGroupWithRunningChild()
+{
+ // as the group has precedence over its children, starting a group will restart all the children
+ QSequentialAnimationGroup group;
+
+ TestAnimation *anim1 = new TestAnimation();
+ anim1->setStartValue(0);
+ anim1->setEndValue(100);
+ anim1->setDuration(200);
+
+ TestAnimation *anim2 = new TestAnimation();
+ anim2->setStartValue(0);
+ anim2->setEndValue(100);
+ anim2->setDuration(200);
+
+ QSignalSpy stateChangedSpy1(anim1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+ QSignalSpy stateChangedSpy2(anim2, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ QCOMPARE(stateChangedSpy1.count(), 0);
+ QCOMPARE(stateChangedSpy2.count(), 0);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2->state(), QAnimationGroup::Stopped);
+
+ group.addAnimation(anim1);
+ group.addAnimation(anim2);
+
+ anim1->start();
+ anim2->start();
+ anim2->pause();
+
+ QVERIFY(compareStates(stateChangedSpy1, (StateList() << QAbstractAnimation::Running)));
+
+ QVERIFY(compareStates(stateChangedSpy2, (StateList() << QAbstractAnimation::Running
+ << QAbstractAnimation::Paused)));
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1->state(), QAnimationGroup::Running);
+ QCOMPARE(anim2->state(), QAnimationGroup::Paused);
+
+ group.start();
+
+ QVERIFY(compareStates(stateChangedSpy1, (StateList() << QAbstractAnimation::Running
+ << QAbstractAnimation::Stopped
+ << QAbstractAnimation::Running)));
+ QVERIFY(compareStates(stateChangedSpy2, (StateList() << QAbstractAnimation::Running
+ << QAbstractAnimation::Paused)));
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim1->state(), QAnimationGroup::Running);
+ QCOMPARE(anim2->state(), QAnimationGroup::Paused);
+
+ QTest::qWait(300);
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2->state(), QAnimationGroup::Running);
+
+ QCOMPARE(stateChangedSpy2.count(), 4);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy2.at(2).at(1)),
+ QAnimationGroup::Stopped);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy2.at(3).at(1)),
+ QAnimationGroup::Running);
+
+ group.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2->state(), QAnimationGroup::Stopped);
+}
+
+void tst_QSequentialAnimationGroup::zeroDurationAnimation()
+{
+ QSequentialAnimationGroup group;
+
+ TestAnimation *anim1 = new TestAnimation();
+ anim1->setStartValue(0);
+ anim1->setEndValue(100);
+ anim1->setDuration(0);
+
+ TestAnimation *anim2 = new TestAnimation();
+ anim2->setStartValue(0);
+ anim2->setEndValue(100);
+ anim2->setDuration(100);
+
+ AnimationObject o1;
+ QPropertyAnimation *anim3 = new QPropertyAnimation(&o1, "value");
+ anim3->setEndValue(100);
+ anim3->setDuration(0);
+
+ QSignalSpy stateChangedSpy(anim1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ group.addAnimation(anim1);
+ group.addAnimation(anim2);
+ group.addAnimation(anim3);
+ group.setLoopCount(2);
+ group.start();
+
+ QCOMPARE(stateChangedSpy.count(), 2);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy.at(0).at(1)),
+ QAnimationGroup::Running);
+ QCOMPARE(qVariantValue<QAbstractAnimation::State>(stateChangedSpy.at(1).at(1)),
+ QAnimationGroup::Stopped);
+
+ QCOMPARE(anim1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2->state(), QAnimationGroup::Running);
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+
+ //now let's try to seek to the next loop
+ group.setCurrentTime(group.duration() + 1);
+ QCOMPARE(anim1->state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim2->state(), QAnimationGroup::Running);
+ QCOMPARE(anim3->state(), QAnimationGroup::Stopped);
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(o1.value(), 100); //anim3 should have been run
+}
+
+void tst_QSequentialAnimationGroup::stopUncontrolledAnimations()
+{
+ QSequentialAnimationGroup group;
+
+ AnimationObject o1;
+ UncontrolledAnimation notTimeDriven(&o1, "value");
+ QCOMPARE(notTimeDriven.totalDuration(), -1);
+
+ TestAnimation loopsForever;
+ loopsForever.setStartValue(0);
+ loopsForever.setEndValue(100);
+ loopsForever.setDuration(100);
+ loopsForever.setLoopCount(-1);
+
+ group.addAnimation(&notTimeDriven);
+ group.addAnimation(&loopsForever);
+
+ group.start();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(notTimeDriven.state(), QAnimationGroup::Running);
+ QCOMPARE(loopsForever.state(), QAnimationGroup::Stopped);
+
+ notTimeDriven.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(notTimeDriven.state(), QAnimationGroup::Stopped);
+ QCOMPARE(loopsForever.state(), QAnimationGroup::Running);
+
+ loopsForever.stop();
+
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(notTimeDriven.state(), QAnimationGroup::Stopped);
+ QCOMPARE(loopsForever.state(), QAnimationGroup::Stopped);
+}
+
+void tst_QSequentialAnimationGroup::finishWithUncontrolledAnimation()
+{
+ AnimationObject o1;
+
+ //1st case:
+ //first we test a group with one uncontrolled animation
+ QSequentialAnimationGroup group;
+ UncontrolledAnimation notTimeDriven(&o1, "value", &group);
+ QSignalSpy spy(&group, SIGNAL(finished()));
+
+ group.start();
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(notTimeDriven.state(), QAnimationGroup::Running);
+ QCOMPARE(group.currentTime(), 0);
+ QCOMPARE(notTimeDriven.currentTime(), 0);
+
+ QTest::qWait(300); //wait for the end of notTimeDriven
+ QCOMPARE(notTimeDriven.state(), QAnimationGroup::Stopped);
+ const int actualDuration = notTimeDriven.currentTime();
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(group.currentTime(), actualDuration);
+ QCOMPARE(spy.count(), 1);
+
+ //2nd case:
+ // lets make sure the seeking will work again
+ spy.clear();
+ QPropertyAnimation anim(&group);
+ QSignalSpy animStateChangedSpy(&anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)));
+
+ group.setCurrentTime(300);
+ QCOMPARE(group.state(), QAnimationGroup::Stopped);
+ QCOMPARE(notTimeDriven.currentTime(), actualDuration);
+ QCOMPARE(group.currentAnimation(), &anim);
+
+ //3rd case:
+ //now let's add a perfectly defined animation at the end
+ QCOMPARE(animStateChangedSpy.count(), 0);
+ group.start();
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(notTimeDriven.state(), QAnimationGroup::Running);
+ QCOMPARE(group.currentTime(), 0);
+ QCOMPARE(notTimeDriven.currentTime(), 0);
+
+ QCOMPARE(animStateChangedSpy.count(), 0);
+
+ QTest::qWait(300); //wait for the end of notTimeDriven
+ QCOMPARE(notTimeDriven.state(), QAnimationGroup::Stopped);
+ QCOMPARE(group.state(), QAnimationGroup::Running);
+ QCOMPARE(anim.state(), QAnimationGroup::Running);
+ QCOMPARE(group.currentAnimation(), &anim);
+ QCOMPARE(animStateChangedSpy.count(), 1);
+ QTest::qWait(300); //wait for the end of anim
+
+ QCOMPARE(anim.state(), QAnimationGroup::Stopped);
+ QCOMPARE(anim.currentTime(), anim.duration());
+
+ //we should simply be at the end
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(animStateChangedSpy.count(), 2);
+ QCOMPARE(group.currentTime(), notTimeDriven.currentTime() + anim.currentTime());
+}
+
+void tst_QSequentialAnimationGroup::addRemoveAnimation()
+{
+ //this test is specific to the sequential animation group
+ QSequentialAnimationGroup group;
+
+ QCOMPARE(group.duration(), 0);
+ QCOMPARE(group.currentTime(), 0);
+ QVariantAnimation *anim1 = new QPropertyAnimation;
+ group.addAnimation(anim1);
+ QCOMPARE(group.duration(), 250);
+ QCOMPARE(group.currentTime(), 0);
+ QCOMPARE(group.currentAnimation(), anim1);
+
+ //let's append an animation
+ QVariantAnimation *anim2 = new QPropertyAnimation;
+ group.addAnimation(anim2);
+ QCOMPARE(group.duration(), 500);
+ QCOMPARE(group.currentTime(), 0);
+ QCOMPARE(group.currentAnimation(), anim1);
+
+ //let's prepend an animation
+ QVariantAnimation *anim0 = new QPropertyAnimation;
+ group.insertAnimationAt(0, anim0);
+ QCOMPARE(group.duration(), 750);
+ QCOMPARE(group.currentTime(), 0);
+ QCOMPARE(group.currentAnimation(), anim0); //anim0 has become the new currentAnimation
+
+ group.setCurrentTime(300); //anim0 | anim1 | anim2
+ QCOMPARE(group.currentTime(), 300);
+ QCOMPARE(group.currentAnimation(), anim1);
+ QCOMPARE(anim1->currentTime(), 50);
+
+ group.removeAnimation(anim0); //anim1 | anim2
+ QCOMPARE(group.currentTime(), 50);
+ QCOMPARE(group.currentAnimation(), anim1);
+ QCOMPARE(anim1->currentTime(), 50);
+
+ group.setCurrentTime(0);
+ group.insertAnimationAt(0, anim0); //anim0 | anim1 | anim2
+ group.setCurrentTime(300);
+ QCOMPARE(group.currentTime(), 300);
+ QCOMPARE(group.currentAnimation(), anim1);
+ QCOMPARE(anim1->currentTime(), 50);
+
+ group.removeAnimation(anim1); //anim0 | anim2
+ QCOMPARE(group.currentTime(), 250);
+ QCOMPARE(group.currentAnimation(), anim2);
+ QCOMPARE(anim0->currentTime(), 250);
+}
+
+void tst_QSequentialAnimationGroup::currentAnimation()
+{
+ QSequentialAnimationGroup group;
+ QVERIFY(group.currentAnimation() == 0);
+
+ QPropertyAnimation anim;
+ anim.setDuration(0);
+ group.addAnimation(&anim);
+ QCOMPARE(group.currentAnimation(), &anim);
+}
+
+void tst_QSequentialAnimationGroup::currentAnimationWithZeroDuration()
+{
+ QSequentialAnimationGroup group;
+ QVERIFY(group.currentAnimation() == 0);
+
+ QPropertyAnimation zero1;
+ zero1.setDuration(0);
+ QPropertyAnimation zero2;
+ zero2.setDuration(0);
+
+ QPropertyAnimation anim;
+
+ QPropertyAnimation zero3;
+ zero3.setDuration(0);
+ QPropertyAnimation zero4;
+ zero4.setDuration(0);
+
+
+ group.addAnimation(&zero1);
+ group.addAnimation(&zero2);
+ group.addAnimation(&anim);
+ group.addAnimation(&zero3);
+ group.addAnimation(&zero4);
+
+ QCOMPARE(group.currentAnimation(), &zero1);
+
+ group.setCurrentTime(0);
+ QCOMPARE(group.currentAnimation(), &anim);
+
+ group.setCurrentTime(group.duration());
+ QCOMPARE(group.currentAnimation(), &zero4);
+
+ group.setDirection(QAbstractAnimation::Backward);
+
+ group.setCurrentTime(0);
+ QCOMPARE(group.currentAnimation(), &zero1);
+
+ group.setCurrentTime(group.duration());
+ QCOMPARE(group.currentAnimation(), &anim);
+}
+
+void tst_QSequentialAnimationGroup::insertAnimation()
+{
+ QSequentialAnimationGroup group;
+ group.setLoopCount(2);
+ QPropertyAnimation *anim = new QPropertyAnimation(&group);
+ QCOMPARE(group.duration(), anim->duration());
+ group.setCurrentTime(300);
+ QCOMPARE(group.currentLoop(), 1);
+
+ //this will crash if the sequential group calls duration on the created animation
+ new QPropertyAnimation(&group);
+}
+
+
+class SequentialAnimationGroup : public QSequentialAnimationGroup
+{
+ Q_OBJECT
+public slots:
+ void clearAnimations()
+ {
+ QSequentialAnimationGroup::clearAnimations();
+ }
+
+ void refill()
+ {
+ stop();
+ clearAnimations();
+ new QPropertyAnimation(this);
+ start();
+ }
+
+};
+
+
+void tst_QSequentialAnimationGroup::clearAnimations()
+{
+ SequentialAnimationGroup group;
+ QPointer<QAbstractAnimation> anim1 = new QPropertyAnimation(&group);
+ group.connect(anim1, SIGNAL(finished()), SLOT(clearAnimations()));
+ new QPropertyAnimation(&group);
+ QCOMPARE(group.animationCount(), 2);
+
+ group.start();
+ QTest::qWait(anim1->duration() + 100);
+ QCOMPARE(group.animationCount(), 0);
+ QCOMPARE(group.state(), QAbstractAnimation::Stopped);
+ QCOMPARE(group.currentTime(), 0);
+
+ anim1 = new QPropertyAnimation(&group);
+ group.connect(anim1, SIGNAL(finished()), SLOT(refill()));
+ group.start();
+ QTest::qWait(anim1->duration() + 100);
+ QVERIFY(anim1 == 0); //anim1 should have been deleted
+ QCOMPARE(group.state(), QAbstractAnimation::Running);
+}
+
+QTEST_MAIN(tst_QSequentialAnimationGroup)
+#include "tst_qsequentialanimationgroup.moc"
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/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
index 80d90a6..274b177 100644
--- a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
@@ -134,6 +134,7 @@ private slots:
void task250023_fetchMore();
void task251296_hiddenChildren();
void task252507_mapFromToSource();
+ void task255652_removeRowsRecursive();
protected:
void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
@@ -390,7 +391,7 @@ void tst_QSortFilterProxyModel::sort()
QModelIndex index = m_proxy->index(row, 0, QModelIndex());
QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row));
}
-
+
}
void tst_QSortFilterProxyModel::sortHierarchy_data()
@@ -411,7 +412,7 @@ void tst_QSortFilterProxyModel::sortHierarchy_data()
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">")
<< (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">");
-
+
#if 1
QTest::newRow("hierarchical ascending")
<< static_cast<int>(Qt::AscendingOrder)
@@ -571,7 +572,7 @@ void tst_QSortFilterProxyModel::insertRows()
QModelIndex index = m_proxy->index(row, 0, QModelIndex());
QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row));
}
-
+
// insert the row
m_proxy->insertRows(position, insert.count(), QModelIndex());
QCOMPARE(m_model->rowCount(QModelIndex()), expected.count());
@@ -615,7 +616,7 @@ void tst_QSortFilterProxyModel::prependRow()
QStandardItem sub2("sub2");
sub2.appendRow(new QStandardItem("sub3"));
item.insertRow(0, &sub2);
-
+
QModelIndex index_sub2 = proxy.mapFromSource(model.indexFromItem(&sub2));
QCOMPARE(sub2.rowCount(), proxy.rowCount(index_sub2));
@@ -626,7 +627,7 @@ void tst_QSortFilterProxyModel::prependRow()
/*
void tst_QSortFilterProxyModel::insertColumns_data()
{
-
+
}
void tst_QSortFilterProxyModel::insertColumns()
@@ -923,7 +924,7 @@ void tst_QSortFilterProxyModel::removeRows()
// prepare model
foreach (QString s, initial)
model.appendRow(new QStandardItem(s));
-
+
// remove the rows
QCOMPARE(proxy.removeRows(position, count, QModelIndex()), success);
QCOMPARE(model.rowCount(QModelIndex()), expectedSource.count());
@@ -1164,10 +1165,10 @@ void tst_QSortFilterProxyModel::removeColumns()
proxy.setSourceModel(&model);
if (!filter.isEmpty())
proxy.setFilterRegExp(QRegExp(filter));
-
+
// prepare model
model.setHorizontalHeaderLabels(initial);
-
+
// remove the columns
QCOMPARE(proxy.removeColumns(position, count, QModelIndex()), success);
QCOMPARE(model.columnCount(QModelIndex()), expectedSource.count());
@@ -1266,7 +1267,7 @@ void tst_QSortFilterProxyModel::filter_data()
<< "golf"
<< "quebec"
<< "foxtrot"
- << "india"
+ << "india"
<< "romeo"
<< "november"
<< "oskar"
@@ -1274,9 +1275,9 @@ void tst_QSortFilterProxyModel::filter_data()
<< "kilo"
<< "whiskey"
<< "mike"
- << "papa"
+ << "papa"
<< "sierra"
- << "xray"
+ << "xray"
<< "viktor")
<< (QStringList()
<< "delta"
@@ -1334,7 +1335,7 @@ void tst_QSortFilterProxyModel::filterHierarchy_data()
<< "foo" << "boo" << "baz" << "moo" << "laa" << "haa")
<< (QStringList()
<< "foo" << "boo" << "moo");
-
+
QTest::newRow("simple hierarchy") << "b.*z"
<< (QStringList() << "baz" << "<" << "boz" << "<" << "moo" << ">" << ">")
<< (QStringList() << "baz" << "<" << "boz" << ">");
@@ -1671,7 +1672,7 @@ void tst_QSortFilterProxyModel::removeSourceRows()
QSignalSpy insertSpy(&proxy, SIGNAL(rowsInserted(QModelIndex, int, int)));
QSignalSpy aboutToRemoveSpy(&proxy, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)));
QSignalSpy aboutToInsertSpy(&proxy, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)));
-
+
model.removeRows(start, count, QModelIndex());
QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count());
@@ -1827,7 +1828,7 @@ void tst_QSortFilterProxyModel::changeFilter()
QFETCH(IntPairList, finalRemoveIntervals);
QFETCH(IntPairList, insertIntervals);
QFETCH(QStringList, finalProxyItems);
-
+
QStandardItemModel model;
QSortFilterProxyModel proxy;
@@ -1880,7 +1881,7 @@ void tst_QSortFilterProxyModel::changeFilter()
#ifdef Q_OS_IRIX
QEXPECT_FAIL("filter (2)", "Not reliable on IRIX", Abort);
-#endif
+#endif
QCOMPARE(finalInsertSpy.count(), insertIntervals.count());
for (int i = 0; i < finalInsertSpy.count(); ++i) {
QList<QVariant> args = finalInsertSpy.at(i);
@@ -2068,7 +2069,7 @@ void tst_QSortFilterProxyModel::sortFilterRole()
model.setData(index, sourceItems.at(i).first, Qt::DisplayRole);
model.setData(index, sourceItems.at(i).second, Qt::UserRole);
}
-
+
proxy.setFilterRegExp("2");
QCOMPARE(proxy.rowCount(), 0); // Qt::DisplayRole is default role
@@ -2358,7 +2359,7 @@ void tst_QSortFilterProxyModel::sourceInsertRows()
model.insertColumns(0, 1, parent);
model.insertRows(0, 1, parent);
}
-
+
model.insertRows(0, 1, QModelIndex());
model.insertRows(0, 1, QModelIndex());
@@ -2462,7 +2463,7 @@ void tst_QSortFilterProxyModel::task236755_hiddenColumns()
QVERIFY(view.isColumnHidden(0));
}
-void tst_QSortFilterProxyModel::task247867_insertRowsSort()
+void tst_QSortFilterProxyModel::task247867_insertRowsSort()
{
QStandardItemModel model(2,2);
QSortFilterProxyModel proxyModel;
@@ -2567,7 +2568,7 @@ void tst_QSortFilterProxyModel::task248868_dynamicSorting()
QStringList initial2 = initial;
initial2.replaceInStrings("bateau", "girafe");
model1.setStringList(initial2); //this will cause a reset
-
+
QStringList expected2 = initial2;
expected2.sort();
@@ -2648,7 +2649,7 @@ class QtTestModel: public QAbstractItemModel
{
if (!idx.isValid())
return QVariant();
-
+
if (role == Qt::DisplayRole) {
if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) {
wrongIndex = true;
@@ -2727,6 +2728,16 @@ void tst_QSortFilterProxyModel::task251296_hiddenChildren()
QCOMPARE(proxy.rowCount(indexA) , 1);
QModelIndex indexC = proxy.index(0, 0, indexA);
QCOMPARE(proxy.data(indexC).toString(), QString::fromLatin1("C VISIBLE"));
+
+ proxy.setFilterRegExp("C");
+ QCOMPARE(proxy.rowCount(QModelIndex()), 0);
+ itemC->setText("invisible");
+ itemA->setText("AC");
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), 1);
+ indexA = proxy.index(0,0);
+ QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("AC"));
+ QCOMPARE(proxy.rowCount(indexA) , 0);
}
void tst_QSortFilterProxyModel::task252507_mapFromToSource()
@@ -2746,5 +2757,63 @@ void tst_QSortFilterProxyModel::task252507_mapFromToSource()
QCOMPARE(proxy.mapFromSource(proxy.index(6, 2)), QModelIndex());
}
+static QStandardItem *addEntry(QStandardItem* pParent, const QString &description)
+{
+ QStandardItem* pItem = new QStandardItem(description);
+ pParent->appendRow(pItem);
+ return pItem;
+}
+
+
+void tst_QSortFilterProxyModel::task255652_removeRowsRecursive()
+{
+ QStandardItemModel pModel;
+ QStandardItem *pItem1 = new QStandardItem("root");
+ pModel.appendRow(pItem1);
+ QList<QStandardItem *> items;
+
+ QStandardItem *pItem11 = addEntry(pItem1,"Sub-heading");
+ items << pItem11;
+ QStandardItem *pItem111 = addEntry(pItem11,"A");
+ items << pItem111;
+ items << addEntry(pItem111,"A1");
+ items << addEntry(pItem111,"A2");
+ QStandardItem *pItem112 = addEntry(pItem11,"B");
+ items << pItem112;
+ items << addEntry(pItem112,"B1");
+ items << addEntry(pItem112,"B2");
+ QStandardItem *pItem1123 = addEntry(pItem112,"B3");
+ items << pItem1123;
+ items << addEntry(pItem1123,"B3-");
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&pModel);
+
+ QList<QPersistentModelIndex> sourceIndexes;
+ QList<QPersistentModelIndex> proxyIndexes;
+ foreach (QStandardItem *item, items) {
+ QModelIndex idx = item->index();
+ sourceIndexes << idx;
+ proxyIndexes << proxy.mapFromSource(idx);
+ }
+
+ foreach (const QPersistentModelIndex &pidx, sourceIndexes)
+ QVERIFY(pidx.isValid());
+ foreach (const QPersistentModelIndex &pidx, proxyIndexes)
+ QVERIFY(pidx.isValid());
+
+ QList<QStandardItem*> itemRow = pItem1->takeRow(0);
+
+ QCOMPARE(itemRow.count(), 1);
+ QCOMPARE(itemRow.first(), pItem11);
+
+ foreach (const QPersistentModelIndex &pidx, sourceIndexes)
+ QVERIFY(!pidx.isValid());
+ foreach (const QPersistentModelIndex &pidx, proxyIndexes)
+ QVERIFY(!pidx.isValid());
+
+ delete pItem11;
+}
+
QTEST_MAIN(tst_QSortFilterProxyModel)
#include "tst_qsortfilterproxymodel.moc"
diff --git a/tests/auto/qspinbox/tst_qspinbox.cpp b/tests/auto/qspinbox/tst_qspinbox.cpp
index 1867356..575f261 100644
--- a/tests/auto/qspinbox/tst_qspinbox.cpp
+++ b/tests/auto/qspinbox/tst_qspinbox.cpp
@@ -241,6 +241,12 @@ void tst_QSpinBox::getSetCheck()
QCOMPARE(0.0, obj2.value());
obj2.setValue(1.0);
QCOMPARE(1.0, obj2.value());
+
+ // Make sure we update line edit geometry when updating
+ // buttons - see task 235747
+ QRect oldEditGeometry = obj1.childrenRect();
+ obj1.setButtonSymbols(QAbstractSpinBox::NoButtons);
+ QVERIFY(obj1.childrenRect() != oldEditGeometry);
}
tst_QSpinBox::tst_QSpinBox()
diff --git a/tests/auto/qsplitter/qsplitter.pro b/tests/auto/qsplitter/qsplitter.pro
index 86d02b5..8c3e40b 100644
--- a/tests/auto/qsplitter/qsplitter.pro
+++ b/tests/auto/qsplitter/qsplitter.pro
@@ -8,4 +8,7 @@ wince*|symbian*: {
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 51bd99f..5fa0286 100644
--- a/tests/auto/qsplitter/tst_qsplitter.cpp
+++ b/tests/auto/qsplitter/tst_qsplitter.cpp