Qt: Refactor GameListWidget tool buttons and corresponding menu actions

This commit is contained in:
Davide Pesavento 2025-07-14 00:10:11 -04:00 committed by Connor McLaughlin
parent 01b81c74ef
commit 21f44b3782
6 changed files with 105 additions and 142 deletions

View File

@ -930,7 +930,10 @@ void GameListModel::setColumnDisplayNames()
class GameListSortModel final : public QSortFilterProxyModel
{
public:
explicit GameListSortModel(GameListModel* parent) : QSortFilterProxyModel(parent), m_model(parent) {}
explicit GameListSortModel(GameListModel* parent) : QSortFilterProxyModel(parent), m_model(parent)
{
m_merge_disc_sets = Host::GetBaseBoolSettingValue("UI", "GameListMergeDiscSets", true);
}
bool isMergingDiscSets() const { return m_merge_disc_sets; }
@ -945,11 +948,13 @@ public:
m_filter_type = type;
invalidateRowsFilter();
}
void setFilterRegion(DiscRegion region)
{
m_filter_region = region;
invalidateRowsFilter();
}
void setFilterName(std::string name)
{
m_filter_name = std::move(name);
@ -1133,16 +1138,14 @@ GameListWidget::GameListWidget(QWidget* parent /* = nullptr */) : QWidget(parent
GameListWidget::~GameListWidget() = default;
void GameListWidget::initialize()
void GameListWidget::initialize(QAction* actionGameList, QAction* actionGameGrid, QAction* actionMergeDiscSets,
QAction* actionListShowIcons, QAction* actionGridShowTitles)
{
const bool merge_disc_sets = Host::GetBaseBoolSettingValue("UI", "GameListMergeDiscSets", true);
m_model = new GameListModel(this);
connect(m_model, &GameListModel::coverScaleChanged, this, &GameListWidget::onCoverScaleChanged);
m_sort_model = new GameListSortModel(m_model);
m_sort_model->setSourceModel(m_model);
m_sort_model->setMergeDiscSets(merge_disc_sets);
m_ui.setupUi(this);
for (u32 type = 0; type < static_cast<u32>(GameList::EntryType::MaxCount); type++)
@ -1168,11 +1171,12 @@ void GameListWidget::initialize()
m_empty_ui.supportedFormats->setText(qApp->translate("GameListWidget", SUPPORTED_FORMATS_STRING));
m_ui.stack->insertWidget(2, m_empty_widget);
connect(m_ui.viewGameList, &QPushButton::clicked, this, &GameListWidget::showGameList);
connect(m_ui.viewGameGrid, &QPushButton::clicked, this, &GameListWidget::showGameGrid);
m_ui.viewGameList->setDefaultAction(actionGameList);
m_ui.viewGameGrid->setDefaultAction(actionGameGrid);
m_ui.viewMergeDiscSets->setDefaultAction(actionMergeDiscSets);
m_ui.viewGridTitles->setDefaultAction(actionGridShowTitles);
connect(m_ui.gridScale, &QSlider::valueChanged, m_grid_view, &GameListGridView::setZoomPct);
connect(m_ui.viewGridTitles, &QPushButton::toggled, this, &GameListWidget::setShowCoverTitles);
connect(m_ui.viewMergeDiscSets, &QPushButton::toggled, this, &GameListWidget::setMergeDiscSets);
connect(m_ui.filterType, &QComboBox::currentIndexChanged, this, [this](int index) {
m_sort_model->setFilterType((index == 0) ? GameList::EntryType::MaxCount :
static_cast<GameList::EntryType>(index - 1));
@ -1199,13 +1203,16 @@ void GameListWidget::initialize()
const bool grid_view = Host::GetBaseBoolSettingValue("UI", "GameListGridView", false);
if (grid_view)
m_ui.stack->setCurrentIndex(1);
actionGameGrid->setChecked(true);
else
m_ui.stack->setCurrentIndex(0);
setFocusProxy(grid_view ? static_cast<QWidget*>(m_grid_view) : static_cast<QWidget*>(m_list_view));
actionGameList->setChecked(true);
actionMergeDiscSets->setChecked(m_sort_model->isMergingDiscSets());
actionListShowIcons->setChecked(m_model->getShowGameIcons());
actionGridShowTitles->setChecked(m_model->getShowCoverTitles());
onCoverScaleChanged(m_model->getCoverScale());
updateToolbar();
resizeListViewColumnsToFit();
updateView(grid_view);
updateToolbar(grid_view);
updateBackground(true);
}
@ -1219,21 +1226,6 @@ bool GameListWidget::isShowingGameGrid() const
return m_ui.stack->currentIndex() == 1;
}
bool GameListWidget::isShowingGridCoverTitles() const
{
return m_model->getShowCoverTitles();
}
bool GameListWidget::isMergingDiscSets() const
{
return m_sort_model->isMergingDiscSets();
}
bool GameListWidget::isShowingGameIcons() const
{
return m_model->getShowGameIcons();
}
void GameListWidget::refresh(bool invalidate_cache)
{
cancelRefresh();
@ -1317,8 +1309,8 @@ void GameListWidget::onRefreshProgress(const QString& status, int current, int t
if (m_ui.stack->currentIndex() == 2)
{
const bool grid_view = Host::GetBaseBoolSettingValue("UI", "GameListGridView", false);
m_ui.stack->setCurrentIndex(grid_view ? 1 : 0);
setFocusProxy(grid_view ? static_cast<QWidget*>(m_grid_view) : static_cast<QWidget*>(m_list_view));
updateView(grid_view);
updateToolbar(grid_view);
}
if (!m_model->hasTakenGameList() || time >= SHORT_REFRESH_TIME)
@ -1417,68 +1409,42 @@ void GameListWidget::onSearchReturnPressed()
void GameListWidget::showGameList()
{
if (m_ui.stack->currentIndex() == 0 || m_model->rowCount() == 0)
{
updateToolbar();
if (isShowingGameList())
return;
}
Host::SetBaseBoolSettingValue("UI", "GameListGridView", false);
Host::CommitBaseSettingChanges();
m_ui.stack->setCurrentIndex(0);
setFocusProxy(m_list_view);
resizeListViewColumnsToFit();
updateToolbar();
emit layoutChanged();
// keep showing the placeholder widget if we have no games
if (m_model->rowCount() > 0)
updateView(false);
updateToolbar(false);
}
void GameListWidget::showGameGrid()
{
if (m_ui.stack->currentIndex() == 1 || m_model->rowCount() == 0)
{
updateToolbar();
if (isShowingGameGrid())
return;
}
Host::SetBaseBoolSettingValue("UI", "GameListGridView", true);
Host::CommitBaseSettingChanges();
m_ui.stack->setCurrentIndex(1);
setFocusProxy(m_grid_view);
updateToolbar();
emit layoutChanged();
}
void GameListWidget::setShowCoverTitles(bool enabled)
{
if (m_model->getShowCoverTitles() == enabled)
{
updateToolbar();
return;
}
// keep showing the placeholder widget if we have no games
if (m_model->rowCount() > 0)
updateView(true);
Host::SetBaseBoolSettingValue("UI", "GameListShowCoverTitles", enabled);
Host::CommitBaseSettingChanges();
m_model->setShowCoverTitles(enabled);
m_grid_view->updateLayout();
if (isShowingGameGrid())
m_model->refresh();
updateToolbar();
emit layoutChanged();
updateToolbar(true);
}
void GameListWidget::setMergeDiscSets(bool enabled)
{
if (m_sort_model->isMergingDiscSets() == enabled)
{
updateToolbar();
return;
}
Host::SetBaseBoolSettingValue("UI", "GameListMergeDiscSets", enabled);
Host::CommitBaseSettingChanges();
m_sort_model->setMergeDiscSets(enabled);
updateToolbar();
emit layoutChanged();
}
void GameListWidget::setShowGameIcons(bool enabled)
@ -1491,30 +1457,36 @@ void GameListWidget::setShowGameIcons(bool enabled)
m_model->setShowGameIcons(enabled);
}
void GameListWidget::updateToolbar()
void GameListWidget::setShowCoverTitles(bool enabled)
{
const bool grid_view = isShowingGameGrid();
{
QSignalBlocker sb(m_ui.viewGameGrid);
m_ui.viewGameGrid->setChecked(grid_view);
}
{
QSignalBlocker sb(m_ui.viewGameList);
m_ui.viewGameList->setChecked(!grid_view);
}
{
QSignalBlocker sb(m_ui.viewGridTitles);
m_ui.viewGridTitles->setChecked(m_model->getShowCoverTitles());
}
{
QSignalBlocker sb(m_ui.viewMergeDiscSets);
m_ui.viewMergeDiscSets->setChecked(m_sort_model->isMergingDiscSets());
}
{
QSignalBlocker sb(m_ui.gridScale);
m_ui.gridScale->setValue(static_cast<int>(m_model->getCoverScale() * 100.0f));
}
if (m_model->getShowCoverTitles() == enabled)
return;
Host::SetBaseBoolSettingValue("UI", "GameListShowCoverTitles", enabled);
Host::CommitBaseSettingChanges();
m_model->setShowCoverTitles(enabled);
m_grid_view->updateLayout();
if (isShowingGameGrid())
m_model->refresh();
}
void GameListWidget::updateView(bool grid_view)
{
if (grid_view)
{
m_ui.stack->setCurrentIndex(1);
setFocusProxy(m_grid_view);
}
else
{
m_ui.stack->setCurrentIndex(0);
setFocusProxy(m_list_view);
resizeListViewColumnsToFit();
}
}
void GameListWidget::updateToolbar(bool grid_view)
{
m_ui.viewGridTitles->setEnabled(grid_view);
m_ui.gridScale->setEnabled(grid_view);
}
@ -1538,7 +1510,7 @@ void GameListWidget::resizeListViewColumnsToFit()
const GameList::Entry* GameListWidget::getSelectedEntry() const
{
if (m_ui.stack->currentIndex() == 0)
if (isShowingGameList())
{
const QItemSelectionModel* selection_model = m_list_view->selectionModel();
if (!selection_model->hasSelection())
@ -1727,7 +1699,7 @@ void GameListListView::onHeaderContextMenuRequested(const QPoint& point)
QAction* action = menu.addAction(m_model->getColumnDisplayName(column));
action->setCheckable(true);
action->setChecked(!isColumnHidden(column));
connect(action, &QAction::toggled, [this, column](bool enabled) {
connect(action, &QAction::triggered, [this, column](bool enabled) {
setAndSaveColumnHidden(column, !enabled);
resizeColumnsToFit();
});

View File

@ -221,7 +221,8 @@ public:
ALWAYS_INLINE GameListListView* getListView() const { return m_list_view; }
ALWAYS_INLINE GameListGridView* getGridView() const { return m_grid_view; }
void initialize();
void initialize(QAction* actionGameList, QAction* actionGameGrid, QAction* actionMergeDiscSets,
QAction* actionListShowIcons, QAction* actionGridShowTitles);
void resizeListViewColumnsToFit();
void refresh(bool invalidate_cache);
@ -232,9 +233,6 @@ public:
bool isShowingGameList() const;
bool isShowingGameGrid() const;
bool isShowingGridCoverTitles() const;
bool isMergingDiscSets() const;
bool isShowingGameIcons() const;
const GameList::Entry* getSelectedEntry() const;
@ -247,7 +245,6 @@ Q_SIGNALS:
void entryContextMenuRequested(const QPoint& point);
void addGameDirectoryRequested();
void layoutChanged();
private Q_SLOTS:
void onRefreshProgress(const QString& status, int current, int total, float time);
@ -265,9 +262,9 @@ private Q_SLOTS:
public Q_SLOTS:
void showGameList();
void showGameGrid();
void setShowCoverTitles(bool enabled);
void setMergeDiscSets(bool enabled);
void setShowGameIcons(bool enabled);
void setShowCoverTitles(bool enabled);
void refreshGridCovers();
void focusSearchWidget();
@ -275,7 +272,8 @@ protected:
void resizeEvent(QResizeEvent* event);
private:
void updateToolbar();
void updateView(bool grid_view);
void updateToolbar(bool grid_view);
Ui::GameListWidget m_ui;

View File

@ -54,9 +54,6 @@
<property name="text">
<string>Game List</string>
</property>
<property name="icon">
<iconset theme="list-check"/>
</property>
<property name="checkable">
<bool>true</bool>
</property>
@ -76,9 +73,6 @@
<property name="text">
<string>Game Grid</string>
</property>
<property name="icon">
<iconset theme="function-line"/>
</property>
<property name="checkable">
<bool>true</bool>
</property>
@ -98,9 +92,6 @@
<property name="text">
<string>Merge Multi-Disc Games</string>
</property>
<property name="icon">
<iconset theme="play-list-2-line"/>
</property>
<property name="checkable">
<bool>true</bool>
</property>
@ -120,9 +111,6 @@
<property name="text">
<string>Show Titles</string>
</property>
<property name="icon">
<iconset theme="price-tag-3-line"/>
</property>
<property name="checkable">
<bool>true</bool>
</property>

View File

@ -398,6 +398,7 @@ void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main, bool
AssertMsg(m_ui.mainContainer->count() == 1, "Has no display widget");
m_ui.mainContainer->addWidget(container);
m_ui.mainContainer->setCurrentIndex(1);
m_ui.actionViewSystemDisplay->setChecked(true);
}
updateDisplayRelatedActions(true, render_to_main, fullscreen);
@ -460,7 +461,10 @@ void MainWindow::destroyDisplayWidget(bool show_game_list)
if (show_game_list)
{
m_ui.mainContainer->setCurrentIndex(0);
m_game_list_widget->resizeListViewColumnsToFit();
if (m_game_list_widget->isShowingGameGrid())
m_ui.actionViewGameGrid->setChecked(true);
else
m_ui.actionViewGameList->setChecked(true);
}
}
@ -542,6 +546,7 @@ void MainWindow::onSystemStarted()
m_was_disc_change_request = false;
s_system_starting = false;
s_system_valid = true;
updateEmulationActions(false, true, s_achievements_hardcore_mode);
updateWindowTitle();
updateStatusBarWidgetVisibility();
@ -1383,14 +1388,14 @@ void MainWindow::onViewStatusBarActionToggled(bool checked)
void MainWindow::onViewGameListActionTriggered()
{
switchToGameListView();
m_game_list_widget->showGameList();
switchToGameListView();
}
void MainWindow::onViewGameGridActionTriggered()
{
switchToGameListView();
m_game_list_widget->showGameGrid();
switchToGameListView();
}
void MainWindow::onViewSystemDisplayTriggered()
@ -1443,25 +1448,6 @@ void MainWindow::onGameListRefreshComplete()
clearProgressBar();
}
void MainWindow::onGameListLayoutChanged()
{
// re-sync with menu
{
QSignalBlocker sb(m_ui.actionGridViewShowTitles);
m_ui.actionGridViewShowTitles->setChecked(m_game_list_widget->isShowingGridCoverTitles());
}
{
QSignalBlocker sb(m_ui.actionMergeDiscSets);
m_ui.actionMergeDiscSets->setChecked(m_game_list_widget->isMergingDiscSets());
}
{
QSignalBlocker sb(m_ui.actionShowGameIcons);
m_ui.actionShowGameIcons->setChecked(m_game_list_widget->isShowingGameIcons());
}
}
void MainWindow::onGameListSelectionChanged()
{
auto lock = GameList::GetLock();
@ -1735,8 +1721,15 @@ void MainWindow::setupAdditionalUi()
m_ui.actionViewToolbarLabelsBesideIcons->setChecked(
Host::GetBaseBoolSettingValue("UI", "ToolbarLabelsBesideIcons", false));
// mutually exclusive actions
QActionGroup* group = new QActionGroup(this);
group->addAction(m_ui.actionViewGameList);
group->addAction(m_ui.actionViewGameGrid);
group->addAction(m_ui.actionViewSystemDisplay);
m_game_list_widget = new GameListWidget(m_ui.mainContainer);
m_game_list_widget->initialize();
m_game_list_widget->initialize(m_ui.actionViewGameList, m_ui.actionViewGameGrid, m_ui.actionMergeDiscSets,
m_ui.actionShowGameIcons, m_ui.actionGridViewShowTitles);
m_ui.mainContainer->addWidget(m_game_list_widget);
m_status_progress_widget = new QProgressBar(m_ui.statusBar);
@ -1774,7 +1767,6 @@ void MainWindow::setupAdditionalUi()
connect(action, &QAction::triggered, [scale]() { g_emu_thread->requestDisplaySize(scale); });
}
onGameListLayoutChanged();
updateDebugMenuVisibility();
m_shortcuts.open_file = new QShortcut(QKeySequence::Open, this, this, &MainWindow::onStartFileActionTriggered);
@ -2154,7 +2146,7 @@ void MainWindow::switchToEmulationView()
if (!wantsDisplayWidget() || !isShowingGameList())
return;
// we're no longer surfaceless! this will call back to UpdateDisplay(), which will swap the widget out.
// we're no longer surfaceless! this will call back to acquireRenderWindow(), which will swap the widget out.
g_emu_thread->setSurfaceless(false);
// resume if we weren't paused at switch time
@ -2313,7 +2305,6 @@ void MainWindow::connectSignals()
// These need to be queued connections to stop crashing due to menus opening/closing and switching focus.
connect(m_game_list_widget, &GameListWidget::refreshProgress, this, &MainWindow::onGameListRefreshProgress);
connect(m_game_list_widget, &GameListWidget::refreshComplete, this, &MainWindow::onGameListRefreshComplete);
connect(m_game_list_widget, &GameListWidget::layoutChanged, this, &MainWindow::onGameListLayoutChanged);
connect(m_game_list_widget, &GameListWidget::selectionChanged, this, &MainWindow::onGameListSelectionChanged,
Qt::QueuedConnection);
connect(m_game_list_widget, &GameListWidget::entryActivated, this, &MainWindow::onGameListEntryActivated,

View File

@ -213,7 +213,6 @@ private Q_SLOTS:
void onGameListRefreshComplete();
void onGameListRefreshProgress(const QString& status, int current, int total);
void onGameListLayoutChanged();
void onGameListSelectionChanged();
void onGameListEntryActivated();
void onGameListEntryContextMenuRequested(const QPoint& point);

View File

@ -743,9 +743,6 @@
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="text">
<string>Lock Toolbar</string>
</property>
@ -786,6 +783,9 @@
</property>
</action>
<action name="actionViewGameList">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="list-check"/>
</property>
@ -794,6 +794,9 @@
</property>
</action>
<action name="actionViewSystemDisplay">
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
@ -826,6 +829,9 @@
</property>
</action>
<action name="actionViewGameGrid">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="function-line"/>
</property>
@ -840,6 +846,9 @@
<property name="checked">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="play-list-2-line"/>
</property>
<property name="text">
<string>Merge Multi-Disc Games</string>
</property>
@ -851,9 +860,15 @@
<property name="checked">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="price-tag-3-line"/>
</property>
<property name="text">
<string>Show Titles (Grid View)</string>
</property>
<property name="toolTip">
<string>Show Titles</string>
</property>
</action>
<action name="actionGridViewZoomIn">
<property name="text">