[desktop] Add icon-only mode to grid and improve design (#3485)

- Move Game Icon Size to the main toolbar. It's cleaner that way
- Add a "Show Game Name" toggle that does as it says. Disabling it
  basically creates an "icons-only" mode. Useful for controller-only
  nav with big icons (TODO: maybe make a 192 size?)
- Fixed a crash with controller nav. Oops
- Rounded corners of the game icon in grid mode
- Fixed the scroll bar creating extra clamping range on the grid icons
- Item can be deselected if user clicks on the blank space outside of the view

As a bonus fixed a crash on mod manager

Future TODOs for design:
- [ ] Row 1 type. Not sure what to do here tbh.
- [ ] Move around game list settings in configure_ui to make it clear
  that nothing there affects the grid view.
- [ ] 192x192 size? 256 feels too big on my 1440p screen whereas 128
  feels too small.
- Set text space as a function of fontMetrics.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3485
Reviewed-by: DraVee <dravee@eden-emu.dev>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
This commit is contained in:
crueter 2026-02-07 22:48:39 +01:00
parent e10f55d9db
commit ca9f2d43be
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
13 changed files with 273 additions and 130 deletions

View file

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include <QPainter>
#include <QPainterPath>
#include "game_card.h"
#include "qt_common/config/uisettings.h"
@ -18,7 +19,7 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
painter->setRenderHint(QPainter::Antialiasing);
// padding
QRect cardRect = option.rect.adjusted(4, 4, -4, -4);
QRect cardRect = option.rect.adjusted(4 + m_padding / 2, 4, -4 - m_padding / 2, -4);
// colors
QPalette palette = option.palette;
@ -32,7 +33,7 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
borderColor = palette.highlight().color().lighter(150);
textColor = palette.highlightedText().color();
} else if (option.state & QStyle::State_MouseOver) {
backgroundColor = backgroundColor.lighter(110);
backgroundColor = backgroundColor.lighter(120);
}
// bg
@ -40,7 +41,7 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
painter->setPen(QPen(borderColor, 1));
painter->drawRoundedRect(cardRect, 10, 10);
static constexpr const int padding = 10;
static constexpr const int padding = 8;
// icon
int _iconsize = UISettings::values.game_icon_size.GetValue();
@ -58,7 +59,18 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
iconRect = QRect(x, y, scaledSize.width(), scaledSize.height());
painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
// Put this in a separate thing on the painter stack to prevent clipping the text.
painter->save();
// round image edges
QPainterPath path;
path.addRoundedRect(iconRect, 10, 10);
painter->setClipPath(path);
painter->drawPixmap(iconRect, iconPixmap);
painter->restore();
} else {
// if there is no icon just draw a blank rect
iconRect = QRect(cardRect.left() + padding,
@ -66,31 +78,33 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
_iconsize, _iconsize);
}
// if "none" is selected, pretend there's a
_iconsize = _iconsize ? _iconsize : 96;
if (UISettings::values.show_game_name.GetValue()) {
// if "none" is selected, pretend there's a
_iconsize = _iconsize ? _iconsize : 96;
// padding + text
QRect textRect = cardRect;
textRect.setTop(iconRect.bottom() + 8);
textRect.adjust(padding, 0, -padding, -padding);
// padding + text
QRect textRect = cardRect;
textRect.setTop(iconRect.bottom() + 8);
textRect.adjust(padding, 0, -padding, -padding);
// We are already crammed on space, ignore the row 2
QString title = index.data(Qt::DisplayRole).toString();
title = title.split(QLatin1Char('\n')).first();
// We are already crammed on space, ignore the row 2
QString title = index.data(Qt::DisplayRole).toString();
title = title.split(QLatin1Char('\n')).first();
// now draw text
painter->setPen(textColor);
QFont font = option.font;
font.setBold(true);
// now draw text
painter->setPen(textColor);
QFont font = option.font;
font.setBold(true);
// TODO(crueter): fix this abysmal scaling
// If "none" is selected, then default to 8.5 point font.
font.setPointSize(1 + std::max(7.0, _iconsize ? std::sqrt(_iconsize * 0.6) : 7.5));
// TODO(crueter): fix this abysmal scaling
// If "none" is selected, then default to 8.5 point font.
font.setPointSize(1 + std::max(7.0, _iconsize ? std::sqrt(_iconsize * 0.6) : 7.5));
// TODO(crueter): elide mode
painter->setFont(font);
// TODO(crueter): elide mode
painter->setFont(font);
painter->drawText(textRect, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, title);
painter->drawText(textRect, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, title);
}
painter->restore();
}
@ -99,6 +113,7 @@ QSize GameCard::sizeHint(const QStyleOptionViewItem& option, const QModelIndex&
return m_size;
}
void GameCard::setSize(const QSize& newSize) {
void GameCard::setSize(const QSize& newSize, const int padding) {
m_size = newSize;
m_padding = padding;
}