#include "kstandarditemlistwidget.h"
#include "kfileitemlistview.h"
-#include "kfileitemmodel.h"
#include "private/kfileitemclipboard.h"
#include "private/kitemlistroleeditor.h"
#include "private/kitemviewsutils.h"
#include <KIconUtils>
#include <KRatingPainter>
#include <KStringHandler>
+#include <klocalizedstring.h>
#include <QApplication>
#include <QGraphicsScene>
drawSiblingsInformation(painter);
}
+ auto pixmap = isHovered() ? m_hoverPixmap : m_pixmap;
+ if (!m_overlays.isEmpty()) {
+ const qreal dpr = KItemViewsUtils::devicePixelRatio(this);
+
+ const bool iconOnTop = (m_layout == IconsLayout);
+ const KItemListStyleOption &option = styleOption();
+ const qreal padding = option.padding;
+
+ const int widgetIconSize = iconSize();
+ const int maxIconWidth = iconOnTop ? size().width() - 2 * padding : widgetIconSize;
+ const int maxIconHeight = widgetIconSize;
+
+ pixmap = addOverlays(pixmap, m_overlays, QSize(maxIconWidth, maxIconHeight), dpr);
+ }
+
const KItemListStyleOption &itemListStyleOption = styleOption();
- if (isHovered() && !m_pixmap.isNull()) {
+ if (isHovered() && !pixmap.isNull()) {
if (hoverOpacity() < 1.0) {
/*
- * Linear interpolation between m_pixmap and m_hoverPixmap.
+ * Linear interpolation between pixmap and m_hoverPixmap.
*
* Note that this cannot be achieved by painting m_hoverPixmap over
- * m_pixmap, even if the opacities are adjusted. For details see
+ * pixmap, even if the opacities are adjusted. For details see
* https://git.reviewboard.kde.org/r/109614/
*/
- // Paint pixmap1 so that pixmap1 = m_pixmap * (1.0 - hoverOpacity())
- QPixmap pixmap1(m_pixmap.size());
- pixmap1.setDevicePixelRatio(m_pixmap.devicePixelRatio());
+ // Paint pixmap1 so that pixmap1 = pixmap * (1.0 - hoverOpacity())
+ QPixmap pixmap1(pixmap.size());
+ pixmap1.setDevicePixelRatio(pixmap.devicePixelRatio());
pixmap1.fill(Qt::transparent);
{
QPainter p(&pixmap1);
p.setOpacity(1.0 - hoverOpacity());
- p.drawPixmap(0, 0, m_pixmap);
+ p.drawPixmap(0, 0, pixmap);
}
// Paint pixmap2 so that pixmap2 = m_hoverPixmap * hoverOpacity()
}
// Paint pixmap2 on pixmap1 using CompositionMode_Plus
- // Now pixmap1 = pixmap2 + m_pixmap * (1.0 - hoverOpacity())
- // = m_hoverPixmap * hoverOpacity() + m_pixmap * (1.0 - hoverOpacity())
+ // Now pixmap1 = pixmap2 + pixmap * (1.0 - hoverOpacity())
+ // = m_hoverPixmap * hoverOpacity() + pixmap * (1.0 - hoverOpacity())
{
QPainter p(&pixmap1);
p.setCompositionMode(QPainter::CompositionMode_Plus);
// Finally paint pixmap1 on the widget
drawPixmap(painter, pixmap1);
} else {
- drawPixmap(painter, m_hoverPixmap);
+ drawPixmap(painter, pixmap);
}
- } else if (!m_pixmap.isNull()) {
- drawPixmap(painter, m_pixmap);
+ } else if (!pixmap.isNull()) {
+ drawPixmap(painter, pixmap);
}
painter->setFont(m_customizedFont);
m_activateSoonAnimation->setEndValue(1.0);
m_activateSoonAnimation->setDuration(timeUntilActivation);
- const QVariant originalIconName{data()["iconName"]};
+ const QVariant originalIconName{value("iconName")};
connect(m_activateSoonAnimation, &QVariantAnimation::valueChanged, this, [originalIconName, this](const QVariant &value) {
auto progress = value.toFloat();
bool KStandardItemListWidget::isIconControlledByActivateSoonAnimation() const
{
- return m_activateSoonAnimation && data()["iconName"] == "folder-open";
+ return m_activateSoonAnimation && value("iconName") == "folder-open";
}
KItemListWidgetInformant *KStandardItemListWidget::createInformant()
{
m_dirtyContent = true;
m_dirtyContentRoles.insert("iconPixmap");
- m_dirtyContentRoles.insert("iconOverlays");
}
void KStandardItemListWidget::refreshCache()
// use a generic icon as fallback
iconName = QStringLiteral("unknown");
}
- const QStringList overlays = values["iconOverlays"].toStringList();
const bool hasFocus = scene()->views()[0]->parentWidget()->hasFocus();
m_pixmap = pixmapForIcon(iconName,
- m_overlays,
QSize(maxIconWidth, maxIconHeight),
m_layout != IconsLayout && isActiveWindow() && isSelected() && hasFocus ? QIcon::Selected : QIcon::Normal);
} else {
- if (!m_overlays.isEmpty()) {
- m_pixmap = addOverlays(m_pixmap, m_overlays, QSize(maxIconWidth, maxIconHeight), dpr);
- } else if (m_pixmap.width() / m_pixmap.devicePixelRatio() != maxIconWidth || m_pixmap.height() / m_pixmap.devicePixelRatio() != maxIconHeight) {
+ if (m_pixmap.width() / m_pixmap.devicePixelRatio() != maxIconWidth || m_pixmap.height() / m_pixmap.devicePixelRatio() != maxIconHeight) {
// A custom pixmap has been applied. Assure that the pixmap
// is scaled to the maximum available size.
KPixmapModifier::scale(m_pixmap, QSize(maxIconWidth, maxIconHeight) * dpr);
QColor((c1.red() * p1 + c2.red() * p2) / 100, (c1.green() * p1 + c2.green() * p2) / 100, (c1.blue() * p1 + c2.blue() * p2) / 100);
}
-QPixmap KStandardItemListWidget::addOverlays(const QPixmap &pixmap,
- const QHash<Qt::Corner, QString> &overlays,
- const QSize &size,
- qreal devicePixelRatioF,
- QIcon::Mode mode) const
+QPixmap
+KStandardItemListWidget::addOverlays(const QPixmap &pixmap, const QHash<Qt::Corner, QString> &overlays, const QSize &size, qreal dpr, QIcon::Mode mode) const
{
+ // similar to KIconUtils::addOverlays, keep in sync preferrably
if (overlays.isEmpty()) {
return pixmap;
}
- QHash<Qt::Corner, QIcon> overlayIcons;
+ int width = size.width();
+ int height = size.height();
+ const int iconSize = qMin(width, height);
+
+ // Determine the overlay icon
+ int overlaySize;
+ if (iconSize < 32) {
+ overlaySize = 8;
+ } else if (iconSize <= 48) {
+ overlaySize = 16;
+ } else if (iconSize <= 96) {
+ overlaySize = 22;
+ } else if (iconSize < 256) {
+ overlaySize = 32;
+ } else {
+ overlaySize = 64;
+ }
+
+ auto phyiscalSize = QSize(std::clamp(pixmap.width(), qFloor(2 * overlaySize * dpr), qFloor(size.width() * dpr)),
+ std::clamp(pixmap.height(), qFloor(2 * overlaySize * dpr), qFloor(size.height() * dpr)));
+
+ QPixmap output(phyiscalSize);
+ output.setDevicePixelRatio(dpr);
+ output.fill(Qt::transparent);
+ QPainter painter(&output);
+ painter.drawPixmap(qFloor(phyiscalSize.width() / dpr / 2) - qFloor(pixmap.width() / pixmap.devicePixelRatio() / 2),
+ // align the icon to the bottom to match the behavior elsewhere
+ qFloor(phyiscalSize.height() / dpr) - qFloor(pixmap.height() / pixmap.devicePixelRatio()),
+ pixmap);
+
+ width = qCeil(phyiscalSize.width() / dpr);
+ height = qCeil(phyiscalSize.height() / dpr);
+
+ // Iterate over stored overlays
for (const auto &[corner, overlay] : overlays.asKeyValueRange()) {
- overlayIcons.insert(corner, QIcon::fromTheme(overlay));
+ const QPixmap overlayPixmap = QIcon::fromTheme(overlay).pixmap(QSize{overlaySize, overlaySize}, dpr, mode);
+ if (overlayPixmap.isNull()) {
+ continue;
+ }
+
+ QPoint startPoint;
+ switch (corner) {
+ case Qt::BottomLeftCorner:
+ startPoint = QPoint{0, height - overlaySize};
+ break;
+ case Qt::BottomRightCorner:
+ startPoint = QPoint{width - overlaySize, height - overlaySize};
+ break;
+ case Qt::TopRightCorner:
+ startPoint = QPoint{width - overlaySize, 0};
+ break;
+ case Qt::TopLeftCorner:
+ startPoint = QPoint{};
+ break;
+ }
+ painter.drawPixmap(startPoint, overlayPixmap);
}
- return KIconUtils::addOverlays(pixmap, overlayIcons).pixmap(size, devicePixelRatioF, mode);
+ return output;
}
void KStandardItemListWidget::drawPixmap(QPainter *painter, const QPixmap &pixmap)
m_roleEditor = nullptr;
}
-QPixmap KStandardItemListWidget::pixmapForIcon(const QString &name, const QHash<Qt::Corner, QString> &overlays, const QSize &size, QIcon::Mode mode) const
+QPixmap KStandardItemListWidget::pixmapForIcon(const QString &name, const QSize &size, QIcon::Mode mode) const
{
static const QIcon fallbackIcon = QIcon::fromTheme(QStringLiteral("unknown"));
const qreal dpr = KItemViewsUtils::devicePixelRatio(this);
int iconHeight = size.height();
QSize iconSize = QSize(iconHeight, iconHeight);
- const QString key = "KStandardItemListWidget:" % name % ":" % overlays.values().join(QLatin1Char(':')) % ":" % QString::number(iconHeight) % "@"
- % QString::number(dpr) % ":" % QString::number(mode);
+ const QString key = "KStandardItemListWidget:" % name % ":" % QString::number(iconHeight) % "@" % QString::number(dpr) % ":" % QString::number(mode);
QPixmap pixmap;
if (!QPixmapCache::find(key, &pixmap)) {
KPixmapModifier::scale(pixmap, iconSize * dpr);
}
- pixmap = addOverlays(pixmap, overlays, size, dpr, mode);
-
QPixmapCache::insert(key, pixmap);
}
pixmap.setDevicePixelRatio(dpr);