Index: autotests/CMakeLists.txt =================================================================== --- autotests/CMakeLists.txt +++ autotests/CMakeLists.txt @@ -17,3 +17,13 @@ kiconloader_benchmark kicontheme_unittest ) + +### Test for RCC loading + +get_target_property(QT_RCC_EXECUTABLE Qt5::rcc LOCATION) +add_custom_command(OUTPUT icontheme.rcc + COMMAND ${QT_RCC_EXECUTABLE} --binary -o icontheme.rcc ${CMAKE_CURRENT_SOURCE_DIR}/icontheme.qrc + DEPENDS icontheme.qrc +) +ecm_add_test(kiconloader_rcctest.cpp LINK_LIBRARIES Qt5::Test KF5::IconThemes KF5::WidgetsAddons KF5::ConfigCore) +add_custom_target(rcctest-rcc ALL DEPENDS icontheme.rcc) # a custom target that is always built Index: autotests/icontheme.qrc =================================================================== --- /dev/null +++ autotests/icontheme.qrc @@ -0,0 +1,6 @@ + + + tiny.theme + test-22x22.png + + Index: autotests/kiconloader_rcctest.cpp =================================================================== --- /dev/null +++ autotests/kiconloader_rcctest.cpp @@ -0,0 +1,86 @@ +/* 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 + +// 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); + qputenv("XDG_DATA_DIRS", "/doesnotexist"); // ensure hicolor/oxygen/breeze are not found + QFile rcc("icontheme.rcc"); + Q_ASSERT(rcc.exists()); + QCoreApplication::setApplicationName("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"; + 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 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 = "kf5_rcc_theme"; +}; + +QTEST_MAIN(KIconLoader_RCCThemeTest) + +#include "kiconloader_rcctest.moc" Index: autotests/tiny.theme =================================================================== --- /dev/null +++ autotests/tiny.theme @@ -0,0 +1,38 @@ +[Icon Theme] +Name=Tiny +Comment=Tiny icon theme +Hidden=false +Directories=22x22/actions,22x22/animations,22x22/apps,22x22/mimetypes,22x22/appsNoContext,22x22/appsNoType,22x22/appsNoContextOrType +Inherits=hicolor +FollowsColorScheme=true + +[22x22/actions] +Size=22 +Context=Actions +Type=Threshold + +[22x22/animations] +Size=22 +Context=Animations +Type=Threshold + +[22x22/apps] +Size=22 +Context=Applications +Type=Threshold + +[22x22/mimetypes] +Size=22 +Context=MimeTypes +Type=Threshold + +[22x22/appsNoContext] +Size=22 +Type=Threshold + +[22x22/appsNoType] +Size=22 +Context=MimeTypes + +[22x22/appsNoContextOrType] +Size=22 Index: src/kicontheme.cpp =================================================================== --- src/kicontheme.cpp +++ src/kicontheme.cpp @@ -25,19 +25,51 @@ #include +#include #include #include #include #include #include #include +#include #include // KLocalizedString::localizedFilePath. Need such functionality in, hmm, QLocale? QStandardPaths? #include #include +Q_GLOBAL_STATIC(QString, _themeOverride) + +// Support for icon themes in RCC files. +// The intended use case is standalone apps on Windows / MacOS / etc. +// For this reason we use AppDataLocation: BINDIR/data on Windows, Resources on OS X +void initRCCIconTheme() +{ + const QString iconThemeRcc = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("icontheme.rcc")); + if (!iconThemeRcc.isEmpty()) { + const QString iconThemeName = QStringLiteral("kf5_rcc_theme"); + const QString iconSubdir = QStringLiteral("/icons/") + iconThemeName; + if (QResource::registerResource(iconThemeRcc, iconSubdir)) { + if (QFileInfo::exists(QLatin1Char(':') + iconSubdir + QStringLiteral("/index.theme"))) { + // Tell Qt about the theme + // Note that since qtbase commit a8621a3f8, this means the QPA (i.e. KIconLoader) will NOT be used. + QIcon::setThemeName(iconThemeName); // Qt looks under :/icons automatically + // Tell KIconTheme about the theme, in case KIconLoader is used directly + *_themeOverride() = iconThemeName; + } else { + qWarning() << "No index.theme found in" << iconThemeRcc; + QResource::unregisterResource(iconThemeRcc, iconSubdir); + } + } else { + qWarning() << "Invalid rcc file" << iconThemeRcc; + } + } +} +Q_COREAPP_STARTUP_FUNCTION(initRCCIconTheme) + + class KIconTheme::KIconThemePrivate { public: @@ -56,7 +88,6 @@ QVector mDirs; bool followsColorScheme : 1; }; -Q_GLOBAL_STATIC(QString, _themeOverride) Q_GLOBAL_STATIC(QString, _theme) Q_GLOBAL_STATIC(QStringList, _theme_list)