summaryrefslogtreecommitdiffstats
path: root/tests/auto/gui/image/qicon
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/gui/image/qicon')
-rw-r--r--tests/auto/gui/image/qicon/CMakeLists.txt15
-rw-r--r--tests/auto/gui/image/qicon/icons/fallbacktheme/16x16/edit-cut.pngbin0 -> 267 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/fallbacktheme/index.theme8
-rw-r--r--tests/auto/gui/image/qicon/icons/hicolor/16x16/hicolor-icon.pngbin0 -> 267 bytes
-rw-r--r--tests/auto/gui/image/qicon/icons/hicolor/index.theme11
-rw-r--r--tests/auto/gui/image/qicon/icons/testtheme/index.theme2
-rw-r--r--tests/auto/gui/image/qicon/icons/themeparent/index.theme1
-rw-r--r--tests/auto/gui/image/qicon/plugin/CMakeLists.txt20
-rw-r--r--tests/auto/gui/image/qicon/plugin/main.cpp73
-rw-r--r--tests/auto/gui/image/qicon/plugin/plugin.json3
-rw-r--r--tests/auto/gui/image/qicon/tst_qicon.cpp82
11 files changed, 207 insertions, 8 deletions
diff --git a/tests/auto/gui/image/qicon/CMakeLists.txt b/tests/auto/gui/image/qicon/CMakeLists.txt
index c900c60d5b..93f75741c0 100644
--- a/tests/auto/gui/image/qicon/CMakeLists.txt
+++ b/tests/auto/gui/image/qicon/CMakeLists.txt
@@ -5,6 +5,12 @@
## 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}
@@ -31,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}
)
@@ -56,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"
@@ -95,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
new file mode 100644
index 0000000000..661ef1ad03
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/fallbacktheme/16x16/edit-cut.png
Binary files differ
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
new file mode 100644
index 0000000000..661ef1ad03
--- /dev/null
+++ b/tests/auto/gui/image/qicon/icons/hicolor/16x16/hicolor-icon.png
Binary files differ
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 ebb0f1e9d2..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()
@@ -813,6 +852,11 @@ void tst_QIcon::fromThemeCache()
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"