Qt/Loader: Let users choose which packages to install

This commit is contained in:
Megamouse 2023-06-01 02:08:09 +02:00
parent c3b7229fbb
commit 66e1cf96e2
6 changed files with 111 additions and 44 deletions

View file

@ -1645,17 +1645,19 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
} }
} }
std::vector<std::string> pkgs;
if (!lock_file && !ins_dir.empty()) if (!lock_file && !ins_dir.empty())
{ {
sys_log.notice("Found INSDIR: %s", ins_dir); sys_log.notice("Found INSDIR: %s", ins_dir);
for (auto&& entry : fs::dir{ins_dir}) for (auto&& entry : fs::dir{ins_dir})
{ {
const std::string pkg = ins_dir + entry.name; const std::string pkg_file = ins_dir + entry.name;
if (!entry.is_directory && entry.name.ends_with(".PKG") && !rpcs3::utils::install_pkg(pkg))
if (!entry.is_directory && entry.name.ends_with(".PKG"))
{ {
sys_log.error("Failed to install %s", pkg); pkgs.push_back(pkg_file);
return game_boot_result::install_failed;
} }
} }
} }
@ -1670,10 +1672,9 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
{ {
const std::string pkg_file = pkg_dir + entry.name + "/INSTALL.PKG"; const std::string pkg_file = pkg_dir + entry.name + "/INSTALL.PKG";
if (fs::is_file(pkg_file) && !rpcs3::utils::install_pkg(pkg_file)) if (fs::is_file(pkg_file))
{ {
sys_log.error("Failed to install %s", pkg_file); pkgs.push_back(pkg_file);
return game_boot_result::install_failed;
} }
} }
} }
@ -1689,14 +1690,30 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
{ {
const std::string pkg_file = extra_dir + entry.name + "/DATA000.PKG"; const std::string pkg_file = extra_dir + entry.name + "/DATA000.PKG";
if (fs::is_file(pkg_file) && !rpcs3::utils::install_pkg(pkg_file)) if (fs::is_file(pkg_file))
{ {
sys_log.error("Failed to install %s", pkg_file); pkgs.push_back(pkg_file);
}
}
}
}
if (!pkgs.empty())
{
bool install_success = true;
BlockingCallFromMainThread([this, &pkgs, &install_success]()
{
if (!GetCallbacks().on_install_pkgs(pkgs))
{
install_success = false;
}
});
if (!install_success)
{
sys_log.error("Failed to install packages");
return game_boot_result::install_failed; return game_boot_result::install_failed;
} }
} }
}
}
if (!lock_file) if (!lock_file)
{ {

View file

@ -95,6 +95,7 @@ struct EmuCallbacks
std::function<bool(const std::string&, s32, s32, s32&, s32&, u8*, bool)> get_scaled_image; // (filename, target_width, target_height, width, height, dst, force_fit) std::function<bool(const std::string&, s32, s32, s32&, s32&, u8*, bool)> get_scaled_image; // (filename, target_width, target_height, width, height, dst, force_fit)
std::string(*resolve_path)(std::string_view) = [](std::string_view arg){ return std::string{arg}; }; // Resolve path using Qt std::string(*resolve_path)(std::string_view) = [](std::string_view arg){ return std::string{arg}; }; // Resolve path using Qt
std::function<std::vector<std::string>()> get_font_dirs; std::function<std::vector<std::string>()> get_font_dirs;
std::function<bool(const std::vector<std::string>&)> on_install_pkgs;
}; };
namespace utils namespace utils

View file

@ -348,5 +348,18 @@ EmuCallbacks main_application::CreateCallbacks()
return font_dirs; return font_dirs;
}; };
callbacks.on_install_pkgs = [](const std::vector<std::string>& pkgs)
{
for (const std::string& pkg : pkgs)
{
if (!rpcs3::utils::install_pkg(pkg))
{
sys_log.error("Failed to install %s", pkg);
return false;
}
}
return true;
};
return callbacks; return callbacks;
} }

View file

@ -554,6 +554,21 @@ void gui_application::InitializeCallbacks()
}); });
}; };
if (m_show_gui) // If this is false, we already have a fallback in the main_application.
{
callbacks.on_install_pkgs = [this](const std::vector<std::string>& pkgs)
{
ensure(m_main_window);
ensure(!pkgs.empty());
QStringList pkg_list;
for (const std::string& pkg : pkgs)
{
pkg_list << QString::fromStdString(pkg);
}
return m_main_window->InstallPackages(pkg_list, true);
};
}
Emu.SetCallbacks(std::move(callbacks)); Emu.SetCallbacks(std::move(callbacks));
} }

View file

@ -710,10 +710,12 @@ bool main_window::InstallFileInExData(const std::string& extension, const QStrin
return to.commit(); return to.commit();
} }
void main_window::InstallPackages(QStringList file_paths) bool main_window::InstallPackages(QStringList file_paths, bool from_boot)
{ {
if (file_paths.isEmpty()) if (file_paths.isEmpty())
{ {
ensure(!from_boot);
// If this function was called without a path, ask the user for files to install. // If this function was called without a path, ask the user for files to install.
const QString path_last_pkg = m_gui_settings->GetValue(gui::fd_install_pkg).toString(); const QString path_last_pkg = m_gui_settings->GetValue(gui::fd_install_pkg).toString();
const QStringList paths = QFileDialog::getOpenFileNames(this, tr("Select packages and/or rap files to install"), const QStringList paths = QFileDialog::getOpenFileNames(this, tr("Select packages and/or rap files to install"),
@ -721,7 +723,7 @@ void main_window::InstallPackages(QStringList file_paths)
if (paths.isEmpty()) if (paths.isEmpty())
{ {
return; return true;
} }
file_paths.append(paths); file_paths.append(paths);
@ -739,7 +741,7 @@ void main_window::InstallPackages(QStringList file_paths)
if (!info.is_valid) if (!info.is_valid)
{ {
QMessageBox::warning(this, tr("Invalid package!"), tr("The selected package is invalid!\n\nPath:\n%0").arg(file_path)); QMessageBox::warning(this, tr("Invalid package!"), tr("The selected package is invalid!\n\nPath:\n%0").arg(file_path));
return; return false;
} }
if (info.type != compat::package_type::other) if (info.type != compat::package_type::other)
@ -780,21 +782,10 @@ void main_window::InstallPackages(QStringList file_paths)
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
{ {
gui_log.notice("PKG: Cancelled installation from drop.\n%s", sstr(info_string)); gui_log.notice("PKG: Cancelled installation from drop.\n%s", sstr(info_string));
return; return true;
} }
} }
if (!m_gui_settings->GetBootConfirmation(this))
{
// Last chance to cancel the operation
return;
}
if (!Emu.IsStopped())
{
Emu.GracefulShutdown(false);
}
// Install rap files if available // Install rap files if available
int installed_rap_and_edat_count = 0; int installed_rap_and_edat_count = 0;
@ -818,8 +809,22 @@ void main_window::InstallPackages(QStringList file_paths)
} }
}; };
if (!from_boot)
{
if (!m_gui_settings->GetBootConfirmation(this))
{
// Last chance to cancel the operation
return true;
}
if (!Emu.IsStopped())
{
Emu.GracefulShutdown(false);
}
install_filetype("rap"); install_filetype("rap");
install_filetype("edat"); install_filetype("edat");
}
if (installed_rap_and_edat_count > 0) if (installed_rap_and_edat_count > 0)
{ {
@ -830,21 +835,30 @@ void main_window::InstallPackages(QStringList file_paths)
// Find remaining package files // Find remaining package files
file_paths = file_paths.filter(QRegularExpression(".*\\.pkg", QRegularExpression::PatternOption::CaseInsensitiveOption)); file_paths = file_paths.filter(QRegularExpression(".*\\.pkg", QRegularExpression::PatternOption::CaseInsensitiveOption));
if (!file_paths.isEmpty()) if (file_paths.isEmpty())
{ {
return true;
}
if (from_boot)
{
return HandlePackageInstallation(file_paths, true);
}
// Handle further installations with a timeout. Otherwise the source explorer instance is not usable during the following file processing. // Handle further installations with a timeout. Otherwise the source explorer instance is not usable during the following file processing.
QTimer::singleShot(0, [this, paths = std::move(file_paths)]() QTimer::singleShot(0, [this, paths = std::move(file_paths)]()
{ {
HandlePackageInstallation(paths); HandlePackageInstallation(paths, false);
}); });
}
return true;
} }
void main_window::HandlePackageInstallation(QStringList file_paths) bool main_window::HandlePackageInstallation(QStringList file_paths, bool from_boot)
{ {
if (file_paths.empty()) if (file_paths.empty())
{ {
return; return false;
} }
std::vector<compat::package_info> packages; std::vector<compat::package_info> packages;
@ -868,15 +882,18 @@ void main_window::HandlePackageInstallation(QStringList file_paths)
if (packages.empty()) if (packages.empty())
{ {
return; return true;
} }
if (!from_boot)
{
if (!m_gui_settings->GetBootConfirmation(this)) if (!m_gui_settings->GetBootConfirmation(this))
{ {
return; return true;
} }
Emu.GracefulShutdown(false); Emu.GracefulShutdown(false);
}
std::vector<std::string> path_vec; std::vector<std::string> path_vec;
for (const compat::package_info& pkg : packages) for (const compat::package_info& pkg : packages)
@ -973,7 +990,9 @@ void main_window::HandlePackageInstallation(QStringList file_paths)
} }
} }
if (worker()) const bool success = worker();
if (success)
{ {
pdlg.SetValue(pdlg.maximum()); pdlg.SetValue(pdlg.maximum());
std::this_thread::sleep_for(100ms); std::this_thread::sleep_for(100ms);
@ -1032,7 +1051,7 @@ void main_window::HandlePackageInstallation(QStringList file_paths)
if (bootable_paths_installed.empty()) if (bootable_paths_installed.empty())
{ {
m_gui_settings->ShowInfoBox(tr("Success!"), tr("Successfully installed software from package(s)!"), gui::ib_pkg_success, this); m_gui_settings->ShowInfoBox(tr("Success!"), tr("Successfully installed software from package(s)!"), gui::ib_pkg_success, this);
return; return true;
} }
auto dlg = new QDialog(this); auto dlg = new QDialog(this);
@ -1144,6 +1163,8 @@ void main_window::HandlePackageInstallation(QStringList file_paths)
} }
} }
} }
return success;
} }
void main_window::ExtractMSELF() void main_window::ExtractMSELF()

View file

@ -86,7 +86,7 @@ public:
bool Init(bool with_cli_boot); bool Init(bool with_cli_boot);
QIcon GetAppIcon() const; QIcon GetAppIcon() const;
bool OnMissingFw(); bool OnMissingFw();
void InstallPackages(QStringList file_paths = QStringList()); bool InstallPackages(QStringList file_paths = {}, bool from_boot = false);
void InstallPup(QString file_path = ""); void InstallPup(QString file_path = "");
Q_SIGNALS: Q_SIGNALS:
@ -149,7 +149,7 @@ private:
static bool InstallFileInExData(const std::string& extension, const QString& path, const std::string& filename); static bool InstallFileInExData(const std::string& extension, const QString& path, const std::string& filename);
void HandlePackageInstallation(QStringList file_paths); bool HandlePackageInstallation(QStringList file_paths, bool from_boot);
void HandlePupInstallation(const QString& file_path, const QString& dir_path = ""); void HandlePupInstallation(const QString& file_path, const QString& dir_path = "");
void ExtractPup(); void ExtractPup();