diff options
Diffstat (limited to 'tests/auto/gui/image/qicon/tst_qicon.cpp')
-rw-r--r-- | tests/auto/gui/image/qicon/tst_qicon.cpp | 142 |
1 files changed, 105 insertions, 37 deletions
diff --git a/tests/auto/gui/image/qicon/tst_qicon.cpp b/tests/auto/gui/image/qicon/tst_qicon.cpp index 0cd433ecb1..99b4a0589e 100644 --- a/tests/auto/gui/image/qicon/tst_qicon.cpp +++ b/tests/auto/gui/image/qicon/tst_qicon.cpp @@ -1,37 +1,14 @@ -/**************************************************************************** -** -** 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 <QTest> #include <QImageReader> #include <QBuffer> #include <QStandardPaths> +#include <QPainter> +#if QT_CONFIG(process) #include <QProcess> - +#endif #include <qicon.h> #include <qiconengine.h> @@ -57,12 +34,14 @@ private slots: void detach(); void addFile(); void pixmap(); + void paint(); void availableSizes(); void name(); void streamAvailableSizes_data(); void streamAvailableSizes(); void fromTheme(); void fromThemeCache(); + void fromThemeConstant(); #ifndef QT_NO_WIDGETS void task184901_badCache(); @@ -143,8 +122,8 @@ void tst_QIcon::actualSize() auto expectedDeviceSize = [](QSize deviceIndependentExpectedSize, QSize maxSourceImageSize) -> QSize { qreal dpr = qApp->devicePixelRatio(); - return QSize(qMin(int(deviceIndependentExpectedSize.width() * dpr), maxSourceImageSize.width()), - qMin(int(deviceIndependentExpectedSize.height() * dpr), maxSourceImageSize.height())); + return QSize(qMin(qRound(deviceIndependentExpectedSize.width() * dpr), maxSourceImageSize.width()), + qMin(qRound(deviceIndependentExpectedSize.height() * dpr), maxSourceImageSize.height())); }; QSize sourceSize = QImage(source).size(); @@ -213,21 +192,21 @@ void tst_QIcon::isNull() { // test string constructor with empty string QIcon iconEmptyString = QIcon(QString()); QVERIFY(iconEmptyString.isNull()); - QVERIFY(!iconEmptyString.actualSize(QSize(32, 32)).isValid());; + QVERIFY(!iconEmptyString.actualSize(QSize(32, 32)).isValid()); // test string constructor with non-existing file QIcon iconNoFile = QIcon("imagedoesnotexist"); - QVERIFY(!iconNoFile.isNull()); + QVERIFY(iconNoFile.isNull()); QVERIFY(!iconNoFile.actualSize(QSize(32, 32)).isValid()); // test string constructor with non-existing file with suffix QIcon iconNoFileSuffix = QIcon("imagedoesnotexist.png"); - QVERIFY(!iconNoFileSuffix.isNull()); + QVERIFY(iconNoFileSuffix.isNull()); QVERIFY(!iconNoFileSuffix.actualSize(QSize(32, 32)).isValid()); // test string constructor with existing file but unsupported format QIcon iconUnsupportedFormat = QIcon(m_sourceFileName); - QVERIFY(!iconUnsupportedFormat.isNull()); + QVERIFY(iconUnsupportedFormat.isNull()); QVERIFY(!iconUnsupportedFormat.actualSize(QSize(32, 32)).isValid()); // test string constructor with existing file and supported format @@ -409,6 +388,9 @@ void tst_QIcon::detach() void tst_QIcon::addFile() { + if (qApp->devicePixelRatio() != int(qApp->devicePixelRatio())) + QSKIP("Test is not ready for non integer devicePixelRatio", QTest::SkipAll); + QIcon icon; icon.addFile(QLatin1String(":/styles/commonstyle/images/standardbutton-open-16.png")); icon.addFile(QLatin1String(":/styles/commonstyle/images/standardbutton-open-32.png")); @@ -462,6 +444,52 @@ void tst_QIcon::pixmap() QVERIFY(icon.pixmap(QSize(16, 16), -1).size().width() >= 16); } +void tst_QIcon::paint() +{ + QImage img16_1x(16, 16, QImage::Format_ARGB32); + img16_1x.fill(qRgb(0, 0, 0xff)); + img16_1x.setDevicePixelRatio(1.); + + QImage img16_2x(32, 32, QImage::Format_ARGB32); + img16_2x.fill(qRgb(0, 0xff, 0xff)); + img16_2x.setDevicePixelRatio(2.); + + QImage img32_1x(32, 32, QImage::Format_ARGB32); + img32_1x.fill(qRgb(0xff, 0, 0)); + img32_1x.setDevicePixelRatio(1.); + + QImage img32_2x(64, 64, QImage::Format_ARGB32); + img32_2x.fill(qRgb(0x0, 0xff, 0)); + img32_2x.setDevicePixelRatio(2.); + + QIcon icon; + icon.addPixmap(QPixmap::fromImage(img16_1x)); + icon.addPixmap(QPixmap::fromImage(img16_2x)); + icon.addPixmap(QPixmap::fromImage(img32_1x)); + icon.addPixmap(QPixmap::fromImage(img32_2x)); + + // Test painting the icon version with a device independent size of 32x32 + QRect iconRect(0, 0, 32, 32); + + auto imageWithPaintedIconAtDpr = [&](qreal dpr) { + QImage paintDevice(64 * dpr, 64 * dpr, QImage::Format_ARGB32); + paintDevice.setDevicePixelRatio(dpr); + + QPainter painter(&paintDevice); + icon.paint(&painter, iconRect); + return paintDevice; + }; + + QImage imageWithIcon1x = imageWithPaintedIconAtDpr(1.0); + QCOMPARE(imageWithIcon1x.pixel(iconRect.center()), qRgb(0xff, 0, 0)); + + QImage imageWithIcon2x = imageWithPaintedIconAtDpr(2.0); + QCOMPARE(imageWithIcon2x.pixel(iconRect.center()), qRgb(0, 0xff, 0)); + + QImage imageWithIcon3x = imageWithPaintedIconAtDpr(3.0); + QCOMPARE(imageWithIcon3x.pixel(iconRect.center()), qRgb(0, 0xff, 0)); +} + static bool sizeLess(const QSize &a, const QSize &b) { return a.width() < b.width(); @@ -525,6 +553,10 @@ void tst_QIcon::availableSizes() void tst_QIcon::name() { + const auto reset = qScopeGuard([]{ + QIcon::setThemeName({}); + QIcon::setThemeSearchPaths({}); + }); { // No name if icon does not come from a theme QIcon icon(":/image.png"); @@ -602,6 +634,7 @@ void tst_QIcon::task184901_badCache() void tst_QIcon::fromTheme() { + const bool abIconFromPlatform = !QIcon::fromTheme("address-book-new").isNull(); QString firstSearchPath = QLatin1String(":/icons"); QString secondSearchPath = QLatin1String(":/second_icons"); QIcon::setThemeSearchPaths(QStringList() << firstSearchPath << secondSearchPath); @@ -690,14 +723,44 @@ void tst_QIcon::fromTheme() QCOMPARE(i.availableSizes(), abIcon.availableSizes()); } + // Setting or changing the fallback theme should invalidate earlier lookups. + // We can only test this if the system doesn't provide an icon, because once + // we got a valid icon, it will be cached, and even if we proxy to a different + // engine when a fallback theme is set, the cacheKey of the icon will be the + // same. + const QIcon editCut = QIcon::fromTheme("edit-cut"); + if (editCut.isNull()) { + QIcon::setFallbackThemeName("fallbacktheme"); + QVERIFY(!QIcon::fromTheme("edit-cut").isNull()); + } + // Make sure setting the theme name clears the state QIcon::setThemeName(""); abIcon = QIcon::fromTheme("address-book-new"); - QVERIFY(abIcon.isNull()); + QCOMPARE_NE(abIcon.isNull(), abIconFromPlatform); + + // Test fallback icon behavior for empty theme names. + // Can only reliably test this on systems that don't have a + // named system icon theme. + QIcon::setThemeName(""); // Reset user-theme + if (QIcon::themeName().isEmpty()) { + // Test icon from fallback theme even when theme name is empty + QIcon::setFallbackThemeName("fallbacktheme"); + QVERIFY(!QIcon::fromTheme("edit-cut").isNull()); + + // Test icon from fallback path even when theme name is empty + fallbackIcon = QIcon::fromTheme("red"); + QVERIFY(!fallbackIcon.isNull()); + QVERIFY(QIcon::hasThemeIcon("red")); + QCOMPARE(fallbackIcon.availableSizes().size(), 1); + } // Passing a full path to fromTheme is not very useful, but should work anyway QIcon fullPathIcon = QIcon::fromTheme(m_pngImageFileName); QVERIFY(!fullPathIcon.isNull()); + + // Restore to system fallback theme + QIcon::setFallbackThemeName(""); } static inline QString findGtkUpdateIconCache() @@ -758,7 +821,7 @@ void tst_QIcon::fromThemeCache() QTest::qWait(1000); // wait enough to have a different modification time in seconds QVERIFY(QFile(QStringLiteral(":/styles/commonstyle/images/standardbutton-save-16.png")) .copy(dir.path() + QLatin1String("/testcache/16x16/actions/button-save.png"))); - QVERIFY(QFileInfo(cacheName).lastModified() < QFileInfo(dir.path() + QLatin1String("/testcache/16x16/actions")).lastModified()); + QVERIFY(QFileInfo(cacheName).lastModified(QTimeZone::UTC) < QFileInfo(dir.path() + QLatin1String("/testcache/16x16/actions")).lastModified(QTimeZone::UTC)); QIcon::setThemeSearchPaths(QStringList() << dir.path()); // reload themes QVERIFY(!QIcon::fromTheme("button-open").isNull()); @@ -779,13 +842,18 @@ void tst_QIcon::fromThemeCache() QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); #endif // QT_CONFIG(process) - QVERIFY(QFileInfo(cacheName).lastModified() >= QFileInfo(dir.path() + QLatin1String("/testcache/16x16/actions")).lastModified()); + QVERIFY(QFileInfo(cacheName).lastModified(QTimeZone::UTC) >= QFileInfo(dir.path() + QLatin1String("/testcache/16x16/actions")).lastModified(QTimeZone::UTC)); QIcon::setThemeSearchPaths(QStringList() << dir.path()); // reload themes QVERIFY(!QIcon::fromTheme("button-open").isNull()); QVERIFY(!QIcon::fromTheme("button-open-fallback").isNull()); QVERIFY(QIcon::fromTheme("notexist-fallback").isNull()); } +void tst_QIcon::fromThemeConstant() +{ + const QIcon icon = QIcon::fromTheme(QIcon::ThemeIcon::EditCut); +} + void tst_QIcon::task223279_inconsistentAddFile() { QIcon icon1; |