diff --git a/Source/Core/DolphinQt/MenuBar.cpp b/Source/Core/DolphinQt/MenuBar.cpp index fef441c062..39d2421b88 100644 --- a/Source/Core/DolphinQt/MenuBar.cpp +++ b/Source/Core/DolphinQt/MenuBar.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -334,6 +335,8 @@ void MenuBar::AddToolsMenu() m_import_wii_save = tools_menu->addAction(tr("Import Wii Save..."), this, &MenuBar::ImportWiiSave); + m_import_wii_saves = + tools_menu->addAction(tr("Import Wii Saves..."), this, &MenuBar::ImportWiiSaves); m_export_wii_saves = tools_menu->addAction(tr("Export All Wii Saves"), this, &MenuBar::ExportWiiSaves); @@ -1085,6 +1088,7 @@ void MenuBar::UpdateToolsMenu(const Core::State state) m_import_backup->setEnabled(is_uninitialized); m_check_nand->setEnabled(is_uninitialized); m_import_wii_save->setEnabled(is_uninitialized); + m_import_wii_saves->setEnabled(is_uninitialized); m_export_wii_saves->setEnabled(is_uninitialized); if (is_uninitialized) @@ -1156,7 +1160,8 @@ void MenuBar::ImportWiiSave() return ModalMessageBox::question( this, tr("Save Import"), tr("Save data for this title already exists in the NAND. Consider backing up " - "the current data before overwriting.\nOverwrite now?")) == QMessageBox::Yes; + "the current data before overwriting.\n\nOverwrite existing save data?")) == + QMessageBox::Yes; }; const auto result = WiiSave::Import(file.toStdString(), can_overwrite); @@ -1187,6 +1192,95 @@ void MenuBar::ImportWiiSave() } } +void MenuBar::ImportWiiSaves() +{ + QString folder = + DolphinFileDialog::getExistingDirectory(this, tr("Select Save Folder"), QDir::currentPath()); + + if (folder.isEmpty()) + return; + + QDirIterator it(folder, QStringList(QStringLiteral("*.bin")), QDir::Files, + QDirIterator::Subdirectories); + QStringList failure_details; + size_t success_count = 0; + size_t fail_count = 0; + bool yes_all = false; + bool no_all = false; + + while (it.hasNext()) + { + const QString file = it.next(); + + auto can_overwrite = [&] { + if (yes_all) + return true; + if (no_all) + return false; + + auto response = ModalMessageBox::question( + this, tr("Save Import"), + tr("%1: Save data for this title already exists in the NAND. Consider backing up " + "the current data before overwriting.\n\nOverwrite existing save data?") + .arg(file), + QMessageBox::StandardButton::YesAll | QMessageBox::StandardButton::Yes | + QMessageBox::StandardButton::No | QMessageBox::StandardButton::NoAll); + + if (response == QMessageBox::YesAll) + { + yes_all = true; + return true; + } + else if (response == QMessageBox::NoAll) + { + no_all = true; + return false; + } + return response == QMessageBox::Yes; + }; + + const auto result = WiiSave::Import(file.toStdString(), can_overwrite); + switch (result) + { + case WiiSave::CopyResult::Success: + success_count++; + break; + case WiiSave::CopyResult::CorruptedSource: + fail_count++; + failure_details.append(tr("%1: Failed to import save file. The given file appears to be " + "corrupted or is not a valid Wii save.") + .arg(file)); + break; + case WiiSave::CopyResult::TitleMissing: + fail_count++; + failure_details.append( + tr("%1: Failed to import save file. Please launch the game once, then try again.") + .arg(file)); + break; + case WiiSave::CopyResult::Cancelled: + break; + default: + fail_count++; + failure_details.append( + tr("%1: Failed to import save file. Your NAND may be corrupt, or something is preventing " + "access to files within it. Try repairing your NAND (Tools -> Manage NAND -> Check " + "NAND...), then import the save again.") + .arg(file)); + break; + } + } + + if (success_count == 0 && fail_count == 0) + return; + + ModalMessageBox::information(this, tr("Save Import"), + tr("Successfully imported %1 save file(s) with %2 failure(s)") + .arg(success_count) + .arg(fail_count), + QMessageBox::Ok, QMessageBox::NoButton, Qt::WindowModal, + failure_details.join(QStringLiteral("\n\n"))); +} + void MenuBar::ExportWiiSaves() { const QString export_dir = DolphinFileDialog::getExistingDirectory( diff --git a/Source/Core/DolphinQt/MenuBar.h b/Source/Core/DolphinQt/MenuBar.h index 29457c15f7..aeae8353c7 100644 --- a/Source/Core/DolphinQt/MenuBar.h +++ b/Source/Core/DolphinQt/MenuBar.h @@ -153,6 +153,7 @@ private: void InstallWAD(); void ImportWiiSave(); + void ImportWiiSaves(); void ExportWiiSaves(); void CheckNAND(); void NANDExtractCertificates(); @@ -214,6 +215,7 @@ private: QAction* m_extract_certificates; std::array m_wii_remotes; QAction* m_import_wii_save; + QAction* m_import_wii_saves; QAction* m_export_wii_saves; // Emulation diff --git a/Source/Core/DolphinQt/QtUtils/ModalMessageBox.cpp b/Source/Core/DolphinQt/QtUtils/ModalMessageBox.cpp index e80db0ad7e..ddb85fe7d8 100644 --- a/Source/Core/DolphinQt/QtUtils/ModalMessageBox.cpp +++ b/Source/Core/DolphinQt/QtUtils/ModalMessageBox.cpp @@ -21,7 +21,7 @@ ModalMessageBox::ModalMessageBox(QWidget* parent, Qt::WindowModality modality) static inline int ExecMessageBox(ModalMessageBox::Icon icon, QWidget* parent, const QString& title, const QString& text, ModalMessageBox::StandardButtons buttons, ModalMessageBox::StandardButton default_button, - Qt::WindowModality modality) + Qt::WindowModality modality, QString detailed_text) { ModalMessageBox msg(parent, modality); msg.setIcon(icon); @@ -29,6 +29,7 @@ static inline int ExecMessageBox(ModalMessageBox::Icon icon, QWidget* parent, co msg.setText(text); msg.setStandardButtons(buttons); msg.setDefaultButton(default_button); + msg.setDetailedText(detailed_text); SetQWidgetWindowDecorations(&msg); return msg.exec(); @@ -36,32 +37,32 @@ static inline int ExecMessageBox(ModalMessageBox::Icon icon, QWidget* parent, co int ModalMessageBox::critical(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons, StandardButton default_button, - Qt::WindowModality modality) + Qt::WindowModality modality, const QString& detailedText) { return ExecMessageBox(QMessageBox::Critical, parent, title, text, buttons, default_button, - modality); + modality, detailedText); } int ModalMessageBox::information(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons, StandardButton default_button, - Qt::WindowModality modality) + Qt::WindowModality modality, const QString& detailedText) { return ExecMessageBox(QMessageBox::Information, parent, title, text, buttons, default_button, - modality); + modality, detailedText); } int ModalMessageBox::question(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons, StandardButton default_button, - Qt::WindowModality modality) + Qt::WindowModality modality, const QString& detailedText) { return ExecMessageBox(QMessageBox::Warning, parent, title, text, buttons, default_button, - modality); + modality, detailedText); } int ModalMessageBox::warning(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons, StandardButton default_button, - Qt::WindowModality modality) + Qt::WindowModality modality, const QString& detailedText) { return ExecMessageBox(QMessageBox::Warning, parent, title, text, buttons, default_button, - modality); + modality, detailedText); } diff --git a/Source/Core/DolphinQt/QtUtils/ModalMessageBox.h b/Source/Core/DolphinQt/QtUtils/ModalMessageBox.h index b64d77208d..7f9fdfbba3 100644 --- a/Source/Core/DolphinQt/QtUtils/ModalMessageBox.h +++ b/Source/Core/DolphinQt/QtUtils/ModalMessageBox.h @@ -13,14 +13,18 @@ public: static int critical(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons = Ok, StandardButton default_button = NoButton, - Qt::WindowModality modality = Qt::WindowModal); + Qt::WindowModality modality = Qt::WindowModal, + const QString& detailed_text = QString()); static int information(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons = Ok, StandardButton default_button = NoButton, - Qt::WindowModality modality = Qt::WindowModal); + Qt::WindowModality modality = Qt::WindowModal, + const QString& detailedText = QString()); static int question(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons = Yes | No, StandardButton default_button = NoButton, - Qt::WindowModality modality = Qt::WindowModal); + Qt::WindowModality modality = Qt::WindowModal, + const QString& detailedText = QString()); static int warning(QWidget* parent, const QString& title, const QString& text, StandardButtons buttons = Ok, StandardButton default_button = NoButton, - Qt::WindowModality modality = Qt::WindowModal); + Qt::WindowModality modality = Qt::WindowModal, + const QString& detailedText = QString()); };