From 6d8d7ebc66d9deb5adb4edb246590481b1236bbc Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sun, 5 Jul 2020 09:29:39 -0400 Subject: [PATCH] Update the install and progress dialogs - Remove the overwrite files checkbox, it will always overwrite - The progressbar now reflects the progress in terms of data transferred. --- src/yuzu/install_dialog.cpp | 12 ++-- src/yuzu/install_dialog.h | 2 +- src/yuzu/main.cpp | 118 ++++++++++++++++-------------------- src/yuzu/main.h | 13 ++-- 4 files changed, 65 insertions(+), 80 deletions(-) diff --git a/src/yuzu/install_dialog.cpp b/src/yuzu/install_dialog.cpp index 5f3b4c9636..06b0b1874a 100644 --- a/src/yuzu/install_dialog.cpp +++ b/src/yuzu/install_dialog.cpp @@ -22,7 +22,7 @@ InstallDialog::InstallDialog(QWidget* parent, const QStringList& files) : QDialo item->setCheckState(Qt::Checked); } - file_list->setMinimumWidth((file_list->sizeHintForColumn(0) * 10) / 9); + file_list->setMinimumWidth((file_list->sizeHintForColumn(0) * 11) / 10); vbox_layout = new QVBoxLayout; @@ -30,8 +30,8 @@ InstallDialog::InstallDialog(QWidget* parent, const QStringList& files) : QDialo description = new QLabel(tr("Please confirm these are the files you wish to install.")); - overwrite_files = new QCheckBox(tr("Overwrite Existing Files")); - overwrite_files->setCheckState(Qt::Unchecked); + update_description = + new QLabel(tr("Installing an Update or DLC will overwrite the previously installed one.")); buttons = new QDialogButtonBox; buttons->addButton(QDialogButtonBox::Cancel); @@ -40,10 +40,10 @@ InstallDialog::InstallDialog(QWidget* parent, const QStringList& files) : QDialo connect(buttons, &QDialogButtonBox::accepted, this, &InstallDialog::accept); connect(buttons, &QDialogButtonBox::rejected, this, &InstallDialog::reject); - hbox_layout->addWidget(overwrite_files); hbox_layout->addWidget(buttons); vbox_layout->addWidget(description); + vbox_layout->addWidget(update_description); vbox_layout->addWidget(file_list); vbox_layout->addLayout(hbox_layout); @@ -67,10 +67,6 @@ QStringList InstallDialog::GetFiles() const { return files; } -bool InstallDialog::ShouldOverwriteFiles() const { - return overwrite_files->isChecked(); -} - int InstallDialog::GetMinimumWidth() const { return file_list->width(); } diff --git a/src/yuzu/install_dialog.h b/src/yuzu/install_dialog.h index 55a458ba87..e4aba1b06f 100644 --- a/src/yuzu/install_dialog.h +++ b/src/yuzu/install_dialog.h @@ -31,6 +31,6 @@ private: QHBoxLayout* hbox_layout; QLabel* description; - QCheckBox* overwrite_files; + QLabel* update_description; QDialogButtonBox* buttons; }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 4539cbe0d8..8a57e34c71 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -848,6 +848,9 @@ void GMainWindow::ConnectWidgetEvents() { connect(game_list, &GameList::OpenPerGameGeneralRequested, this, &GMainWindow::OnGameListOpenPerGameProperties); + connect(this, &GMainWindow::UpdateInstallProgress, this, + &GMainWindow::IncrementInstallProgress); + connect(this, &GMainWindow::EmulationStarting, render_window, &GRenderWindow::OnEmulationStarting); connect(this, &GMainWindow::EmulationStopping, render_window, @@ -1594,6 +1597,10 @@ void GMainWindow::OnMenuLoadFolder() { } } +void GMainWindow::IncrementInstallProgress() { + install_progress->setValue(install_progress->value() + 1); +} + void GMainWindow::OnMenuInstallToNAND() { const QString file_filter = tr("Installable Switch File (*.nca *.nsp *.xci);;Nintendo Content Archive " @@ -1613,28 +1620,35 @@ void GMainWindow::OnMenuInstallToNAND() { } const QStringList files = installDialog.GetFiles(); - const bool overwrite_files = installDialog.ShouldOverwriteFiles(); - int count = 0; - const int total_count = filenames.size(); + int remaining = filenames.size(); + + // This would only overflow above 2^43 bytes (8.796 TB) + int total_size = 0; + for (const QString& file : files) { + total_size += static_cast(QFile(file).size() / 0x1000); + } + if (total_size < 0) { + LOG_CRITICAL(Frontend, "Attempting to install too many files, aborting."); + return; + } QStringList new_files{}; // Newly installed files that do not yet exist in the NAND QStringList overwritten_files{}; // Files that overwrote those existing in the NAND - QStringList existing_files{}; // Files that were not installed as they already exist in the NAND - QStringList failed_files{}; // Files that failed to install due to errors + QStringList failed_files{}; // Files that failed to install due to errors ui.action_Install_File_NAND->setEnabled(false); - QProgressDialog install_progress(QStringLiteral(""), tr("Cancel"), 0, total_count, this); - install_progress.setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint & - ~Qt::WindowMaximizeButtonHint); - install_progress.setAutoClose(false); - install_progress.setFixedWidth(installDialog.GetMinimumWidth()); - install_progress.show(); + install_progress = new QProgressDialog(QStringLiteral(""), tr("Cancel"), 0, total_size, this); + install_progress->setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint & + ~Qt::WindowMaximizeButtonHint); + install_progress->setAttribute(Qt::WA_DeleteOnClose, true); + install_progress->setFixedWidth(installDialog.GetMinimumWidth() + 40); + install_progress->show(); for (const QString& file : files) { - install_progress.setWindowTitle(tr("%n file(s) remaining", "", total_count - count)); - install_progress.setLabelText( + install_progress->setWindowTitle(tr("%n file(s) remaining", "", remaining)); + install_progress->setLabelText( tr("Installing file \"%1\"...").arg(QFileInfo(file).fileName())); QFuture future; @@ -1642,19 +1656,21 @@ void GMainWindow::OnMenuInstallToNAND() { if (file.endsWith(QStringLiteral("xci"), Qt::CaseInsensitive) || file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { - future = QtConcurrent::run([this, &file, &overwrite_files, &install_progress] { - return InstallNSPXCI(file, overwrite_files, install_progress); - }); + + future = QtConcurrent::run([this, &file] { return InstallNSPXCI(file); }); while (!future.isFinished()) { QCoreApplication::processEvents(); } result = future.result(); + } else { - result = InstallNCA(file, overwrite_files, install_progress); + result = InstallNCA(file); } + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + switch (result) { case InstallResult::Success: new_files.append(QFileInfo(file).fileName()); @@ -1662,19 +1678,15 @@ void GMainWindow::OnMenuInstallToNAND() { case InstallResult::Overwrite: overwritten_files.append(QFileInfo(file).fileName()); break; - case InstallResult::AlreadyExists: - existing_files.append(QFileInfo(file).fileName()); - break; case InstallResult::Failure: failed_files.append(QFileInfo(file).fileName()); break; } - install_progress.setValue(++count); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + --remaining; } - install_progress.close(); + install_progress->close(); const QString install_results = (new_files.isEmpty() ? QStringLiteral("") @@ -1682,9 +1694,6 @@ void GMainWindow::OnMenuInstallToNAND() { (overwritten_files.isEmpty() ? QStringLiteral("") : tr("%n file(s) were overwritten\n", "", overwritten_files.size())) + - (existing_files.isEmpty() - ? QStringLiteral("") - : tr("%n file(s) already exist in NAND\n", "", existing_files.size())) + (failed_files.isEmpty() ? QStringLiteral("") : tr("%n file(s) failed to install\n", "", failed_files.size())); @@ -1695,11 +1704,9 @@ void GMainWindow::OnMenuInstallToNAND() { ui.action_Install_File_NAND->setEnabled(true); } -InstallResult GMainWindow::InstallNSPXCI(const QString& filename, bool overwrite_files, - QProgressDialog& install_progress) { - const auto qt_raw_copy = [this, &install_progress](const FileSys::VirtualFile& src, - const FileSys::VirtualFile& dest, - std::size_t block_size) { +InstallResult GMainWindow::InstallNSPXCI(const QString& filename) { + const auto qt_raw_copy = [this](const FileSys::VirtualFile& src, + const FileSys::VirtualFile& dest, std::size_t block_size) { if (src == nullptr || dest == nullptr) { return false; } @@ -1710,11 +1717,13 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename, bool overwrite std::array buffer{}; for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { - if (install_progress.wasCanceled()) { + if (install_progress->wasCanceled()) { dest->Resize(0); return false; } + emit UpdateInstallProgress(); + const auto read = src->Read(buffer.data(), buffer.size(), i); dest->Write(buffer.data(), read, i); } @@ -1739,32 +1748,19 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename, bool overwrite } const auto res = Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->InstallEntry( - *nsp, false, qt_raw_copy); + *nsp, true, qt_raw_copy); if (res == FileSys::InstallResult::Success) { return InstallResult::Success; } else if (res == FileSys::InstallResult::ErrorAlreadyExists) { - if (overwrite_files) { - const auto res2 = Core::System::GetInstance() - .GetFileSystemController() - .GetUserNANDContents() - ->InstallEntry(*nsp, true, qt_raw_copy); - if (res2 != FileSys::InstallResult::Success) { - return InstallResult::Failure; - } - return InstallResult::Overwrite; - } else { - return InstallResult::AlreadyExists; - } + return InstallResult::Overwrite; } else { return InstallResult::Failure; } } -InstallResult GMainWindow::InstallNCA(const QString& filename, bool overwrite_files, - QProgressDialog& install_progress) { - const auto qt_raw_copy = [this, &install_progress](const FileSys::VirtualFile& src, - const FileSys::VirtualFile& dest, - std::size_t block_size) { +InstallResult GMainWindow::InstallNCA(const QString& filename) { + const auto qt_raw_copy = [this](const FileSys::VirtualFile& src, + const FileSys::VirtualFile& dest, std::size_t block_size) { if (src == nullptr || dest == nullptr) { return false; } @@ -1775,11 +1771,13 @@ InstallResult GMainWindow::InstallNCA(const QString& filename, bool overwrite_fi std::array buffer{}; for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { - if (install_progress.wasCanceled()) { + if (install_progress->wasCanceled()) { dest->Resize(0); return false; } + emit UpdateInstallProgress(); + const auto read = src->Read(buffer.data(), buffer.size(), i); dest->Write(buffer.data(), read, i); } @@ -1830,30 +1828,18 @@ InstallResult GMainWindow::InstallNCA(const QString& filename, bool overwrite_fi res = Core::System::GetInstance() .GetFileSystemController() .GetUserNANDContents() - ->InstallEntry(*nca, static_cast(index), false, qt_raw_copy); + ->InstallEntry(*nca, static_cast(index), true, qt_raw_copy); } else { res = Core::System::GetInstance() .GetFileSystemController() .GetSystemNANDContents() - ->InstallEntry(*nca, static_cast(index), false, qt_raw_copy); + ->InstallEntry(*nca, static_cast(index), true, qt_raw_copy); } if (res == FileSys::InstallResult::Success) { return InstallResult::Success; } else if (res == FileSys::InstallResult::ErrorAlreadyExists) { - if (overwrite_files) { - const auto res2 = - Core::System::GetInstance() - .GetFileSystemController() - .GetUserNANDContents() - ->InstallEntry(*nca, static_cast(index), true, qt_raw_copy); - if (res2 != FileSys::InstallResult::Success) { - return InstallResult::Failure; - } - return InstallResult::Overwrite; - } else { - return InstallResult::AlreadyExists; - } + return InstallResult::Overwrite; } else { return InstallResult::Failure; } diff --git a/src/yuzu/main.h b/src/yuzu/main.h index deea8170d4..adff65fb5e 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -51,7 +51,6 @@ enum class EmulatedDirectoryTarget { enum class InstallResult { Success, Overwrite, - AlreadyExists, Failure, }; @@ -110,6 +109,8 @@ signals: // Signal that tells widgets to update icons to use the current theme void UpdateThemedIcons(); + void UpdateInstallProgress(); + void ErrorDisplayFinished(); void ProfileSelectorFinishedSelection(std::optional uuid); @@ -206,6 +207,7 @@ private slots: void OnGameListOpenPerGameProperties(const std::string& file); void OnMenuLoadFile(); void OnMenuLoadFolder(); + void IncrementInstallProgress(); void OnMenuInstallToNAND(); void OnMenuRecentFile(); void OnConfigure(); @@ -226,10 +228,8 @@ private slots: private: std::optional SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); - InstallResult InstallNSPXCI(const QString& filename, bool overwrite_files, - QProgressDialog& install_progress); - InstallResult InstallNCA(const QString& filename, bool overwrite_files, - QProgressDialog& install_progress); + InstallResult InstallNSPXCI(const QString& filename); + InstallResult InstallNCA(const QString& filename); void UpdateWindowTitle(const std::string& title_name = {}, const std::string& title_version = {}); void UpdateStatusBar(); @@ -284,6 +284,9 @@ private: HotkeyRegistry hotkey_registry; + // Install progress dialog + QProgressDialog* install_progress; + protected: void dropEvent(QDropEvent* event) override; void dragEnterEvent(QDragEnterEvent* event) override;