mirror of
https://github.com/Dark98/threeSD.git
synced 2026-07-03 08:39:04 +00:00
Add CIABuildDialog
This commit is contained in:
@@ -13,6 +13,9 @@ add_executable(threeSD
|
||||
helpers/multi_job.h
|
||||
helpers/simple_job.cpp
|
||||
helpers/simple_job.h
|
||||
cia_build_dialog.cpp
|
||||
cia_build_dialog.h
|
||||
cia_build_dialog.ui
|
||||
import_dialog.cpp
|
||||
import_dialog.h
|
||||
import_dialog.ui
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// Copyright 2021 threeSD Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <QDesktopWidget>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include "common/assert.h"
|
||||
#include "frontend/cia_build_dialog.h"
|
||||
#include "ui_cia_build_dialog.h"
|
||||
|
||||
CIABuildDialog::CIABuildDialog(QWidget* parent, bool is_dir_, bool is_nand, bool enable_legit,
|
||||
const QString& default_path)
|
||||
: QDialog(parent), ui(std::make_unique<Ui::CIABuildDialog>()), is_dir(is_dir_) {
|
||||
ui->setupUi(this);
|
||||
|
||||
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_nand) {
|
||||
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) {
|
||||
message.append(tr(
|
||||
"Legit tickets for these titles do not include console-identifying information."));
|
||||
} else {
|
||||
message.append(tr(
|
||||
"Legit ticket for this title does not include console-identifying information."));
|
||||
}
|
||||
ui->legitLabel->setText(message);
|
||||
}
|
||||
if (!enable_legit) {
|
||||
const auto message =
|
||||
is_dir ? tr("This option is not available as some of the titles are not legit.")
|
||||
: tr("This option is not available as the title is not legit.");
|
||||
ui->pirateLegitButton->setEnabled(false);
|
||||
ui->pirateLegitLabel->setText(message);
|
||||
ui->legitButton->setEnabled(false);
|
||||
ui->legitLabel->setText(message);
|
||||
}
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, [this] {
|
||||
if (ui->destination->text().isEmpty()) {
|
||||
const QString message = is_dir ? tr("Please specify destination folder.")
|
||||
: tr("Please specify destination file.");
|
||||
QMessageBox::warning(this, tr("threeSD"), message);
|
||||
return;
|
||||
}
|
||||
accept();
|
||||
});
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &CIABuildDialog::reject);
|
||||
|
||||
if (is_dir) {
|
||||
ui->destination->setText(default_path);
|
||||
}
|
||||
connect(ui->destinationExplore, &QToolButton::clicked, [this, default_path] {
|
||||
QString path;
|
||||
if (is_dir) {
|
||||
path = QFileDialog::getExistingDirectory(this, tr("Batch Build CIA"),
|
||||
ui->destination->text());
|
||||
} else {
|
||||
const auto cur = ui->destination->text().isEmpty()
|
||||
? default_path
|
||||
: QFileInfo(ui->destination->text()).path();
|
||||
path = QFileDialog::getSaveFileName(this, tr("Build CIA"), cur,
|
||||
tr("CTR Importable Archive (*.cia)"));
|
||||
}
|
||||
if (!path.isEmpty()) {
|
||||
ui->destination->setText(path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
CIABuildDialog::~CIABuildDialog() = default;
|
||||
|
||||
std::pair<QString, Core::CIABuildType> CIABuildDialog::GetResults() const {
|
||||
Core::CIABuildType type;
|
||||
if (ui->standardButton->isChecked()) {
|
||||
type = Core::CIABuildType::Standard;
|
||||
} else if (ui->pirateLegitButton->isChecked()) {
|
||||
type = Core::CIABuildType::PirateLegit;
|
||||
} else if (ui->legitButton->isChecked()) {
|
||||
type = Core::CIABuildType::Legit;
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
return {ui->destination->text(), type};
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2021 threeSD Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <QDialog>
|
||||
#include "core/ncch/cia_common.h"
|
||||
|
||||
namespace Ui {
|
||||
class CIABuildDialog;
|
||||
}
|
||||
|
||||
class CIABuildDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CIABuildDialog(QWidget* parent, bool is_dir, bool is_nand, bool enable_legit,
|
||||
const QString& default_path);
|
||||
~CIABuildDialog();
|
||||
|
||||
std::pair<QString, Core::CIABuildType> GetResults() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::CIABuildDialog> ui;
|
||||
bool is_dir;
|
||||
};
|
||||
@@ -0,0 +1,125 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CIABuildDialog</class>
|
||||
<widget class="QDialog" name="CIABuildDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>510</width>
|
||||
<height>260</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Build CIA</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel">
|
||||
<property name="text">
|
||||
<string>Destination:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="destination"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="destinationExplore">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox">
|
||||
<property name="title">
|
||||
<string>Build Type</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="standardButton">
|
||||
<property name="text">
|
||||
<string>Standard</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel">
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Recommended for general use.<br>Decrypted CIA with decrypted contents and standard ticket.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="pirateLegitButton">
|
||||
<property name="text">
|
||||
<string>Legit with standard ticket ("pirate legit")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="pirateLegitLabel">
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Encrypted CIA with legit TMD, encrypted contents and standard ticket.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="legitButton">
|
||||
<property name="text">
|
||||
<string>Legit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="legitLabel">
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Encrypted CIA with legit TMD, encrypted contents and legit ticket.<br>WARNING: Legit ticket may include console identifying information!</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok|QDialogButtonBox::Cancel</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "common/progress_callback.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "frontend/cia_build_dialog.h"
|
||||
#include "frontend/helpers/multi_job.h"
|
||||
#include "frontend/helpers/simple_job.h"
|
||||
#include "frontend/import_dialog.h"
|
||||
@@ -788,18 +789,21 @@ void ImportDialog::StartBatchDumpingCXI() {
|
||||
// CIA building
|
||||
|
||||
void ImportDialog::StartBuildingCIASingle(const Core::ContentSpecifier& specifier) {
|
||||
const QString path = QFileDialog::getSaveFileName(this, tr("Build CIA"), last_build_cia_path,
|
||||
tr("CTR Importable Archive (*.cia)"));
|
||||
if (path.isEmpty()) {
|
||||
CIABuildDialog dialog(this,
|
||||
/*is_dir*/ false,
|
||||
/*is_nand*/ specifier.type == Core::ContentType::SystemTitle,
|
||||
/*enable_legit*/ importer.CanBuildLegitCIA(specifier),
|
||||
last_build_cia_path);
|
||||
if (dialog.exec() != QDialog::Accepted) {
|
||||
return;
|
||||
}
|
||||
const auto& [path, type] = dialog.GetResults();
|
||||
last_build_cia_path = QFileInfo(path).path();
|
||||
|
||||
auto* job = new SimpleJob(
|
||||
this,
|
||||
[this, specifier, path](const Common::ProgressCallback& callback) {
|
||||
return importer.BuildCIA(Core::CIABuildType::Standard, specifier, path.toStdString(),
|
||||
callback);
|
||||
[this, specifier, path = path, type = type](const Common::ProgressCallback& callback) {
|
||||
return importer.BuildCIA(type, specifier, path.toStdString(), callback);
|
||||
},
|
||||
[this] { importer.AbortBuildCIA(); });
|
||||
RunSimpleJob(job);
|
||||
@@ -835,11 +839,19 @@ void ImportDialog::StartBatchBuildingCIA() {
|
||||
|
||||
to_import.erase(removed_iter, to_import.end());
|
||||
|
||||
QString path =
|
||||
QFileDialog::getExistingDirectory(this, tr("Batch Build CIA"), last_batch_build_cia_path);
|
||||
if (path.isEmpty()) {
|
||||
const bool is_nand = std::all_of(to_import.begin(), to_import.end(),
|
||||
[](const Core::ContentSpecifier& specifier) {
|
||||
return specifier.type == Core::ContentType::SystemTitle;
|
||||
});
|
||||
const bool enable_legit = std::all_of(to_import.begin(), to_import.end(),
|
||||
[this](const Core::ContentSpecifier& specifier) {
|
||||
return importer.CanBuildLegitCIA(specifier);
|
||||
});
|
||||
CIABuildDialog dialog(this, /*is_dir*/ true, is_nand, enable_legit, last_batch_build_cia_path);
|
||||
if (dialog.exec() != QDialog::Accepted) {
|
||||
return;
|
||||
}
|
||||
auto [path, type] = dialog.GetResults();
|
||||
last_batch_build_cia_path = path;
|
||||
if (!path.endsWith(QChar::fromLatin1('/')) && !path.endsWith(QChar::fromLatin1('\\'))) {
|
||||
path.append(QStringLiteral("/"));
|
||||
@@ -853,10 +865,10 @@ void ImportDialog::StartBatchBuildingCIA() {
|
||||
});
|
||||
auto* job = new MultiJob(
|
||||
this, importer, std::move(to_import),
|
||||
[path](Core::SDMCImporter& importer, const Core::ContentSpecifier& specifier,
|
||||
const Common::ProgressCallback& callback) {
|
||||
return importer.BuildCIA(Core::CIABuildType::Standard, specifier, path.toStdString(),
|
||||
callback, true);
|
||||
[path = path, type = type](Core::SDMCImporter& importer,
|
||||
const Core::ContentSpecifier& specifier,
|
||||
const Common::ProgressCallback& callback) {
|
||||
return importer.BuildCIA(type, specifier, path.toStdString(), callback, true);
|
||||
},
|
||||
&Core::SDMCImporter::AbortBuildCIA);
|
||||
RunMultiJob(job, total_count, total_size);
|
||||
|
||||
Reference in New Issue
Block a user