Merge pull request #3434 from BreadFish64/MultipleInstalls
QT: allow installation of multiple CIAs
This commit is contained in:
commit
0cea9c54ac
2 changed files with 43 additions and 27 deletions
|
@ -96,8 +96,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
|
// register types to use in slots and signals
|
||||||
qRegisterMetaType<size_t>("size_t");
|
qRegisterMetaType<size_t>("size_t");
|
||||||
|
qRegisterMetaType<Service::AM::InstallStatus>("Service::AM::InstallStatus");
|
||||||
|
|
||||||
LoadTranslation();
|
LoadTranslation();
|
||||||
|
|
||||||
|
@ -382,6 +383,8 @@ void GMainWindow::ConnectWidgetEvents() {
|
||||||
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);
|
connect(this, &GMainWindow::UpdateProgress, this, &GMainWindow::OnUpdateProgress);
|
||||||
|
connect(this, &GMainWindow::CIAInstallReport, this, &GMainWindow::OnCIAInstallReport);
|
||||||
|
connect(this, &GMainWindow::CIAInstallFinished, this, &GMainWindow::OnCIAInstallFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::ConnectMenuEvents() {
|
void GMainWindow::ConnectMenuEvents() {
|
||||||
|
@ -791,24 +794,28 @@ void GMainWindow::OnMenuSelectGameListRoot() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnMenuInstallCIA() {
|
void GMainWindow::OnMenuInstallCIA() {
|
||||||
QString filepath = QFileDialog::getOpenFileName(
|
QStringList filepaths = QFileDialog::getOpenFileNames(
|
||||||
this, tr("Load File"), UISettings::values.roms_path,
|
this, tr("Load Files"), UISettings::values.roms_path,
|
||||||
tr("3DS Installation File (*.CIA*)") + ";;" + tr("All Files (*.*)"));
|
tr("3DS Installation File (*.CIA*)") + ";;" + tr("All Files (*.*)"));
|
||||||
if (filepath.isEmpty())
|
if (filepaths.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ui.action_Install_CIA->setEnabled(false);
|
ui.action_Install_CIA->setEnabled(false);
|
||||||
progress_bar->show();
|
progress_bar->show();
|
||||||
watcher = new QFutureWatcher<Service::AM::InstallStatus>;
|
|
||||||
QFuture<Service::AM::InstallStatus> f = QtConcurrent::run([&, filepath] {
|
QtConcurrent::run([&, filepaths] {
|
||||||
|
QString current_path;
|
||||||
|
Service::AM::InstallStatus status;
|
||||||
const auto cia_progress = [&](size_t written, size_t total) {
|
const auto cia_progress = [&](size_t written, size_t total) {
|
||||||
emit UpdateProgress(written, total);
|
emit UpdateProgress(written, total);
|
||||||
};
|
};
|
||||||
return Service::AM::InstallCIA(filepath.toStdString(), cia_progress);
|
for (const auto current_path : filepaths) {
|
||||||
|
status = Service::AM::InstallCIA(current_path.toStdString(), cia_progress);
|
||||||
|
emit CIAInstallReport(status, current_path);
|
||||||
|
}
|
||||||
|
emit CIAInstallFinished();
|
||||||
|
return;
|
||||||
});
|
});
|
||||||
connect(watcher, &QFutureWatcher<Service::AM::InstallStatus>::finished, this,
|
|
||||||
&GMainWindow::OnCIAInstallFinished);
|
|
||||||
watcher->setFuture(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnUpdateProgress(size_t written, size_t total) {
|
void GMainWindow::OnUpdateProgress(size_t written, size_t total) {
|
||||||
|
@ -816,32 +823,37 @@ void GMainWindow::OnUpdateProgress(size_t written, size_t total) {
|
||||||
progress_bar->setValue(written);
|
progress_bar->setValue(written);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnCIAInstallFinished() {
|
void GMainWindow::OnCIAInstallReport(Service::AM::InstallStatus status, QString filepath) {
|
||||||
progress_bar->hide();
|
QString filename = QFileInfo(filepath).fileName();
|
||||||
progress_bar->setValue(0);
|
switch (status) {
|
||||||
switch (watcher->future()) {
|
|
||||||
case Service::AM::InstallStatus::Success:
|
case Service::AM::InstallStatus::Success:
|
||||||
this->statusBar()->showMessage(tr("The file has been installed successfully."));
|
this->statusBar()->showMessage(tr("%1 has been installed successfully.").arg(filename));
|
||||||
break;
|
break;
|
||||||
case Service::AM::InstallStatus::ErrorFailedToOpenFile:
|
case Service::AM::InstallStatus::ErrorFailedToOpenFile:
|
||||||
QMessageBox::critical(this, tr("Unable to open File"),
|
QMessageBox::critical(this, tr("Unable to open File"),
|
||||||
tr("Could not open the selected file"));
|
tr("Could not open %1").arg(filename));
|
||||||
break;
|
break;
|
||||||
case Service::AM::InstallStatus::ErrorAborted:
|
case Service::AM::InstallStatus::ErrorAborted:
|
||||||
QMessageBox::critical(
|
QMessageBox::critical(
|
||||||
this, tr("Installation aborted"),
|
this, tr("Installation aborted"),
|
||||||
tr("The installation was aborted. Please see the log for more details"));
|
tr("The installation of %1 was aborted. Please see the log for more details")
|
||||||
|
.arg(filename));
|
||||||
break;
|
break;
|
||||||
case Service::AM::InstallStatus::ErrorInvalid:
|
case Service::AM::InstallStatus::ErrorInvalid:
|
||||||
QMessageBox::critical(this, tr("Invalid File"), tr("The selected file is not a valid CIA"));
|
QMessageBox::critical(this, tr("Invalid File"), tr("%1 is not a valid CIA").arg(filename));
|
||||||
break;
|
break;
|
||||||
case Service::AM::InstallStatus::ErrorEncrypted:
|
case Service::AM::InstallStatus::ErrorEncrypted:
|
||||||
QMessageBox::critical(this, tr("Encrypted File"),
|
QMessageBox::critical(this, tr("Encrypted File"),
|
||||||
tr("The file that you are trying to install must be decrypted "
|
tr("%1 must be decrypted "
|
||||||
"before being used with Citra. A real 3DS is required."));
|
"before being used with Citra. A real 3DS is required.")
|
||||||
|
.arg(filename));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
delete watcher;
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnCIAInstallFinished() {
|
||||||
|
progress_bar->hide();
|
||||||
|
progress_bar->setValue(0);
|
||||||
ui.action_Install_CIA->setEnabled(true);
|
ui.action_Install_CIA->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,7 +909,8 @@ void GMainWindow::OnMenuReportCompatibility() {
|
||||||
QMessageBox::critical(
|
QMessageBox::critical(
|
||||||
this, tr("Missing Citra Account"),
|
this, tr("Missing Citra Account"),
|
||||||
tr("In order to submit a game compatibility test case, you must link your Citra "
|
tr("In order to submit a game compatibility test case, you must link your Citra "
|
||||||
"account.<br><br/>To link your Citra account, go to Emulation > Configuration > "
|
"account.<br><br/>To link your Citra account, go to Emulation > Configuration "
|
||||||
|
"> "
|
||||||
"Web."));
|
"Web."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1048,8 +1061,7 @@ void GMainWindow::UpdateStatusBar() {
|
||||||
.arg(results.emulation_speed * 100.0, 0, 'f', 0)
|
.arg(results.emulation_speed * 100.0, 0, 'f', 0)
|
||||||
.arg(Settings::values.frame_limit));
|
.arg(Settings::values.frame_limit));
|
||||||
} else {
|
} else {
|
||||||
emu_speed_label->setText(tr("Speed: %1%")
|
emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
|
||||||
.arg(results.emulation_speed * 100.0, 0, 'f', 0));
|
|
||||||
}
|
}
|
||||||
game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0));
|
game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0));
|
||||||
emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2));
|
emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2));
|
||||||
|
|
|
@ -70,7 +70,10 @@ 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);
|
void UpdateProgress(size_t written, size_t total);
|
||||||
|
void CIAInstallReport(Service::AM::InstallStatus status, QString filepath);
|
||||||
|
void CIAInstallFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitializeWidgets();
|
void InitializeWidgets();
|
||||||
|
@ -136,6 +139,7 @@ private slots:
|
||||||
void OnMenuLoadFile();
|
void OnMenuLoadFile();
|
||||||
void OnMenuInstallCIA();
|
void OnMenuInstallCIA();
|
||||||
void OnUpdateProgress(size_t written, size_t total);
|
void OnUpdateProgress(size_t written, size_t total);
|
||||||
|
void OnCIAInstallReport(Service::AM::InstallStatus status, QString filepath);
|
||||||
void OnCIAInstallFinished();
|
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();
|
||||||
|
@ -168,7 +172,6 @@ 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;
|
QProgressBar* progress_bar = nullptr;
|
||||||
|
@ -210,3 +213,4 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(size_t);
|
Q_DECLARE_METATYPE(size_t);
|
||||||
|
Q_DECLARE_METATYPE(Service::AM::InstallStatus);
|
||||||
|
|
Loading…
Reference in a new issue