Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement importing multiple saves from an export folder #13278

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions Source/Core/DolphinQt/MenuBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <QSignalBlocker>
#include <QUrl>

#include <QDirIterator>
#include <fmt/format.h>

#include "Common/Align.h"
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1187,6 +1191,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"),
file + QStringLiteral(": ") +
tr("Save data for this title already exists in the NAND. Consider backing up "
"the current data before overwriting.\nOverwrite now?"),
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(file + QStringLiteral(": ") +
tr("Failed to import save file. The given file appears to be "
"corrupted or is not a valid Wii save."));
break;
case WiiSave::CopyResult::TitleMissing:
fail_count++;
failure_details.append(
file + QStringLiteral(": ") +
tr("Failed to import save file. Please launch the game once, then try again."));
break;
case WiiSave::CopyResult::Cancelled:
break;
default:
fail_count++;
failure_details.append(
file + QStringLiteral(": ") +
tr("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."));
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(
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/DolphinQt/MenuBar.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ class MenuBar final : public QMenuBar

void InstallWAD();
void ImportWiiSave();
void ImportWiiSaves();
void ExportWiiSaves();
void CheckNAND();
void NANDExtractCertificates();
Expand Down Expand Up @@ -214,6 +215,7 @@ class MenuBar final : public QMenuBar
QAction* m_extract_certificates;
std::array<QAction*, 5> m_wii_remotes;
QAction* m_import_wii_save;
QAction* m_import_wii_saves;
QAction* m_export_wii_saves;

// Emulation
Expand Down
19 changes: 10 additions & 9 deletions Source/Core/DolphinQt/QtUtils/ModalMessageBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,47 +21,48 @@ 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);
msg.setWindowTitle(title);
msg.setText(text);
msg.setStandardButtons(buttons);
msg.setDefaultButton(default_button);
msg.setDetailedText(detailed_text);

SetQWidgetWindowDecorations(&msg);
return msg.exec();
}

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);
}
12 changes: 8 additions & 4 deletions Source/Core/DolphinQt/QtUtils/ModalMessageBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@ class ModalMessageBox : public QMessageBox

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());
};