views: Use scene devicePixelRatio rather than qApp

When possible, use the devicePixelRatio from the scene which on Wayland
unlike the QApplication will properly support fractional scaling.

A KItemViewsUtils class is introduced that can be reused elsewhere.
This commit is contained in:
Kai Uwe Broulik 2023-11-20 14:16:18 +01:00
parent 26adfe689a
commit ecd3675aaa
7 changed files with 63 additions and 14 deletions

View file

@ -83,6 +83,7 @@ target_sources(dolphinprivate PRIVATE
kitemviews/private/kitemlistsmoothscroller.cpp kitemviews/private/kitemlistsmoothscroller.cpp
kitemviews/private/kitemlistviewanimation.cpp kitemviews/private/kitemlistviewanimation.cpp
kitemviews/private/kitemlistviewlayouter.cpp kitemviews/private/kitemlistviewlayouter.cpp
kitemviews/private/kitemviewsutils.cpp
kitemviews/private/kpixmapmodifier.cpp kitemviews/private/kpixmapmodifier.cpp
settings/applyviewpropsjob.cpp settings/applyviewpropsjob.cpp
settings/viewmodes/viewmodesettings.cpp settings/viewmodes/viewmodesettings.cpp

View file

@ -9,6 +9,7 @@
#include "kfileitemlistwidget.h" #include "kfileitemlistwidget.h"
#include "kfileitemmodel.h" #include "kfileitemmodel.h"
#include "kfileitemmodelrolesupdater.h" #include "kfileitemmodelrolesupdater.h"
#include "private/kitemviewsutils.h"
#include "private/kpixmapmodifier.h" #include "private/kpixmapmodifier.h"
#include <KIconLoader> #include <KIconLoader>
@ -157,7 +158,7 @@ QPixmap KFileItemListView::createDragPixmap(const KItemSet &indexes) const
yCount = xCount; yCount = xCount;
} }
const qreal dpr = scene()->views()[0]->devicePixelRatio(); const qreal dpr = KItemViewsUtils::devicePixelRatio(this);
// Draw the selected items into the grid cells. // Draw the selected items into the grid cells.
QPixmap dragPixmap(QSize(xCount * size + xCount, yCount * size + yCount) * dpr); QPixmap dragPixmap(QSize(xCount * size + xCount, yCount * size + yCount) * dpr);
dragPixmap.setDevicePixelRatio(dpr); dragPixmap.setDevicePixelRatio(dpr);
@ -255,6 +256,7 @@ void KFileItemListView::onModelChanged(KItemModelBase *current, KItemModelBase *
if (current) { if (current) {
m_modelRolesUpdater = new KFileItemModelRolesUpdater(static_cast<KFileItemModel *>(current), this); m_modelRolesUpdater = new KFileItemModelRolesUpdater(static_cast<KFileItemModel *>(current), this);
m_modelRolesUpdater->setIconSize(availableIconSize()); m_modelRolesUpdater->setIconSize(availableIconSize());
m_modelRolesUpdater->setDevicePixelRatio(KItemViewsUtils::devicePixelRatio(this));
applyRolesToModel(); applyRolesToModel();
} }
@ -414,6 +416,7 @@ void KFileItemListView::updateIconSize()
} }
m_modelRolesUpdater->setIconSize(availableIconSize()); m_modelRolesUpdater->setIconSize(availableIconSize());
m_modelRolesUpdater->setDevicePixelRatio(KItemViewsUtils::devicePixelRatio(this));
// Update the visible index range (which has most likely changed after the // Update the visible index range (which has most likely changed after the
// icon size change) before unpausing m_modelRolesUpdater. // icon size change) before unpausing m_modelRolesUpdater.

View file

