mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-27 11:28:58 +02:00
[desktop] Basic grid view implementation (#3479)
Closes #3441 Basic impl of a grid view on the game list. The ideal solution here would be to use QSortFilterProxyModel and abstract the game list model out to a QStandardItemModel, but that is too much effort for me rn. Adapted the "card" design from QML, can 1000% be improved but QPainter is just such a pain to deal with. Implanting a Qt Quick scene into there would legitimately be easier. Anyways, margins and text sizes lgtm at all sizes, though please give feedback on both that and the general card design. Future TODOs: - [ ] Auto size mode - [ ] Refactor to use models Signed-off-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3479
This commit is contained in:
parent
69aff83ef4
commit
b9e052b3a7
19 changed files with 517 additions and 122 deletions
104
src/yuzu/game/game_card.cpp
Normal file
104
src/yuzu/game/game_card.cpp
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <QPainter>
|
||||
#include "game_card.h"
|
||||
#include "qt_common/config/uisettings.h"
|
||||
|
||||
GameCard::GameCard(QObject* parent) : QStyledItemDelegate{parent} {
|
||||
setObjectName("GameCard");
|
||||
}
|
||||
|
||||
void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const {
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
// padding
|
||||
QRect cardRect = option.rect.adjusted(4, 4, -4, -4);
|
||||
|
||||
// colors
|
||||
QPalette palette = option.palette;
|
||||
QColor backgroundColor = palette.window().color();
|
||||
QColor borderColor = palette.dark().color();
|
||||
QColor textColor = palette.text().color();
|
||||
|
||||
// if it's selected add a blue background
|
||||
if (option.state & QStyle::State_Selected) {
|
||||
backgroundColor = palette.highlight().color();
|
||||
borderColor = palette.highlight().color().lighter(150);
|
||||
textColor = palette.highlightedText().color();
|
||||
} else if (option.state & QStyle::State_MouseOver) {
|
||||
backgroundColor = backgroundColor.lighter(110);
|
||||
}
|
||||
|
||||
// bg
|
||||
painter->setBrush(backgroundColor);
|
||||
painter->setPen(QPen(borderColor, 1));
|
||||
painter->drawRoundedRect(cardRect, 10, 10);
|
||||
|
||||
static constexpr const int padding = 10;
|
||||
|
||||
// icon
|
||||
int _iconsize = UISettings::values.game_icon_size.GetValue();
|
||||
QSize iconSize(_iconsize, _iconsize);
|
||||
QPixmap iconPixmap = index.data(Qt::DecorationRole).value<QPixmap>();
|
||||
|
||||
QRect iconRect;
|
||||
if (!iconPixmap.isNull()) {
|
||||
QSize scaledSize = iconPixmap.size();
|
||||
scaledSize.scale(iconSize, Qt::KeepAspectRatio);
|
||||
|
||||
int x = cardRect.left() + (cardRect.width() - scaledSize.width()) / 2;
|
||||
int y = cardRect.top() + padding;
|
||||
|
||||
iconRect = QRect(x, y, scaledSize.width(), scaledSize.height());
|
||||
|
||||
painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
painter->drawPixmap(iconRect, iconPixmap);
|
||||
} else {
|
||||
// if there is no icon just draw a blank rect
|
||||
iconRect = QRect(cardRect.left() + padding,
|
||||
cardRect.top() + padding,
|
||||
_iconsize, _iconsize);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
painter->drawText(textRect, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, title);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QSize GameCard::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void GameCard::setSize(const QSize& newSize) {
|
||||
m_size = newSize;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue