From 0a39fde201cd77aac3d62acd282ddd3ef1cfd7e7 Mon Sep 17 00:00:00 2001 From: David Griswold Date: Sun, 2 Mar 2025 16:01:49 +0100 Subject: [PATCH] citra_qt: Add quicksave / quicklaod hotkey --- src/citra_qt/citra_qt.cpp | 65 ++++++++++++++++++++------- src/citra_qt/configuration/config.cpp | 10 +++-- src/citra_qt/configuration/config.h | 2 +- src/citra_qt/main.ui | 13 ++++++ 4 files changed, 68 insertions(+), 22 deletions(-) diff --git a/src/citra_qt/citra_qt.cpp b/src/citra_qt/citra_qt.cpp index 0b3c78f70..1b6cedc66 100644 --- a/src/citra_qt/citra_qt.cpp +++ b/src/citra_qt/citra_qt.cpp @@ -692,25 +692,36 @@ void GMainWindow::InitializeRecentFileMenuActions() { void GMainWindow::InitializeSaveStateMenuActions() { for (u32 i = 0; i < Core::SaveStateSlotCount; ++i) { actions_load_state[i] = new QAction(this); - actions_load_state[i]->setData(i + 1); + actions_load_state[i]->setData(i); connect(actions_load_state[i], &QAction::triggered, this, &GMainWindow::OnLoadState); - ui->menu_Load_State->addAction(actions_load_state[i]); - + if (i > 0) + ui->menu_Load_State->addAction(actions_load_state[i]); actions_save_state[i] = new QAction(this); - actions_save_state[i]->setData(i + 1); + actions_save_state[i]->setData(i); connect(actions_save_state[i], &QAction::triggered, this, &GMainWindow::OnSaveState); - ui->menu_Save_State->addAction(actions_save_state[i]); + if (i > 0) + ui->menu_Save_State->addAction(actions_save_state[i]); } connect(ui->action_Load_from_Newest_Slot, &QAction::triggered, this, [this] { UpdateSaveStates(); if (newest_slot != 0) { - actions_load_state[newest_slot - 1]->trigger(); + actions_load_state[newest_slot]->trigger(); } }); connect(ui->action_Save_to_Oldest_Slot, &QAction::triggered, this, [this] { UpdateSaveStates(); - actions_save_state[oldest_slot - 1]->trigger(); + actions_save_state[oldest_slot]->trigger(); + }); + + // Quick save / load uses slot + connect(ui->action_Quick_Save, &QAction::triggered, this, [this] { + UpdateSaveStates(); + actions_save_state[0]->trigger(); + }); + connect(ui->action_Quick_Load, &QAction::triggered, this, [this] { + UpdateSaveStates(); + actions_load_state[0]->trigger(); }); connect(ui->menu_Load_State->menuAction(), &QAction::hovered, this, @@ -753,8 +764,12 @@ void GMainWindow::InitializeHotkeys() { link_action_shortcut(ui->action_Screen_Layout_Upright_Screens, QStringLiteral("Rotate Screens Upright")); link_action_shortcut(ui->action_Advance_Frame, QStringLiteral("Advance Frame")); - link_action_shortcut(ui->action_Load_from_Newest_Slot, QStringLiteral("Load from Newest Slot")); - link_action_shortcut(ui->action_Save_to_Oldest_Slot, QStringLiteral("Save to Oldest Slot")); + link_action_shortcut(ui->action_Load_from_Newest_Slot, + QStringLiteral("Load from Newest Non-Quick Slot")); + link_action_shortcut(ui->action_Save_to_Oldest_Slot, + QStringLiteral("Save to Oldest Non-Quick Slot")); + link_action_shortcut(ui->action_Quick_Save, QStringLiteral("Quick Save")); + link_action_shortcut(ui->action_Quick_Load, QStringLiteral("Quick Load")); link_action_shortcut(ui->action_View_Lobby, QStringLiteral("Multiplayer Browse Public Rooms")); link_action_shortcut(ui->action_Start_Room, QStringLiteral("Multiplayer Create Room")); link_action_shortcut(ui->action_Connect_To_Room, @@ -1667,7 +1682,7 @@ void GMainWindow::UpdateSaveStates() { ui->menu_Save_State->setEnabled(true); ui->action_Load_from_Newest_Slot->setEnabled(false); - oldest_slot = newest_slot = 0; + oldest_slot = newest_slot = 1; oldest_slot_time = std::numeric_limits::max(); newest_slot_time = 0; @@ -1678,13 +1693,30 @@ void GMainWindow::UpdateSaveStates() { auto savestates = Core::ListSaveStates(title_id, movie.GetCurrentMovieID()); for (u32 i = 0; i < Core::SaveStateSlotCount; ++i) { actions_load_state[i]->setEnabled(false); - actions_load_state[i]->setText(tr("Slot %1").arg(i + 1)); - actions_save_state[i]->setText(tr("Slot %1").arg(i + 1)); + if (i == 0) { + actions_load_state[i]->setText(tr("Quick Load")); + actions_save_state[i]->setText(tr("Quick Save")); + } else { + actions_load_state[i]->setText(tr("Slot %1").arg(i)); + actions_save_state[i]->setText(tr("Slot %1").arg(i)); + } } for (const auto& savestate : savestates) { const bool display_name = savestate.status == Core::SaveStateInfo::ValidationStatus::RevisionDismatch && !savestate.build_name.empty(); + actions_load_state[savestate.slot]->setEnabled(true); + if (savestate.slot == 0) { + const auto text = tr("%2 %3") + .arg(QDateTime::fromSecsSinceEpoch(savestate.time) + .toString(QStringLiteral("yyyy-MM-dd hh:mm:ss"))) + .arg(display_name ? QString::fromStdString(savestate.build_name) + : QLatin1String()) + .trimmed(); + ui->action_Quick_Save->setText(tr("Quick Save - %1").arg(text).trimmed()); + ui->action_Quick_Load->setText(tr("Quick Load - %1").arg(text).trimmed()); + continue; + } const auto text = tr("Slot %1 - %2 %3") .arg(savestate.slot) @@ -1693,12 +1725,10 @@ void GMainWindow::UpdateSaveStates() { .arg(display_name ? QString::fromStdString(savestate.build_name) : QLatin1String()) .trimmed(); - actions_load_state[savestate.slot - 1]->setEnabled(true); - actions_load_state[savestate.slot - 1]->setText(text); - actions_save_state[savestate.slot - 1]->setText(text); + actions_load_state[savestate.slot]->setText(text); + actions_save_state[savestate.slot]->setText(text); ui->action_Load_from_Newest_Slot->setEnabled(true); - if (savestate.time > newest_slot_time) { newest_slot = savestate.slot; newest_slot_time = savestate.time; @@ -1708,7 +1738,8 @@ void GMainWindow::UpdateSaveStates() { oldest_slot_time = savestate.time; } } - for (u32 i = 0; i < Core::SaveStateSlotCount; ++i) { + // Value as 1 because quicksave slot is not used for this calculation + for (u32 i = 1; i < Core::SaveStateSlotCount; ++i) { if (!actions_load_state[i]->isEnabled()) { // Prefer empty slot oldest_slot = i + 1; diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index a925ca3b2..69a060eb0 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -54,7 +54,7 @@ const std::array, Settings::NativeAnalog::NumAnalogs> QtConfi // This must be in alphabetical order according to action name as it must have the same order as // UISetting::values.shortcuts, which is alphabetically ordered. // clang-format off -const std::array QtConfig::default_hotkeys {{ +const std::array QtConfig::default_hotkeys {{ {QStringLiteral("Advance Frame"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}}, {QStringLiteral("Audio Mute/Unmute"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), Qt::WindowShortcut}}, {QStringLiteral("Audio Volume Down"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}}, @@ -70,16 +70,18 @@ const std::array QtConfig::default_hotkeys {{ {QStringLiteral("Increase Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("+"), Qt::ApplicationShortcut}}, {QStringLiteral("Load Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F2"), Qt::WidgetWithChildrenShortcut}}, {QStringLiteral("Load File"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), Qt::WidgetWithChildrenShortcut}}, - {QStringLiteral("Load from Newest Slot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+V"), Qt::WindowShortcut}}, - {QStringLiteral("Multiplayer Browse Public Lobby"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+B"), Qt::ApplicationShortcut}}, + {QStringLiteral("Load from Newest Non-Quick Slot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+V"), Qt::WindowShortcut}}, + {QStringLiteral("Multiplayer Browse Public Game Lobby"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+B"), Qt::ApplicationShortcut}}, {QStringLiteral("Multiplayer Create Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+N"), Qt::ApplicationShortcut}}, {QStringLiteral("Multiplayer Direct Connect to Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Shift"), Qt::ApplicationShortcut}}, {QStringLiteral("Multiplayer Leave Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+L"), Qt::ApplicationShortcut}}, {QStringLiteral("Multiplayer Show Current Room"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+R"), Qt::ApplicationShortcut}}, + {QStringLiteral("Quick Save"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}}, + {QStringLiteral("Quick Load"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}}, {QStringLiteral("Remove Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F3"), Qt::ApplicationShortcut}}, {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}}, {QStringLiteral("Rotate Screens Upright"), QStringLiteral("Main Window"), {QStringLiteral("F8"), Qt::WindowShortcut}}, - {QStringLiteral("Save to Oldest Slot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+C"), Qt::WindowShortcut}}, + {QStringLiteral("Save to Oldest Non-Quick Slot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+C"), Qt::WindowShortcut}}, {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}}, {QStringLiteral("Swap Screens"), QStringLiteral("Main Window"), {QStringLiteral("F9"), Qt::WindowShortcut}}, {QStringLiteral("Toggle 3D"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+3"), Qt::ApplicationShortcut}}, diff --git a/src/citra_qt/configuration/config.h b/src/citra_qt/configuration/config.h index d1412b1fa..064db894a 100644 --- a/src/citra_qt/configuration/config.h +++ b/src/citra_qt/configuration/config.h @@ -26,7 +26,7 @@ public: static const std::array default_buttons; static const std::array, Settings::NativeAnalog::NumAnalogs> default_analogs; - static const std::array default_hotkeys; + static const std::array default_hotkeys; private: void Initialize(const std::string& config_name); diff --git a/src/citra_qt/main.ui b/src/citra_qt/main.ui index 271a1bc78..02afdfd3d 100644 --- a/src/citra_qt/main.ui +++ b/src/citra_qt/main.ui @@ -98,6 +98,7 @@ Save State + @@ -105,6 +106,8 @@ Load State + + @@ -338,11 +341,21 @@ Save to Oldest Slot + + + Quick Save + + Load from Newest Slot + + + Quick Load + + Configure...