@ -10,6 +10,7 @@
#include "kfileitemmodel.h" #include "kfileitemmodel.h"
#include "private/kfileitemclipboard.h" #include "private/kfileitemclipboard.h"
#include "private/kitemlistroleeditor.h" #include "private/kitemlistroleeditor.h"
#include "private/kitemviewsutils.h"
#include "private/kpixmapmodifier.h" #include "private/kpixmapmodifier.h"
#include <KIconEffect> #include <KIconEffect>
@ -965,6 +966,7 @@ void KStandardItemListWidget::updatePixmapCache()
const bool iconOnTop = (m_layout == IconsLayout); const bool iconOnTop = (m_layout == IconsLayout);
const KItemListStyleOption &option = styleOption(); const KItemListStyleOption &option = styleOption();
const qreal padding = option.padding; const qreal padding = option.padding;
const qreal dpr = KItemViewsUtils::devicePixelRatio(this);
const int widgetIconSize = iconSize(); const int widgetIconSize = iconSize();
const int maxIconWidth = iconOnTop ? widgetSize.width() - 2 * padding : widgetIconSize; const int maxIconWidth = iconOnTop ? widgetSize.width() - 2 * padding : widgetIconSize;
@ -1025,7 +1027,7 @@ void KStandardItemListWidget::updatePixmapCache()
} else if (m_pixmap.width() / m_pixmap.devicePixelRatio() != maxIconWidth || m_pixmap.height() / m_pixmap.devicePixelRatio() != maxIconHeight) { } else 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 // A custom pixmap has been applied. Assure that the pixmap
// is scaled to the maximum available size. // is scaled to the maximum available size.
KPixmapModifier::scale(m_pixmap, QSize(maxIconWidth, maxIconHeight) * qApp->devicePixelRatio()); KPixmapModifier::scale(m_pixmap, QSize(maxIconWidth, maxIconHeight) * dpr);
} }
if (m_pixmap.isNull()) { if (m_pixmap.isNull()) {
@ -1073,8 +1075,8 @@ void KStandardItemListWidget::updatePixmapCache()
const int maxScaledIconHeight = scaledIconSize; const int maxScaledIconHeight = scaledIconSize;
m_scaledPixmapSize = m_pixmap.size(); m_scaledPixmapSize = m_pixmap.size();
m_scaledPixmapSize.scale(maxScaledIconWidth * qApp->devicePixelRatio(), maxScaledIconHeight * qApp->devicePixelRatio(), Qt::KeepAspectRatio); m_scaledPixmapSize.scale(maxScaledIconWidth * dpr, maxScaledIconHeight * dpr, Qt::KeepAspectRatio);
m_scaledPixmapSize = m_scaledPixmapSize / qApp->devicePixelRatio(); m_scaledPixmapSize = m_scaledPixmapSize / dpr;
if (iconOnTop) { if (iconOnTop) {
// Center horizontally and align on bottom within the icon-area // Center horizontally and align on bottom within the icon-area
@ -1171,7 +1173,7 @@ void KStandardItemListWidget::updateTextsCache()
if (ratingSize.width() > availableWidth) { if (ratingSize.width() > availableWidth) {
ratingSize.rwidth() = availableWidth; ratingSize.rwidth() = availableWidth;
} }
const qreal dpr = qApp->devicePixelRatio(); const qreal dpr = KItemViewsUtils::devicePixelRatio(this);
m_rating = QPixmap(ratingSize.toSize() * dpr); m_rating = QPixmap(ratingSize.toSize() * dpr);
m_rating.setDevicePixelRatio(dpr); m_rating.setDevicePixelRatio(dpr);
m_rating.fill(Qt::transparent); m_rating.fill(Qt::transparent);
@ -1473,9 +1475,10 @@ void KStandardItemListWidget::updateAdditionalInfoTextColor()
void KStandardItemListWidget::drawPixmap(QPainter *painter, const QPixmap &pixmap) void KStandardItemListWidget::drawPixmap(QPainter *painter, const QPixmap &pixmap)
{ {
if (m_scaledPixmapSize != pixmap.size() / pixmap.devicePixelRatio()) { if (m_scaledPixmapSize != pixmap.size() / pixmap.devicePixelRatio()) {
const qreal dpr = KItemViewsUtils::devicePixelRatio(this);
QPixmap scaledPixmap = pixmap; QPixmap scaledPixmap = pixmap;
KPixmapModifier::scale(scaledPixmap, m_scaledPixmapSize * qApp->devicePixelRatio()); KPixmapModifier::scale(scaledPixmap, m_scaledPixmapSize * dpr);
scaledPixmap.setDevicePixelRatio(qApp->devicePixelRatio()); scaledPixmap.setDevicePixelRatio(dpr);
painter->drawPixmap(m_pixmapPos, scaledPixmap); painter->drawPixmap(m_pixmapPos, scaledPixmap);
#ifdef KSTANDARDITEMLISTWIDGET_DEBUG #ifdef KSTANDARDITEMLISTWIDGET_DEBUG
@ -1559,10 +1562,7 @@ void KStandardItemListWidget::closeRoleEditor()
QPixmap KStandardItemListWidget::pixmapForIcon(const QString &name, const QStringList &overlays, int size, QIcon::Mode mode) const QPixmap KStandardItemListWidget::pixmapForIcon(const QString &name, const QStringList &overlays, int size, QIcon::Mode mode) const
{ {
static const QIcon fallbackIcon = QIcon::fromTheme(QStringLiteral("unknown")); static const QIcon fallbackIcon = QIcon::fromTheme(QStringLiteral("unknown"));
qreal dpr = qApp->devicePixelRatio(); const qreal dpr = KItemViewsUtils::devicePixelRatio(this);
if (scene() && !scene()->views().isEmpty()) {
dpr = scene()->views().constFirst()->devicePixelRatioF();
}
size *= dpr; size *= dpr;

View file

@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2023 Kai Uwe Broulik <kde@broulik.de>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "kitemviewsutils.h"
#include <QApplication>
#include <QGraphicsItem>
#include <QGraphicsScene>
#include <QGraphicsView>
qreal KItemViewsUtils::devicePixelRatio(const QGraphicsItem *item)
{
qreal dpr = qApp->devicePixelRatio();
if (item->scene()) {
if (const auto views = item->scene()->views(); !views.isEmpty()) {
dpr = views.first()->devicePixelRatioF();
}
}
return dpr;
}

View file

@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: 2023 Kai Uwe Broulik <kde@broulik.de>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef KITEMVIEWSUTILS_H
#define KITEMVIEWSUTILS_H
#include <qtypes.h>
class QGraphicsItem;
class KItemViewsUtils
{
public:
static qreal devicePixelRatio(const QGraphicsItem *item);
};
#endif // KITEMVIEWSUTILS_H

View file

@ -5,6 +5,7 @@
*/ */
#include "dolphinfileitemlistwidget.h" #include "dolphinfileitemlistwidget.h"
#include "../kitemviews/private/kitemviewsutils.h"
#include "dolphindebug.h" #include "dolphindebug.h"
@ -77,7 +78,7 @@ void DolphinFileItemListWidget::refreshCache()
setTextColor(color); setTextColor(color);
} }
QPixmap DolphinFileItemListWidget::overlayForState(KVersionControlPlugin::ItemVersion version, int size) QPixmap DolphinFileItemListWidget::overlayForState(KVersionControlPlugin::ItemVersion version, int size) const
{ {
int overlayHeight = KIconLoader::SizeSmall; int overlayHeight = KIconLoader::SizeSmall;
if (size >= KIconLoader::SizeEnormous) { if (size >= KIconLoader::SizeEnormous) {
@ -122,7 +123,8 @@ QPixmap DolphinFileItemListWidget::overlayForState(KVersionControlPlugin::ItemVe
break; break;
} }
return QIcon::fromTheme(iconName).pixmap(QSize(overlayHeight, overlayHeight)); const qreal dpr = KItemViewsUtils::devicePixelRatio(this);
return QIcon::fromTheme(iconName).pixmap(QSize(overlayHeight, overlayHeight), dpr);
} }
#include "moc_dolphinfileitemlistwidget.cpp" #include "moc_dolphinfileitemlistwidget.cpp"

View file

@ -29,7 +29,7 @@ protected:
void refreshCache() override; void refreshCache() override;
private: private:
static QPixmap overlayForState(KVersionControlPlugin::ItemVersion version, int size); QPixmap overlayForState(KVersionControlPlugin::ItemVersion version, int size) const;
}; };
#endif #endif