diff --git a/CMakeLists.txt b/CMakeLists.txt index 334c68c..4c3c664 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,96 +1,101 @@ cmake_minimum_required(VERSION 3.0) set(KF5_VERSION "5.51.0") # handled by release scripts set(KF5_DEP_VERSION "5.50.0") # handled by release scripts project(KIconThemes VERSION ${KF5_VERSION}) # ECM setup include(FeatureSummary) find_package(ECM 5.50.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) include(KDEInstallDirs) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) include(GenerateExportHeader) include(ECMSetupVersion) include(ECMGenerateHeaders) include(ECMMarkNonGuiExecutable) include(ECMQtDeclareLoggingCategory) include(ECMAddQch) option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF) add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)") ecm_setup_version(PROJECT VARIABLE_PREFIX KICONTHEMES VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kiconthemes_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5IconThemesConfigVersion.cmake" SOVERSION 5) # Dependencies set(REQUIRED_QT_VERSION 5.8.0) find_package(Qt5Widgets ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE) find_package(Qt5Svg ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE) find_package(Qt5DBus ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE) find_package(KF5Archive ${KF5_DEP_VERSION} REQUIRED) find_package(KF5I18n ${KF5_DEP_VERSION} REQUIRED) find_package(KF5CoreAddons ${KF5_DEP_VERSION} REQUIRED) find_package(KF5ConfigWidgets ${KF5_DEP_VERSION} REQUIRED) find_package(KF5WidgetsAddons ${KF5_DEP_VERSION} REQUIRED) find_package(KF5ItemViews ${KF5_DEP_VERSION} REQUIRED) remove_definitions(-DQT_NO_CAST_FROM_ASCII) remove_definitions(-DQT_NO_CAST_FROM_BYTEARRAY) add_definitions(-DTRANSLATION_DOMAIN=\"kiconthemes5\") if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") ki18n_install(po) endif() +#add_definitions(-DQT_NO_CAST_FROM_ASCII) +add_definitions(-DQT_NO_CAST_TO_ASCII) +add_definitions(-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT) +add_definitions(-DQT_NO_URL_CAST_FROM_STRING) +add_definitions(-DQT_USE_QSTRINGBUILDER) add_subdirectory(src) if (BUILD_TESTING) add_subdirectory(tests) add_subdirectory(autotests) endif() # create a Config.cmake and a ConfigVersion.cmake file and install them set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5IconThemes") if (BUILD_QCH) ecm_install_qch_export( TARGETS KF5IconThemes_QCH FILE KF5IconThemesQchTargets.cmake DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF5IconThemesQchTargets.cmake\")") endif() include(CMakePackageConfigHelpers) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5IconThemesConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5IconThemesConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5IconThemesConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5IconThemesConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) install(EXPORT KF5IconThemesTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5IconThemesTargets.cmake NAMESPACE KF5:: ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kiconthemes_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/autotests/kiconengine_unittest.cpp b/autotests/kiconengine_unittest.cpp index f758ac6..7da098e 100644 --- a/autotests/kiconengine_unittest.cpp +++ b/autotests/kiconengine_unittest.cpp @@ -1,145 +1,145 @@ /* Copyright (C) 2016 David Rosca This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include extern KICONTHEMES_EXPORT int kiconloader_ms_between_checks; class KIconEngine_UnitTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase() { QStandardPaths::setTestModeEnabled(true); // Remove icon cache - const QString cacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + "/icon-cache.kcache"; + const QString cacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/icon-cache.kcache"); QFile::remove(cacheFile); KConfigGroup cg(KSharedConfig::openConfig(), "Icons"); cg.writeEntry("Theme", "oxygen"); cg.sync(); QDir testDataDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)); testIconsDir = QDir(testDataDir.absoluteFilePath(QStringLiteral("icons"))); // we will be recursively deleting these, so a sanity check is in order QVERIFY(testIconsDir.absolutePath().contains(QStringLiteral("qttest"))); testIconsDir.removeRecursively(); // set up a minimal Oxygen icon theme, in case it is not installed QVERIFY(testIconsDir.mkpath(QStringLiteral("oxygen/22x22/apps"))); QVERIFY(QFile::copy(QStringLiteral(":/oxygen.theme"), testIconsDir.filePath(QStringLiteral("oxygen/index.theme")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("oxygen/22x22/apps/kde.png")))); QVERIFY(testIconsDir.mkpath(QStringLiteral("oxygen/22x22/actions"))); // we need the dir to exist since KIconThemes caches mDirs // Clear SHM cache KIconLoader::global()->reconfigure(QString()); } void testValidIconName() { QIcon icon(new KIconEngine(QStringLiteral("kde"), KIconLoader::global())); QVERIFY(!icon.isNull()); QVERIFY(!icon.name().isEmpty()); } void testInvalidIconName() { QIcon icon(new KIconEngine(QStringLiteral("invalid-icon-name"), KIconLoader::global())); QVERIFY(icon.isNull()); QVERIFY2(icon.name().isEmpty(), qPrintable(icon.name())); } void testUnknownIconNotCached() // QIcon version of the test in kiconloader_unittest.cpp { // This is a test to ensure that "unknown" icons are cached as unknown // for performance reasons, but after a while they'll be looked up again // so that newly installed icons can be used without a reboot. kiconloader_ms_between_checks = 500000; QString actionIconsSubdir = QStringLiteral("oxygen/22x22/actions"); QVERIFY(testIconsDir.mkpath(actionIconsSubdir)); QString actionIconsDir = testIconsDir.filePath(actionIconsSubdir); QString nonExistingIconName = QStringLiteral("asvdfg_fhqwhgds"); QString newIconPath = actionIconsDir + QLatin1String("/") + nonExistingIconName + QLatin1String(".png"); QFile::remove(newIconPath); // Find a non-existent icon QIcon icon(new KIconEngine(nonExistingIconName, KIconLoader::global())); QVERIFY(icon.isNull()); QVERIFY(icon.name().isEmpty()); // Install the existing icon by copying. QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), newIconPath)); // Attempt to find the icon again, the cache will still be used for now. QIcon icon2(new KIconEngine(nonExistingIconName, KIconLoader::global())); QVERIFY(icon2.isNull()); QVERIFY(icon2.name().isEmpty()); // Force a recheck to happen on next lookup kiconloader_ms_between_checks = 0; // Verify the icon can now be found. QIcon nowExistingIcon(new KIconEngine(nonExistingIconName, KIconLoader::global())); QVERIFY(!nowExistingIcon.isNull()); QCOMPARE(nowExistingIcon.name(), nonExistingIconName); // And verify again, this time with the cache kiconloader_ms_between_checks = 50000; QIcon icon3(new KIconEngine(nonExistingIconName, KIconLoader::global())); QVERIFY(!icon3.isNull()); QCOMPARE(icon3.name(), nonExistingIconName); } void testCenterIcon() { QIcon icon(new KIconEngine(QStringLiteral("kde"), KIconLoader::global())); QVERIFY(!icon.isNull()); // "kde" icon is actually "test-22x22.png", so this is original icon image const QImage image = icon.pixmap(22, 22).toImage(); // center vertically QVERIFY(icon.pixmap(22, 26).toImage().copy(0, 2, 22, 22) == image); // center horizontally QVERIFY(icon.pixmap(26, 22).toImage().copy(2, 0, 22, 22) == image); } private: QDir testIconsDir; }; QTEST_MAIN(KIconEngine_UnitTest) #include "kiconengine_unittest.moc" diff --git a/autotests/kiconloader_benchmark.cpp b/autotests/kiconloader_benchmark.cpp index eb0f71b..839364c 100644 --- a/autotests/kiconloader_benchmark.cpp +++ b/autotests/kiconloader_benchmark.cpp @@ -1,132 +1,132 @@ /* This file is part of the KDE libraries Copyright 2016 Aleix Pol Gonzalez This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include class KIconLoader_Benchmark : public QObject { Q_OBJECT private Q_SLOTS: void init() { #if 0 // Enable this code to benchmark very first startup. // Starting the application again uses the on-disk cache, so actually benchmarking -with- a cache is more relevant. // Remove icon cache const QString cacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + "/icon-cache.kcache"; QFile::remove(cacheFile); // Clear SHM cache KIconLoader::global()->reconfigure(QString()); #endif } void benchmarkExistingIcons() { //icon list I get to load kwrite static QStringList icons = { QStringLiteral("accessories-text-editor"), QStringLiteral("bookmarks"), QStringLiteral("dialog-close"), QStringLiteral("edit-cut"), QStringLiteral("edit-paste"), QStringLiteral("edit-copy"), QStringLiteral("document-save"), QStringLiteral("edit-undo"), QStringLiteral("edit-redo"), QStringLiteral("code-context"), QStringLiteral("document-print"), QStringLiteral("document-print-preview"), QStringLiteral("view-refresh"), QStringLiteral("document-save-as"), QStringLiteral("preferences-other"), QStringLiteral("edit-select-all"), QStringLiteral("zoom-in"), QStringLiteral("zoom-out"), QStringLiteral("edit-find"), QStringLiteral("go-down-search"), QStringLiteral("go-up-search"), QStringLiteral("tools-check-spelling"), QStringLiteral("bookmark-new"), QStringLiteral("format-indent-more"), QStringLiteral("format-indent-less"), QStringLiteral("text-plain"), QStringLiteral("go-up"), QStringLiteral("go-down"), QStringLiteral("dialog-ok"), QStringLiteral("dialog-cancel"), QStringLiteral("window-close"), QStringLiteral("document-new"), QStringLiteral("document-open"), QStringLiteral("document-open-recent"), QStringLiteral("window-new"), QStringLiteral("application-exit"), QStringLiteral("show-menu"), QStringLiteral("configure-shortcuts"), QStringLiteral("configure-toolbars"), QStringLiteral("help-contents"), QStringLiteral("help-contextual"), QStringLiteral("tools-report-bug"), QStringLiteral("preferences-desktop-locale"), QStringLiteral("kde") }; QBENCHMARK { foreach (const QString &iconName, icons) { const QIcon icon = QIcon::fromTheme(iconName); if(icon.isNull()) QSKIP("missing icons"); QVERIFY(!icon.pixmap(24, 24).isNull()); //QVERIFY(!icon.pixmap(512, 512).isNull()); } } } void benchmarkNonExistingIcon_notCached() { QBENCHMARK { // Remove icon cache - const QString cacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + "/icon-cache.kcache"; + const QString cacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/icon-cache.kcache"); QFile::remove(cacheFile); // Clear SHM cache KIconLoader::global()->reconfigure(QString()); QIcon icon(new KIconEngine(QStringLiteral("invalid-icon-name"), KIconLoader::global())); QVERIFY(icon.isNull()); QVERIFY2(icon.name().isEmpty(), qPrintable(icon.name())); QVERIFY(!icon.pixmap(QSize(16, 16), QIcon::Normal).isNull()); } } void benchmarkNonExistingIcon_cached() { QBENCHMARK { QIcon icon(new KIconEngine(QStringLiteral("invalid-icon-name"), KIconLoader::global())); QVERIFY(icon.isNull()); QVERIFY2(icon.name().isEmpty(), qPrintable(icon.name())); QVERIFY(!icon.pixmap(QSize(16, 16), QIcon::Normal).isNull()); } } }; QTEST_MAIN(KIconLoader_Benchmark) #include "kiconloader_benchmark.moc" diff --git a/autotests/kiconloader_rcctest.cpp b/autotests/kiconloader_rcctest.cpp index 3ab68bc..e2c6d82 100644 --- a/autotests/kiconloader_rcctest.cpp +++ b/autotests/kiconloader_rcctest.cpp @@ -1,97 +1,97 @@ /* This file is part of the KDE libraries Copyright 2015 Christoph Cullmann Copyright 2016 David Faure This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include // Install icontheme.rcc where KIconThemes will find it. // This must be done before QCoreApplication is even created, given the Q_COREAPP_STARTUP_FUNCTION in kiconthemes void earlyInit() { - QStandardPaths::enableTestMode(true); + QStandardPaths::setTestModeEnabled(true); qputenv("XDG_DATA_DIRS", "/doesnotexist"); // ensure hicolor/oxygen/breeze are not found QFile rcc(QStringLiteral("icontheme.rcc")); Q_ASSERT(rcc.exists()); QCoreApplication::setApplicationName(QStringLiteral("myappname")); // for a fixed location on Unix (appname is empty here otherwise) const QString destDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); QDir().mkpath(destDir); - const QString dest = destDir + "/icontheme.rcc"; + const QString dest = destDir + QStringLiteral("/icontheme.rcc"); QFile::remove(dest); if (!rcc.copy(dest)) { qWarning() << "Error copying to" << dest; } } Q_CONSTRUCTOR_FUNCTION(earlyInit) class KIconLoader_RCCThemeTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase() { // Remove icon cache - const QString cacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + "/icon-cache.kcache"; + const QString cacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/icon-cache.kcache"); QFile::remove(cacheFile); // Clear SHM cache KIconLoader::global()->reconfigure(QString()); } void testThemeName() { QCOMPARE(QIcon::themeName(), m_internalThemeName); } void testQIconFromTheme() { // load icon with Qt API QVERIFY(!QIcon::fromTheme(QStringLiteral("someiconintheme")).isNull()); } void testKIconLoader() { // Check that direct usage of KIconLoader (e.g. from KToolBar) works QVERIFY(KIconLoader::global()->theme()); QCOMPARE(KIconLoader::global()->theme()->internalName(), m_internalThemeName); // load icon with KIconLoader API (unlikely to happen in reality) QString path; KIconLoader::global()->loadIcon(QStringLiteral("someiconintheme"), KIconLoader::Desktop, 22, KIconLoader::DefaultState, QStringList(), &path); QCOMPARE(path, QString(QStringLiteral(":/icons/") + m_internalThemeName + QStringLiteral("/22x22/appsNoContext/someiconintheme.png"))); } private: const QString m_internalThemeName = QStringLiteral("kf5_rcc_theme"); }; QTEST_MAIN(KIconLoader_RCCThemeTest) #include "kiconloader_rcctest.moc" diff --git a/autotests/kiconloader_resourcethemetest.cpp b/autotests/kiconloader_resourcethemetest.cpp index e43e29e..b32c0b1 100644 --- a/autotests/kiconloader_resourcethemetest.cpp +++ b/autotests/kiconloader_resourcethemetest.cpp @@ -1,58 +1,58 @@ /* This file is part of the KDE libraries Copyright 2015 Christoph Cullmann This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include class KIconLoader_ResourceThemeTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase() { QStandardPaths::setTestModeEnabled(true); // set our test theme only present in :/icons KConfigGroup cg(KSharedConfig::openConfig(), "Icons"); cg.writeEntry("Theme", "themeinresource"); cg.sync(); } void testThemeFound() { // try to load icon that can only be found in resource theme and check we found it in the resource QString path; KIconLoader::global()->loadIcon(QStringLiteral("someiconintheme"), KIconLoader::Desktop, 22, KIconLoader::DefaultState, QStringList(), &path); - QCOMPARE(path, QString(":/icons/themeinresource/22x22/appsNoContext/someiconintheme.png")); + QCOMPARE(path, QStringLiteral(":/icons/themeinresource/22x22/appsNoContext/someiconintheme.png")); } }; QTEST_MAIN(KIconLoader_ResourceThemeTest) #include "kiconloader_resourcethemetest.moc" diff --git a/autotests/kiconloader_unittest.cpp b/autotests/kiconloader_unittest.cpp index 9bbdb4c..8dd3409 100644 --- a/autotests/kiconloader_unittest.cpp +++ b/autotests/kiconloader_unittest.cpp @@ -1,530 +1,530 @@ /* This file is part of the KDE libraries Copyright 2008 David Faure This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include extern KICONTHEMES_EXPORT void uintToHex(uint32_t colorData, QChar *buffer); class KIconLoader_UnitTest : public QObject { Q_OBJECT public: KIconLoader_UnitTest() : testSizes({ 12, 22, 32, 42, 82, 132, 243 }) {} private: QDir testDataDir; QDir testIconsDir; QString appName; QDir appDataDir; const QVector testSizes; private Q_SLOTS: void initTestCase() { QStandardPaths::setTestModeEnabled(true); const QStringList genericIconsFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("mime/generic-icons")); QVERIFY(!genericIconsFiles.isEmpty()); // KIconLoader relies on fallbacks to generic icons (e.g. x-office-document), which comes from a shared-mime-info file. Make sure it's installed! KConfigGroup cg(KSharedConfig::openConfig(), "Icons"); cg.writeEntry("Theme", "breeze"); cg.sync(); testDataDir = QDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)); testIconsDir = QDir(testDataDir.absoluteFilePath(QStringLiteral("icons"))); appName = QStringLiteral("kiconloader_unittest"); appDataDir = QDir(testDataDir.absoluteFilePath(appName)); // we will be recursively deleting these, so a sanity check is in order QVERIFY(testIconsDir.absolutePath().contains(QStringLiteral("qttest"))); QVERIFY(appDataDir.absolutePath().contains(QStringLiteral("qttest"))); testIconsDir.removeRecursively(); appDataDir.removeRecursively(); QVERIFY(appDataDir.mkpath(QStringLiteral("pics"))); QVERIFY(QFile::copy(QStringLiteral(":/app-image.png"), appDataDir.filePath(QStringLiteral("pics/image1.png")))); QVERIFY(QFile::copy(QStringLiteral(":/app-image.png"), appDataDir.filePath(QStringLiteral("pics/image2.png")))); // set up a minimal Oxygen icon theme, in case it is not installed QVERIFY(testIconsDir.mkpath(QStringLiteral("oxygen/22x22/actions"))); QVERIFY(testIconsDir.mkpath(QStringLiteral("oxygen/22x22/animations"))); QVERIFY(testIconsDir.mkpath(QStringLiteral("oxygen/22x22/apps"))); QVERIFY(testIconsDir.mkpath(QStringLiteral("oxygen/22x22/mimetypes"))); QVERIFY(testIconsDir.mkpath(QStringLiteral("oxygen/32x32/apps"))); QVERIFY(QFile::copy(QStringLiteral(":/oxygen.theme"), testIconsDir.filePath(QStringLiteral("oxygen/index.theme")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("oxygen/22x22/apps/kde.png")))); QVERIFY(QFile::copy(QStringLiteral(":/anim-22x22.png"), testIconsDir.filePath(QStringLiteral("oxygen/22x22/animations/process-working.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("oxygen/22x22/mimetypes/text-plain.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("oxygen/22x22/mimetypes/application-octet-stream.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("oxygen/22x22/mimetypes/image-x-generic.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("oxygen/22x22/mimetypes/video-x-generic.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("oxygen/22x22/mimetypes/x-office-document.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("oxygen/22x22/mimetypes/audio-x-generic.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("oxygen/22x22/mimetypes/unknown.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-32x32.png"), testIconsDir.filePath(QStringLiteral("oxygen/32x32/apps/kde.png")))); // set up a minimal Breeze icon theme, fallback to oxygen QVERIFY(testIconsDir.mkpath(QStringLiteral("breeze/22x22/actions"))); QVERIFY(testIconsDir.mkpath(QStringLiteral("breeze/22x22/animations"))); QVERIFY(testIconsDir.mkpath(QStringLiteral("breeze/22x22/apps"))); QVERIFY(testIconsDir.mkpath(QStringLiteral("breeze/22x22/mimetypes"))); QVERIFY(testIconsDir.mkpath(QStringLiteral("breeze/22x22/appsNoContext"))); QVERIFY(testIconsDir.mkpath(QStringLiteral("breeze/22x22/appsNoType"))); QVERIFY(testIconsDir.mkpath(QStringLiteral("breeze/22x22/appsNoContextOrType"))); const QString breezeThemeFile = testIconsDir.filePath(QStringLiteral("breeze/index.theme")); QVERIFY(QFile::copy(QStringLiteral(":/breeze.theme"), breezeThemeFile)); //kde.png is missing, it should fallback to oxygen //QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/apps/kde.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/appsNoContext/iconindirectorywithoutcontext.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/appsNoType/iconindirectorywithouttype.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/appsNoContextOrType/iconindirectorywithoutcontextortype.png")))); QVERIFY(QFile::copy(QStringLiteral(":/anim-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/animations/process-working.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/mimetypes/text-plain.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/mimetypes/application-octet-stream.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/mimetypes/image-x-generic.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/mimetypes/video-x-generic.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/mimetypes/x-office-document.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/mimetypes/audio-x-generic.png")))); QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), testIconsDir.filePath(QStringLiteral("breeze/22x22/mimetypes/unknown.png")))); QVERIFY(QFile::copy(QStringLiteral(":/coloredsvgicon.svg"), testIconsDir.filePath(QStringLiteral("breeze/22x22/apps/coloredsvgicon.svg")))); QVERIFY(QFile::setPermissions(breezeThemeFile, QFileDevice::ReadOwner|QFileDevice::WriteOwner)); KConfig configFile(breezeThemeFile); KConfigGroup iconThemeGroup = configFile.group("Icon Theme"); QVERIFY(iconThemeGroup.isValid()); QStringList dirs = iconThemeGroup.readEntry("Directories", QStringList()); Q_FOREACH(int i, testSizes) { const QString relDir = QStringLiteral("%1x%1/emblems").arg(i); const QString dir = testIconsDir.filePath(QStringLiteral("breeze/") + relDir); QVERIFY(QDir().mkpath(dir)); QPixmap img(i, i); img.fill(Qt::red); - QVERIFY(img.save(dir + "/red.png")); + QVERIFY(img.save(dir + QStringLiteral("/red.png"))); dirs += relDir; KConfigGroup dirGroup = configFile.group(relDir); dirGroup.writeEntry("Size", i); dirGroup.writeEntry("Context", "Emblems"); dirGroup.writeEntry("Type", "Fixed"); } iconThemeGroup.writeEntry("Directories", dirs); QVERIFY(configFile.sync()); } void cleanupTestCase() { if (testIconsDir != QDir()) { testIconsDir.removeRecursively(); } if (appDataDir != QDir()) { appDataDir.removeRecursively(); } } void init() { // Remove icon cache - const QString cacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + "/icon-cache.kcache"; + const QString cacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QStringLiteral("/icon-cache.kcache"); QFile::remove(cacheFile); // Clear SHM cache KIconLoader::global()->reconfigure(QString()); } void testUnknownIconNotCached() { // This is a test to ensure that "unknown" icons do not pin themselves // in the icon loader. Or in other words, if an "unknown" icon is // returned, but the appropriate icon is subsequently installed // properly, the next request for that icon should return the new icon // instead of the unknown icon. QString actionIconsSubdir = QStringLiteral("oxygen/22x22/actions"); QVERIFY(testIconsDir.mkpath(actionIconsSubdir)); QString actionIconsDir = testIconsDir.filePath(actionIconsSubdir); QString nonExistingIconName = QStringLiteral("fhqwhgads_homsar"); QString newIconPath = actionIconsDir + QLatin1String("/") + nonExistingIconName + QLatin1String(".png"); QFile::remove(newIconPath); KIconLoader iconLoader; // Find a non-existent icon, allowing unknown icon to be returned QPixmap nonExistingIcon = iconLoader.loadIcon( nonExistingIconName, KIconLoader::Toolbar); QCOMPARE(nonExistingIcon.isNull(), false); // Install the existing icon by copying. QVERIFY(QFile::copy(QStringLiteral(":/test-22x22.png"), newIconPath)); // Verify the icon can now be found. QPixmap nowExistingIcon = iconLoader.loadIcon( nonExistingIconName, KIconLoader::Toolbar); QVERIFY(nowExistingIcon.cacheKey() != nonExistingIcon.cacheKey()); QCOMPARE(iconLoader.iconPath(nonExistingIconName, KIconLoader::Toolbar), newIconPath); } void testLoadIconCanReturnNull() { // This is a test for the "canReturnNull" argument of KIconLoader::loadIcon(). // We try to load an icon that doesn't exist, first with canReturnNull=false (the default) // then with canReturnNull=true. KIconLoader iconLoader; // We expect a warning here... This doesn't work though, due to the extended debug //QTest::ignoreMessage(QtWarningMsg, "KIconLoader::loadIcon: No such icon \"this-icon-does-not-exist\""); QPixmap pix = iconLoader.loadIcon(QStringLiteral("this-icon-does-not-exist"), KIconLoader::Desktop, 16); QVERIFY(!pix.isNull()); QCOMPARE(pix.size(), QSize(16, 16)); // Try it again, to see if the cache interfers pix = iconLoader.loadIcon(QStringLiteral("this-icon-does-not-exist"), KIconLoader::Desktop, 16); QVERIFY(!pix.isNull()); QCOMPARE(pix.size(), QSize(16, 16)); // And now set canReturnNull to true pix = iconLoader.loadIcon(QStringLiteral("this-icon-does-not-exist"), KIconLoader::Desktop, 16, KIconLoader::DefaultState, QStringList(), nullptr, true); QVERIFY(pix.isNull()); // Try getting the "unknown" icon again, to see if the above call didn't put a null icon into the cache... pix = iconLoader.loadIcon(QStringLiteral("this-icon-does-not-exist"), KIconLoader::Desktop, 16); QVERIFY(!pix.isNull()); QCOMPARE(pix.size(), QSize(16, 16)); // Another one, to clear "last" cache pix = iconLoader.loadIcon(QStringLiteral("this-icon-does-not-exist-either"), KIconLoader::Desktop, 16); QVERIFY(!pix.isNull()); QCOMPARE(pix.size(), QSize(16, 16)); // Now load the initial one again - do we get the warning again? pix = iconLoader.loadIcon(QStringLiteral("this-icon-does-not-exist"), KIconLoader::Desktop, 16); QVERIFY(!pix.isNull()); QCOMPARE(pix.size(), QSize(16, 16)); pix = iconLoader.loadIcon(QStringLiteral("#crazyname"), KIconLoader::NoGroup, 1600); QVERIFY(!pix.isNull()); QCOMPARE(pix.size(), QSize(1600, 1600)); } void testAppPicsDir() { KIconLoader appIconLoader(appName); QString iconPath = appIconLoader.iconPath(QStringLiteral("image1"), KIconLoader::User); - QCOMPARE(iconPath, appDataDir.filePath("pics/image1.png")); + QCOMPARE(iconPath, appDataDir.filePath(QStringLiteral("pics/image1.png"))); QVERIFY(QFile::exists(iconPath)); // Load it again, to use the "last loaded" cache QString iconPath2 = appIconLoader.iconPath(QStringLiteral("image1"), KIconLoader::User); QCOMPARE(iconPath, iconPath2); // Load something else, to clear the "last loaded" cache QString iconPathTextEdit = appIconLoader.iconPath(QStringLiteral("image2"), KIconLoader::User); - QCOMPARE(iconPathTextEdit, appDataDir.filePath("pics/image2.png")); + QCOMPARE(iconPathTextEdit, appDataDir.filePath(QStringLiteral("pics/image2.png"))); QVERIFY(QFile::exists(iconPathTextEdit)); // Now load kdialog again, to use the real kiconcache iconPath2 = appIconLoader.iconPath(QStringLiteral("image1"), KIconLoader::User); QCOMPARE(iconPath, iconPath2); } void testAppPicsDir_KDE_icon() { // #### This test is broken; it passes even if appName is set to foobar, because // QIcon::pixmap returns an unknown icon if it can't find the real icon... KIconLoader appIconLoader(appName); // Now using KDE::icon. Separate test so that KIconLoader isn't fully inited. QIcon icon = KDE::icon(QStringLiteral("image1"), &appIconLoader); { QPixmap pix = icon.pixmap(QSize(22, 22)); QVERIFY(!pix.isNull()); } QCOMPARE(icon.actualSize(QSize(96, 22)), QSize(22, 22)); QCOMPARE(icon.actualSize(QSize(22, 96)), QSize(22, 22)); QCOMPARE(icon.actualSize(QSize(22, 16)), QSize(16, 16)); // Can we ask for a really small size? { QPixmap pix8 = icon.pixmap(QSize(8, 8)); QCOMPARE(pix8.size(), QSize(8, 8)); } } void testLoadMimeTypeIcon_data() { QTest::addColumn("iconName"); QTest::addColumn("expectedFileName"); - QTest::newRow("existing icon") << "text-plain" << "text-plain.png"; - QTest::newRow("octet-stream icon") << "application-octet-stream" << "application-octet-stream.png"; - QTest::newRow("non-existing icon") << "foo-bar" << "application-octet-stream.png"; + QTest::newRow("existing icon") << QStringLiteral("text-plain") << QStringLiteral("text-plain.png"); + QTest::newRow("octet-stream icon") << QStringLiteral("application-octet-stream") << QStringLiteral("application-octet-stream.png"); + QTest::newRow("non-existing icon") << QStringLiteral("foo-bar") << QStringLiteral("application-octet-stream.png"); // Test this again, because now we won't go into the "fast path" of loadMimeTypeIcon anymore. - QTest::newRow("existing icon again") << "text-plain" << "text-plain.png"; - QTest::newRow("generic fallback") << "image-foo-bar" << "image-x-generic.png"; - QTest::newRow("video generic fallback") << "video-foo-bar" << "video-x-generic.png"; - QTest::newRow("image-x-generic itself") << "image-x-generic" << "image-x-generic.png"; - QTest::newRow("x-office-document icon") << "x-office-document" << "x-office-document.png"; - QTest::newRow("unavailable generic icon") << "application/x-font-vfont" << "application-octet-stream.png"; - QTest::newRow("#184852") << "audio/x-tuxguitar" << "audio-x-generic.png"; - QTest::newRow("#178847") << "image/x-compressed-xcf" << "image-x-generic.png"; - QTest::newRow("mimetype generic icon") << "application-x-fluid" << "x-office-document.png"; + QTest::newRow("existing icon again") << QStringLiteral("text-plain") << QStringLiteral("text-plain.png"); + QTest::newRow("generic fallback") << QStringLiteral("image-foo-bar") << QStringLiteral("image-x-generic.png"); + QTest::newRow("video generic fallback") << QStringLiteral("video-foo-bar") << QStringLiteral("video-x-generic.png"); + QTest::newRow("image-x-generic itself") << QStringLiteral("image-x-generic") << QStringLiteral("image-x-generic.png"); + QTest::newRow("x-office-document icon") << QStringLiteral("x-office-document") << QStringLiteral("x-office-document.png"); + QTest::newRow("unavailable generic icon") << QStringLiteral("application/x-font-vfont") << QStringLiteral("application-octet-stream.png"); + QTest::newRow("#184852") << QStringLiteral("audio/x-tuxguitar") << QStringLiteral("audio-x-generic.png"); + QTest::newRow("#178847") << QStringLiteral("image/x-compressed-xcf") << QStringLiteral("image-x-generic.png"); + QTest::newRow("mimetype generic icon") << QStringLiteral("application-x-fluid") << QStringLiteral("x-office-document.png"); } void testLoadMimeTypeIcon() { QFETCH(QString, iconName); QFETCH(QString, expectedFileName); KIconLoader iconLoader; QString path; QPixmap pix = iconLoader.loadMimeTypeIcon(iconName, KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path); QVERIFY(!pix.isNull()); - QCOMPARE(path.section('/', -1), expectedFileName); + QCOMPARE(path.section(QLatin1Char('/'), -1), expectedFileName); // do the same test using a global iconloader, so that // we get into the final return statement, which can only happen // if d->extraDesktopIconsLoaded becomes true first.... QString path2; pix = KIconLoader::global()->loadMimeTypeIcon(iconName, KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path2); QVERIFY(!pix.isNull()); QCOMPARE(path2, path); } void testHasIcon() { // Do everything twice to check code paths that might use a cache - QVERIFY(KIconLoader::global()->hasIcon("kde")); - QVERIFY(KIconLoader::global()->hasIcon("kde")); + QVERIFY(KIconLoader::global()->hasIcon(QStringLiteral("kde"))); + QVERIFY(KIconLoader::global()->hasIcon(QStringLiteral("kde"))); KIconLoader iconLoader; - QVERIFY(iconLoader.hasIcon("kde")); + QVERIFY(iconLoader.hasIcon(QStringLiteral("kde"))); - QVERIFY(KIconLoader::global()->hasIcon("process-working")); - QVERIFY(KIconLoader::global()->hasIcon("process-working")); - QVERIFY(!KIconLoader::global()->hasIcon("no-such-icon-exists")); - QVERIFY(!KIconLoader::global()->hasIcon("no-such-icon-exists")); + QVERIFY(KIconLoader::global()->hasIcon(QStringLiteral("process-working"))); + QVERIFY(KIconLoader::global()->hasIcon(QStringLiteral("process-working"))); + QVERIFY(!KIconLoader::global()->hasIcon(QStringLiteral("no-such-icon-exists"))); + QVERIFY(!KIconLoader::global()->hasIcon(QStringLiteral("no-such-icon-exists"))); } void testIconPath() { // Test iconPath with non-existing icon const QString path = KIconLoader::global()->iconPath(QStringLiteral("nope-no-such-icon"), KIconLoader::Desktop, true /*canReturnNull*/); QVERIFY2(path.isEmpty(), qPrintable(path)); const QString unknownPath = KIconLoader::global()->iconPath(QStringLiteral("nope-no-such-icon"), KIconLoader::Desktop, false); QVERIFY(!unknownPath.isEmpty()); QVERIFY(QFile::exists(unknownPath)); } void testPathStore() { QString path; QPixmap pix = KIconLoader::global()->loadIcon(QStringLiteral("kde"), KIconLoader::Desktop, 0, KIconLoader::DefaultState, QStringList(), &path); QVERIFY(!path.isEmpty()); QVERIFY(QFile::exists(path)); - QVERIFY2(path.contains("32x32"), qPrintable(path)); + QVERIFY2(path.contains(QStringLiteral("32x32")), qPrintable(path)); QCOMPARE(pix.size(), QSize(32, 32)); // Compare with iconPath() QString path2 = KIconLoader::global()->iconPath(QStringLiteral("kde"), KIconLoader::Desktop); QCOMPARE(path2, path); // Now specify a size pix = KIconLoader::global()->loadIcon(QStringLiteral("kde"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path); QVERIFY(!path.isEmpty()); QVERIFY(QFile::exists(path)); - QVERIFY2(path.contains("22x22"), qPrintable(path)); + QVERIFY2(path.contains(QStringLiteral("22x22")), qPrintable(path)); QCOMPARE(pix.size(), QSize(24, 24)); - QVERIFY(KIconLoader::global()->hasIcon("kde")); + QVERIFY(KIconLoader::global()->hasIcon(QStringLiteral("kde"))); path = QString(); KIconLoader::global()->loadIcon(QStringLiteral("does_not_exist"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path, true /* canReturnNull */); QVERIFY2(path.isEmpty(), qPrintable(path)); path = QStringLiteral("some filler to check loadIcon() clears the variable"); KIconLoader::global()->loadIcon(QStringLiteral("does_not_exist"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path, true /* canReturnNull */); QVERIFY2(path.isEmpty(), qPrintable(path)); //Test that addAppDir doesn't break loading of icons from the old known paths KIconLoader loader; //only addAppDir loader.addAppDir(QStringLiteral("kiconloader_unittest")); path = QString(); loader.loadIcon(QStringLiteral("kde"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path); QVERIFY(!path.isEmpty()); path = QString(); loader.loadIcon(QStringLiteral("image1"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path); QVERIFY(!path.isEmpty()); //only reconfigure KIconLoader loader2; path = QString(); loader2.reconfigure(QStringLiteral("kiconloader_unittest")); loader2.loadIcon(QStringLiteral("kde"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path); QVERIFY(!path.isEmpty()); loader2.loadIcon(QStringLiteral("image1"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path); QVERIFY(!path.isEmpty()); //both addAppDir and reconfigure KIconLoader loader3; path = QString(); loader3.addAppDir(QStringLiteral("kiconloader_unittest")); loader3.reconfigure(QStringLiteral("kiconloader_unittest")); loader3.loadIcon(QStringLiteral("kde"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path); QVERIFY(!path.isEmpty()); path = QString(); loader3.loadIcon(QStringLiteral("image1"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path); QVERIFY(!path.isEmpty()); } void testPathsNoContextType() { { QString path; KIconLoader::global()->loadIcon(QStringLiteral("iconindirectorywithoutcontext"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path); - QVERIFY(path.endsWith("appsNoContext/iconindirectorywithoutcontext.png")); + QVERIFY(path.endsWith(QLatin1String("appsNoContext/iconindirectorywithoutcontext.png"))); } { QString path; KIconLoader::global()->loadIcon(QStringLiteral("iconindirectorywithouttype"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path); - QVERIFY(path.endsWith("appsNoType/iconindirectorywithouttype.png")); + QVERIFY(path.endsWith(QLatin1String("appsNoType/iconindirectorywithouttype.png"))); } { QString path; KIconLoader::global()->loadIcon(QStringLiteral("iconindirectorywithoutcontextortype"), KIconLoader::Desktop, 24, KIconLoader::DefaultState, QStringList(), &path); - QVERIFY(path.endsWith("appsNoContextOrType/iconindirectorywithoutcontextortype.png")); + QVERIFY(path.endsWith(QLatin1String("appsNoContextOrType/iconindirectorywithoutcontextortype.png"))); } } void testLoadIconNoGroupOrSize() // #246016 { QPixmap pix = KIconLoader::global()->loadIcon(QStringLiteral("connected"), KIconLoader::NoGroup); QVERIFY(!pix.isNull()); } void testLoadPixmapSequence() { KPixmapSequence seq = KIconLoader::global()->loadPixmapSequence(QStringLiteral("process-working"), 22); QVERIFY(seq.isValid()); } void testAppropriateSizes() { const KIconLoader iconLoader; const QRegularExpression rx(QStringLiteral("/(\\d+)x\\d+/")); for(int i=1; i= i) { ts = curr; break; } } QVERIFY(ts == foundSize); } } void testColoredSvgIcon() { QPalette pal = qApp->palette(); pal.setColor(QPalette::WindowText, QColor(255, 0, 0)); qApp->setPalette(pal); QImage img = KIconLoader::global()->loadIcon(QStringLiteral("coloredsvgicon"), KIconLoader::NoGroup).toImage(); QVERIFY(!img.isNull()); //Has the image been recolored to red, //that is the color we wrote in kdeglobals as text color? QCOMPARE(img.pixel(0,0), (uint)4294901760); } void testUintToHex() { // HEX (ARGB format without the #): ff6496c8 QColor testColorNoAlpha(100, 150, 200); // The ARGB string in which the composed hex value is stored. QString argbHex(8, Qt::Uninitialized); // Verify the ARGB hex (ff6496c8) uintToHex(testColorNoAlpha.rgba(), argbHex.data()); - QCOMPARE(argbHex, QString("ff6496c8")); + QCOMPARE(argbHex, QStringLiteral("ff6496c8")); // HEX (ARGB format without the #): 7b6496c8 QColor testColorWithAlpha(100, 150, 200, 123); // Test uintToHex to verify its ARGB output. uintToHex(testColorWithAlpha.rgba(), argbHex.data()); - QCOMPARE(argbHex, QString("7b6496c8")); + QCOMPARE(argbHex, QStringLiteral("7b6496c8")); } }; QTEST_MAIN(KIconLoader_UnitTest) #include "kiconloader_unittest.moc" diff --git a/src/kicondialog.cpp b/src/kicondialog.cpp index fa09f20..1f4193e 100644 --- a/src/kicondialog.cpp +++ b/src/kicondialog.cpp @@ -1,664 +1,664 @@ /* vi: ts=8 sts=4 sw=4 * * This file is part of the KDE project, module kfile. * Copyright (C) 2000 Geert Jansen * (C) 2000 Kurt Granroth * (C) 1997 Christoph Neerfeld * (C) 2002 Carsten Pfeiffer * * This is free software; it comes under the GNU Library General * Public License, version 2. See the file "COPYING.LIB" for the * exact licensing terms. */ #include "kicondialog.h" #include "kicondialog_p.h" #include #include #ifndef _WIN32_WCE #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * Qt allocates very little horizontal space for the icon name, * even if the gridSize width is large. This delegate allocates * the gridSize width (minus some padding) for the icon and icon name. */ class KIconCanvasDelegate : public QAbstractItemDelegate { public: KIconCanvasDelegate(KIconCanvas *parent, QAbstractItemDelegate *defaultDelegate); ~KIconCanvasDelegate() override {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; private: KIconCanvas *m_iconCanvas = nullptr; QAbstractItemDelegate *m_defaultDelegate = nullptr; static const int HORIZONTAL_EDGE_PAD = 3; }; KIconCanvasDelegate::KIconCanvasDelegate(KIconCanvas *parent, QAbstractItemDelegate *defaultDelegate) : QAbstractItemDelegate(parent) { m_iconCanvas = parent; m_defaultDelegate = defaultDelegate; } void KIconCanvasDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { const int GRID_WIDTH = m_iconCanvas->gridSize().width(); QStyleOptionViewItem newOption = option; // Manipulate the width available. newOption.rect.setX((option.rect.x() / GRID_WIDTH) * GRID_WIDTH + HORIZONTAL_EDGE_PAD); newOption.rect.setWidth(GRID_WIDTH - 2 * HORIZONTAL_EDGE_PAD); m_defaultDelegate->paint(painter, newOption, index); } QSize KIconCanvasDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { QSize size = m_defaultDelegate->sizeHint(option, index); const int GRID_WIDTH = m_iconCanvas->gridSize().width(); size.setWidth(GRID_WIDTH - 2 * HORIZONTAL_EDGE_PAD); return size; } /* * KIconCanvas: Iconview for the iconloader dialog. */ KIconCanvas::KIconCanvas(QWidget *parent) : QListWidget(parent), m_loading(false), m_timer(new QTimer(this)), m_delegate(new KIconCanvasDelegate(this, itemDelegate())) { setViewMode(IconMode); setUniformItemSizes(true); setMovement(Static); setIconSize(QSize(60, 60)); connect(m_timer, SIGNAL(timeout()), this, SLOT(loadFiles())); connect(this, &QListWidget::currentItemChanged, this, &KIconCanvas::currentListItemChanged); setGridSize(QSize(100, 80)); setItemDelegate(m_delegate); } KIconCanvas::~KIconCanvas() { delete m_timer; delete m_delegate; } void KIconCanvas::loadFiles(const QStringList &files) { clear(); m_files = files; emit startLoading(m_files.count()); m_timer->setSingleShot(true); m_timer->start(10); m_loading = false; } void KIconCanvas::loadFiles() { setResizeMode(QListWidget::Fixed); QApplication::setOverrideCursor(Qt::WaitCursor); // disable updates to not trigger paint events when adding child items, // but force an initial paint so that we do not get garbage repaint(); setUpdatesEnabled(false); // Cache these as we will call them frequently. const int canvasIconWidth = iconSize().width(); const int canvasIconHeight = iconSize().width(); const bool uniformIconSize = uniformItemSizes(); m_loading = true; int i; QStringList::ConstIterator it; uint emitProgress = 10; // so we will emit it once in the beginning QStringList::ConstIterator end(m_files.constEnd()); for (it = m_files.constBegin(), i = 0; it != end; ++it, ++i) { if (emitProgress >= 10) { emit progress(i); emitProgress = 0; } emitProgress++; if (!m_loading) { // user clicked on a button that will load another set of icons break; } QImage img; // Use the extension as the format. Works for XPM and PNG, but not for SVG QString path = *it; QString ext = path.right(3).toUpper(); if (ext != QLatin1String("SVG") && ext != QLatin1String("VGZ")) { img.load(*it); } else { #ifndef _WIN32_WCE // Special stuff for SVG icons img = QImage(canvasIconWidth, canvasIconHeight, QImage::Format_ARGB32_Premultiplied); img.fill(0); QSvgRenderer renderer(*it); if (renderer.isValid()) { QPainter p(&img); renderer.render(&p); } #endif } if (img.isNull()) { continue; } if (img.width() > canvasIconWidth || img.height() > canvasIconHeight) { if (img.width() / (float)canvasIconWidth > img.height() / (float)canvasIconHeight) { int height = (int)(((float)canvasIconWidth / img.width()) * img.height()); img = img.scaled(canvasIconWidth, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } else { int width = (int)(((float)canvasIconHeight / img.height()) * img.width()); img = img.scaled(width, canvasIconHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } } if (uniformIconSize && (img.width() != canvasIconWidth || img.height() != canvasIconHeight)) { // Image is smaller than desired. Draw onto a transparent QImage of the required dimensions. // (Unpleasant glitches occur if we break the uniformIconSizes() contract). QImage paddedImage = QImage(canvasIconWidth, canvasIconHeight, QImage::Format_ARGB32_Premultiplied); paddedImage.fill(0); QPainter painter(&paddedImage); painter.drawImage((canvasIconWidth - img.width()) / 2, (canvasIconHeight - img.height()) / 2, img); img = paddedImage; } QPixmap pm = QPixmap::fromImage(img); QFileInfo fi(*it); QListWidgetItem *item = new QListWidgetItem(pm, fi.completeBaseName(), this); item->setData(Qt::UserRole, *it); item->setToolTip(fi.completeBaseName()); } // enable updates since we have to draw the whole view now setUpdatesEnabled(true); QApplication::restoreOverrideCursor(); m_loading = false; emit finished(); setResizeMode(QListWidget::Adjust); } QString KIconCanvas::getCurrent() const { if (!currentItem()) { return QString(); } return currentItem()->data(Qt::UserRole).toString(); } void KIconCanvas::stopLoading() { m_loading = false; } void KIconCanvas::currentListItemChanged(QListWidgetItem *item) { emit nameChanged((item != nullptr) ? item->text() : QString()); } // TODO KF6 remove and override KIconDialog::showEvent() class ShowEventFilter : public QObject { public: explicit ShowEventFilter(QObject *parent) : QObject(parent) {} ~ShowEventFilter() override {} private: bool eventFilter(QObject *watched, QEvent *event) override { if (event->type() == QEvent::Show) { KIconDialog *q = static_cast(parent()); q->d->showIcons(); q->d->searchLine->setFocus(); } return QObject::eventFilter(watched, event); } }; /* * KIconDialog: Dialog for selecting icons. Both system and user * specified icons can be chosen. */ KIconDialog::KIconDialog(QWidget *parent) : QDialog(parent), d(new KIconDialogPrivate(this)) { setModal(true); setWindowTitle(i18n("Select Icon")); d->mpLoader = KIconLoader::global(); d->init(); installEventFilter(new ShowEventFilter(this)); } KIconDialog::KIconDialog(KIconLoader *loader, QWidget *parent) : QDialog(parent), d(new KIconDialogPrivate(this)) { setModal(true); setWindowTitle(i18n("Select Icon")); d->mpLoader = loader; d->init(); installEventFilter(new ShowEventFilter(this)); } void KIconDialog::KIconDialogPrivate::init() { mGroupOrSize = KIconLoader::Desktop; mContext = KIconLoader::Any; QVBoxLayout *top = new QVBoxLayout; q->setLayout(top); QGroupBox *bgroup = new QGroupBox(q); bgroup->setTitle(i18n("Icon Source")); QVBoxLayout *vbox = new QVBoxLayout; bgroup->setLayout(vbox); top->addWidget(bgroup); QGridLayout *grid = new QGridLayout(); vbox->addLayout(grid); mpSystemIcons = new QRadioButton(i18n("S&ystem icons:"), bgroup); connect(mpSystemIcons, SIGNAL(clicked()), q, SLOT(_k_slotSystemIconClicked())); grid->addWidget(mpSystemIcons, 1, 0); mpCombo = new QComboBox(bgroup); connect(mpCombo, SIGNAL(activated(int)), q, SLOT(_k_slotContext(int))); grid->addWidget(mpCombo, 1, 1); mpOtherIcons = new QRadioButton(i18n("O&ther icons:"), bgroup); connect(mpOtherIcons, SIGNAL(clicked()), q, SLOT(_k_slotOtherIconClicked())); grid->addWidget(mpOtherIcons, 2, 0); mpBrowseBut = new QPushButton(i18n("&Browse..."), bgroup); connect(mpBrowseBut, SIGNAL(clicked()), q, SLOT(_k_slotBrowse())); grid->addWidget(mpBrowseBut, 2, 1); // // ADD SEARCHLINE // QHBoxLayout *searchLayout = new QHBoxLayout(); searchLayout->setMargin(0); top->addLayout(searchLayout); QLabel *searchLabel = new QLabel(i18n("&Search:"), q); searchLayout->addWidget(searchLabel); searchLine = new KListWidgetSearchLine(q); searchLayout->addWidget(searchLine); searchLabel->setBuddy(searchLine); QString wtstr = i18n("Search interactively for icon names (e.g. folder)."); searchLabel->setWhatsThis(wtstr); searchLine->setWhatsThis(wtstr); mpCanvas = new KIconCanvas(q); connect(mpCanvas, SIGNAL(itemActivated(QListWidgetItem*)), q, SLOT(_k_slotAcceptIcons())); top->addWidget(mpCanvas); searchLine->setListWidget(mpCanvas); // Compute width of canvas with 4 icons displayed in a row QStyleOption opt; opt.initFrom(mpCanvas); int width = 4 * mpCanvas->gridSize().width() + 1; width += mpCanvas->verticalScrollBar()->sizeHint().width(); width += 2 * mpCanvas->frameWidth(); if (mpCanvas->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, mpCanvas)) { width += mpCanvas->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, mpCanvas); } mpCanvas->setMinimumSize(width, 125); mpProgress = new QProgressBar(q); top->addWidget(mpProgress); connect(mpCanvas, SIGNAL(startLoading(int)), q, SLOT(_k_slotStartLoading(int))); connect(mpCanvas, SIGNAL(progress(int)), q, SLOT(_k_slotProgress(int))); connect(mpCanvas, SIGNAL(finished()), q, SLOT(_k_slotFinished())); // When pressing Ok or Cancel, stop loading icons connect(q, &QDialog::finished, mpCanvas, &KIconCanvas::stopLoading); static const char *const context_text[] = { I18N_NOOP("Actions"), I18N_NOOP("Applications"), I18N_NOOP("Categories"), I18N_NOOP("Devices"), I18N_NOOP("Emblems"), I18N_NOOP("Emotes"), I18N_NOOP("Mimetypes"), I18N_NOOP("Places"), I18N_NOOP("Status"), I18N_NOOP("All") }; static const KIconLoader::Context context_id[] = { KIconLoader::Action, KIconLoader::Application, KIconLoader::Category, KIconLoader::Device, KIconLoader::Emblem, KIconLoader::Emote, KIconLoader::MimeType, KIconLoader::Place, KIconLoader::StatusIcon, KIconLoader::Any }; mNumContext = 0; int cnt = sizeof(context_text) / sizeof(context_text[ 0 ]); // check all 3 arrays have same sizes Q_ASSERT(cnt == sizeof(context_id) / sizeof(context_id[ 0 ]) && cnt == sizeof(mContextMap) / sizeof(mContextMap[ 0 ])); for (int i = 0; i < cnt; ++i) { if (mpLoader->hasContext(context_id[ i ])) { mpCombo->addItem(i18n(context_text[ i ])); mContextMap[ mNumContext++ ] = context_id[ i ]; } } mpCombo->setMaxVisibleItems(cnt); mpCombo->setFixedSize(mpCombo->sizeHint()); mpBrowseBut->setFixedWidth(mpCombo->width()); QDialogButtonBox *buttonBox = new QDialogButtonBox(q); buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, &QDialogButtonBox::accepted, q, &KIconDialog::slotOk); connect(buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject); top->addWidget(buttonBox); // Make the dialog a little taller q->resize(q->sizeHint() + QSize(0, 100)); q->adjustSize(); } KIconDialog::~KIconDialog() { delete d; } void KIconDialog::KIconDialogPrivate::_k_slotAcceptIcons() { custom.clear(); q->slotOk(); } static bool sortByFileName(const QString &path1, const QString &path2) { const QString fileName1 = path1.mid(path1.lastIndexOf(QLatin1Char('/')) + 1); const QString fileName2 = path2.mid(path1.lastIndexOf(QLatin1Char('/')) + 1); return QString::compare(fileName1, fileName2, Qt::CaseInsensitive) < 0; } void KIconDialog::KIconDialogPrivate::showIcons() { mpCanvas->clear(); QStringList filelist; if (mpSystemIcons->isChecked()) { if (m_bStrictIconSize) { filelist = mpLoader->queryIcons(mGroupOrSize, mContext); } else { filelist = mpLoader->queryIconsByContext(mGroupOrSize, mContext); } } else if (!customLocation.isEmpty()) { filelist = mpLoader->queryIconsByDir(customLocation); } else { // List PNG files found directly in the kiconload search paths. Q_FOREACH (const QString &relDir, KIconLoader::global()->searchPaths()) { const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, relDir, QStandardPaths::LocateDirectory); for (const QString &dir : dirs) { Q_FOREACH (const QString &fileName, QDir(dir).entryList(QStringList() << QLatin1String("*.png"))) { filelist << dir + QLatin1Char('/') + fileName; } } } } - qSort(filelist.begin(), filelist.end(), sortByFileName); + std::sort(filelist.begin(), filelist.end(), sortByFileName); // The KIconCanvas has uniformItemSizes set which really expects // all added icons to be the same size, otherwise weirdness ensues :) // Ensure all SVGs are scaled to the desired size and that as few icons // need to be padded as possible by specifying a sensible size. if (mGroupOrSize < -1) { // mGroupOrSize can be -1 if NoGroup is chosen. // Explicit size. mpCanvas->setIconSize(QSize(-mGroupOrSize, -mGroupOrSize)); } else { // Icon group. int groupSize = mpLoader->currentSize((KIconLoader::Group)mGroupOrSize); mpCanvas->setIconSize(QSize(groupSize, groupSize)); } mpCanvas->loadFiles(filelist); } void KIconDialog::setStrictIconSize(bool b) { d->m_bStrictIconSize = b; } bool KIconDialog::strictIconSize() const { return d->m_bStrictIconSize; } void KIconDialog::setIconSize(int size) { // see KIconLoader, if you think this is weird if (size == 0) { d->mGroupOrSize = KIconLoader::Desktop; // default Group } else { d->mGroupOrSize = -size; // yes, KIconLoader::queryIconsByContext is weird } } int KIconDialog::iconSize() const { // 0 or any other value ==> mGroupOrSize is a group, so we return 0 return (d->mGroupOrSize < 0) ? -d->mGroupOrSize : 0; } void KIconDialog::setup(KIconLoader::Group group, KIconLoader::Context context, bool strictIconSize, int iconSize, bool user, bool lockUser, bool lockCustomDir) { d->m_bStrictIconSize = strictIconSize; d->m_bLockUser = lockUser; d->m_bLockCustomDir = lockCustomDir; if (iconSize == 0) { if (group == KIconLoader::NoGroup) { // NoGroup has numeric value -1, which should // not really be used with KIconLoader::queryIcons*(...); // pick a proper group. d->mGroupOrSize = KIconLoader::Small; } else { d->mGroupOrSize = group; } } else { d->mGroupOrSize = -iconSize; } d->mpSystemIcons->setChecked(!user); d->mpSystemIcons->setEnabled(!lockUser || !user); d->mpOtherIcons->setChecked(user); d->mpOtherIcons->setEnabled(!lockUser || user); d->mpCombo->setEnabled(!user); d->mpBrowseBut->setEnabled(user && !lockCustomDir); d->setContext(context); } void KIconDialog::KIconDialogPrivate::setContext(KIconLoader::Context context) { mContext = context; for (int i = 0; i < mNumContext; ++i) { if (mContextMap[ i ] == context) { mpCombo->setCurrentIndex(i); return; } } } void KIconDialog::setCustomLocation(const QString &location) { d->customLocation = location; } QString KIconDialog::openDialog() { if (exec() == Accepted) { if (!d->custom.isEmpty()) { return d->custom; } const QString name = d->mpCanvas->getCurrent(); if (name.isEmpty() || d->mpOtherIcons->isChecked()) { return name; } QFileInfo fi(name); return fi.completeBaseName(); } return QString(); } void KIconDialog::showDialog() { setModal(false); show(); } void KIconDialog::slotOk() { QString name; if (!d->custom.isEmpty()) { name = d->custom; } else { name = d->mpCanvas->getCurrent(); if (!name.isEmpty() && d->mpSystemIcons->isChecked()) { const QFileInfo fi(name); name = fi.completeBaseName(); } } emit newIconName(name); QDialog::accept(); } QString KIconDialog::getIcon(KIconLoader::Group group, KIconLoader::Context context, bool strictIconSize, int iconSize, bool user, QWidget *parent, const QString &caption) { KIconDialog dlg(parent); dlg.setup(group, context, strictIconSize, iconSize, user); if (!caption.isEmpty()) { dlg.setWindowTitle(caption); } return dlg.openDialog(); } void KIconDialog::KIconDialogPrivate::_k_slotBrowse() { if (browseDialog) { browseDialog.data()->show(); browseDialog.data()->raise(); return; } // Create a file dialog to select an ICO, PNG, XPM or SVG file, // with the image previewer shown. QFileDialog *dlg = new QFileDialog(q, i18n("Select Icon"), QString(), i18n("*.ico *.png *.xpm *.svg *.svgz|Icon Files (*.ico *.png *.xpm *.svg *.svgz)")); dlg->setModal(false); dlg->setFileMode(QFileDialog::ExistingFile); connect(dlg, SIGNAL(fileSelected(QString)), q, SLOT(_k_customFileSelected(QString))); browseDialog = dlg; dlg->show(); } void KIconDialog::KIconDialogPrivate::_k_customFileSelected(const QString &path) { if (!path.isEmpty()) { custom = path; if (mpSystemIcons->isChecked()) { customLocation = QFileInfo(custom).absolutePath(); } q->slotOk(); } } void KIconDialog::KIconDialogPrivate::_k_slotSystemIconClicked() { mpBrowseBut->setEnabled(false); mpCombo->setEnabled(true); showIcons(); } void KIconDialog::KIconDialogPrivate::_k_slotOtherIconClicked() { mpBrowseBut->setEnabled(!m_bLockCustomDir); mpCombo->setEnabled(false); showIcons(); } void KIconDialog::KIconDialogPrivate::_k_slotContext(int id) { mContext = static_cast(mContextMap[ id ]); showIcons(); } void KIconDialog::KIconDialogPrivate::_k_slotStartLoading(int steps) { if (steps < 10) { mpProgress->hide(); } else { mNumOfSteps = steps; mpProgress->setValue(0); mpProgress->show(); } } void KIconDialog::KIconDialogPrivate::_k_slotProgress(int p) { mpProgress->setValue(static_cast(100.0 * (double)p / (double)mNumOfSteps)); } void KIconDialog::KIconDialogPrivate::_k_slotFinished() { mNumOfSteps = 1; mpProgress->hide(); } #include "moc_kicondialog.cpp" #include "moc_kicondialog_p.cpp" diff --git a/src/tools/kiconfinder/kiconfinder.cpp b/src/tools/kiconfinder/kiconfinder.cpp index 54072e2..9844c8c 100644 --- a/src/tools/kiconfinder/kiconfinder.cpp +++ b/src/tools/kiconfinder/kiconfinder.cpp @@ -1,52 +1,52 @@ /* This file is part of the KDE project Copyright (C) 2008 David Faure This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or ( at your option ) version 3 or, at the discretion of KDE e.V. ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include <../kiconthemes_version.h> #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); app.setApplicationName(QStringLiteral("kiconfinder")); - app.setApplicationVersion(KICONTHEMES_VERSION_STRING); + app.setApplicationVersion(QLatin1String(KICONTHEMES_VERSION_STRING)); QCommandLineParser parser; parser.setApplicationDescription(app.translate("main", "Finds an icon based on its name")); parser.addPositionalArgument(QStringLiteral("iconname"), app.translate("main", "The icon name to look for")); parser.addHelpOption(); parser.process(app); if(parser.positionalArguments().isEmpty()) parser.showHelp(); Q_FOREACH(const QString& iconName, parser.positionalArguments()) { const QString icon = KIconLoader::global()->iconPath(iconName, KIconLoader::Desktop /*TODO configurable*/, true); if ( !icon.isEmpty() ) { printf("%s\n", icon.toLocal8Bit().constData()); } else { return 1; // error } } return 0; }