summaryrefslogtreecommitdiffstats
path: root/tests/baseline
diff options
context:
space:
mode:
Diffstat (limited to 'tests/baseline')
-rw-r--r--tests/baseline/CMakeLists.txt5
-rw-r--r--tests/baseline/painting/CMakeLists.txt9
-rw-r--r--tests/baseline/painting/scripts/aliasing.qps13
-rw-r--r--tests/baseline/painting/scripts/cliprects.qps295
-rw-r--r--tests/baseline/painting/scripts/pattern_xform.qps79
-rw-r--r--tests/baseline/painting/scripts/pattern_xform2.qps81
-rw-r--r--tests/baseline/painting/scripts/pixmapfragments.qps65
-rw-r--r--tests/baseline/painting/scripts/text.qps2
-rw-r--r--tests/baseline/painting/tst_baseline_painting.cpp74
-rw-r--r--tests/baseline/shared/baselineprotocol.cpp65
-rw-r--r--tests/baseline/shared/baselineprotocol.h29
-rw-r--r--tests/baseline/shared/lookup3.cpp35
-rw-r--r--tests/baseline/shared/paintcommands.cpp239
-rw-r--r--tests/baseline/shared/paintcommands.h43
-rw-r--r--tests/baseline/shared/qbaselinetest.cpp95
-rw-r--r--tests/baseline/shared/qbaselinetest.h38
-rw-r--r--tests/baseline/shared/qwidgetbaselinetest.cpp126
-rw-r--r--tests/baseline/shared/qwidgetbaselinetest.h31
-rw-r--r--tests/baseline/stylesheet/CMakeLists.txt6
-rw-r--r--tests/baseline/stylesheet/qss/dummy.qss31
-rw-r--r--tests/baseline/stylesheet/qss/qheaderview/selectedFontWeight.qss16
-rw-r--r--tests/baseline/stylesheet/qss/qtoolbutton/menuButton_no_border.qss1
-rw-r--r--tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_padding.qss12
-rw-r--r--tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_position.qss4
-rw-r--r--tests/baseline/stylesheet/qss/qtreeview/showDecorationSelected.qss3
-rw-r--r--tests/baseline/stylesheet/qss/qtreeview/styledIndicators.qss18
-rw-r--r--tests/baseline/stylesheet/qss/qtreeview/styledItem.qss7
-rw-r--r--tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss10
-rw-r--r--tests/baseline/stylesheet/tst_baseline_stylesheet.cpp127
-rw-r--r--tests/baseline/text/CMakeLists.txt6
-rw-r--r--tests/baseline/text/data/colored_list.html68
-rw-r--r--tests/baseline/text/tst_baseline_text.cpp55
-rw-r--r--tests/baseline/widgets/CMakeLists.txt6
-rw-r--r--tests/baseline/widgets/tst_baseline_widgets.cpp881
34 files changed, 2044 insertions, 531 deletions
diff --git a/tests/baseline/CMakeLists.txt b/tests/baseline/CMakeLists.txt
index df5d35863b..037ffd9e0e 100644
--- a/tests/baseline/CMakeLists.txt
+++ b/tests/baseline/CMakeLists.txt
@@ -1,4 +1,7 @@
-if(TARGET Qt::Network)
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(TARGET Qt::Gui AND TARGET Qt::Network AND QT_FEATURE_pdf)
add_subdirectory(painting)
endif()
if(TARGET Qt::Network AND TARGET Qt::Widgets)
diff --git a/tests/baseline/painting/CMakeLists.txt b/tests/baseline/painting/CMakeLists.txt
index b32d8f1324..72e737d227 100644
--- a/tests/baseline/painting/CMakeLists.txt
+++ b/tests/baseline/painting/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
#####################################################################
## tst_baseline_painting Test:
#####################################################################
@@ -14,9 +17,11 @@ qt_internal_add_test(tst_baseline_painting
../shared/qbaselinetest.cpp ../shared/qbaselinetest.h
../shared/paintcommands.cpp ../shared/paintcommands.h
tst_baseline_painting.cpp
+ NO_PCH_SOURCES
+ tst_baseline_painting.cpp # undef QT_NO_FOREACH
INCLUDE_DIRECTORIES
../shared
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::Gui
Qt::GuiPrivate
Qt::Network
@@ -68,6 +73,6 @@ qt_internal_add_resource(tst_baseline_painting "images"
#####################################################################
qt_internal_extend_target(tst_baseline_painting CONDITION QT_FEATURE_opengl
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::OpenGL
)
diff --git a/tests/baseline/painting/scripts/aliasing.qps b/tests/baseline/painting/scripts/aliasing.qps
index 59878f9c4d..1fb0113396 100644
--- a/tests/baseline/painting/scripts/aliasing.qps
+++ b/tests/baseline/painting/scripts/aliasing.qps
@@ -19,6 +19,17 @@ begin_block drawing
setPen black
drawText 0 68 "QwErTy@"
+ setPen green 1 SolidLine
+ drawLine 0 75 10 75
+ setPen 800000ff 1
+ drawPoint 0 75
+ drawPoint 10 75
+
+ setPen green 2 SolidLine
+ drawLine 20 75 30 75
+ setPen 800000ff 2
+ drawPoint 20 75
+ drawPoint 30 75
setPen black 1
setBrush 7f7fff
@@ -153,4 +164,4 @@ drawText 15 185 "1.0"
resetMatrix
drawText 430 95 "Aliased"
-drawText 430 275 "Anti-Aliased" \ No newline at end of file
+drawText 430 275 "Anti-Aliased"
diff --git a/tests/baseline/painting/scripts/cliprects.qps b/tests/baseline/painting/scripts/cliprects.qps
index aa0367eccf..cbc2a90055 100644
--- a/tests/baseline/painting/scripts/cliprects.qps
+++ b/tests/baseline/painting/scripts/cliprects.qps
@@ -1,7 +1,7 @@
# Version: 1
# CheckVsReference: 5%
-
+save
translate 10 10
setPen NoPen
@@ -56,4 +56,297 @@ setRenderHint Antialiasing
setRenderHint SmoothPixmapTransform
repeat_block clipping
+restore
+
+# Excercise combining different clips
+
+translate 0 250
+scale 0.9 0.9
+setFont "times" 10 bold
+region_addRect dummyRegion 1000 1000 10 10
+region_addRect realRegion 20 10 60 30
+path_addRect dummyPath 1000 1000 10 10
+path_addRect realPath 20 10 60 30
+begin_block paintstuff
+fillRect 0 0 100 50 orange
+drawText 0 5 "Should be clipped"
+drawText 0 15 "Should be clipped"
+drawText 0 25 "Should be clipped"
+drawText 0 35 "Should be clipped"
+drawText 0 45 "Should be clipped"
+drawText 0 55 "Should be clipped"
+end_block
+
+translate 0 100
+
+# rect replaced by x
+save
+setClipRect 1000 1000 10 10 ReplaceClip
+setClipRect 20 10 60 30 ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRect 1000 1000 10 10 ReplaceClip
+setClipRectF 20 10 60 30 ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRect 1000 1000 10 10 ReplaceClip
+setClipRegion realRegion ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRect 1000 1000 10 10 ReplaceClip
+setClipPath realPath ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+# rectF replaced by x
+save
+setClipRectF 1000 1000 10 10 ReplaceClip
+setClipRect 20 10 60 30 ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRectF 1000 1000 10 10 ReplaceClip
+setClipRectF 20 10 60 30 ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRectF 1000 1000 10 10 ReplaceClip
+setClipRegion realRegion ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRectF 1000 1000 10 10 ReplaceClip
+setClipPath realPath ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+translate -800 100
+
+# region replaced by x
+save
+setClipRegion dummyRegion ReplaceClip
+setClipRect 20 10 60 30 ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRegion dummyRegion ReplaceClip
+setClipRectF 20 10 60 30 ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRegion dummyRegion ReplaceClip
+setClipRegion realRegion ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRegion dummyRegion ReplaceClip
+setClipPath realPath ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+# path replaced by x
+save
+setClipPath dummyPath ReplaceClip
+setClipRect 20 10 60 30 ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipPath dummyPath ReplaceClip
+setClipRectF 20 10 60 30 ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipPath dummyPath ReplaceClip
+setClipRegion realRegion ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+save
+setClipPath dummyPath ReplaceClip
+setClipPath realPath ReplaceClip
+repeat_block paintstuff
+restore
+translate 100 0
+
+region_addRect intregion 0 10 60 30
+path_addRect intpath 0 10 60 30
+
+translate -800 100
+# rect & x
+save
+setClipRect 0 10 60 30 ReplaceClip
+translate 40 0
+setClipRect 0 10 60 30 IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRect 0 10 60 30 ReplaceClip
+translate 40 0
+setClipRectF 0 10 60 30 IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRect 0 10 60 30 ReplaceClip
+translate 40 0
+setClipRegion intregion IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRect 0 10 60 30 ReplaceClip
+translate 40 0
+setClipPath intpath IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+# rectF & x
+save
+setClipRectF 0 10 60 30 ReplaceClip
+translate 40 0
+setClipRect 0 10 60 30 IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRectF 0 10 60 30 ReplaceClip
+translate 40 0
+setClipRectF 0 10 60 30 IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRectF 0 10 60 30 ReplaceClip
+translate 40 0
+setClipRegion intregion IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRectF 0 10 60 30 ReplaceClip
+translate 40 0
+setClipPath intpath IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+translate -800 100
+
+# region & x
+save
+setClipRegion intregion ReplaceClip
+translate 40 0
+setClipRect 0 10 60 30 IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRegion intregion ReplaceClip
+translate 40 0
+setClipRectF 0 10 60 30 IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRegion intregion ReplaceClip
+translate 40 0
+setClipRegion intregion IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipRegion intregion ReplaceClip
+translate 40 0
+setClipPath intpath IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+# path & x
+save
+setClipPath intpath ReplaceClip
+translate 40 0
+setClipRect 0 10 60 30 IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipPath intpath ReplaceClip
+translate 40 0
+setClipRectF 0 10 60 30 IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipPath intpath ReplaceClip
+translate 40 0
+setClipRegion intregion IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
+
+save
+setClipPath intpath ReplaceClip
+translate 40 0
+setClipPath intpath IntersectClip
+translate -40 0
+repeat_block paintstuff
+restore
+translate 100 0
diff --git a/tests/baseline/painting/scripts/pattern_xform.qps b/tests/baseline/painting/scripts/pattern_xform.qps
new file mode 100644
index 0000000000..224969f1c7
--- /dev/null
+++ b/tests/baseline/painting/scripts/pattern_xform.qps
@@ -0,0 +1,79 @@
+# Version: 1
+# CheckVsReference: 5%
+
+#define basic block off screen
+save
+translate -1000 -1000
+begin_block drawrects
+setBrush green Dense4Pattern
+drawRect 0 0 40 40
+setBrush green DiagCrossPattern
+drawRect 40 0 40 40
+setBrush green HorPattern
+brushRotate 30
+drawRect 80 0 40 40
+fillRect 120 0 40 40
+save
+setPen brush 40 SolidLine FlatCap
+setBrush NoBrush
+drawLine 160 20 200 20
+restore
+end_block
+restore
+
+begin_block hintsuite
+save
+setRenderHint NonCosmeticBrushPatterns false
+setRenderHint SmoothPixmapTransform false
+translate 10 10
+repeat_block drawrects
+
+setRenderHint NonCosmeticBrushPatterns false
+setRenderHint SmoothPixmapTransform true
+translate 0 50
+repeat_block drawrects
+
+setRenderHint NonCosmeticBrushPatterns true
+setRenderHint SmoothPixmapTransform false
+translate 0 50
+repeat_block drawrects
+
+setRenderHint NonCosmeticBrushPatterns true
+setRenderHint SmoothPixmapTransform true
+translate 0 50
+repeat_block drawrects
+restore
+end_block
+
+save
+translate 0 200
+scale 2 2
+repeat_block hintsuite
+restore
+
+save
+translate 500 0
+scale 1.5 2.5
+rotate_y 60
+repeat_block hintsuite
+restore
+
+
+translate 0 650
+setBrush blue CrossPattern
+setPen red
+setRenderHint NonCosmeticBrushPatterns false
+
+begin_block dots
+save
+drawRect 0 0 50 50
+setBrushOrigin 12 0
+drawRect 50 0 50 50
+scale 2 1
+drawRect 50 0 50 50
+restore
+end_block dots
+
+setRenderHint NonCosmeticBrushPatterns true
+translate 0 60
+repeat_block dots
diff --git a/tests/baseline/painting/scripts/pattern_xform2.qps b/tests/baseline/painting/scripts/pattern_xform2.qps
new file mode 100644
index 0000000000..4f9314272d
--- /dev/null
+++ b/tests/baseline/painting/scripts/pattern_xform2.qps
@@ -0,0 +1,81 @@
+# Version: 1
+# CheckVsReference: 5%
+
+# 1: Check brush origin vs (non)cosmetic brush patterns
+
+setBrush blue CrossPattern
+begin_block blockName
+save
+setBrushOrigin 0 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 1 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 2 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 3 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 4 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 5 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 6 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 7 0
+fillRect 0 0 32 32
+translate 0 32
+setBrushOrigin 8 0
+fillRect 0 0 32 32
+restore
+end_block blockName
+
+save
+setBrush red CrossPattern
+scale 2 1
+repeat_block blockName
+restore
+
+save
+translate 0 300
+setRenderHint NonCosmeticBrushPatterns true
+setBrush blue CrossPattern
+repeat_block blockName
+setBrush red CrossPattern
+scale 2 1
+repeat_block blockName
+restore
+
+# 2: Check brush update after only xform or hint change
+translate 100 0
+
+save
+setPen NoPen
+setBrush blue DiagCrossPattern
+setRenderHint NonCosmeticBrushPatterns true
+drawRect 10 10 200 100
+scale 10 10
+drawRect 22 1 20 10
+drawRect 22 12 20 10
+setRenderHint NonCosmeticBrushPatterns false
+drawRect 1 12 20 10
+restore
+
+setBrush green DiagCrossPattern
+setPen brush 100 SolidLine FlatCap
+pen_setCosmetic true
+setBrush NoBrush
+translate 0 250
+setRenderHint NonCosmeticBrushPatterns true
+drawLine 10 60 210 60
+scale 10 10
+drawLine 22 6 42 6
+drawLine 22 17 42 17
+setRenderHint NonCosmeticBrushPatterns false
+drawLine 1 17 21 17
+
diff --git a/tests/baseline/painting/scripts/pixmapfragments.qps b/tests/baseline/painting/scripts/pixmapfragments.qps
new file mode 100644
index 0000000000..4c837b760f
--- /dev/null
+++ b/tests/baseline/painting/scripts/pixmapfragments.qps
@@ -0,0 +1,65 @@
+# Version: 1
+# CheckVsReference: 1% (0 0 690 580)
+
+
+setRenderHint Antialiasing
+
+setPen #00ff00
+
+pixmap_load dome_argb32.png the_pixmap
+begin_block draw_stuff
+save
+ drawPixmapFragments the_pixmap 1 50 50 25 25 60 60 1 1 0 1
+ drawPixmapFragments the_pixmap 1 150 50 25 25 60 60 1 1 0 0.5
+ drawPixmapFragments the_pixmap 1 250 50 25 25 60 60 1 1 30 1
+ drawPixmapFragments the_pixmap 1 350 50 25 25 60 60 1.5 1 0 1
+ drawPixmapFragments the_pixmap 1 450 50 25 25 60 60 1 1.5 0 1
+ drawPixmapFragments the_pixmap 2 550 50 25 25 40 40 0.5 0.5 -45 1 600 50 25 25 40 40 0.7 0.7 45 1
+restore
+end_block
+
+
+translate 0 120
+pixmap_load dome_rgb32.png the_pixmap
+repeat_block draw_stuff
+
+translate 0 120
+pixmap_load dome_indexed.png the_pixmap
+repeat_block draw_stuff
+
+translate 0 120
+pixmap_load dome_indexed_mask.png the_pixmap
+repeat_block draw_stuff
+
+translate 0 120
+pixmap_load dome_mono.png the_pixmap
+repeat_block draw_stuff
+
+
+resetMatrix
+translate 700 60
+setPen black
+drawText 0 0 "32 bit w/alpha"
+translate 0 120
+drawText 0 0 "32 bit w/o alpha"
+translate 0 120
+drawText 0 0 "8 bit indexed"
+translate 0 120
+drawText 0 0 "8 bit indexed w/mask"
+translate 0 120
+drawText 0 0 "1 bit"
+
+resetMatrix
+translate 25 600
+drawText 0 0 "simple"
+translate 100 0
+drawText 0 0 "opacity"
+translate 100 0
+drawText 0 0 "rotation"
+translate 100 0
+drawText 0 0 "scale x"
+translate 100 0
+drawText 0 0 "scale y"
+translate 100 0
+drawText 0 0 "two fragments"
+translate 100 0
diff --git a/tests/baseline/painting/scripts/text.qps b/tests/baseline/painting/scripts/text.qps
index 4d81b3084c..6bacdfd5e6 100644
--- a/tests/baseline/painting/scripts/text.qps
+++ b/tests/baseline/painting/scripts/text.qps
@@ -165,7 +165,7 @@ translate 0 75
save
setPen black
setFont "sansserif" 16 normal
- drawText 0 40 "e😃m😇o😍j😜i😸!"
+ drawText 0 40 "e😃m😇o😍j😜i😸!✈️"
restore
translate 0 75
diff --git a/tests/baseline/painting/tst_baseline_painting.cpp b/tests/baseline/painting/tst_baseline_painting.cpp
index a5d787f6ce..f486b33430 100644
--- a/tests/baseline/painting/tst_baseline_painting.cpp
+++ b/tests/baseline/painting/tst_baseline_painting.cpp
@@ -1,30 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
#include "paintcommands.h"
#include <qbaselinetest.h>
@@ -66,7 +43,8 @@ private:
};
void setupTestSuite(const QStringList& blacklist = QStringList());
- void runTestSuite(GraphicsEngine engine, QImage::Format format, const QSurfaceFormat &contextFormat = QSurfaceFormat());
+ void runTestSuite(GraphicsEngine engine, QImage::Format format,
+ const QSurfaceFormat &contextFormat = QSurfaceFormat::defaultFormat());
void paint(QPaintDevice *device, GraphicsEngine engine, QImage::Format format, const QStringList &script, const QString &filePath);
QStringList qpsFiles;
@@ -76,7 +54,7 @@ private:
private slots:
void initTestCase();
- void cleanupTestCase() {}
+ void init();
void testRasterARGB32PM_data();
void testRasterARGB32PM();
@@ -112,6 +90,7 @@ private slots:
void testCoreOpenGL_data();
void testCoreOpenGL();
private:
+ void initOpenGL();
bool checkSystemGLSupport();
bool checkSystemCoreGLSupport();
#endif
@@ -143,13 +122,22 @@ void tst_Lancelot::initTestCase()
std::sort(qpsFiles.begin(), qpsFiles.end());
foreach (const QString& fileName, qpsFiles) {
QFile file(scriptsDir + fileName);
- file.open(QFile::ReadOnly);
+ QVERIFY(file.open(QFile::ReadOnly));
QByteArray cont = file.readAll();
scripts.insert(fileName, QString::fromUtf8(cont).split(QLatin1Char('\n'), Qt::SkipEmptyParts));
scriptChecksums.insert(fileName, qChecksum(cont));
}
+
+#ifndef QT_NO_OPENGL
+ initOpenGL();
+#endif
}
+void tst_Lancelot::init()
+{
+ // This gets called for every row. QSKIP if current item is blacklisted on the baseline server:
+ QBASELINE_SKIP_IF_BLACKLISTED;
+}
void tst_Lancelot::testRasterARGB32PM_data()
{
@@ -292,6 +280,14 @@ void tst_Lancelot::testPdf()
#ifndef QT_NO_OPENGL
+void tst_Lancelot::initOpenGL()
+{
+ // Stencil buffer is needed for clipping
+ QSurfaceFormat glFormat;
+ glFormat.setStencilBufferSize(8);
+ QSurfaceFormat::setDefaultFormat(glFormat);
+}
+
bool tst_Lancelot::checkSystemGLSupport()
{
QWindow win;
@@ -315,7 +311,7 @@ bool tst_Lancelot::checkSystemCoreGLSupport()
if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL)
return false;
- QSurfaceFormat coreFormat;
+ QSurfaceFormat coreFormat(QSurfaceFormat::defaultFormat());
coreFormat.setVersion(3, 2);
coreFormat.setProfile(QSurfaceFormat::CoreProfile);
QWindow win;
@@ -370,7 +366,7 @@ void tst_Lancelot::testCoreOpenGL_data()
void tst_Lancelot::testCoreOpenGL()
{
- QSurfaceFormat coreFormat;
+ QSurfaceFormat coreFormat(QSurfaceFormat::defaultFormat());
coreFormat.setVersion(3, 2);
coreFormat.setProfile(QSurfaceFormat::CoreProfile);
runTestSuite(OpenGL, QImage::Format_RGB32, coreFormat);
@@ -427,19 +423,22 @@ void tst_Lancelot::runTestSuite(GraphicsEngine engine, QImage::Format format, co
QString tempStem(QDir::tempPath() + QLatin1String("/lancelot_XXXXXX_") + qpsFile.chopped(4));
QTemporaryFile pdfFile(tempStem + QLatin1String(".pdf"));
- pdfFile.open();
+ QVERIFY(pdfFile.open());
QPdfWriter writer(&pdfFile);
writer.setPdfVersion(QPdfWriter::PdfVersion_1_6);
- writer.setResolution(150);
+ QPageSize pageSize(QSize(800, 800), QStringLiteral("LancePage"), QPageSize::ExactMatch);
+ writer.setPageSize(pageSize);
+ writer.setPageMargins(QMarginsF());
+ writer.setResolution(72);
paint(&writer, engine, format, script, QFileInfo(filePath).absoluteFilePath());
pdfFile.close();
// Convert pdf to something we can read into a QImage, using macOS' sips utility
QTemporaryFile pngFile(tempStem + QLatin1String(".png"));
- pngFile.open(); // Just create the file name
+ QVERIFY(pngFile.open()); // Just create the file name
pngFile.close();
QProcess proc;
- const char *rawArgs = "-s format png --cropOffset 20 20 -c 800 800 -o";
+ const char *rawArgs = "-s format png -o";
QStringList argList = QString::fromLatin1(rawArgs).split(QLatin1Char(' '));
proc.start(QLatin1String("sips"), argList << pngFile.fileName() << pdfFile.fileName());
proc.waitForFinished(2 * 60 * 1000); // May need some time
@@ -480,7 +479,8 @@ QTEST_MAIN(tst_Lancelot)
int main(int argc, char *argv[])
{
- qSetGlobalQHashSeed(0); // Avoid rendering variations caused by QHash randomization
+ // Avoid rendering variations caused by QHash randomization
+ QHashSeed::setDeterministicGlobalSeed();
QBaselineTest::handleCmdLineArgs(&argc, &argv);
return _realmain(argc, argv);
diff --git a/tests/baseline/shared/baselineprotocol.cpp b/tests/baseline/shared/baselineprotocol.cpp
index ab6ced204a..6a38e71831 100644
--- a/tests/baseline/shared/baselineprotocol.cpp
+++ b/tests/baseline/shared/baselineprotocol.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "baselineprotocol.h"
#include <QLibraryInfo>
#include <QImage>
@@ -70,24 +45,26 @@ PlatformInfo PlatformInfo::localHostInfo()
#endif
pi.insert(PI_OSVersion, QSysInfo::kernelVersion());
+ QString gc = qEnvironmentVariable("BASELINE_GIT_COMMIT");
#if QT_CONFIG(process)
- QProcess git;
- QString cmd;
- QStringList args;
-#if defined(Q_OS_WIN)
- cmd = QLS("cmd.exe");
- args << QLS("/c") << QLS("git");
-#else
- cmd = QLS("git");
-#endif
- args << QLS("log") << QLS("--max-count=1") << QLS("--pretty=%H [%an] [%ad] %s");
- git.start(cmd, args);
- git.waitForFinished(3000);
- if (!git.exitCode())
- pi.insert(PI_GitCommit, QString::fromLocal8Bit(git.readAllStandardOutput().constData()).simplified());
- else
- pi.insert(PI_GitCommit, QLS("Unknown"));
+ if (gc.isEmpty()) {
+ QProcess git;
+ QString cmd;
+ QStringList args;
+ #if defined(Q_OS_WIN)
+ cmd = QLS("cmd.exe");
+ args << QLS("/c") << QLS("git");
+ #else
+ cmd = QLS("git");
+ #endif
+ args << QLS("log") << QLS("--max-count=1") << QLS("--pretty=%H [%an] [%ad] %s");
+ git.start(cmd, args);
+ git.waitForFinished(3000);
+ if (!git.exitCode())
+ gc = QString::fromLocal8Bit(git.readAllStandardOutput().constData()).simplified();
+ }
#endif // QT_CONFIG(process)
+ pi.insert(PI_GitCommit, gc.isEmpty() ? QLS("Unknown") : gc);
if (qEnvironmentVariableIsSet("JENKINS_HOME"))
pi.setAdHocRun(false);
@@ -293,7 +270,7 @@ bool BaselineProtocol::connect(const QString &testCase, bool *dryrun, const Plat
socket.connectToHost(serverName, ServerPort);
if (!socket.waitForConnected(Timeout)) {
- QThread::msleep(3000); // Wait a bit and try again, the server might just be restarting
+ QThread::sleep(std::chrono::seconds{3}); // Wait a bit and try again, the server might just be restarting
if (!socket.waitForConnected(Timeout)) {
errMsg += QLS("TCP connectToHost failed. Host:") + QLS(serverName) + QLS(" port:") + QString::number(ServerPort);
return false;
diff --git a/tests/baseline/shared/baselineprotocol.h b/tests/baseline/shared/baselineprotocol.h
index a5cc6ba661..598a0cd3af 100644
--- a/tests/baseline/shared/baselineprotocol.h
+++ b/tests/baseline/shared/baselineprotocol.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef BASELINEPROTOCOL_H
#define BASELINEPROTOCOL_H
diff --git a/tests/baseline/shared/lookup3.cpp b/tests/baseline/shared/lookup3.cpp
index 1fbe6b499e..7964a184ae 100644
--- a/tests/baseline/shared/lookup3.cpp
+++ b/tests/baseline/shared/lookup3.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
/*
@@ -328,7 +303,7 @@ quint32 hashlittle( const void *key, size_t length, quint32 initval)
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
- * noticably faster for short strings (like English words).
+ * noticeably faster for short strings (like English words).
*/
#ifndef VALGRIND
@@ -536,7 +511,7 @@ void hashlittle2(
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
- * noticably faster for short strings (like English words).
+ * noticeably faster for short strings (like English words).
*/
#ifndef VALGRIND
@@ -736,7 +711,7 @@ quint32 hashbig( const void *key, size_t length, quint32 initval)
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
- * noticably faster for short strings (like English words).
+ * noticeably faster for short strings (like English words).
*/
#ifndef VALGRIND
diff --git a/tests/baseline/shared/paintcommands.cpp b/tests/baseline/shared/paintcommands.cpp
index d2e48688f9..20201b66b0 100644
--- a/tests/baseline/shared/paintcommands.cpp
+++ b/tests/baseline/shared/paintcommands.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "paintcommands.h"
#include <qdir.h>
@@ -198,6 +173,13 @@ const char *PaintCommands::imageFormatTable[] = {
"RGBx32FPx4",
"RGBA32FPx4",
"RGBA32FPx4_Premultiplied",
+ "CMYK32",
+};
+
+const char *PaintCommands::renderHintTable[] = {
+ "Antialiasing",
+ "SmoothPixmapTransform",
+ "NonCosmeticBrushPatterns"
};
int PaintCommands::translateEnum(const char *table[], const QString &pattern, int limit)
@@ -338,7 +320,7 @@ void PaintCommands::staticInit()
"pen_setCosmetic true");
DECL_PAINTCOMMAND("setRenderHint", command_setRenderHint,
"^setRenderHint\\s+([\\w_0-9]*)\\s*(\\w*)$",
- "setRenderHint <Antialiasing|SmoothPixmapTransform> <true|false>",
+ "setRenderHint <hint> <true|false>",
"setRenderHint Antialiasing true");
DECL_PAINTCOMMAND("clearRenderHint", command_clearRenderHint,
"^clearRenderHint$",
@@ -488,6 +470,20 @@ void PaintCommands::staticInit()
"^fillRectF\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s*(\\w*)?$",
"fillRectF <x> <y> <w> <h> [color]\n - Uses current brush if no color given",
"fillRectF 10.5 10.5 20.2 20.2 blue");
+ DECL_PAINTCOMMAND("drawPixmapFragments", command_drawPixmapFragments,
+ "^drawPixmapFragments\\s+([\\w.:\\/]*)"
+ "\\s+(-?\\w*)"
+ "\\s+(-?[.\\w]*)\\s*(-?[.\\w]*)"
+ "\\s+(-?[.\\w]*)\\s*(-?[.\\w]*)\\s*(-?[.\\w]*)\\s*(-?[.\\w]*)"
+ "\\s+(-?[.\\w]*)\\s*(-?[.\\w]*)\\s*(-?[.\\w]*)\\s*(-?[.\\w]*)"
+ "\\s*(-?[.\\w]*)?\\s*(-?[.\\w]*)?"
+ "\\s*(-?[.\\w]*)?\\s*(-?[.\\w]*)?\\s*(-?[.\\w]*)?\\s*(-?[.\\w]*)?"
+ "\\s*(-?[.\\w]*)?\\s*(-?[.\\w]*)\\s*(-?[.\\w]*)?\\s*(-?[.\\w]*)?$",
+ "drawPixmapFragments <image filename> <count>"
+ " <centerx0> <centery0> <x0> <y0> <w0> <h0> <sx0> <sy0> <r0> <o0>"
+ " <centerx1> <centery1> <x1> <y1> <w1> ..."
+ "\n - where count is 1 or 2, and followed by centerPos, sourceRect, scaleX, scaleY, rotation, opacity <count> times",
+ "drawPixmapFragments :/images/sign.png 1 50 50 10 10 60 60 10 10 30 1");
DECL_PAINTCOMMANDSECTION("painterPaths");
DECL_PAINTCOMMAND("path_moveTo", command_path_moveTo,
@@ -564,8 +560,12 @@ void PaintCommands::staticInit()
"setClipPath mypath ReplaceClip");
DECL_PAINTCOMMAND("setClipRect", command_setClipRect,
"^setClipRect\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s+(-?\\w*)\\s*(\\w*)$",
- "setClipRect <x1> <y1> <x2> <y2> <clip operation enum>",
- "setClipRect 0.0 0.0 10.0 10.0 ReplaceClip");
+ "setClipRect <x> <y> <w> <h> <clip operation enum>",
+ "setClipRect 0 0 10 10 ReplaceClip");
+ DECL_PAINTCOMMAND("setClipRectF", command_setClipRectF,
+ "^setClipRectF\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s+(-?[.\\w]*)\\s*(\\w.*)$",
+ "setClipRectF <x> <y> <w> <h> <clip operation enum>",
+ "setClipRectF 0.1 0.2 10.3 10.4 ReplaceClip");
DECL_PAINTCOMMAND("setClipping", command_setClipping,
"^setClipping\\s+(\\w*)$",
"setClipping <true|false>",
@@ -686,6 +686,7 @@ void PaintCommands::staticInit()
ADD_ENUMLIST("image formats", imageFormatTable);
ADD_ENUMLIST("coordinate modes", coordinateMethodTable);
ADD_ENUMLIST("size modes", sizeModeTable);
+ ADD_ENUMLIST("render hints", renderHintTable);
}
#undef DECL_PAINTCOMMAND
@@ -745,8 +746,8 @@ void PaintCommands::runCommand(const QString &scriptLine)
return;
}
QString firstWord = scriptLine.section(separators, 0, 0);
- QList<int> indices = s_commandHash.values(firstWord);
- foreach(int idx, indices) {
+ const QList<int> indices = s_commandHash.values(firstWord);
+ for (int idx : indices) {
PaintCommandInfos command = s_commandInfoTable.at(idx);
Q_ASSERT(command.regExp.isValid());
QRegularExpressionMatch match = command.regExp.match(scriptLine);
@@ -921,7 +922,7 @@ void PaintCommands::command_import(QRegularExpressionMatch re)
if (m_verboseMode) {
printf(" -(lance) Command buffer now looks like:\n");
- for (int i = 0; i < m_commands.count(); ++i)
+ for (int i = 0; i < m_commands.size(); ++i)
printf(" ---> {%s}\n", qPrintable(m_commands.at(i)));
}
delete file;
@@ -939,7 +940,7 @@ void PaintCommands::command_begin_block(QRegularExpressionMatch re)
m_commands[m_currentCommandIndex] = QLatin1String("# begin block (") + blockName + QLatin1Char(')');
QStringList newBlock;
int i = m_currentCommandIndex + 1;
- for (; i < m_commands.count(); ++i) {
+ for (; i < m_commands.size(); ++i) {
const QString &nextCmd = m_commands.at(i);
if (nextCmd.startsWith("end_block")) {
m_commands[i] = QLatin1String("# end block (") + blockName + QLatin1Char(')');
@@ -949,10 +950,10 @@ void PaintCommands::command_begin_block(QRegularExpressionMatch re)
}
if (m_verboseMode)
- for (int j = 0; j < newBlock.count(); ++j)
+ for (int j = 0; j < newBlock.size(); ++j)
printf(" %d: %s\n", j, qPrintable(newBlock.at(j)));
- if (i >= m_commands.count())
+ if (i >= m_commands.size())
printf(" - Warning! Block doesn't have an 'end_block' marker!\n");
m_blockMap.insert(blockName, newBlock);
@@ -1466,6 +1467,93 @@ void PaintCommands::command_fillRectF(QRegularExpressionMatch re)
}
}
+void PaintCommands::command_drawPixmapFragments(QRegularExpressionMatch re)
+{
+ QPixmap pm;
+ pm = m_pixmapMap[re.captured(1)]; // try cache first
+ if (pm.isNull())
+ pm = image_load<QPixmap>(re.captured(1));
+ if (pm.isNull()) {
+ QFileInfo fi(m_filepath);
+ QDir dir = fi.absoluteDir();
+ dir.cdUp();
+ dir.cd("images");
+ QString fileName = dir.absolutePath() + QLatin1Char('/') + re.captured(1);
+ pm = QPixmap(fileName);
+ if (pm.isNull() && !fileName.endsWith(".png")) {
+ fileName.append(".png");
+ pm = QPixmap(fileName);
+ }
+ }
+ if (pm.isNull()) {
+ fprintf(stderr, "ERROR(drawPixmapFragments): failed to load pixmap: '%s'\n",
+ qPrintable(re.captured(1)));
+ return;
+ }
+
+ int count = convertToInt(re.captured(2));
+
+ struct Fragment {
+ double posx;
+ double posy;
+ double srcx;
+ double srcy;
+ double srcw;
+ double srch;
+ double sx;
+ double sy;
+ double rotation;
+ double opacity;
+ };
+
+ QList<Fragment> fragments;
+ for (int i = 0; i < count; ++i) {
+ int captureIndexStart = 3 + i * 10;
+ if (re.hasCaptured(captureIndexStart)) {
+ Fragment f;
+ f.posx = convertToDouble(re.captured(captureIndexStart));
+ f.posy = convertToDouble(re.captured(captureIndexStart + 1));
+ f.srcx = convertToDouble(re.captured(captureIndexStart + 2));
+ f.srcy = convertToDouble(re.captured(captureIndexStart + 3));
+ f.srcw = convertToDouble(re.captured(captureIndexStart + 4));
+ f.srch = convertToDouble(re.captured(captureIndexStart + 5));
+ f.sx = convertToDouble(re.captured(captureIndexStart + 6));
+ f.sy = convertToDouble(re.captured(captureIndexStart + 7));
+ f.rotation = convertToDouble(re.captured(captureIndexStart + 8));
+ f.opacity = convertToDouble(re.captured(captureIndexStart + 9));
+ fragments.append(f);
+ } else {
+ break;
+ }
+ }
+
+ if (m_verboseMode) {
+ printf(" -(lance) drawPixmapFragments('%s' count=%d ",
+ qPrintable(re.captured(1)), int(fragments.count()));
+ for (int i = 0; i < fragments.count(); ++i) {
+ printf("pos=(%.2f, %.2f) srcrect=(%.2f %.2f %.2f %.2f) scale=(%.2f %.2f) rotation=%.2f opacity=%.2f ",
+ fragments[i].posx, fragments[i].posy,
+ fragments[i].srcx, fragments[i].srcy, fragments[i].srcw, fragments[i].srch,
+ fragments[i].sx, fragments[i].sy,
+ fragments[i].rotation,
+ fragments[i].opacity);
+ }
+ printf("\n");
+ }
+
+ QList<QPainter::PixmapFragment> pixmapFragments;
+ for (int i = 0; i < fragments.count(); ++i) {
+ pixmapFragments.append(
+ QPainter::PixmapFragment::create(QPointF(fragments[i].posx, fragments[i].posy),
+ QRectF(fragments[i].srcx, fragments[i].srcy, fragments[i].srcw, fragments[i].srch),
+ fragments[i].sx, fragments[i].sy,
+ fragments[i].rotation,
+ fragments[i].opacity));
+ }
+
+ m_painter->drawPixmapFragments(pixmapFragments.constData(), pixmapFragments.count(), pm);
+}
+
/***************************************************************************************************/
void PaintCommands::command_noop(QRegularExpressionMatch)
{
@@ -2082,6 +2170,25 @@ void PaintCommands::command_setClipRect(QRegularExpressionMatch re)
}
/***************************************************************************************************/
+void PaintCommands::command_setClipRectF(QRegularExpressionMatch re)
+{
+ QStringList caps = re.capturedTexts();
+ double x = convertToDouble(caps.at(1));
+ double y = convertToDouble(caps.at(2));
+ double w = convertToDouble(caps.at(3));
+ double h = convertToDouble(caps.at(4));
+
+ int combine = translateEnum(clipOperationTable, caps.at(5), Qt::IntersectClip + 1);
+ if (combine == -1)
+ combine = Qt::ReplaceClip;
+
+ if (m_verboseMode)
+ printf(" -(lance) setClipRectF(%f, %f, %f, %f), %s\n", x, y, w, h, clipOperationTable[combine]);
+
+ m_painter->setClipRect(QRectF(x, y, w, h), Qt::ClipOperation(combine));
+}
+
+/***************************************************************************************************/
void PaintCommands::command_setClipPath(QRegularExpressionMatch re)
{
int combine = translateEnum(clipOperationTable, re.captured(2), Qt::IntersectClip + 1);
@@ -2121,19 +2228,27 @@ void PaintCommands::command_setFont(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
QString family = caps.at(1);
- int size = convertToInt(caps.at(2));
-
- int weight = translateEnum(fontWeightTable, re.captured(3).toLower(), 5);
- if (weight != -1) {
- switch (weight) {
- case 0: weight = QFont::Light; break;
- case 1: weight = QFont::Normal; break;
- case 2: weight = QFont::DemiBold; break;
- case 3: weight = QFont::Bold; break;
- case 4: weight = QFont::Black; break;
- }
- } else {
- weight = convertToInt(re.captured(3));
+
+ int size = -1; // Default
+ QString sizeArg = caps.at(2);
+ if (!sizeArg.isEmpty())
+ size = convertToInt(caps.at(2));
+
+ int weight = -1; // Default
+ QString weightArg = caps.at(3);
+ if (!weightArg.isEmpty()) {
+ weight = translateEnum(fontWeightTable, weightArg.toLower(), 5);
+ if (weight != -1) {
+ switch (weight) {
+ case 0: weight = QFont::Light; break;
+ case 1: weight = QFont::Normal; break;
+ case 2: weight = QFont::DemiBold; break;
+ case 3: weight = QFont::Bold; break;
+ case 4: weight = QFont::Black; break;
+ }
+ } else {
+ weight = convertToInt(weightArg);
+ }
}
bool italic = caps.at(4).toLower() == "true" || caps.at(4).toLower() == "italic";
@@ -2234,18 +2349,27 @@ void PaintCommands::command_setPen2(QRegularExpressionMatch re)
void PaintCommands::command_setRenderHint(QRegularExpressionMatch re)
{
QString hintString = re.captured(1).toLower();
- bool on = re.captured(2).isEmpty() || re.captured(2).toLower() == "true";
- if (hintString.contains("antialiasing")) {
- if (m_verboseMode)
- printf(" -(lance) setRenderHint Antialiasing\n");
+ QString setting = re.captured(2).toLower();
- m_painter->setRenderHint(QPainter::Antialiasing, on);
+ bool on = setting.isEmpty() || setting == "true" || setting == "on";
+ QPainter::RenderHint hint;
+ int hintIdx = -1;
+ if (hintString.contains("antialiasing")) {
+ hintIdx = 0;
+ hint = QPainter::Antialiasing;
} else if (hintString.contains("smoothpixmaptransform")) {
+ hintIdx = 1;
+ hint = QPainter::SmoothPixmapTransform;
+ } else if (hintString.contains("noncosmeticbrushpatterns")) {
+ hintIdx = 2;
+ hint = QPainter::NonCosmeticBrushPatterns;
+ }
+ if (hintIdx >= 0) {
if (m_verboseMode)
- printf(" -(lance) setRenderHint SmoothPixmapTransform\n");
- m_painter->setRenderHint(QPainter::SmoothPixmapTransform, on);
+ printf(" -(lance) setRenderHint %s %s\n", renderHintTable[hintIdx], on ? "true" : "false");
+ m_painter->setRenderHint(hint, on);
} else {
- fprintf(stderr, "ERROR(setRenderHint): unknown hint '%s'\n", qPrintable(hintString));
+ fprintf(stderr, "ERROR(setRenderHint): unknown hint '%s'\n", qPrintable(re.captured(1)));
}
}
@@ -2254,6 +2378,7 @@ void PaintCommands::command_clearRenderHint(QRegularExpressionMatch /*re*/)
{
m_painter->setRenderHint(QPainter::Antialiasing, false);
m_painter->setRenderHint(QPainter::SmoothPixmapTransform, false);
+ m_painter->setRenderHint(QPainter::NonCosmeticBrushPatterns, false);
if (m_verboseMode)
printf(" -(lance) clearRenderHint\n");
}
diff --git a/tests/baseline/shared/paintcommands.h b/tests/baseline/shared/paintcommands.h
index 15c6d3fa58..45f78f9af6 100644
--- a/tests/baseline/shared/paintcommands.h
+++ b/tests/baseline/shared/paintcommands.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef PAINTCOMMANDS_H
#define PAINTCOMMANDS_H
@@ -68,15 +43,13 @@ class PaintCommands
{
public:
// construction / initialization
- PaintCommands(const QStringList &cmds, int w, int h, QImage::Format format)
+ PaintCommands(const QStringList &cmds, int /*w*/, int /*h*/, QImage::Format format)
: m_painter(0)
, m_surface_painter(0)
, m_format(format)
, m_commands(cmds)
, m_gradientSpread(QGradient::PadSpread)
, m_gradientCoordinate(QGradient::LogicalMode)
- , m_width(w)
- , m_height(h)
, m_verboseMode(false)
, m_type(WidgetType)
, m_checkers_background(true)
@@ -87,7 +60,9 @@ public:
, m_surface_glbuffer(0)
, m_surface_glpaintdevice(0)
#endif
- { staticInit(); }
+ {
+ staticInit();
+ }
public:
void setCheckersBackground(bool b) { staticInit(); m_checkers_background = b; }
@@ -162,7 +137,7 @@ private:
void command_brushShear(QRegularExpressionMatch re);
void command_setClipPath(QRegularExpressionMatch re);
void command_setClipRect(QRegularExpressionMatch re);
- void command_setClipRectangle(QRegularExpressionMatch re);
+ void command_setClipRectF(QRegularExpressionMatch re);
void command_setClipRegion(QRegularExpressionMatch re);
void command_setClipping(QRegularExpressionMatch re);
void command_setCompositionMode(QRegularExpressionMatch re);
@@ -208,6 +183,7 @@ private:
void command_drawTiledPixmap(QRegularExpressionMatch re);
void command_fillRect(QRegularExpressionMatch re);
void command_fillRectF(QRegularExpressionMatch re);
+ void command_drawPixmapFragments(QRegularExpressionMatch re);
// paths
void command_path_addEllipse(QRegularExpressionMatch re);
@@ -276,8 +252,6 @@ private:
QGradient::Spread m_gradientSpread;
QGradient::CoordinateMode m_gradientCoordinate;
bool m_abort;
- int m_width;
- int m_height;
bool m_verboseMode;
DeviceType m_type;
@@ -305,6 +279,7 @@ private:
static const char *compositionModeTable[];
static const char *imageFormatTable[];
static const char *sizeModeTable[];
+ static const char *renderHintTable[];
static int translateEnum(const char *table[], const QString &pattern, int limit);
// utility
diff --git a/tests/baseline/shared/qbaselinetest.cpp b/tests/baseline/shared/qbaselinetest.cpp
index 493be4bd7a..e41b8d5321 100644
--- a/tests/baseline/shared/qbaselinetest.cpp
+++ b/tests/baseline/shared/qbaselinetest.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qbaselinetest.h"
#include "baselineprotocol.h"
@@ -51,9 +26,6 @@ static QByteArray curFunction;
static ImageItemList itemList;
static bool gotBaselines;
-static QString definedTestProject;
-static QString definedTestCase;
-
void handleCmdLineArgs(int *argcp, char ***argvp)
{
@@ -167,7 +139,7 @@ void fetchCustomClientProperties()
key = line.left(colonPos).simplified().replace(' ', '_');
val = line.mid(colonPos+1).trimmed();
}
- if (!key.isEmpty() && key.length() < 64 && val.length() < 256) // ###TBD: maximum 256 chars in value?
+ if (!key.isEmpty() && key.size() < 64 && val.size() < 256) // ###TBD: maximum 256 chars in value?
addClientProperty(key, val);
else
qDebug() << "Unparseable script output ignored:" << line;
@@ -200,10 +172,7 @@ bool connect(QByteArray *msg, bool *error)
if (!customAutoModeSet)
clientInfo.setAdHocRun(defaultInfo.isAdHocRun());
- if (!definedTestProject.isEmpty())
- clientInfo.insert(PI_Project, definedTestProject);
-
- QString testCase = definedTestCase;
+ QString testCase = clientInfo.value(PI_TestCase);
if (testCase.isEmpty() && QTest::testObject() && QTest::testObject()->metaObject()) {
//qDebug() << "Trying to Read TestCaseName from Testlib!";
testCase = QTest::testObject()->metaObject()->className();
@@ -233,16 +202,10 @@ bool disconnectFromBaselineServer()
return false;
}
-bool connectToBaselineServer(QByteArray *msg, const QString &testProject, const QString &testCase)
+bool connectToBaselineServer(QByteArray *msg)
{
bool dummy;
QByteArray dummyMsg;
-
- if (!testProject.isEmpty())
- definedTestProject = testProject;
- if (!testCase.isEmpty())
- definedTestCase = testCase;
-
return connect(msg ? msg : &dummyMsg, &dummy);
}
@@ -259,7 +222,7 @@ void setSimFail(bool fail)
void setProject(const QString &projectName)
{
- definedTestProject = projectName;
+ addClientProperty(PI_Project, projectName);
}
void setProjectImageKeys(const QStringList &keys)
@@ -286,6 +249,7 @@ void modifyImage(QImage *img)
bool compareItem(const ImageItem &baseline, const QImage &img, QByteArray *msg, bool *error)
{
+ *error = false;
ImageItem item = baseline;
if (simfail) {
// Simulate test failure by forcing image mismatch; for testing purposes
@@ -296,6 +260,7 @@ bool compareItem(const ImageItem &baseline, const QImage &img, QByteArray *msg,
} else {
item.image = img;
}
+ bool isNewItem = false;
item.imageChecksums.clear();
item.imageChecksums.prepend(ImageItem::computeChecksum(item.image));
QByteArray srvMsg;
@@ -307,9 +272,11 @@ bool compareItem(const ImageItem &baseline, const QImage &img, QByteArray *msg,
return true;
break;
case ImageItem::BaselineNotFound:
- if (!customInfo.overrides().isEmpty() || baselinePolicy == UploadNone) {
- qWarning() << "Cannot compare to baseline: No such baseline found on server.";
+ if (!customInfo.overrides().isEmpty())
return true;
+ if (baselinePolicy == UploadNone) {
+ isNewItem = true;
+ break;
}
if (proto.submitNewBaseline(item, &srvMsg))
qDebug() << msg->constData() << "Baseline not found on server. New baseline uploaded.";
@@ -322,7 +289,6 @@ bool compareItem(const ImageItem &baseline, const QImage &img, QByteArray *msg,
return true;
break;
}
- *error = false;
// The actual comparison of the given image with the baseline:
if (baseline.imageChecksums.contains(item.imageChecksums.at(0))) {
if (!proto.submitMatch(item, &srvMsg))
@@ -343,7 +309,11 @@ bool compareItem(const ImageItem &baseline, const QImage &img, QByteArray *msg,
qInfo() << "Baseline server reports:" << srvMsg;
return true; // The server decides: a fuzzy match means no mismatch
}
- *msg += "Mismatch. See report:\n " + srvMsg;
+ if (isNewItem)
+ *msg += "No baseline on server, so cannot compare.";
+ else
+ *msg += "Mismatch.";
+ *msg += " See report:\n " + srvMsg;
if (dryRunMode) {
qDebug() << "Dryrun, so ignoring" << *msg;
return true;
@@ -409,22 +379,21 @@ QTestData &newRow(const char *dataTag, quint16 checksum)
return QTest::newRow(dataTag);
}
-
-bool testImage(const QImage& img, QByteArray *msg, bool *error)
+const ImageItem *findCurrentItem(QByteArray *msg, bool *error)
{
if (!connected && !connect(msg, error))
- return true;
+ return nullptr;
if (QTest::currentTestFunction() != curFunction || itemList.isEmpty()) {
- qWarning() << "Usage error: QBASELINE_TEST used without corresponding QBaselineTest::newRow()";
- return true;
+ qWarning() << "Usage error: QBASELINE_ macro used without corresponding QBaselineTest::newRow()";
+ return nullptr;
}
if (!gotBaselines) {
if (!proto.requestBaselineChecksums(QString::fromLatin1(QTest::currentTestFunction()), &itemList) || itemList.isEmpty()) {
*msg = "Communication with baseline server failed: " + proto.errorMessage().toLatin1();
*error = true;
- return true;
+ return nullptr;
}
gotBaselines = true;
}
@@ -434,10 +403,24 @@ bool testImage(const QImage& img, QByteArray *msg, bool *error)
while (it != itemList.constEnd() && it->itemName != curTag)
++it;
if (it == itemList.constEnd()) {
- qWarning() << "Usage error: QBASELINE_TEST used without corresponding QBaselineTest::newRow() for row" << curTag;
- return true;
+ qWarning() << "Usage error: QBASELINE_ macro used without corresponding QBaselineTest::newRow() for row" << curTag;
+ return nullptr;
}
- return compareItem(*it, img, msg, error);
+ return &(*it);
+}
+
+bool testImage(const QImage &img, QByteArray *msg, bool *error)
+{
+ const ImageItem *item = findCurrentItem(msg, error);
+ return item ? compareItem(*item, img, msg, error) : true;
+}
+
+bool isCurrentItemBlacklisted()
+{
+ QByteArray msg;
+ bool error = false;
+ const ImageItem *item = findCurrentItem(&msg, &error);
+ return item ? (item->status == ImageItem::IgnoreItem) : false;
}
}
diff --git a/tests/baseline/shared/qbaselinetest.h b/tests/baseline/shared/qbaselinetest.h
index 68f2efe461..f120e2bcd8 100644
--- a/tests/baseline/shared/qbaselinetest.h
+++ b/tests/baseline/shared/qbaselinetest.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef BASELINETEST_H
#define BASELINETEST_H
@@ -39,10 +14,11 @@ void handleCmdLineArgs(int *argcp, char ***argvp);
void setProject(const QString &projectName); // Selects server config settings and top level dir
void setProjectImageKeys(const QStringList &keys); // Overrides the ItemPathKeys config setting
void addClientProperty(const QString& key, const QString& value);
-bool connectToBaselineServer(QByteArray *msg = nullptr, const QString &testProject = QString(), const QString &testCase = QString());
+bool connectToBaselineServer(QByteArray *msg = nullptr);
bool checkImage(const QImage& img, const char *name, quint16 checksum, QByteArray *msg, bool *error, int manualdatatag = 0);
bool testImage(const QImage& img, QByteArray *msg, bool *error);
QTestData &newRow(const char *dataTag, quint16 checksum = 0);
+bool isCurrentItemBlacklisted();
bool disconnectFromBaselineServer();
bool shouldAbortIfUnstable();
}
@@ -84,4 +60,10 @@ do {\
}\
} while (0)
+#define QBASELINE_SKIP_IF_BLACKLISTED \
+do {\
+ if (QBaselineTest::isCurrentItemBlacklisted())\
+ QSKIP("Blacklisted on baseline server.");\
+} while (0)
+
#endif // BASELINETEST_H
diff --git a/tests/baseline/shared/qwidgetbaselinetest.cpp b/tests/baseline/shared/qwidgetbaselinetest.cpp
index e4b36ddb69..72a074e268 100644
--- a/tests/baseline/shared/qwidgetbaselinetest.cpp
+++ b/tests/baseline/shared/qwidgetbaselinetest.cpp
@@ -1,38 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qwidgetbaselinetest.h"
#include <qbaselinetest.h>
#include <QApplication>
#include <QStyle>
+#include <QStyleHints>
#include <QScreen>
+#include <QtWidgets/private/qapplication_p.h>
+
QT_BEGIN_NAMESPACE
QWidgetBaselineTest::QWidgetBaselineTest()
@@ -47,18 +25,25 @@ QWidgetBaselineTest::QWidgetBaselineTest()
// Encode a number of parameters that impact the UI
QPalette palette;
QFont font;
- QByteArray appearanceBytes;
- {
- QDataStream appearanceStream(&appearanceBytes, QIODevice::WriteOnly);
- appearanceStream << palette << font <<
+ const QString styleName =
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QApplication::style()->metaObject()->className();
#else
QApplication::style()->name();
#endif
+ // turn off animations and make the cursor flash time really long to avoid blinking
+ QApplication::style()->setProperty("_qt_animation_time", QTime());
+ QGuiApplication::styleHints()->setCursorFlashTime(50000);
+
+ QByteArray appearanceBytes;
+ {
+ QDataStream appearanceStream(&appearanceBytes, QIODevice::WriteOnly);
+ appearanceStream << palette << font;
const qreal screenDpr = QApplication::primaryScreen()->devicePixelRatio();
- if (screenDpr != 1.0)
- qWarning() << "DPR is" << screenDpr << "- images will be scaled";
+ if (screenDpr != 1.0) {
+ qWarning() << "DPR is" << screenDpr << "- images will not be compared to 1.0 baseline!";
+ appearanceStream << screenDpr;
+ }
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
const quint16 appearanceId = qChecksum(appearanceBytes, appearanceBytes.size());
@@ -72,8 +57,8 @@ QWidgetBaselineTest::QWidgetBaselineTest()
const QColor windowColor = palette.window().color();
const QColor textColor = palette.text().color();
const QString appearanceIdString = (windowColor.value() > textColor.value()
- ? QString("light-%1") : QString("dark-%1"))
- .arg(appearanceId, 0, 16);
+ ? QString("light-%1-%2") : QString("dark-%1-%2"))
+ .arg(styleName).arg(appearanceId, 0, 16);
QBaselineTest::addClientProperty("AppearanceID", appearanceIdString);
// let users know where they can find the results
@@ -92,11 +77,15 @@ void QWidgetBaselineTest::initTestCase()
void QWidgetBaselineTest::init()
{
QVERIFY(!window);
- window = new QWidget;
+ background = new QWidget(nullptr, Qt::FramelessWindowHint);
+ window = new QWidget(background, Qt::Window);
window->setWindowTitle(QTest::currentDataTag());
+ window->setFocusPolicy(Qt::StrongFocus);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ background->setScreen(QGuiApplication::primaryScreen());
window->setScreen(QGuiApplication::primaryScreen());
#endif
+ background->move(QGuiApplication::primaryScreen()->availableGeometry().topLeft());
window->move(QGuiApplication::primaryScreen()->availableGeometry().topLeft());
doInit();
@@ -106,33 +95,46 @@ void QWidgetBaselineTest::cleanup()
{
doCleanup();
- delete window;
+ delete background;
+ background = nullptr;
window = nullptr;
}
void QWidgetBaselineTest::makeVisible()
{
Q_ASSERT(window);
+ background->showMaximized();
window->show();
- QApplication::setActiveWindow(window);
+ QApplicationPrivate::setActiveWindow(window);
QVERIFY(QTest::qWaitForWindowActive(window));
- // explicitly unset focus, the test needs to control when focus is shown
- if (window->focusWidget())
- window->focusWidget()->clearFocus();
+ // explicitly set focus on the window so that the test widget doesn't have it
+ window->setFocus(Qt::OtherFocusReason);
+ QTRY_COMPARE(window->focusWidget(), window);
}
/*
- Always return images scaled to a DPR of 1.0.
-
- This might produce some fuzzy differences, but lets us
- compare those.
+ Grabs the test window and returns the resulting QImage, without
+ compensating for DPR differences.
*/
QImage QWidgetBaselineTest::takeSnapshot()
{
- QGuiApplication::processEvents();
- QPixmap pm = window->grab();
- QTransform scaleTransform = QTransform::fromScale(1.0 / pm.devicePixelRatioF(), 1.0 / pm.devicePixelRatioF());
- return pm.toImage().transformed(scaleTransform, Qt::SmoothTransformation);
+ // make sure all effects are done
+ QTest::qWait(250);
+ return window->grab().toImage();
+}
+
+/*
+ Grabs the test window screen and returns the resulting QImage, without
+ compensating for DPR differences.
+ This can be used for popup windows.
+*/
+QImage QWidgetBaselineTest::takeScreenSnapshot(const QRect& windowRect)
+{
+ // make sure all effects are done - wait longer here because entire
+ // windows might be fading in and out.
+ QTest::qWait(750);
+ return window->screen()->grabWindow(0, windowRect.x(), windowRect.y(),
+ windowRect.width(), windowRect.height()).toImage();
}
/*!
@@ -145,23 +147,25 @@ QImage QWidgetBaselineTest::takeSnapshot()
void QWidgetBaselineTest::takeStandardSnapshots()
{
makeVisible();
- struct PublicWidget : QWidget {
- bool focusNextPrevChild(bool next) override { return QWidget::focusNextPrevChild(next); }
- };
+ QWidget *oldFocusWidget = testWindow()->focusWidget();
+ QCOMPARE(oldFocusWidget, testWindow());
QBASELINE_CHECK_DEFERRED(takeSnapshot(), "default");
// try hard to set focus
- static_cast<PublicWidget*>(window)->focusNextPrevChild(true);
- if (!window->focusWidget()) {
- QWidget *firstChild = window->findChild<QWidget*>();
- if (firstChild)
- firstChild->setFocus();
- }
-
- if (testWindow()->focusWidget()) {
+ QWidget *testWidget = window->nextInFocusChain();
+ if (!testWidget)
+ testWidget = window->findChild<QWidget*>();
+ QVERIFY(testWidget);
+ // use TabFocusReason, some widgets handle that specifically to e.g. select
+ testWidget->setFocus(Qt::TabFocusReason);
+
+ if (testWindow()->focusWidget() != oldFocusWidget) {
QBASELINE_CHECK_DEFERRED(takeSnapshot(), "focused");
- testWindow()->focusWidget()->clearFocus();
+ // set focus back
+ oldFocusWidget->setFocus(Qt::OtherFocusReason);
+ } else {
+ qWarning() << "Couldn't set focus on tested widget" << testWidget;
}
// this disables all children
diff --git a/tests/baseline/shared/qwidgetbaselinetest.h b/tests/baseline/shared/qwidgetbaselinetest.h
index db73dd0540..2142217c09 100644
--- a/tests/baseline/shared/qwidgetbaselinetest.h
+++ b/tests/baseline/shared/qwidgetbaselinetest.h
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#pragma once
@@ -57,8 +32,10 @@ private slots:
protected:
void makeVisible();
QImage takeSnapshot();
+ QImage takeScreenSnapshot(const QRect& rect = QRect());
private:
+ QWidget *background = nullptr;
QWidget *window = nullptr;
};
diff --git a/tests/baseline/stylesheet/CMakeLists.txt b/tests/baseline/stylesheet/CMakeLists.txt
index 11f6e52179..3fdaa739fe 100644
--- a/tests/baseline/stylesheet/CMakeLists.txt
+++ b/tests/baseline/stylesheet/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
qss/*)
@@ -11,9 +14,10 @@ qt_internal_add_test(tst_baseline_stylesheet
tst_baseline_stylesheet.cpp
INCLUDE_DIRECTORIES
../shared
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::Gui
Qt::Widgets
+ Qt::WidgetsPrivate
Qt::Network
TESTDATA ${test_data}
)
diff --git a/tests/baseline/stylesheet/qss/dummy.qss b/tests/baseline/stylesheet/qss/dummy.qss
new file mode 100644
index 0000000000..7f09309153
--- /dev/null
+++ b/tests/baseline/stylesheet/qss/dummy.qss
@@ -0,0 +1,31 @@
+/* dummy stylesheet to reproduce QTBUG-100433 for QToolButton
+QDummyView {
+ alternate-background-color: yellow;
+}
+
+QDummyView {
+ show-decoration-selected: 1;
+}
+
+QDummyView::item {
+ border: 1px solid #d9d9d9;
+ border-top-color: transparent;
+ border-bottom-color: transparent;
+}
+
+QDummyView::item:hover {
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1);
+ border: 1px solid #bfcde4;
+}
+
+QDummyView::item:selected {
+ border: 1px solid #567dbc;
+}
+
+QDummyView::item:selected:active{
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);
+}
+
+QDummyView::item:selected:!active {
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);
+}
diff --git a/tests/baseline/stylesheet/qss/qheaderview/selectedFontWeight.qss b/tests/baseline/stylesheet/qss/qheaderview/selectedFontWeight.qss
new file mode 100644
index 0000000000..1c45a99767
--- /dev/null
+++ b/tests/baseline/stylesheet/qss/qheaderview/selectedFontWeight.qss
@@ -0,0 +1,16 @@
+QHeaderView::section {
+ background-color: red;
+ font-size: 10px;
+}
+
+QHeaderView::section:checked {
+ background-color: green;
+ font-size: 20px;
+ font-weight: bold;
+}
+
+QHeaderView::section:first {
+ background-color: yellow;
+ font-size: 20px;
+ font-weight: normal;
+}
diff --git a/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_no_border.qss b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_no_border.qss
new file mode 100644
index 0000000000..e9e098eb5c
--- /dev/null
+++ b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_no_border.qss
@@ -0,0 +1 @@
+QToolButton::menu-button { border: none }
diff --git a/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_padding.qss b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_padding.qss
new file mode 100644
index 0000000000..44e67671f0
--- /dev/null
+++ b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_padding.qss
@@ -0,0 +1,12 @@
+QToolButton {
+ border: 5px solid #9e9e9e;
+ background: #ffffff;
+ padding-top: 8px;
+ padding-bottom: 8px;
+}
+QToolButton[popupMode=InstantPopup] {
+ padding-right: 75px;
+}
+QToolButton::menu-indicator {
+ subcontrol-position: right;
+};
diff --git a/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_position.qss b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_position.qss
new file mode 100644
index 0000000000..4a1a5f0c23
--- /dev/null
+++ b/tests/baseline/stylesheet/qss/qtoolbutton/menuButton_subcontrol_position.qss
@@ -0,0 +1,4 @@
+QToolButton::menu-indicator {
+ subcontrol-position: right center;
+ subcontrol-origin: padding;
+}
diff --git a/tests/baseline/stylesheet/qss/qtreeview/showDecorationSelected.qss b/tests/baseline/stylesheet/qss/qtreeview/showDecorationSelected.qss
new file mode 100644
index 0000000000..b279b587bd
--- /dev/null
+++ b/tests/baseline/stylesheet/qss/qtreeview/showDecorationSelected.qss
@@ -0,0 +1,3 @@
+QTreeView {
+ show-decoration-selected: 1
+}
diff --git a/tests/baseline/stylesheet/qss/qtreeview/styledIndicators.qss b/tests/baseline/stylesheet/qss/qtreeview/styledIndicators.qss
new file mode 100644
index 0000000000..02263ad644
--- /dev/null
+++ b/tests/baseline/stylesheet/qss/qtreeview/styledIndicators.qss
@@ -0,0 +1,18 @@
+QTreeWidget::indicator:indeterminate {
+ background: red
+}
+QTreeWidget::indicator:indeterminate:disabled {
+ background: pink
+}
+QTreeWidget::indicator:checked {
+ background: green
+}
+QTreeWidget::indicator:checked:disabled {
+ background: lightgreen
+}
+QTreeWidget::indicator:unchecked {
+ background: blue
+}
+QTreeWidget::indicator:unchecked:disabled {
+ background: lightblue
+};
diff --git a/tests/baseline/stylesheet/qss/qtreeview/styledItem.qss b/tests/baseline/stylesheet/qss/qtreeview/styledItem.qss
new file mode 100644
index 0000000000..1da627881c
--- /dev/null
+++ b/tests/baseline/stylesheet/qss/qtreeview/styledItem.qss
@@ -0,0 +1,7 @@
+QAbstractItemView::item
+{
+ background: grey;
+}
+QTreeWidget::indicator:checked {
+ background: green
+}
diff --git a/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss b/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss
new file mode 100644
index 0000000000..7d54a74fe5
--- /dev/null
+++ b/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss
@@ -0,0 +1,10 @@
+QTreeView {
+ alternate-background-color: yellow;
+ show-decoration-selected: 1;
+}
+QTreeView::item:selected:active {
+ background: qlineargradient(x1:0, y1:0 x2: 0, y2: 1, stop: 0 #fea1f1 stop: 1 #567dbc)
+}
+QTreeView::branch {
+ border: 2px
+}
diff --git a/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp b/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp
index 99b21b4bb5..67a618988b 100644
--- a/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp
+++ b/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qbaselinetest.h>
#include <qwidgetbaselinetest.h>
@@ -49,6 +24,12 @@ private slots:
void tst_QScrollArea_data();
void tst_QScrollArea();
+ void tst_QTreeView_data();
+ void tst_QTreeView();
+
+ void tst_QHeaderView_data();
+ void tst_QHeaderView();
+
private:
QDir styleSheetDir;
};
@@ -85,7 +66,7 @@ void tst_Stylesheet::loadTestFiles()
for (const auto &qssFile : qssFiles) {
QFileInfo fileInfo(qssFile);
QFile file(qssFile);
- file.open(QFile::ReadOnly);
+ QVERIFY(file.open(QFile::ReadOnly));
QString styleSheet = QString::fromUtf8(file.readAll());
QBaselineTest::newRow(fileInfo.baseName().toUtf8()) << styleSheet;
}
@@ -98,7 +79,7 @@ void tst_Stylesheet::tst_QToolButton_data()
void tst_Stylesheet::tst_QToolButton()
{
- const QIcon fileIcon = QApplication::style()->standardIcon(QStyle::SP_FileIcon);
+ const QIcon trashIcon = QApplication::style()->standardIcon(QStyle::SP_TrashIcon);
QVBoxLayout *vbox = new QVBoxLayout;
@@ -107,8 +88,8 @@ void tst_Stylesheet::tst_QToolButton()
Qt::ToolButtonTextUnderIcon, Qt::ToolButtonTextBesideIcon}) {
QToolButton *normal = new QToolButton;
normal->setToolButtonStyle(buttonStyle);
- normal->setText("Text");
- normal->setIcon(fileIcon);
+ normal->setText("Norm");
+ normal->setIcon(trashIcon);
normalButtons->addWidget(normal);
}
vbox->addLayout(normalButtons);
@@ -116,7 +97,7 @@ void tst_Stylesheet::tst_QToolButton()
QHBoxLayout *arrowButtons = new QHBoxLayout;
for (const auto &arrowType : {Qt::LeftArrow, Qt::RightArrow, Qt::UpArrow, Qt::DownArrow}) {
QToolButton *arrow = new QToolButton;
- arrow->setText("Text");
+ arrow->setText("Arrs");
arrow->setArrowType(arrowType);
arrowButtons->addWidget(arrow);
}
@@ -126,7 +107,7 @@ void tst_Stylesheet::tst_QToolButton()
for (const auto &buttonStyle : {Qt::ToolButtonTextOnly,
Qt::ToolButtonTextUnderIcon, Qt::ToolButtonTextBesideIcon}) {
QToolButton *arrow = new QToolButton;
- arrow->setText("Text");
+ arrow->setText("ArrTxt");
arrow->setArrowType(Qt::UpArrow);
arrow->setToolButtonStyle(buttonStyle);
arrowWithTextButtons->addWidget(arrow);
@@ -137,8 +118,8 @@ void tst_Stylesheet::tst_QToolButton()
for (const auto &popupMode : {QToolButton::InstantPopup, QToolButton::MenuButtonPopup,
QToolButton::DelayedPopup}) {
QToolButton *menuButton = new QToolButton;
- menuButton->setText("Text");
- menuButton->setIcon(fileIcon);
+ menuButton->setText("PppMd");
+ menuButton->setIcon(trashIcon);
QMenu *menuButtonMenu = new QMenu;
menuButtonMenu->addAction(QIcon(":/icons/align-left.png"), "Left");
menuButtonMenu->addAction(QIcon(":/icons/align-right.png"), "Right");
@@ -170,13 +151,87 @@ void tst_Stylesheet::tst_QScrollArea()
QBASELINE_TEST(takeSnapshot());
}
+void tst_Stylesheet::tst_QTreeView_data()
+{
+ loadTestFiles();
+}
+
+void tst_Stylesheet::tst_QTreeView()
+{
+ QHBoxLayout *layout = new QHBoxLayout;
+ QTreeWidget *tw = new QTreeWidget();
+ tw->header()->hide();
+ layout->addWidget(tw);
+
+ enum {
+ Unchecked = 0,
+ Checked = 1,
+ Children = 2,
+ Disabled = 3,
+ CheckedDisabled = 4,
+ ChildrenDisabled = 5,
+ NConfigs
+ };
+
+ for (int i = 0; i < NConfigs; ++i) {
+ QTreeWidgetItem *topLevelItem = new QTreeWidgetItem(tw, QStringList{QString("top %1").arg(i)});
+ switch (i) {
+ case Unchecked:
+ case Disabled:
+ topLevelItem->setCheckState(0, Qt::Unchecked);
+ break;
+ case Checked:
+ case CheckedDisabled:
+ topLevelItem->setCheckState(0, Qt::Checked);
+ break;
+ case Children:
+ case ChildrenDisabled:
+ topLevelItem->setCheckState(0, Qt::PartiallyChecked);
+ topLevelItem->setExpanded(true);
+ for (int j = 0; j < 2; ++j) {
+ QTreeWidgetItem *childItem = new QTreeWidgetItem(topLevelItem, QStringList{QString("child %1").arg(j)});
+ childItem->setCheckState(0, j % 2 ? Qt::Unchecked : Qt::Checked);
+ }
+ break;
+ }
+ topLevelItem->setDisabled(i >= Disabled);
+ }
+ testWindow()->setLayout(layout);
+ tw->setRootIsDecorated(true);
+ makeVisible();
+
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "rootDecorated");
+ tw->setRootIsDecorated(false);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "rootNotDecorated");
+
+ tw->topLevelItem(Children)->child(0)->setSelected(true);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "itemSelected");
+}
+
+void tst_Stylesheet::tst_QHeaderView_data()
+{
+ loadTestFiles();
+}
+
+void tst_Stylesheet::tst_QHeaderView()
+{
+ QHBoxLayout *layout = new QHBoxLayout;
+ QTableWidget *tw = new QTableWidget(10, 10);
+ tw->setCurrentCell(1, 1);
+ layout->addWidget(tw);
+ testWindow()->setLayout(layout);
+ makeVisible();
+ QBASELINE_TEST(takeSnapshot());
+}
+
#define main _realmain
QTEST_MAIN(tst_Stylesheet)
#undef main
int main(int argc, char *argv[])
{
- qSetGlobalQHashSeed(0); // Avoid rendering variations caused by QHash randomization
+ // Avoid rendering variations caused by QHash randomization
+ QHashSeed::setDeterministicGlobalSeed();
QBaselineTest::handleCmdLineArgs(&argc, &argv);
return _realmain(argc, argv);
diff --git a/tests/baseline/text/CMakeLists.txt b/tests/baseline/text/CMakeLists.txt
index 707b3794b5..74d01337cb 100644
--- a/tests/baseline/text/CMakeLists.txt
+++ b/tests/baseline/text/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
list(APPEND test_data "./data")
qt_internal_add_test(tst_baseline_text
@@ -8,9 +11,10 @@ qt_internal_add_test(tst_baseline_text
tst_baseline_text.cpp
INCLUDE_DIRECTORIES
../shared
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::Gui
Qt::Widgets
+ Qt::WidgetsPrivate
Qt::Network
TESTDATA ${test_data}
)
diff --git a/tests/baseline/text/data/colored_list.html b/tests/baseline/text/data/colored_list.html
new file mode 100644
index 0000000000..d1cca94460
--- /dev/null
+++ b/tests/baseline/text/data/colored_list.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html>
+<head>
+<style type="text/css">
+p, li { white-space: pre-wrap; }
+hr { height: 1px; border-width: 0; }
+li.unchecked::marker { content: "\2610"; }
+li.checked::marker { content: "\2612"; }
+body { background-color: #111155; color: #ffffff; }
+</style>
+</head>
+<body>
+
+<ul>
+<li>disc</li>
+<li style=" color:#a58d47;">bronze</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red bullet, pink text</span></li>
+<li style=" color:#dddddd;" class="checked">checked</li>
+<li style=" color:#dddddd;" class="unchecked">unchecked</li>
+</ul>
+
+<ul type="circle">
+<li>circle</li>
+<li style=" color:#dddddd;">silver</li>
+<li style=" color:lightgrey;"><span style=" color:#ffcdb9;">grey bullet, pink text</span></li>
+<li style=" color:#dddddd;" class="checked">checked</li>
+<li style=" color:#dddddd;" class="unchecked">unchecked</li>
+</ul>
+
+<ul type="square">
+<li style=" color:#ffffff;">square</li>
+<li style=" color:#fceebb;">gold</li>
+<li style=" color:yellow;"><span style=" color:#ffcdb9;">yellow bullet, pink text</span></li>
+<li style=" color:#dddddd;" class="checked">checked</li>
+<li style=" color:#dddddd;" class="unchecked">unchecked</li>
+</ul>
+
+<ol>
+<li>decimal</li>
+<li style=" color:#a58d47;">bronze decimal</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red number, pink text</span></li>
+</ol>
+
+<ol type="A">
+<li>uppercase</li>
+<li style=" color:#a58d47;">bronze uppercase</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red letter, pink text</span></li>
+</ol>
+
+<ol type="a">
+<li>lowercase</li>
+<li style=" color:#a58d47;">bronze lowercase</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red letter, pink text</span></li>
+</ol>
+
+<ol type="i">
+<li>lower roman</li>
+<li style=" color:#a58d47;">bronze roman</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red number, pink text</span></li>
+</ol>
+
+<ol type="I">
+<li>upper roman</li>
+<li style=" color:#a58d47;">bronze roman</li>
+<li style=" color:red;"><span style=" color:#ffcdb9;">red number, pink text</span></li>
+</ol>
+</body>
+</html>
diff --git a/tests/baseline/text/tst_baseline_text.cpp b/tests/baseline/text/tst_baseline_text.cpp
index 363a2ef6cd..59a5f478a5 100644
--- a/tests/baseline/text/tst_baseline_text.cpp
+++ b/tests/baseline/text/tst_baseline_text.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qbaselinetest.h>
#include <qwidgetbaselinetest.h>
@@ -42,6 +17,7 @@ public:
private slots:
void tst_render_data();
void tst_render();
+ void tst_differentScriptsBackgrounds();
private:
QDir htmlDir;
@@ -73,7 +49,7 @@ void tst_Text::loadTestFiles()
for (const auto &htmlFile : htmlFiles) {
QFileInfo fileInfo(htmlFile);
QFile file(htmlFile);
- file.open(QFile::ReadOnly);
+ QVERIFY(file.open(QFile::ReadOnly));
QString html = QString::fromUtf8(file.readAll());
QBaselineTest::newRow(fileInfo.baseName().toUtf8()) << html;
}
@@ -106,6 +82,26 @@ void tst_Text::tst_render()
QBASELINE_TEST(image);
}
+void tst_Text::tst_differentScriptsBackgrounds()
+{
+ QTextDocument textDocument;
+ textDocument.setPageSize(QSizeF(800, 600));
+ textDocument.setHtml(QString::fromUtf8("<i><font style=\"font-size:72px\"><font style=\"background:#FFFF00\">イ雨エ</font></font></i>"));
+
+ QImage image(800, 600, QImage::Format_ARGB32);
+ image.fill(Qt::white);
+
+ {
+ QPainter painter(&image);
+
+ QAbstractTextDocumentLayout::PaintContext context;
+ context.palette.setColor(QPalette::Text, Qt::black);
+ textDocument.documentLayout()->draw(&painter, context);
+ }
+
+ QBASELINE_CHECK(image, "tst_differentScriptsBackgrounds");
+}
+
#define main _realmain
QTEST_MAIN(tst_Text)
@@ -113,7 +109,8 @@ QTEST_MAIN(tst_Text)
int main(int argc, char *argv[])
{
- qSetGlobalQHashSeed(0); // Avoid rendering variations caused by QHash randomization
+ // Avoid rendering variations caused by QHash randomization
+ QHashSeed::setDeterministicGlobalSeed();
QBaselineTest::handleCmdLineArgs(&argc, &argv);
return _realmain(argc, argv);
diff --git a/tests/baseline/widgets/CMakeLists.txt b/tests/baseline/widgets/CMakeLists.txt
index 124e67785f..07938f69b4 100644
--- a/tests/baseline/widgets/CMakeLists.txt
+++ b/tests/baseline/widgets/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
qt_internal_add_test(tst_baseline_widgets
SOURCES
../shared/baselineprotocol.cpp ../shared/baselineprotocol.h ../shared/lookup3.cpp
@@ -6,8 +9,9 @@ qt_internal_add_test(tst_baseline_widgets
tst_baseline_widgets.cpp
INCLUDE_DIRECTORIES
../shared
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::Gui
Qt::Widgets
+ Qt::WidgetsPrivate
Qt::Network
)
diff --git a/tests/baseline/widgets/tst_baseline_widgets.cpp b/tests/baseline/widgets/tst_baseline_widgets.cpp
index d49e9b494f..8a763eb8fa 100644
--- a/tests/baseline/widgets/tst_baseline_widgets.cpp
+++ b/tests/baseline/widgets/tst_baseline_widgets.cpp
@@ -1,30 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qbaselinetest.h>
#include <qwidgetbaselinetest.h>
@@ -45,12 +20,26 @@ private slots:
void tst_QPushButton_data();
void tst_QPushButton();
+ void tst_QPushButtonSquare();
+
void tst_QProgressBar_data();
void tst_QProgressBar();
void tst_QSpinBox_data();
void tst_QSpinBox();
+ void tst_QDoubleSpinBox_data();
+ void tst_QDoubleSpinBox();
+
+ void tst_QDateTimeEdit_data();
+ void tst_QDateTimeEdit();
+
+ void tst_QTimeEdit_data();
+ void tst_QTimeEdit();
+
+ void tst_QDateEdit_data();
+ void tst_QDateEdit();
+
void tst_QDial_data();
void tst_QDial();
@@ -65,6 +54,46 @@ private slots:
void tst_QTabBar_data();
void tst_QTabBar();
+
+ void tst_QTabWidget_data();
+ void tst_QTabWidget();
+
+ void tst_QListView_data();
+ void tst_QListView();
+
+ void tst_QTableView_data();
+ void tst_QTableView();
+
+ void tst_QTreeView_data();
+ void tst_QTreeView();
+
+ void tst_QLineEdit_data();
+ void tst_QLineEdit();
+
+ void tst_QMenu_data();
+ void tst_QMenu();
+
+ void tst_QCombobox_data();
+ void tst_QCombobox();
+
+ void tst_QCommandLinkButton_data();
+ void tst_QCommandLinkButton();
+
+ void tst_QLCDNumber_data();
+ void tst_QLCDNumber();
+
+private:
+
+ // Abstract SpinBox test for QSpinBox, QDoubleSpinBox, QDateTimeEdit, QDateEdit, QTimeEdit
+ void tst_SpinBox_data();
+ void tst_SpinBox(QAbstractSpinBox* spinBox);
+
+ // 78 standard icons from 6.3
+ const int numberStandardIcons = 78;
+
+ // recursive methods for QTreeView population
+ void tst_QTreeView_populateTree(QStandardItem* node, int height, int itemsPerNode, bool hasIcon);
+ QStandardItem* tst_QTreeView_populateItem(int height, int number, bool hasIcon);
};
void tst_Widgets::tst_QSlider_data()
@@ -158,6 +187,29 @@ void tst_Widgets::tst_QPushButton()
testButton->setDown(false);
}
+void tst_Widgets::tst_QPushButtonSquare()
+{
+ QVBoxLayout layout;
+
+ QPushButton button(testWindow());
+ button.setText(QLatin1String("Square"));
+ const auto sizeHint = button.sizeHint().width();
+ // Depending on the current QStyle, this may result in
+ // a different button look - on macOS it will look as
+ // a toolbutton:
+ button.setFixedSize(sizeHint, sizeHint);
+
+ layout.addWidget(&button);
+ testWindow()->setLayout(&layout);
+
+ takeStandardSnapshots();
+
+ button.setCheckable(true);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "square_unchecked");
+ button.setChecked(true);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "square_checked");
+}
+
void tst_Widgets::tst_QProgressBar_data()
{
QTest::addColumn<Qt::Orientation>("orientation");
@@ -195,38 +247,126 @@ void tst_Widgets::tst_QProgressBar()
takeStandardSnapshots();
}
-void tst_Widgets::tst_QSpinBox_data()
+void tst_Widgets::tst_SpinBox_data()
{
QTest::addColumn<QAbstractSpinBox::ButtonSymbols>("buttons");
- QTest::addRow("NoButtons") << QSpinBox::NoButtons;
- QTest::addRow("UpDownArrows") << QSpinBox::UpDownArrows;
- QTest::addRow("PlusMinus") << QSpinBox::PlusMinus;
+ QTest::addRow("NoButtons") << QAbstractSpinBox::NoButtons;
+ QTest::addRow("UpDownArrows") << QAbstractSpinBox::UpDownArrows;
+ QTest::addRow("PlusMinus") << QAbstractSpinBox::PlusMinus;
}
-void tst_Widgets::tst_QSpinBox()
+void tst_Widgets::tst_SpinBox(QAbstractSpinBox *spinBox)
{
- QFETCH(const QSpinBox::ButtonSymbols, buttons);
+ QFETCH(const QAbstractSpinBox::ButtonSymbols, buttons);
- QSpinBox *spinBox = new QSpinBox;
spinBox->setButtonSymbols(buttons);
spinBox->setMinimumWidth(200);
- QVBoxLayout *layout = new QVBoxLayout;
- layout->addWidget(spinBox);
-
- testWindow()->setLayout(layout);
+ QVBoxLayout layout;
+ layout.addWidget(spinBox);
+ testWindow()->setLayout(&layout);
takeStandardSnapshots();
- // Left is default alignment:
- QBASELINE_CHECK(takeSnapshot(), "align_left");
-
spinBox->setAlignment(Qt::AlignHCenter);
- QBASELINE_CHECK(takeSnapshot(), "align_center");
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "alignCenter");
spinBox->setAlignment(Qt::AlignRight);
- QBASELINE_CHECK(takeSnapshot(), "align_right");
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "alignRight");
+
+ // Press / release up button
+ QStyleOptionSpinBox styleOption;
+ styleOption.initFrom(spinBox);
+ QPoint clickTarget = spinBox->style()->subControlRect(QStyle::CC_SpinBox,&styleOption,
+ QStyle::SC_SpinBoxUp,spinBox).center();
+
+ QTest::mousePress(spinBox, Qt::LeftButton, Qt::KeyboardModifiers(), clickTarget);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "upPressed");
+ QTest::mouseRelease(spinBox, Qt::LeftButton, Qt::KeyboardModifiers(), clickTarget);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "upReleased");
+
+ // Press / release down button
+ clickTarget = spinBox->style()->subControlRect(QStyle::CC_SpinBox,&styleOption,
+ QStyle::SC_SpinBoxDown,spinBox).center();
+
+ QTest::mousePress(spinBox, Qt::LeftButton, Qt::KeyboardModifiers(), clickTarget);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "downPressed");
+ QTest::mouseRelease(spinBox, Qt::LeftButton, Qt::KeyboardModifiers(), clickTarget);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "downReleased");
+}
+
+void tst_Widgets::tst_QSpinBox_data()
+{
+ tst_SpinBox_data();
+}
+
+void tst_Widgets::tst_QSpinBox()
+{
+ QSpinBox spinBox;
+ tst_SpinBox(&spinBox);
+}
+
+void tst_Widgets::tst_QDoubleSpinBox_data()
+{
+ tst_SpinBox_data();
+}
+
+void tst_Widgets::tst_QDoubleSpinBox()
+{
+ QDoubleSpinBox spinBox;
+ tst_SpinBox(&spinBox);
+}
+
+void tst_Widgets::tst_QDateTimeEdit_data()
+{
+ tst_SpinBox_data();
+}
+
+void tst_Widgets::tst_QDateTimeEdit()
+{
+ QDateTimeEdit edit;
+ tst_SpinBox(&edit);
+
+ // show calendar popup
+ QStyleOptionSpinBox styleOption;
+ styleOption.initFrom(&edit);
+ const QRect buttonUp = edit.style()->subControlRect(QStyle::CC_SpinBox,&styleOption,
+ QStyle::SC_SpinBoxUp,&edit);
+
+ // no rect for popup button => use bottom center of up-button
+ QPoint clickTarget = buttonUp.center();
+ clickTarget.setY(buttonUp.bottomLeft().y());
+ edit.setCalendarPopup(true);
+ QTest::mouseClick(&edit, Qt::LeftButton, Qt::KeyboardModifiers(), clickTarget);
+ QCalendarWidget* calendar = edit.calendarWidget();
+ QVERIFY(calendar);
+ QVBoxLayout layout;
+ layout.addWidget(calendar);
+ testWindow()->setLayout(&layout);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "showCalendar");
+}
+
+void tst_Widgets::tst_QTimeEdit_data()
+{
+ tst_SpinBox_data();
+}
+
+void tst_Widgets::tst_QTimeEdit()
+{
+ QTimeEdit edit;
+ tst_SpinBox(&edit);
+}
+
+void tst_Widgets::tst_QDateEdit_data()
+{
+ tst_SpinBox_data();
+}
+
+void tst_Widgets::tst_QDateEdit()
+{
+ QDateEdit edit;
+ tst_SpinBox(&edit);
}
void tst_Widgets::tst_QDial_data()
@@ -287,8 +427,14 @@ void tst_Widgets::tst_QCheckbox()
QFETCH(bool, hasIcon);
QFETCH(bool, isTriState);
+ class CheckBox : public QCheckBox
+ {
+ public:
+ using QCheckBox::initStyleOption;
+ };
+
QBoxLayout layout(QBoxLayout::TopToBottom);
- QCheckBox box;
+ CheckBox box;
box.setTristate(isTriState);
if (!text.isEmpty())
@@ -301,10 +447,11 @@ void tst_Widgets::tst_QCheckbox()
testWindow()->setLayout(&layout);
takeStandardSnapshots();
- do
- {
+ do {
const Qt::CheckState checkState = box.checkState();
- const QPoint clickTarget = box.rect().center();
+ QStyleOptionButton styleOption;
+ box.initStyleOption(&styleOption);
+ const QPoint clickTarget = box.style()->subElementRect(QStyle::SE_CheckBoxClickRect, &styleOption, &box).center();
const std::array titles = {"unChecked", "partiallyChecked", "checked"};
const QString snapShotTitle = titles[checkState];
@@ -337,7 +484,14 @@ void tst_Widgets::tst_QRadioButton()
QFETCH(QString,text);
QFETCH(bool,hasIcon);
- QRadioButton button1(testWindow());
+ class RadioButton : public QRadioButton
+ {
+ public:
+ using QRadioButton::QRadioButton;
+ using QRadioButton::initStyleOption;
+ };
+
+ RadioButton button1(testWindow());
if (!text.isEmpty())
button1.setText(text);
@@ -347,7 +501,7 @@ void tst_Widgets::tst_QRadioButton()
button1.setChecked(false);
- QRadioButton button2(testWindow());
+ RadioButton button2(testWindow());
if (!text.isEmpty())
button2.setText(text);
@@ -364,7 +518,10 @@ void tst_Widgets::tst_QRadioButton()
testWindow()->setLayout(&box);
takeStandardSnapshots();
- const QPoint clickTarget = button1.rect().center();
+ QStyleOptionButton styleOption;
+ button1.initStyleOption(&styleOption);
+ const QPoint clickTarget = button1.style()->subElementRect(QStyle::SE_RadioButtonClickRect, &styleOption, &button1).center();
+
QTest::mousePress(&button1,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0);
QVERIFY(button1.isDown());
QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressUnchecked");
@@ -459,13 +616,14 @@ void tst_Widgets::tst_QTabBar_data()
QTest::addColumn<QTabBar::Shape>("shape");
QTest::addColumn<int>("numberTabs");
QTest::addColumn<int>("fixedWidth");
+ QTest::addColumn<bool>("isClosable");
// fixedWidth <0 will be interpreted as variable width
- QTest::newRow("RoundedNorth_3_variableWidth") << QTabBar::RoundedNorth << 3 << -1;
- QTest::newRow("RoundedEast_3_variableWidth") << QTabBar::RoundedEast << 3 << -1;
- QTest::newRow("RoundedWest_3_variableWidth") << QTabBar::RoundedWest << 3 << -1;
- QTest::newRow("RoundedSouth_3_variableWidth") << QTabBar::RoundedSouth << 3 << -1;
- QTest::newRow("RoundedNorth_20_fixedWidth") << QTabBar::RoundedNorth << 20 << 250;
+ QTest::newRow("RoundedNorth_3_variableWidth") << QTabBar::RoundedNorth << 3 << -1 << false;
+ QTest::newRow("RoundedEast_3_variableWidth") << QTabBar::RoundedEast << 3 << -1 << false;
+ QTest::newRow("RoundedWest_3_variableWidth") << QTabBar::RoundedWest << 3 << -1 << false;
+ QTest::newRow("RoundedSouth_3_variableWidth") << QTabBar::RoundedSouth << 3 << -1 << false;
+ QTest::newRow("RoundedNorth_20_fixedWidth") << QTabBar::RoundedNorth << 20 << 250 << true;
}
void tst_Widgets::tst_QTabBar()
@@ -473,9 +631,11 @@ void tst_Widgets::tst_QTabBar()
QFETCH(QTabBar::Shape, shape);
QFETCH(int, numberTabs);
QFETCH(int, fixedWidth);
+ QFETCH(bool, isClosable);
QTabBar bar (testWindow());
bar.setShape(shape);
+ bar.setTabsClosable(isClosable);
if (fixedWidth > 0)
bar.setFixedWidth(fixedWidth);
@@ -505,6 +665,614 @@ void tst_Widgets::tst_QTabBar()
QTest::mouseRelease(&bar,Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0);
QVERIFY(bar.currentIndex() == 1);
}
+
+ // test press/release on close button
+ if (isClosable) {
+
+ // CloseButton is either left or right
+ QWidget *leftButton = bar.tabButton(bar.currentIndex(),QTabBar::ButtonPosition::LeftSide);
+ QWidget *rightButton = bar.tabButton(bar.currentIndex(),QTabBar::ButtonPosition::RightSide);
+ QAbstractButton *button = qobject_cast<QAbstractButton*>(leftButton);
+ if (button == nullptr)
+ button = qobject_cast<QAbstractButton*>(rightButton);
+
+ if (button != nullptr) {
+ clickTarget = button->rect().center();
+ QTest::mousePress(button,Qt::MouseButton::LeftButton,
+ Qt::KeyboardModifiers(), clickTarget,0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressCloseFirstTab");
+ QTest::mouseRelease(button,Qt::MouseButton::LeftButton,
+ Qt::KeyboardModifiers(), clickTarget,0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "releaseCloseFirstTab");
+ }
+ }
+}
+
+void tst_Widgets::tst_QTabWidget_data()
+{
+ QTest::addColumn<QTabWidget::TabPosition>("tabPosition");
+ QTest::addColumn<int>("numberTabs");
+ QTest::addColumn<QString>("tabText");
+ QTest::addColumn<int>("fixedWidth");
+ QTest::addColumn<bool>("isClosable");
+ QTest::addColumn<bool>("isDocumentMode");
+
+ // fixedWidth <0 will be interpreted as variable width
+ QTest::newRow("North_3_variableWidthDocMode") << QTabWidget::North << 3 << "This is a tab text" << -1 << false << true;
+ QTest::newRow("East_3_variableWidth") << QTabWidget::East << 3 << "This is a tab text" << -1 << false << false;
+ QTest::newRow("West_3_variableWidthDocMode") << QTabWidget::West << 3 << "This is a tab text" << -1 << false << true;
+ QTest::newRow("South_3_variableWidth") << QTabWidget::South << 3 << "This is a tab text" << -1 << true << false;
+ QTest::newRow("North_20_fixedWidthDocMode") << QTabWidget::North << 20
+ << "This is a very long text to actually force wrapping!" << 100 << true << true;
+ QTest::newRow("South_20_variableWidth") << QTabWidget::South << 20
+ << "This is a very long text to actually force wrapping!" << -1 << false << false;
+}
+
+void tst_Widgets::tst_QTabWidget()
+{
+ QFETCH(QTabWidget::TabPosition, tabPosition);
+ QFETCH(int, numberTabs);
+ QFETCH(QString, tabText);
+ QFETCH(int, fixedWidth);
+ QFETCH(bool, isClosable);
+ QFETCH(bool, isDocumentMode);
+
+ QTabWidget tabWidget (testWindow());
+ if (fixedWidth > 0)
+ tabWidget.setFixedWidth(fixedWidth);
+ tabWidget.setTabPosition(tabPosition);
+ tabWidget.setTabsClosable(isClosable);
+ tabWidget.setDocumentMode(isDocumentMode);
+
+ for (int i = 0; i < numberTabs; ++i) {
+ QLabel *tabLabel = new QLabel("Tab number " + QString::number(i) + "\n" + tabText, &tabWidget);
+ QBoxLayout *tabBox = new QBoxLayout(QBoxLayout::TopToBottom,&tabWidget);
+ tabBox->addWidget(tabLabel);
+ tabWidget.insertTab(i,tabLabel,"Tab_" + QString::number(i));
+ tabWidget.setCurrentIndex(i);
+ tabWidget.currentWidget()->setLayout(tabBox);
+ }
+
+ tabWidget.setCurrentIndex(0);
+ QBoxLayout box(QBoxLayout::LeftToRight, testWindow());
+ box.addWidget(&tabWidget);
+ testWindow()->setLayout(&box);
+ takeStandardSnapshots();
+
+ // press/release on second tab if it exists
+ if (numberTabs > 1) {
+ const QPoint clickTarget = tabWidget.tabBar()->tabRect(1).center();
+ QTest::mousePress(tabWidget.tabBar(),Qt::MouseButton::LeftButton,Qt::KeyboardModifiers(), clickTarget,0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressSecondTab");
+ QTest::mouseRelease(tabWidget.tabBar(),Qt::MouseButton::LeftButton, Qt::KeyboardModifiers(), clickTarget,0);
+ QVERIFY(tabWidget.currentIndex() == 1);
+ }
+
+ // test press/release on close button
+ if (isClosable) {
+
+ // CloseButton is either left or right
+ QWidget *leftButton = tabWidget.tabBar()->tabButton(tabWidget.currentIndex(),QTabBar::ButtonPosition::LeftSide);
+ QWidget *rightButton = tabWidget.tabBar()->tabButton(tabWidget.currentIndex(),QTabBar::ButtonPosition::RightSide);
+ QAbstractButton *button = qobject_cast<QAbstractButton*>(leftButton);
+ if (button == nullptr)
+ button = qobject_cast<QAbstractButton*>(rightButton);
+
+ if (button != nullptr) {
+ const QPoint clickTarget = button->rect().center();
+ QTest::mousePress(button,Qt::MouseButton::LeftButton,
+ Qt::KeyboardModifiers(), clickTarget,0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "pressCloseTab");
+ QTest::mouseRelease(button,Qt::MouseButton::LeftButton,
+ Qt::KeyboardModifiers(), clickTarget,0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "releaseCloseTab");
+ }
+ }
+}
+
+void tst_Widgets::tst_QListView_data()
+{
+ QTest::addColumn<QListView::ViewMode>("viewMode");
+ QTest::addColumn<bool>("isWrapping");
+ QTest::addColumn<bool>("hasWordWrap");
+ QTest::addColumn<int>("numberItems");
+ QTest::addColumn<QSize>("fixedSize");
+
+
+ // QSize() will be interpreted as variable size
+ QTest::newRow("ListModeWrappingNoWordWrapFixed_10") <<
+ QListView::ListMode << true << false << 10 << QSize(100, 500);
+ QTest::newRow("ListModeNoWrappingNoWordWrapVariable_20") <<
+ QListView::ListMode << false << true << 20 << QSize();
+ QTest::newRow("ListModeNoWrappingWordWrapVariable_30") <<
+ QListView::ListMode << false << true << 30 << QSize();
+ QTest::newRow("IconModeNoWrappingNoWordWrapFixed_10") <<
+ QListView::IconMode << false << false << 10 << QSize(100, 500);
+ QTest::newRow("IconModeWrappingNoWordWrapVariable_20") <<
+ QListView::IconMode << true << false << 20 << QSize();
+ QTest::newRow("IconModeWrappingWordWrapVariable_30") <<
+ QListView::IconMode << true << true << 30 << QSize(100, 500);
+}
+void tst_Widgets::tst_QListView()
+{
+ QFETCH(QListView::ViewMode,viewMode);
+ QFETCH(bool,isWrapping);
+ QFETCH(bool,hasWordWrap);
+ QFETCH(int,numberItems);
+ QFETCH(QSize,fixedSize);
+
+ QListView listView;
+ listView.setViewMode(viewMode);
+ listView.setWrapping(isWrapping);
+ listView.setWordWrap(hasWordWrap);
+ if (fixedSize.isValid())
+ listView.setFixedSize(fixedSize);
+
+ QStandardItemModel model(0,1,testWindow());
+
+ // Populate model, add standard icons if required
+ const QString itemText = hasWordWrap ? "This is a long text for word wrapping Item_"
+ : "ListItem_";
+ int icon = 0;
+ for (int i = 0; i < numberItems; ++i) {
+ QStandardItem *item;
+ if (viewMode == QListView::IconMode) {
+ item = new QStandardItem(QApplication::style()->standardIcon
+ (static_cast<QStyle::StandardPixmap>(icon)), itemText + QString::number(i));
+ icon = (icon + 1) % numberStandardIcons;
+ } else {
+ item = new QStandardItem(itemText + QString::number(i));
+ }
+ model.appendRow(item);
+ }
+
+ listView.setModel(&model);
+ QBoxLayout layout(QBoxLayout::LeftToRight, testWindow());
+ layout.addWidget(&listView);
+ testWindow()->setLayout(&layout);
+ takeStandardSnapshots();
+
+ // click on first item
+ QPoint clickTarget = listView.visualRect(model.index(0,0)).center();
+ QTest::mouseClick(listView.viewport(),Qt::MouseButton::LeftButton,
+ Qt::KeyboardModifiers(), clickTarget,0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickFirstItem");
+
+ // click on scond item
+ if (numberItems > 1) {
+ clickTarget = listView.visualRect(model.index(1,0)).center();
+ QTest::mouseClick(listView.viewport(),Qt::MouseButton::LeftButton,
+ Qt::KeyboardModifiers(), clickTarget,0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickSecondItem");
+ }
+
+ // Hide first row
+ listView.setRowHidden(0,true);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "hideFirstItem");
+}
+
+void tst_Widgets::tst_QTableView_data()
+{
+ QTest::addColumn<bool>("hasHeader");
+ QTest::addColumn<bool>("hasRowNumbers");
+ QTest::addColumn<bool>("hasWordWrap");
+ QTest::addColumn<int>("numberRows");
+ QTest::addColumn<int>("numberColumns");
+ QTest::addColumn<int>("iconColumn");
+ QTest::addColumn<QSize>("fixedSize");
+
+ // QSize() => variable size; iconColumn -1 => no icon
+ QTest::newRow("HeaderRowNumWordWrapFixed_10") << true << true << true << 10 << 3 << -1 << QSize(500, 100);
+ QTest::newRow("HeaderVariable_20") << true << false << false << 20 << 4 << 1 << QSize();
+ QTest::newRow("HeaderFixed_20") << true << false << false << 20 << 4 << 1 << QSize(500, 700);
+}
+
+void tst_Widgets::tst_QTableView()
+{
+ QFETCH(bool, hasHeader);
+ QFETCH(bool, hasRowNumbers);
+ QFETCH(bool, hasWordWrap);
+ QFETCH(int, numberRows);
+ QFETCH(int, numberColumns);
+ QFETCH(int, iconColumn);
+ QFETCH(QSize, fixedSize);
+
+ // Populate model
+ int icon = 0;
+ QStandardItemModel model(numberRows, numberColumns, testWindow());
+
+ if (hasHeader) {
+ for (int i = 0; i < numberColumns; ++i)
+ model.setHorizontalHeaderItem(i, new QStandardItem("Header_" + QString::number(i)));
+ }
+
+ const QString wrap = hasWordWrap ? "\n long text to wrap words" : "" ;
+ for (int row = 0; row < numberRows; ++row) {
+ for (int column = 0; column < numberColumns; ++column) {
+ QStandardItem *item;
+ const QString itemText = QString::number(row) + "/" + QString::number(column) + wrap;
+ if (iconColumn == column) {
+ item = new QStandardItem(QApplication::style()->standardIcon
+ (static_cast<QStyle::StandardPixmap>(icon)),itemText);
+
+ icon = (icon + 1) % numberStandardIcons;
+ } else {
+ item = new QStandardItem(itemText);
+ }
+ model.setItem(row,column,item);
+ }
+ if (hasRowNumbers)
+ model.setVerticalHeaderItem(row, new QStandardItem(QString::number(row)));
+ }
+
+ QTableView tableView(testWindow());
+ tableView.setWordWrap(hasWordWrap);
+ if (fixedSize.isValid())
+ tableView.setFixedSize(fixedSize);
+
+ QBoxLayout layout(QBoxLayout::LeftToRight, testWindow());
+ tableView.setModel(&model);
+ layout.addWidget(&tableView);
+
+ takeStandardSnapshots();
+
+ // Hide grid
+ tableView.setShowGrid(false);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "hideGrid");
+ tableView.setShowGrid(true);
+
+ // click item 0,0
+ QPoint clickTarget = tableView.visualRect(model.index(0,0)).center();
+ QTest::mouseClick(tableView.viewport(),Qt::MouseButton::LeftButton,
+ Qt::KeyboardModifiers(), clickTarget,0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickFirstItem");
+
+ // click item 0,1 if it exists
+ if (numberColumns > 1) {
+ clickTarget = tableView.visualRect(model.index(0,1)).center();
+ QTest::mouseClick(tableView.viewport(),Qt::MouseButton::LeftButton,
+ Qt::KeyboardModifiers(), clickTarget,0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickSecondItem");
+ }
+
+ tableView.clearSelection();
+
+ // Hide first row and column
+ tableView.setRowHidden(0, true);
+ tableView.setColumnHidden(0, true);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "hideFirstRowColumn");
+ tableView.setRowHidden(0, false);
+ tableView.setColumnHidden(0, false);
+
+ // Select first row
+ tableView.selectRow(0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "selectFirstRow");
+
+ // Select first column
+ tableView.selectColumn(0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "selectFirstColumn");
+}
+
+void tst_Widgets::tst_QTreeView_data()
+{
+ QTest::addColumn<bool>("showHeader");
+ QTest::addColumn<bool>("hasIcons");
+ QTest::addColumn<bool>("alternatingRowColors");
+ QTest::addColumn<QSize>("fixedSize");
+ QTest::addColumn<int>("treeHeight");
+ QTest::addColumn<int>("itemsPerNode");
+
+ // QSize() => variable size
+ QTest::newRow("HeaderIcons_4_3") << true << true << false << QSize() << 3 << 2;
+ QTest::newRow("NoHeaderNoIcons_4_4") << false << false << false << QSize(100, 350) << 3 << 2;
+ QTest::newRow("AlternatingRows") << true << true << true << QSize() << 3 << 2;
+}
+
+void tst_Widgets::tst_QTreeView()
+{
+ QFETCH(bool, showHeader);
+ QFETCH(bool, hasIcons);
+ QFETCH(bool, alternatingRowColors);
+ QFETCH(QSize, fixedSize);
+ QFETCH(int, treeHeight);
+ QFETCH(int, itemsPerNode);
+ QVERIFY(treeHeight > 0 && itemsPerNode > 0);
+
+ QTreeView treeView(testWindow());
+ fixedSize.isValid() ? treeView.setFixedSize(fixedSize)
+ : treeView.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
+
+ QStandardItemModel model(&treeView);
+ showHeader ? model.setHorizontalHeaderItem(0, new QStandardItem("TreeHeader"))
+ : treeView.setHeaderHidden(true);
+
+ treeView.setAlternatingRowColors(alternatingRowColors);
+
+ // Populate tree model
+ for (int i = 0; i < itemsPerNode; ++i) {
+ QStandardItem* root = tst_QTreeView_populateItem(treeHeight, i, hasIcons);
+ tst_QTreeView_populateTree(root,treeHeight - 1,itemsPerNode, hasIcons);
+ model.appendRow(root);
+ }
+
+ treeView.setModel(&model);
+ QBoxLayout layout(QBoxLayout::LeftToRight, testWindow());
+ layout.addWidget(&treeView);
+ testWindow()->setLayout(&layout);
+
+ treeView.expandAll();
+ treeView.resizeColumnToContents(0);
+ takeStandardSnapshots();
+
+ // Partly expand if possible
+ if (treeHeight > 1) {
+ treeView.expandToDepth(1);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "partlyExpanded");
+ }
+
+ // Click on first node
+ QPoint clickTarget = treeView.visualRect(model.index(0, 0)).center();
+ QTest::mouseClick(treeView.viewport(),Qt::MouseButton::LeftButton,
+ Qt::KeyboardModifiers(), clickTarget, 0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickFirstNode");
+
+ // Hide first row
+ treeView.setRowHidden(0, model.index(0, 0), true);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "hideFirstRow");
+ treeView.setRowHidden(0, model.index(0, 0), false);
+
+ // Click on second row if it exists
+ if (itemsPerNode > 1) {
+ clickTarget = treeView.visualRect(model.index(1, 0)).center();
+ QTest::mouseClick(treeView.viewport(), Qt::MouseButton::LeftButton,
+ Qt::KeyboardModifiers(), clickTarget, 0);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "clickSecondNode");
+ }
+}
+
+void tst_Widgets::tst_QTreeView_populateTree(QStandardItem* node, int height, int itemsPerNode, bool hasIcon)
+{
+ QList<QStandardItem*> items;
+ for (int i = 0; i < itemsPerNode; ++i) {
+ if (height == 0) {
+ items.append(tst_QTreeView_populateItem(height, i, hasIcon));
+ } else {
+ QStandardItem* item = tst_QTreeView_populateItem(height, i, hasIcon);
+ tst_QTreeView_populateTree(item, height - 1, itemsPerNode, hasIcon);
+ items.append(item);
+ }
+ }
+ return node->appendColumn(items);
+}
+
+QStandardItem* tst_Widgets::tst_QTreeView_populateItem(int height, int number, bool hasIcon)
+{
+ static int icon = 0;
+ static int itemCount = 0;
+
+ QStandardItem* item;
+ const QString itemText = QString("%1/%2/%3").arg(height).arg(number).arg(itemCount);
+ ++itemCount;
+
+ if (hasIcon) {
+ item = new QStandardItem(QApplication::style()->standardIcon
+ (static_cast<QStyle::StandardPixmap>(icon)), itemText);
+
+ icon = (icon + 1) % numberStandardIcons;
+ } else {
+ item = new QStandardItem(itemText);
+ }
+ return item;
+}
+
+void tst_Widgets::tst_QLineEdit_data()
+{
+ QTest::addColumn<bool>("hasFrame");
+ QTest::addColumn<QLineEdit::EchoMode>("echoMode");
+ QTest::addColumn<QString>("placeHolderText");
+ QTest::addColumn<QString>("text");
+
+ QTest::newRow("framePassword") << true << QLineEdit::Password << "password" << "secret";
+ QTest::newRow("noFrameCleartext") << false << QLineEdit::Normal << "text" << "this is a text";
+}
+
+void tst_Widgets::tst_QLineEdit()
+{
+ QFETCH(const bool, hasFrame);
+ QFETCH(const QLineEdit::EchoMode, echoMode);
+ QFETCH(const QString, placeHolderText);
+ QFETCH(const QString, text);
+
+ QLineEdit lineEdit(testWindow());
+ lineEdit.setFrame(hasFrame);
+ lineEdit.setEchoMode(echoMode);
+ lineEdit.setPlaceholderText(placeHolderText);
+
+ QHBoxLayout layout;
+ layout.addWidget(&lineEdit);
+ testWindow()->setLayout(&layout);
+ takeStandardSnapshots();
+
+ lineEdit.setText(text);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "setText");
+
+ lineEdit.setAlignment(Qt::AlignRight);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "alignedRight");
+
+ lineEdit.setAlignment(Qt::AlignCenter);
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "alignedCenter");
+
+ lineEdit.setSelection(0,text.size());
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "textSelected");
+}
+
+void tst_Widgets::tst_QMenu_data()
+{
+ QTest::addColumn<QStringList>("actions");
+
+ const QStringList menu1 = {"Text", "", "TextAndIcon", "", "SubMenu", "", "Checked"};
+ QTest::newRow("showMenuPopup") << menu1;
+}
+
+void tst_Widgets::tst_QMenu()
+{
+ QFETCH(const QStringList, actions);
+
+ testWindow()->resize(300, 200);
+
+ QBoxLayout layout(QBoxLayout::TopToBottom);
+ QMenu menu1;
+
+ for (const auto& menuItem : actions) {
+ if (!menuItem.isEmpty()) {
+ if (menuItem == "Text") {
+ menu1.addAction(QString("MenuItem"));
+ menu1.addAction(QString(""));
+ } else if (menuItem == "TextAndIcon") {
+ // Using pixmap icon
+ QPixmap pix(10, 10);
+ pix.fill(Qt::green);
+ menu1.addAction(QIcon(pix), QString("MenuWithIcon"));
+ menu1.addAction(QIcon(), QString("MenuNoIcon"));
+ } else if (menuItem == "SubMenu") {
+ QMenu* submenu = menu1.addMenu(QString("&Submenu1"));
+ submenu->addAction("SubMenuA");
+ submenu->addAction("SubMenuB");
+ } else if (menuItem == "Checked") {
+ auto checked = menu1.addAction(QString("MenuChecked"));
+ checked->setCheckable(true);
+ checked->setChecked(true);
+ auto notChecked = menu1.addAction(QString("MenuNotChecked"));
+ notChecked->setCheckable(true);
+ notChecked->setChecked(false);
+ }
+ } else {
+ menu1.addSeparator();
+ }
+ }
+
+ layout.addWidget(&menu1);
+ testWindow()->setLayout(&layout);
+
+ testWindow()->show();
+ QVERIFY(QTest::qWaitForWindowExposed(testWindow()));
+ QRect testWindowRect(testWindow()->geometry());
+ // There can be rounded corners in the window and this leads to test
+ // case to be fuzzy. Adjust window rectangle that need to be captured
+ int adjustPixel = menu1.geometry().left();
+ testWindowRect.adjust(adjustPixel, adjustPixel, -adjustPixel, -adjustPixel);
+ QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "showitems");
+
+ // Normal menu item with text
+ QTest::keyClick(&menu1, Qt::Key_Down);
+ QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenutext");
+ QTest::keyClick(&menu1, Qt::Key_Down);
+ QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenunotext");
+
+ // Menu with icon and text
+ QTest::keyClick(&menu1, Qt::Key_Down);
+ QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenuwithicon");
+ QTest::keyClick(&menu1, Qt::Key_Down);
+ QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenuwithnullicon");
+
+ // Sub-menu items
+ QTest::keyClick(&menu1, Qt::Key_Down);
+ QTest::keyClick(&menu1, Qt::Key_Right);
+ QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectsubmenu");
+ QTest::keyClick(&menu1, Qt::Key_Left);
+
+ // Checked menu
+ QTest::keyClick(&menu1, Qt::Key_Down);
+ QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenuchecked");
+ QTest::keyClick(&menu1, Qt::Key_Down);
+ QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindowRect), "selectmenunotchecked");
+}
+
+void tst_Widgets::tst_QCombobox_data()
+{
+ QTest::addColumn<bool>("hasFrame");
+ QTest::addColumn<bool>("isEditable");
+
+ QTest::addRow("frameNonEditable") << true << false;
+ QTest::addRow("frameEditable") << true << true;
+ QTest::addRow("noFrameNonEditable") << false << false;
+ QTest::addRow("noFrameEditable") << false << true;
+}
+
+void tst_Widgets::tst_QCombobox()
+{
+ QFETCH(const bool, hasFrame);
+ QFETCH(const bool, isEditable);
+
+ testWindow()->resize(300, 300);
+
+ QScopedPointer<QComboBox> combobox(new QComboBox(testWindow()));
+ QStringList items;
+ items << tr("Item1") << tr("Item2") << tr("Item3");
+ QStringListModel* itemModel = new QStringListModel(items, this);
+ combobox->setModel(itemModel);
+ combobox->setFrame(hasFrame);
+ combobox->setEditable(isEditable);
+
+ QHBoxLayout layout;
+ layout.addWidget(combobox.get());
+ testWindow()->setLayout(&layout);
+ takeStandardSnapshots();
+
+ QTest::keyClick(combobox.get(), Qt::Key_Down, Qt::AltModifier);
+ QBASELINE_CHECK_DEFERRED(takeScreenSnapshot(testWindow()->geometry()), "combobox");
+}
+
+void tst_Widgets::tst_QCommandLinkButton_data()
+{
+ QTest::addColumn<bool>("flat");
+ QTest::addColumn<QString>("description");
+
+ QTest::addRow("flatDescription") << true << QString("Command button very specific to windows vista");
+ QTest::addRow("flatNoDescription") << true << QString("");
+ QTest::addRow("noFlatNoDescription") << false << QString("");
+}
+
+void tst_Widgets::tst_QCommandLinkButton()
+{
+ QFETCH(const bool, flat);
+ QFETCH(const QString, description);
+
+ QScopedPointer<QCommandLinkButton> commandLink(new QCommandLinkButton(QString("CommandLink"), description, testWindow()));
+ commandLink->setFlat(flat);
+ commandLink->setDescription(description);
+
+ QHBoxLayout layout;
+ layout.addWidget(commandLink.get());
+ testWindow()->setLayout(&layout);
+ takeStandardSnapshots();
+}
+
+void tst_Widgets::tst_QLCDNumber_data()
+{
+ QTest::addColumn<int>("segmentstyle");
+
+ QTest::addRow("outline") << 0;
+ QTest::addRow("filled") << 1;
+ QTest::addRow("flat") << 2;
+}
+
+void tst_Widgets::tst_QLCDNumber()
+{
+ QFETCH(const int, segmentstyle);
+
+ testWindow()->resize(100, 100);
+
+ QScopedPointer<QLCDNumber> lcdNumber(new QLCDNumber(99, testWindow()));
+ lcdNumber->setHexMode();
+ lcdNumber->setSegmentStyle(static_cast<QLCDNumber::SegmentStyle>(segmentstyle));
+
+
+ QHBoxLayout layout;
+ layout.addWidget(lcdNumber.get());
+ testWindow()->setLayout(&layout);
+
+ QBASELINE_CHECK_DEFERRED(takeSnapshot(), "lcdnumber");
}
#define main _realmain
@@ -513,7 +1281,8 @@ QTEST_MAIN(tst_Widgets)
int main(int argc, char *argv[])
{
- qSetGlobalQHashSeed(0); // Avoid rendering variations caused by QHash randomization
+ // Avoid rendering variations caused by QHash randomization
+ QHashSeed::setDeterministicGlobalSeed();
QBaselineTest::handleCmdLineArgs(&argc, &argv);
return _realmain(argc, argv);