diff options
Diffstat (limited to 'tests/baseline')
22 files changed, 661 insertions, 79 deletions
diff --git a/tests/baseline/CMakeLists.txt b/tests/baseline/CMakeLists.txt index a5a5084e87..037ffd9e0e 100644 --- a/tests/baseline/CMakeLists.txt +++ b/tests/baseline/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -if(TARGET Qt::Network) +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 1c2100b596..72e737d227 100644 --- a/tests/baseline/painting/CMakeLists.txt +++ b/tests/baseline/painting/CMakeLists.txt @@ -17,6 +17,8 @@ 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 LIBRARIES 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/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 f9738b61e8..f486b33430 100644 --- a/tests/baseline/painting/tst_baseline_painting.cpp +++ b/tests/baseline/painting/tst_baseline_painting.cpp @@ -1,5 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// 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> @@ -52,7 +54,7 @@ private: private slots: void initTestCase(); - void cleanupTestCase() {} + void init(); void testRasterARGB32PM_data(); void testRasterARGB32PM(); @@ -120,7 +122,7 @@ 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)); @@ -131,6 +133,11 @@ void tst_Lancelot::initTestCase() #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() { @@ -416,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 diff --git a/tests/baseline/shared/baselineprotocol.cpp b/tests/baseline/shared/baselineprotocol.cpp index 198057abe6..6a38e71831 100644 --- a/tests/baseline/shared/baselineprotocol.cpp +++ b/tests/baseline/shared/baselineprotocol.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "baselineprotocol.h" #include <QLibraryInfo> #include <QImage> @@ -270,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 4696900d91..598a0cd3af 100644 --- a/tests/baseline/shared/baselineprotocol.h +++ b/tests/baseline/shared/baselineprotocol.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// 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 bb91b3ac06..7964a184ae 100644 --- a/tests/baseline/shared/lookup3.cpp +++ b/tests/baseline/shared/lookup3.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only /* diff --git a/tests/baseline/shared/paintcommands.cpp b/tests/baseline/shared/paintcommands.cpp index 4a3de0168b..2cb3cd3bba 100644 --- a/tests/baseline/shared/paintcommands.cpp +++ b/tests/baseline/shared/paintcommands.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "paintcommands.h" #include <qdir.h> @@ -173,6 +173,7 @@ const char *PaintCommands::imageFormatTable[] = { "RGBx32FPx4", "RGBA32FPx4", "RGBA32FPx4_Premultiplied", + "CMYK32", }; const char *PaintCommands::renderHintTable[] = { @@ -449,10 +450,12 @@ void PaintCommands::staticInit() "^drawGlyphRun\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$", "drawGlyphRun <x> <y> <text> - Will create glyph run using QTextLayout and draw this", "drawGlyphRun 10 10 \"my text\""); +#ifndef QT_NO_TEXTHTMLPARSER DECL_PAINTCOMMAND("drawTextDocument", command_drawTextDocument, "^drawTextDocument\\s+(-?\\w*)\\s+(-?\\w*)\\s+\"(.*)\"$", "drawTextDocument <x> <y> <html>", "drawTextDocument 10 10 \"html\""); +#endif DECL_PAINTCOMMAND("drawTiledPixmap", command_drawTiledPixmap, "^drawTiledPixmap\\s+([\\w.:\\/]*)" "\\s+(-?\\w*)\\s+(-?\\w*)\\s*(-?\\w*)\\s*(-?\\w*)" @@ -469,6 +472,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, @@ -731,8 +748,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); @@ -907,7 +924,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; @@ -925,7 +942,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(')'); @@ -935,10 +952,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); @@ -1389,6 +1406,7 @@ void PaintCommands::command_drawGlyphRun(QRegularExpressionMatch re) m_painter->drawGlyphRun(QPointF(x, y), glyphRun); } +#ifndef QT_NO_TEXTHTMLPARSER void PaintCommands::command_drawTextDocument(QRegularExpressionMatch re) { if (!m_shouldDrawText) @@ -1410,6 +1428,7 @@ void PaintCommands::command_drawTextDocument(QRegularExpressionMatch re) doc.drawContents(m_painter); m_painter->restore(); } +#endif /***************************************************************************************************/ void PaintCommands::command_fillRect(QRegularExpressionMatch re) @@ -1452,6 +1471,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) { diff --git a/tests/baseline/shared/paintcommands.h b/tests/baseline/shared/paintcommands.h index 0d8044fc47..de412e246e 100644 --- a/tests/baseline/shared/paintcommands.h +++ b/tests/baseline/shared/paintcommands.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef PAINTCOMMANDS_H #define PAINTCOMMANDS_H @@ -43,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) @@ -62,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; } @@ -179,10 +179,13 @@ private: void command_drawText(QRegularExpressionMatch re); void command_drawStaticText(QRegularExpressionMatch re); void command_drawGlyphRun(QRegularExpressionMatch re); +#ifndef QT_NO_TEXTHTMLPARSER void command_drawTextDocument(QRegularExpressionMatch re); +#endif 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); @@ -251,8 +254,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; diff --git a/tests/baseline/shared/qbaselinetest.cpp b/tests/baseline/shared/qbaselinetest.cpp index 95da71d9e7..e41b8d5321 100644 --- a/tests/baseline/shared/qbaselinetest.cpp +++ b/tests/baseline/shared/qbaselinetest.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "qbaselinetest.h" #include "baselineprotocol.h" @@ -139,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; @@ -249,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 @@ -259,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; @@ -270,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."; @@ -285,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)) @@ -306,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; @@ -372,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; } @@ -397,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 2d605b0e2b..f120e2bcd8 100644 --- a/tests/baseline/shared/qbaselinetest.h +++ b/tests/baseline/shared/qbaselinetest.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef BASELINETEST_H #define BASELINETEST_H @@ -18,6 +18,7 @@ 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(); } @@ -59,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 1c150bd79f..72a074e268 100644 --- a/tests/baseline/shared/qwidgetbaselinetest.cpp +++ b/tests/baseline/shared/qwidgetbaselinetest.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "qwidgetbaselinetest.h" @@ -77,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(); @@ -91,19 +95,21 @@ void QWidgetBaselineTest::cleanup() { doCleanup(); - delete window; + delete background; + background = nullptr; window = nullptr; } void QWidgetBaselineTest::makeVisible() { Q_ASSERT(window); + background->showMaximized(); window->show(); 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); } /* @@ -117,6 +123,20 @@ QImage QWidgetBaselineTest::takeSnapshot() 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(); +} + /*! Sets standard widget properties on the test window and its children, and uploads snapshots. The widgets are returned in the same state @@ -127,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 9b96ea0a1a..2142217c09 100644 --- a/tests/baseline/shared/qwidgetbaselinetest.h +++ b/tests/baseline/shared/qwidgetbaselinetest.h @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #pragma once @@ -32,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/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/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/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 11c8221443..67a618988b 100644 --- a/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp +++ b/tests/baseline/stylesheet/tst_baseline_stylesheet.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qbaselinetest.h> #include <qwidgetbaselinetest.h> @@ -27,6 +27,9 @@ private slots: void tst_QTreeView_data(); void tst_QTreeView(); + void tst_QHeaderView_data(); + void tst_QHeaderView(); + private: QDir styleSheetDir; }; @@ -63,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; } @@ -160,19 +163,29 @@ void tst_Stylesheet::tst_QTreeView() tw->header()->hide(); layout->addWidget(tw); - for (int i = 0; i < 6; ++i) { + 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 0: - case 3: + case Unchecked: + case Disabled: topLevelItem->setCheckState(0, Qt::Unchecked); break; - case 1: - case 4: + case Checked: + case CheckedDisabled: topLevelItem->setCheckState(0, Qt::Checked); break; - case 2: - case 5: + case Children: + case ChildrenDisabled: topLevelItem->setCheckState(0, Qt::PartiallyChecked); topLevelItem->setExpanded(true); for (int j = 0; j < 2; ++j) { @@ -181,7 +194,7 @@ void tst_Stylesheet::tst_QTreeView() } break; } - topLevelItem->setDisabled(i > 2); + topLevelItem->setDisabled(i >= Disabled); } testWindow()->setLayout(layout); tw->setRootIsDecorated(true); @@ -190,6 +203,25 @@ void tst_Stylesheet::tst_QTreeView() 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 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 0d2c2d47f5..59a5f478a5 100644 --- a/tests/baseline/text/tst_baseline_text.cpp +++ b/tests/baseline/text/tst_baseline_text.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qbaselinetest.h> #include <qwidgetbaselinetest.h> @@ -17,6 +17,7 @@ public: private slots: void tst_render_data(); void tst_render(); + void tst_differentScriptsBackgrounds(); private: QDir htmlDir; @@ -48,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; } @@ -81,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) diff --git a/tests/baseline/widgets/tst_baseline_widgets.cpp b/tests/baseline/widgets/tst_baseline_widgets.cpp index 64b8ea4aba..8a763eb8fa 100644 --- a/tests/baseline/widgets/tst_baseline_widgets.cpp +++ b/tests/baseline/widgets/tst_baseline_widgets.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qbaselinetest.h> #include <qwidgetbaselinetest.h> @@ -70,6 +70,18 @@ private slots: 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 @@ -945,19 +957,22 @@ 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 << QSize() << 3 << 2; - QTest::newRow("NoHeaderNoIcons_4_4") << false << false << QSize(100, 350) << 3 << 2; + 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); @@ -971,6 +986,8 @@ void tst_Widgets::tst_QTreeView() 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); @@ -1085,10 +1102,179 @@ void tst_Widgets::tst_QLineEdit() lineEdit.setAlignment(Qt::AlignCenter); QBASELINE_CHECK_DEFERRED(takeSnapshot(), "alignedCenter"); - lineEdit.setSelection(0,text.length()); + 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 QTEST_MAIN(tst_Widgets) #undef main |