[utilities/krusader] app/Panel/PanelView: Panel: render item icons in the row's effective foreground colour

Toni Asensi Esteve <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit b972812956b46080984fea6d3828fdf405459e81 by Toni Asensi Esteve, on behalf of Junker der Provinz.
Committed on 26/07/2026 at 22:28.
Pushed by asensi into branch 'master'.

Panel: render item icons in the row's effective foreground colour

The file-panel icons were rendered once and cached with no awareness of
the row colours from KrColorCache. With custom colours (Konfigurator ->
Colors) a light monochrome icon can sit on a light Marked/Current row
background and become illegible - the row TEXT follows the configured
colours, the icon never did. A per-row QIcon::Selected flip is not
possible here: the delegate strips State_Selected and the views use
NoSelection with an internal marked set, so the icon mode is always
Normal.

Instead, pass the row's effective foreground colour (the same one
computed for Qt::ForegroundRole) into KrView::getIcon and re-render
monochrome colour-scheme SVGs through KIconLoader::loadScaledIcon with
KIconColors(tint). Coloured SVGs and raster icons pass through
unchanged. The tint is skipped when the row colour equals the palette
text colour, so KDE-default setups render pixel-identically and keep
sharing the un-tinted pixmap-cache entries. Inactive-panel dimming
takes precedence over tinting so coloured icons keep their dim blend.
The tint colour is part of the QPixmapCache key; KrColorCache already
flushes QPixmapCache on colour-config changes.

M  +35   -4    app/Panel/PanelView/krview.cpp
M  +2    -2    app/Panel/PanelView/krview.h
M  +12   -1    app/Panel/PanelView/listmodel.cpp

https://invent.kde.org/utilities/krusader/-/commit/b972812956b46080984fea6d3828fdf405459e81

diff --git a/app/Panel/PanelView/krview.cpp b/app/Panel/PanelView/krview.cpp
index 5b447e463..951c777ae 100644
--- a/app/Panel/PanelView/krview.cpp
+++ b/app/Panel/PanelView/krview.cpp
@@ -37,9 +37,13 @@
 #include <QMimeType>
 #include <qnamespace.h>
 
+#include <KIconColors>
+#include <KIconLoader>
 #include <KLocalizedString>
 #include <KSharedConfig>
 
+#include <QGuiApplication>
+
 #define FILEITEM getFileItem()
 
 KrView *KrViewOperator::_changedView = nullptr;
@@ -307,7 +311,7 @@ QPixmap KrView::processIcon(const QPixmap &icon, bool dim, const QColor &dimColo
     return QPixmap::fromImage(dimmed, Qt::ColorOnly | Qt::ThresholdDither | Qt::ThresholdAlphaDither | Qt::NoOpaqueDetection);
 }
 
-QPixmap KrView::getIcon(FileItem *fileitem, bool active, int size /*, KRListItem::cmpColor color*/)
+QPixmap KrView::getIcon(FileItem *fileitem, bool active, int size, const QColor &iconTint /*, KRListItem::cmpColor color*/)
 {
     // KConfigGroup ag( krConfig, "Advanced");
     //////////////////////////////
@@ -321,6 +325,13 @@ QPixmap KrView::getIcon(FileItem *fileitem, bool active, int size /*, KRListItem
     QColor dimColor;
     int dimFactor;
     bool dim = !active && KrColorCache::getColorCache().getDimSettings(dimColor, dimFactor);
+    // Inactive-panel dimming takes precedence over tinting: the dim blend in
+    // processIcon must keep applying to coloured icons and previews-fallbacks
+    // too, so the tint is dropped for dimmed (inactive) panels rather than the
+    // other way around.
+    QColor tint = iconTint;
+    if (dim)
+        tint = QColor();
 
     if (iconName.isNull())
         iconName = "";
@@ -330,13 +341,33 @@ QPixmap KrView::getIcon(FileItem *fileitem, bool active, int size /*, KRListItem
         cacheName.append("LINK_");
     if (dim)
         cacheName.append("DIM_");
+    if (tint.isValid())
+        cacheName.append(QStringLiteral("TINT%1_").arg(tint.rgba(), 8, 16, QLatin1Char('0')));
     cacheName.append(iconName);
 
     // QPixmapCache::setCacheLimit( ag.readEntry("Icon Cache Size",_IconCacheSize) );
 
     // first try the cache
     if (!QPixmapCache::find(cacheName, &icon)) {
-        icon = processIcon(Icon(iconName, Icon("unknown")).pixmap(size), dim, dimColor, dimFactor, fileitem->isSymLink());
+        QPixmap base;
+        if (tint.isValid()) {
+            // Re-render monochrome (color-scheme stylesheet) SVG icons using the
+            // row's effective foreground colour, so the icon matches the text
+            // it sits next to (e.g. custom Marked/Current colours). Coloured
+            // SVGs and raster icons are returned unchanged by the loader.
+            base = KIconLoader::global()->loadScaledIcon(iconName.isEmpty() ? QStringLiteral("unknown") : iconName,
+                                                         KIconLoader::Desktop,
+                                                         qGuiApp->devicePixelRatio(),
+                                                         QSize(size, size),
+                                                         KIconLoader::DefaultState,
+                                                         QStringList(),
+                                                         nullptr,
+                                                         /*canReturnNull=*/true,
+                                                         KIconColors(tint));
+        }
+        if (base.isNull()) // no tint requested, or icon not found by KIconLoader
+            base = Icon(iconName, Icon("unknown")).pixmap(size);
+        icon = processIcon(base, dim, dimColor, dimFactor, fileitem->isSymLink());
         // insert it into the cache
         QPixmapCache::insert(cacheName, icon);
     }
