diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index 190f19b70..dae15de46 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -520,7 +520,7 @@ void MainWindow::onGameListContextMenuRequested(const QPoint& point, const GameL { if (!entry->code.empty()) { - m_host_interface->populateGameListContextMenu(entry->code.c_str(), this, &menu); + m_host_interface->populateGameListContextMenu(entry, this, &menu); menu.addSeparator(); } @@ -913,8 +913,7 @@ void MainWindow::connectSignals() "ShowTimersState"); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.actionDebugShowMDECState, "Debug", "ShowMDECState"); - SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.actionDebugShowDMAState, "Debug", - "ShowDMAState"); + SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.actionDebugShowDMAState, "Debug", "ShowDMAState"); addThemeToMenu(tr("Default"), QStringLiteral("default")); addThemeToMenu(tr("Fusion"), QStringLiteral("fusion")); @@ -1223,13 +1222,37 @@ void MainWindow::onCheckForUpdatesActionTriggered() checkForUpdates(true); } -void MainWindow::onToolsMemoryCardEditorTriggered() +void MainWindow::openMemoryCardEditor(const QString& card_a_path, const QString& card_b_path) { if (!m_memory_card_editor_dialog) m_memory_card_editor_dialog = new MemoryCardEditorDialog(this); m_memory_card_editor_dialog->setModal(false); m_memory_card_editor_dialog->show(); + + if (!card_a_path.isEmpty()) + { + if (!m_memory_card_editor_dialog->setCardA(card_a_path)) + { + QMessageBox::critical( + this, tr("Memory Card Not Found"), + tr("Memory card '%1' could not be found. Try starting the game and saving to create it.").arg(card_a_path)); + } + } + if (!card_b_path.isEmpty()) + { + if (!m_memory_card_editor_dialog->setCardB(card_b_path)) + { + QMessageBox::critical( + this, tr("Memory Card Not Found"), + tr("Memory card '%1' could not be found. Try starting the game and saving to create it.").arg(card_b_path)); + } + } +} + +void MainWindow::onToolsMemoryCardEditorTriggered() +{ + openMemoryCardEditor(QString(), QString()); } void MainWindow::onToolsCheatManagerTriggered() diff --git a/src/duckstation-qt/mainwindow.h b/src/duckstation-qt/mainwindow.h index 575102ba9..9c8463474 100644 --- a/src/duckstation-qt/mainwindow.h +++ b/src/duckstation-qt/mainwindow.h @@ -31,6 +31,9 @@ public: /// Performs update check if enabled in settings. void startupUpdateCheck(); + /// Opens memory card editor with the specified paths. + void openMemoryCardEditor(const QString& card_a_path, const QString& card_b_path); + public Q_SLOTS: /// Updates debug menu visibility (hides if disabled). void updateDebugMenuVisibility(); diff --git a/src/duckstation-qt/memorycardeditordialog.cpp b/src/duckstation-qt/memorycardeditordialog.cpp index 2c7c4ad75..71c8db808 100644 --- a/src/duckstation-qt/memorycardeditordialog.cpp +++ b/src/duckstation-qt/memorycardeditordialog.cpp @@ -31,6 +31,26 @@ MemoryCardEditorDialog::MemoryCardEditorDialog(QWidget* parent) : QDialog(parent MemoryCardEditorDialog::~MemoryCardEditorDialog() = default; +bool MemoryCardEditorDialog::setCardA(const QString& path) +{ + const int index = m_ui.cardAPath->findData(QVariant(path)); + if (index < 0) + return false; + + m_ui.cardAPath->setCurrentIndex(index); + return true; +} + +bool MemoryCardEditorDialog::setCardB(const QString& path) +{ + const int index = m_ui.cardBPath->findData(QVariant(path)); + if (index < 0) + return false; + + m_ui.cardBPath->setCurrentIndex(index); + return true; +} + void MemoryCardEditorDialog::resizeEvent(QResizeEvent* ev) { QtUtils::ResizeColumnsForTableView(m_card_a.table, {32, -1, 100, 45}); diff --git a/src/duckstation-qt/memorycardeditordialog.h b/src/duckstation-qt/memorycardeditordialog.h index 58ef95691..d51cb7ea3 100644 --- a/src/duckstation-qt/memorycardeditordialog.h +++ b/src/duckstation-qt/memorycardeditordialog.h @@ -15,6 +15,9 @@ public: MemoryCardEditorDialog(QWidget* parent); ~MemoryCardEditorDialog(); + bool setCardA(const QString& path); + bool setCardB(const QString& path); + protected: void resizeEvent(QResizeEvent* ev); void closeEvent(QCloseEvent* ev); diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index 44481a597..dbad99a0b 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -890,7 +890,7 @@ void QtHostInterface::populateSaveStateMenus(const char* game_code, QMenu* load_ add_slot(tr("Global Save %1 (%2)"), tr("Global Save %1 (Empty)"), true, static_cast(slot)); } -void QtHostInterface::populateGameListContextMenu(const char* game_code, QWidget* parent_window, QMenu* menu) +void QtHostInterface::populateGameListContextMenu(const GameListEntry* entry, QWidget* parent_window, QMenu* menu) { QAction* resume_action = menu->addAction(tr("Resume")); resume_action->setEnabled(false); @@ -898,7 +898,7 @@ void QtHostInterface::populateGameListContextMenu(const char* game_code, QWidget QMenu* load_state_menu = menu->addMenu(tr("Load State")); load_state_menu->setEnabled(false); - const std::vector available_states(GetAvailableSaveStates(game_code)); + const std::vector available_states(GetAvailableSaveStates(entry->code.c_str())); const QString timestamp_format = QLocale::system().dateTimeFormat(QLocale::ShortFormat); for (const SaveStateInfo& ssi : available_states) { @@ -926,23 +926,53 @@ void QtHostInterface::populateGameListContextMenu(const char* game_code, QWidget connect(action, &QAction::triggered, [this, path]() { loadState(path); }); } + QAction* open_memory_cards_action = menu->addAction(tr("Edit Memory Cards...")); + connect(open_memory_cards_action, &QAction::triggered, [this, entry]() { + std::string paths[2]; + for (u32 i = 0; i < 2; i++) + { + MemoryCardType type = g_settings.memory_card_types[i]; + if (entry->code.empty() && type == MemoryCardType::PerGame) + type = MemoryCardType::Shared; + + switch (type) + { + case MemoryCardType::None: + continue; + case MemoryCardType::Shared: + paths[i] = + g_settings.memory_card_paths[i].empty() ? GetSharedMemoryCardPath(i) : g_settings.memory_card_paths[i]; + break; + case MemoryCardType::PerGame: + paths[i] = GetGameMemoryCardPath(entry->code.c_str(), i); + break; + case MemoryCardType::PerGameTitle: + paths[i] = GetGameMemoryCardPath(entry->title.c_str(), i); + break; + default: + break; + } + } + + m_main_window->openMemoryCardEditor(QString::fromStdString(paths[0]), QString::fromStdString(paths[1])); + }); + const bool has_any_states = resume_action->isEnabled() || load_state_menu->isEnabled(); QAction* delete_save_states_action = menu->addAction(tr("Delete Save States...")); delete_save_states_action->setEnabled(has_any_states); if (has_any_states) { - const std::string game_code_copy(game_code); - connect(delete_save_states_action, &QAction::triggered, [this, parent_window, game_code_copy] { + connect(delete_save_states_action, &QAction::triggered, [this, parent_window, entry] { if (QMessageBox::warning( parent_window, tr("Confirm Save State Deletion"), tr("Are you sure you want to delete all save states for %1?\n\nThe saves will not be recoverable.") - .arg(game_code_copy.c_str()), + .arg(QString::fromStdString(entry->code)), QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes) { return; } - DeleteSaveStates(game_code_copy.c_str(), true); + DeleteSaveStates(entry->code.c_str(), true); }); } } diff --git a/src/duckstation-qt/qthostinterface.h b/src/duckstation-qt/qthostinterface.h index 05e27fb9e..453b6f12a 100644 --- a/src/duckstation-qt/qthostinterface.h +++ b/src/duckstation-qt/qthostinterface.h @@ -25,6 +25,7 @@ class QTimer; class QTranslator; class GameList; +struct GameListEntry; class INISettingsInterface; class MainWindow; @@ -87,7 +88,7 @@ public: void populateSaveStateMenus(const char* game_code, QMenu* load_menu, QMenu* save_menu); /// Fills menu with save state info and handlers. - void populateGameListContextMenu(const char* game_code, QWidget* parent_window, QMenu* menu); + void populateGameListContextMenu(const GameListEntry* entry, QWidget* parent_window, QMenu* menu); /// Fills menu with the current playlist entries. The disc index is marked as checked. void populatePlaylistEntryMenu(QMenu* menu);