add CIA installation to QT frontend
This commit is contained in:
parent
b7cf793814
commit
80852f918a
|
@ -10,7 +10,9 @@
|
||||||
#define QT_NO_OPENGL
|
#define QT_NO_OPENGL
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QFutureWatcher>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
#include <QtWidgets>
|
#include <QtWidgets>
|
||||||
#include "citra_qt/aboutdialog.h"
|
#include "citra_qt/aboutdialog.h"
|
||||||
|
@ -92,6 +94,9 @@ void GMainWindow::ShowCallouts() {
|
||||||
}
|
}
|
||||||
|
|
||||||
GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) {
|
GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) {
|
||||||
|
// register size_t to use in slots and signals
|
||||||
|
qRegisterMetaType<size_t>("size_t");
|
||||||
|
|
||||||
Pica::g_debug_context = Pica::DebugContext::Construct();
|
Pica::g_debug_context = Pica::DebugContext::Construct();
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
|
@ -158,6 +163,10 @@ void GMainWindow::InitializeWidgets() {
|
||||||
message_label->setAlignment(Qt::AlignLeft);
|
message_label->setAlignment(Qt::AlignLeft);
|
||||||
statusBar()->addPermanentWidget(message_label, 1);
|
statusBar()->addPermanentWidget(message_label, 1);
|
||||||
|
|
||||||
|
progress_bar = new QProgressBar();
|
||||||
|
progress_bar->hide();
|
||||||
|
statusBar()->addPermanentWidget(progress_bar);
|
||||||
|
|
||||||
emu_speed_label = new QLabel();
|
emu_speed_label = new QLabel();
|
||||||
emu_speed_label->setToolTip(tr("Current emulation speed. Values higher or lower than 100% "
|
emu_speed_label->setToolTip(tr("Current emulation speed. Values higher or lower than 100% "
|
||||||
"indicate emulation is running faster or slower than a 3DS."));
|
"indicate emulation is running faster or slower than a 3DS."));
|
||||||
|
@ -333,11 +342,14 @@ void GMainWindow::ConnectWidgetEvents() {
|
||||||
connect(this, SIGNAL(EmulationStopping()), render_window, SLOT(OnEmulationStopping()));
|
connect(this, SIGNAL(EmulationStopping()), render_window, SLOT(OnEmulationStopping()));
|
||||||
|
|
||||||
connect(&status_bar_update_timer, &QTimer::timeout, this, &GMainWindow::UpdateStatusBar);
|
connect(&status_bar_update_timer, &QTimer::timeout, this, &GMainWindow::UpdateStatusBar);
|
||||||
|
|
||||||
|
connect(this, &GMainWindow::UpdateProgress, this, &GMainWindow::OnUpdateProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::ConnectMenuEvents() {
|
void GMainWindow::ConnectMenuEvents() {
|
||||||
// File
|
// File
|
||||||
connect(ui.action_Load_File, &QAction::triggered, this, &GMainWindow::OnMenuLoadFile);
|
connect(ui.action_Load_File, &QAction::triggered, this, &GMainWindow::OnMenuLoadFile);
|
||||||
|
connect(ui.action_Install_CIA, &QAction::triggered, this, &GMainWindow::OnMenuInstallCIA);
|
||||||
connect(ui.action_Select_Game_List_Root, &QAction::triggered, this,
|
connect(ui.action_Select_Game_List_Root, &QAction::triggered, this,
|
||||||
&GMainWindow::OnMenuSelectGameListRoot);
|
&GMainWindow::OnMenuSelectGameListRoot);
|
||||||
connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close);
|
connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close);
|
||||||
|
@ -696,6 +708,61 @@ void GMainWindow::OnMenuSelectGameListRoot() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnMenuInstallCIA() {
|
||||||
|
QString filepath = QFileDialog::getOpenFileName(
|
||||||
|
this, tr("Load File"), UISettings::values.roms_path,
|
||||||
|
tr("3DS Installation File (*.CIA*)") + ";;" + tr("All Files (*.*)"));
|
||||||
|
if (filepath.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ui.action_Install_CIA->setEnabled(false);
|
||||||
|
progress_bar->show();
|
||||||
|
watcher = new QFutureWatcher<Service::AM::InstallStatus>;
|
||||||
|
QFuture<Service::AM::InstallStatus> f = QtConcurrent::run([&, filepath] {
|
||||||
|
const auto cia_progress = [&](size_t written, size_t total) {
|
||||||
|
emit UpdateProgress(written, total);
|
||||||
|
};
|
||||||
|
return Service::AM::InstallCIA(filepath.toStdString(), cia_progress);
|
||||||
|
});
|
||||||
|
connect(watcher, &QFutureWatcher<Service::AM::InstallStatus>::finished, this,
|
||||||
|
&GMainWindow::OnCIAInstallFinished);
|
||||||
|
watcher->setFuture(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnUpdateProgress(size_t written, size_t total) {
|
||||||
|
progress_bar->setMaximum(total);
|
||||||
|
progress_bar->setValue(written);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnCIAInstallFinished() {
|
||||||
|
progress_bar->hide();
|
||||||
|
progress_bar->setValue(0);
|
||||||
|
switch (watcher->future()) {
|
||||||
|
case Service::AM::InstallStatus::Success:
|
||||||
|
this->statusBar()->showMessage(tr("The file has been installed successfully."));
|
||||||
|
break;
|
||||||
|
case Service::AM::InstallStatus::ErrorFailedToOpenFile:
|
||||||
|
QMessageBox::critical(this, tr("Unable to open File"),
|
||||||
|
tr("Could not open the selected file"));
|
||||||
|
break;
|
||||||
|
case Service::AM::InstallStatus::ErrorAborted:
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, tr("Installation aborted"),
|
||||||
|
tr("The installation was aborted. Please see the log for more details"));
|
||||||
|
break;
|
||||||
|
case Service::AM::InstallStatus::ErrorInvalid:
|
||||||
|
QMessageBox::critical(this, tr("Invalid File"), tr("The selected file is not a valid CIA"));
|
||||||
|
break;
|
||||||
|
case Service::AM::InstallStatus::ErrorEncrypted:
|
||||||
|
QMessageBox::critical(this, tr("Encrypted File"),
|
||||||
|
tr("The file that you are trying to install must be decrypted "
|
||||||
|
"before being used with Citra. A real 3DS is required."));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delete watcher;
|
||||||
|
ui.action_Install_CIA->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
void GMainWindow::OnMenuRecentFile() {
|
void GMainWindow::OnMenuRecentFile() {
|
||||||
QAction* action = qobject_cast<QAction*>(sender());
|
QAction* action = qobject_cast<QAction*>(sender());
|
||||||
assert(action);
|
assert(action);
|
||||||
|
|
|
@ -8,24 +8,28 @@
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/am/am.h"
|
||||||
#include "ui_main.h"
|
#include "ui_main.h"
|
||||||
|
|
||||||
|
class AboutDialog;
|
||||||
class Config;
|
class Config;
|
||||||
class EmuThread;
|
class EmuThread;
|
||||||
class GameList;
|
class GameList;
|
||||||
class GImageInfo;
|
class GImageInfo;
|
||||||
class GPUCommandStreamWidget;
|
|
||||||
class GPUCommandListWidget;
|
class GPUCommandListWidget;
|
||||||
|
class GPUCommandStreamWidget;
|
||||||
class GraphicsBreakPointsWidget;
|
class GraphicsBreakPointsWidget;
|
||||||
class GraphicsTracingWidget;
|
class GraphicsTracingWidget;
|
||||||
class GraphicsVertexShaderWidget;
|
class GraphicsVertexShaderWidget;
|
||||||
class GRenderWindow;
|
class GRenderWindow;
|
||||||
class MicroProfileDialog;
|
class MicroProfileDialog;
|
||||||
class ProfilerWidget;
|
class ProfilerWidget;
|
||||||
|
template <typename>
|
||||||
|
class QFutureWatcher;
|
||||||
|
class QProgressBar;
|
||||||
class RegistersWidget;
|
class RegistersWidget;
|
||||||
class Updater;
|
class Updater;
|
||||||
class WaitTreeWidget;
|
class WaitTreeWidget;
|
||||||
class AboutDialog;
|
|
||||||
|
|
||||||
class GMainWindow : public QMainWindow {
|
class GMainWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -64,6 +68,7 @@ signals:
|
||||||
* system emulation handles and memory are still valid, but are about become invalid.
|
* system emulation handles and memory are still valid, but are about become invalid.
|
||||||
*/
|
*/
|
||||||
void EmulationStopping();
|
void EmulationStopping();
|
||||||
|
void UpdateProgress(size_t written, size_t total);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitializeWidgets();
|
void InitializeWidgets();
|
||||||
|
@ -125,6 +130,9 @@ private slots:
|
||||||
void OnGameListLoadFile(QString game_path);
|
void OnGameListLoadFile(QString game_path);
|
||||||
void OnGameListOpenSaveFolder(u64 program_id);
|
void OnGameListOpenSaveFolder(u64 program_id);
|
||||||
void OnMenuLoadFile();
|
void OnMenuLoadFile();
|
||||||
|
void OnMenuInstallCIA();
|
||||||
|
void OnUpdateProgress(size_t written, size_t total);
|
||||||
|
void OnCIAInstallFinished();
|
||||||
/// Called whenever a user selects the "File->Select Game List Root" menu item
|
/// Called whenever a user selects the "File->Select Game List Root" menu item
|
||||||
void OnMenuSelectGameListRoot();
|
void OnMenuSelectGameListRoot();
|
||||||
void OnMenuRecentFile();
|
void OnMenuRecentFile();
|
||||||
|
@ -149,8 +157,10 @@ private:
|
||||||
|
|
||||||
GRenderWindow* render_window;
|
GRenderWindow* render_window;
|
||||||
GameList* game_list;
|
GameList* game_list;
|
||||||
|
QFutureWatcher<Service::AM::InstallStatus>* watcher = nullptr;
|
||||||
|
|
||||||
// Status bar elements
|
// Status bar elements
|
||||||
|
QProgressBar* progress_bar = nullptr;
|
||||||
QLabel* message_label = nullptr;
|
QLabel* message_label = nullptr;
|
||||||
QLabel* emu_speed_label = nullptr;
|
QLabel* emu_speed_label = nullptr;
|
||||||
QLabel* game_fps_label = nullptr;
|
QLabel* game_fps_label = nullptr;
|
||||||
|
@ -185,3 +195,5 @@ protected:
|
||||||
void dragEnterEvent(QDragEnterEvent* event) override;
|
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||||
void dragMoveEvent(QDragMoveEvent* event) override;
|
void dragMoveEvent(QDragMoveEvent* event) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(size_t);
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="action_Load_File"/>
|
<addaction name="action_Load_File"/>
|
||||||
|
<addaction name="action_Install_CIA"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="action_Select_Game_List_Root"/>
|
<addaction name="action_Select_Game_List_Root"/>
|
||||||
<addaction name="menu_recent_files"/>
|
<addaction name="menu_recent_files"/>
|
||||||
|
@ -112,6 +113,11 @@
|
||||||
<string>Load File...</string>
|
<string>Load File...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_Install_CIA">
|
||||||
|
<property name="text">
|
||||||
|
<string>Install CIA...</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="action_Load_Symbol_Map">
|
<action name="action_Load_Symbol_Map">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Load Symbol Map...</string>
|
<string>Load Symbol Map...</string>
|
||||||
|
|
Reference in New Issue