@@ -344,14 +375,14 @@ QPixmap KrView::getIcon(FileItem *fileitem, bool active, int size /*, KRListItem
     return icon;
 }
 
-QPixmap KrView::getIcon(FileItem *fileitem)
+QPixmap KrView::getIcon(FileItem *fileitem, const QColor &iconTint)
 {
     if (_previews) {
         QPixmap icon;
         if (_previews->getPreview(fileitem, icon, _focused))
             return icon;
     }
-    return getIcon(fileitem, _focused, _fileIconSize);
+    return getIcon(fileitem, _focused, _fileIconSize, iconTint);
 }
 
 /**
diff --git a/app/Panel/PanelView/krview.h b/app/Panel/PanelView/krview.h
index d0b762e41..332cc879c 100644
--- a/app/Panel/PanelView/krview.h
+++ b/app/Panel/PanelView/krview.h
@@ -420,7 +420,7 @@ public:
         return _focused;
     }
 
-    QPixmap getIcon(FileItem *fileitem);
+    QPixmap getIcon(FileItem *fileitem, const QColor &iconTint = QColor());
 
     void setMainWindow(QWidget *mainWindow)
     {
@@ -448,7 +448,7 @@ public:
     // todo: what about selection modes ???
     virtual ~KrView();
 
-    static QPixmap getIcon(FileItem *fileitem, bool active, int size = 0);
+    static QPixmap getIcon(FileItem *fileitem, bool active, int size = 0, const QColor &iconTint = QColor());
     static QPixmap processIcon(const QPixmap &icon, bool dim, const QColor &dimColor, int dimFactor, bool symlink);
 
     // Get GUI strings for file item properties
diff --git a/app/Panel/PanelView/listmodel.cpp b/app/Panel/PanelView/listmodel.cpp
index 1a81fac9f..40728b385 100644
--- a/app/Panel/PanelView/listmodel.cpp
+++ b/app/Panel/PanelView/listmodel.cpp
@@ -19,6 +19,9 @@
 #include <KLocalizedString>
 #include <KSharedConfig>
 
+#include <QGuiApplication>
+#include <QPalette>
+
 ListModel::ListModel(KrInterView *view)
     : QAbstractListModel(nullptr)
     , _extensionEnabled(true)
@@ -180,7 +183,15 @@ QVariant ListModel::data(const QModelIndex &index, int role) const
             if (properties()->displayIcons) {
                 if (_justForSizeHint)
                     return QPixmap(_view->fileIconSize(), _view->fileIconSize());
-                return QIcon(_view->getIcon(fileitem));
+                // Tint monochrome icons to the row's effective foreground colour
+                // (normal/current/marked, as computed for Qt::ForegroundRole), so
+                // the icon stays legible on custom row colours. Skip the tint when
+                // the row colour is just the palette text colour: rendering is
+                // visually identical and the un-tinted cache entries stay shared.
+                QColor tint = data(index, Qt::ForegroundRole).value<QColor>();
+                if (tint == QGuiApplication::palette().color(QPalette::Active, QPalette::Text))
+                    tint = QColor();
+                return QIcon(_view->getIcon(fileitem, tint));
             }
             break;
         }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.