diff options
Diffstat (limited to 'tests/auto/gui/image/qicon')
-rw-r--r-- | tests/auto/gui/image/qicon/CMakeLists.txt | 17 | ||||
-rw-r--r-- | tests/auto/gui/image/qicon/icons/fallbacktheme/16x16/edit-cut.png | bin | 0 -> 267 bytes | |||
-rw-r--r-- | tests/auto/gui/image/qicon/icons/fallbacktheme/index.theme | 8 | ||||
-rw-r--r-- | tests/auto/gui/image/qicon/icons/hicolor/16x16/hicolor-icon.png | bin | 0 -> 267 bytes | |||
-rw-r--r-- | tests/auto/gui/image/qicon/icons/hicolor/index.theme | 11 | ||||
-rw-r--r-- | tests/auto/gui/image/qicon/icons/testtheme/index.theme | 2 | ||||
-rw-r--r-- | tests/auto/gui/image/qicon/icons/themeparent/index.theme | 1 | ||||
-rw-r--r-- | tests/auto/gui/image/qicon/plugin/CMakeLists.txt | 20 | ||||
-rw-r--r-- | tests/auto/gui/image/qicon/plugin/main.cpp | 73 | ||||
-rw-r--r-- | tests/auto/gui/image/qicon/plugin/plugin.json | 3 | ||||
-rw-r--r-- | tests/auto/gui/image/qicon/tst_qicon.cpp | 86 |
11 files changed, 209 insertions, 12 deletions
diff --git a/tests/auto/gui/image/qicon/CMakeLists.txt b/tests/auto/gui/image/qicon/CMakeLists.txt index 52f45b2483..93f75741c0 100644 --- a/tests/auto/gui/image/qicon/CMakeLists.txt +++ b/tests/auto/gui/image/qicon/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Generated from qicon.pro. - ##################################################################### ## tst_qicon Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qicon LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data file(GLOB_RECURSE test_data_glob RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} @@ -33,11 +37,14 @@ file(GLOB_RECURSE test_data_glob *.svgz) list(APPEND test_data ${test_data_glob}) +add_subdirectory(plugin) + qt_internal_add_test(tst_qicon SOURCES tst_qicon.cpp LIBRARIES Qt::Gui + TestIconPlugin TESTDATA ${test_data} ) @@ -58,6 +65,10 @@ set(tst_qicon_resource_files "./icons/themeparent/index.theme" "./icons/themeparent/scalable/actions/address-book-new.svg" "./icons/themeparent/scalable/actions/appointment-new.svg" + "./icons/fallbacktheme/index.theme" + "./icons/fallbacktheme/16x16/edit-cut.png" + "./icons/hicolor/index.theme" + "./icons/hicolor/16x16/hicolor-icon.png" "./second_icons/testtheme/32x32/actions/appointment-new.png" "./styles/commonstyle/images/standardbutton-open-128.png" "./styles/commonstyle/images/standardbutton-open-16.png" @@ -97,3 +108,5 @@ qt_internal_extend_target(tst_qicon CONDITION TARGET Qt::Widgets LIBRARIES Qt::Widgets ) + +add_dependencies(tst_qicon TestIconPlugin) diff --git a/tests/auto/gui/image/qicon/icons/fallbacktheme/16x16/edit-cut.png b/tests/auto/gui/image/qicon/icons/fallbacktheme/16x16/edit-cut.png Binary files differnew file mode 100644 index 0000000000..661ef1ad03 --- /dev/null +++ b/tests/auto/gui/image/qicon/icons/fallbacktheme/16x16/edit-cut.png diff --git a/tests/auto/gui/image/qicon/icons/fallbacktheme/index.theme b/tests/auto/gui/image/qicon/icons/fallbacktheme/index.theme new file mode 100644 index 0000000000..809d296669 --- /dev/null +++ b/tests/auto/gui/image/qicon/icons/fallbacktheme/index.theme @@ -0,0 +1,8 @@ +[Icon Theme] +Name=fallbacktheme + +Directories=16x16 + +[16x16] +Size=16 +Type=Fixed diff --git a/tests/auto/gui/image/qicon/icons/hicolor/16x16/hicolor-icon.png b/tests/auto/gui/image/qicon/icons/hicolor/16x16/hicolor-icon.png Binary files differnew file mode 100644 index 0000000000..661ef1ad03 --- /dev/null +++ b/tests/auto/gui/image/qicon/icons/hicolor/16x16/hicolor-icon.png diff --git a/tests/auto/gui/image/qicon/icons/hicolor/index.theme b/tests/auto/gui/image/qicon/icons/hicolor/index.theme new file mode 100644 index 0000000000..e5e5cef9b1 --- /dev/null +++ b/tests/auto/gui/image/qicon/icons/hicolor/index.theme @@ -0,0 +1,11 @@ +[Icon Theme] +Name=hicolor + +# Provide a minimal hicolor theme, so that our hicolor fallback +# lookup during testing will find that theme on all systems. + +Directories=16x16 + +[16x16] +Size=16 +Type=Fixed diff --git a/tests/auto/gui/image/qicon/icons/testtheme/index.theme b/tests/auto/gui/image/qicon/icons/testtheme/index.theme index e18736ab43..53664b14b2 100644 --- a/tests/auto/gui/image/qicon/icons/testtheme/index.theme +++ b/tests/auto/gui/image/qicon/icons/testtheme/index.theme @@ -1,7 +1,7 @@ [Icon Theme] _Name=Test _Comment=Test Theme -Inherits=crystalsvg, themeparent +Inherits=themeparent Example=x-directory-normal # KDE Specific Stuff diff --git a/tests/auto/gui/image/qicon/icons/themeparent/index.theme b/tests/auto/gui/image/qicon/icons/themeparent/index.theme index e536a0bf2f..96267addd6 100644 --- a/tests/auto/gui/image/qicon/icons/themeparent/index.theme +++ b/tests/auto/gui/image/qicon/icons/themeparent/index.theme @@ -1,7 +1,6 @@ [Icon Theme] _Name=Test _Comment=Test Theme -Inherits=gnome,crystalsvg Example=x-directory-normal # KDE Specific Stuff diff --git a/tests/auto/gui/image/qicon/plugin/CMakeLists.txt b/tests/auto/gui/image/qicon/plugin/CMakeLists.txt new file mode 100644 index 0000000000..cae49b2df1 --- /dev/null +++ b/tests/auto/gui/image/qicon/plugin/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## TestIconEngine Plugin: +##################################################################### + +qt_internal_add_plugin(TestIconPlugin + STATIC + OUTPUT_NAME qtesticonplugin + OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" + SKIP_INSTALL + PLUGIN_TYPE iconengines + DEFAULT_IF TRUE + SOURCES + main.cpp + LIBRARIES + Qt::Core + Qt::Gui +) diff --git a/tests/auto/gui/image/qicon/plugin/main.cpp b/tests/auto/gui/image/qicon/plugin/main.cpp new file mode 100644 index 0000000000..58d9807142 --- /dev/null +++ b/tests/auto/gui/image/qicon/plugin/main.cpp @@ -0,0 +1,73 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <qiconengineplugin.h> +#include <qiconengine.h> + +QT_BEGIN_NAMESPACE + +class TestIconPlugin : public QIconEnginePlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QIconEngineFactoryInterface" FILE "plugin.json") + +public: + QIconEngine *create(const QString &icon) override; +}; + +class TestIconEngine : public QIconEngine +{ +public: + TestIconEngine(const QString &icon) + : m_iconName(QIcon::themeName() + "/" + icon) + { + } + + ~TestIconEngine() + {} + + QIconEngine *clone() const override + { + return new TestIconEngine(m_iconName); + } + + QString key() const override + { + return QStringLiteral("TestIconEngine"); + } + + QString iconName() override + { + return m_iconName; + } + + bool isNull() override + { + return m_iconName.isNull(); + } + + QList<QSize> availableSizes(QIcon::Mode, QIcon::State) override + { + return {{16, 16}, {48, 48}, {64, 64}}; + } + + void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override + { + Q_UNUSED(painter); + Q_UNUSED(rect); + Q_UNUSED(mode); + Q_UNUSED(state); + } + +private: + const QString m_iconName; +}; + +QIconEngine *TestIconPlugin::create(const QString &icon) +{ + return new TestIconEngine(icon); +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/tests/auto/gui/image/qicon/plugin/plugin.json b/tests/auto/gui/image/qicon/plugin/plugin.json new file mode 100644 index 0000000000..96b59aa79e --- /dev/null +++ b/tests/auto/gui/image/qicon/plugin/plugin.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "plugintheme", "SpecialTheme" ] +} diff --git a/tests/auto/gui/image/qicon/tst_qicon.cpp b/tests/auto/gui/image/qicon/tst_qicon.cpp index 514a2d9bcf..d95ee66fb6 100644 --- a/tests/auto/gui/image/qicon/tst_qicon.cpp +++ b/tests/auto/gui/image/qicon/tst_qicon.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 <QTest> #include <QImageReader> @@ -41,12 +41,16 @@ private slots: void streamAvailableSizes(); void fromTheme(); void fromThemeCache(); + void fromThemeConstant(); #ifndef QT_NO_WIDGETS void task184901_badCache(); #endif void task223279_inconsistentAddFile(); + void themeFromPlugin_data(); + void themeFromPlugin(); + private: bool haveImageFormat(QByteArray const&); @@ -191,21 +195,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 @@ -552,6 +556,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"); @@ -629,6 +637,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); @@ -717,14 +726,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() @@ -785,7 +824,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()); @@ -806,13 +845,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; @@ -831,6 +875,32 @@ void tst_QIcon::task223279_inconsistentAddFile() QCOMPARE(pm1.size(), pm2.size()); } +Q_IMPORT_PLUGIN(TestIconPlugin) + +void tst_QIcon::themeFromPlugin_data() +{ + QTest::addColumn<QString>("themeName"); + + QTest::addRow("plugintheme") << "plugintheme"; + QTest::addRow("specialtheme") << "specialTheme"; // deliberately not matching case +} + +void tst_QIcon::themeFromPlugin() +{ + QFETCH(const QString, themeName); + auto restoreTheme = qScopeGuard([oldTheme = QIcon::themeName()]{ + QIcon::setThemeName(oldTheme); + }); + + QIcon icon = QIcon::fromTheme("icon1"); + QVERIFY(icon.isNull()); + + QIcon::setThemeName(themeName); + + icon = QIcon::fromTheme("icon1"); + QVERIFY(!icon.isNull()); + QCOMPARE(icon.name(), themeName + "/icon1"); +} QTEST_MAIN(tst_QIcon) #include "tst_qicon.moc" |