diff --git a/src/duckstation-qt/gamelistwidget.cpp b/src/duckstation-qt/gamelistwidget.cpp index cc98eda78..2769c8b59 100644 --- a/src/duckstation-qt/gamelistwidget.cpp +++ b/src/duckstation-qt/gamelistwidget.cpp @@ -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(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(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(m_grid_view) : static_cast(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(m_grid_view) : static_cast(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(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(); }); diff --git a/src/duckstation-qt/gamelistwidget.h b/src/duckstation-qt/gamelistwidget.h index ec5262985..174ffeb63 100644 --- a/src/duckstation-qt/gamelistwidget.h +++ b/src/duckstation-qt/gamelistwidget.h @@ -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; diff --git a/src/duckstation-qt/gamelistwidget.ui b/src/duckstation-qt/gamelistwidget.ui index 6c08dba6d..30ee5fbc6 100644 --- a/src/duckstation-qt/gamelistwidget.ui +++ b/src/duckstation-qt/gamelistwidget.ui @@ -54,9 +54,6 @@ Game List - - - true @@ -76,9 +73,6 @@ Game Grid - - - true @@ -98,9 +92,6 @@ Merge Multi-Disc Games - - - true @@ -120,9 +111,6 @@ Show Titles - - - true diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index e3bcdc093..dc3e83e99 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -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, diff --git a/src/duckstation-qt/mainwindow.h b/src/duckstation-qt/mainwindow.h index 41f375088..7debe1337 100644 --- a/src/duckstation-qt/mainwindow.h +++ b/src/duckstation-qt/mainwindow.h @@ -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); diff --git a/src/duckstation-qt/mainwindow.ui b/src/duckstation-qt/mainwindow.ui index 6b5ca5e0c..b092b01da 100644 --- a/src/duckstation-qt/mainwindow.ui +++ b/src/duckstation-qt/mainwindow.ui @@ -743,9 +743,6 @@ true - - false - Lock Toolbar @@ -786,6 +783,9 @@ + + true + @@ -794,6 +794,9 @@ + + true + false @@ -826,6 +829,9 @@ + + true + @@ -840,6 +846,9 @@ true + + + Merge Multi-Disc Games @@ -851,9 +860,15 @@ true + + + Show Titles (Grid View) + + Show Titles +