diff --git a/krusader/BookMan/krbookmarkbutton.cpp b/krusader/BookMan/krbookmarkbutton.cpp --- a/krusader/BookMan/krbookmarkbutton.cpp +++ b/krusader/BookMan/krbookmarkbutton.cpp @@ -22,6 +22,7 @@ #include "krbookmarkbutton.h" #include "krbookmarkhandler.h" #include "../krglobal.h" +#include "../icon.h" // QtGui #include @@ -35,13 +36,13 @@ KrBookmarkButton::KrBookmarkButton(QWidget *parent): QToolButton(parent) { setAutoRaise(true); - setIcon(QIcon::fromTheme("bookmarks")); + setIcon(Icon("bookmarks")); setText(i18n("BookMan II")); setToolTip(i18n("BookMan II")); setPopupMode(QToolButton::InstantPopup); setAcceptDrops(false); - acmBookmarks = new KActionMenu(QIcon::fromTheme("bookmarks"), i18n("Bookmarks"), this); + acmBookmarks = new KActionMenu(Icon("bookmarks"), i18n("Bookmarks"), this); acmBookmarks->setDelayed(false); // TODO KF5 : explicit cast as QMenu doesn't have those methods //(acmBookmarks->menu())->setKeyboardShortcutsEnabled(true); diff --git a/krusader/CMakeLists.txt b/krusader/CMakeLists.txt --- a/krusader/CMakeLists.txt +++ b/krusader/CMakeLists.txt @@ -28,6 +28,7 @@ set(krusader_SRCS krglobal.cpp + icon.cpp actionsbase.cpp tabactions.cpp kractions.cpp diff --git a/krusader/GUI/dirhistorybutton.cpp b/krusader/GUI/dirhistorybutton.cpp --- a/krusader/GUI/dirhistorybutton.cpp +++ b/krusader/GUI/dirhistorybutton.cpp @@ -20,6 +20,7 @@ *****************************************************************************/ #include "dirhistorybutton.h" +#include "../icon.h" #include "../Panel/dirhistoryqueue.h" #include "../FileSystem/filesystem.h" @@ -37,7 +38,7 @@ DirHistoryButton::DirHistoryButton(DirHistoryQueue* hQ, QWidget *parent) : QToolButton(parent) { setAutoRaise(true); - setIcon(QIcon::fromTheme("chronometer")); + setIcon(Icon("chronometer")); setText(i18n("Open the folder history list")); setToolTip(i18n("Open the folder history list")); setPopupMode(QToolButton::InstantPopup); diff --git a/krusader/icon.h b/krusader/icon.h new file mode 100644 --- /dev/null +++ b/krusader/icon.h @@ -0,0 +1,16 @@ +// TODO: GPL header + +#ifndef ICON_H +#define ICON_H + +// QtGui +#include +#include + +class Icon : public QIcon +{ +public: + Icon(QString name); +}; + +#endif // ICON_H diff --git a/krusader/icon.cpp b/krusader/icon.cpp new file mode 100644 --- /dev/null +++ b/krusader/icon.cpp @@ -0,0 +1,69 @@ +// TODO: GPL header + +#include "icon.h" + +// TODO: qt component comments +#include +#include + + +class IconEngine : public QIconEngine +{ +public: + IconEngine(QString iconName, QIcon fallbackIcon) : _iconName(iconName), _fallbackIcon(fallbackIcon) + { + // TODO: fill from settings + _themeFallbackList << "breeze" << "oxygen"; + } + + virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override; + virtual QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override; + + virtual IconEngine *clone() const override + { + return new IconEngine(*this); + } + +private: + QString _iconName; + QStringList _themeFallbackList; + QIcon _fallbackIcon; +}; + +// TODO: use some neutral icon from resource file as a fallback +Icon::Icon(QString name) : QIcon(new IconEngine(name, QIcon::fromTheme("emblem-unreadable"))) +{ +} + +QPixmap IconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) +{ + // TODO: implement icon cache here as setThemeName invalidates Qt icon cache + // TODO: need to track system icon theme change and reset active theme name to system theme, invalidate Krusader icon cache + + if (QIcon::hasThemeIcon(_iconName)) + return QIcon::fromTheme(_iconName).pixmap(size, mode, state); + + QPixmap pixmap; + auto currentTheme = QIcon::themeName(); + for (auto fallbackThemeName : _themeFallbackList) { + QIcon::setThemeName(fallbackThemeName); + if (QIcon::hasThemeIcon(_iconName)) { + pixmap = QIcon::fromTheme(_iconName).pixmap(size, mode, state); + break; + } + } + QIcon::setThemeName(currentTheme); + + if (pixmap.isNull()) { + pixmap = _fallbackIcon.pixmap(size, mode, state); + } + + return pixmap; +} + +void IconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) +{ + QSize pixmapSize = rect.size(); + QPixmap px = pixmap(pixmapSize, mode, state); + painter->drawPixmap(rect, px); +} diff --git a/krusader/krusader.cpp b/krusader/krusader.cpp --- a/krusader/krusader.cpp +++ b/krusader/krusader.cpp @@ -139,7 +139,6 @@ // create an icon loader krLoader = KIconLoader::global(); -// iconLoader->addExtraDesktopThemes(); // create MountMan KrGlobal::mountMan = new KMountMan(this); diff --git a/krusader/main.cpp b/krusader/main.cpp --- a/krusader/main.cpp +++ b/krusader/main.cpp @@ -91,39 +91,6 @@ int main(int argc, char *argv[]) { -// ============ begin icon-stuff =========== -// If the user has no icon specified over the commandline we set up our own. -// this is according to the users privileges. The icons are in Krusader::privIcon() - -/* bool hasIcon = false; - int i = 0; - char * myArgv[argc+2];*/ - -// if no --miniicon is given, --icon is used. So we don't need to check for --miniicon separately -/* for (i = 0; i < argc; ++i) { - if (strstr(argv[ i ], "-icon") != 0) // important: just one dash because both can appear! - hasIcon = true; - } - - static const char* const icon_text = "--icon"; - const char* icon_name = Krusader::privIcon(); - char addedParams[strlen(icon_text)+strlen(icon_name)+2]; - - if (! hasIcon) { - for (i = 0; i < argc; ++i) - myArgv[ i ] = argv[ i ]; - - strcpy(addedParams, icon_text); - strcpy(addedParams + strlen(icon_text) + 1, icon_name); - - myArgv[ argc ] = addedParams; - myArgv[ ++argc ] = addedParams + strlen(icon_text) + 1; - myArgv[ ++argc ] = 0; - - argv = myArgv; - }*/ -// ============ end icon-stuff =========== - // set global log message format qSetMessagePattern(KrServices::GLOBAL_MESSAGE_PATTERN); @@ -134,6 +101,12 @@ QApplication app(argc, argv); KLocalizedString::setApplicationDomain("krusader"); + // init icon theme + qDebug() << "System icon theme: " << QIcon::themeName(); + // [WORKAROUND] setThemeName sets user theme in QIconLoader and allows to avoid Qt issues with invalid icon caching later + // IMPORTANT: this must be done before the first QIcon::fromTheme call + QIcon::setThemeName(QIcon::themeName()); + // ABOUT data information #ifdef RELEASE_NAME QString versionName = QString("%1 \"%2\"").arg(VERSION).arg(RELEASE_NAME); @@ -326,8 +299,6 @@ fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); } - qDebug() << "Qt icon theme: " << QIcon::themeName(); - // catching SIGTERM, SIGHUP, SIGQUIT signal(SIGTERM, sigterm_handler); signal(SIGPIPE, sigterm_handler);