mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-04-03 20:05:33 +02:00
Qt: ask user for install options before starting the installation
This commit is contained in:
parent
92f56215d0
commit
bba1cf4b6e
|
|
@ -801,7 +801,7 @@ bool main_window::InstallPackages(QStringList file_paths, bool from_boot)
|
|||
|
||||
if (file_paths.count() == 1)
|
||||
{
|
||||
const QString file_path = file_paths.front();
|
||||
const QString& file_path = file_paths.front();
|
||||
const QFileInfo file_info(file_path);
|
||||
|
||||
if (file_info.isDir())
|
||||
|
|
@ -819,92 +819,6 @@ bool main_window::InstallPackages(QStringList file_paths, bool from_boot)
|
|||
|
||||
return InstallPackages(dir_file_paths, from_boot);
|
||||
}
|
||||
|
||||
if (file_info.suffix().compare("pkg", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
compat::package_info info = game_compatibility::GetPkgInfo(file_path, m_game_list_frame ? m_game_list_frame->GetGameCompatibility() : nullptr);
|
||||
|
||||
if (!info.is_valid)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Invalid package!"), tr("The selected package is invalid!\n\nPath:\n%0").arg(file_path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (info.type != compat::package_type::other)
|
||||
{
|
||||
if (info.type == compat::package_type::dlc)
|
||||
{
|
||||
info.local_cat = tr("\nDLC", "Block for package type (DLC)");
|
||||
}
|
||||
else
|
||||
{
|
||||
info.local_cat = tr("\nUpdate", "Block for package type (Update)");
|
||||
}
|
||||
}
|
||||
else if (!info.local_cat.isEmpty())
|
||||
{
|
||||
info.local_cat = tr("\n%0", "Block for package type").arg(info.local_cat);
|
||||
}
|
||||
|
||||
if (!info.title_id.isEmpty())
|
||||
{
|
||||
info.title_id = tr("\n%0", "Block for Title ID").arg(info.title_id);
|
||||
}
|
||||
|
||||
if (!info.version.isEmpty())
|
||||
{
|
||||
info.version = tr("\nVersion %0", "Block for Version").arg(info.version);
|
||||
}
|
||||
|
||||
if (!info.changelog.isEmpty())
|
||||
{
|
||||
info.changelog = tr("Changelog:\n%0", "Block for Changelog").arg(info.changelog);
|
||||
}
|
||||
|
||||
u64 free_space = 0;
|
||||
|
||||
// Retrieve disk space info on data path's drive
|
||||
if (fs::device_stat stat{}; fs::statfs(rpcs3::utils::get_hdd0_dir(), stat))
|
||||
{
|
||||
free_space = stat.avail_free;
|
||||
}
|
||||
|
||||
const QString installation_info =
|
||||
tr("Installation path: %0\nAvailable disk space: %1%2\nRequired disk space: %3")
|
||||
.arg(QString::fromStdString(rpcs3::utils::get_hdd0_game_dir()))
|
||||
.arg(gui::utils::format_byte_size(free_space))
|
||||
.arg(info.data_size <= free_space ? QString() : tr(" - <b>NOT ENOUGH SPACE</b>"))
|
||||
.arg(gui::utils::format_byte_size(info.data_size));
|
||||
|
||||
const QString info_string = QStringLiteral("%0\n\n%1%2%3%4").arg(file_info.fileName()).arg(info.title).arg(info.local_cat).arg(info.title_id).arg(info.version);
|
||||
QString message = tr("Do you want to install this package?\n\n%0\n\n%1").arg(info_string).arg(installation_info);
|
||||
|
||||
QMessageBox mb(QMessageBox::Icon::Question, tr("PKG Decrypter / Installer"), gui::utils::make_paragraph(message), QMessageBox::Yes | QMessageBox::No, this);
|
||||
mb.setDefaultButton(QMessageBox::No);
|
||||
mb.setTextFormat(Qt::RichText); // Support HTML tags
|
||||
mb.button(QMessageBox::Yes)->setEnabled(info.data_size <= free_space);
|
||||
|
||||
if (!info.changelog.isEmpty())
|
||||
{
|
||||
mb.setInformativeText(tr("To see the changelog, please click \"Show Details\"."));
|
||||
mb.setDetailedText(info.changelog);
|
||||
|
||||
// Smartass hack to make the unresizeable message box wide enough for the changelog
|
||||
const int log_width = QLabel(info.changelog).sizeHint().width();
|
||||
while (QLabel(message).sizeHint().width() < log_width)
|
||||
{
|
||||
message += " ";
|
||||
}
|
||||
|
||||
mb.setText(message);
|
||||
}
|
||||
|
||||
if (mb.exec() != QMessageBox::Yes)
|
||||
{
|
||||
gui_log.notice("PKG: Cancelled installation from drop.\n%s\n%s", info_string, info.changelog);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Install rap files if available
|
||||
|
|
@ -983,28 +897,22 @@ bool main_window::HandlePackageInstallation(QStringList file_paths, bool from_bo
|
|||
}
|
||||
|
||||
std::vector<compat::package_info> packages;
|
||||
bool precompile_caches = false;
|
||||
bool create_desktop_shortcuts = false;
|
||||
bool create_app_shortcut = false;
|
||||
|
||||
game_compatibility* compat = m_game_list_frame ? m_game_list_frame->GetGameCompatibility() : nullptr;
|
||||
|
||||
if (file_paths.size() > 1)
|
||||
// Let the user choose the packages to install and select the order in which they shall be installed.
|
||||
pkg_install_dialog dlg(file_paths, compat, this);
|
||||
connect(&dlg, &QDialog::accepted, this, [&]()
|
||||
{
|
||||
// Let the user choose the packages to install and select the order in which they shall be installed.
|
||||
pkg_install_dialog dlg(file_paths, compat, this);
|
||||
connect(&dlg, &QDialog::accepted, this, [&packages, &dlg]()
|
||||
{
|
||||
packages = dlg.GetPathsToInstall();
|
||||
});
|
||||
dlg.exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
packages.push_back(game_compatibility::GetPkgInfo(file_paths.front(), compat));
|
||||
}
|
||||
|
||||
if (packages.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
packages = dlg.get_paths_to_install();
|
||||
precompile_caches = dlg.precompile_caches();
|
||||
create_desktop_shortcuts = dlg.create_desktop_shortcuts();
|
||||
create_app_shortcut = dlg.create_app_shortcut();
|
||||
});
|
||||
dlg.exec();
|
||||
|
||||
if (!from_boot)
|
||||
{
|
||||
|
|
@ -1178,7 +1086,7 @@ bool main_window::HandlePackageInstallation(QStringList file_paths, bool from_bo
|
|||
|
||||
if (!bootable_paths_installed.empty())
|
||||
{
|
||||
m_game_list_frame->AddRefreshedSlot([this, paths = std::move(bootable_paths_installed)](std::set<std::string>& claimed_paths) mutable
|
||||
m_game_list_frame->AddRefreshedSlot([this, create_desktop_shortcuts, precompile_caches, create_app_shortcut, paths = std::move(bootable_paths_installed)](std::set<std::string>& claimed_paths) mutable
|
||||
{
|
||||
// Try to claim operations on ID
|
||||
for (auto it = paths.begin(); it != paths.end();)
|
||||
|
|
@ -1196,7 +1104,12 @@ bool main_window::HandlePackageInstallation(QStringList file_paths, bool from_bo
|
|||
}
|
||||
}
|
||||
|
||||
ShowOptionalGamePreparations(tr("Success!"), tr("Successfully installed software from package(s)!"), std::move(paths));
|
||||
CreateShortCuts(paths, create_desktop_shortcuts, create_app_shortcut);
|
||||
|
||||
if (precompile_caches)
|
||||
{
|
||||
PrecompileCachesFromInstalledPackages(paths);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -2431,49 +2344,7 @@ void main_window::ShowOptionalGamePreparations(const QString& title, const QStri
|
|||
dlg->hide();
|
||||
dlg->accept();
|
||||
|
||||
std::set<gui::utils::shortcut_location> locations;
|
||||
|
||||
#ifdef _WIN32
|
||||
locations.insert(gui::utils::shortcut_location::rpcs3_shortcuts);
|
||||
#endif
|
||||
if (create_desktop_shortcuts)
|
||||
{
|
||||
locations.insert(gui::utils::shortcut_location::desktop);
|
||||
}
|
||||
|
||||
if (create_app_shortcut)
|
||||
{
|
||||
locations.insert(gui::utils::shortcut_location::applications);
|
||||
}
|
||||
|
||||
if (!locations.empty())
|
||||
{
|
||||
std::vector<game_info> game_data_shortcuts;
|
||||
|
||||
for (const auto& [boot_path, title_id] : paths)
|
||||
{
|
||||
for (const game_info& gameinfo : m_game_list_frame->GetGameInfo())
|
||||
{
|
||||
if (gameinfo && gameinfo->info.serial == title_id.toStdString())
|
||||
{
|
||||
if (Emu.IsPathInsideDir(boot_path, gameinfo->info.path))
|
||||
{
|
||||
if (!locations.empty())
|
||||
{
|
||||
game_data_shortcuts.push_back(gameinfo);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!game_data_shortcuts.empty() && !locations.empty())
|
||||
{
|
||||
m_game_list_frame->CreateShortcuts(game_data_shortcuts, locations);
|
||||
}
|
||||
}
|
||||
CreateShortCuts(paths, create_desktop_shortcuts, create_app_shortcut);
|
||||
|
||||
if (precompile_caches)
|
||||
{
|
||||
|
|
@ -2485,6 +2356,55 @@ void main_window::ShowOptionalGamePreparations(const QString& title, const QStri
|
|||
dlg->open();
|
||||
}
|
||||
|
||||
void main_window::CreateShortCuts(const std::map<std::string, QString>& paths, bool create_desktop_shortcuts, bool create_app_shortcut)
|
||||
{
|
||||
if (paths.empty()) return;
|
||||
|
||||
std::set<gui::utils::shortcut_location> locations;
|
||||
|
||||
#ifdef _WIN32
|
||||
locations.insert(gui::utils::shortcut_location::rpcs3_shortcuts);
|
||||
#endif
|
||||
if (create_desktop_shortcuts)
|
||||
{
|
||||
locations.insert(gui::utils::shortcut_location::desktop);
|
||||
}
|
||||
|
||||
if (create_app_shortcut)
|
||||
{
|
||||
locations.insert(gui::utils::shortcut_location::applications);
|
||||
}
|
||||
|
||||
if (!locations.empty())
|
||||
{
|
||||
std::vector<game_info> game_data_shortcuts;
|
||||
|
||||
for (const auto& [boot_path, title_id] : paths)
|
||||
{
|
||||
for (const game_info& gameinfo : m_game_list_frame->GetGameInfo())
|
||||
{
|
||||
if (gameinfo && gameinfo->info.serial == title_id.toStdString())
|
||||
{
|
||||
if (Emu.IsPathInsideDir(boot_path, gameinfo->info.path))
|
||||
{
|
||||
if (!locations.empty())
|
||||
{
|
||||
game_data_shortcuts.push_back(gameinfo);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!game_data_shortcuts.empty() && !locations.empty())
|
||||
{
|
||||
m_game_list_frame->CreateShortcuts(game_data_shortcuts, locations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main_window::PrecompileCachesFromInstalledPackages(const std::map<std::string, QString>& bootable_paths)
|
||||
{
|
||||
std::vector<game_info> game_data;
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ private:
|
|||
static bool InstallFileInExData(const std::string& extension, const QString& path, const std::string& filename);
|
||||
|
||||
bool HandlePackageInstallation(QStringList file_paths, bool from_boot);
|
||||
void CreateShortCuts(const std::map<std::string, QString>& paths, bool create_desktop_shortcuts, bool create_app_shortcut);
|
||||
|
||||
void HandlePupInstallation(const QString& file_path, const QString& dir_path = "");
|
||||
void ExtractPup();
|
||||
|
|
|
|||
|
|
@ -7,12 +7,11 @@
|
|||
#include "Emu/system_utils.hpp"
|
||||
#include "Utilities/File.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QFileInfo>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
#include <QCheckBox>
|
||||
|
||||
enum Roles
|
||||
{
|
||||
|
|
@ -105,8 +104,6 @@ pkg_install_dialog::pkg_install_dialog(const QStringList& paths, game_compatibil
|
|||
item->setData(Roles::VersionRole, info.version);
|
||||
item->setData(Roles::DataSizeRole, static_cast<qulonglong>(info.data_size));
|
||||
item->setToolTip(tooltip);
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
item->setCheckState(Qt::Checked);
|
||||
}
|
||||
|
||||
m_dir_list->sortItems();
|
||||
|
|
@ -134,42 +131,79 @@ pkg_install_dialog::pkg_install_dialog(const QStringList& paths, game_compatibil
|
|||
}
|
||||
});
|
||||
|
||||
connect(m_dir_list, &QListWidget::itemChanged, this, [this, installation_info, buttons](QListWidgetItem*)
|
||||
QHBoxLayout* hbox = nullptr;
|
||||
if (m_dir_list->count() > 1)
|
||||
{
|
||||
UpdateInfo(installation_info, buttons);
|
||||
});
|
||||
for (int i = 0; i < m_dir_list->count(); i++)
|
||||
{
|
||||
if (QListWidgetItem* item = m_dir_list->item(i))
|
||||
{
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
item->setCheckState(Qt::Checked);
|
||||
}
|
||||
}
|
||||
|
||||
connect(m_dir_list, &QListWidget::itemChanged, this, [this, installation_info, buttons](QListWidgetItem*)
|
||||
{
|
||||
update_info(installation_info, buttons);
|
||||
});
|
||||
|
||||
QToolButton* move_up = new QToolButton;
|
||||
move_up->setArrowType(Qt::UpArrow);
|
||||
move_up->setToolTip(tr("Move selected item up"));
|
||||
connect(move_up, &QToolButton::clicked, this, [this]() { MoveItem(-1); });
|
||||
QToolButton* move_up = new QToolButton;
|
||||
move_up->setArrowType(Qt::UpArrow);
|
||||
move_up->setToolTip(tr("Move selected item up"));
|
||||
connect(move_up, &QToolButton::clicked, this, [this]() { move_item(-1); });
|
||||
|
||||
QToolButton* move_down = new QToolButton;
|
||||
move_down->setArrowType(Qt::DownArrow);
|
||||
move_down->setToolTip(tr("Move selected item down"));
|
||||
connect(move_down, &QToolButton::clicked, this, [this]() { MoveItem(1); });
|
||||
QToolButton* move_down = new QToolButton;
|
||||
move_down->setArrowType(Qt::DownArrow);
|
||||
move_down->setToolTip(tr("Move selected item down"));
|
||||
connect(move_down, &QToolButton::clicked, this, [this]() { move_item(1); });
|
||||
|
||||
QHBoxLayout* hbox = new QHBoxLayout;
|
||||
hbox->addStretch();
|
||||
hbox->addWidget(move_up);
|
||||
hbox->addWidget(move_down);
|
||||
hbox = new QHBoxLayout;
|
||||
hbox->addStretch();
|
||||
hbox->addWidget(move_up);
|
||||
hbox->addWidget(move_down);
|
||||
}
|
||||
|
||||
QLabel* description = new QLabel(tr("You are about to install multiple packages.\nReorder and/or exclude them if needed, then click \"Install\" to proceed."));
|
||||
QLabel* description = new QLabel(m_dir_list->count() == 1
|
||||
? tr("Do you want to install this package?")
|
||||
: tr("You are about to install multiple packages.\nReorder and/or exclude them if needed, then click \"Install\" to proceed.")
|
||||
);
|
||||
QLabel* label = new QLabel(tr("Would you like to precompile caches and install shortcuts to the installed software?"));
|
||||
|
||||
QCheckBox* precompile_check = new QCheckBox(tr("Precompile caches"));
|
||||
connect(precompile_check, &QCheckBox::checkStateChanged, this, [this](Qt::CheckState state){ m_precompile_caches = state != Qt::CheckState::Unchecked; });
|
||||
precompile_check->setChecked(true);
|
||||
|
||||
QCheckBox* desk_check = new QCheckBox(tr("Add desktop shortcut(s)"));
|
||||
connect(desk_check, &QCheckBox::checkStateChanged, this, [this](Qt::CheckState state){ m_create_desktop_shortcuts = state != Qt::CheckState::Unchecked; });
|
||||
|
||||
#ifdef _WIN32
|
||||
QCheckBox* quick_check = new QCheckBox(tr("Add Start menu shortcut(s)"));
|
||||
#elif defined(__APPLE__)
|
||||
QCheckBox* quick_check = new QCheckBox(tr("Add dock shortcut(s)"));
|
||||
#else
|
||||
QCheckBox* quick_check = new QCheckBox(tr("Add launcher shortcut(s)"));
|
||||
#endif
|
||||
connect(quick_check, &QCheckBox::checkStateChanged, this, [this](Qt::CheckState state){ m_create_app_shortcut = state != Qt::CheckState::Unchecked; });
|
||||
|
||||
QVBoxLayout* vbox = new QVBoxLayout;
|
||||
vbox->addWidget(description);
|
||||
vbox->addLayout(hbox);
|
||||
if (hbox) vbox->addLayout(hbox);
|
||||
vbox->addWidget(m_dir_list);
|
||||
vbox->addWidget(label);
|
||||
vbox->addWidget(precompile_check);
|
||||
vbox->addWidget(desk_check);
|
||||
vbox->addWidget(quick_check);
|
||||
vbox->addWidget(installation_info);
|
||||
vbox->addWidget(buttons);
|
||||
|
||||
setLayout(vbox);
|
||||
setWindowTitle(tr("Batch PKG Installation"));
|
||||
setWindowTitle(tr("PKG Installation"));
|
||||
setObjectName("pkg_install_dialog");
|
||||
UpdateInfo(installation_info, buttons); // Just to show and check available and required size
|
||||
update_info(installation_info, buttons); // Just to show and check available and required size
|
||||
}
|
||||
|
||||
void pkg_install_dialog::UpdateInfo(QLabel* installation_info, QDialogButtonBox* buttons) const
|
||||
void pkg_install_dialog::update_info(QLabel* installation_info, QDialogButtonBox* buttons) const
|
||||
{
|
||||
u64 data_size = 0;
|
||||
u64 free_space = 0;
|
||||
|
|
@ -182,7 +216,7 @@ void pkg_install_dialog::UpdateInfo(QLabel* installation_info, QDialogButtonBox*
|
|||
|
||||
for (int i = 0; i < m_dir_list->count(); i++)
|
||||
{
|
||||
if (m_dir_list->item(i)->checkState() == Qt::Checked)
|
||||
if (m_dir_list->count() == 1 || m_dir_list->item(i)->checkState() == Qt::Checked)
|
||||
{
|
||||
data_size += m_dir_list->item(i)->data(Roles::DataSizeRole).toULongLong();
|
||||
}
|
||||
|
|
@ -197,7 +231,7 @@ void pkg_install_dialog::UpdateInfo(QLabel* installation_info, QDialogButtonBox*
|
|||
buttons->button(QDialogButtonBox::Ok)->setEnabled(data_size && (data_size <= free_space));
|
||||
}
|
||||
|
||||
void pkg_install_dialog::MoveItem(int offset) const
|
||||
void pkg_install_dialog::move_item(int offset) const
|
||||
{
|
||||
const int src_index = m_dir_list->currentRow();
|
||||
const int dest_index = src_index + offset;
|
||||
|
|
@ -211,14 +245,14 @@ void pkg_install_dialog::MoveItem(int offset) const
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<compat::package_info> pkg_install_dialog::GetPathsToInstall() const
|
||||
std::vector<compat::package_info> pkg_install_dialog::get_paths_to_install() const
|
||||
{
|
||||
std::vector<compat::package_info> result;
|
||||
|
||||
for (int i = 0; i < m_dir_list->count(); i++)
|
||||
{
|
||||
const QListWidgetItem* item = m_dir_list->item(i);
|
||||
if (item && item->checkState() == Qt::Checked)
|
||||
if (item && (m_dir_list->count() == 1 || item->checkState() == Qt::Checked))
|
||||
{
|
||||
compat::package_info info;
|
||||
info.path = item->data(Roles::FullPathRole).toString();
|
||||
|
|
|
|||
|
|
@ -18,11 +18,17 @@ class pkg_install_dialog : public QDialog
|
|||
|
||||
public:
|
||||
explicit pkg_install_dialog(const QStringList& paths, game_compatibility* compat, QWidget* parent = nullptr);
|
||||
std::vector<compat::package_info> GetPathsToInstall() const;
|
||||
std::vector<compat::package_info> get_paths_to_install() const;
|
||||
bool precompile_caches() const { return m_precompile_caches; }
|
||||
bool create_desktop_shortcuts() const { return m_create_desktop_shortcuts; }
|
||||
bool create_app_shortcut() const { return m_create_app_shortcut; }
|
||||
|
||||
private:
|
||||
void UpdateInfo(QLabel* installation_info, QDialogButtonBox* buttons) const;
|
||||
void MoveItem(int offset) const;
|
||||
void update_info(QLabel* installation_info, QDialogButtonBox* buttons) const;
|
||||
void move_item(int offset) const;
|
||||
|
||||
QListWidget* m_dir_list;
|
||||
bool m_precompile_caches = false;
|
||||
bool m_create_desktop_shortcuts = false;
|
||||
bool m_create_app_shortcut = false;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue