summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/yuzu/install_dialog.cpp12
-rw-r--r--src/yuzu/install_dialog.h2
-rw-r--r--src/yuzu/main.cpp118
-rw-r--r--src/yuzu/main.h13
4 files changed, 65 insertions, 80 deletions
diff --git a/src/yuzu/install_dialog.cpp b/src/yuzu/install_dialog.cpp
index 5f3b4c963..06b0b1874 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
22 item->setCheckState(Qt::Checked); 22 item->setCheckState(Qt::Checked);
23 } 23 }
24 24
25 file_list->setMinimumWidth((file_list->sizeHintForColumn(0) * 10) / 9); 25 file_list->setMinimumWidth((file_list->sizeHintForColumn(0) * 11) / 10);
26 26
27 vbox_layout = new QVBoxLayout; 27 vbox_layout = new QVBoxLayout;
28 28
@@ -30,8 +30,8 @@ InstallDialog::InstallDialog(QWidget* parent, const QStringList& files) : QDialo
30 30
31 description = new QLabel(tr("Please confirm these are the files you wish to install.")); 31 description = new QLabel(tr("Please confirm these are the files you wish to install."));
32 32
33 overwrite_files = new QCheckBox(tr("Overwrite Existing Files")); 33 update_description =
34 overwrite_files->setCheckState(Qt::Unchecked); 34 new QLabel(tr("Installing an Update or DLC will overwrite the previously installed one."));
35 35
36 buttons = new QDialogButtonBox; 36 buttons = new QDialogButtonBox;
37 buttons->addButton(QDialogButtonBox::Cancel); 37 buttons->addButton(QDialogButtonBox::Cancel);
@@ -40,10 +40,10 @@ InstallDialog::InstallDialog(QWidget* parent, const QStringList& files) : QDialo
40 connect(buttons, &QDialogButtonBox::accepted, this, &InstallDialog::accept); 40 connect(buttons, &QDialogButtonBox::accepted, this, &InstallDialog::accept);
41 connect(buttons, &QDialogButtonBox::rejected, this, &InstallDialog::reject); 41 connect(buttons, &QDialogButtonBox::rejected, this, &InstallDialog::reject);
42 42
43 hbox_layout->addWidget(overwrite_files);
44 hbox_layout->addWidget(buttons); 43 hbox_layout->addWidget(buttons);
45 44
46 vbox_layout->addWidget(description); 45 vbox_layout->addWidget(description);
46 vbox_layout->addWidget(update_description);
47 vbox_layout->addWidget(file_list); 47 vbox_layout->addWidget(file_list);
48 vbox_layout->addLayout(hbox_layout); 48 vbox_layout->addLayout(hbox_layout);
49 49
@@ -67,10 +67,6 @@ QStringList InstallDialog::GetFiles() const {
67 return files; 67 return files;
68} 68}
69 69
70bool InstallDialog::ShouldOverwriteFiles() const {
71 return overwrite_files->isChecked();
72}
73
74int InstallDialog::GetMinimumWidth() const { 70int InstallDialog::GetMinimumWidth() const {
75 return file_list->width(); 71 return file_list->width();
76} 72}
diff --git a/src/yuzu/install_dialog.h b/src/yuzu/install_dialog.h
index 55a458ba8..e4aba1b06 100644
--- a/src/yuzu/install_dialog.h
+++ b/src/yuzu/install_dialog.h
@@ -31,6 +31,6 @@ private:
31 QHBoxLayout* hbox_layout; 31 QHBoxLayout* hbox_layout;
32 32
33 QLabel* description; 33 QLabel* description;
34 QCheckBox* overwrite_files; 34 QLabel* update_description;
35 QDialogButtonBox* buttons; 35 QDialogButtonBox* buttons;
36}; 36};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 4539cbe0d..8a57e34c7 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -848,6 +848,9 @@ void GMainWindow::ConnectWidgetEvents() {
848 connect(game_list, &GameList::OpenPerGameGeneralRequested, this, 848 connect(game_list, &GameList::OpenPerGameGeneralRequested, this,
849 &GMainWindow::OnGameListOpenPerGameProperties); 849 &GMainWindow::OnGameListOpenPerGameProperties);
850 850
851 connect(this, &GMainWindow::UpdateInstallProgress, this,
852 &GMainWindow::IncrementInstallProgress);
853
851 connect(this, &GMainWindow::EmulationStarting, render_window, 854 connect(this, &GMainWindow::EmulationStarting, render_window,
852 &GRenderWindow::OnEmulationStarting); 855 &GRenderWindow::OnEmulationStarting);
853 connect(this, &GMainWindow::EmulationStopping, render_window, 856 connect(this, &GMainWindow::EmulationStopping, render_window,
@@ -1594,6 +1597,10 @@ void GMainWindow::OnMenuLoadFolder() {
1594 } 1597 }
1595} 1598}
1596 1599
1600void GMainWindow::IncrementInstallProgress() {
1601 install_progress->setValue(install_progress->value() + 1);
1602}
1603
1597void GMainWindow::OnMenuInstallToNAND() { 1604void GMainWindow::OnMenuInstallToNAND() {
1598 const QString file_filter = 1605 const QString file_filter =
1599 tr("Installable Switch File (*.nca *.nsp *.xci);;Nintendo Content Archive " 1606 tr("Installable Switch File (*.nca *.nsp *.xci);;Nintendo Content Archive "
@@ -1613,28 +1620,35 @@ void GMainWindow::OnMenuInstallToNAND() {
1613 } 1620 }
1614 1621
1615 const QStringList files = installDialog.GetFiles(); 1622 const QStringList files = installDialog.GetFiles();
1616 const bool overwrite_files = installDialog.ShouldOverwriteFiles();
1617 1623
1618 int count = 0; 1624 int remaining = filenames.size();
1619 const int total_count = filenames.size(); 1625
1626 // This would only overflow above 2^43 bytes (8.796 TB)
1627 int total_size = 0;
1628 for (const QString& file : files) {
1629 total_size += static_cast<int>(QFile(file).size() / 0x1000);
1630 }
1631 if (total_size < 0) {
1632 LOG_CRITICAL(Frontend, "Attempting to install too many files, aborting.");
1633 return;
1634 }
1620 1635
1621 QStringList new_files{}; // Newly installed files that do not yet exist in the NAND 1636 QStringList new_files{}; // Newly installed files that do not yet exist in the NAND
1622 QStringList overwritten_files{}; // Files that overwrote those existing in the NAND 1637 QStringList overwritten_files{}; // Files that overwrote those existing in the NAND
1623 QStringList existing_files{}; // Files that were not installed as they already exist in the NAND 1638 QStringList failed_files{}; // Files that failed to install due to errors
1624 QStringList failed_files{}; // Files that failed to install due to errors
1625 1639
1626 ui.action_Install_File_NAND->setEnabled(false); 1640 ui.action_Install_File_NAND->setEnabled(false);
1627 1641
1628 QProgressDialog install_progress(QStringLiteral(""), tr("Cancel"), 0, total_count, this); 1642 install_progress = new QProgressDialog(QStringLiteral(""), tr("Cancel"), 0, total_size, this);
1629 install_progress.setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint & 1643 install_progress->setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint &
1630 ~Qt::WindowMaximizeButtonHint); 1644 ~Qt::WindowMaximizeButtonHint);
1631 install_progress.setAutoClose(false); 1645 install_progress->setAttribute(Qt::WA_DeleteOnClose, true);
1632 install_progress.setFixedWidth(installDialog.GetMinimumWidth()); 1646 install_progress->setFixedWidth(installDialog.GetMinimumWidth() + 40);
1633 install_progress.show(); 1647 install_progress->show();
1634 1648
1635 for (const QString& file : files) { 1649 for (const QString& file : files) {
1636 install_progress.setWindowTitle(tr("%n file(s) remaining", "", total_count - count)); 1650 install_progress->setWindowTitle(tr("%n file(s) remaining", "", remaining));
1637 install_progress.setLabelText( 1651 install_progress->setLabelText(
1638 tr("Installing file \"%1\"...").arg(QFileInfo(file).fileName())); 1652 tr("Installing file \"%1\"...").arg(QFileInfo(file).fileName()));
1639 1653
1640 QFuture<InstallResult> future; 1654 QFuture<InstallResult> future;
@@ -1642,19 +1656,21 @@ void GMainWindow::OnMenuInstallToNAND() {
1642 1656
1643 if (file.endsWith(QStringLiteral("xci"), Qt::CaseInsensitive) || 1657 if (file.endsWith(QStringLiteral("xci"), Qt::CaseInsensitive) ||
1644 file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { 1658 file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) {
1645 future = QtConcurrent::run([this, &file, &overwrite_files, &install_progress] { 1659
1646 return InstallNSPXCI(file, overwrite_files, install_progress); 1660 future = QtConcurrent::run([this, &file] { return InstallNSPXCI(file); });
1647 });
1648 1661
1649 while (!future.isFinished()) { 1662 while (!future.isFinished()) {
1650 QCoreApplication::processEvents(); 1663 QCoreApplication::processEvents();
1651 } 1664 }
1652 1665
1653 result = future.result(); 1666 result = future.result();
1667
1654 } else { 1668 } else {
1655 result = InstallNCA(file, overwrite_files, install_progress); 1669 result = InstallNCA(file);
1656 } 1670 }
1657 1671
1672 std::this_thread::sleep_for(std::chrono::milliseconds(10));
1673
1658 switch (result) { 1674 switch (result) {
1659 case InstallResult::Success: 1675 case InstallResult::Success:
1660 new_files.append(QFileInfo(file).fileName()); 1676 new_files.append(QFileInfo(file).fileName());
@@ -1662,19 +1678,15 @@ void GMainWindow::OnMenuInstallToNAND() {
1662 case InstallResult::Overwrite: 1678 case InstallResult::Overwrite:
1663 overwritten_files.append(QFileInfo(file).fileName()); 1679 overwritten_files.append(QFileInfo(file).fileName());
1664 break; 1680 break;
1665 case InstallResult::AlreadyExists:
1666 existing_files.append(QFileInfo(file).fileName());
1667 break;
1668 case InstallResult::Failure: 1681 case InstallResult::Failure:
1669 failed_files.append(QFileInfo(file).fileName()); 1682 failed_files.append(QFileInfo(file).fileName());
1670 break; 1683 break;
1671 } 1684 }
1672 1685
1673 install_progress.setValue(++count); 1686 --remaining;
1674 std::this_thread::sleep_for(std::chrono::milliseconds(10));
1675 } 1687 }
1676 1688
1677 install_progress.close(); 1689 install_progress->close();
1678 1690
1679 const QString install_results = 1691 const QString install_results =
1680 (new_files.isEmpty() ? QStringLiteral("") 1692 (new_files.isEmpty() ? QStringLiteral("")
@@ -1682,9 +1694,6 @@ void GMainWindow::OnMenuInstallToNAND() {
1682 (overwritten_files.isEmpty() 1694 (overwritten_files.isEmpty()
1683 ? QStringLiteral("") 1695 ? QStringLiteral("")
1684 : tr("%n file(s) were overwritten\n", "", overwritten_files.size())) + 1696 : tr("%n file(s) were overwritten\n", "", overwritten_files.size())) +
1685 (existing_files.isEmpty()
1686 ? QStringLiteral("")
1687 : tr("%n file(s) already exist in NAND\n", "", existing_files.size())) +
1688 (failed_files.isEmpty() ? QStringLiteral("") 1697 (failed_files.isEmpty() ? QStringLiteral("")
1689 : tr("%n file(s) failed to install\n", "", failed_files.size())); 1698 : tr("%n file(s) failed to install\n", "", failed_files.size()));
1690 1699
@@ -1695,11 +1704,9 @@ void GMainWindow::OnMenuInstallToNAND() {
1695 ui.action_Install_File_NAND->setEnabled(true); 1704 ui.action_Install_File_NAND->setEnabled(true);
1696} 1705}
1697 1706
1698InstallResult GMainWindow::InstallNSPXCI(const QString& filename, bool overwrite_files, 1707InstallResult GMainWindow::InstallNSPXCI(const QString& filename) {
1699 QProgressDialog& install_progress) { 1708 const auto qt_raw_copy = [this](const FileSys::VirtualFile& src,
1700 const auto qt_raw_copy = [this, &install_progress](const FileSys::VirtualFile& src, 1709 const FileSys::VirtualFile& dest, std::size_t block_size) {
1701 const FileSys::VirtualFile& dest,
1702 std::size_t block_size) {
1703 if (src == nullptr || dest == nullptr) { 1710 if (src == nullptr || dest == nullptr) {
1704 return false; 1711 return false;
1705 } 1712 }
@@ -1710,11 +1717,13 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename, bool overwrite
1710 std::array<u8, 0x1000> buffer{}; 1717 std::array<u8, 0x1000> buffer{};
1711 1718
1712 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { 1719 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
1713 if (install_progress.wasCanceled()) { 1720 if (install_progress->wasCanceled()) {
1714 dest->Resize(0); 1721 dest->Resize(0);
1715 return false; 1722 return false;
1716 } 1723 }
1717 1724
1725 emit UpdateInstallProgress();
1726
1718 const auto read = src->Read(buffer.data(), buffer.size(), i); 1727 const auto read = src->Read(buffer.data(), buffer.size(), i);
1719 dest->Write(buffer.data(), read, i); 1728 dest->Write(buffer.data(), read, i);
1720 } 1729 }
@@ -1739,32 +1748,19 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename, bool overwrite
1739 } 1748 }
1740 const auto res = 1749 const auto res =
1741 Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->InstallEntry( 1750 Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->InstallEntry(
1742 *nsp, false, qt_raw_copy); 1751 *nsp, true, qt_raw_copy);
1743 if (res == FileSys::InstallResult::Success) { 1752 if (res == FileSys::InstallResult::Success) {
1744 return InstallResult::Success; 1753 return InstallResult::Success;
1745 } else if (res == FileSys::InstallResult::ErrorAlreadyExists) { 1754 } else if (res == FileSys::InstallResult::ErrorAlreadyExists) {
1746 if (overwrite_files) { 1755 return InstallResult::Overwrite;
1747 const auto res2 = Core::System::GetInstance()
1748 .GetFileSystemController()
1749 .GetUserNANDContents()
1750 ->InstallEntry(*nsp, true, qt_raw_copy);
1751 if (res2 != FileSys::InstallResult::Success) {
1752 return InstallResult::Failure;
1753 }
1754 return InstallResult::Overwrite;
1755 } else {
1756 return InstallResult::AlreadyExists;
1757 }
1758 } else { 1756 } else {
1759 return InstallResult::Failure; 1757 return InstallResult::Failure;
1760 } 1758 }
1761} 1759}
1762 1760
1763InstallResult GMainWindow::InstallNCA(const QString& filename, bool overwrite_files, 1761InstallResult GMainWindow::InstallNCA(const QString& filename) {
1764 QProgressDialog& install_progress) { 1762 const auto qt_raw_copy = [this](const FileSys::VirtualFile& src,
1765 const auto qt_raw_copy = [this, &install_progress](const FileSys::VirtualFile& src, 1763 const FileSys::VirtualFile& dest, std::size_t block_size) {
1766 const FileSys::VirtualFile& dest,
1767 std::size_t block_size) {
1768 if (src == nullptr || dest == nullptr) { 1764 if (src == nullptr || dest == nullptr) {
1769 return false; 1765 return false;
1770 } 1766 }
@@ -1775,11 +1771,13 @@ InstallResult GMainWindow::InstallNCA(const QString& filename, bool overwrite_fi
1775 std::array<u8, 0x1000> buffer{}; 1771 std::array<u8, 0x1000> buffer{};
1776 1772
1777 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { 1773 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
1778 if (install_progress.wasCanceled()) { 1774 if (install_progress->wasCanceled()) {
1779 dest->Resize(0); 1775 dest->Resize(0);
1780 return false; 1776 return false;
1781 } 1777 }
1782 1778
1779 emit UpdateInstallProgress();
1780
1783 const auto read = src->Read(buffer.data(), buffer.size(), i); 1781 const auto read = src->Read(buffer.data(), buffer.size(), i);
1784 dest->Write(buffer.data(), read, i); 1782 dest->Write(buffer.data(), read, i);
1785 } 1783 }
@@ -1830,30 +1828,18 @@ InstallResult GMainWindow::InstallNCA(const QString& filename, bool overwrite_fi
1830 res = Core::System::GetInstance() 1828 res = Core::System::GetInstance()
1831 .GetFileSystemController() 1829 .GetFileSystemController()
1832 .GetUserNANDContents() 1830 .GetUserNANDContents()
1833 ->InstallEntry(*nca, static_cast<FileSys::TitleType>(index), false, qt_raw_copy); 1831 ->InstallEntry(*nca, static_cast<FileSys::TitleType>(index), true, qt_raw_copy);
1834 } else { 1832 } else {
1835 res = Core::System::GetInstance() 1833 res = Core::System::GetInstance()
1836 .GetFileSystemController() 1834 .GetFileSystemController()
1837 .GetSystemNANDContents() 1835 .GetSystemNANDContents()
1838 ->InstallEntry(*nca, static_cast<FileSys::TitleType>(index), false, qt_raw_copy); 1836 ->InstallEntry(*nca, static_cast<FileSys::TitleType>(index), true, qt_raw_copy);
1839 } 1837 }
1840 1838
1841 if (res == FileSys::InstallResult::Success) { 1839 if (res == FileSys::InstallResult::Success) {
1842 return InstallResult::Success; 1840 return InstallResult::Success;
1843 } else if (res == FileSys::InstallResult::ErrorAlreadyExists) { 1841 } else if (res == FileSys::InstallResult::ErrorAlreadyExists) {
1844 if (overwrite_files) { 1842 return InstallResult::Overwrite;
1845 const auto res2 =
1846 Core::System::GetInstance()
1847 .GetFileSystemController()
1848 .GetUserNANDContents()
1849 ->InstallEntry(*nca, static_cast<FileSys::TitleType>(index), true, qt_raw_copy);
1850 if (res2 != FileSys::InstallResult::Success) {
1851 return InstallResult::Failure;
1852 }
1853 return InstallResult::Overwrite;
1854 } else {
1855 return InstallResult::AlreadyExists;
1856 }
1857 } else { 1843 } else {
1858 return InstallResult::Failure; 1844 return InstallResult::Failure;
1859 } 1845 }
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index deea8170d..adff65fb5 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -51,7 +51,6 @@ enum class EmulatedDirectoryTarget {
51enum class InstallResult { 51enum class InstallResult {
52 Success, 52 Success,
53 Overwrite, 53 Overwrite,
54 AlreadyExists,
55 Failure, 54 Failure,
56}; 55};
57 56
@@ -110,6 +109,8 @@ signals:
110 // Signal that tells widgets to update icons to use the current theme 109 // Signal that tells widgets to update icons to use the current theme
111 void UpdateThemedIcons(); 110 void UpdateThemedIcons();
112 111
112 void UpdateInstallProgress();
113
113 void ErrorDisplayFinished(); 114 void ErrorDisplayFinished();
114 115
115 void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid); 116 void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid);
@@ -206,6 +207,7 @@ private slots:
206 void OnGameListOpenPerGameProperties(const std::string& file); 207 void OnGameListOpenPerGameProperties(const std::string& file);
207 void OnMenuLoadFile(); 208 void OnMenuLoadFile();
208 void OnMenuLoadFolder(); 209 void OnMenuLoadFolder();
210 void IncrementInstallProgress();
209 void OnMenuInstallToNAND(); 211 void OnMenuInstallToNAND();
210 void OnMenuRecentFile(); 212 void OnMenuRecentFile();
211 void OnConfigure(); 213 void OnConfigure();
@@ -226,10 +228,8 @@ private slots:
226 228
227private: 229private:
228 std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); 230 std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
229 InstallResult InstallNSPXCI(const QString& filename, bool overwrite_files, 231 InstallResult InstallNSPXCI(const QString& filename);
230 QProgressDialog& install_progress); 232 InstallResult InstallNCA(const QString& filename);
231 InstallResult InstallNCA(const QString& filename, bool overwrite_files,
232 QProgressDialog& install_progress);
233 void UpdateWindowTitle(const std::string& title_name = {}, 233 void UpdateWindowTitle(const std::string& title_name = {},
234 const std::string& title_version = {}); 234 const std::string& title_version = {});
235 void UpdateStatusBar(); 235 void UpdateStatusBar();
@@ -284,6 +284,9 @@ private:
284 284
285 HotkeyRegistry hotkey_registry; 285 HotkeyRegistry hotkey_registry;
286 286
287 // Install progress dialog
288 QProgressDialog* install_progress;
289
287protected: 290protected:
288 void dropEvent(QDropEvent* event) override; 291 void dropEvent(QDropEvent* event) override;
289 void dragEnterEvent(QDragEnterEvent* event) override; 292 void dragEnterEvent(QDragEnterEvent* event) override;