Browse Source
[desktop] Add basic carousel view (#4112)
[desktop] Add basic carousel view (#4112)
Adds a basic carousel view, or essentially a horizontal list a la Android/Qt Quick. Lacks a lot of niceties like autoscroll, smooth shifts, etc. Will work on those later Also fixed a bug introduced recently that capped game icon size to 8 at the low end, breaking the None option Signed-off-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4112 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev> Reviewed-by: Lizzie <lizzie@eden-emu.dev>pull/4116/head
No known key found for this signature in database
GPG Key ID: 425ACD2D4830EBC6
16 changed files with 300 additions and 45 deletions
-
2src/common/settings_enums.h
-
2src/qt_common/config/uisettings.h
-
1src/qt_common/game_list/game_list_p.h
-
4src/yuzu/CMakeLists.txt
-
107src/yuzu/game/carousel.cpp
-
27src/yuzu/game/carousel.h
-
69src/yuzu/game/game_card.cpp
-
10src/yuzu/game/game_card.h
-
13src/yuzu/game/game_grid.cpp
-
4src/yuzu/game/game_grid.h
-
71src/yuzu/game/game_list.cpp
-
7src/yuzu/game/game_list.h
-
2src/yuzu/game/game_tree.h
-
11src/yuzu/main.ui
-
14src/yuzu/main_window.cpp
-
1src/yuzu/main_window.h
@ -0,0 +1,107 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
|
||||
|
#include "qt_common/config/uisettings.h"
|
||||
|
#include "qt_common/game_list/model.h"
|
||||
|
#include "yuzu/game/common.h"
|
||||
|
#include "yuzu/game/game_card.h"
|
||||
|
#include "yuzu/game/carousel.h"
|
||||
|
|
||||
|
GameCarousel::GameCarousel(QWidget* parent) : QListView{parent} { |
||||
|
m_gameCard = new GameCard(this); |
||||
|
setItemDelegate(m_gameCard); |
||||
|
|
||||
|
setViewMode(QListView::IconMode); |
||||
|
setMovement(QListView::Static); |
||||
|
setUniformItemSizes(true); |
||||
|
setSelectionMode(QAbstractItemView::SingleSelection); |
||||
|
|
||||
|
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); |
||||
|
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); |
||||
|
|
||||
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
||||
|
|
||||
|
setEditTriggers(QAbstractItemView::NoEditTriggers); |
||||
|
setContextMenuPolicy(Qt::CustomContextMenu); |
||||
|
|
||||
|
setSpacing(10); |
||||
|
setWordWrap(true); |
||||
|
setTextElideMode(Qt::ElideRight); |
||||
|
setFlow(QListView::LeftToRight); |
||||
|
setWrapping(false); |
||||
|
} |
||||
|
|
||||
|
void GameCarousel::SetModel(GameListModel* model) { |
||||
|
QListView::setModel(model); |
||||
|
UpdateIconSize(); |
||||
|
} |
||||
|
|
||||
|
void GameCarousel::ApplyFilter(const QString& edit_filter_text, GameListModel* model) { |
||||
|
int row_count = model->rowCount(); |
||||
|
|
||||
|
for (int i = 0; i < row_count; ++i) { |
||||
|
QStandardItem* item = model->item(i, 0); |
||||
|
if (!item) |
||||
|
continue; |
||||
|
|
||||
|
if (Yuzu::FilterMatches(edit_filter_text, item)) { |
||||
|
setRowHidden(i, false); |
||||
|
} else { |
||||
|
setRowHidden(i, true); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void GameCarousel::UpdateIconSize() { |
||||
|
const u32 icon_size = UISettings::values.game_icon_size.GetValue(); |
||||
|
|
||||
|
int heightMargin = 0; |
||||
|
int widthMargin = 80; |
||||
|
|
||||
|
// TODO(crueter): get rid of this nonsense
|
||||
|
if (UISettings::values.show_game_name) { |
||||
|
switch (icon_size) { |
||||
|
case 128: |
||||
|
heightMargin = 65; |
||||
|
break; |
||||
|
case 0: |
||||
|
widthMargin = 120; |
||||
|
heightMargin = 120; |
||||
|
break; |
||||
|
case 64: |
||||
|
heightMargin = 77; |
||||
|
break; |
||||
|
case 32: |
||||
|
case 256: |
||||
|
heightMargin = 81; |
||||
|
break; |
||||
|
} |
||||
|
} else { |
||||
|
widthMargin = 24; |
||||
|
heightMargin = 24; |
||||
|
} |
||||
|
|
||||
|
const int min_item_width = icon_size + widthMargin; |
||||
|
const int min_item_height = icon_size + heightMargin; |
||||
|
const int grid_height = std::max(min_item_height, viewport()->height()); |
||||
|
|
||||
|
QSize content_size(min_item_width, min_item_height); |
||||
|
QSize grid_size(min_item_width, grid_height); |
||||
|
if (gridSize() != grid_size) { |
||||
|
setUpdatesEnabled(false); |
||||
|
|
||||
|
setGridSize(grid_size); |
||||
|
m_gameCard->setSize(grid_size, content_size, 0, 0); |
||||
|
|
||||
|
setUpdatesEnabled(true); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
QModelIndex GameCarousel::indexAt(const QPoint& point) const { |
||||
|
QModelIndex index = QListView::indexAt(point); |
||||
|
if (!index.isValid()) |
||||
|
return {}; |
||||
|
if (m_gameCard && !m_gameCard->hitTest(point, index, this, visualRect(index))) |
||||
|
return {}; |
||||
|
return index; |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
||||
|
// SPDX-License-Identifier: GPL-3.0-or-later |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <QListView> |
||||
|
#include <QString> |
||||
|
|
||||
|
class GameCard; |
||||
|
class GameListModel; |
||||
|
class QResizeEvent; |
||||
|
|
||||
|
class GameCarousel : public QListView { |
||||
|
Q_OBJECT |
||||
|
|
||||
|
public: |
||||
|
explicit GameCarousel(QWidget* parent = nullptr); |
||||
|
|
||||
|
void SetModel(GameListModel* model); |
||||
|
void ApplyFilter(const QString& edit_filter_text, GameListModel* model); |
||||
|
void UpdateIconSize(); |
||||
|
|
||||
|
QModelIndex indexAt(const QPoint& point) const override; |
||||
|
|
||||
|
private: |
||||
|
GameCard* m_gameCard = nullptr; |
||||
|
}; |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue