gui/archive install dialog: refactor dialog.

- allow can using folder for install some archive in same time.
This commit is contained in:
Zangetsu38 2021-05-27 13:47:14 +02:00 committed by Nicolas Jallamion
parent 8b0400a077
commit 3373b19dde
7 changed files with 166 additions and 173 deletions

View File

@ -185,9 +185,6 @@ struct GuiState {
std::map<std::string, User> users;
std::map<std::string, ImGui_Texture> users_avatar;
std::string app_ver;
bool content_reinstall_confirm = false;
MemoryEditor memory_editor;
MemoryEditor gxp_shader_editor;
size_t memory_editor_start = 0;

View File

@ -28,169 +28,182 @@
namespace gui {
struct ContentInfo {
std::string title;
std::string title_id;
std::string category;
std::string content_id;
fs::path path;
};
static bool delete_archive_file;
static std::string state, type, title;
static std::vector<ContentInfo> content_installed;
static std::vector<fs::path> content_failed;
static nfdchar_t *archive_path;
static float global_progress = 0;
static float content_count = 0;
static float number_of_content(const fs::path &path) {
float count = 0;
for (const auto &content : fs::directory_iterator(path)) {
if ((content.path().extension() == ".zip") || (content.path().extension() == ".vpk"))
++count;
}
return count;
}
void draw_archive_install_dialog(GuiState &gui, HostState &host) {
const auto display_size = ImGui::GetIO().DisplaySize;
const auto RES_SCALE = ImVec2(display_size.x / host.res_width_dpi_scale, display_size.y / host.dpi_scale);
const auto SCALE = ImVec2(RES_SCALE.x * host.dpi_scale, RES_SCALE.x * host.dpi_scale);
nfdresult_t result = NFD_CANCEL;
static std::mutex install_mutex;
static bool draw_file_dialog = true;
static bool content_install_confirm = false;
static bool finished_installing = false;
static bool failed_installation = false;
const auto RES_SCALE = ImVec2(display_size.x / host.res_width_dpi_scale, display_size.y / host.res_height_dpi_scale);
const auto SCALE = ImVec2(RES_SCALE.x * host.dpi_scale, RES_SCALE.y * host.dpi_scale);
const auto BUTTON_SIZE = ImVec2(160.f * SCALE.x, 45.f * SCALE.y);
const auto WINDOW_SIZE = ImVec2(616.f * SCALE.x, 284.f * SCALE.y);
static std::atomic<float> progress(0);
static bool reinstalling = false;
static std::mutex install_mutex;
static const auto progress_callback = [&](float updated_progress) {
progress = updated_progress;
};
std::lock_guard<std::mutex> lock(install_mutex);
if (draw_file_dialog) {
result = NFD_OpenDialog("vpk,zip", nullptr, &archive_path);
draw_file_dialog = false;
finished_installing = false;
if (result == NFD_OKAY) {
auto indicator = gui.lang.indicator;
ImGui::SetNextWindowPos(ImVec2(0.f, 0.f), ImGuiCond_Always);
ImGui::SetNextWindowSize(display_size);
ImGui::Begin("archive_install", &gui.file_menu.archive_install_dialog, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings);
ImGui::SetNextWindowPos(ImVec2(display_size.x / 2.f, display_size.y / 2.f), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
ImGui::SetWindowFontScale(RES_SCALE.x);
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 10.f * SCALE.x);
ImGui::BeginChild("##archive_Install_child", WINDOW_SIZE, true, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings);
const auto POS_BUTTON = (ImGui::GetWindowWidth() / 2.f) - (BUTTON_SIZE.x / 2.f) + (10.f * SCALE.x);
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.f) - (ImGui::CalcTextSize(title.c_str()).x / 2.f));
ImGui::TextColored(GUI_COLOR_TEXT_MENUBAR, "%s", title.c_str());
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
if (type.empty()) {
ImGui::SetCursorPosX(POS_BUTTON);
title = "Select install type";
if (ImGui::Button("Select File", BUTTON_SIZE))
type = "file";
ImGui::Spacing();
ImGui::SetCursorPosX(POS_BUTTON);
if (ImGui::Button("Select Directory", BUTTON_SIZE))
type = "directory";
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
ImGui::SetCursorPosX(POS_BUTTON);
if (ImGui::Button("Cancel", BUTTON_SIZE))
gui.file_menu.archive_install_dialog = false;
} else {
if (state.empty()) {
nfdresult_t result = NFD_CANCEL;
if (type == "file")
result = NFD_OpenDialog("zip,vpk", nullptr, &archive_path);
else
result = NFD_PickFolder(nullptr, &archive_path);
if (result == NFD_OKAY) {
state = "install";
} else
type.clear();
} else if (state == "install") {
std::thread installation([&host, &gui]() {
if (install_archive(host, &gui, fs::path(string_utils::utf_to_wide(archive_path)), progress_callback)) {
std::lock_guard<std::mutex> lock(install_mutex);
content_install_confirm = true;
} else if (!gui.content_reinstall_confirm) {
std::lock_guard<std::mutex> lock(install_mutex);
failed_installation = true;
}
{
std::lock_guard<std::mutex> lock(install_mutex);
finished_installing = true;
global_progress = 1;
const auto content_path = fs::path(string_utils::utf_to_wide(archive_path));
if (type == "directory") {
content_count = number_of_content(content_path);
for (const auto &content : fs::directory_iterator(content_path)) {
if ((content.path().extension() == std::string(".zip")) || (content.path().extension() == std::string(".vpk"))) {
if (install_archive(host, &gui, content, progress_callback)) {
std::lock_guard<std::mutex> lock(install_mutex);
content_installed.push_back({ host.app_title, host.app_title_id, host.app_category, host.app_content_id, content });
} else
content_failed.push_back(content);
++global_progress;
progress = 0;
}
}
} else {
content_count = 1.f;
if (install_archive(host, &gui, content_path, progress_callback)) {
std::lock_guard<std::mutex> lock(install_mutex);
content_installed.push_back({ host.app_title, host.app_title_id, host.app_category, host.app_content_id, content_path });
} else
content_failed.push_back(content_path);
progress = 0;
}
content_count = 0;
global_progress = 0;
state = "finished";
});
installation.detach();
} else {
gui.file_menu.archive_install_dialog = false;
draw_file_dialog = true;
}
}
if (failed_installation)
ImGui::OpenPopup("Content installation failed");
if (reinstalling) {
finished_installing = false;
std::thread reinstallation([&host, &gui]() {
if (install_archive(host, &gui, fs::path(string_utils::utf_to_wide(archive_path)), progress_callback)) {
std::lock_guard<std::mutex> lock(install_mutex);
content_install_confirm = true;
} else if (!gui.content_reinstall_confirm) {
ImGui::OpenPopup("Content installation failed");
}
{
std::lock_guard<std::mutex> lock(install_mutex);
finished_installing = true;
gui.content_reinstall_confirm = false;
}
});
reinstalling = false;
reinstallation.detach();
}
if (!finished_installing) {
ImGui::OpenPopup("Content Installation");
if (ImGui::BeginPopupModal("Content Installation", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextColored(GUI_COLOR_TEXT, "Installation in progress, please wait...");
const float PROGRESS_BAR_WIDTH = 150.f * SCALE.x;
ImGui::SetCursorPosX((ImGui::GetWindowContentRegionWidth() / 2) - (PROGRESS_BAR_WIDTH / 2) + (10.f * SCALE.x));
state = "installing";
} else if (state == "installing") {
title = "Installing";
ImGui::SetCursorPos(ImVec2(178.f * host.dpi_scale, ImGui::GetCursorPosY() + (20.f * host.dpi_scale)));
ImGui::TextColored(GUI_COLOR_TEXT, "%s", host.app_title.c_str());
const auto installing = !indicator["installing"].empty() ? indicator["installing"].c_str() : "Installing...";
ImGui::SetCursorPos(ImVec2(178.f * host.dpi_scale, ImGui::GetCursorPosY() + (20.f * host.dpi_scale)));
ImGui::TextColored(GUI_COLOR_TEXT, "%s", installing);
const float PROGRESS_BAR_WIDTH = 502.f * host.dpi_scale;
const auto PROGRESS_BAR_POS = (ImGui::GetWindowWidth() / 2) - (PROGRESS_BAR_WIDTH / 2.f);
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, GUI_PROGRESS_BAR);
ImGui::ProgressBar(progress / 100.f, ImVec2(PROGRESS_BAR_WIDTH, 20.f * SCALE.y), nullptr);
ImGui::SetCursorPos(ImVec2(PROGRESS_BAR_POS, ImGui::GetCursorPosY() + (14.f * host.dpi_scale)));
ImGui::ProgressBar(global_progress / content_count, ImVec2(PROGRESS_BAR_WIDTH, 15.f * host.dpi_scale), "");
const auto global_progress_str = fmt::format("{}/{}", global_progress, content_count);
ImGui::SetCursorPos(ImVec2((ImGui::GetWindowWidth() / 2.f) - (ImGui::CalcTextSize(global_progress_str.c_str()).x / 2.f), ImGui::GetCursorPosY() + (6.f * host.dpi_scale)));
ImGui::TextColored(GUI_COLOR_TEXT, "%s", global_progress_str.c_str());
ImGui::SetCursorPos(ImVec2(PROGRESS_BAR_POS, ImGui::GetCursorPosY() + (14.f * host.dpi_scale)));
ImGui::ProgressBar(progress / 100.f, ImVec2(PROGRESS_BAR_WIDTH, 15.f * host.dpi_scale), "");
const auto progress_str = std::to_string(uint32_t(progress)).append("%");
ImGui::SetCursorPos(ImVec2((ImGui::GetWindowWidth() / 2.f) - (ImGui::CalcTextSize(progress_str.c_str()).x / 2.f), ImGui::GetCursorPosY() + (6.f * host.dpi_scale)));
ImGui::TextColored(GUI_COLOR_TEXT, "%s", progress_str.c_str());
ImGui::PopStyleColor();
} else if (state == "finished") {
title = !indicator["install_complete"].empty() ? indicator["install_complete"] : "Installation complete.";
ImGui::SetNextWindowPos(ImVec2(ImGui::GetWindowPos().x + (5.f * SCALE.x), ImGui::GetWindowPos().y + BUTTON_SIZE.y));
ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.f);
ImGui::BeginChild("##content_installed_list", ImVec2(WINDOW_SIZE.x - (10.f * SCALE.x), WINDOW_SIZE.y - (BUTTON_SIZE.y * 2.f) - (25 * SCALE.y)), false, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings);
if (!content_installed.empty()) {
ImGui::TextColored(GUI_COLOR_TEXT_TITLE, "%lu content have success installed:", content_installed.size());
for (const auto &content : content_installed)
ImGui::TextColored(GUI_COLOR_TEXT, "%s [%s]", content.title_id.c_str(), content.title.c_str());
}
if (!content_failed.empty()) {
ImGui::TextColored(GUI_COLOR_TEXT_TITLE, "%lu content have failed install:", content_failed.size());
for (const auto &content : content_failed)
ImGui::TextColored(GUI_COLOR_TEXT, "%s", content.string().c_str());
}
ImGui::EndChild();
ImGui::PopStyleVar();
ImGui::Separator();
ImGui::Spacing();
ImGui::Checkbox("Delete archive?", &delete_archive_file);
ImGui::SetCursorPos(ImVec2(POS_BUTTON, ImGui::GetWindowSize().y - BUTTON_SIZE.y - (12.f * SCALE.y)));
if (ImGui::Button("OK", BUTTON_SIZE)) {
for (const auto &content : content_installed) {
host.app_category = content.category;
host.app_title_id = content.title_id;
host.app_content_id = content.content_id;
update_notice_info(gui, host, "content");
if (content.category == "gd")
init_user_app(gui, host, content.title_id);
if (delete_archive_file)
fs::remove(content.path);
}
archive_path = nullptr;
gui.file_menu.archive_install_dialog = false;
delete_archive_file = false;
content_installed.clear();
content_failed.clear();
type.clear();
state.clear();
}
}
ImGui::EndPopup();
}
static const auto BUTTON_SIZE = ImVec2(60.f * SCALE.x, 45.f * SCALE.y);
if (gui.content_reinstall_confirm && finished_installing)
ImGui::OpenPopup("Content reinstallation");
ImGui::PushStyleColor(ImGuiCol_Text, GUI_COLOR_TEXT_MENUBAR);
if (ImGui::BeginPopupModal("Content reinstallation", &gui.content_reinstall_confirm, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::PopStyleColor();
ImGui::TextColored(GUI_COLOR_TEXT, "This content is already installed:\n%s [%s].", host.app_title_id.c_str(), host.app_title.c_str());
if (!gui.app_ver.empty() && gui.app_ver != host.app_version)
ImGui::TextColored(GUI_COLOR_TEXT, "Update content version from: %s to: %s.", gui.app_ver.c_str(), host.app_version.c_str());
ImGui::Spacing();
ImGui::TextColored(GUI_COLOR_TEXT, "Do you want to reinstall it?");
ImGui::Separator();
ImGui::Spacing();
ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 2 - 65 * host.dpi_scale);
if (ImGui::Button("Yes", BUTTON_SIZE)) {
reinstalling = true;
}
ImGui::SameLine();
if (ImGui::Button("No", BUTTON_SIZE)) {
archive_path = nullptr;
gui.content_reinstall_confirm = false;
gui.file_menu.archive_install_dialog = false;
draw_file_dialog = true;
}
ImGui::EndPopup();
} else
ImGui::PopStyleColor();
if (content_install_confirm)
ImGui::OpenPopup("Content installation success");
ImGui::PushStyleColor(ImGuiCol_Text, GUI_COLOR_TEXT_MENUBAR);
if (ImGui::BeginPopupModal("Content installation success", &content_install_confirm, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::PopStyleColor();
ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 5);
ImGui::TextColored(GUI_COLOR_TEXT, "Successfully installed content.\n%s [%s] %s", host.app_title_id.c_str(), host.app_title.c_str(), host.app_version.c_str());
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
ImGui::Checkbox("Delete the archive for the content installed?", &delete_archive_file);
ImGui::Spacing();
ImGui::SetCursorPosX((ImGui::GetWindowWidth() / 2.f) - (30 * SCALE.x));
if (ImGui::Button("OK", BUTTON_SIZE)) {
if (delete_archive_file) {
fs::remove(fs::path(string_utils::utf_to_wide(archive_path)));
delete_archive_file = false;
}
content_install_confirm = false;
draw_file_dialog = true;
archive_path = nullptr;
if (host.app_category == "gd")
init_user_app(gui, host, host.app_title_id);
update_notice_info(gui, host, "content");
gui.file_menu.archive_install_dialog = false;
}
ImGui::EndPopup();
} else
ImGui::PopStyleColor();
ImGui::PushStyleColor(ImGuiCol_Text, GUI_COLOR_TEXT_MENUBAR);
if (ImGui::BeginPopupModal("Content installation failed", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::PopStyleColor();
ImGui::TextColored(GUI_COLOR_TEXT, "Installation failed, please check the log for more information.");
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
ImGui::Checkbox("Delete vpk/zip file of the content that failed to install?", &delete_archive_file);
ImGui::Spacing();
ImGui::SetCursorPosX((ImGui::GetWindowWidth() / 2.f) - (30 * SCALE.x));
if (ImGui::Button("OK", BUTTON_SIZE)) {
if (delete_archive_file) {
fs::remove(fs::path(string_utils::utf_to_wide(archive_path)));
delete_archive_file = false;
}
draw_file_dialog = true;
archive_path = nullptr;
gui.file_menu.archive_install_dialog = false;
}
ImGui::EndPopup();
} else
ImGui::PopStyleColor();
ImGui::EndChild();
ImGui::PopStyleVar();
ImGui::End();
}
} // namespace gui

View File

@ -523,6 +523,8 @@ void draw_live_area(GuiState &gui, HostState &host) {
if (gui.live_area.manual)
draw_manual(gui, host);
if (gui.file_menu.archive_install_dialog)
draw_archive_install_dialog(gui, host);
if (gui.file_menu.pkg_install_dialog)
draw_pkg_install_dialog(gui, host);
@ -560,8 +562,6 @@ void draw_ui(GuiState &gui, HostState &host) {
if (gui.file_menu.firmware_install_dialog)
draw_firmware_install_dialog(gui, host);
if (gui.file_menu.archive_install_dialog)
draw_archive_install_dialog(gui, host);
if (gui.file_menu.license_install_dialog)
draw_license_install_dialog(gui, host);
if (gui.debug_menu.threads_dialog)

View File

@ -111,7 +111,7 @@ static bool set_notice_info(GuiState &gui, HostState &host, const NoticeList &in
msg = !indicator["install_complete"].empty() ? indicator["install_complete"] : "Installation complete.";
}
vfs::FileBuffer params;
if (vfs::read_file(VitaIoDevice::ux0, params, host.pref_path, content_path.string() + "/sce_sys/param.sfo")) {
if (vfs::read_file(VitaIoDevice::ux0, params, host.pref_path, content_path / "sce_sys/param.sfo")) {
SfoFile sfo_handle;
sfo::load(sfo_handle, params);
if (!sfo::get_data_by_key(name, sfo_handle, fmt::format("TITLE_{:0>2d}", host.cfg.sys_lang)))

View File

@ -120,7 +120,7 @@ void draw_pkg_install_dialog(GuiState &gui, HostState &host) {
if (ImGui::Button("OK", BUTTON_SIZE) && !zRIF.empty())
state = "install";
} else if (state == "install") {
std::thread installation(([&host]() {
std::thread installation([&host]() {
if (install_pkg(std::string(pkg_path), host, zRIF, progress_callback)) {
std::lock_guard<std::mutex> lock(install_mutex);
state = "success";
@ -128,7 +128,7 @@ void draw_pkg_install_dialog(GuiState &gui, HostState &host) {
state = "fail";
}
zRIF.clear();
}));
});
installation.detach();
state = "installing";
} else if (state == "success") {

View File

@ -64,7 +64,7 @@ static bool open_license(HostState &host, const fs::path &license_path) {
bool copy_license(HostState &host, const fs::path &license_path) {
if (open_license(host, license_path)) {
host.license_content_id = license_buf.content_id;
host.license_title_id = std::string(host.license_content_id).substr(7, 9);
host.license_title_id = host.license_content_id.substr(7, 9);
const auto dst_path{ fs::path(host.pref_path) / "ux0/license" / host.license_title_id };
if (!fs::exists(dst_path))
fs::create_directories(dst_path);

View File

@ -115,18 +115,9 @@ bool install_archive(HostState &host, GuiState *gui, const fs::path &archive_pat
theme = true;
//This was here before to check if the game files were in the zip root, since this commit
// allows support for the game to be inside folders and install it anyways
//i thought we should comment this check
//edited to be compatible right away if someone wants to uncomment it
//if (m_filename.find(sfo_path.string()) != std::string::npos)
//break;
if (m_filename.find("eboot.bin") != std::string::npos) {
extra_path = m_filename.replace(m_filename.find("eboot.bin"), strlen("eboot.bin"), "");
continue;
}
// allows support for the content to be inside folders and install it anyways
if ((m_filename.find(sfo_path.string()) != std::string::npos) && (m_filename != sfo_path.string()))
extra_path = m_filename.erase(m_filename.find(sfo_path.string()));
}
vfs::FileBuffer params;
@ -185,14 +176,6 @@ bool install_archive(HostState &host, GuiState *gui, const fs::path &archive_pat
} else if (status == gui::UNK_STATE) {
exit(0);
}
} else if (gui->file_menu.archive_install_dialog && !gui->content_reinstall_confirm) {
vfs::FileBuffer params;
vfs::read_app_file(params, host.pref_path, host.app_title_id, sfo_path);
sfo::load(host.sfo_handle, params);
sfo::get_data_by_key(gui->app_ver, host.sfo_handle, "APP_VER");
gui->content_reinstall_confirm = true;
fclose(vpk_fp);
return false;
}
}