From e0134678cd4a730c9bbe3797fba782fb5cfab75e Mon Sep 17 00:00:00 2001 From: crueter Date: Thu, 5 Feb 2026 14:11:45 -0500 Subject: [PATCH] fix mod naming and live update Signed-off-by: crueter --- src/frontend_common/mod_manager.cpp | 6 +-- src/frontend_common/mod_manager.h | 8 +++- src/qt_common/util/mod.cpp | 29 +++++++----- src/qt_common/util/mod.h | 6 ++- .../configure_per_game_addons.cpp | 47 +++++++++++++++---- 5 files changed, 69 insertions(+), 27 deletions(-) diff --git a/src/frontend_common/mod_manager.cpp b/src/frontend_common/mod_manager.cpp index 316d10a0b4..cbe4869b16 100644 --- a/src/frontend_common/mod_manager.cpp +++ b/src/frontend_common/mod_manager.cpp @@ -38,7 +38,7 @@ std::optional GetModFolder(const std::string& root) { return std::nullopt; } -bool InstallMod(const std::filesystem::path& path, const u64 program_id, const bool copy) { +ModInstallResult InstallMod(const std::filesystem::path& path, const u64 program_id, const bool copy) { const auto program_id_string = fmt::format("{:016X}", program_id); const auto mod_name = path.filename(); const auto mod_dir = @@ -54,12 +54,12 @@ bool InstallMod(const std::filesystem::path& path, const u64 program_id, const b std::filesystem::remove_all(path); } catch (std::exception& e) { LOG_ERROR(Frontend, "Mod install failed with message {}", e.what()); - return false; + return Failed; } LOG_INFO(Frontend, "Copied mod from {} to {}", path.string(), mod_dir.string()); - return true; + return Success; } } // namespace FrontendCommon diff --git a/src/frontend_common/mod_manager.h b/src/frontend_common/mod_manager.h index f9b033b936..e516a02a2e 100644 --- a/src/frontend_common/mod_manager.h +++ b/src/frontend_common/mod_manager.h @@ -6,7 +6,13 @@ namespace FrontendCommon { +enum ModInstallResult { + Cancelled, + Failed, + Success, +}; + std::optional GetModFolder(const std::string& root); -bool InstallMod(const std::filesystem::path &path, const u64 program_id, const bool copy = true); +ModInstallResult InstallMod(const std::filesystem::path &path, const u64 program_id, const bool copy = true); } diff --git a/src/qt_common/util/mod.cpp b/src/qt_common/util/mod.cpp index 18c30c01fd..e1d6d1887a 100644 --- a/src/qt_common/util/mod.cpp +++ b/src/qt_common/util/mod.cpp @@ -1,6 +1,5 @@ #include #include -#include "frontend_common/mod_manager.h" #include "mod.h" #include "qt_common/abstract/frontend.h" @@ -22,8 +21,6 @@ QString GetModFolder(const QString& root, const QString& fallbackName) { QString name = QtCommon::Frontend::GetTextInput( tr("Mod Name"), tr("What should this mod be called?"), default_name); - qDebug() << "Naming mod:" << name; - // if std_path is empty, frontend_common could not determine mod type and/or name. // so we have to prompt the user and set up the structure ourselves if (!std_path) { @@ -61,8 +58,10 @@ QString GetModFolder(const QString& root, const QString& fallbackName) { const auto mod_dir = fs::temp_directory_path() / "eden" / "mod" / name.toStdString(); const auto tmp = mod_dir / to_make; fs::remove_all(mod_dir); - if (!fs::create_directories(tmp)) + if (!fs::create_directories(tmp)) { + LOG_ERROR(Frontend, "Failed to create temporary directory {}", tmp.string()); return QString(); + } std_path = mod_dir; @@ -81,24 +80,28 @@ QString GetModFolder(const QString& root, const QString& fallbackName) { std_path = new_path; } - qDebug() << "Mod path" << std_path->string(); - return QString::fromStdString(std_path->string()); } -bool InstallMod(const QString& path, const QString& fallbackName, const u64 program_id, +FrontendCommon::ModInstallResult InstallMod(const QString& path, const QString& fallbackName, const u64 program_id, const bool copy) { const auto target = GetModFolder(path, fallbackName); + if (target.isEmpty()) { + return FrontendCommon::Cancelled; + } + return FrontendCommon::InstallMod(target.toStdString(), program_id, copy); } -bool InstallModFromZip(const QString& path, const u64 program_id) { +FrontendCommon::ModInstallResult InstallModFromZip(const QString& path, const u64 program_id) { namespace fs = std::filesystem; fs::path tmp{fs::temp_directory_path() / "eden" / "unzip_mod"}; fs::remove_all(tmp); - if (!fs::create_directories(tmp)) - return false; + if (!fs::create_directories(tmp)) { + LOG_ERROR(Frontend, "Failed to create temporary directory {}", tmp.string()); + return FrontendCommon::Failed; + } QString qCacheDir = QString::fromStdString(tmp.string()); @@ -106,8 +109,10 @@ bool InstallModFromZip(const QString& path, const u64 program_id) { // TODO(crueter): use QtCompress QStringList result = JlCompress::extractDir(&zip, qCacheDir); - if (result.isEmpty()) - return false; + if (result.isEmpty()) { + LOG_ERROR(Frontend, "Zip file {} is empty", path.toStdString()); + return FrontendCommon::Failed; + } const auto fallback = fs::path{path.toStdString()}.stem(); diff --git a/src/qt_common/util/mod.h b/src/qt_common/util/mod.h index 8039331417..02464412fa 100644 --- a/src/qt_common/util/mod.h +++ b/src/qt_common/util/mod.h @@ -2,13 +2,15 @@ #include #include "common/common_types.h" +#include "frontend_common/mod_manager.h" namespace QtCommon::Mod { QString GetModFolder(const QString &root, const QString &fallbackName); -bool InstallMod(const QString &path, const QString &fallbackName, const u64 program_id, const bool copy = true); +FrontendCommon::ModInstallResult InstallMod(const QString& path, const QString& fallbackName, + const u64 program_id, const bool copy = true); -bool InstallModFromZip(const QString &path, const u64 program_id); +FrontendCommon::ModInstallResult InstallModFromZip(const QString &path, const u64 program_id); } diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index 68e5b4e7f2..98dc6835d1 100644 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp @@ -14,18 +14,20 @@ #include #include #include +#include #include "common/fs/fs.h" #include "common/fs/path_util.h" #include "core/core.h" #include "core/file_sys/patch_manager.h" #include "core/loader/loader.h" +#include "frontend_common/mod_manager.h" #include "qt_common/abstract/frontend.h" +#include "qt_common/config/uisettings.h" #include "qt_common/util/mod.h" #include "ui_configure_per_game_addons.h" #include "yuzu/configuration/configure_input.h" #include "yuzu/configuration/configure_per_game_addons.h" -#include "qt_common/config/uisettings.h" ConfigurePerGameAddons::ConfigurePerGameAddons(Core::System& system_, QWidget* parent) : QWidget(parent), ui{std::make_unique()}, system{system_} { @@ -104,31 +106,58 @@ void ConfigurePerGameAddons::SetTitleId(u64 id) { } void ConfigurePerGameAddons::InstallModFolder() { - const auto path = QtCommon::Frontend::GetExistingDirectory(tr("Mod Folder")); + const auto path = QtCommon::Frontend::GetExistingDirectory( + tr("Mod Folder"), QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); if (path.isEmpty()) { return; } // TODO: Pending refresh game list - if (QtCommon::Mod::InstallMod(path, {}, title_id)) { + auto ret = QtCommon::Mod::InstallMod(path, {}, title_id); + switch (ret) { + case FrontendCommon::Success: QtCommon::Frontend::Information(tr("Mod Installed"), tr("Mod was successfully installed.")); + item_model->removeRows(0, item_model->rowCount()); + list_items.clear(); LoadConfiguration(); - } else { - QtCommon::Frontend::Critical(tr("Mod Install Failed"), tr("Mod install was unsuccessful. Check the log for details.")); + break; + case FrontendCommon::Failed: + QtCommon::Frontend::Critical( + tr("Mod Install Failed"), + tr("Mod install was unsuccessful. Check the log for details.")); + break; + case FrontendCommon::Cancelled: + default: + break; } } void ConfigurePerGameAddons::InstallModZip() { - const auto path = QtCommon::Frontend::GetOpenFileName(tr("Zipped Mod Location"), {}, tr("Zipped Archives (*.zip)")); + const auto path = QtCommon::Frontend::GetOpenFileName( + tr("Zipped Mod Location"), + QStandardPaths::writableLocation(QStandardPaths::DownloadLocation), + tr("Zipped Archives (*.zip)")); if (path.isEmpty()) { return; } - if (QtCommon::Mod::InstallModFromZip(path, title_id)) { + auto ret = QtCommon::Mod::InstallModFromZip(path, title_id); + + switch (ret) { + case FrontendCommon::Success: QtCommon::Frontend::Information(tr("Mod Installed"), tr("Mod was successfully installed.")); + item_model->removeRows(0, item_model->rowCount()); + list_items.clear(); LoadConfiguration(); - } else { - QtCommon::Frontend::Critical(tr("Mod Install Failed"), tr("Mod install was unsuccessful. Check the log for details.")); + break; + case FrontendCommon::Failed: + QtCommon::Frontend::Critical( + tr("Mod Install Failed"), + tr("Mod install was unsuccessful. Check the log for details.")); + break; + case FrontendCommon::Cancelled: + default: + break; } }