mirror of
https://github.com/Dark98/threeSD.git
synced 2026-07-05 16:49:08 +00:00
Remove context help from all dialogs
This commit is contained in:
@@ -1,94 +1,95 @@
|
|||||||
// Copyright 2021 threeSD Project
|
// Copyright 2021 threeSD Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "frontend/cia_build_dialog.h"
|
#include "frontend/cia_build_dialog.h"
|
||||||
#include "ui_cia_build_dialog.h"
|
#include "ui_cia_build_dialog.h"
|
||||||
|
|
||||||
CIABuildDialog::CIABuildDialog(QWidget* parent, bool is_dir_, bool is_nand, bool enable_legit,
|
CIABuildDialog::CIABuildDialog(QWidget* parent, bool is_dir_, bool is_nand, bool enable_legit,
|
||||||
const QString& default_path)
|
const QString& default_path)
|
||||||
: QDialog(parent), ui(std::make_unique<Ui::CIABuildDialog>()), is_dir(is_dir_) {
|
: QDialog(parent), ui(std::make_unique<Ui::CIABuildDialog>()), is_dir(is_dir_) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
||||||
|
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
||||||
if (is_dir) {
|
|
||||||
setWindowTitle(tr("Batch Build CIA"));
|
if (is_dir) {
|
||||||
}
|
setWindowTitle(tr("Batch Build CIA"));
|
||||||
if (is_nand) {
|
}
|
||||||
ui->pirateLegitButton->setVisible(false);
|
if (is_nand) {
|
||||||
ui->pirateLegitLabel->setVisible(false);
|
ui->pirateLegitButton->setVisible(false);
|
||||||
|
ui->pirateLegitLabel->setVisible(false);
|
||||||
auto message = tr("Encrypted CIA with legit TMD, encrypted contents and legit ticket.<br>");
|
|
||||||
if (is_dir) {
|
auto message = tr("Encrypted CIA with legit TMD, encrypted contents and legit ticket.<br>");
|
||||||
message.append(tr(
|
if (is_dir) {
|
||||||
"Legit tickets for these titles do not include console-identifying information."));
|
message.append(tr(
|
||||||
} else {
|
"Legit tickets for these titles do not include console-identifying information."));
|
||||||
message.append(tr(
|
} else {
|
||||||
"Legit ticket for this title does not include console-identifying information."));
|
message.append(tr(
|
||||||
}
|
"Legit ticket for this title does not include console-identifying information."));
|
||||||
ui->legitLabel->setText(message);
|
}
|
||||||
}
|
ui->legitLabel->setText(message);
|
||||||
if (!enable_legit) {
|
}
|
||||||
const auto message =
|
if (!enable_legit) {
|
||||||
is_dir ? tr("This option is not available as some of the titles are not legit.")
|
const auto message =
|
||||||
: tr("This option is not available as the title is not legit.");
|
is_dir ? tr("This option is not available as some of the titles are not legit.")
|
||||||
ui->pirateLegitButton->setEnabled(false);
|
: tr("This option is not available as the title is not legit.");
|
||||||
ui->pirateLegitLabel->setText(message);
|
ui->pirateLegitButton->setEnabled(false);
|
||||||
ui->legitButton->setEnabled(false);
|
ui->pirateLegitLabel->setText(message);
|
||||||
ui->legitLabel->setText(message);
|
ui->legitButton->setEnabled(false);
|
||||||
}
|
ui->legitLabel->setText(message);
|
||||||
|
}
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, [this] {
|
|
||||||
if (ui->destination->text().isEmpty()) {
|
connect(ui->buttonBox, &QDialogButtonBox::accepted, [this] {
|
||||||
const QString message = is_dir ? tr("Please specify destination folder.")
|
if (ui->destination->text().isEmpty()) {
|
||||||
: tr("Please specify destination file.");
|
const QString message = is_dir ? tr("Please specify destination folder.")
|
||||||
QMessageBox::warning(this, tr("threeSD"), message);
|
: tr("Please specify destination file.");
|
||||||
return;
|
QMessageBox::warning(this, tr("threeSD"), message);
|
||||||
}
|
return;
|
||||||
accept();
|
}
|
||||||
});
|
accept();
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &CIABuildDialog::reject);
|
});
|
||||||
|
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &CIABuildDialog::reject);
|
||||||
if (is_dir) {
|
|
||||||
ui->destination->setText(default_path);
|
if (is_dir) {
|
||||||
}
|
ui->destination->setText(default_path);
|
||||||
connect(ui->destinationExplore, &QToolButton::clicked, [this, default_path] {
|
}
|
||||||
QString path;
|
connect(ui->destinationExplore, &QToolButton::clicked, [this, default_path] {
|
||||||
if (is_dir) {
|
QString path;
|
||||||
path = QFileDialog::getExistingDirectory(this, tr("Batch Build CIA"),
|
if (is_dir) {
|
||||||
ui->destination->text());
|
path = QFileDialog::getExistingDirectory(this, tr("Batch Build CIA"),
|
||||||
} else {
|
ui->destination->text());
|
||||||
const auto cur = ui->destination->text().isEmpty()
|
} else {
|
||||||
? default_path
|
const auto cur = ui->destination->text().isEmpty()
|
||||||
: QFileInfo(ui->destination->text()).path();
|
? default_path
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Build CIA"), cur,
|
: QFileInfo(ui->destination->text()).path();
|
||||||
tr("CTR Importable Archive (*.cia)"));
|
path = QFileDialog::getSaveFileName(this, tr("Build CIA"), cur,
|
||||||
}
|
tr("CTR Importable Archive (*.cia)"));
|
||||||
if (!path.isEmpty()) {
|
}
|
||||||
ui->destination->setText(path);
|
if (!path.isEmpty()) {
|
||||||
}
|
ui->destination->setText(path);
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
CIABuildDialog::~CIABuildDialog() = default;
|
|
||||||
|
CIABuildDialog::~CIABuildDialog() = default;
|
||||||
std::pair<QString, Core::CIABuildType> CIABuildDialog::GetResults() const {
|
|
||||||
Core::CIABuildType type;
|
std::pair<QString, Core::CIABuildType> CIABuildDialog::GetResults() const {
|
||||||
if (ui->standardButton->isChecked()) {
|
Core::CIABuildType type;
|
||||||
type = Core::CIABuildType::Standard;
|
if (ui->standardButton->isChecked()) {
|
||||||
} else if (ui->pirateLegitButton->isChecked()) {
|
type = Core::CIABuildType::Standard;
|
||||||
type = Core::CIABuildType::PirateLegit;
|
} else if (ui->pirateLegitButton->isChecked()) {
|
||||||
} else if (ui->legitButton->isChecked()) {
|
type = Core::CIABuildType::PirateLegit;
|
||||||
type = Core::CIABuildType::Legit;
|
} else if (ui->legitButton->isChecked()) {
|
||||||
} else {
|
type = Core::CIABuildType::Legit;
|
||||||
UNREACHABLE();
|
} else {
|
||||||
}
|
UNREACHABLE();
|
||||||
return {ui->destination->text(), type};
|
}
|
||||||
}
|
return {ui->destination->text(), type};
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,8 +37,9 @@ void SimpleJob::StartWithProgressDialog(QWidget* widget) {
|
|||||||
bar->setValue(0);
|
bar->setValue(0);
|
||||||
|
|
||||||
auto* dialog = new QProgressDialog(tr("Initializing..."), tr("Cancel"), 0, 0, widget);
|
auto* dialog = new QProgressDialog(tr("Initializing..."), tr("Cancel"), 0, 0, widget);
|
||||||
dialog->setBar(bar);
|
dialog->setWindowFlags(dialog->windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
dialog->setWindowModality(Qt::WindowModal);
|
dialog->setWindowModality(Qt::WindowModal);
|
||||||
|
dialog->setBar(bar);
|
||||||
dialog->setMinimumDuration(0);
|
dialog->setMinimumDuration(0);
|
||||||
|
|
||||||
connect(this, &SimpleJob::ProgressUpdated, this, [bar, dialog](u64 current, u64 total) {
|
connect(this, &SimpleJob::ProgressUpdated, this, [bar, dialog](u64 current, u64 total) {
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ ImportDialog::ImportDialog(QWidget* parent, const Core::Config& config_)
|
|||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
||||||
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
||||||
|
|
||||||
@@ -126,6 +127,7 @@ ImportDialog::~ImportDialog() = default;
|
|||||||
|
|
||||||
void ImportDialog::RelistContent() {
|
void ImportDialog::RelistContent() {
|
||||||
auto* dialog = new QProgressDialog(tr("Loading Contents..."), tr("Cancel"), 0, 0, this);
|
auto* dialog = new QProgressDialog(tr("Loading Contents..."), tr("Cancel"), 0, 0, this);
|
||||||
|
dialog->setWindowFlags(dialog->windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
dialog->setWindowModality(Qt::WindowModal);
|
dialog->setWindowModality(Qt::WindowModal);
|
||||||
dialog->setCancelButton(nullptr);
|
dialog->setCancelButton(nullptr);
|
||||||
dialog->setMinimumDuration(0);
|
dialog->setMinimumDuration(0);
|
||||||
@@ -585,9 +587,10 @@ void ImportDialog::RunMultiJob(MultiJob* job, std::size_t total_count, u64 total
|
|||||||
bar->setValue(0);
|
bar->setValue(0);
|
||||||
|
|
||||||
auto* dialog = new QProgressDialog(tr("Initializing..."), tr("Cancel"), 0, 0, this);
|
auto* dialog = new QProgressDialog(tr("Initializing..."), tr("Cancel"), 0, 0, this);
|
||||||
|
dialog->setWindowFlags(dialog->windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
|
dialog->setWindowModality(Qt::WindowModal);
|
||||||
dialog->setBar(bar);
|
dialog->setBar(bar);
|
||||||
dialog->setLabel(label);
|
dialog->setLabel(label);
|
||||||
dialog->setWindowModality(Qt::WindowModal);
|
|
||||||
dialog->setMinimumDuration(0);
|
dialog->setMinimumDuration(0);
|
||||||
|
|
||||||
connect(job, &MultiJob::NextContent, this,
|
connect(job, &MultiJob::NextContent, this,
|
||||||
@@ -639,6 +642,8 @@ void ImportDialog::RunMultiJob(MultiJob* job, std::size_t total_count, u64 total
|
|||||||
connect(dialog, &QProgressDialog::canceled, this, [this, job] {
|
connect(dialog, &QProgressDialog::canceled, this, [this, job] {
|
||||||
// Add yet-another-ProgressDialog to indicate cancel progress
|
// Add yet-another-ProgressDialog to indicate cancel progress
|
||||||
auto* cancel_dialog = new QProgressDialog(tr("Canceling..."), tr("Cancel"), 0, 0, this);
|
auto* cancel_dialog = new QProgressDialog(tr("Canceling..."), tr("Cancel"), 0, 0, this);
|
||||||
|
cancel_dialog->setWindowFlags(cancel_dialog->windowFlags() &
|
||||||
|
(~Qt::WindowContextHelpButtonHint));
|
||||||
cancel_dialog->setWindowModality(Qt::WindowModal);
|
cancel_dialog->setWindowModality(Qt::WindowModal);
|
||||||
cancel_dialog->setCancelButton(nullptr);
|
cancel_dialog->setCancelButton(nullptr);
|
||||||
cancel_dialog->setMinimumDuration(0);
|
cancel_dialog->setMinimumDuration(0);
|
||||||
|
|||||||
+251
-250
@@ -1,250 +1,251 @@
|
|||||||
// Copyright 2014 Citra Emulator Project / 2019 threeSD Project
|
// Copyright 2014 Citra Emulator Project / 2019 threeSD Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QStorageInfo>
|
#include <QStorageInfo>
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
#include <qdevicewatcher.h>
|
#include <qdevicewatcher.h>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
#include "frontend/import_dialog.h"
|
#include "frontend/import_dialog.h"
|
||||||
#include "frontend/main.h"
|
#include "frontend/main.h"
|
||||||
#include "frontend/utilities.h"
|
#include "frontend/utilities.h"
|
||||||
#include "ui_main.h"
|
#include "ui_main.h"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "common/common_paths.h"
|
#include "common/common_paths.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef QT_STATICPLUGIN
|
#ifdef QT_STATICPLUGIN
|
||||||
#include <QtPlugin>
|
#include <QtPlugin>
|
||||||
|
|
||||||
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
|
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||||
Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin)
|
Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool IsConfigGood(const Core::Config& config) {
|
bool IsConfigGood(const Core::Config& config) {
|
||||||
return !config.sdmc_path.empty() && !config.user_path.empty() &&
|
return !config.sdmc_path.empty() && !config.user_path.empty() &&
|
||||||
!config.movable_sed_path.empty() && !config.bootrom_path.empty();
|
!config.movable_sed_path.empty() && !config.bootrom_path.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
MainDialog::MainDialog(QWidget* parent) : QDialog(parent), ui(std::make_unique<Ui::MainDialog>()) {
|
MainDialog::MainDialog(QWidget* parent) : QDialog(parent), ui(std::make_unique<Ui::MainDialog>()) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
||||||
|
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
||||||
ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)->setEnabled(false);
|
|
||||||
ui->buttonBox->button(QDialogButtonBox::StandardButton::Reset)->setText(tr("Refresh"));
|
ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)->setEnabled(false);
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::StandardButton::Reset)->setText(tr("Refresh"));
|
||||||
LoadPresetConfig();
|
|
||||||
|
LoadPresetConfig();
|
||||||
connect(ui->utilitiesButton, &QPushButton::clicked, [this] {
|
|
||||||
UtilitiesDialog dialog(this);
|
connect(ui->utilitiesButton, &QPushButton::clicked, [this] {
|
||||||
dialog.exec();
|
UtilitiesDialog dialog(this);
|
||||||
});
|
dialog.exec();
|
||||||
|
});
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* button) {
|
|
||||||
if (button == ui->buttonBox->button(QDialogButtonBox::StandardButton::Reset)) {
|
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* button) {
|
||||||
LoadPresetConfig();
|
if (button == ui->buttonBox->button(QDialogButtonBox::StandardButton::Reset)) {
|
||||||
} else if (button == ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)) {
|
LoadPresetConfig();
|
||||||
LaunchImportDialog();
|
} else if (button == ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)) {
|
||||||
}
|
LaunchImportDialog();
|
||||||
});
|
}
|
||||||
|
});
|
||||||
QString destination_text{};
|
|
||||||
const auto destination = FileUtil::GetUserPathType();
|
QString destination_text{};
|
||||||
if (destination == FileUtil::UserPathType::Normal) {
|
const auto destination = FileUtil::GetUserPathType();
|
||||||
#ifdef __linux__
|
if (destination == FileUtil::UserPathType::Normal) {
|
||||||
destination_text = tr("Non-Flatpak Citra Install");
|
#ifdef __linux__
|
||||||
#else
|
destination_text = tr("Non-Flatpak Citra Install");
|
||||||
destination_text = tr("User-wide Citra Install");
|
#else
|
||||||
#endif
|
destination_text = tr("User-wide Citra Install");
|
||||||
} else if (destination == FileUtil::UserPathType::Portable) {
|
#endif
|
||||||
destination_text = tr("Portable Citra Install");
|
} else if (destination == FileUtil::UserPathType::Portable) {
|
||||||
} else if (destination == FileUtil::UserPathType::Flatpak) {
|
destination_text = tr("Portable Citra Install");
|
||||||
destination_text = tr("Flatpak Citra Install");
|
} else if (destination == FileUtil::UserPathType::Flatpak) {
|
||||||
} else {
|
destination_text = tr("Flatpak Citra Install");
|
||||||
UNREACHABLE();
|
} else {
|
||||||
}
|
UNREACHABLE();
|
||||||
ui->importDestination->setText(tr("Import Destination: %1").arg(destination_text));
|
}
|
||||||
|
ui->importDestination->setText(tr("Import Destination: %1").arg(destination_text));
|
||||||
connect(ui->main, &QTreeWidget::itemSelectionChanged, [this] {
|
|
||||||
ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)
|
connect(ui->main, &QTreeWidget::itemSelectionChanged, [this] {
|
||||||
->setEnabled(!ui->main->selectedItems().empty());
|
ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)
|
||||||
});
|
->setEnabled(!ui->main->selectedItems().empty());
|
||||||
connect(ui->main, &QTreeWidget::itemDoubleClicked, [this] {
|
});
|
||||||
if (!ui->main->selectedItems().empty())
|
connect(ui->main, &QTreeWidget::itemDoubleClicked, [this] {
|
||||||
LaunchImportDialog();
|
if (!ui->main->selectedItems().empty())
|
||||||
});
|
LaunchImportDialog();
|
||||||
|
});
|
||||||
ui->main->setIndentation(4);
|
|
||||||
ui->main->setColumnWidth(0, 0.3 * width());
|
ui->main->setIndentation(4);
|
||||||
ui->main->setColumnWidth(1, 0.4 * width());
|
ui->main->setColumnWidth(0, 0.3 * width());
|
||||||
ui->main->setColumnWidth(2, 0.2 * width());
|
ui->main->setColumnWidth(1, 0.4 * width());
|
||||||
|
ui->main->setColumnWidth(2, 0.2 * width());
|
||||||
// Set up device watcher
|
|
||||||
auto* device_watcher = new QDeviceWatcher(this);
|
// Set up device watcher
|
||||||
device_watcher->start();
|
auto* device_watcher = new QDeviceWatcher(this);
|
||||||
connect(device_watcher, &QDeviceWatcher::deviceAdded, this, &MainDialog::LoadPresetConfig);
|
device_watcher->start();
|
||||||
connect(device_watcher, &QDeviceWatcher::deviceChanged, this, &MainDialog::LoadPresetConfig);
|
connect(device_watcher, &QDeviceWatcher::deviceAdded, this, &MainDialog::LoadPresetConfig);
|
||||||
connect(device_watcher, &QDeviceWatcher::deviceRemoved, this, &MainDialog::LoadPresetConfig);
|
connect(device_watcher, &QDeviceWatcher::deviceChanged, this, &MainDialog::LoadPresetConfig);
|
||||||
}
|
connect(device_watcher, &QDeviceWatcher::deviceRemoved, this, &MainDialog::LoadPresetConfig);
|
||||||
|
}
|
||||||
MainDialog::~MainDialog() = default;
|
|
||||||
|
MainDialog::~MainDialog() = default;
|
||||||
static const std::regex sdmc_path_regex{"(.+)([/\\\\])Nintendo 3DS/([0-9a-f]{32})/([0-9a-f]{32})/"};
|
|
||||||
|
static const std::regex sdmc_path_regex{"(.+)([/\\\\])Nintendo 3DS/([0-9a-f]{32})/([0-9a-f]{32})/"};
|
||||||
void MainDialog::LoadPresetConfig() {
|
|
||||||
ui->main->clear();
|
void MainDialog::LoadPresetConfig() {
|
||||||
preset_config_list.clear();
|
ui->main->clear();
|
||||||
|
preset_config_list.clear();
|
||||||
for (const auto& storage : QStorageInfo::mountedVolumes()) {
|
|
||||||
if (!storage.isValid() || !storage.isReady()) {
|
for (const auto& storage : QStorageInfo::mountedVolumes()) {
|
||||||
continue;
|
if (!storage.isValid() || !storage.isReady()) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
auto list = Core::LoadPresetConfig(storage.rootPath().toStdString());
|
|
||||||
for (std::size_t i = 0; i < list.size(); ++i) {
|
auto list = Core::LoadPresetConfig(storage.rootPath().toStdString());
|
||||||
preset_config_list.emplace_back(list[i]);
|
for (std::size_t i = 0; i < list.size(); ++i) {
|
||||||
|
preset_config_list.emplace_back(list[i]);
|
||||||
QString path = storage.rootPath();
|
|
||||||
if (path.endsWith(QLatin1Char{'/'}) || path.endsWith(QLatin1Char{'\\'})) {
|
QString path = storage.rootPath();
|
||||||
path.remove(path.size() - 1, 1);
|
if (path.endsWith(QLatin1Char{'/'}) || path.endsWith(QLatin1Char{'\\'})) {
|
||||||
}
|
path.remove(path.size() - 1, 1);
|
||||||
|
}
|
||||||
// Get ID0
|
|
||||||
QString id0 = tr("Unknown");
|
// Get ID0
|
||||||
std::smatch match;
|
QString id0 = tr("Unknown");
|
||||||
if (std::regex_match(list[i].sdmc_path, match, sdmc_path_regex)) {
|
std::smatch match;
|
||||||
if (match.size() >= 5) {
|
if (std::regex_match(list[i].sdmc_path, match, sdmc_path_regex)) {
|
||||||
id0 = QString::fromStdString(match[3].str());
|
if (match.size() >= 5) {
|
||||||
}
|
id0 = QString::fromStdString(match[3].str());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Get status
|
|
||||||
QString status = tr("Good");
|
// Get status
|
||||||
if (!IsConfigGood(list[i])) {
|
QString status = tr("Good");
|
||||||
status = tr("No Configuration Found");
|
if (!IsConfigGood(list[i])) {
|
||||||
} else if (list[i].version != Core::CurrentDumperVersion) {
|
status = tr("No Configuration Found");
|
||||||
status = tr("Version Dismatch");
|
} else if (list[i].version != Core::CurrentDumperVersion) {
|
||||||
} else if (list[i].safe_mode_firm_path.empty() ||
|
status = tr("Version Dismatch");
|
||||||
list[i].config_savegame_path.empty() ||
|
} else if (list[i].safe_mode_firm_path.empty() ||
|
||||||
list[i].system_archives_path.empty()) {
|
list[i].config_savegame_path.empty() ||
|
||||||
|
list[i].system_archives_path.empty()) {
|
||||||
status = tr("Missing System Files");
|
|
||||||
} else if (list[i].seed_db_path.empty()) {
|
status = tr("Missing System Files");
|
||||||
status = tr("Good, Missing Seeds");
|
} else if (list[i].seed_db_path.empty()) {
|
||||||
}
|
status = tr("Good, Missing Seeds");
|
||||||
|
}
|
||||||
auto* item = new QTreeWidgetItem{{path, id0, status}};
|
|
||||||
ui->main->invisibleRootItem()->addChild(item);
|
auto* item = new QTreeWidgetItem{{path, id0, status}};
|
||||||
}
|
ui->main->invisibleRootItem()->addChild(item);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto* item = new QTreeWidgetItem{{tr("Browse SD Card Root...")}};
|
|
||||||
item->setFirstColumnSpanned(true);
|
auto* item = new QTreeWidgetItem{{tr("Browse SD Card Root...")}};
|
||||||
ui->main->invisibleRootItem()->addChild(item);
|
item->setFirstColumnSpanned(true);
|
||||||
}
|
ui->main->invisibleRootItem()->addChild(item);
|
||||||
|
}
|
||||||
void MainDialog::LaunchImportDialog() {
|
|
||||||
auto* item = ui->main->currentItem();
|
void MainDialog::LaunchImportDialog() {
|
||||||
if (!item) {
|
auto* item = ui->main->currentItem();
|
||||||
return;
|
if (!item) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
Core::Config config;
|
|
||||||
const auto index = ui->main->invisibleRootItem()->indexOfChild(item);
|
Core::Config config;
|
||||||
if (index == ui->main->invisibleRootItem()->childCount() - 1) {
|
const auto index = ui->main->invisibleRootItem()->indexOfChild(item);
|
||||||
const QString path = QFileDialog::getExistingDirectory(this, tr("Select SD Card Root"));
|
if (index == ui->main->invisibleRootItem()->childCount() - 1) {
|
||||||
if (path.isEmpty()) {
|
const QString path = QFileDialog::getExistingDirectory(this, tr("Select SD Card Root"));
|
||||||
return;
|
if (path.isEmpty()) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
const auto& list = Core::LoadPresetConfig(path.toStdString());
|
|
||||||
if (list.size() > 1) {
|
const auto& list = Core::LoadPresetConfig(path.toStdString());
|
||||||
QMessageBox::information(
|
if (list.size() > 1) {
|
||||||
this, tr("threeSD"),
|
QMessageBox::information(
|
||||||
tr("You have more than one 3DS data on your SD Card.\nthreeSD will "
|
this, tr("threeSD"),
|
||||||
"select the first one for you."));
|
tr("You have more than one 3DS data on your SD Card.\nthreeSD will "
|
||||||
} else if (list.empty() || !IsConfigGood(list[0])) {
|
"select the first one for you."));
|
||||||
QMessageBox::critical(
|
} else if (list.empty() || !IsConfigGood(list[0])) {
|
||||||
this, tr("Error"),
|
QMessageBox::critical(
|
||||||
tr("Could not load configuration.<br>Please check if you have followed the <a "
|
this, tr("Error"),
|
||||||
"href='https://github.com/zhaowenlan1779/threeSD/wiki/Quickstart-Guide'>"
|
tr("Could not load configuration.<br>Please check if you have followed the <a "
|
||||||
"guide</a> correctly."));
|
"href='https://github.com/zhaowenlan1779/threeSD/wiki/Quickstart-Guide'>"
|
||||||
return;
|
"guide</a> correctly."));
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
config = list[0];
|
|
||||||
} else {
|
config = list[0];
|
||||||
config = preset_config_list.at(index);
|
} else {
|
||||||
}
|
config = preset_config_list.at(index);
|
||||||
|
}
|
||||||
// Check config integrity
|
|
||||||
if (!IsConfigGood(config)) {
|
// Check config integrity
|
||||||
QMessageBox::critical(
|
if (!IsConfigGood(config)) {
|
||||||
this, tr("Error"),
|
QMessageBox::critical(
|
||||||
tr("Could not load configuration from this SD card. You need to prepare your SD card "
|
this, tr("Error"),
|
||||||
"before using threeSD.<br>Please check if you have followed the <a "
|
tr("Could not load configuration from this SD card. You need to prepare your SD card "
|
||||||
"href='https://github.com/zhaowenlan1779/threeSD/wiki/Quickstart-Guide'>"
|
"before using threeSD.<br>Please check if you have followed the <a "
|
||||||
"guide</a> correctly."));
|
"href='https://github.com/zhaowenlan1779/threeSD/wiki/Quickstart-Guide'>"
|
||||||
return;
|
"guide</a> correctly."));
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
if (config.version != Core::CurrentDumperVersion) {
|
|
||||||
QMessageBox::critical(this, tr("Version Dismatch"),
|
if (config.version != Core::CurrentDumperVersion) {
|
||||||
tr("You are using an unsupported version of threeSDumper.<br>Please "
|
QMessageBox::critical(this, tr("Version Dismatch"),
|
||||||
"ensure that you are using the most recent version of both "
|
tr("You are using an unsupported version of threeSDumper.<br>Please "
|
||||||
"threeSD and threeSDumper and try again."));
|
"ensure that you are using the most recent version of both "
|
||||||
return;
|
"threeSD and threeSDumper and try again."));
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
if (config.safe_mode_firm_path.empty() || config.config_savegame_path.empty() ||
|
|
||||||
config.system_archives_path.empty()) {
|
if (config.safe_mode_firm_path.empty() || config.config_savegame_path.empty() ||
|
||||||
QMessageBox::warning(
|
config.system_archives_path.empty()) {
|
||||||
this, tr("Warning"),
|
QMessageBox::warning(
|
||||||
tr("Certain system files are missing from your configuration.<br>Some contents "
|
this, tr("Warning"),
|
||||||
"may not be importable, or may not run.<br>Please check if you have followed the <a "
|
tr("Certain system files are missing from your configuration.<br>Some contents "
|
||||||
"href='https://github.com/zhaowenlan1779/threeSD/wiki/Quickstart-Guide'>guide</a> "
|
"may not be importable, or may not run.<br>Please check if you have followed the <a "
|
||||||
"correctly."));
|
"href='https://github.com/zhaowenlan1779/threeSD/wiki/Quickstart-Guide'>guide</a> "
|
||||||
} else if (config.seed_db_path.empty()) {
|
"correctly."));
|
||||||
QMessageBox::warning(this, tr("Warning"),
|
} else if (config.seed_db_path.empty()) {
|
||||||
tr("Seed database is missing from your configuration.<br>Your system "
|
QMessageBox::warning(this, tr("Warning"),
|
||||||
"likely does not have any seeds.<br>However, if it does have any, "
|
tr("Seed database is missing from your configuration.<br>Your system "
|
||||||
"imported games using seed encryption may not work."));
|
"likely does not have any seeds.<br>However, if it does have any, "
|
||||||
}
|
"imported games using seed encryption may not work."));
|
||||||
|
}
|
||||||
ImportDialog dialog(this, config);
|
|
||||||
dialog.exec();
|
ImportDialog dialog(this, config);
|
||||||
}
|
dialog.exec();
|
||||||
|
}
|
||||||
int main(int argc, char* argv[]) {
|
|
||||||
// Init settings params
|
int main(int argc, char* argv[]) {
|
||||||
QCoreApplication::setOrganizationName(QStringLiteral("zhaowenlan1779"));
|
// Init settings params
|
||||||
QCoreApplication::setApplicationName(QStringLiteral("threeSD"));
|
QCoreApplication::setOrganizationName(QStringLiteral("zhaowenlan1779"));
|
||||||
|
QCoreApplication::setApplicationName(QStringLiteral("threeSD"));
|
||||||
#ifdef __APPLE__
|
|
||||||
std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + "..";
|
#ifdef __APPLE__
|
||||||
chdir(bin_path.c_str());
|
std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + "..";
|
||||||
#endif
|
chdir(bin_path.c_str());
|
||||||
|
#endif
|
||||||
QApplication app(argc, argv);
|
|
||||||
|
QApplication app(argc, argv);
|
||||||
QIcon::setThemeSearchPaths(QStringList(QStringLiteral(":/icons/default")));
|
|
||||||
QIcon::setThemeName(QStringLiteral(":/icons/default"));
|
QIcon::setThemeSearchPaths(QStringList(QStringLiteral(":/icons/default")));
|
||||||
|
QIcon::setThemeName(QStringLiteral(":/icons/default"));
|
||||||
MainDialog main_dialog;
|
|
||||||
main_dialog.show();
|
MainDialog main_dialog;
|
||||||
|
main_dialog.show();
|
||||||
return app.exec();
|
|
||||||
}
|
return app.exec();
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ SelectFilesDialog::SelectFilesDialog(QWidget* parent, bool source_is_dir_, bool
|
|||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
||||||
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ TitleInfoDialog::TitleInfoDialog(QWidget* parent, Core::SDMCImporter& importer_,
|
|||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
||||||
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
||||||
|
|
||||||
|
|||||||
+305
-303
@@ -1,303 +1,305 @@
|
|||||||
// Copyright 2020 threeSD Project
|
// Copyright 2020 threeSD Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QProgressDialog>
|
#include <QProgressDialog>
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
#include "core/file_sys/data/data_container.h"
|
#include "core/file_sys/data/data_container.h"
|
||||||
#include "core/file_sys/data/extdata.h"
|
#include "core/file_sys/data/extdata.h"
|
||||||
#include "core/file_sys/data/savegame.h"
|
#include "core/file_sys/data/savegame.h"
|
||||||
#include "core/file_sys/ncch_container.h"
|
#include "core/file_sys/ncch_container.h"
|
||||||
#include "core/key/key.h"
|
#include "core/key/key.h"
|
||||||
#include "core/sdmc_decryptor.h"
|
#include "core/sdmc_decryptor.h"
|
||||||
#include "frontend/select_files_dialog.h"
|
#include "frontend/select_files_dialog.h"
|
||||||
#include "frontend/utilities.h"
|
#include "frontend/utilities.h"
|
||||||
#include "ui_utilities.h"
|
#include "ui_utilities.h"
|
||||||
|
|
||||||
UtilitiesDialog::UtilitiesDialog(QWidget* parent)
|
UtilitiesDialog::UtilitiesDialog(QWidget* parent)
|
||||||
: QDialog(parent), ui(std::make_unique<Ui::UtilitiesDialog>()) {
|
: QDialog(parent), ui(std::make_unique<Ui::UtilitiesDialog>()) {
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
|
||||||
|
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
|
||||||
connect(ui->useSdDecryption, &QCheckBox::clicked, [this] {
|
|
||||||
const bool checked = ui->useSdDecryption->isChecked();
|
connect(ui->useSdDecryption, &QCheckBox::clicked, [this] {
|
||||||
|
const bool checked = ui->useSdDecryption->isChecked();
|
||||||
ui->boot9Path->setEnabled(checked);
|
|
||||||
ui->boot9PathExplore->setEnabled(checked);
|
ui->boot9Path->setEnabled(checked);
|
||||||
ui->movableSedPath->setEnabled(checked);
|
ui->boot9PathExplore->setEnabled(checked);
|
||||||
ui->movableSedPathExplore->setEnabled(checked);
|
ui->movableSedPath->setEnabled(checked);
|
||||||
ui->sdmcPath->setEnabled(checked);
|
ui->movableSedPathExplore->setEnabled(checked);
|
||||||
ui->sdmcPathExplore->setEnabled(checked);
|
ui->sdmcPath->setEnabled(checked);
|
||||||
|
ui->sdmcPathExplore->setEnabled(checked);
|
||||||
// First hide both, to avoid resizing the dialog
|
|
||||||
ui->sdDecryptionLabel->setVisible(false);
|
// First hide both, to avoid resizing the dialog
|
||||||
ui->sdDecryptionDisabledLabel->setVisible(false);
|
ui->sdDecryptionLabel->setVisible(false);
|
||||||
ui->sdDecryptionLabel->setVisible(checked);
|
ui->sdDecryptionDisabledLabel->setVisible(false);
|
||||||
ui->sdDecryptionDisabledLabel->setVisible(!checked);
|
ui->sdDecryptionLabel->setVisible(checked);
|
||||||
ui->sdDecryption->setEnabled(checked);
|
ui->sdDecryptionDisabledLabel->setVisible(!checked);
|
||||||
|
ui->sdDecryption->setEnabled(checked);
|
||||||
ui->extdataExtractionLabel->setVisible(false);
|
|
||||||
ui->extdataExtractionDisabledLabel->setVisible(false);
|
ui->extdataExtractionLabel->setVisible(false);
|
||||||
ui->extdataExtractionLabel->setVisible(checked);
|
ui->extdataExtractionDisabledLabel->setVisible(false);
|
||||||
ui->extdataExtractionDisabledLabel->setVisible(!checked);
|
ui->extdataExtractionLabel->setVisible(checked);
|
||||||
ui->extdataExtraction->setEnabled(checked);
|
ui->extdataExtractionDisabledLabel->setVisible(!checked);
|
||||||
|
ui->extdataExtraction->setEnabled(checked);
|
||||||
ui->romfsExtractionLabel->setVisible(false);
|
|
||||||
ui->romfsExtractionDisabledLabel->setVisible(false);
|
ui->romfsExtractionLabel->setVisible(false);
|
||||||
ui->romfsExtractionLabel->setVisible(!checked);
|
ui->romfsExtractionDisabledLabel->setVisible(false);
|
||||||
ui->romfsExtractionDisabledLabel->setVisible(checked);
|
ui->romfsExtractionLabel->setVisible(!checked);
|
||||||
ui->romfsExtraction->setEnabled(!checked);
|
ui->romfsExtractionDisabledLabel->setVisible(checked);
|
||||||
});
|
ui->romfsExtraction->setEnabled(!checked);
|
||||||
|
});
|
||||||
connect(ui->boot9PathExplore, &QToolButton::clicked, [this] {
|
|
||||||
const QString path = QFileDialog::getOpenFileName(this, tr("Select File"));
|
connect(ui->boot9PathExplore, &QToolButton::clicked, [this] {
|
||||||
if (!path.isEmpty()) {
|
const QString path = QFileDialog::getOpenFileName(this, tr("Select File"));
|
||||||
ui->boot9Path->setText(path);
|
if (!path.isEmpty()) {
|
||||||
}
|
ui->boot9Path->setText(path);
|
||||||
});
|
}
|
||||||
connect(ui->movableSedPathExplore, &QToolButton::clicked, [this] {
|
});
|
||||||
const QString path = QFileDialog::getOpenFileName(this, tr("Select File"));
|
connect(ui->movableSedPathExplore, &QToolButton::clicked, [this] {
|
||||||
if (!path.isEmpty()) {
|
const QString path = QFileDialog::getOpenFileName(this, tr("Select File"));
|
||||||
ui->movableSedPath->setText(path);
|
if (!path.isEmpty()) {
|
||||||
}
|
ui->movableSedPath->setText(path);
|
||||||
});
|
}
|
||||||
connect(ui->sdmcPathExplore, &QToolButton::clicked, [this] {
|
});
|
||||||
const QString path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
|
connect(ui->sdmcPathExplore, &QToolButton::clicked, [this] {
|
||||||
if (!path.isEmpty()) {
|
const QString path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
|
||||||
ui->sdmcPath->setText(path);
|
if (!path.isEmpty()) {
|
||||||
}
|
ui->sdmcPath->setText(path);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
connect(ui->sdDecryption, &QPushButton::clicked, this, &UtilitiesDialog::SDDecryptionTool);
|
|
||||||
connect(ui->savedataExtraction, &QPushButton::clicked, this,
|
connect(ui->sdDecryption, &QPushButton::clicked, this, &UtilitiesDialog::SDDecryptionTool);
|
||||||
&UtilitiesDialog::SaveDataExtractionTool);
|
connect(ui->savedataExtraction, &QPushButton::clicked, this,
|
||||||
connect(ui->extdataExtraction, &QPushButton::clicked, this,
|
&UtilitiesDialog::SaveDataExtractionTool);
|
||||||
&UtilitiesDialog::ExtdataExtractionTool);
|
connect(ui->extdataExtraction, &QPushButton::clicked, this,
|
||||||
connect(ui->romfsExtraction, &QPushButton::clicked, this,
|
&UtilitiesDialog::ExtdataExtractionTool);
|
||||||
&UtilitiesDialog::RomFSExtractionTool);
|
connect(ui->romfsExtraction, &QPushButton::clicked, this,
|
||||||
}
|
&UtilitiesDialog::RomFSExtractionTool);
|
||||||
|
}
|
||||||
UtilitiesDialog::~UtilitiesDialog() = default;
|
|
||||||
|
UtilitiesDialog::~UtilitiesDialog() = default;
|
||||||
std::pair<QString, QString> UtilitiesDialog::GetFilePaths(bool source_is_dir,
|
|
||||||
bool destination_is_dir) {
|
std::pair<QString, QString> UtilitiesDialog::GetFilePaths(bool source_is_dir,
|
||||||
|
bool destination_is_dir) {
|
||||||
SelectFilesDialog dialog(this, source_is_dir, destination_is_dir);
|
|
||||||
if (dialog.exec() == QDialog::Accepted) {
|
SelectFilesDialog dialog(this, source_is_dir, destination_is_dir);
|
||||||
return dialog.GetResults();
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
} else {
|
return dialog.GetResults();
|
||||||
return {};
|
} else {
|
||||||
}
|
return {};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
bool UtilitiesDialog::LoadSDKeys() {
|
|
||||||
if (ui->boot9Path->text().isEmpty() || ui->movableSedPath->text().isEmpty()) {
|
bool UtilitiesDialog::LoadSDKeys() {
|
||||||
QMessageBox::critical(this, tr("Error"),
|
if (ui->boot9Path->text().isEmpty() || ui->movableSedPath->text().isEmpty()) {
|
||||||
tr("Please select boot9.bin and movable.sed paths."));
|
QMessageBox::critical(this, tr("Error"),
|
||||||
return false;
|
tr("Please select boot9.bin and movable.sed paths."));
|
||||||
}
|
return false;
|
||||||
if (ui->sdmcPath->text().isEmpty()) {
|
}
|
||||||
QMessageBox::critical(this, tr("Error"),
|
if (ui->sdmcPath->text().isEmpty()) {
|
||||||
tr("Please select SDMC root (\"Nintendo 3DS/<ID0>/<ID1>\")."));
|
QMessageBox::critical(this, tr("Error"),
|
||||||
return false;
|
tr("Please select SDMC root (\"Nintendo 3DS/<ID0>/<ID1>\")."));
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
Core::Key::ClearKeys();
|
|
||||||
Core::Key::LoadBootromKeys(ui->boot9Path->text().toStdString());
|
Core::Key::ClearKeys();
|
||||||
Core::Key::LoadMovableSedKeys(ui->movableSedPath->text().toStdString());
|
Core::Key::LoadBootromKeys(ui->boot9Path->text().toStdString());
|
||||||
|
Core::Key::LoadMovableSedKeys(ui->movableSedPath->text().toStdString());
|
||||||
if (!Core::Key::IsNormalKeyAvailable(Core::Key::SDKey)) {
|
|
||||||
LOG_ERROR(Core, "SDKey is not available");
|
if (!Core::Key::IsNormalKeyAvailable(Core::Key::SDKey)) {
|
||||||
QMessageBox::critical(this, tr("Error"),
|
LOG_ERROR(Core, "SDKey is not available");
|
||||||
tr("Could not load SD Key. Please check your files."));
|
QMessageBox::critical(this, tr("Error"),
|
||||||
return false;
|
tr("Could not load SD Key. Please check your files."));
|
||||||
}
|
return false;
|
||||||
return true;
|
}
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
void UtilitiesDialog::ShowProgressDialog(std::function<bool()> operation) {
|
|
||||||
auto* dialog = new QProgressDialog(tr("Processing..."), tr("Cancel"), 0, 0, this);
|
void UtilitiesDialog::ShowProgressDialog(std::function<bool()> operation) {
|
||||||
dialog->setWindowModality(Qt::WindowModal);
|
auto* dialog = new QProgressDialog(tr("Processing..."), tr("Cancel"), 0, 0, this);
|
||||||
dialog->setCancelButton(nullptr);
|
dialog->setWindowFlags(dialog->windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
dialog->setMinimumDuration(0);
|
dialog->setWindowModality(Qt::WindowModal);
|
||||||
dialog->setValue(0);
|
dialog->setCancelButton(nullptr);
|
||||||
|
dialog->setMinimumDuration(0);
|
||||||
using FutureWatcher = QFutureWatcher<void>;
|
dialog->setValue(0);
|
||||||
auto* future_watcher = new FutureWatcher(this);
|
|
||||||
connect(future_watcher, &FutureWatcher::finished, this, [this, dialog] {
|
using FutureWatcher = QFutureWatcher<void>;
|
||||||
dialog->hide();
|
auto* future_watcher = new FutureWatcher(this);
|
||||||
ShowResult();
|
connect(future_watcher, &FutureWatcher::finished, this, [this, dialog] {
|
||||||
});
|
dialog->hide();
|
||||||
|
ShowResult();
|
||||||
auto future = QtConcurrent::run([operation, this] { result = operation(); });
|
});
|
||||||
future_watcher->setFuture(future);
|
|
||||||
}
|
auto future = QtConcurrent::run([operation, this] { result = operation(); });
|
||||||
|
future_watcher->setFuture(future);
|
||||||
std::tuple<bool, std::string, std::string> UtilitiesDialog::GetSDMCRoot(const QString& source) {
|
}
|
||||||
QString sdmc_root = ui->sdmcPath->text().replace(QLatin1Char{'\\'}, QLatin1Char{'/'});
|
|
||||||
if (!sdmc_root.endsWith(QLatin1Char{'/'})) {
|
std::tuple<bool, std::string, std::string> UtilitiesDialog::GetSDMCRoot(const QString& source) {
|
||||||
sdmc_root.append(QLatin1Char{'/'});
|
QString sdmc_root = ui->sdmcPath->text().replace(QLatin1Char{'\\'}, QLatin1Char{'/'});
|
||||||
}
|
if (!sdmc_root.endsWith(QLatin1Char{'/'})) {
|
||||||
if (!source.startsWith(sdmc_root)) {
|
sdmc_root.append(QLatin1Char{'/'});
|
||||||
QMessageBox::critical(this, tr("Error"), tr("The file selected is not in SDMC root."));
|
}
|
||||||
return {false, "", ""};
|
if (!source.startsWith(sdmc_root)) {
|
||||||
}
|
QMessageBox::critical(this, tr("Error"), tr("The file selected is not in SDMC root."));
|
||||||
const std::string relative_source =
|
return {false, "", ""};
|
||||||
source.toStdString().substr(sdmc_root.toStdString().size() - 1);
|
}
|
||||||
|
const std::string relative_source =
|
||||||
return {true, sdmc_root.toStdString(), relative_source};
|
source.toStdString().substr(sdmc_root.toStdString().size() - 1);
|
||||||
}
|
|
||||||
|
return {true, sdmc_root.toStdString(), relative_source};
|
||||||
void UtilitiesDialog::SDDecryptionTool() {
|
}
|
||||||
if (!LoadSDKeys()) {
|
|
||||||
return;
|
void UtilitiesDialog::SDDecryptionTool() {
|
||||||
}
|
if (!LoadSDKeys()) {
|
||||||
const auto& [source, destination] = GetFilePaths(false, false);
|
return;
|
||||||
if (source.isEmpty() || destination.isEmpty()) {
|
}
|
||||||
return;
|
const auto& [source, destination] = GetFilePaths(false, false);
|
||||||
}
|
if (source.isEmpty() || destination.isEmpty()) {
|
||||||
|
return;
|
||||||
const auto& [success, sdmc_root, relative_source] = GetSDMCRoot(source);
|
}
|
||||||
if (!success) {
|
|
||||||
return;
|
const auto& [success, sdmc_root, relative_source] = GetSDMCRoot(source);
|
||||||
}
|
if (!success) {
|
||||||
// TODO: Add Progress reporting
|
return;
|
||||||
ShowProgressDialog(
|
}
|
||||||
[sdmc_root = sdmc_root, relative_source = relative_source, destination = destination] {
|
// TODO: Add Progress reporting
|
||||||
Core::SDMCDecryptor decryptor(sdmc_root);
|
ShowProgressDialog(
|
||||||
return decryptor.DecryptAndWriteFile(relative_source, destination.toStdString());
|
[sdmc_root = sdmc_root, relative_source = relative_source, destination = destination] {
|
||||||
});
|
Core::SDMCDecryptor decryptor(sdmc_root);
|
||||||
}
|
return decryptor.DecryptAndWriteFile(relative_source, destination.toStdString());
|
||||||
|
});
|
||||||
void UtilitiesDialog::SaveDataExtractionTool() {
|
}
|
||||||
const bool decryption = ui->useSdDecryption->isChecked();
|
|
||||||
if (decryption && !LoadSDKeys()) {
|
void UtilitiesDialog::SaveDataExtractionTool() {
|
||||||
return;
|
const bool decryption = ui->useSdDecryption->isChecked();
|
||||||
}
|
if (decryption && !LoadSDKeys()) {
|
||||||
const auto& [source, destination] = GetFilePaths(false, true);
|
return;
|
||||||
if (source.isEmpty() || destination.isEmpty()) {
|
}
|
||||||
return;
|
const auto& [source, destination] = GetFilePaths(false, true);
|
||||||
}
|
if (source.isEmpty() || destination.isEmpty()) {
|
||||||
|
return;
|
||||||
if (decryption) {
|
}
|
||||||
const auto& [success, sdmc_root, relative_source] = GetSDMCRoot(source);
|
|
||||||
if (!success) {
|
if (decryption) {
|
||||||
return;
|
const auto& [success, sdmc_root, relative_source] = GetSDMCRoot(source);
|
||||||
}
|
if (!success) {
|
||||||
|
return;
|
||||||
// TODO: Add Progress reporting
|
}
|
||||||
ShowProgressDialog([sdmc_root = sdmc_root, relative_source = relative_source,
|
|
||||||
source = source, destination = destination] {
|
// TODO: Add Progress reporting
|
||||||
const auto size = FileUtil::GetSize(source.toStdString());
|
ShowProgressDialog([sdmc_root = sdmc_root, relative_source = relative_source,
|
||||||
std::vector<u8> data(size);
|
source = source, destination = destination] {
|
||||||
Core::SDMCFile file(sdmc_root, relative_source, "rb");
|
const auto size = FileUtil::GetSize(source.toStdString());
|
||||||
if (file.ReadBytes(data.data(), size) != size) {
|
std::vector<u8> data(size);
|
||||||
return false;
|
Core::SDMCFile file(sdmc_root, relative_source, "rb");
|
||||||
}
|
if (file.ReadBytes(data.data(), size) != size) {
|
||||||
|
return false;
|
||||||
Core::DataContainer container(data);
|
}
|
||||||
if (!container.IsGood()) {
|
|
||||||
return false;
|
Core::DataContainer container(data);
|
||||||
}
|
if (!container.IsGood()) {
|
||||||
|
return false;
|
||||||
std::vector<std::vector<u8>> container_data;
|
}
|
||||||
if (!container.GetIVFCLevel4Data(container_data)) {
|
|
||||||
return false;
|
std::vector<std::vector<u8>> container_data;
|
||||||
}
|
if (!container.GetIVFCLevel4Data(container_data)) {
|
||||||
|
return false;
|
||||||
Core::Savegame save(std::move(container_data));
|
}
|
||||||
if (!save.IsGood()) {
|
|
||||||
return false;
|
Core::Savegame save(std::move(container_data));
|
||||||
}
|
if (!save.IsGood()) {
|
||||||
|
return false;
|
||||||
return save.Extract(destination.toStdString());
|
}
|
||||||
});
|
|
||||||
} else {
|
return save.Extract(destination.toStdString());
|
||||||
// TODO: Add Progress reporting
|
});
|
||||||
ShowProgressDialog([source = source, destination = destination] {
|
} else {
|
||||||
FileUtil::IOFile file(source.toStdString(), "rb");
|
// TODO: Add Progress reporting
|
||||||
std::vector<u8> data = file.GetData();
|
ShowProgressDialog([source = source, destination = destination] {
|
||||||
if (data.empty()) {
|
FileUtil::IOFile file(source.toStdString(), "rb");
|
||||||
return false;
|
std::vector<u8> data = file.GetData();
|
||||||
}
|
if (data.empty()) {
|
||||||
|
return false;
|
||||||
Core::DataContainer container(data);
|
}
|
||||||
if (!container.IsGood()) {
|
|
||||||
return false;
|
Core::DataContainer container(data);
|
||||||
}
|
if (!container.IsGood()) {
|
||||||
|
return false;
|
||||||
std::vector<std::vector<u8>> container_data;
|
}
|
||||||
if (!container.GetIVFCLevel4Data(container_data)) {
|
|
||||||
return false;
|
std::vector<std::vector<u8>> container_data;
|
||||||
}
|
if (!container.GetIVFCLevel4Data(container_data)) {
|
||||||
|
return false;
|
||||||
Core::Savegame save(std::move(container_data));
|
}
|
||||||
if (!save.IsGood()) {
|
|
||||||
return false;
|
Core::Savegame save(std::move(container_data));
|
||||||
}
|
if (!save.IsGood()) {
|
||||||
|
return false;
|
||||||
return save.Extract(destination.toStdString());
|
}
|
||||||
});
|
|
||||||
}
|
return save.Extract(destination.toStdString());
|
||||||
}
|
});
|
||||||
|
}
|
||||||
void UtilitiesDialog::ExtdataExtractionTool() {
|
}
|
||||||
if (!LoadSDKeys()) {
|
|
||||||
return;
|
void UtilitiesDialog::ExtdataExtractionTool() {
|
||||||
}
|
if (!LoadSDKeys()) {
|
||||||
const auto& [source, destination] = GetFilePaths(true, true);
|
return;
|
||||||
if (source.isEmpty() || destination.isEmpty()) {
|
}
|
||||||
return;
|
const auto& [source, destination] = GetFilePaths(true, true);
|
||||||
}
|
if (source.isEmpty() || destination.isEmpty()) {
|
||||||
|
return;
|
||||||
const auto& [success, sdmc_root, relative_source] = GetSDMCRoot(source);
|
}
|
||||||
if (!success) {
|
|
||||||
return;
|
const auto& [success, sdmc_root, relative_source] = GetSDMCRoot(source);
|
||||||
}
|
if (!success) {
|
||||||
// TODO: Add Progress reporting
|
return;
|
||||||
ShowProgressDialog(
|
}
|
||||||
[sdmc_root = sdmc_root, relative_source = relative_source, destination = destination] {
|
// TODO: Add Progress reporting
|
||||||
Core::SDMCDecryptor decryptor(sdmc_root);
|
ShowProgressDialog(
|
||||||
Core::Extdata extdata(relative_source, decryptor);
|
[sdmc_root = sdmc_root, relative_source = relative_source, destination = destination] {
|
||||||
if (!extdata.IsGood()) {
|
Core::SDMCDecryptor decryptor(sdmc_root);
|
||||||
return false;
|
Core::Extdata extdata(relative_source, decryptor);
|
||||||
}
|
if (!extdata.IsGood()) {
|
||||||
|
return false;
|
||||||
return extdata.Extract(destination.toStdString());
|
}
|
||||||
});
|
|
||||||
}
|
return extdata.Extract(destination.toStdString());
|
||||||
|
});
|
||||||
void UtilitiesDialog::RomFSExtractionTool() {
|
}
|
||||||
const auto& [source, destination] = GetFilePaths(false, false);
|
|
||||||
if (source.isEmpty() || destination.isEmpty()) {
|
void UtilitiesDialog::RomFSExtractionTool() {
|
||||||
return;
|
const auto& [source, destination] = GetFilePaths(false, false);
|
||||||
}
|
if (source.isEmpty() || destination.isEmpty()) {
|
||||||
|
return;
|
||||||
ShowProgressDialog([source = source, destination = destination] {
|
}
|
||||||
FileUtil::IOFile src_file(source.toStdString(), "rb");
|
|
||||||
std::vector<u8> data = src_file.GetData();
|
ShowProgressDialog([source = source, destination = destination] {
|
||||||
if (data.empty()) {
|
FileUtil::IOFile src_file(source.toStdString(), "rb");
|
||||||
return false;
|
std::vector<u8> data = src_file.GetData();
|
||||||
}
|
if (data.empty()) {
|
||||||
|
return false;
|
||||||
const auto& shared_romfs = Core::LoadSharedRomFS(data);
|
}
|
||||||
return FileUtil::WriteBytesToFile(destination.toStdString(), shared_romfs.data(),
|
|
||||||
shared_romfs.size());
|
const auto& shared_romfs = Core::LoadSharedRomFS(data);
|
||||||
});
|
return FileUtil::WriteBytesToFile(destination.toStdString(), shared_romfs.data(),
|
||||||
}
|
shared_romfs.size());
|
||||||
|
});
|
||||||
void UtilitiesDialog::ShowResult() {
|
}
|
||||||
if (result) {
|
|
||||||
QMessageBox::information(this, tr("Success"), tr("Operation completed successfully."));
|
void UtilitiesDialog::ShowResult() {
|
||||||
} else {
|
if (result) {
|
||||||
QMessageBox::critical(this, tr("Error"),
|
QMessageBox::information(this, tr("Success"), tr("Operation completed successfully."));
|
||||||
tr("An error occured while performing the operation."));
|
} else {
|
||||||
}
|
QMessageBox::critical(this, tr("Error"),
|
||||||
}
|
tr("An error occured while performing the operation."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user