Commit 968c411a authored by Alexander Volkov's avatar Alexander Volkov Committed by Nate Graham

Add HiDPI support for thumbnails

Summary:
The idea is to localize changes in ThumbnailView as much as possible:
ThumbnailView::thumbnailSize() returns the size in device independent
pixels, i.e. it seems from the outside that ThumbnailView behaves as
well as before this change. But, of course, item delegates must take
into account that ThumbnailView::thumbnailForIndex() will return
a pixmap with the devicePixelRatio set.

CCBUG: 373178

Reviewers: #gwenview, ngraham

Reviewed By: #gwenview, ngraham

Subscribers: ngraham

Tags: #gwenview

Differential Revision: https://phabricator.kde.org/D20267
parent 97e7de52
......@@ -164,7 +164,8 @@ struct PreviewItemDelegatePrivate
const int posX = mContextBarActions == PreviewItemDelegate::SelectionAction
? 0
: (rect.width() - mContextBar->width()) / 2;
const int posY = qMax(CONTEXTBAR_MARGIN, mThumbnailSize.height() - thumbnailPix.height() - mContextBar->height());
const int thumbnailPixHeight = qRound(thumbnailPix.height() / thumbnailPix.devicePixelRatio());
const int posY = qMax(CONTEXTBAR_MARGIN, mThumbnailSize.height() - thumbnailPixHeight - mContextBar->height());
mContextBar->move(rect.topLeft() + QPoint(posX, posY));
mContextBar->show();
}
......@@ -317,13 +318,15 @@ struct PreviewItemDelegatePrivate
{
const QPoint shadowOffset(-SHADOW_SIZE, -SHADOW_SIZE + 1);
int key = rect.height() * 1000 + rect.width();
const auto dpr = painter->device()->devicePixelRatioF();
int key = qRound((rect.height() * 1000 + rect.width()) * dpr);
ShadowCache::Iterator it = mShadowCache.find(key);
if (it == mShadowCache.end()) {
QSize size = QSize(rect.width() + 2 * SHADOW_SIZE, rect.height() + 2 * SHADOW_SIZE);
QColor color(0, 0, 0, SHADOW_STRENGTH);
QPixmap shadow = PaintUtils::generateFuzzyRect(size, color, SHADOW_SIZE);
QPixmap shadow = PaintUtils::generateFuzzyRect(size * dpr, color, qRound(SHADOW_SIZE * dpr));
shadow.setDevicePixelRatio(dpr);
it = mShadowCache.insert(key, shadow);
}
painter->drawPixmap(rect.topLeft() + shadowOffset, it.value());
......@@ -688,6 +691,7 @@ void PreviewItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem &
int thumbnailHeight = d->mThumbnailSize.height();
QSize fullSize;
QPixmap thumbnailPix = d->mView->thumbnailForIndex(index, &fullSize);
QSize thumbnailSize = thumbnailPix.size() / thumbnailPix.devicePixelRatio();
const KFileItem fileItem = fileItemForIndex(index);
const bool opaque = !thumbnailPix.hasAlphaChannel();
const bool isDirOrArchive = ArchiveUtils::fileItemIsDirOrArchive(fileItem);
......@@ -739,10 +743,10 @@ void PreviewItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem &
// Compute thumbnailRect
QRect thumbnailRect = QRect(
rect.left() + (rect.width() - thumbnailPix.width()) / 2,
rect.top() + (thumbnailHeight - thumbnailPix.height()) + ITEM_MARGIN,
thumbnailPix.width(),
thumbnailPix.height());
rect.left() + (rect.width() - thumbnailSize.width()) / 2,
rect.top() + (thumbnailHeight - thumbnailSize.height()) + ITEM_MARGIN,
thumbnailSize.width(),
thumbnailSize.height());
// Draw background
const QRect backgroundRect = thumbnailRect.adjusted(-ITEM_MARGIN, -ITEM_MARGIN, ITEM_MARGIN, ITEM_MARGIN);
......
......@@ -102,13 +102,15 @@ struct ThumbnailBarItemDelegatePrivate
{
const QPoint shadowOffset(-SHADOW_SIZE, -SHADOW_SIZE + 1);
int key = rect.height() * 1000 + rect.width();
const auto dpr = painter->device()->devicePixelRatioF();
int key = qRound((rect.height() * 1000 + rect.width()) * dpr);
ShadowCache::Iterator it = mShadowCache.find(key);
if (it == mShadowCache.end()) {
QSize size = QSize(rect.width() + 2 * SHADOW_SIZE, rect.height() + 2 * SHADOW_SIZE);
QColor color(0, 0, 0, SHADOW_STRENGTH);
QPixmap shadow = PaintUtils::generateFuzzyRect(size, color, SHADOW_SIZE);
QPixmap shadow = PaintUtils::generateFuzzyRect(size * dpr, color, qRound(SHADOW_SIZE * dpr));
shadow.setDevicePixelRatio(dpr);
it = mShadowCache.insert(key, shadow);
}
painter->drawPixmap(rect.topLeft() + shadowOffset, it.value());
......@@ -175,7 +177,7 @@ QSize ThumbnailBarItemDelegate::sizeHint(const QStyleOptionViewItem & /*option*/
size = d->mView->gridSize();
} else {
QPixmap thumbnailPix = d->mView->thumbnailForIndex(index);
size = thumbnailPix.size();
size = thumbnailPix.size() / thumbnailPix.devicePixelRatio();
size.rwidth() += ITEM_MARGIN * 2;
size.rheight() += ITEM_MARGIN * 2;
}
......@@ -203,6 +205,7 @@ void ThumbnailBarItemDelegate::paint(QPainter * painter, const QStyleOptionViewI
bool isSelected = option.state & QStyle::State_Selected;
bool isCurrent = d->mView->selectionModel()->currentIndex() == index;
QPixmap thumbnailPix = d->mView->thumbnailForIndex(index);
QSize thumbnailSize = thumbnailPix.size() / thumbnailPix.devicePixelRatio();
QRect rect = option.rect;
QStyleOptionViewItem opt = option;
......@@ -219,10 +222,10 @@ void ThumbnailBarItemDelegate::paint(QPainter * painter, const QStyleOptionViewI
// Draw thumbnail
if (!thumbnailPix.isNull()) {
QRect thumbnailRect = QRect(
rect.left() + (rect.width() - thumbnailPix.width()) / 2,
rect.top() + (rect.height() - thumbnailPix.height()) / 2 - 1,
thumbnailPix.width(),
thumbnailPix.height());
rect.left() + (rect.width() - thumbnailSize.width()) / 2,
rect.top() + (rect.height() - thumbnailSize.height()) / 2 - 1,
thumbnailSize.width(),
thumbnailSize.height());
if (!thumbnailPix.hasAlphaChannel()) {
d->drawShadow(painter, thumbnailRect);
......
......@@ -65,7 +65,7 @@ void ThumbnailSlider::slotActionTriggered(int actionTriggered)
void ThumbnailSlider::updateToolTip()
{
// FIXME: i18n?
const int size = slider()->sliderPosition();
const int size = qRound(slider()->sliderPosition() * devicePixelRatioF());
const QString text = QStringLiteral("%1 x %2").arg(size).arg(size);
slider()->setToolTip(text);
}
......
......@@ -379,11 +379,12 @@ void ThumbnailView::updateThumbnailSize()
{
QSize value = d->mThumbnailSize;
// mWaitingThumbnail
const auto dpr = devicePixelRatioF();
int waitingThumbnailSize;
if (value.width() > 64) {
waitingThumbnailSize = 48;
if (value.width() > 64 * dpr) {
waitingThumbnailSize = qRound(48 * dpr);
} else {
waitingThumbnailSize = 32;
waitingThumbnailSize = qRound(32 * dpr);
}
QPixmap icon = DesktopIcon(QStringLiteral("chronometer"), waitingThumbnailSize);
QPixmap pix(value);
......@@ -393,6 +394,7 @@ void ThumbnailView::updateThumbnailSize()
painter.drawPixmap((value.width() - icon.width()) / 2, (value.height() - icon.height()) / 2, icon);
painter.end();
d->mWaitingThumbnail = pix;
d->mWaitingThumbnail.setDevicePixelRatio(dpr);
// Stop smoothing
d->mSmoothThumbnailTimer.stop();
......@@ -406,8 +408,8 @@ void ThumbnailView::updateThumbnailSize()
it.value().mAdjustedPix = QPixmap();
}
emit thumbnailSizeChanged(value);
emit thumbnailWidthChanged(value.width());
emit thumbnailSizeChanged(value / dpr);
emit thumbnailWidthChanged(qRound(value.width() / dpr));
if (d->mScaleMode != ScaleToFit) {
scheduleDelayedItemsLayout();
}
......@@ -416,11 +418,14 @@ void ThumbnailView::updateThumbnailSize()
void ThumbnailView::setThumbnailWidth(int width)
{
if(d->mThumbnailSize.width() == width) {
const auto dpr = devicePixelRatioF();
const qreal newWidthF = width * dpr;
const int newWidth = qRound(newWidthF);
if(d->mThumbnailSize.width() == newWidth) {
return;
}
int height = round((qreal)width / d->mThumbnailAspectRatio);
d->mThumbnailSize = QSize(width, height);
int height = qRound(newWidthF / d->mThumbnailAspectRatio);
d->mThumbnailSize = QSize(newWidth, height);
updateThumbnailSize();
}
......@@ -443,7 +448,7 @@ qreal ThumbnailView::thumbnailAspectRatio() const
QSize ThumbnailView::thumbnailSize() const
{
return d->mThumbnailSize;
return d->mThumbnailSize / devicePixelRatioF();
}
void ThumbnailView::setThumbnailViewHelper(AbstractThumbnailViewHelper* helper)
......@@ -670,6 +675,7 @@ QPixmap ThumbnailView::thumbnailForIndex(const QModelIndex& index, QSize* fullSi
if (fullSize) {
*fullSize = thumbnail.mRealFullSize;
}
thumbnail.mAdjustedPix.setDevicePixelRatio(devicePixelRatioF());
return thumbnail.mAdjustedPix;
}
......@@ -810,7 +816,7 @@ void ThumbnailView::wheelEvent(QWheelEvent* event)
// setThumbnailSize() does not work
//verticalScrollBar()->setSingleStep(d->mThumbnailSize / 5);
if (event->modifiers() == Qt::ControlModifier) {
int width = d->mThumbnailSize.width() + (event->delta() > 0 ? 1 : -1) * WHEEL_ZOOM_MULTIPLIER;
int width = thumbnailSize().width() + (event->delta() > 0 ? 1 : -1) * WHEEL_ZOOM_MULTIPLIER;
width = qMax(int(MinThumbnailSize), qMin(width, int(MaxThumbnailSize)));
setThumbnailWidth(width);
} else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment