Really properly be per-monitor DPI aware

This is so hard...
This commit is contained in:
Pengfei
2021-08-17 00:30:08 +08:00
parent d78c1cb734
commit 0cf7e8a84a
21 changed files with 656 additions and 621 deletions
+2
View File
@@ -9,6 +9,8 @@ endif()
file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/themes/*)
add_executable(threeSD
helpers/dpi_aware_dialog.cpp
helpers/dpi_aware_dialog.h
helpers/frontend_common.cpp
helpers/frontend_common.h
helpers/multi_job.cpp
+3 -4
View File
@@ -12,12 +12,11 @@
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);
: DPIAwareDialog(parent, 510, 260), ui(std::make_unique<Ui::CIABuildDialog>()),
is_dir(is_dir_) {
ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
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"));
+2 -2
View File
@@ -6,14 +6,14 @@
#include <memory>
#include <utility>
#include <QDialog>
#include "core/file_sys/cia_common.h"
#include "frontend/helpers/dpi_aware_dialog.h"
namespace Ui {
class CIABuildDialog;
}
class CIABuildDialog : public QDialog {
class CIABuildDialog : public DPIAwareDialog {
Q_OBJECT
public:
-17
View File
@@ -2,14 +2,6 @@
<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>
@@ -59,9 +51,6 @@
</item>
<item>
<widget class="QLabel">
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="text">
<string>Recommended for general use.&lt;br&gt;Decrypted CIA with decrypted contents and standard ticket.</string>
</property>
@@ -76,9 +65,6 @@
</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>
@@ -93,9 +79,6 @@
</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.&lt;br&gt;WARNING: Legit ticket may include console identifying information!</string>
</property>
+68
View File
@@ -0,0 +1,68 @@
// Copyright 2021 threeSD Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <QScreen>
#include <QWindow>
#include "common/logging/log.h"
#include "frontend/helpers/dpi_aware_dialog.h"
DPIAwareDialog::DPIAwareDialog(QWidget* parent, int width, int height)
: QDialog(parent), original_width(width), original_height(height) {}
DPIAwareDialog::~DPIAwareDialog() = default;
void DPIAwareDialog::showEvent(QShowEvent* event) {
QDialog::showEvent(event);
if (window_handle) {
return;
}
// Initialize window_handle and connections
window_handle = windowHandle();
if (!window_handle) {
return;
}
#ifdef __APPLE__
// Note: macOS implements system level virtualization, so there's no need to connect here.
// but we still need to call SetContentSizes() at least once to set up the UI
resize(original_width, original_height);
SetContentSizes();
#else
resized = false;
connect(window_handle, &QWindow::screenChanged, this, &DPIAwareDialog::OnScreenChanged);
OnScreenChanged();
#endif
}
void DPIAwareDialog::resizeEvent(QResizeEvent* event) {
QDialog::resizeEvent(event);
resized = true;
}
#ifndef __APPLE__
void DPIAwareDialog::OnScreenChanged() {
// Resize according to DPI
const double scaleX = window_handle->screen()->logicalDotsPerInchX() / 96.0;
const double scaleY = window_handle->screen()->logicalDotsPerInchY() / 96.0;
if (resized) {
const int new_width = static_cast<int>(scaleX * width() / previous_scaleX);
const int new_height = static_cast<int>(scaleY * height() / previous_scaleY);
setMinimumSize(0, 0); // Enforce this resize
resize(new_width, new_height);
} else {
const int new_width = static_cast<int>(original_width * scaleX);
const int new_height = static_cast<int>(original_height * scaleY);
setMinimumSize(new_width, new_height);
adjustSize();
resized = false; // This resize isn't user-initiated
}
SetContentSizes(previous_width, previous_height);
previous_scaleX = scaleX;
previous_scaleY = scaleY;
previous_width = width();
previous_height = height();
}
#endif
+36
View File
@@ -0,0 +1,36 @@
// Copyright 2021 threeSD Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <QDialog>
class DPIAwareDialog : public QDialog {
public:
explicit DPIAwareDialog(QWidget* parent, int width, int height);
~DPIAwareDialog() override;
protected:
void showEvent(QShowEvent* event) override;
void resizeEvent(QResizeEvent* event) override;
// Called with two zeroes to set up content sizes that are relative to dialog size. Also called
// when screen is changed, to update those sizes.
virtual void SetContentSizes(int previous_width, int previous_height){};
private:
#ifndef __APPLE__
void OnScreenChanged();
#endif
QWindow* window_handle{};
const int original_width{};
const int original_height{};
bool resized = false; // whether this dialog has been manually resized
double previous_scaleX{};
double previous_scaleY{};
int previous_width{};
int previous_height{};
};
+16 -11
View File
@@ -82,17 +82,14 @@ static QPixmap GetContentIcon(const Core::ContentSpecifier& specifier,
}
ImportDialog::ImportDialog(QWidget* parent, const Core::Config& config_)
: QDialog(parent), ui(std::make_unique<Ui::ImportDialog>()), config(config_) {
: DPIAwareDialog(parent, 560, 320), ui(std::make_unique<Ui::ImportDialog>()), config(config_) {
qRegisterMetaType<u64>("u64");
qRegisterMetaType<std::size_t>("std::size_t");
qRegisterMetaType<Core::ContentSpecifier>();
ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
RelistContent();
UpdateSizeDisplay();
@@ -113,18 +110,26 @@ ImportDialog::ImportDialog(QWidget* parent, const Core::Config& config_)
connect(ui->title_view_button, &QRadioButton::toggled, this, &ImportDialog::RepopulateContent);
connect(ui->advanced_button, &QPushButton::clicked, this, &ImportDialog::ShowAdvancedMenu);
// Set up column widths.
// These values are tweaked with regard to the default dialog size.
ui->main->setColumnWidth(0, width() * 0.11);
ui->main->setColumnWidth(1, width() * 0.525);
ui->main->setColumnWidth(2, width() * 0.18);
ui->main->setColumnWidth(3, width() * 0.10);
ui->main->header()->setStretchLastSection(false);
connect(ui->main, &QTreeWidget::customContextMenuRequested, this, &ImportDialog::OnContextMenu);
}
ImportDialog::~ImportDialog() = default;
void ImportDialog::SetContentSizes(int previous_width, int previous_height) {
const int current_width = width();
if (previous_width == 0) { // first time
ui->main->setColumnWidth(0, current_width * 0.11);
ui->main->setColumnWidth(1, current_width * 0.55);
ui->main->setColumnWidth(2, current_width * 0.15);
ui->main->setColumnWidth(3, current_width * 0.1);
} else { // proportionally update column widths
for (int i : {0, 1, 2, 3}) {
ui->main->setColumnWidth(i, ui->main->columnWidth(i) * current_width / previous_width);
}
}
}
void ImportDialog::RelistContent() {
auto* dialog = new QProgressDialog(tr("Loading Contents..."), tr("Cancel"), 0, 0, this);
dialog->setWindowFlags(dialog->windowFlags() & (~Qt::WindowContextHelpButtonHint));
+4 -2
View File
@@ -7,10 +7,10 @@
#include <memory>
#include <string>
#include <vector>
#include <QDialog>
#include <QPixmap>
#include "core/file_sys/ncch_container.h"
#include "core/importer.h"
#include "helpers/dpi_aware_dialog.h"
class AdvancedMenu;
class MultiJob;
@@ -21,7 +21,7 @@ namespace Ui {
class ImportDialog;
}
class ImportDialog : public QDialog {
class ImportDialog final : public DPIAwareDialog {
Q_OBJECT
public:
@@ -29,6 +29,8 @@ public:
~ImportDialog() override;
private:
void SetContentSizes(int previous_width, int previous_height) override;
void RelistContent();
void RepopulateContent();
void UpdateSizeDisplay();
-8
View File
@@ -2,14 +2,6 @@
<ui version="4.0">
<class>ImportDialog</class>
<widget class="QDialog" name="ImportDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>560</width>
<height>320</height>
</rect>
</property>
<property name="windowTitle">
<string>Select Contents</string>
</property>
+15 -8
View File
@@ -5,7 +5,6 @@
#include <regex>
#include <string>
#include <QApplication>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QMessageBox>
#include <QStorageInfo>
@@ -37,12 +36,11 @@ bool IsConfigGood(const Core::Config& config) {
!config.movable_sed_path.empty() && !config.bootrom_path.empty();
}
MainDialog::MainDialog(QWidget* parent) : QDialog(parent), ui(std::make_unique<Ui::MainDialog>()) {
ui->setupUi(this);
MainDialog::MainDialog(QWidget* parent)
: DPIAwareDialog(parent, 640, 256), ui(std::make_unique<Ui::MainDialog>()) {
ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
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"));
@@ -89,9 +87,6 @@ MainDialog::MainDialog(QWidget* parent) : QDialog(parent), ui(std::make_unique<U
});
ui->main->setIndentation(4);
ui->main->setColumnWidth(0, 0.3 * 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);
@@ -103,6 +98,18 @@ MainDialog::MainDialog(QWidget* parent) : QDialog(parent), ui(std::make_unique<U
MainDialog::~MainDialog() = default;
void MainDialog::SetContentSizes(int previous_width, int previous_height) {
const int current_width = width();
if (previous_width == 0) { // first time
ui->main->setColumnWidth(0, 0.3 * current_width);
ui->main->setColumnWidth(1, 0.4 * current_width);
} else { // proportionally update column widths
for (int i : {0, 1}) {
ui->main->setColumnWidth(i, ui->main->columnWidth(i) * current_width / previous_width);
}
}
}
static const std::regex sdmc_path_regex{"(.+)([/\\\\])Nintendo 3DS/([0-9a-f]{32})/([0-9a-f]{32})/"};
void MainDialog::LoadPresetConfig() {
+30 -28
View File
@@ -1,28 +1,30 @@
// Copyright 2019 threeSD Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <QDialog>
#include "core/importer.h"
namespace Ui {
class MainDialog;
}
class MainDialog : public QDialog {
Q_OBJECT
public:
explicit MainDialog(QWidget* parent = nullptr);
~MainDialog() override;
private:
void LoadPresetConfig();
void LaunchImportDialog();
std::vector<Core::Config> preset_config_list;
std::unique_ptr<Ui::MainDialog> ui;
};
// Copyright 2019 threeSD Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include "core/importer.h"
#include "frontend/helpers/dpi_aware_dialog.h"
namespace Ui {
class MainDialog;
}
class MainDialog final : public DPIAwareDialog {
Q_OBJECT
public:
explicit MainDialog(QWidget* parent = nullptr);
~MainDialog() override;
private:
void SetContentSizes(int previous_width, int previous_height) override;
void LoadPresetConfig();
void LaunchImportDialog();
std::vector<Core::Config> preset_config_list;
std::unique_ptr<Ui::MainDialog> ui;
};
+78 -86
View File
@@ -1,86 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainDialog</class>
<widget class="QDialog" name="MainDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>256</height>
</rect>
</property>
<property name="windowTitle">
<string>threeSD</string>
</property>
<layout class="QVBoxLayout">
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel">
<property name="text">
<string>Select your SD card root, or manually browse when not detected.</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="utilitiesButton">
<property name="text">
<string>Utilities...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTreeWidget" name="main">
<column>
<property name="text">
<string>Path</string>
</property>
</column>
<column>
<property name="text">
<string>ID</string>
</property>
</column>
<column>
<property name="text">
<string>Status</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="importDestination"/>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok|QDialogButtonBox::Reset</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainDialog</class>
<widget class="QDialog" name="MainDialog">
<property name="windowTitle">
<string>threeSD</string>
</property>
<layout class="QVBoxLayout">
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel">
<property name="text">
<string>Select your SD card root, or manually browse when not detected.</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="utilitiesButton">
<property name="text">
<string>Utilities...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTreeWidget" name="main">
<column>
<property name="text">
<string>Path</string>
</property>
</column>
<column>
<property name="text">
<string>ID</string>
</property>
</column>
<column>
<property name="text">
<string>Status</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="importDestination"/>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok|QDialogButtonBox::Reset</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+2 -5
View File
@@ -9,14 +9,11 @@
#include "ui_select_files_dialog.h"
SelectFilesDialog::SelectFilesDialog(QWidget* parent, bool source_is_dir_, bool destination_is_dir_)
: QDialog(parent), ui(std::make_unique<Ui::SelectFilesDialog>()), source_is_dir(source_is_dir_),
destination_is_dir(destination_is_dir_) {
: DPIAwareDialog(parent, 480, 96), ui(std::make_unique<Ui::SelectFilesDialog>()),
source_is_dir(source_is_dir_), destination_is_dir(destination_is_dir_) {
ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
connect(ui->buttonBox, &QDialogButtonBox::accepted, [this] {
if (ui->source->text().isEmpty() || ui->destination->text().isEmpty()) {
+27 -29
View File
@@ -1,29 +1,27 @@
// Copyright 2020 threeSD Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <QDialog>
class QWidget;
namespace Ui {
class SelectFilesDialog;
}
class SelectFilesDialog : public QDialog {
Q_OBJECT
public:
explicit SelectFilesDialog(QWidget* parent, bool source_is_dir, bool destination_is_dir);
~SelectFilesDialog() override;
std::pair<QString, QString> GetResults() const;
private:
std::unique_ptr<Ui::SelectFilesDialog> ui;
bool source_is_dir; // Whether Source should be a directory
bool destination_is_dir; // Whether Destination should be a directory
};
// Copyright 2020 threeSD Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include "frontend/helpers/dpi_aware_dialog.h"
namespace Ui {
class SelectFilesDialog;
}
class SelectFilesDialog : public DPIAwareDialog {
Q_OBJECT
public:
explicit SelectFilesDialog(QWidget* parent, bool source_is_dir, bool destination_is_dir);
~SelectFilesDialog() override;
std::pair<QString, QString> GetResults() const;
private:
std::unique_ptr<Ui::SelectFilesDialog> ui;
bool source_is_dir; // Whether Source should be a directory
bool destination_is_dir; // Whether Destination should be a directory
};
+68 -76
View File
@@ -1,76 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SelectFilesDialog</class>
<widget class="QDialog" name="SelectFilesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>480</width>
<height>96</height>
</rect>
</property>
<property name="windowTitle">
<string>Select Files</string>
</property>
<layout class="QVBoxLayout">
<item>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QLabel">
<property name="text">
<string>Source:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="source"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="sourceExplore">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel">
<property name="text">
<string>Destination:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="destination"/>
</item>
<item row="1" column="2">
<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="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok|QDialogButtonBox::Cancel</set>
</property>
</widget>
</item>
</layout>
</widget>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SelectFilesDialog</class>
<widget class="QDialog" name="SelectFilesDialog">
<property name="windowTitle">
<string>Select Files</string>
</property>
<layout class="QVBoxLayout">
<item>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QLabel">
<property name="text">
<string>Source:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="source"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="sourceExplore">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel">
<property name="text">
<string>Destination:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="destination"/>
</item>
<item row="1" column="2">
<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="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok|QDialogButtonBox::Cancel</set>
</property>
</widget>
</item>
</layout>
</widget>
</ui>
+2 -5
View File
@@ -20,14 +20,11 @@
TitleInfoDialog::TitleInfoDialog(QWidget* parent, Core::SDMCImporter& importer_,
Core::ContentSpecifier specifier_)
: QDialog(parent), ui(std::make_unique<Ui::TitleInfoDialog>()), importer(importer_),
specifier(std::move(specifier_)) {
: DPIAwareDialog(parent, 500, 360), ui(std::make_unique<Ui::TitleInfoDialog>()),
importer(importer_), specifier(std::move(specifier_)) {
ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
const double scale = qApp->desktop()->logicalDpiX() / 96.0;
resize(static_cast<int>(width() * scale), static_cast<int>(height() * scale));
LoadInfo();
+2 -2
View File
@@ -3,8 +3,8 @@
// Refer to the license.txt file included.
#include <memory>
#include <QDialog>
#include "core/file_sys/smdh.h"
#include "frontend/helpers/dpi_aware_dialog.h"
namespace Core {
struct Config;
@@ -18,7 +18,7 @@ namespace Ui {
class TitleInfoDialog;
}
class TitleInfoDialog : public QDialog {
class TitleInfoDialog : public DPIAwareDialog {
Q_OBJECT
public:
-8
View File
@@ -2,14 +2,6 @@
<ui version="4.0">
<class>TitleInfoDialog</class>
<widget class="QDialog" name="TitleInfoDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>360</height>
</rect>
</property>
<property name="windowTitle">
<string>Title Info</string>
</property>
+1 -4
View File
@@ -19,13 +19,10 @@
#include "ui_utilities.h"
UtilitiesDialog::UtilitiesDialog(QWidget* parent)
: QDialog(parent), ui(std::make_unique<Ui::UtilitiesDialog>()) {
: DPIAwareDialog(parent, 640, 384), ui(std::make_unique<Ui::UtilitiesDialog>()) {
ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
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();
+49 -49
View File
@@ -1,49 +1,49 @@
// Copyright 2020 threeSD Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <functional>
#include <memory>
#include <QDialog>
class QWidget;
namespace Ui {
class UtilitiesDialog;
}
class UtilitiesDialog : public QDialog {
Q_OBJECT
public:
explicit UtilitiesDialog(QWidget* parent);
~UtilitiesDialog() override;
private:
/**
* Open a dialog to ask the user for source and destination paths.
* @return {source, destination}
*/
std::pair<QString, QString> GetFilePaths(bool source_is_dir, bool destination_is_dir);
bool LoadSDKeys();
void ShowProgressDialog(std::function<bool()> operation);
/**
* Gets SDMC root, and relative source path.
* @return {success, sdmc root, relative source path}
*/
std::tuple<bool, std::string, std::string> GetSDMCRoot(const QString& source);
void SDDecryptionTool();
void SaveDataExtractionTool();
void ExtdataExtractionTool();
void RomFSExtractionTool();
void ShowResult();
bool result = false; /// Result of the last operation.
std::unique_ptr<Ui::UtilitiesDialog> ui;
};
// Copyright 2020 threeSD Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <functional>
#include <memory>
#include "frontend/helpers/dpi_aware_dialog.h"
class QWidget;
namespace Ui {
class UtilitiesDialog;
}
class UtilitiesDialog : public DPIAwareDialog {
Q_OBJECT
public:
explicit UtilitiesDialog(QWidget* parent);
~UtilitiesDialog() override;
private:
/**
* Open a dialog to ask the user for source and destination paths.
* @return {source, destination}
*/
std::pair<QString, QString> GetFilePaths(bool source_is_dir, bool destination_is_dir);
bool LoadSDKeys();
void ShowProgressDialog(std::function<bool()> operation);
/**
* Gets SDMC root, and relative source path.
* @return {success, sdmc root, relative source path}
*/
std::tuple<bool, std::string, std::string> GetSDMCRoot(const QString& source);
void SDDecryptionTool();
void SaveDataExtractionTool();
void ExtdataExtractionTool();
void RomFSExtractionTool();
void ShowResult();
bool result = false; /// Result of the last operation.
std::unique_ptr<Ui::UtilitiesDialog> ui;
};
+251 -277
View File
@@ -1,277 +1,251 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UtilitiesDialog</class>
<widget class="QDialog" name="UtilitiesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>384</height>
</rect>
</property>
<property name="windowTitle">
<string>threeSD Utilities</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QGroupBox">
<property name="title">
<string>Encryption</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QCheckBox" name="useSdDecryption">
<property name="text">
<string>Use SD Decryption (check this when your files are directly from SD Card)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QLabel">
<property name="text">
<string>boot9.bin</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="boot9Path"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="boot9PathExplore">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel">
<property name="text">
<string>movable.sed</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="movableSedPath"/>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="movableSedPathExplore">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel">
<property name="text">
<string>SDMC Root</string>
</property>
<property name="toolTip">
<string>Path to "Nintendo 3DS/&lt;ID0>/&lt;ID1>" folder.</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="sdmcPath"/>
</item>
<item row="2" column="2">
<widget class="QToolButton" name="sdmcPathExplore">
<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>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox">
<property name="title">
<string>SD Decryption</string>
</property>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="sdDecryptionLabel">
<property name="text">
<string>Decrypt files from your SD Card.</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="sdDecryptionDisabledLabel">
<property name="text">
<string>SD Decryption must be enabled to use this tool.</string>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="sdDecryption">
<property name="text">
<string>Open...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox">
<property name="title">
<string>Save Data Extraction</string>
</property>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="savedataExtractionLabel">
<property name="text">
<string>Extract 3DS SD Savegames.</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="savedataExtractionDisabledLabel">
<property name="text">
<string>SD Decryption must be enabled to use this tool.</string>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="savedataExtraction">
<property name="text">
<string>Open...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox">
<property name="title">
<string>Extdata Extraction</string>
</property>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="extdataExtractionLabel">
<property name="text">
<string>Extract 3DS Extra Data.</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="extdataExtractionDisabledLabel">
<property name="text">
<string>SD Decryption must be enabled to use this tool.</string>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="extdataExtraction">
<property name="text">
<string>Open...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox">
<property name="title">
<string>RomFS Extraction</string>
</property>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="romfsExtractionLabel">
<property name="text">
<string>Extract shared RomFS from NCCH. Useful for System Archives.</string>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="romfsExtractionDisabledLabel">
<property name="text">
<string>SD Decryption must be disabled to use this tool.</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="romfsExtraction">
<property name="text">
<string>Open...</string>
</property>
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UtilitiesDialog</class>
<widget class="QDialog" name="UtilitiesDialog">
<property name="windowTitle">
<string>threeSD Utilities</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QGroupBox">
<property name="title">
<string>Encryption</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QCheckBox" name="useSdDecryption">
<property name="text">
<string>Use SD Decryption (check this when your files are directly from SD Card)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QLabel">
<property name="text">
<string>boot9.bin</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="boot9Path"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="boot9PathExplore">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel">
<property name="text">
<string>movable.sed</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="movableSedPath"/>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="movableSedPathExplore">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel">
<property name="text">
<string>SDMC Root</string>
</property>
<property name="toolTip">
<string>Path to "Nintendo 3DS/&lt;ID0>/&lt;ID1>" folder.</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="sdmcPath"/>
</item>
<item row="2" column="2">
<widget class="QToolButton" name="sdmcPathExplore">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox">
<property name="title">
<string>SD Decryption</string>
</property>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="sdDecryptionLabel">
<property name="text">
<string>Decrypt files from your SD Card.</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="sdDecryptionDisabledLabel">
<property name="text">
<string>SD Decryption must be enabled to use this tool.</string>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="sdDecryption">
<property name="text">
<string>Open...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox">
<property name="title">
<string>Save Data Extraction</string>
</property>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="savedataExtractionLabel">
<property name="text">
<string>Extract 3DS SD Savegames.</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="savedataExtractionDisabledLabel">
<property name="text">
<string>SD Decryption must be enabled to use this tool.</string>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="savedataExtraction">
<property name="text">
<string>Open...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox">
<property name="title">
<string>Extdata Extraction</string>
</property>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="extdataExtractionLabel">
<property name="text">
<string>Extract 3DS Extra Data.</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="extdataExtractionDisabledLabel">
<property name="text">
<string>SD Decryption must be enabled to use this tool.</string>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="extdataExtraction">
<property name="text">
<string>Open...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox">
<property name="title">
<string>RomFS Extraction</string>
</property>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="romfsExtractionLabel">
<property name="text">
<string>Extract shared RomFS from NCCH. Useful for System Archives.</string>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="romfsExtractionDisabledLabel">
<property name="text">
<string>SD Decryption must be disabled to use this tool.</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="romfsExtraction">
<property name="text">
<string>Open...</string>
</property>
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</ui>