From 3062a35eb1297067446156c43e9d0df2f684edff Mon Sep 17 00:00:00 2001 From: boludoz Date: Sun, 15 Oct 2023 02:02:22 -0300 Subject: Improved shortcut: add games in applist for Windows, question for start game at fullscreen & better unicode support for some Windows path funcs. --- src/yuzu/game_list.cpp | 4 - src/yuzu/main.cpp | 490 ++++++++++++++++++++++++++++++------------------- src/yuzu/main.h | 22 ++- src/yuzu/util/util.cpp | 17 +- src/yuzu/util/util.h | 14 +- 5 files changed, 347 insertions(+), 200 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 2bb1a0239..fbe099661 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -566,10 +566,8 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry")); QMenu* shortcut_menu = context_menu.addMenu(tr("Create Shortcut")); QAction* create_desktop_shortcut = shortcut_menu->addAction(tr("Add to Desktop")); -#ifndef WIN32 QAction* create_applications_menu_shortcut = shortcut_menu->addAction(tr("Add to Applications Menu")); -#endif context_menu.addSeparator(); QAction* properties = context_menu.addAction(tr("Properties")); @@ -647,11 +645,9 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri connect(create_desktop_shortcut, &QAction::triggered, [this, program_id, path]() { emit CreateShortcut(program_id, path, GameListShortcutTarget::Desktop); }); -#ifndef WIN32 connect(create_applications_menu_shortcut, &QAction::triggered, [this, program_id, path]() { emit CreateShortcut(program_id, path, GameListShortcutTarget::Applications); }); -#endif connect(properties, &QAction::triggered, [this, path]() { emit OpenPerGameGeneralRequested(path); }); }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 1431cf2fe..e4dc717ed 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2840,170 +2840,350 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id, QDesktopServices::openUrl(QUrl(QStringLiteral("https://yuzu-emu.org/game/") + directory)); } -void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path, - GameListShortcutTarget target) { - // Get path to yuzu executable - const QStringList args = QApplication::arguments(); - std::filesystem::path yuzu_command = args[0].toStdString(); +bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, + const std::string& comment, + const std::filesystem::path& icon_path, + const std::filesystem::path& command, + const std::string& arguments, const std::string& categories, + const std::string& keywords, const std::string& name) { - // If relative path, make it an absolute path - if (yuzu_command.c_str()[0] == '.') { - yuzu_command = Common::FS::GetCurrentDir() / yuzu_command; - } + bool shortcut_succeeded = false; -#if defined(__linux__) - // Warn once if we are making a shortcut to a volatile AppImage - const std::string appimage_ending = - std::string(Common::g_scm_rev).substr(0, 9).append(".AppImage"); - if (yuzu_command.string().ends_with(appimage_ending) && - !UISettings::values.shortcut_already_warned) { - if (QMessageBox::warning(this, tr("Create Shortcut"), - tr("This will create a shortcut to the current AppImage. This may " - "not work well if you update. Continue?"), - QMessageBox::StandardButton::Ok | - QMessageBox::StandardButton::Cancel) == - QMessageBox::StandardButton::Cancel) { - return; + // Replace characters that are illegal in Windows filenames + std::filesystem::path shortcut_path_full = + shortcut_path / Common::FS::UTF8FilenameSantizer(name); + +#if defined(__linux__) || defined(__FreeBSD__) + shortcut_path_full += ".desktop"; +#elif defined(_WIN32) + shortcut_path_full += ".lnk"; +#endif + + LOG_INFO(Common, "[GMainWindow::CreateShortcutLink] Create shortcut path: {}", + shortcut_path_full.string()); + +#if defined(__linux__) || defined(__FreeBSD__) + // This desktop file template was writing referencing + // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html + try { + + // Plus 'Type' is required + if (name.empty()) { + LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Name is empty"); + shortcut_succeeded = false; + return shortcut_succeeded; } - UISettings::values.shortcut_already_warned = true; - } -#endif // __linux__ + std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); - std::filesystem::path target_directory{}; + if (shortcut_stream.is_open()) { - switch (target) { - case GameListShortcutTarget::Desktop: { - const QString desktop_path = - QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); - target_directory = desktop_path.toUtf8().toStdString(); - break; - } - case GameListShortcutTarget::Applications: { - const QString applications_path = - QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation); - if (applications_path.isEmpty()) { - const char* home = std::getenv("HOME"); - if (home != nullptr) { - target_directory = std::filesystem::path(home) / ".local/share/applications"; + fmt::print(shortcut_stream, "[Desktop Entry]\n"); + fmt::print(shortcut_stream, "Type=Application\n"); + fmt::print(shortcut_stream, "Version=1.0\n"); + fmt::print(shortcut_stream, "Name={}\n", name); + + if (!comment.empty()) { + fmt::print(shortcut_stream, "Comment={}\n", comment); } + + if (std::filesystem::is_regular_file(icon_path)) { + fmt::print(shortcut_stream, "Icon={}\n", icon_path.string()); + } + + fmt::print(shortcut_stream, "TryExec={}\n", command.string()); + fmt::print(shortcut_stream, "Exec={}", command.string()); + + if (!arguments.empty()) { + fmt::print(shortcut_stream, " {}", arguments); + } + + fmt::print(shortcut_stream, "\n"); + + if (!categories.empty()) { + fmt::print(shortcut_stream, "Categories={}\n", categories); + } + + if (!keywords.empty()) { + fmt::print(shortcut_stream, "Keywords={}\n", keywords); + } + + shortcut_stream.close(); + return true; + } else { - target_directory = applications_path.toUtf8().toStdString(); + LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create shortcut"); + return false; } - break; + + shortcut_stream.close(); + } catch (const std::exception& e) { + LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create shortcut: {}", + e.what()); } - default: - return; +#elif defined(_WIN32) + // Initialize COM + auto hr = CoInitialize(NULL); + if (FAILED(hr)) { + return shortcut_succeeded; } - const QDir dir(QString::fromStdString(target_directory.generic_string())); - if (!dir.exists()) { - QMessageBox::critical(this, tr("Create Shortcut"), - tr("Cannot create shortcut. Path \"%1\" does not exist.") - .arg(QString::fromStdString(target_directory.generic_string())), - QMessageBox::StandardButton::Ok); - return; + IShellLinkW* ps1; + + auto hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, + (void**)&ps1); + + // The UTF-16 / UTF-8 conversion is broken in C++, it is necessary to perform these steps and + // resort to the native Windows function. + std::wstring wshortcut_path_full = Common::UTF8ToUTF16W(shortcut_path_full.string()); + std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string()); + std::wstring wcommand = Common::UTF8ToUTF16W(command.string()); + std::wstring warguments = Common::UTF8ToUTF16W(arguments); + std::wstring wcomment = Common::UTF8ToUTF16W(comment); + + if (SUCCEEDED(hres)) { + if (std::filesystem::is_regular_file(command)) + hres = ps1->SetPath(wcommand.data()); + + if (SUCCEEDED(hres) && !arguments.empty()) + hres = ps1->SetArguments(warguments.data()); + + if (SUCCEEDED(hres) && !comment.empty()) + hres = ps1->SetDescription(wcomment.data()); + + if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) + hres = ps1->SetIconLocation(wicon_path.data(), 0); + + IPersistFile* pPersistFile = nullptr; + + if (SUCCEEDED(hres)) { + hres = ps1->QueryInterface(IID_IPersistFile, (void**)&pPersistFile); + + if (SUCCEEDED(hres) && pPersistFile != nullptr) { + hres = pPersistFile->Save(wshortcut_path_full.data(), TRUE); + if (SUCCEEDED(hres)) { + shortcut_succeeded = true; + } + } + } + + if (pPersistFile != nullptr) { + pPersistFile->Release(); + } + } else { + LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create IShellLinkWinstance"); } - const std::string game_file_name = std::filesystem::path(game_path).filename().string(); - // Determine full paths for icon and shortcut -#if defined(__linux__) || defined(__FreeBSD__) - const char* home = std::getenv("HOME"); - const std::filesystem::path home_path = (home == nullptr ? "~" : home); - const char* xdg_data_home = std::getenv("XDG_DATA_HOME"); - - std::filesystem::path system_icons_path = - (xdg_data_home == nullptr ? home_path / ".local/share/" - : std::filesystem::path(xdg_data_home)) / - "icons/hicolor/256x256"; - if (!Common::FS::CreateDirs(system_icons_path)) { + ps1->Release(); + CoUninitialize(); +#endif + + if (shortcut_succeeded && std::filesystem::is_regular_file(shortcut_path_full)) { + LOG_INFO(Common, "[GMainWindow::CreateShortcutLink] Shortcut created"); + } else { + LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Shortcut error, failed to create it"); + shortcut_succeeded = false; + } + + return shortcut_succeeded; +} + +// Messages in pre-defined message boxes for less code spaghetti +bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, + const std::string title) { + QMessageBox::StandardButtons buttons; + int result = 0; + + switch (imsg) { + + case GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES: + buttons = QMessageBox::Yes | QMessageBox::No; + + result = + QMessageBox::information(parent, tr("Create Shortcut"), + tr("Do you want to launch the game in fullscreen?"), buttons); + + LOG_INFO(Frontend, "Shortcut will launch in fullscreen"); + return (result == QMessageBox::No) ? false : true; + + case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS: + QMessageBox::information( + parent, tr("Create Shortcut"), + tr("Successfully created a shortcut to %1").arg(QString::fromStdString(title))); + LOG_INFO(Frontend, "Successfully created a shortcut to {}", title); + return true; + + case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING: + result = QMessageBox::warning( + this, tr("Create Shortcut"), + tr("This will create a shortcut to the current AppImage. This may " + "not work well if you update. Continue?"), + QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel); + return (result == QMessageBox::StandardButton::Cancel) ? true : false; + case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN: + buttons = QMessageBox::Ok; + QMessageBox::critical(parent, tr("Create Shortcut"), + tr("Cannot create shortcut in Apps. Restart yuzu as administrator."), + buttons); + LOG_ERROR(Frontend, "Cannot create shortcut in Apps. Restart yuzu as administrator."); + return true; + default: + buttons = QMessageBox::Ok; + QMessageBox::critical( + parent, tr("Create Shortcut"), + tr("Failed to create a shortcut to %1").arg(QString::fromStdString(title)), buttons); + LOG_ERROR(Frontend, "Failed to create a shortcut to {}", title); + return true; + } + + return true; +} + +bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, + std::filesystem::path& icons_path) { + + // Get path to Yuzu icons directory & icon extension + std::string ico_extension = "png"; +#if defined(_WIN32) + icons_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons"; + ico_extension = "ico"; +#elif defined(__linux__) || defined(__FreeBSD__) + icons_path = GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; +#endif + + // Create icons directory if it doesn't exist + if (!Common::FS::CreateDirs(icons_path)) { QMessageBox::critical( this, tr("Create Icon"), tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.") - .arg(QString::fromStdString(system_icons_path)), + .arg(QString::fromStdString(icons_path.string())), QMessageBox::StandardButton::Ok); - return; + icons_path = ""; // Reset path + return false; } - std::filesystem::path icon_path = - system_icons_path / (program_id == 0 ? fmt::format("yuzu-{}.png", game_file_name) - : fmt::format("yuzu-{:016X}.png", program_id)); - const std::filesystem::path shortcut_path = - target_directory / (program_id == 0 ? fmt::format("yuzu-{}.desktop", game_file_name) - : fmt::format("yuzu-{:016X}.desktop", program_id)); -#elif defined(WIN32) - std::filesystem::path icons_path = - Common::FS::GetYuzuPathString(Common::FS::YuzuPath::IconsDir); - std::filesystem::path icon_path = - icons_path / ((program_id == 0 ? fmt::format("yuzu-{}.ico", game_file_name) - : fmt::format("yuzu-{:016X}.ico", program_id))); -#else - std::string icon_extension; -#endif - // Get title from game file - const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), - system->GetContentProvider()}; - const auto control = pm.GetControlMetadata(); - const auto loader = Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read)); + // Create icon file path + icons_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension) + : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension)); + return true; +} - std::string title{fmt::format("{:016X}", program_id)}; +void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path, + GameListShortcutTarget target) { - if (control.first != nullptr) { - title = control.first->GetApplicationName(); - } else { - loader->ReadTitle(title); + // Get path to yuzu executable + const QStringList args = QApplication::arguments(); + std::filesystem::path yuzu_command = args[0].toStdString(); + + // If relative path, make it an absolute path + if (yuzu_command.c_str()[0] == '.') { + yuzu_command = Common::FS::GetCurrentDir() / yuzu_command; } - // Get icon from game file - std::vector icon_image_file{}; - if (control.second != nullptr) { - icon_image_file = control.second->ReadAllBytes(); - } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) { - LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path); + // Shortcut path + std::filesystem::path shortcut_path{}; + if (target == GameListShortcutTarget::Desktop) { + shortcut_path = Common::FS::GetDesktopPath(); + if (!std::filesystem::exists(shortcut_path)) { + shortcut_path = + QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString(); + } + } else if (target == GameListShortcutTarget::Applications) { + +#if defined(_WIN32) + HANDLE hProcess = GetCurrentProcess(); + if (!IsUserAnAdmin()) { + GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN, + ""); + return; + } + CloseHandle(hProcess); +#endif // _WIN32 + + shortcut_path = Common::FS::GetAppsShortcutsPath(); + if (!std::filesystem::exists(shortcut_path)) { + shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) + .toStdString(); + } } - QImage icon_data = - QImage::fromData(icon_image_file.data(), static_cast(icon_image_file.size())); -#if defined(__linux__) || defined(__FreeBSD__) - // Convert and write the icon as a PNG - if (!icon_data.save(QString::fromStdString(icon_path.string()))) { - LOG_ERROR(Frontend, "Could not write icon as PNG to file"); + // Icon path and title + std::string title; + std::filesystem::path icons_path; + if (std::filesystem::exists(shortcut_path)) { + + // Get title from game file + const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), + system->GetContentProvider()}; + const auto control = pm.GetControlMetadata(); + const auto loader = + Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read)); + + title = fmt::format("{:016X}", program_id); + + if (control.first != nullptr) { + title = control.first->GetApplicationName(); + } else { + loader->ReadTitle(title); + } + + // Get icon from game file + std::vector icon_image_file{}; + if (control.second != nullptr) { + icon_image_file = control.second->ReadAllBytes(); + } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) { + LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path); + } + + QImage icon_data = + QImage::fromData(icon_image_file.data(), static_cast(icon_image_file.size())); + + if (GMainWindow::MakeShortcutIcoPath(program_id, title, icons_path)) { + if (!SaveIconToFile(icon_data, icons_path)) { + LOG_ERROR(Frontend, "Could not write icon to file"); + } + } + } else { - LOG_INFO(Frontend, "Wrote an icon to {}", icon_path.string()); - } -#elif defined(WIN32) - if (!SaveIconToFile(icon_path.string(), icon_data)) { - LOG_ERROR(Frontend, "Could not write icon to file"); + GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, + title); + LOG_ERROR(Frontend, "[GMainWindow::OnGameListCreateShortcut] Invalid shortcut target"); return; } -#endif // __linux__ -#ifdef _WIN32 - // Replace characters that are illegal in Windows filenames by a dash - const std::string illegal_chars = "<>:\"/\\|?*"; - for (char c : illegal_chars) { - std::replace(title.begin(), title.end(), c, '_'); +// Special case for AppImages +#if defined(__linux__) + // Warn once if we are making a shortcut to a volatile AppImage + const std::string appimage_ending = + std::string(Common::g_scm_rev).substr(0, 9).append(".AppImage"); + if (yuzu_command.string().ends_with(appimage_ending) && + !UISettings::values.shortcut_already_warned) { + if (GMainWindow::CreateShortcutMessagesGUI( + this, GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING, title)) { + return; + } + UISettings::values.shortcut_already_warned = true; } - const std::filesystem::path shortcut_path = target_directory / (title + ".lnk").c_str(); -#endif +#endif // __linux__ + // Create shortcut + std::string arguments = fmt::format("-g \"{:s}\"", game_path); + if (GMainWindow::CreateShortcutMessagesGUI( + this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, title)) { + arguments = "-f " + arguments; + } const std::string comment = tr("Start %1 with the yuzu Emulator").arg(QString::fromStdString(title)).toStdString(); - const std::string arguments = fmt::format("-g \"{:s}\"", game_path); const std::string categories = "Game;Emulator;Qt;"; const std::string keywords = "Switch;Nintendo;"; - if (!CreateShortcut(shortcut_path.string(), title, comment, icon_path.string(), - yuzu_command.string(), arguments, categories, keywords)) { - QMessageBox::critical(this, tr("Create Shortcut"), - tr("Failed to create a shortcut at %1") - .arg(QString::fromStdString(shortcut_path.string()))); + if (GMainWindow::CreateShortcutLink(shortcut_path, comment, icons_path, yuzu_command, arguments, + categories, keywords, title)) { + GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS, + title); return; } - LOG_INFO(Frontend, "Wrote a shortcut to {}", shortcut_path.string()); - QMessageBox::information( - this, tr("Create Shortcut"), - tr("Successfully created a shortcut to %1").arg(QString::fromStdString(title))); + GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, title); } void GMainWindow::OnGameListOpenDirectory(const QString& directory) { @@ -3998,66 +4178,6 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file } } -bool GMainWindow::CreateShortcut(const std::string& shortcut_path, const std::string& title, - const std::string& comment, const std::string& icon_path, - const std::string& command, const std::string& arguments, - const std::string& categories, const std::string& keywords) { -#if defined(__linux__) || defined(__FreeBSD__) - // This desktop file template was writing referencing - // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html - std::string shortcut_contents{}; - shortcut_contents.append("[Desktop Entry]\n"); - shortcut_contents.append("Type=Application\n"); - shortcut_contents.append("Version=1.0\n"); - shortcut_contents.append(fmt::format("Name={:s}\n", title)); - shortcut_contents.append(fmt::format("Comment={:s}\n", comment)); - shortcut_contents.append(fmt::format("Icon={:s}\n", icon_path)); - shortcut_contents.append(fmt::format("TryExec={:s}\n", command)); - shortcut_contents.append(fmt::format("Exec={:s} {:s}\n", command, arguments)); - shortcut_contents.append(fmt::format("Categories={:s}\n", categories)); - shortcut_contents.append(fmt::format("Keywords={:s}\n", keywords)); - - std::ofstream shortcut_stream(shortcut_path); - if (!shortcut_stream.is_open()) { - LOG_WARNING(Common, "Failed to create file {:s}", shortcut_path); - return false; - } - shortcut_stream << shortcut_contents; - shortcut_stream.close(); - - return true; -#elif defined(WIN32) - IShellLinkW* shell_link; - auto hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, - (void**)&shell_link); - if (FAILED(hres)) { - return false; - } - shell_link->SetPath( - Common::UTF8ToUTF16W(command).data()); // Path to the object we are referring to - shell_link->SetArguments(Common::UTF8ToUTF16W(arguments).data()); - shell_link->SetDescription(Common::UTF8ToUTF16W(comment).data()); - shell_link->SetIconLocation(Common::UTF8ToUTF16W(icon_path).data(), 0); - - IPersistFile* persist_file; - hres = shell_link->QueryInterface(IID_IPersistFile, (void**)&persist_file); - if (FAILED(hres)) { - return false; - } - - hres = persist_file->Save(Common::UTF8ToUTF16W(shortcut_path).data(), TRUE); - if (FAILED(hres)) { - return false; - } - - persist_file->Release(); - shell_link->Release(); - - return true; -#endif - return false; -} - void GMainWindow::OnLoadAmiibo() { if (emu_thread == nullptr || !emu_thread->IsRunning()) { return; diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 270a40c5f..bf6756b48 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -151,6 +152,14 @@ class GMainWindow : public QMainWindow { UI_EMU_STOPPING, }; + const enum { + CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, + CREATE_SHORTCUT_MSGBOX_SUCCESS, + CREATE_SHORTCUT_MSGBOX_ERROR, + CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING, + CREATE_SHORTCUT_MSGBOX_ADMIN, + }; + public: void filterBarSetChecked(bool state); void UpdateUITheme(); @@ -433,11 +442,14 @@ private: bool ConfirmShutdownGame(); QString GetTasStateDescription() const; - bool CreateShortcut(const std::string& shortcut_path, const std::string& title, - const std::string& comment, const std::string& icon_path, - const std::string& command, const std::string& arguments, - const std::string& categories, const std::string& keywords); - + bool CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, const std::string title); + bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, + std::filesystem::path& icons_path); + bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment, + const std::filesystem::path& icon_path, + const std::filesystem::path& command, const std::string& arguments, + const std::string& categories, const std::string& keywords, + const std::string& name); /** * Mimic the behavior of QMessageBox::question but link controller navigation to the dialog * The only difference is that it returns a boolean. diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp index f2854c8ec..4d199ebd1 100644 --- a/src/yuzu/util/util.cpp +++ b/src/yuzu/util/util.cpp @@ -42,7 +42,7 @@ QPixmap CreateCirclePixmapFromColor(const QColor& color) { return circle_pixmap; } -bool SaveIconToFile(const std::string_view path, const QImage& image) { +bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path) { #if defined(WIN32) #pragma pack(push, 2) struct IconDir { @@ -73,7 +73,7 @@ bool SaveIconToFile(const std::string_view path, const QImage& image) { .id_count = static_cast(scale_sizes.size()), }; - Common::FS::IOFile icon_file(path, Common::FS::FileAccessMode::Write, + Common::FS::IOFile icon_file(icon_path.string(), Common::FS::FileAccessMode::Write, Common::FS::FileType::BinaryFile); if (!icon_file.IsOpen()) { return false; @@ -135,7 +135,16 @@ bool SaveIconToFile(const std::string_view path, const QImage& image) { icon_file.Close(); return true; -#else - return false; +#elif defined(__linux__) || defined(__FreeBSD__) + // Convert and write the icon as a PNG + if (!image.save(QString::fromStdString(icon_path.string()))) { + LOG_ERROR(Frontend, "Could not write icon as PNG to file"); + } else { + LOG_INFO(Frontend, "Wrote an icon to {}", icon_path.string()); + } + + return true; #endif + + return false; } diff --git a/src/yuzu/util/util.h b/src/yuzu/util/util.h index 09c14ce3f..8839e160a 100644 --- a/src/yuzu/util/util.h +++ b/src/yuzu/util/util.h @@ -3,26 +3,36 @@ #pragma once +#include #include #include /// Returns a QFont object appropriate to use as a monospace font for debugging widgets, etc. + [[nodiscard]] QFont GetMonospaceFont(); /// Convert a size in bytes into a readable format (KiB, MiB, etc.) + [[nodiscard]] QString ReadableByteSize(qulonglong size); /** * Creates a circle pixmap from a specified color + * * @param color The color the pixmap shall have + * * @return QPixmap circle pixmap */ + [[nodiscard]] QPixmap CreateCirclePixmapFromColor(const QColor& color); /** * Saves a windows icon to a file - * @param path The icons path + * * @param image The image to save + * + * @param path The icons path + * * @return bool If the operation succeeded */ -[[nodiscard]] bool SaveIconToFile(const std::string_view path, const QImage& image); + +[[nodiscard]] bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path); -- cgit v1.2.3 From 0a75519ab590e250c94dc04b3f6072a69ef7e96b Mon Sep 17 00:00:00 2001 From: boludoz Date: Sun, 15 Oct 2023 03:16:29 -0300 Subject: Fixes and improvements --- src/yuzu/main.h | 2 +- src/yuzu/util/util.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.h b/src/yuzu/main.h index bf6756b48..d7426607f 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -152,7 +152,7 @@ class GMainWindow : public QMainWindow { UI_EMU_STOPPING, }; - const enum { + enum { CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, CREATE_SHORTCUT_MSGBOX_SUCCESS, CREATE_SHORTCUT_MSGBOX_ERROR, diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp index 4d199ebd1..9755004ad 100644 --- a/src/yuzu/util/util.cpp +++ b/src/yuzu/util/util.cpp @@ -144,7 +144,7 @@ bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path) } return true; -#endif - +#else return false; +#endif } -- cgit v1.2.3 From 4d4fe69223bd6cd053cbd2088e5925fb653a12d3 Mon Sep 17 00:00:00 2001 From: boludoz Date: Sun, 15 Oct 2023 14:44:23 -0300 Subject: Unnecessary feature removed --- src/yuzu/main.cpp | 16 ++++------------ src/yuzu/util/util.h | 3 --- 2 files changed, 4 insertions(+), 15 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index e4dc717ed..fd68ac9b6 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -3082,13 +3082,9 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga // Shortcut path std::filesystem::path shortcut_path{}; if (target == GameListShortcutTarget::Desktop) { - shortcut_path = Common::FS::GetDesktopPath(); - if (!std::filesystem::exists(shortcut_path)) { - shortcut_path = - QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString(); - } + shortcut_path = + QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString(); } else if (target == GameListShortcutTarget::Applications) { - #if defined(_WIN32) HANDLE hProcess = GetCurrentProcess(); if (!IsUserAnAdmin()) { @@ -3098,12 +3094,8 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga } CloseHandle(hProcess); #endif // _WIN32 - - shortcut_path = Common::FS::GetAppsShortcutsPath(); - if (!std::filesystem::exists(shortcut_path)) { - shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) - .toStdString(); - } + shortcut_path = + QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString(); } // Icon path and title diff --git a/src/yuzu/util/util.h b/src/yuzu/util/util.h index 8839e160a..31e82ff67 100644 --- a/src/yuzu/util/util.h +++ b/src/yuzu/util/util.h @@ -8,11 +8,9 @@ #include /// Returns a QFont object appropriate to use as a monospace font for debugging widgets, etc. - [[nodiscard]] QFont GetMonospaceFont(); /// Convert a size in bytes into a readable format (KiB, MiB, etc.) - [[nodiscard]] QString ReadableByteSize(qulonglong size); /** @@ -34,5 +32,4 @@ * * @return bool If the operation succeeded */ - [[nodiscard]] bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path); -- cgit v1.2.3 From 9ffa1801c75073afb851351ecdd1a8b40e33cc5c Mon Sep 17 00:00:00 2001 From: boludoz Date: Sun, 15 Oct 2023 20:57:06 -0300 Subject: Typing and formatting errors fixed. --- src/yuzu/main.cpp | 24 +++++++++++------------- src/yuzu/util/util.cpp | 3 +-- src/yuzu/util/util.h | 10 ++-------- 3 files changed, 14 insertions(+), 23 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index fd68ac9b6..c3c12eeec 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2851,7 +2851,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, // Replace characters that are illegal in Windows filenames std::filesystem::path shortcut_path_full = - shortcut_path / Common::FS::UTF8FilenameSantizer(name); + shortcut_path / Common::FS::UTF8FilenameSanitizer(name); #if defined(__linux__) || defined(__FreeBSD__) shortcut_path_full += ".desktop"; @@ -2859,8 +2859,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, shortcut_path_full += ".lnk"; #endif - LOG_INFO(Common, "[GMainWindow::CreateShortcutLink] Create shortcut path: {}", - shortcut_path_full.string()); + LOG_ERROR(Frontend, "Create shortcut path: {}", shortcut_path_full.string()); #if defined(__linux__) || defined(__FreeBSD__) // This desktop file template was writing referencing @@ -2869,7 +2868,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, // Plus 'Type' is required if (name.empty()) { - LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Name is empty"); + LOG_ERROR(Frontend, "Name is empty"); shortcut_succeeded = false; return shortcut_succeeded; } @@ -2911,14 +2910,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, return true; } else { - LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create shortcut"); + LOG_ERROR(Frontend, "Failed to create shortcut"); return false; } shortcut_stream.close(); } catch (const std::exception& e) { - LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create shortcut: {}", - e.what()); + LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); } #elif defined(_WIN32) // Initialize COM @@ -2970,7 +2968,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, pPersistFile->Release(); } } else { - LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create IShellLinkWinstance"); + LOG_ERROR(Frontend, "Failed to create IShellLinkWinstance"); } ps1->Release(); @@ -2978,9 +2976,9 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, #endif if (shortcut_succeeded && std::filesystem::is_regular_file(shortcut_path_full)) { - LOG_INFO(Common, "[GMainWindow::CreateShortcutLink] Shortcut created"); + LOG_ERROR(Frontend, "Shortcut created"); } else { - LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Shortcut error, failed to create it"); + LOG_ERROR(Frontend, "Shortcut error, failed to create it"); shortcut_succeeded = false; } @@ -3047,7 +3045,7 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi icons_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons"; ico_extension = "ico"; #elif defined(__linux__) || defined(__FreeBSD__) - icons_path = GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; + icons_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; #endif // Create icons directory if it doesn't exist @@ -3130,7 +3128,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga QImage::fromData(icon_image_file.data(), static_cast(icon_image_file.size())); if (GMainWindow::MakeShortcutIcoPath(program_id, title, icons_path)) { - if (!SaveIconToFile(icon_data, icons_path)) { + if (!SaveIconToFile(icons_path, icon_data)) { LOG_ERROR(Frontend, "Could not write icon to file"); } } @@ -3138,7 +3136,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga } else { GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, title); - LOG_ERROR(Frontend, "[GMainWindow::OnGameListCreateShortcut] Invalid shortcut target"); + LOG_ERROR(Frontend, "Invalid shortcut target"); return; } diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp index 9755004ad..7b2a47496 100644 --- a/src/yuzu/util/util.cpp +++ b/src/yuzu/util/util.cpp @@ -42,7 +42,7 @@ QPixmap CreateCirclePixmapFromColor(const QColor& color) { return circle_pixmap; } -bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path) { +bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image) { #if defined(WIN32) #pragma pack(push, 2) struct IconDir { @@ -142,7 +142,6 @@ bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path) } else { LOG_INFO(Frontend, "Wrote an icon to {}", icon_path.string()); } - return true; #else return false; diff --git a/src/yuzu/util/util.h b/src/yuzu/util/util.h index 31e82ff67..4094cf6c2 100644 --- a/src/yuzu/util/util.h +++ b/src/yuzu/util/util.h @@ -15,21 +15,15 @@ /** * Creates a circle pixmap from a specified color - * * @param color The color the pixmap shall have - * * @return QPixmap circle pixmap */ - [[nodiscard]] QPixmap CreateCirclePixmapFromColor(const QColor& color); /** * Saves a windows icon to a file - * - * @param image The image to save - * * @param path The icons path - * + * @param image The image to save * @return bool If the operation succeeded */ -[[nodiscard]] bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path); +[[nodiscard]] bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image); -- cgit v1.2.3 From 74961d4dfb394c098da494f6beacdd994c089566 Mon Sep 17 00:00:00 2001 From: boludoz Date: Sun, 15 Oct 2023 21:40:10 -0300 Subject: Less code, simpler, better. --- src/yuzu/main.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index c3c12eeec..f2b91a7f3 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2849,9 +2849,21 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, bool shortcut_succeeded = false; + // Copy characters if they are not illegal in Windows filenames + std::string filename = ""; + const std::string illegal_chars = "<>:\"/\\|?*"; + filename.reserve(name.size()); + std::copy_if(name.begin(), name.end(), std::back_inserter(filename), + [&illegal_chars](char c) { return illegal_chars.find(c) == std::string::npos; }); + + if (filename.empty()) { + LOG_ERROR(Frontend, "Filename is empty"); + shortcut_succeeded = false; + return shortcut_succeeded; + } + // Replace characters that are illegal in Windows filenames - std::filesystem::path shortcut_path_full = - shortcut_path / Common::FS::UTF8FilenameSanitizer(name); + std::filesystem::path shortcut_path_full = shortcut_path / filename; #if defined(__linux__) || defined(__FreeBSD__) shortcut_path_full += ".desktop"; -- cgit v1.2.3 From 26417da5d36ea5aae4410a5c35405e27f39661d2 Mon Sep 17 00:00:00 2001 From: boludoz Date: Mon, 16 Oct 2023 03:26:40 -0300 Subject: Some improvements (suggestions) --- src/yuzu/main.cpp | 158 ++++++++++++++++++++++++++---------------------------- src/yuzu/main.h | 2 +- 2 files changed, 77 insertions(+), 83 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f2b91a7f3..36f9551a1 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2847,8 +2847,6 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& arguments, const std::string& categories, const std::string& keywords, const std::string& name) { - bool shortcut_succeeded = false; - // Copy characters if they are not illegal in Windows filenames std::string filename = ""; const std::string illegal_chars = "<>:\"/\\|?*"; @@ -2858,22 +2856,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, if (filename.empty()) { LOG_ERROR(Frontend, "Filename is empty"); - shortcut_succeeded = false; - return shortcut_succeeded; + return false; } - // Replace characters that are illegal in Windows filenames + // Append .desktop or .lnk extension std::filesystem::path shortcut_path_full = shortcut_path / filename; -#if defined(__linux__) || defined(__FreeBSD__) - shortcut_path_full += ".desktop"; -#elif defined(_WIN32) - shortcut_path_full += ".lnk"; -#endif - - LOG_ERROR(Frontend, "Create shortcut path: {}", shortcut_path_full.string()); - -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD // This desktop file template was writing referencing // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html try { @@ -2881,9 +2870,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, // Plus 'Type' is required if (name.empty()) { LOG_ERROR(Frontend, "Name is empty"); - shortcut_succeeded = false; - return shortcut_succeeded; + return false; } + + // Append .desktop extension + shortcut_path_full += ".desktop"; + + // Create shortcut file std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); if (shortcut_stream.is_open()) { @@ -2923,78 +2916,82 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, } else { LOG_ERROR(Frontend, "Failed to create shortcut"); - return false; } shortcut_stream.close(); } catch (const std::exception& e) { LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); } -#elif defined(_WIN32) - // Initialize COM - auto hr = CoInitialize(NULL); - if (FAILED(hr)) { - return shortcut_succeeded; - } + return false; +#elif defined(_WIN32) // Windows + HRESULT hr = CoInitialize(NULL); + if (SUCCEEDED(hr)) { - IShellLinkW* ps1; + IShellLinkW* ps1 = nullptr; + IPersistFile* persist_file = nullptr; - auto hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, - (void**)&ps1); + SCOPE_EXIT({ + if (persist_file != nullptr) { + persist_file->Release(); + } + if (ps1 != nullptr) { + ps1->Release(); + } - // The UTF-16 / UTF-8 conversion is broken in C++, it is necessary to perform these steps and - // resort to the native Windows function. - std::wstring wshortcut_path_full = Common::UTF8ToUTF16W(shortcut_path_full.string()); - std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string()); - std::wstring wcommand = Common::UTF8ToUTF16W(command.string()); - std::wstring warguments = Common::UTF8ToUTF16W(arguments); - std::wstring wcomment = Common::UTF8ToUTF16W(comment); + CoUninitialize(); + }); - if (SUCCEEDED(hres)) { - if (std::filesystem::is_regular_file(command)) - hres = ps1->SetPath(wcommand.data()); + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + IID_IShellLinkW, (void**)&ps1); - if (SUCCEEDED(hres) && !arguments.empty()) - hres = ps1->SetArguments(warguments.data()); + std::wstring wshortcut_path_full = Common::UTF8ToUTF16W(shortcut_path_full.string()); + std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string()); + std::wstring wcommand = Common::UTF8ToUTF16W(command.string()); + std::wstring warguments = Common::UTF8ToUTF16W(arguments); + std::wstring wcomment = Common::UTF8ToUTF16W(comment); + + if (SUCCEEDED(hres)) { + if (std::filesystem::is_regular_file(command)) { + hres = ps1->SetPath(wcommand.data()); + } else { + LOG_ERROR(Frontend, "Command is not a regular file"); + return false; + } - if (SUCCEEDED(hres) && !comment.empty()) - hres = ps1->SetDescription(wcomment.data()); + if (SUCCEEDED(hres) && !arguments.empty()) { + hres = ps1->SetArguments(warguments.data()); + } - if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) - hres = ps1->SetIconLocation(wicon_path.data(), 0); + if (SUCCEEDED(hres) && !comment.empty()) { + hres = ps1->SetDescription(wcomment.data()); + } - IPersistFile* pPersistFile = nullptr; + if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) { + hres = ps1->SetIconLocation(wicon_path.data(), 0); + } - if (SUCCEEDED(hres)) { - hres = ps1->QueryInterface(IID_IPersistFile, (void**)&pPersistFile); + if (SUCCEEDED(hres)) { + hres = ps1->QueryInterface(IID_IPersistFile, (void**)&persist_file); + } - if (SUCCEEDED(hres) && pPersistFile != nullptr) { - hres = pPersistFile->Save(wshortcut_path_full.data(), TRUE); + if (SUCCEEDED(hres) && persist_file != nullptr) { + // Append .lnk extension and save shortcut + shortcut_path_full += ".lnk"; + hres = persist_file->Save(wshortcut_path_full.data(), TRUE); if (SUCCEEDED(hres)) { - shortcut_succeeded = true; + return true; + } else { + LOG_ERROR(Frontend, "Failed to create shortcut"); } } + } else { + LOG_ERROR(Frontend, "Failed to create CoCreateInstance"); } - - if (pPersistFile != nullptr) { - pPersistFile->Release(); - } - } else { - LOG_ERROR(Frontend, "Failed to create IShellLinkWinstance"); } - - ps1->Release(); - CoUninitialize(); + return false; +#else // Unsupported platform + return false; #endif - - if (shortcut_succeeded && std::filesystem::is_regular_file(shortcut_path_full)) { - LOG_ERROR(Frontend, "Shortcut created"); - } else { - LOG_ERROR(Frontend, "Shortcut error, failed to create it"); - shortcut_succeeded = false; - } - - return shortcut_succeeded; } // Messages in pre-defined message boxes for less code spaghetti @@ -3049,31 +3046,31 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, } bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, - std::filesystem::path& icons_path) { + std::filesystem::path& out_icon_path) { // Get path to Yuzu icons directory & icon extension std::string ico_extension = "png"; #if defined(_WIN32) - icons_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons"; + out_icon_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons"; ico_extension = "ico"; #elif defined(__linux__) || defined(__FreeBSD__) - icons_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; + out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; #endif // Create icons directory if it doesn't exist - if (!Common::FS::CreateDirs(icons_path)) { + if (!Common::FS::CreateDirs(out_icon_path)) { QMessageBox::critical( this, tr("Create Icon"), tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.") - .arg(QString::fromStdString(icons_path.string())), + .arg(QString::fromStdString(out_icon_path.string())), QMessageBox::StandardButton::Ok); - icons_path = ""; // Reset path + out_icon_path = ""; // Reset path return false; } // Create icon file path - icons_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension) - : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension)); + out_icon_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension) + : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension)); return true; } @@ -3096,13 +3093,11 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString(); } else if (target == GameListShortcutTarget::Applications) { #if defined(_WIN32) - HANDLE hProcess = GetCurrentProcess(); if (!IsUserAnAdmin()) { GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN, ""); return; } - CloseHandle(hProcess); #endif // _WIN32 shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString(); @@ -3110,9 +3105,8 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga // Icon path and title std::string title; - std::filesystem::path icons_path; + std::filesystem::path out_icon_path; if (std::filesystem::exists(shortcut_path)) { - // Get title from game file const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), system->GetContentProvider()}; @@ -3139,8 +3133,8 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga QImage icon_data = QImage::fromData(icon_image_file.data(), static_cast(icon_image_file.size())); - if (GMainWindow::MakeShortcutIcoPath(program_id, title, icons_path)) { - if (!SaveIconToFile(icons_path, icon_data)) { + if (GMainWindow::MakeShortcutIcoPath(program_id, title, out_icon_path)) { + if (!SaveIconToFile(out_icon_path, icon_data)) { LOG_ERROR(Frontend, "Could not write icon to file"); } } @@ -3178,8 +3172,8 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga const std::string categories = "Game;Emulator;Qt;"; const std::string keywords = "Switch;Nintendo;"; - if (GMainWindow::CreateShortcutLink(shortcut_path, comment, icons_path, yuzu_command, arguments, - categories, keywords, title)) { + if (GMainWindow::CreateShortcutLink(shortcut_path, comment, out_icon_path, yuzu_command, + arguments, categories, keywords, title)) { GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS, title); return; diff --git a/src/yuzu/main.h b/src/yuzu/main.h index d7426607f..d3a1bf5b9 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -444,7 +444,7 @@ private: QString GetTasStateDescription() const; bool CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, const std::string title); bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, - std::filesystem::path& icons_path); + std::filesystem::path& out_icon_path); bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment, const std::filesystem::path& icon_path, const std::filesystem::path& command, const std::string& arguments, -- cgit v1.2.3 From 89d3e81be8b923711a548b0973276353392449a6 Mon Sep 17 00:00:00 2001 From: boludoz Date: Mon, 16 Oct 2023 16:01:46 -0300 Subject: Sugestions and fixes. --- src/yuzu/main.cpp | 104 ++++++++++++++++++++++++++++-------------------------- src/yuzu/main.h | 2 +- 2 files changed, 54 insertions(+), 52 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 36f9551a1..feb455763 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2859,11 +2859,15 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, return false; } - // Append .desktop or .lnk extension + if (!std::filesystem::is_regular_file(command)) { + LOG_ERROR(Frontend, "Command is not a regular file"); + return false; + } + std::filesystem::path shortcut_path_full = shortcut_path / filename; #if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD - // This desktop file template was writing referencing + // Reference for the desktop file template: // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html try { @@ -2911,17 +2915,17 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, fmt::print(shortcut_stream, "Keywords={}\n", keywords); } + // Flush and close file + shortcut_stream.flush(); shortcut_stream.close(); return true; - } else { LOG_ERROR(Frontend, "Failed to create shortcut"); } - - shortcut_stream.close(); } catch (const std::exception& e) { LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); } + shortcut_stream.close(); return false; #elif defined(_WIN32) // Windows HRESULT hr = CoInitialize(NULL); @@ -2944,19 +2948,15 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void**)&ps1); - std::wstring wshortcut_path_full = Common::UTF8ToUTF16W(shortcut_path_full.string()); + std::wstring wshortcut_path_full = + Common::UTF8ToUTF16W((shortcut_path_full).string() + ".lnk"); std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string()); std::wstring wcommand = Common::UTF8ToUTF16W(command.string()); std::wstring warguments = Common::UTF8ToUTF16W(arguments); std::wstring wcomment = Common::UTF8ToUTF16W(comment); if (SUCCEEDED(hres)) { - if (std::filesystem::is_regular_file(command)) { - hres = ps1->SetPath(wcommand.data()); - } else { - LOG_ERROR(Frontend, "Command is not a regular file"); - return false; - } + hres = ps1->SetPath(wcommand.data()); if (SUCCEEDED(hres) && !arguments.empty()) { hres = ps1->SetArguments(warguments.data()); @@ -2975,8 +2975,6 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, } if (SUCCEEDED(hres) && persist_file != nullptr) { - // Append .lnk extension and save shortcut - shortcut_path_full += ".lnk"; hres = persist_file->Save(wshortcut_path_full.data(), TRUE); if (SUCCEEDED(hres)) { return true; @@ -2995,9 +2993,10 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, } // Messages in pre-defined message boxes for less code spaghetti -bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, - const std::string title) { +bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) { QMessageBox::StandardButtons buttons; + std::string_view game_title_sv = game_title.toStdString(); + int result = 0; switch (imsg) { @@ -3013,18 +3012,18 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, return (result == QMessageBox::No) ? false : true; case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS: - QMessageBox::information( - parent, tr("Create Shortcut"), - tr("Successfully created a shortcut to %1").arg(QString::fromStdString(title))); - LOG_INFO(Frontend, "Successfully created a shortcut to {}", title); + QMessageBox::information(parent, tr("Create Shortcut"), + tr("Successfully created a shortcut to %1").arg(game_title)); + LOG_INFO(Frontend, "Successfully created a shortcut to {}", game_title_sv); return true; case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING: - result = QMessageBox::warning( - this, tr("Create Shortcut"), - tr("This will create a shortcut to the current AppImage. This may " - "not work well if you update. Continue?"), - QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel); + buttons = QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel; + result = + QMessageBox::warning(this, tr("Create Shortcut"), + tr("This will create a shortcut to the current AppImage. This may " + "not work well if you update. Continue?"), + buttons); return (result == QMessageBox::StandardButton::Cancel) ? true : false; case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN: buttons = QMessageBox::Ok; @@ -3035,10 +3034,9 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, return true; default: buttons = QMessageBox::Ok; - QMessageBox::critical( - parent, tr("Create Shortcut"), - tr("Failed to create a shortcut to %1").arg(QString::fromStdString(title)), buttons); - LOG_ERROR(Frontend, "Failed to create a shortcut to {}", title); + QMessageBox::critical(parent, tr("Create Shortcut"), + tr("Failed to create a shortcut to %1").arg(game_title), buttons); + LOG_ERROR(Frontend, "Failed to create a shortcut to {}", game_title_sv); return true; } @@ -3077,6 +3075,10 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path, GameListShortcutTarget target) { + std::string game_title; + QString qt_game_title; + std::filesystem::path out_icon_path; + // Get path to yuzu executable const QStringList args = QApplication::arguments(); std::filesystem::path yuzu_command = args[0].toStdString(); @@ -3092,20 +3094,11 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga shortcut_path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString(); } else if (target == GameListShortcutTarget::Applications) { -#if defined(_WIN32) - if (!IsUserAnAdmin()) { - GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN, - ""); - return; - } -#endif // _WIN32 shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString(); } // Icon path and title - std::string title; - std::filesystem::path out_icon_path; if (std::filesystem::exists(shortcut_path)) { // Get title from game file const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), @@ -3114,14 +3107,16 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga const auto loader = Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read)); - title = fmt::format("{:016X}", program_id); + game_title = fmt::format("{:016X}", program_id); if (control.first != nullptr) { - title = control.first->GetApplicationName(); + game_title = control.first->GetApplicationName(); } else { - loader->ReadTitle(title); + loader->ReadTitle(game_title); } + qt_game_title = QString::fromStdString(game_title); + // Get icon from game file std::vector icon_image_file{}; if (control.second != nullptr) { @@ -3133,7 +3128,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga QImage icon_data = QImage::fromData(icon_image_file.data(), static_cast(icon_image_file.size())); - if (GMainWindow::MakeShortcutIcoPath(program_id, title, out_icon_path)) { + if (GMainWindow::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) { if (!SaveIconToFile(out_icon_path, icon_data)) { LOG_ERROR(Frontend, "Could not write icon to file"); } @@ -3141,20 +3136,26 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga } else { GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, - title); + qt_game_title); LOG_ERROR(Frontend, "Invalid shortcut target"); return; } -// Special case for AppImages -#if defined(__linux__) +#if defined(_WIN32) + if (!IsUserAnAdmin() && target == GameListShortcutTarget::Applications) { + GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN, + qt_game_title); + return; + } +#elif defined(__linux__) + // Special case for AppImages // Warn once if we are making a shortcut to a volatile AppImage const std::string appimage_ending = std::string(Common::g_scm_rev).substr(0, 9).append(".AppImage"); if (yuzu_command.string().ends_with(appimage_ending) && !UISettings::values.shortcut_already_warned) { if (GMainWindow::CreateShortcutMessagesGUI( - this, GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING, title)) { + this, GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING, qt_game_title)) { return; } UISettings::values.shortcut_already_warned = true; @@ -3164,22 +3165,23 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga // Create shortcut std::string arguments = fmt::format("-g \"{:s}\"", game_path); if (GMainWindow::CreateShortcutMessagesGUI( - this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, title)) { + this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, qt_game_title)) { arguments = "-f " + arguments; } const std::string comment = - tr("Start %1 with the yuzu Emulator").arg(QString::fromStdString(title)).toStdString(); + tr("Start %1 with the yuzu Emulator").arg(QString::fromStdString(game_title)).toStdString(); const std::string categories = "Game;Emulator;Qt;"; const std::string keywords = "Switch;Nintendo;"; if (GMainWindow::CreateShortcutLink(shortcut_path, comment, out_icon_path, yuzu_command, - arguments, categories, keywords, title)) { + arguments, categories, keywords, game_title)) { GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS, - title); + qt_game_title); return; } - GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, title); + GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, + qt_game_title); } void GMainWindow::OnGameListOpenDirectory(const QString& directory) { diff --git a/src/yuzu/main.h b/src/yuzu/main.h index d3a1bf5b9..41902cc8d 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -442,7 +442,7 @@ private: bool ConfirmShutdownGame(); QString GetTasStateDescription() const; - bool CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, const std::string title); + bool CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title); bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, std::filesystem::path& out_icon_path); bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment, -- cgit v1.2.3 From d759de9f96faa8f530b3724b79ccc04ab0d01a09 Mon Sep 17 00:00:00 2001 From: boludoz Date: Mon, 16 Oct 2023 16:11:24 -0300 Subject: More missed suggestions --- src/yuzu/main.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index feb455763..90bb61c15 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2995,12 +2995,10 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, // Messages in pre-defined message boxes for less code spaghetti bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) { QMessageBox::StandardButtons buttons; - std::string_view game_title_sv = game_title.toStdString(); int result = 0; switch (imsg) { - case GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES: buttons = QMessageBox::Yes | QMessageBox::No; @@ -3009,12 +3007,11 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt tr("Do you want to launch the game in fullscreen?"), buttons); LOG_INFO(Frontend, "Shortcut will launch in fullscreen"); - return (result == QMessageBox::No) ? false : true; + return result == QMessageBox::Yes; case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS: QMessageBox::information(parent, tr("Create Shortcut"), tr("Successfully created a shortcut to %1").arg(game_title)); - LOG_INFO(Frontend, "Successfully created a shortcut to {}", game_title_sv); return true; case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING: @@ -3024,7 +3021,7 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt tr("This will create a shortcut to the current AppImage. This may " "not work well if you update. Continue?"), buttons); - return (result == QMessageBox::StandardButton::Cancel) ? true : false; + return result == QMessageBox::StandardButton::Ok; case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN: buttons = QMessageBox::Ok; QMessageBox::critical(parent, tr("Create Shortcut"), @@ -3036,7 +3033,6 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt buttons = QMessageBox::Ok; QMessageBox::critical(parent, tr("Create Shortcut"), tr("Failed to create a shortcut to %1").arg(game_title), buttons); - LOG_ERROR(Frontend, "Failed to create a shortcut to {}", game_title_sv); return true; } -- cgit v1.2.3 From ae88d01d8dfc9c39206d3fb37938e44a3480c70f Mon Sep 17 00:00:00 2001 From: boludoz Date: Mon, 16 Oct 2023 16:47:21 -0300 Subject: .clear() instead = ""; and switch improved. --- src/yuzu/main.cpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 90bb61c15..82b38fc07 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2997,23 +2997,17 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt QMessageBox::StandardButtons buttons; int result = 0; - switch (imsg) { case GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES: buttons = QMessageBox::Yes | QMessageBox::No; - result = QMessageBox::information(parent, tr("Create Shortcut"), tr("Do you want to launch the game in fullscreen?"), buttons); - - LOG_INFO(Frontend, "Shortcut will launch in fullscreen"); - return result == QMessageBox::Yes; - + return (result == QMessageBox::Yes); case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS: QMessageBox::information(parent, tr("Create Shortcut"), tr("Successfully created a shortcut to %1").arg(game_title)); - return true; - + break; case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING: buttons = QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel; result = @@ -3021,22 +3015,20 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt tr("This will create a shortcut to the current AppImage. This may " "not work well if you update. Continue?"), buttons); - return result == QMessageBox::StandardButton::Ok; + return (result == QMessageBox::Ok); case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN: buttons = QMessageBox::Ok; QMessageBox::critical(parent, tr("Create Shortcut"), tr("Cannot create shortcut in Apps. Restart yuzu as administrator."), buttons); - LOG_ERROR(Frontend, "Cannot create shortcut in Apps. Restart yuzu as administrator."); - return true; + break; default: buttons = QMessageBox::Ok; QMessageBox::critical(parent, tr("Create Shortcut"), tr("Failed to create a shortcut to %1").arg(game_title), buttons); - return true; + break; } - - return true; + return false; } bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, @@ -3058,7 +3050,7 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.") .arg(QString::fromStdString(out_icon_path.string())), QMessageBox::StandardButton::Ok); - out_icon_path = ""; // Reset path + out_icon_path.clear(); return false; } @@ -3165,7 +3157,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga arguments = "-f " + arguments; } const std::string comment = - tr("Start %1 with the yuzu Emulator").arg(QString::fromStdString(game_title)).toStdString(); + tr("Start %1 with the yuzu Emulator").arg(qt_game_title).toStdString(); const std::string categories = "Game;Emulator;Qt;"; const std::string keywords = "Switch;Nintendo;"; -- cgit v1.2.3 From de0b35b97456313498785facccad5980cea737f7 Mon Sep 17 00:00:00 2001 From: boludoz Date: Mon, 16 Oct 2023 16:54:51 -0300 Subject: Comment using fmt instead qt. --- src/yuzu/main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 82b38fc07..54b36552d 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -3156,8 +3156,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, qt_game_title)) { arguments = "-f " + arguments; } - const std::string comment = - tr("Start %1 with the yuzu Emulator").arg(qt_game_title).toStdString(); + const std::string comment = fmt::format("Start {:s} with the yuzu Emulator", game_title); const std::string categories = "Game;Emulator;Qt;"; const std::string keywords = "Switch;Nintendo;"; -- cgit v1.2.3 From 1ae0f0f3f64446b3128da0f1b1151d95739c9a6e Mon Sep 17 00:00:00 2001 From: boludoz Date: Mon, 16 Oct 2023 18:59:21 -0300 Subject: shortcut_stream.close(); fixed --- src/yuzu/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 54b36552d..e49de921c 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2922,10 +2922,10 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, } else { LOG_ERROR(Frontend, "Failed to create shortcut"); } + shortcut_stream.close(); } catch (const std::exception& e) { LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); } - shortcut_stream.close(); return false; #elif defined(_WIN32) // Windows HRESULT hr = CoInitialize(NULL); -- cgit v1.2.3 From 1afe6d51eed4a420bb7289955333a2bb10c06b99 Mon Sep 17 00:00:00 2001 From: boludoz Date: Mon, 16 Oct 2023 23:42:45 -0300 Subject: More @liamwhite suggestions applied. --- src/yuzu/main.cpp | 200 ++++++++++++++++++++++++------------------------------ 1 file changed, 87 insertions(+), 113 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index e49de921c..75fbd042a 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2845,7 +2845,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::filesystem::path& icon_path, const std::filesystem::path& command, const std::string& arguments, const std::string& categories, - const std::string& keywords, const std::string& name) { + const std::string& keywords, const std::string& name) try { // Copy characters if they are not illegal in Windows filenames std::string filename = ""; @@ -2869,145 +2869,120 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, #if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD // Reference for the desktop file template: // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html - try { - // Plus 'Type' is required - if (name.empty()) { - LOG_ERROR(Frontend, "Name is empty"); - return false; - } - - // Append .desktop extension - shortcut_path_full += ".desktop"; - - // Create shortcut file - std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); - - if (shortcut_stream.is_open()) { - - fmt::print(shortcut_stream, "[Desktop Entry]\n"); - fmt::print(shortcut_stream, "Type=Application\n"); - fmt::print(shortcut_stream, "Version=1.0\n"); - fmt::print(shortcut_stream, "Name={}\n", name); - - if (!comment.empty()) { - fmt::print(shortcut_stream, "Comment={}\n", comment); - } - - if (std::filesystem::is_regular_file(icon_path)) { - fmt::print(shortcut_stream, "Icon={}\n", icon_path.string()); - } - - fmt::print(shortcut_stream, "TryExec={}\n", command.string()); - fmt::print(shortcut_stream, "Exec={}", command.string()); - - if (!arguments.empty()) { - fmt::print(shortcut_stream, " {}", arguments); - } - - fmt::print(shortcut_stream, "\n"); + // Plus 'Type' is required + if (name.empty()) { + LOG_ERROR(Frontend, "Name is empty"); + return false; + } - if (!categories.empty()) { - fmt::print(shortcut_stream, "Categories={}\n", categories); - } + // Append .desktop extension + shortcut_path_full += ".desktop"; - if (!keywords.empty()) { - fmt::print(shortcut_stream, "Keywords={}\n", keywords); - } + // Create shortcut file + std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); + if (!shortcut_stream.is_open()) { + LOG_ERROR(Frontend, "Failed to create shortcut"); + return false; + } - // Flush and close file - shortcut_stream.flush(); - shortcut_stream.close(); - return true; - } else { - LOG_ERROR(Frontend, "Failed to create shortcut"); - } - shortcut_stream.close(); - } catch (const std::exception& e) { - LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); + fmt::print(shortcut_stream, "[Desktop Entry]\n"); + fmt::print(shortcut_stream, "Type=Application\n"); + fmt::print(shortcut_stream, "Version=1.0\n"); + fmt::print(shortcut_stream, "Name={}\n", name); + if (!comment.empty()) { + fmt::print(shortcut_stream, "Comment={}\n", comment); } - return false; + if (std::filesystem::is_regular_file(icon_path)) { + fmt::print(shortcut_stream, "Icon={}\n", icon_path.string()); + } + fmt::print(shortcut_stream, "TryExec={}\n", command.string()); + fmt::print(shortcut_stream, "Exec={}", command.string()); + if (!arguments.empty()) { + fmt::print(shortcut_stream, " {}", arguments); + } + fmt::print(shortcut_stream, "\n"); + if (!categories.empty()) { + fmt::print(shortcut_stream, "Categories={}\n", categories); + } + if (!keywords.empty()) { + fmt::print(shortcut_stream, "Keywords={}\n", keywords); + } + return true; #elif defined(_WIN32) // Windows HRESULT hr = CoInitialize(NULL); - if (SUCCEEDED(hr)) { - - IShellLinkW* ps1 = nullptr; - IPersistFile* persist_file = nullptr; - - SCOPE_EXIT({ - if (persist_file != nullptr) { - persist_file->Release(); - } - if (ps1 != nullptr) { - ps1->Release(); - } - - CoUninitialize(); - }); - - HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - IID_IShellLinkW, (void**)&ps1); - - std::wstring wshortcut_path_full = - Common::UTF8ToUTF16W((shortcut_path_full).string() + ".lnk"); - std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string()); - std::wstring wcommand = Common::UTF8ToUTF16W(command.string()); - std::wstring warguments = Common::UTF8ToUTF16W(arguments); - std::wstring wcomment = Common::UTF8ToUTF16W(comment); + if (FAILED(hr)) { + LOG_ERROR(Frontend, "CoInitialize failed"); + return false; + } - if (SUCCEEDED(hres)) { - hres = ps1->SetPath(wcommand.data()); + IShellLinkW* ps1 = nullptr; + IPersistFile* persist_file = nullptr; - if (SUCCEEDED(hres) && !arguments.empty()) { - hres = ps1->SetArguments(warguments.data()); - } - - if (SUCCEEDED(hres) && !comment.empty()) { - hres = ps1->SetDescription(wcomment.data()); - } + SCOPE_EXIT({ + if (persist_file != nullptr) { + persist_file->Release(); + } + if (ps1 != nullptr) { + ps1->Release(); + } - if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) { - hres = ps1->SetIconLocation(wicon_path.data(), 0); - } + CoUninitialize(); + }); - if (SUCCEEDED(hres)) { - hres = ps1->QueryInterface(IID_IPersistFile, (void**)&persist_file); - } + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, + (void**)&ps1); - if (SUCCEEDED(hres) && persist_file != nullptr) { - hres = persist_file->Save(wshortcut_path_full.data(), TRUE); - if (SUCCEEDED(hres)) { - return true; - } else { - LOG_ERROR(Frontend, "Failed to create shortcut"); - } - } - } else { - LOG_ERROR(Frontend, "Failed to create CoCreateInstance"); - } + if (SUCCEEDED(hres)) { + hres = ps1->SetPath(Common::UTF8ToUTF16W(command.string()).data()); + } else { + LOG_ERROR(Frontend, "Failed to create CoCreateInstance"); + return false; + } + if (SUCCEEDED(hres) && !arguments.empty()) { + hres = ps1->SetArguments(Common::UTF8ToUTF16W(arguments).data()); } + if (SUCCEEDED(hres) && !comment.empty()) { + hres = ps1->SetDescription(Common::UTF8ToUTF16W(comment).data()); + } + if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) { + hres = ps1->SetIconLocation(Common::UTF8ToUTF16W(icon_path.string()).data(), 0); + } + if (SUCCEEDED(hres)) { + hres = ps1->QueryInterface(IID_IPersistFile, (void**)&persist_file); + } + if (SUCCEEDED(hres) && persist_file != nullptr) { + hres = persist_file->Save( + Common::UTF8ToUTF16W((shortcut_path_full).string() + ".lnk").data(), TRUE); + } + if (SUCCEEDED(hres)) { + return true; + } + LOG_ERROR(Frontend, "Failed to create shortcut"); return false; #else // Unsupported platform return false; #endif +} catch (const std::exception& e) { + LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); + return false; } // Messages in pre-defined message boxes for less code spaghetti bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) { - QMessageBox::StandardButtons buttons; - int result = 0; + QMessageBox::StandardButtons buttons; switch (imsg) { case GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES: buttons = QMessageBox::Yes | QMessageBox::No; result = QMessageBox::information(parent, tr("Create Shortcut"), tr("Do you want to launch the game in fullscreen?"), buttons); - return (result == QMessageBox::Yes); + return result == QMessageBox::Yes; case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS: QMessageBox::information(parent, tr("Create Shortcut"), tr("Successfully created a shortcut to %1").arg(game_title)); - break; + return false; case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING: buttons = QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel; result = @@ -3015,20 +2990,19 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt tr("This will create a shortcut to the current AppImage. This may " "not work well if you update. Continue?"), buttons); - return (result == QMessageBox::Ok); + return result == QMessageBox::Ok; case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN: buttons = QMessageBox::Ok; QMessageBox::critical(parent, tr("Create Shortcut"), tr("Cannot create shortcut in Apps. Restart yuzu as administrator."), buttons); - break; + return false; default: buttons = QMessageBox::Ok; QMessageBox::critical(parent, tr("Create Shortcut"), tr("Failed to create a shortcut to %1").arg(game_title), buttons); - break; + return false; } - return false; } bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, -- cgit v1.2.3 From fc4b45ebd344a3e3d571b8516e73cd9afe824a9b Mon Sep 17 00:00:00 2001 From: boludoz Date: Mon, 16 Oct 2023 23:50:09 -0300 Subject: Moved check. --- src/yuzu/main.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 75fbd042a..0e0d7ef0e 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2847,6 +2847,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& arguments, const std::string& categories, const std::string& keywords, const std::string& name) try { +#if defined(__linux__) || defined(__FreeBSD__) || defined(_WIN32) // Linux, FreeBSD and Windows + // Plus 'name' is required + if (name.empty()) { + LOG_ERROR(Frontend, "Name is empty"); + return false; + } + // Copy characters if they are not illegal in Windows filenames std::string filename = ""; const std::string illegal_chars = "<>:\"/\\|?*"; @@ -2865,17 +2872,12 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, } std::filesystem::path shortcut_path_full = shortcut_path / filename; +#endif #if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD // Reference for the desktop file template: // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html - // Plus 'Type' is required - if (name.empty()) { - LOG_ERROR(Frontend, "Name is empty"); - return false; - } - // Append .desktop extension shortcut_path_full += ".desktop"; -- cgit v1.2.3 From 9908434c14d68faa7fde933258aafd7da15b3b3b Mon Sep 17 00:00:00 2001 From: boludoz Date: Tue, 17 Oct 2023 02:57:35 -0300 Subject: Final refactorization --- src/yuzu/main.cpp | 131 +++++++++++++++++++----------------------------------- 1 file changed, 45 insertions(+), 86 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 0e0d7ef0e..01b64e165 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2846,48 +2846,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::filesystem::path& command, const std::string& arguments, const std::string& categories, const std::string& keywords, const std::string& name) try { - -#if defined(__linux__) || defined(__FreeBSD__) || defined(_WIN32) // Linux, FreeBSD and Windows - // Plus 'name' is required - if (name.empty()) { - LOG_ERROR(Frontend, "Name is empty"); - return false; - } - - // Copy characters if they are not illegal in Windows filenames - std::string filename = ""; - const std::string illegal_chars = "<>:\"/\\|?*"; - filename.reserve(name.size()); - std::copy_if(name.begin(), name.end(), std::back_inserter(filename), - [&illegal_chars](char c) { return illegal_chars.find(c) == std::string::npos; }); - - if (filename.empty()) { - LOG_ERROR(Frontend, "Filename is empty"); - return false; - } - - if (!std::filesystem::is_regular_file(command)) { - LOG_ERROR(Frontend, "Command is not a regular file"); - return false; - } - - std::filesystem::path shortcut_path_full = shortcut_path / filename; -#endif - #if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD - // Reference for the desktop file template: - // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html - - // Append .desktop extension - shortcut_path_full += ".desktop"; - - // Create shortcut file + std::filesystem::path shortcut_path_full = shortcut_path / (name + ".desktop"); std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); if (!shortcut_stream.is_open()) { LOG_ERROR(Frontend, "Failed to create shortcut"); return false; } - fmt::print(shortcut_stream, "[Desktop Entry]\n"); fmt::print(shortcut_stream, "Type=Application\n"); fmt::print(shortcut_stream, "Version=1.0\n"); @@ -2899,11 +2864,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, fmt::print(shortcut_stream, "Icon={}\n", icon_path.string()); } fmt::print(shortcut_stream, "TryExec={}\n", command.string()); - fmt::print(shortcut_stream, "Exec={}", command.string()); - if (!arguments.empty()) { - fmt::print(shortcut_stream, " {}", arguments); - } - fmt::print(shortcut_stream, "\n"); + fmt::print(shortcut_stream, "Exec={} {}\n", command.string(), arguments); if (!categories.empty()) { fmt::print(shortcut_stream, "Categories={}\n", categories); } @@ -2912,15 +2873,14 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, } return true; #elif defined(_WIN32) // Windows - HRESULT hr = CoInitialize(NULL); + HRESULT hr = CoInitialize(nullptr); if (FAILED(hr)) { LOG_ERROR(Frontend, "CoInitialize failed"); return false; } - + SCOPE_EXIT({ CoUninitialize(); }); IShellLinkW* ps1 = nullptr; IPersistFile* persist_file = nullptr; - SCOPE_EXIT({ if (persist_file != nullptr) { persist_file->Release(); @@ -2928,40 +2888,50 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, if (ps1 != nullptr) { ps1->Release(); } - - CoUninitialize(); }); - - HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, - (void**)&ps1); - - if (SUCCEEDED(hres)) { - hres = ps1->SetPath(Common::UTF8ToUTF16W(command.string()).data()); - } else { - LOG_ERROR(Frontend, "Failed to create CoCreateInstance"); + HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW, + reinterpret_cast(&ps1)); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to create IShellLinkW instance"); return false; } - if (SUCCEEDED(hres) && !arguments.empty()) { + hres = ps1->SetPath(command.c_str()); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to set path"); + return false; + } + if (!arguments.empty()) { hres = ps1->SetArguments(Common::UTF8ToUTF16W(arguments).data()); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to set arguments"); + return false; + } } - if (SUCCEEDED(hres) && !comment.empty()) { + if (!comment.empty()) { hres = ps1->SetDescription(Common::UTF8ToUTF16W(comment).data()); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to set description"); + return false; + } } - if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) { - hres = ps1->SetIconLocation(Common::UTF8ToUTF16W(icon_path.string()).data(), 0); - } - if (SUCCEEDED(hres)) { - hres = ps1->QueryInterface(IID_IPersistFile, (void**)&persist_file); + if (std::filesystem::is_regular_file(icon_path)) { + hres = ps1->SetIconLocation(icon_path.c_str(), 0); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to set icon location"); + return false; + } } - if (SUCCEEDED(hres) && persist_file != nullptr) { - hres = persist_file->Save( - Common::UTF8ToUTF16W((shortcut_path_full).string() + ".lnk").data(), TRUE); + hres = ps1->QueryInterface(IID_IPersistFile, reinterpret_cast(&persist_file)); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to get IPersistFile interface"); + return false; } - if (SUCCEEDED(hres)) { - return true; + hres = persist_file->Save(std::filesystem::path{shortcut_path / (name + ".lnk")}.c_str(), TRUE); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to save shortcut"); + return false; } - LOG_ERROR(Frontend, "Failed to create shortcut"); - return false; + return true; #else // Unsupported platform return false; #endif @@ -2969,7 +2939,6 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); return false; } - // Messages in pre-defined message boxes for less code spaghetti bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) { int result = 0; @@ -3009,7 +2978,6 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, std::filesystem::path& out_icon_path) { - // Get path to Yuzu icons directory & icon extension std::string ico_extension = "png"; #if defined(_WIN32) @@ -3038,20 +3006,16 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path, GameListShortcutTarget target) { - std::string game_title; QString qt_game_title; std::filesystem::path out_icon_path; - // Get path to yuzu executable const QStringList args = QApplication::arguments(); std::filesystem::path yuzu_command = args[0].toStdString(); - // If relative path, make it an absolute path if (yuzu_command.c_str()[0] == '.') { yuzu_command = Common::FS::GetCurrentDir() / yuzu_command; } - // Shortcut path std::filesystem::path shortcut_path{}; if (target == GameListShortcutTarget::Desktop) { @@ -3061,7 +3025,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString(); } - // Icon path and title if (std::filesystem::exists(shortcut_path)) { // Get title from game file @@ -3070,17 +3033,20 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga const auto control = pm.GetControlMetadata(); const auto loader = Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read)); - game_title = fmt::format("{:016X}", program_id); - if (control.first != nullptr) { game_title = control.first->GetApplicationName(); } else { loader->ReadTitle(game_title); } - + // Delete illegal characters from title + const std::string illegal_chars = "<>:\"/\\|?*."; + for (auto it = game_title.rbegin(); it != game_title.rend(); ++it) { + if (illegal_chars.find(*it) != std::string::npos) { + game_title.erase(it.base() - 1); + } + } qt_game_title = QString::fromStdString(game_title); - // Get icon from game file std::vector icon_image_file{}; if (control.second != nullptr) { @@ -3088,23 +3054,19 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) { LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path); } - QImage icon_data = QImage::fromData(icon_image_file.data(), static_cast(icon_image_file.size())); - if (GMainWindow::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) { if (!SaveIconToFile(out_icon_path, icon_data)) { LOG_ERROR(Frontend, "Could not write icon to file"); } } - } else { GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, qt_game_title); LOG_ERROR(Frontend, "Invalid shortcut target"); return; } - #if defined(_WIN32) if (!IsUserAnAdmin() && target == GameListShortcutTarget::Applications) { GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN, @@ -3125,7 +3087,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga UISettings::values.shortcut_already_warned = true; } #endif // __linux__ - // Create shortcut std::string arguments = fmt::format("-g \"{:s}\"", game_path); if (GMainWindow::CreateShortcutMessagesGUI( @@ -3142,7 +3103,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga qt_game_title); return; } - GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, qt_game_title); } @@ -4177,7 +4137,6 @@ void GMainWindow::OnLoadAmiibo() { bool GMainWindow::question(QWidget* parent, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - QMessageBox* box_dialog = new QMessageBox(parent); box_dialog->setWindowTitle(title); box_dialog->setText(text); -- cgit v1.2.3 From 2a7edda70ac7bfcce6a830c814a6b8cd559b8c03 Mon Sep 17 00:00:00 2001 From: boludoz Date: Wed, 18 Oct 2023 01:20:46 -0300 Subject: Deleted admin requisite (maybe it was another mistake). --- src/yuzu/main.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 01b64e165..37f1c0bc4 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -3067,13 +3067,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga LOG_ERROR(Frontend, "Invalid shortcut target"); return; } -#if defined(_WIN32) - if (!IsUserAnAdmin() && target == GameListShortcutTarget::Applications) { - GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN, - qt_game_title); - return; - } -#elif defined(__linux__) +#if defined(__linux__) // Special case for AppImages // Warn once if we are making a shortcut to a volatile AppImage const std::string appimage_ending = -- cgit v1.2.3 From 4051bbbed7f0160a6565212affbbb24553a9b510 Mon Sep 17 00:00:00 2001 From: boludoz Date: Wed, 18 Oct 2023 01:26:50 -0300 Subject: Useless code removed related to admin privileges, if it is not an error we can add it later, that is what git is for. --- src/yuzu/main.cpp | 6 ------ src/yuzu/main.h | 1 - 2 files changed, 7 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 37f1c0bc4..73cd06478 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2962,12 +2962,6 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt "not work well if you update. Continue?"), buttons); return result == QMessageBox::Ok; - case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN: - buttons = QMessageBox::Ok; - QMessageBox::critical(parent, tr("Create Shortcut"), - tr("Cannot create shortcut in Apps. Restart yuzu as administrator."), - buttons); - return false; default: buttons = QMessageBox::Ok; QMessageBox::critical(parent, tr("Create Shortcut"), diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 41902cc8d..d203e5301 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -157,7 +157,6 @@ class GMainWindow : public QMainWindow { CREATE_SHORTCUT_MSGBOX_SUCCESS, CREATE_SHORTCUT_MSGBOX_ERROR, CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING, - CREATE_SHORTCUT_MSGBOX_ADMIN, }; public: -- cgit v1.2.3 From ac6290bea76e9719ef7806dab7f92ab53fdd27d0 Mon Sep 17 00:00:00 2001 From: boludoz Date: Wed, 18 Oct 2023 02:35:23 -0300 Subject: TODO: Implement shortcut creation for Apple. --- src/yuzu/game_list.cpp | 6 ++++++ src/yuzu/main.cpp | 8 ++++++-- src/yuzu/main.h | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index fbe099661..90433e245 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -564,10 +564,13 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri QAction* verify_integrity = context_menu.addAction(tr("Verify Integrity")); QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard")); QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry")); +// TODO: Implement shortcut creation for macOS +#if !defined(__APPLE__) QMenu* shortcut_menu = context_menu.addMenu(tr("Create Shortcut")); QAction* create_desktop_shortcut = shortcut_menu->addAction(tr("Add to Desktop")); QAction* create_applications_menu_shortcut = shortcut_menu->addAction(tr("Add to Applications Menu")); +#endif context_menu.addSeparator(); QAction* properties = context_menu.addAction(tr("Properties")); @@ -642,12 +645,15 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri connect(navigate_to_gamedb_entry, &QAction::triggered, [this, program_id]() { emit NavigateToGamedbEntryRequested(program_id, compatibility_list); }); +// TODO: Implement shortcut creation for macOS +#if !defined(__APPLE__) connect(create_desktop_shortcut, &QAction::triggered, [this, program_id, path]() { emit CreateShortcut(program_id, path, GameListShortcutTarget::Desktop); }); connect(create_applications_menu_shortcut, &QAction::triggered, [this, program_id, path]() { emit CreateShortcut(program_id, path, GameListShortcutTarget::Applications); }); +#endif connect(properties, &QAction::triggered, [this, path]() { emit OpenPerGameGeneralRequested(path); }); }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 73cd06478..ec3eb7536 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2839,7 +2839,8 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id, QDesktopServices::openUrl(QUrl(QStringLiteral("https://yuzu-emu.org/game/") + directory)); } - +// TODO: Implement shortcut creation for macOS +#if !defined(__APPLE__) bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment, const std::filesystem::path& icon_path, @@ -2997,9 +2998,11 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension)); return true; } - +#endif // !defined(__APPLE__) void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path, GameListShortcutTarget target) { +// TODO: Implement shortcut creation for macOS +#if !defined(__APPLE__) std::string game_title; QString qt_game_title; std::filesystem::path out_icon_path; @@ -3093,6 +3096,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga } GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, qt_game_title); +#endif } void GMainWindow::OnGameListOpenDirectory(const QString& directory) { diff --git a/src/yuzu/main.h b/src/yuzu/main.h index d203e5301..7a1a97f33 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -441,6 +441,8 @@ private: bool ConfirmShutdownGame(); QString GetTasStateDescription() const; +// TODO: Implement shortcut creation for macOS +#if !defined(__APPLE__) bool CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title); bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, std::filesystem::path& out_icon_path); @@ -449,6 +451,7 @@ private: const std::filesystem::path& command, const std::string& arguments, const std::string& categories, const std::string& keywords, const std::string& name); +#endif /** * Mimic the behavior of QMessageBox::question but link controller navigation to the dialog * The only difference is that it returns a boolean. -- cgit v1.2.3 From ae2130470effa72c3ea1ffc045e9b6b2a77b23d3 Mon Sep 17 00:00:00 2001 From: boludoz Date: Wed, 18 Oct 2023 19:30:21 -0300 Subject: Reverted dirty code in main. --- src/yuzu/main.cpp | 8 ++------ src/yuzu/main.h | 3 --- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index ec3eb7536..73cd06478 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2839,8 +2839,7 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id, QDesktopServices::openUrl(QUrl(QStringLiteral("https://yuzu-emu.org/game/") + directory)); } -// TODO: Implement shortcut creation for macOS -#if !defined(__APPLE__) + bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment, const std::filesystem::path& icon_path, @@ -2998,11 +2997,9 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension)); return true; } -#endif // !defined(__APPLE__) + void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path, GameListShortcutTarget target) { -// TODO: Implement shortcut creation for macOS -#if !defined(__APPLE__) std::string game_title; QString qt_game_title; std::filesystem::path out_icon_path; @@ -3096,7 +3093,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga } GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, qt_game_title); -#endif } void GMainWindow::OnGameListOpenDirectory(const QString& directory) { diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 7a1a97f33..d203e5301 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -441,8 +441,6 @@ private: bool ConfirmShutdownGame(); QString GetTasStateDescription() const; -// TODO: Implement shortcut creation for macOS -#if !defined(__APPLE__) bool CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title); bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, std::filesystem::path& out_icon_path); @@ -451,7 +449,6 @@ private: const std::filesystem::path& command, const std::string& arguments, const std::string& categories, const std::string& keywords, const std::string& name); -#endif /** * Mimic the behavior of QMessageBox::question but link controller navigation to the dialog * The only difference is that it returns a boolean. -- cgit v1.2.3 From 6a7123826a426ed195257da24d75170bfc56f670 Mon Sep 17 00:00:00 2001 From: Liam Date: Wed, 25 Oct 2023 21:26:56 -0400 Subject: qt: remove duplicate exit confirmation setting --- src/yuzu/configuration/shared_translation.cpp | 1 - src/yuzu/main.cpp | 12 +++++++++--- src/yuzu/uisettings.h | 4 ---- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp index 3fe448f27..1434b1a56 100644 --- a/src/yuzu/configuration/shared_translation.cpp +++ b/src/yuzu/configuration/shared_translation.cpp @@ -156,7 +156,6 @@ std::unique_ptr InitializeTranslations(QWidget* parent) { // Ui General INSERT(UISettings, select_user_on_boot, "Prompt for user on game boot", ""); INSERT(UISettings, pause_when_in_background, "Pause emulation when in background", ""); - INSERT(UISettings, confirm_before_closing, "Confirm exit while emulation is running", ""); INSERT(UISettings, confirm_before_stopping, "Confirm before stopping emulation", ""); INSERT(UISettings, hide_mouse, "Hide mouse on inactivity", ""); INSERT(UISettings, controller_applet_disabled, "Disable controller applet", ""); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 0df163029..2b430c40a 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2174,6 +2174,7 @@ void GMainWindow::ShutdownGame() { return; } + play_time_manager->Stop(); OnShutdownBegin(); OnEmulationStopTimeExpired(); OnEmulationStopped(); @@ -3484,7 +3485,7 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) { } void GMainWindow::OnExit() { - OnStopGame(); + ShutdownGame(); } void GMainWindow::OnSaveConfig() { @@ -4847,7 +4848,12 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe } bool GMainWindow::ConfirmClose() { - if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) { + if (emu_thread == nullptr || + UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Never) { + return true; + } + if (!system->GetExitLocked() && + UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Based_On_Game) { return true; } const auto text = tr("Are you sure you want to close yuzu?"); @@ -4952,7 +4958,7 @@ bool GMainWindow::ConfirmChangeGame() { } bool GMainWindow::ConfirmForceLockedExit() { - if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) { + if (emu_thread == nullptr) { return true; } const auto text = tr("The currently running application has requested yuzu to not exit.\n\n" diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index b62ff620c..77d992c54 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -93,10 +93,6 @@ struct Values { Setting show_filter_bar{linkage, true, "showFilterBar", Category::Ui}; Setting show_status_bar{linkage, true, "showStatusBar", Category::Ui}; - Setting confirm_before_closing{ - linkage, true, "confirmClose", Category::UiGeneral, Settings::Specialization::Default, - true, true}; - SwitchableSetting confirm_before_stopping{linkage, ConfirmStop::Ask_Always, "confirmStop", -- cgit v1.2.3 From b0c6bf497a1eabec14c116b710dcc757e77455bf Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 31 Oct 2023 20:11:14 -0400 Subject: romfs: fix extraction of single-directory root --- src/yuzu/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 0df163029..db9da6dc8 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2737,7 +2737,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa return; } - const auto extracted = FileSys::ExtractRomFS(romfs, FileSys::RomFSExtractionType::Full); + const auto extracted = FileSys::ExtractRomFS(romfs); if (extracted == nullptr) { failed(); return; -- cgit v1.2.3 From 90aa937593e53a5d5e070fb623b228578b0b225f Mon Sep 17 00:00:00 2001 From: Kelebek1 Date: Sat, 4 Nov 2023 18:25:40 +0000 Subject: Convert files to LF eol --- src/yuzu/configuration/config.h | 2 +- src/yuzu/configuration/configure_camera.h | 2 +- src/yuzu/configuration/configure_input.h | 2 +- src/yuzu/configuration/configure_input_player.h | 2 +- src/yuzu/configuration/configure_per_game.h | 2 +- src/yuzu/configuration/configure_ringcon.h | 2 +- src/yuzu/configuration/configure_tas.h | 2 +- src/yuzu/configuration/configure_touchscreen_advanced.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 74ec4f771..1589ba057 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/yuzu/configuration/configure_camera.h b/src/yuzu/configuration/configure_camera.h index 9a90512b3..3d822da7b 100644 --- a/src/yuzu/configuration/configure_camera.h +++ b/src/yuzu/configuration/configure_camera.h @@ -1,4 +1,4 @@ -// Text : Copyright 2022 yuzu Emulator Project +// Text : Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index 136cd3a0a..beb503dae 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2016 Citra Emulator Project +// SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index d3255d2b4..fda09e925 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2016 Citra Emulator Project +// SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index 1a727f32c..cc2513001 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/yuzu/configuration/configure_ringcon.h b/src/yuzu/configuration/configure_ringcon.h index b23c27906..6fd95e2b8 100644 --- a/src/yuzu/configuration/configure_ringcon.h +++ b/src/yuzu/configuration/configure_ringcon.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/yuzu/configuration/configure_tas.h b/src/yuzu/configuration/configure_tas.h index 4a6b0ba4e..a91891906 100644 --- a/src/yuzu/configuration/configure_tas.h +++ b/src/yuzu/configuration/configure_tas.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.h b/src/yuzu/configuration/configure_touchscreen_advanced.h index 034dc0d46..b6fdffdc8 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.h +++ b/src/yuzu/configuration/configure_touchscreen_advanced.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2016 Citra Emulator Project +// SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -- cgit v1.2.3 From f07484bc64e6c6f178f4891f1c86ebb23d14dbe7 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Sat, 4 Nov 2023 14:05:05 -0600 Subject: core: hid: Signal color updates --- src/yuzu/configuration/configure_input.cpp | 2 +- src/yuzu/configuration/configure_input_advanced.cpp | 8 ++++++-- src/yuzu/configuration/configure_input_advanced.h | 8 +++++++- 3 files changed, 14 insertions(+), 4 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 3dcad2701..02e23cce6 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -152,7 +152,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, connect(player_controllers[0], &ConfigureInputPlayer::HandheldStateChanged, [this](bool is_handheld) { UpdateDockedState(is_handheld); }); - advanced = new ConfigureInputAdvanced(this); + advanced = new ConfigureInputAdvanced(hid_core, this); ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); ui->tabAdvanced->layout()->addWidget(advanced); diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index 3cfd5d439..441cea3f6 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp @@ -4,11 +4,13 @@ #include #include "common/settings.h" #include "core/core.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" #include "ui_configure_input_advanced.h" #include "yuzu/configuration/configure_input_advanced.h" -ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) - : QWidget(parent), ui(std::make_unique()) { +ConfigureInputAdvanced::ConfigureInputAdvanced(Core::HID::HIDCore& hid_core_, QWidget* parent) + : QWidget(parent), ui(std::make_unique()), hid_core{hid_core_} { ui->setupUi(this); controllers_color_buttons = {{ @@ -123,6 +125,8 @@ void ConfigureInputAdvanced::ApplyConfiguration() { player.button_color_left = colors[1]; player.body_color_right = colors[2]; player.button_color_right = colors[3]; + + hid_core.GetEmulatedControllerByIndex(player_idx)->ReloadColorsFromSettings(); } Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked(); diff --git a/src/yuzu/configuration/configure_input_advanced.h b/src/yuzu/configuration/configure_input_advanced.h index fc1230284..41f822c4a 100644 --- a/src/yuzu/configuration/configure_input_advanced.h +++ b/src/yuzu/configuration/configure_input_advanced.h @@ -14,11 +14,15 @@ namespace Ui { class ConfigureInputAdvanced; } +namespace Core::HID { +class HIDCore; +} // namespace Core::HID + class ConfigureInputAdvanced : public QWidget { Q_OBJECT public: - explicit ConfigureInputAdvanced(QWidget* parent = nullptr); + explicit ConfigureInputAdvanced(Core::HID::HIDCore& hid_core_, QWidget* parent = nullptr); ~ConfigureInputAdvanced() override; void ApplyConfiguration(); @@ -44,4 +48,6 @@ private: std::array, 8> controllers_colors; std::array, 8> controllers_color_buttons; + + Core::HID::HIDCore& hid_core; }; -- cgit v1.2.3 From 4b8b223db2ed0f79ce81083128fe8085786877cc Mon Sep 17 00:00:00 2001 From: Franco M Date: Sun, 5 Nov 2023 00:39:43 +0000 Subject: modified: src/yuzu/main.cpp --- src/yuzu/main.cpp | 73 ++++++------------------------------------------------- 1 file changed, 7 insertions(+), 66 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index c8efd1917..6b6feb1e6 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "core/loader/nca.h" #include "core/tools/renderdoc.h" #ifdef __APPLE__ @@ -2856,6 +2857,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, LOG_ERROR(Frontend, "Failed to create shortcut"); return false; } + // TODO: Migrate fmt::print to std::print in futures STD C++ 23. fmt::print(shortcut_stream, "[Desktop Entry]\n"); fmt::print(shortcut_stream, "Type=Application\n"); fmt::print(shortcut_stream, "Version=1.0\n"); @@ -2983,7 +2985,6 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi #elif defined(__linux__) || defined(__FreeBSD__) out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; #endif - // Create icons directory if it doesn't exist if (!Common::FS::CreateDirs(out_icon_path)) { QMessageBox::critical( @@ -2996,8 +2997,8 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi } // Create icon file path - out_icon_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension) - : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension)); + out_icon_path /= (program_id == 0 ? std::format("yuzu-{}.{}", game_file_name, ico_extension) + : std::format("yuzu-{:016X}.{}", program_id, ico_extension)); return true; } @@ -3030,7 +3031,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga const auto control = pm.GetControlMetadata(); const auto loader = Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read)); - game_title = fmt::format("{:016X}", program_id); + game_title = std::format("{:016X}", program_id); if (control.first != nullptr) { game_title = control.first->GetApplicationName(); } else { @@ -3079,12 +3080,12 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga } #endif // __linux__ // Create shortcut - std::string arguments = fmt::format("-g \"{:s}\"", game_path); + std::string arguments = std::format("-g \"{:s}\"", game_path); if (GMainWindow::CreateShortcutMessagesGUI( this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, qt_game_title)) { arguments = "-f " + arguments; } - const std::string comment = fmt::format("Start {:s} with the yuzu Emulator", game_title); + const std::string comment = std::format("Start {:s} with the yuzu Emulator", game_title); const std::string categories = "Game;Emulator;Qt;"; const std::string keywords = "Switch;Nintendo;"; @@ -4090,66 +4091,6 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file } } -bool GMainWindow::CreateShortcut(const std::string& shortcut_path, const std::string& title, - const std::string& comment, const std::string& icon_path, - const std::string& command, const std::string& arguments, - const std::string& categories, const std::string& keywords) { -#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) - // This desktop file template was writing referencing - // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html - std::string shortcut_contents{}; - shortcut_contents.append("[Desktop Entry]\n"); - shortcut_contents.append("Type=Application\n"); - shortcut_contents.append("Version=1.0\n"); - shortcut_contents.append(fmt::format("Name={:s}\n", title)); - shortcut_contents.append(fmt::format("Comment={:s}\n", comment)); - shortcut_contents.append(fmt::format("Icon={:s}\n", icon_path)); - shortcut_contents.append(fmt::format("TryExec={:s}\n", command)); - shortcut_contents.append(fmt::format("Exec={:s} {:s}\n", command, arguments)); - shortcut_contents.append(fmt::format("Categories={:s}\n", categories)); - shortcut_contents.append(fmt::format("Keywords={:s}\n", keywords)); - - std::ofstream shortcut_stream(shortcut_path); - if (!shortcut_stream.is_open()) { - LOG_WARNING(Common, "Failed to create file {:s}", shortcut_path); - return false; - } - shortcut_stream << shortcut_contents; - shortcut_stream.close(); - - return true; -#elif defined(WIN32) - IShellLinkW* shell_link; - auto hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, - (void**)&shell_link); - if (FAILED(hres)) { - return false; - } - shell_link->SetPath( - Common::UTF8ToUTF16W(command).data()); // Path to the object we are referring to - shell_link->SetArguments(Common::UTF8ToUTF16W(arguments).data()); - shell_link->SetDescription(Common::UTF8ToUTF16W(comment).data()); - shell_link->SetIconLocation(Common::UTF8ToUTF16W(icon_path).data(), 0); - - IPersistFile* persist_file; - hres = shell_link->QueryInterface(IID_IPersistFile, (void**)&persist_file); - if (FAILED(hres)) { - return false; - } - - hres = persist_file->Save(Common::UTF8ToUTF16W(shortcut_path).data(), TRUE); - if (FAILED(hres)) { - return false; - } - - persist_file->Release(); - shell_link->Release(); - - return true; -#endif - return false; -} - void GMainWindow::OnLoadAmiibo() { if (emu_thread == nullptr || !emu_thread->IsRunning()) { return; -- cgit v1.2.3 From 5323d9f6b3cba683522d90fbd9f28b6e11b9348b Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 5 Nov 2023 09:00:45 -0600 Subject: service: acc: Ensure proper profile size --- src/yuzu/configuration/configure_profile_manager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index a47089988..6d2219bf5 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -306,10 +306,10 @@ void ConfigureProfileManager::SetUserImage() { return; } - // Some games crash when the profile image is too big. Resize any image bigger than 256x256 + // Profile image must be 256x256 QImage image(image_path); - if (image.width() > 256 || image.height() > 256) { - image = image.scaled(256, 256, Qt::KeepAspectRatio); + if (image.width() != 256 || image.height() != 256) { + image = image.scaled(256, 256, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); if (!image.save(image_path)) { QMessageBox::warning(this, tr("Error resizing user image"), tr("Unable to resize image")); -- cgit v1.2.3 From 507f360a81f6938a06643eab0df4dc24f3e89307 Mon Sep 17 00:00:00 2001 From: german77 Date: Fri, 3 Nov 2023 23:43:41 -0600 Subject: yuzu: Only store games in the recently played list --- src/yuzu/main.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index db9da6dc8..d1a53614c 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1908,7 +1908,10 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) { void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index, StartGameType type, AmLaunchType launch_type) { LOG_INFO(Frontend, "yuzu starting..."); - StoreRecentFile(filename); // Put the filename on top of the list + + if (program_id > static_cast(Service::AM::Applets::AppletProgramId::MaxProgramId)) { + StoreRecentFile(filename); // Put the filename on top of the list + } // Save configurations UpdateUISettings(); @@ -4272,7 +4275,7 @@ void GMainWindow::OnToggleStatusBar() { } void GMainWindow::OnAlbum() { - constexpr u64 AlbumId = 0x010000000000100Dull; + constexpr u64 AlbumId = static_cast(Service::AM::Applets::AppletProgramId::PhotoViewer); auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); if (!bis_system) { QMessageBox::warning(this, tr("No firmware available"), @@ -4295,7 +4298,7 @@ void GMainWindow::OnAlbum() { } void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { - constexpr u64 CabinetId = 0x0100000000001002ull; + constexpr u64 CabinetId = static_cast(Service::AM::Applets::AppletProgramId::Cabinet); auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); if (!bis_system) { QMessageBox::warning(this, tr("No firmware available"), @@ -4319,7 +4322,7 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { } void GMainWindow::OnMiiEdit() { - constexpr u64 MiiEditId = 0x0100000000001009ull; + constexpr u64 MiiEditId = static_cast(Service::AM::Applets::AppletProgramId::MiiEdit); auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); if (!bis_system) { QMessageBox::warning(this, tr("No firmware available"), -- cgit v1.2.3 From 8d0d0e1c7a95858dc5eaffe0eb0484815b491d9d Mon Sep 17 00:00:00 2001 From: Franco M Date: Tue, 7 Nov 2023 02:32:19 +0000 Subject: Fixed clang --- src/yuzu/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 6b6feb1e6..2402ea6f5 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -4,13 +4,14 @@ #include #include #include +#include #include #include #include #include -#include #include "core/loader/nca.h" #include "core/tools/renderdoc.h" + #ifdef __APPLE__ #include // for chdir #endif @@ -5331,4 +5332,4 @@ int main(int argc, char* argv[]) { int result = app.exec(); detached_tasks.WaitForAllTasks(); return result; -} +} \ No newline at end of file -- cgit v1.2.3 From edce713fc92881bea1f6bb049b06efb2e86d81fa Mon Sep 17 00:00:00 2001 From: Lucas Reis Date: Tue, 7 Nov 2023 22:47:02 -0400 Subject: Allocate resources for test window before getting system info --- src/yuzu/vk_device_info.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/yuzu') diff --git a/src/yuzu/vk_device_info.cpp b/src/yuzu/vk_device_info.cpp index 92f10d315..ab0d39c25 100644 --- a/src/yuzu/vk_device_info.cpp +++ b/src/yuzu/vk_device_info.cpp @@ -31,6 +31,7 @@ void PopulateRecords(std::vector& records, QWindow* window) try { // Create a test window with a Vulkan surface type for checking present modes. QWindow test_window(window); test_window.setSurfaceType(QWindow::VulkanSurface); + test_window.create(); auto wsi = QtCommon::GetWindowSystemInfo(&test_window); vk::InstanceDispatch dld; -- cgit v1.2.3 From 71cdfa6ad576c721227595cac8170fb9095f23e3 Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Wed, 8 Nov 2023 11:25:30 -0500 Subject: shared_translation: Call tr for each string Qt can't parse tr called within a macro, so we must call it on each string. shared_translation: Remove redundant include --- src/yuzu/configuration/shared_translation.cpp | 517 +++++++++++++------------- 1 file changed, 268 insertions(+), 249 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp index 1434b1a56..a7b5def32 100644 --- a/src/yuzu/configuration/shared_translation.cpp +++ b/src/yuzu/configuration/shared_translation.cpp @@ -1,17 +1,18 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/time_zone.h" #include "yuzu/configuration/shared_translation.h" #include #include #include #include +#include #include #include "common/settings.h" #include "common/settings_enums.h" #include "common/settings_setting.h" +#include "common/time_zone.h" #include "yuzu/uisettings.h" namespace ConfigurationShared { @@ -21,123 +22,135 @@ std::unique_ptr InitializeTranslations(QWidget* parent) { const auto& tr = [parent](const char* text) -> QString { return parent->tr(text); }; #define INSERT(SETTINGS, ID, NAME, TOOLTIP) \ - translations->insert(std::pair{SETTINGS::values.ID.Id(), std::pair{tr((NAME)), tr((TOOLTIP))}}) + translations->insert(std::pair{SETTINGS::values.ID.Id(), std::pair{(NAME), (TOOLTIP)}}) // A setting can be ignored by giving it a blank name // Audio - INSERT(Settings, sink_id, "Output Engine:", ""); - INSERT(Settings, audio_output_device_id, "Output Device:", ""); - INSERT(Settings, audio_input_device_id, "Input Device:", ""); - INSERT(Settings, audio_muted, "Mute audio", ""); - INSERT(Settings, volume, "Volume:", ""); - INSERT(Settings, dump_audio_commands, "", ""); - INSERT(UISettings, mute_when_in_background, "Mute audio when in background", ""); + INSERT(Settings, sink_id, tr("Output Engine:"), QStringLiteral()); + INSERT(Settings, audio_output_device_id, tr("Output Device:"), QStringLiteral()); + INSERT(Settings, audio_input_device_id, tr("Input Device:"), QStringLiteral()); + INSERT(Settings, audio_muted, tr("Mute audio"), QStringLiteral()); + INSERT(Settings, volume, tr("Volume:"), QStringLiteral()); + INSERT(Settings, dump_audio_commands, QStringLiteral(), QStringLiteral()); + INSERT(UISettings, mute_when_in_background, tr("Mute audio when in background"), + QStringLiteral()); // Core - INSERT(Settings, use_multi_core, "Multicore CPU Emulation", ""); - INSERT(Settings, memory_layout_mode, "Memory Layout", ""); - INSERT(Settings, use_speed_limit, "", ""); - INSERT(Settings, speed_limit, "Limit Speed Percent", ""); + INSERT(Settings, use_multi_core, tr("Multicore CPU Emulation"), QStringLiteral()); + INSERT(Settings, memory_layout_mode, tr("Memory Layout"), QStringLiteral()); + INSERT(Settings, use_speed_limit, QStringLiteral(), QStringLiteral()); + INSERT(Settings, speed_limit, tr("Limit Speed Percent"), QStringLiteral()); // Cpu - INSERT(Settings, cpu_accuracy, "Accuracy:", ""); + INSERT(Settings, cpu_accuracy, tr("Accuracy:"), QStringLiteral()); // Cpu Debug // Cpu Unsafe - INSERT(Settings, cpuopt_unsafe_unfuse_fma, - "Unfuse FMA (improve performance on CPUs without FMA)", - "This option improves speed by reducing accuracy of fused-multiply-add instructions on " - "CPUs without native FMA support."); - INSERT(Settings, cpuopt_unsafe_reduce_fp_error, "Faster FRSQRTE and FRECPE", - "This option improves the speed of some approximate floating-point functions by using " - "less accurate native approximations."); - INSERT(Settings, cpuopt_unsafe_ignore_standard_fpcr, "Faster ASIMD instructions (32 bits only)", - "This option improves the speed of 32 bits ASIMD floating-point functions by running " - "with incorrect rounding modes."); - INSERT(Settings, cpuopt_unsafe_inaccurate_nan, "Inaccurate NaN handling", - "This option improves speed by removing NaN checking. Please note this also reduces " - "accuracy of certain floating-point instructions."); INSERT( - Settings, cpuopt_unsafe_fastmem_check, "Disable address space checks", - "This option improves speed by eliminating a safety check before every memory read/write " - "in guest. Disabling it may allow a game to read/write the emulator's memory."); - INSERT(Settings, cpuopt_unsafe_ignore_global_monitor, "Ignore global monitor", - "This option improves speed by relying only on the semantics of cmpxchg to ensure " + Settings, cpuopt_unsafe_unfuse_fma, + tr("Unfuse FMA (improve performance on CPUs without FMA)"), + tr("This option improves speed by reducing accuracy of fused-multiply-add instructions on " + "CPUs without native FMA support.")); + INSERT( + Settings, cpuopt_unsafe_reduce_fp_error, tr("Faster FRSQRTE and FRECPE"), + tr("This option improves the speed of some approximate floating-point functions by using " + "less accurate native approximations.")); + INSERT(Settings, cpuopt_unsafe_ignore_standard_fpcr, + tr("Faster ASIMD instructions (32 bits only)"), + tr("This option improves the speed of 32 bits ASIMD floating-point functions by running " + "with incorrect rounding modes.")); + INSERT(Settings, cpuopt_unsafe_inaccurate_nan, tr("Inaccurate NaN handling"), + tr("This option improves speed by removing NaN checking. Please note this also reduces " + "accuracy of certain floating-point instructions.")); + INSERT(Settings, cpuopt_unsafe_fastmem_check, tr("Disable address space checks"), + tr("This option improves speed by eliminating a safety check before every memory " + "read/write " + "in guest. Disabling it may allow a game to read/write the emulator's memory.")); + INSERT( + Settings, cpuopt_unsafe_ignore_global_monitor, tr("Ignore global monitor"), + tr("This option improves speed by relying only on the semantics of cmpxchg to ensure " "safety of exclusive access instructions. Please note this may result in deadlocks and " - "other race conditions."); + "other race conditions.")); // Renderer - INSERT(Settings, renderer_backend, "API:", ""); - INSERT(Settings, vulkan_device, "Device:", ""); - INSERT(Settings, shader_backend, "Shader Backend:", ""); - INSERT(Settings, resolution_setup, "Resolution:", ""); - INSERT(Settings, scaling_filter, "Window Adapting Filter:", ""); - INSERT(Settings, fsr_sharpening_slider, "FSR Sharpness:", ""); - INSERT(Settings, anti_aliasing, "Anti-Aliasing Method:", ""); - INSERT(Settings, fullscreen_mode, "Fullscreen Mode:", ""); - INSERT(Settings, aspect_ratio, "Aspect Ratio:", ""); - INSERT(Settings, use_disk_shader_cache, "Use disk pipeline cache", ""); - INSERT(Settings, use_asynchronous_gpu_emulation, "Use asynchronous GPU emulation", ""); - INSERT(Settings, nvdec_emulation, "NVDEC emulation:", ""); - INSERT(Settings, accelerate_astc, "ASTC Decoding Method:", ""); - INSERT(Settings, astc_recompression, "ASTC Recompression Method:", ""); - INSERT(Settings, vsync_mode, "VSync Mode:", - "FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen " + INSERT(Settings, renderer_backend, tr("API:"), QStringLiteral()); + INSERT(Settings, vulkan_device, tr("Device:"), QStringLiteral()); + INSERT(Settings, shader_backend, tr("Shader Backend:"), QStringLiteral()); + INSERT(Settings, resolution_setup, tr("Resolution:"), QStringLiteral()); + INSERT(Settings, scaling_filter, tr("Window Adapting Filter:"), QStringLiteral()); + INSERT(Settings, fsr_sharpening_slider, tr("FSR Sharpness:"), QStringLiteral()); + INSERT(Settings, anti_aliasing, tr("Anti-Aliasing Method:"), QStringLiteral()); + INSERT(Settings, fullscreen_mode, tr("Fullscreen Mode:"), QStringLiteral()); + INSERT(Settings, aspect_ratio, tr("Aspect Ratio:"), QStringLiteral()); + INSERT(Settings, use_disk_shader_cache, tr("Use disk pipeline cache"), QStringLiteral()); + INSERT(Settings, use_asynchronous_gpu_emulation, tr("Use asynchronous GPU emulation"), + QStringLiteral()); + INSERT(Settings, nvdec_emulation, tr("NVDEC emulation:"), QStringLiteral()); + INSERT(Settings, accelerate_astc, tr("ASTC Decoding Method:"), QStringLiteral()); + INSERT(Settings, astc_recompression, tr("ASTC Recompression Method:"), QStringLiteral()); + INSERT( + Settings, vsync_mode, tr("VSync Mode:"), + tr("FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen " "refresh rate.\nFIFO Relaxed is similar to FIFO but allows tearing as it recovers from " "a slow down.\nMailbox can have lower latency than FIFO and does not tear but may drop " "frames.\nImmediate (no synchronization) just presents whatever is available and can " - "exhibit tearing."); - INSERT(Settings, bg_red, "", ""); - INSERT(Settings, bg_green, "", ""); - INSERT(Settings, bg_blue, "", ""); + "exhibit tearing.")); + INSERT(Settings, bg_red, QStringLiteral(), QStringLiteral()); + INSERT(Settings, bg_green, QStringLiteral(), QStringLiteral()); + INSERT(Settings, bg_blue, QStringLiteral(), QStringLiteral()); // Renderer (Advanced Graphics) - INSERT(Settings, async_presentation, "Enable asynchronous presentation (Vulkan only)", ""); - INSERT(Settings, renderer_force_max_clock, "Force maximum clocks (Vulkan only)", - "Runs work in the background while waiting for graphics commands to keep the GPU from " - "lowering its clock speed."); - INSERT(Settings, max_anisotropy, "Anisotropic Filtering:", ""); - INSERT(Settings, gpu_accuracy, "Accuracy Level:", ""); - INSERT(Settings, use_asynchronous_shaders, "Use asynchronous shader building (Hack)", - "Enables asynchronous shader compilation, which may reduce shader stutter. This feature " - "is experimental."); - INSERT(Settings, use_fast_gpu_time, "Use Fast GPU Time (Hack)", - "Enables Fast GPU Time. This option will force most games to run at their highest " - "native resolution."); - INSERT(Settings, use_vulkan_driver_pipeline_cache, "Use Vulkan pipeline cache", - "Enables GPU vendor-specific pipeline cache. This option can improve shader loading " - "time significantly in cases where the Vulkan driver does not store pipeline cache " - "files internally."); - INSERT(Settings, enable_compute_pipelines, "Enable Compute Pipelines (Intel Vulkan Only)", - "Enable compute pipelines, required by some games.\nThis setting only exists for Intel " + INSERT(Settings, async_presentation, tr("Enable asynchronous presentation (Vulkan only)"), + QStringLiteral()); + INSERT( + Settings, renderer_force_max_clock, tr("Force maximum clocks (Vulkan only)"), + tr("Runs work in the background while waiting for graphics commands to keep the GPU from " + "lowering its clock speed.")); + INSERT(Settings, max_anisotropy, tr("Anisotropic Filtering:"), QStringLiteral()); + INSERT(Settings, gpu_accuracy, tr("Accuracy Level:"), QStringLiteral()); + INSERT( + Settings, use_asynchronous_shaders, tr("Use asynchronous shader building (Hack)"), + tr("Enables asynchronous shader compilation, which may reduce shader stutter. This feature " + "is experimental.")); + INSERT(Settings, use_fast_gpu_time, tr("Use Fast GPU Time (Hack)"), + tr("Enables Fast GPU Time. This option will force most games to run at their highest " + "native resolution.")); + INSERT(Settings, use_vulkan_driver_pipeline_cache, tr("Use Vulkan pipeline cache"), + tr("Enables GPU vendor-specific pipeline cache. This option can improve shader loading " + "time significantly in cases where the Vulkan driver does not store pipeline cache " + "files internally.")); + INSERT( + Settings, enable_compute_pipelines, tr("Enable Compute Pipelines (Intel Vulkan Only)"), + tr("Enable compute pipelines, required by some games.\nThis setting only exists for Intel " "proprietary drivers, and may crash if enabled.\nCompute pipelines are always enabled " - "on all other drivers."); - INSERT(Settings, use_reactive_flushing, "Enable Reactive Flushing", - "Uses reactive flushing instead of predictive flushing, allowing more accurate memory " - "syncing."); - INSERT(Settings, use_video_framerate, "Sync to framerate of video playback", - "Run the game at normal speed during video playback, even when the framerate is " - "unlocked."); - INSERT(Settings, barrier_feedback_loops, "Barrier feedback loops", - "Improves rendering of transparency effects in specific games."); + "on all other drivers.")); + INSERT( + Settings, use_reactive_flushing, tr("Enable Reactive Flushing"), + tr("Uses reactive flushing instead of predictive flushing, allowing more accurate memory " + "syncing.")); + INSERT(Settings, use_video_framerate, tr("Sync to framerate of video playback"), + tr("Run the game at normal speed during video playback, even when the framerate is " + "unlocked.")); + INSERT(Settings, barrier_feedback_loops, tr("Barrier feedback loops"), + tr("Improves rendering of transparency effects in specific games.")); // Renderer (Debug) // System - INSERT(Settings, rng_seed, "RNG Seed", ""); - INSERT(Settings, rng_seed_enabled, "", ""); - INSERT(Settings, device_name, "Device Name", ""); - INSERT(Settings, custom_rtc, "Custom RTC", ""); - INSERT(Settings, custom_rtc_enabled, "", ""); - INSERT(Settings, language_index, - "Language:", "Note: this can be overridden when region setting is auto-select"); - INSERT(Settings, region_index, "Region:", ""); - INSERT(Settings, time_zone_index, "Time Zone:", ""); - INSERT(Settings, sound_index, "Sound Output Mode:", ""); - INSERT(Settings, use_docked_mode, "Console Mode:", ""); - INSERT(Settings, current_user, "", ""); + INSERT(Settings, rng_seed, tr("RNG Seed"), QStringLiteral()); + INSERT(Settings, rng_seed_enabled, QStringLiteral(), QStringLiteral()); + INSERT(Settings, device_name, tr("Device Name"), QStringLiteral()); + INSERT(Settings, custom_rtc, tr("Custom RTC"), QStringLiteral()); + INSERT(Settings, custom_rtc_enabled, QStringLiteral(), QStringLiteral()); + INSERT(Settings, language_index, tr("Language:"), + tr("Note: this can be overridden when region setting is auto-select")); + INSERT(Settings, region_index, tr("Region:"), QStringLiteral()); + INSERT(Settings, time_zone_index, tr("Time Zone:"), QStringLiteral()); + INSERT(Settings, sound_index, tr("Sound Output Mode:"), QStringLiteral()); + INSERT(Settings, use_docked_mode, tr("Console Mode:"), QStringLiteral()); + INSERT(Settings, current_user, QStringLiteral(), QStringLiteral()); // Controls @@ -154,11 +167,14 @@ std::unique_ptr InitializeTranslations(QWidget* parent) { // Ui // Ui General - INSERT(UISettings, select_user_on_boot, "Prompt for user on game boot", ""); - INSERT(UISettings, pause_when_in_background, "Pause emulation when in background", ""); - INSERT(UISettings, confirm_before_stopping, "Confirm before stopping emulation", ""); - INSERT(UISettings, hide_mouse, "Hide mouse on inactivity", ""); - INSERT(UISettings, controller_applet_disabled, "Disable controller applet", ""); + INSERT(UISettings, select_user_on_boot, tr("Prompt for user on game boot"), QStringLiteral()); + INSERT(UISettings, pause_when_in_background, tr("Pause emulation when in background"), + QStringLiteral()); + INSERT(UISettings, confirm_before_stopping, tr("Confirm before stopping emulation"), + QStringLiteral()); + INSERT(UISettings, hide_mouse, tr("Hide mouse on inactivity"), QStringLiteral()); + INSERT(UISettings, controller_applet_disabled, tr("Disable controller applet"), + QStringLiteral()); // Ui Debugging @@ -178,140 +194,141 @@ std::unique_ptr ComboboxEnumeration(QWidget* parent) { return parent->tr(text, context); }; -#define PAIR(ENUM, VALUE, TRANSLATION) \ - { static_cast(Settings::ENUM::VALUE), tr(TRANSLATION) } -#define CTX_PAIR(ENUM, VALUE, TRANSLATION, CONTEXT) \ - { static_cast(Settings::ENUM::VALUE), tr(TRANSLATION, CONTEXT) } +#define PAIR(ENUM, VALUE, TRANSLATION) {static_cast(Settings::ENUM::VALUE), (TRANSLATION)} // Intentionally skipping VSyncMode to let the UI fill that one out translations->insert({Settings::EnumMetadata::Index(), { - PAIR(AstcDecodeMode, Cpu, "CPU"), - PAIR(AstcDecodeMode, Gpu, "GPU"), - PAIR(AstcDecodeMode, CpuAsynchronous, "CPU Asynchronous"), - }}); - translations->insert({Settings::EnumMetadata::Index(), - { - PAIR(AstcRecompression, Uncompressed, "Uncompressed (Best quality)"), - PAIR(AstcRecompression, Bc1, "BC1 (Low quality)"), - PAIR(AstcRecompression, Bc3, "BC3 (Medium quality)"), + PAIR(AstcDecodeMode, Cpu, tr("CPU")), + PAIR(AstcDecodeMode, Gpu, tr("GPU")), + PAIR(AstcDecodeMode, CpuAsynchronous, tr("CPU Asynchronous")), }}); + translations->insert( + {Settings::EnumMetadata::Index(), + { + PAIR(AstcRecompression, Uncompressed, tr("Uncompressed (Best quality)")), + PAIR(AstcRecompression, Bc1, tr("BC1 (Low quality)")), + PAIR(AstcRecompression, Bc3, tr("BC3 (Medium quality)")), + }}); translations->insert({Settings::EnumMetadata::Index(), { #ifdef HAS_OPENGL - PAIR(RendererBackend, OpenGL, "OpenGL"), + PAIR(RendererBackend, OpenGL, tr("OpenGL")), #endif - PAIR(RendererBackend, Vulkan, "Vulkan"), - PAIR(RendererBackend, Null, "Null"), - }}); - translations->insert({Settings::EnumMetadata::Index(), - { - PAIR(ShaderBackend, Glsl, "GLSL"), - PAIR(ShaderBackend, Glasm, "GLASM (Assembly Shaders, NVIDIA Only)"), - PAIR(ShaderBackend, SpirV, "SPIR-V (Experimental, Mesa Only)"), + PAIR(RendererBackend, Vulkan, tr("Vulkan")), + PAIR(RendererBackend, Null, tr("Null")), }}); + translations->insert( + {Settings::EnumMetadata::Index(), + { + PAIR(ShaderBackend, Glsl, tr("GLSL")), + PAIR(ShaderBackend, Glasm, tr("GLASM (Assembly Shaders, NVIDIA Only)")), + PAIR(ShaderBackend, SpirV, tr("SPIR-V (Experimental, Mesa Only)")), + }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(GpuAccuracy, Normal, "Normal"), - PAIR(GpuAccuracy, High, "High"), - PAIR(GpuAccuracy, Extreme, "Extreme"), - }}); - translations->insert({Settings::EnumMetadata::Index(), - { - PAIR(CpuAccuracy, Auto, "Auto"), - PAIR(CpuAccuracy, Accurate, "Accurate"), - PAIR(CpuAccuracy, Unsafe, "Unsafe"), - PAIR(CpuAccuracy, Paranoid, "Paranoid (disables most optimizations)"), + PAIR(GpuAccuracy, Normal, tr("Normal")), + PAIR(GpuAccuracy, High, tr("High")), + PAIR(GpuAccuracy, Extreme, tr("Extreme")), }}); + translations->insert( + {Settings::EnumMetadata::Index(), + { + PAIR(CpuAccuracy, Auto, tr("Auto")), + PAIR(CpuAccuracy, Accurate, tr("Accurate")), + PAIR(CpuAccuracy, Unsafe, tr("Unsafe")), + PAIR(CpuAccuracy, Paranoid, tr("Paranoid (disables most optimizations)")), + }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(FullscreenMode, Borderless, "Borderless Windowed"), - PAIR(FullscreenMode, Exclusive, "Exclusive Fullscreen"), + PAIR(FullscreenMode, Borderless, tr("Borderless Windowed")), + PAIR(FullscreenMode, Exclusive, tr("Exclusive Fullscreen")), }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(NvdecEmulation, Off, "No Video Output"), - PAIR(NvdecEmulation, Cpu, "CPU Video Decoding"), - PAIR(NvdecEmulation, Gpu, "GPU Video Decoding (Default)"), - }}); - translations->insert({Settings::EnumMetadata::Index(), - { - PAIR(ResolutionSetup, Res1_2X, "0.5X (360p/540p) [EXPERIMENTAL]"), - PAIR(ResolutionSetup, Res3_4X, "0.75X (540p/810p) [EXPERIMENTAL]"), - PAIR(ResolutionSetup, Res1X, "1X (720p/1080p)"), - PAIR(ResolutionSetup, Res3_2X, "1.5X (1080p/1620p) [EXPERIMENTAL]"), - PAIR(ResolutionSetup, Res2X, "2X (1440p/2160p)"), - PAIR(ResolutionSetup, Res3X, "3X (2160p/3240p)"), - PAIR(ResolutionSetup, Res4X, "4X (2880p/4320p)"), - PAIR(ResolutionSetup, Res5X, "5X (3600p/5400p)"), - PAIR(ResolutionSetup, Res6X, "6X (4320p/6480p)"), - PAIR(ResolutionSetup, Res7X, "7X (5040p/7560p)"), - PAIR(ResolutionSetup, Res8X, "8X (5760p/8640p)"), + PAIR(NvdecEmulation, Off, tr("No Video Output")), + PAIR(NvdecEmulation, Cpu, tr("CPU Video Decoding")), + PAIR(NvdecEmulation, Gpu, tr("GPU Video Decoding (Default)")), }}); + translations->insert( + {Settings::EnumMetadata::Index(), + { + PAIR(ResolutionSetup, Res1_2X, tr("0.5X (360p/540p) [EXPERIMENTAL]")), + PAIR(ResolutionSetup, Res3_4X, tr("0.75X (540p/810p) [EXPERIMENTAL]")), + PAIR(ResolutionSetup, Res1X, tr("1X (720p/1080p)")), + PAIR(ResolutionSetup, Res3_2X, tr("1.5X (1080p/1620p) [EXPERIMENTAL]")), + PAIR(ResolutionSetup, Res2X, tr("2X (1440p/2160p)")), + PAIR(ResolutionSetup, Res3X, tr("3X (2160p/3240p)")), + PAIR(ResolutionSetup, Res4X, tr("4X (2880p/4320p)")), + PAIR(ResolutionSetup, Res5X, tr("5X (3600p/5400p)")), + PAIR(ResolutionSetup, Res6X, tr("6X (4320p/6480p)")), + PAIR(ResolutionSetup, Res7X, tr("7X (5040p/7560p)")), + PAIR(ResolutionSetup, Res8X, tr("8X (5760p/8640p)")), + }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(ScalingFilter, NearestNeighbor, "Nearest Neighbor"), - PAIR(ScalingFilter, Bilinear, "Bilinear"), - PAIR(ScalingFilter, Bicubic, "Bicubic"), - PAIR(ScalingFilter, Gaussian, "Gaussian"), - PAIR(ScalingFilter, ScaleForce, "ScaleForce"), - PAIR(ScalingFilter, Fsr, "AMD FidelityFX™️ Super Resolution"), + PAIR(ScalingFilter, NearestNeighbor, tr("Nearest Neighbor")), + PAIR(ScalingFilter, Bilinear, tr("Bilinear")), + PAIR(ScalingFilter, Bicubic, tr("Bicubic")), + PAIR(ScalingFilter, Gaussian, tr("Gaussian")), + PAIR(ScalingFilter, ScaleForce, tr("ScaleForce")), + PAIR(ScalingFilter, Fsr, tr("AMD FidelityFX™️ Super Resolution")), }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(AntiAliasing, None, "None"), - PAIR(AntiAliasing, Fxaa, "FXAA"), - PAIR(AntiAliasing, Smaa, "SMAA"), + PAIR(AntiAliasing, None, tr("None")), + PAIR(AntiAliasing, Fxaa, tr("FXAA")), + PAIR(AntiAliasing, Smaa, tr("SMAA")), }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(AspectRatio, R16_9, "Default (16:9)"), - PAIR(AspectRatio, R4_3, "Force 4:3"), - PAIR(AspectRatio, R21_9, "Force 21:9"), - PAIR(AspectRatio, R16_10, "Force 16:10"), - PAIR(AspectRatio, Stretch, "Stretch to Window"), + PAIR(AspectRatio, R16_9, tr("Default (16:9)")), + PAIR(AspectRatio, R4_3, tr("Force 4:3")), + PAIR(AspectRatio, R21_9, tr("Force 21:9")), + PAIR(AspectRatio, R16_10, tr("Force 16:10")), + PAIR(AspectRatio, Stretch, tr("Stretch to Window")), }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(AnisotropyMode, Automatic, "Automatic"), - PAIR(AnisotropyMode, Default, "Default"), - PAIR(AnisotropyMode, X2, "2x"), - PAIR(AnisotropyMode, X4, "4x"), - PAIR(AnisotropyMode, X8, "8x"), - PAIR(AnisotropyMode, X16, "16x"), + PAIR(AnisotropyMode, Automatic, tr("Automatic")), + PAIR(AnisotropyMode, Default, tr("Default")), + PAIR(AnisotropyMode, X2, tr("2x")), + PAIR(AnisotropyMode, X4, tr("4x")), + PAIR(AnisotropyMode, X8, tr("8x")), + PAIR(AnisotropyMode, X16, tr("16x")), }}); translations->insert( {Settings::EnumMetadata::Index(), { - PAIR(Language, Japanese, "Japanese (日本語)"), - PAIR(Language, EnglishAmerican, "American English"), - PAIR(Language, French, "French (français)"), - PAIR(Language, German, "German (Deutsch)"), - PAIR(Language, Italian, "Italian (italiano)"), - PAIR(Language, Spanish, "Spanish (español)"), - PAIR(Language, Chinese, "Chinese"), - PAIR(Language, Korean, "Korean (한국어)"), - PAIR(Language, Dutch, "Dutch (Nederlands)"), - PAIR(Language, Portuguese, "Portuguese (português)"), - PAIR(Language, Russian, "Russian (Русский)"), - PAIR(Language, Taiwanese, "Taiwanese"), - PAIR(Language, EnglishBritish, "British English"), - PAIR(Language, FrenchCanadian, "Canadian French"), - PAIR(Language, SpanishLatin, "Latin American Spanish"), - PAIR(Language, ChineseSimplified, "Simplified Chinese"), - PAIR(Language, ChineseTraditional, "Traditional Chinese (正體中文)"), - PAIR(Language, PortugueseBrazilian, "Brazilian Portuguese (português do Brasil)"), + PAIR(Language, Japanese, tr("Japanese (日本語)")), + PAIR(Language, EnglishAmerican, tr("American English")), + PAIR(Language, French, tr("French (français)")), + PAIR(Language, German, tr("German (Deutsch)")), + PAIR(Language, Italian, tr("Italian (italiano)")), + PAIR(Language, Spanish, tr("Spanish (español)")), + PAIR(Language, Chinese, tr("Chinese")), + PAIR(Language, Korean, tr("Korean (한국어)")), + PAIR(Language, Dutch, tr("Dutch (Nederlands)")), + PAIR(Language, Portuguese, tr("Portuguese (português)")), + PAIR(Language, Russian, tr("Russian (Русский)")), + PAIR(Language, Taiwanese, tr("Taiwanese")), + PAIR(Language, EnglishBritish, tr("British English")), + PAIR(Language, FrenchCanadian, tr("Canadian French")), + PAIR(Language, SpanishLatin, tr("Latin American Spanish")), + PAIR(Language, ChineseSimplified, tr("Simplified Chinese")), + PAIR(Language, ChineseTraditional, tr("Traditional Chinese (正體中文)")), + PAIR(Language, PortugueseBrazilian, tr("Brazilian Portuguese (português do Brasil)")), }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(Region, Japan, "Japan"), - PAIR(Region, Usa, "USA"), - PAIR(Region, Europe, "Europe"), - PAIR(Region, Australia, "Australia"), - PAIR(Region, China, "China"), - PAIR(Region, Korea, "Korea"), - PAIR(Region, Taiwan, "Taiwan"), + PAIR(Region, Japan, tr("Japan")), + PAIR(Region, Usa, tr("USA")), + PAIR(Region, Europe, tr("Europe")), + PAIR(Region, Australia, tr("Australia")), + PAIR(Region, China, tr("China")), + PAIR(Region, Korea, tr("Korea")), + PAIR(Region, Taiwan, tr("Taiwan")), }}); translations->insert( {Settings::EnumMetadata::Index(), @@ -323,72 +340,74 @@ std::unique_ptr ComboboxEnumeration(QWidget* parent) { {static_cast(Settings::TimeZone::Default), tr("Default (%1)", "Default time zone") .arg(QString::fromStdString(Common::TimeZone::GetDefaultTimeZone()))}, - PAIR(TimeZone, Cet, "CET"), - PAIR(TimeZone, Cst6Cdt, "CST6CDT"), - PAIR(TimeZone, Cuba, "Cuba"), - PAIR(TimeZone, Eet, "EET"), - PAIR(TimeZone, Egypt, "Egypt"), - PAIR(TimeZone, Eire, "Eire"), - PAIR(TimeZone, Est, "EST"), - PAIR(TimeZone, Est5Edt, "EST5EDT"), - PAIR(TimeZone, Gb, "GB"), - PAIR(TimeZone, GbEire, "GB-Eire"), - PAIR(TimeZone, Gmt, "GMT"), - PAIR(TimeZone, GmtPlusZero, "GMT+0"), - PAIR(TimeZone, GmtMinusZero, "GMT-0"), - PAIR(TimeZone, GmtZero, "GMT0"), - PAIR(TimeZone, Greenwich, "Greenwich"), - PAIR(TimeZone, Hongkong, "Hongkong"), - PAIR(TimeZone, Hst, "HST"), - PAIR(TimeZone, Iceland, "Iceland"), - PAIR(TimeZone, Iran, "Iran"), - PAIR(TimeZone, Israel, "Israel"), - PAIR(TimeZone, Jamaica, "Jamaica"), - PAIR(TimeZone, Japan, "Japan"), - PAIR(TimeZone, Kwajalein, "Kwajalein"), - PAIR(TimeZone, Libya, "Libya"), - PAIR(TimeZone, Met, "MET"), - PAIR(TimeZone, Mst, "MST"), - PAIR(TimeZone, Mst7Mdt, "MST7MDT"), - PAIR(TimeZone, Navajo, "Navajo"), - PAIR(TimeZone, Nz, "NZ"), - PAIR(TimeZone, NzChat, "NZ-CHAT"), - PAIR(TimeZone, Poland, "Poland"), - PAIR(TimeZone, Portugal, "Portugal"), - PAIR(TimeZone, Prc, "PRC"), - PAIR(TimeZone, Pst8Pdt, "PST8PDT"), - PAIR(TimeZone, Roc, "ROC"), - PAIR(TimeZone, Rok, "ROK"), - PAIR(TimeZone, Singapore, "Singapore"), - PAIR(TimeZone, Turkey, "Turkey"), - PAIR(TimeZone, Uct, "UCT"), - PAIR(TimeZone, Universal, "Universal"), - PAIR(TimeZone, Utc, "UTC"), - PAIR(TimeZone, WSu, "W-SU"), - PAIR(TimeZone, Wet, "WET"), - PAIR(TimeZone, Zulu, "Zulu"), + PAIR(TimeZone, Cet, tr("CET")), + PAIR(TimeZone, Cst6Cdt, tr("CST6CDT")), + PAIR(TimeZone, Cuba, tr("Cuba")), + PAIR(TimeZone, Eet, tr("EET")), + PAIR(TimeZone, Egypt, tr("Egypt")), + PAIR(TimeZone, Eire, tr("Eire")), + PAIR(TimeZone, Est, tr("EST")), + PAIR(TimeZone, Est5Edt, tr("EST5EDT")), + PAIR(TimeZone, Gb, tr("GB")), + PAIR(TimeZone, GbEire, tr("GB-Eire")), + PAIR(TimeZone, Gmt, tr("GMT")), + PAIR(TimeZone, GmtPlusZero, tr("GMT+0")), + PAIR(TimeZone, GmtMinusZero, tr("GMT-0")), + PAIR(TimeZone, GmtZero, tr("GMT0")), + PAIR(TimeZone, Greenwich, tr("Greenwich")), + PAIR(TimeZone, Hongkong, tr("Hongkong")), + PAIR(TimeZone, Hst, tr("HST")), + PAIR(TimeZone, Iceland, tr("Iceland")), + PAIR(TimeZone, Iran, tr("Iran")), + PAIR(TimeZone, Israel, tr("Israel")), + PAIR(TimeZone, Jamaica, tr("Jamaica")), + PAIR(TimeZone, Japan, tr("Japan")), + PAIR(TimeZone, Kwajalein, tr("Kwajalein")), + PAIR(TimeZone, Libya, tr("Libya")), + PAIR(TimeZone, Met, tr("MET")), + PAIR(TimeZone, Mst, tr("MST")), + PAIR(TimeZone, Mst7Mdt, tr("MST7MDT")), + PAIR(TimeZone, Navajo, tr("Navajo")), + PAIR(TimeZone, Nz, tr("NZ")), + PAIR(TimeZone, NzChat, tr("NZ-CHAT")), + PAIR(TimeZone, Poland, tr("Poland")), + PAIR(TimeZone, Portugal, tr("Portugal")), + PAIR(TimeZone, Prc, tr("PRC")), + PAIR(TimeZone, Pst8Pdt, tr("PST8PDT")), + PAIR(TimeZone, Roc, tr("ROC")), + PAIR(TimeZone, Rok, tr("ROK")), + PAIR(TimeZone, Singapore, tr("Singapore")), + PAIR(TimeZone, Turkey, tr("Turkey")), + PAIR(TimeZone, Uct, tr("UCT")), + PAIR(TimeZone, Universal, tr("Universal")), + PAIR(TimeZone, Utc, tr("UTC")), + PAIR(TimeZone, WSu, tr("W-SU")), + PAIR(TimeZone, Wet, tr("WET")), + PAIR(TimeZone, Zulu, tr("Zulu")), }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(AudioMode, Mono, "Mono"), - PAIR(AudioMode, Stereo, "Stereo"), - PAIR(AudioMode, Surround, "Surround"), + PAIR(AudioMode, Mono, tr("Mono")), + PAIR(AudioMode, Stereo, tr("Stereo")), + PAIR(AudioMode, Surround, tr("Surround")), }}); translations->insert({Settings::EnumMetadata::Index(), { - PAIR(MemoryLayout, Memory_4Gb, "4GB DRAM (Default)"), - PAIR(MemoryLayout, Memory_6Gb, "6GB DRAM (Unsafe)"), - PAIR(MemoryLayout, Memory_8Gb, "8GB DRAM (Unsafe)"), + PAIR(MemoryLayout, Memory_4Gb, tr("4GB DRAM (Default)")), + PAIR(MemoryLayout, Memory_6Gb, tr("6GB DRAM (Unsafe)")), + PAIR(MemoryLayout, Memory_8Gb, tr("8GB DRAM (Unsafe)")), + }}); + translations->insert({Settings::EnumMetadata::Index(), + { + PAIR(ConsoleMode, Docked, tr("Docked")), + PAIR(ConsoleMode, Handheld, tr("Handheld")), }}); - translations->insert( - {Settings::EnumMetadata::Index(), - {PAIR(ConsoleMode, Docked, "Docked"), PAIR(ConsoleMode, Handheld, "Handheld")}}); translations->insert( {Settings::EnumMetadata::Index(), { - PAIR(ConfirmStop, Ask_Always, "Always ask (Default)"), - PAIR(ConfirmStop, Ask_Based_On_Game, "Only if game specifies not to stop"), - PAIR(ConfirmStop, Ask_Never, "Never ask"), + PAIR(ConfirmStop, Ask_Always, tr("Always ask (Default)")), + PAIR(ConfirmStop, Ask_Based_On_Game, tr("Only if game specifies not to stop")), + PAIR(ConfirmStop, Ask_Never, tr("Never ask")), }}); #undef PAIR -- cgit v1.2.3 From cb3559539a33da15859bc5f1ded24bdb41f4bd7f Mon Sep 17 00:00:00 2001 From: lat9nq <22451773+lat9nq@users.noreply.github.com> Date: Wed, 8 Nov 2023 11:27:13 -0500 Subject: CMakeLists: Add option to call lupdate directly qt_create_translation silently fails to run at all on my system. Since there is no error, I was unable to determine a fix. This sidesteps the convenience function by setting up the rules ourselves. This is left as an option since this path likely does not work on Windows. --- src/yuzu/CMakeLists.txt | 51 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 33e1fb663..181b2817c 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -252,6 +252,7 @@ file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/qt_themes/*) if (ENABLE_QT_TRANSLATION) set(YUZU_QT_LANGUAGES "${PROJECT_SOURCE_DIR}/dist/languages" CACHE PATH "Path to the translation bundle for the Qt frontend") option(GENERATE_QT_TRANSLATION "Generate en.ts as the translation source file" OFF) + option(WORKAROUND_BROKEN_LUPDATE "Run lupdate directly through CMake if Qt's convenience wrappers don't work" OFF) # Update source TS file if enabled if (GENERATE_QT_TRANSLATION) @@ -259,19 +260,51 @@ if (ENABLE_QT_TRANSLATION) # these calls to qt_create_translation also creates a rule to generate en.qm which conflicts with providing english plurals # so we have to set a OUTPUT_LOCATION so that we don't have multiple rules to generate en.qm set_source_files_properties(${YUZU_QT_LANGUAGES}/en.ts PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations") - qt_create_translation(QM_FILES - ${SRCS} - ${UIS} - ${YUZU_QT_LANGUAGES}/en.ts - OPTIONS - -source-language en_US - -target-language en_US - ) + if (WORKAROUND_BROKEN_LUPDATE) + add_custom_command(OUTPUT ${YUZU_QT_LANGUAGES}/en.ts + COMMAND lupdate + -source-language en_US + -target-language en_US + ${SRCS} + ${UIS} + -ts ${YUZU_QT_LANGUAGES}/en.ts + DEPENDS + ${SRCS} + ${UIS} + WORKING_DIRECTORY + ${CMAKE_CURRENT_SOURCE_DIR} + ) + else() + qt_create_translation(QM_FILES + ${SRCS} + ${UIS} + ${YUZU_QT_LANGUAGES}/en.ts + OPTIONS + -source-language en_US + -target-language en_US + ) + endif() # Generate plurals into dist/english_plurals/generated_en.ts so it can be used to revise dist/english_plurals/en.ts set(GENERATED_PLURALS_FILE ${PROJECT_SOURCE_DIR}/dist/english_plurals/generated_en.ts) set_source_files_properties(${GENERATED_PLURALS_FILE} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/plurals") - qt_create_translation(QM_FILES ${SRCS} ${UIS} ${GENERATED_PLURALS_FILE} OPTIONS -pluralonly -source-language en_US -target-language en_US) + if (WORKAROUND_BROKEN_LUPDATE) + add_custom_command(OUTPUT ${GENERATED_PLURALS_FILE} + COMMAND lupdate + -source-language en_US + -target-language en_US + ${SRCS} + ${UIS} + -ts ${GENERATED_PLURALS_FILE} + DEPENDS + ${SRCS} + ${UIS} + WORKING_DIRECTORY + ${CMAKE_CURRENT_SOURCE_DIR} + ) + else() + qt_create_translation(QM_FILES ${SRCS} ${UIS} ${GENERATED_PLURALS_FILE} OPTIONS -pluralonly -source-language en_US -target-language en_US) + endif() add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts ${GENERATED_PLURALS_FILE}) endif() -- cgit v1.2.3 From c7b31d24b979c36e2a9e59e7ae6876ffbc82a81e Mon Sep 17 00:00:00 2001 From: Franco M Date: Wed, 8 Nov 2023 21:04:30 +0000 Subject: Final change, i think --- src/yuzu/main.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 2402ea6f5..442408280 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -2998,8 +2997,8 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi } // Create icon file path - out_icon_path /= (program_id == 0 ? std::format("yuzu-{}.{}", game_file_name, ico_extension) - : std::format("yuzu-{:016X}.{}", program_id, ico_extension)); + out_icon_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension) + : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension)); return true; } @@ -3032,7 +3031,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga const auto control = pm.GetControlMetadata(); const auto loader = Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read)); - game_title = std::format("{:016X}", program_id); + game_title = fmt::format("{:016X}", program_id); if (control.first != nullptr) { game_title = control.first->GetApplicationName(); } else { @@ -3081,12 +3080,12 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga } #endif // __linux__ // Create shortcut - std::string arguments = std::format("-g \"{:s}\"", game_path); + std::string arguments = fmt::format("-g \"{:s}\"", game_path); if (GMainWindow::CreateShortcutMessagesGUI( this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, qt_game_title)) { arguments = "-f " + arguments; } - const std::string comment = std::format("Start {:s} with the yuzu Emulator", game_title); + const std::string comment = fmt::format("Start {:s} with the yuzu Emulator", game_title); const std::string categories = "Game;Emulator;Qt;"; const std::string keywords = "Switch;Nintendo;"; -- cgit v1.2.3 From f3053920bf75858b702b13a2d80589a386c397b9 Mon Sep 17 00:00:00 2001 From: Franco M Date: Thu, 9 Nov 2023 03:37:06 +0000 Subject: Minor changes --- src/yuzu/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 442408280..a4ad9d8a8 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2980,7 +2980,7 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi // Get path to Yuzu icons directory & icon extension std::string ico_extension = "png"; #if defined(_WIN32) - out_icon_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons"; + out_icon_path = Common::FS::YuzuPath::IconsDir; ico_extension = "ico"; #elif defined(__linux__) || defined(__FreeBSD__) out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; @@ -5331,4 +5331,4 @@ int main(int argc, char* argv[]) { int result = app.exec(); detached_tasks.WaitForAllTasks(); return result; -} \ No newline at end of file +} -- cgit v1.2.3 From c9038af29e05458bd2f647158cc2903132c4c560 Mon Sep 17 00:00:00 2001 From: Franco M Date: Thu, 9 Nov 2023 04:53:10 +0000 Subject: Fix out_icon_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::IconsDir); --- src/yuzu/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index a4ad9d8a8..e0a656a5e 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -2980,7 +2980,7 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi // Get path to Yuzu icons directory & icon extension std::string ico_extension = "png"; #if defined(_WIN32) - out_icon_path = Common::FS::YuzuPath::IconsDir; + out_icon_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::IconsDir); ico_extension = "ico"; #elif defined(__linux__) || defined(__FreeBSD__) out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; -- cgit v1.2.3 From 9169cbf72835bf12434c9f9f1fea11f03d40437f Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Thu, 9 Nov 2023 20:11:13 -0600 Subject: yuzu: Save mute when in background setting --- src/yuzu/configuration/config.cpp | 2 ++ src/yuzu/configuration/configure_audio.cpp | 10 +++++++--- src/yuzu/uisettings.h | 10 +++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index baa3e55f3..42bbb2964 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -360,6 +360,7 @@ void Config::ReadAudioValues() { qt_config->beginGroup(QStringLiteral("Audio")); ReadCategory(Settings::Category::Audio); + ReadCategory(Settings::Category::UiAudio); qt_config->endGroup(); } @@ -900,6 +901,7 @@ void Config::SaveAudioValues() { qt_config->beginGroup(QStringLiteral("Audio")); WriteCategory(Settings::Category::Audio); + WriteCategory(Settings::Category::UiAudio); qt_config->endGroup(); } diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index 81dd51ad3..9b6ef47a7 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp @@ -38,17 +38,21 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) { std::map hold; - auto push = [&](Settings::Category category) { + auto push_settings = [&](Settings::Category category) { for (auto* setting : Settings::values.linkage.by_category[category]) { settings.push_back(setting); } + }; + + auto push_ui_settings = [&](Settings::Category category) { for (auto* setting : UISettings::values.linkage.by_category[category]) { settings.push_back(setting); } }; - push(Settings::Category::Audio); - push(Settings::Category::SystemAudio); + push_settings(Settings::Category::Audio); + push_settings(Settings::Category::SystemAudio); + push_ui_settings(Settings::Category::UiAudio); for (auto* setting : settings) { auto* widget = builder.BuildWidget(setting, apply_funcs); diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 77d992c54..3485a6347 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -109,9 +109,13 @@ struct Values { Settings::Specialization::Default, true, true}; - Setting mute_when_in_background{ - linkage, false, "muteWhenInBackground", Category::Audio, Settings::Specialization::Default, - true, true}; + Setting mute_when_in_background{linkage, + false, + "muteWhenInBackground", + Category::UiAudio, + Settings::Specialization::Default, + true, + true}; Setting hide_mouse{ linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default, true, true}; -- cgit v1.2.3 From 9e331f9957bbc7aec82cd8f96c67373e115bcd68 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Thu, 9 Nov 2023 20:30:00 -0600 Subject: yuzu: Make mute audio persistent --- src/yuzu/main.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 91aba118a..1bf173efb 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1064,12 +1064,6 @@ void GMainWindow::InitializeWidgets() { volume_slider->setObjectName(QStringLiteral("volume_slider")); volume_slider->setMaximum(200); volume_slider->setPageStep(5); - connect(volume_slider, &QSlider::valueChanged, this, [this](int percentage) { - Settings::values.audio_muted = false; - const auto volume = static_cast(percentage); - Settings::values.volume.SetValue(volume); - UpdateVolumeUI(); - }); volume_popup->layout()->addWidget(volume_slider); volume_button = new VolumeButton(); @@ -1077,6 +1071,12 @@ void GMainWindow::InitializeWidgets() { volume_button->setFocusPolicy(Qt::NoFocus); volume_button->setCheckable(true); UpdateVolumeUI(); + connect(volume_slider, &QSlider::valueChanged, this, [this](int percentage) { + Settings::values.audio_muted = false; + const auto volume = static_cast(percentage); + Settings::values.volume.SetValue(volume); + UpdateVolumeUI(); + }); connect(volume_button, &QPushButton::clicked, this, [&] { UpdateVolumeUI(); volume_popup->setVisible(!volume_popup->isVisible()); -- cgit v1.2.3 From 0c032d3f2fca46569562d968b3edb37d972d0975 Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 11 Nov 2023 10:12:11 -0600 Subject: yuzu: Keep homebrew on the recently played list --- src/yuzu/main.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index ce0c71021..d2a054eaa 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1909,7 +1909,8 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t StartGameType type, AmLaunchType launch_type) { LOG_INFO(Frontend, "yuzu starting..."); - if (program_id > static_cast(Service::AM::Applets::AppletProgramId::MaxProgramId)) { + if (program_id == 0 || + program_id > static_cast(Service::AM::Applets::AppletProgramId::MaxProgramId)) { StoreRecentFile(filename); // Put the filename on top of the list } @@ -4295,7 +4296,7 @@ void GMainWindow::OnAlbum() { const auto filename = QString::fromStdString(album_nca->GetFullPath()); UISettings::values.roms_path = QFileInfo(filename).path(); - BootGame(filename); + BootGame(filename, AlbumId); } void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { @@ -4319,7 +4320,7 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { const auto filename = QString::fromStdString(cabinet_nca->GetFullPath()); UISettings::values.roms_path = QFileInfo(filename).path(); - BootGame(filename); + BootGame(filename, CabinetId); } void GMainWindow::OnMiiEdit() { @@ -4342,7 +4343,7 @@ void GMainWindow::OnMiiEdit() { const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); UISettings::values.roms_path = QFileInfo(filename).path(); - BootGame(filename); + BootGame(filename, MiiEditId); } void GMainWindow::OnCaptureScreenshot() { -- cgit v1.2.3 From ae57a99d7d2063661cc15e76e8183122d8e0bc1b Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 11 Nov 2023 20:54:06 -0600 Subject: core: hid: Split SL and SR buttons --- src/yuzu/configuration/config.cpp | 1 + src/yuzu/configuration/configure_input_player.cpp | 36 +- src/yuzu/configuration/configure_input_player.ui | 389 ++++++++++++++------- .../configure_input_player_widget.cpp | 45 ++- 4 files changed, 321 insertions(+), 150 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index baa3e55f3..09cd8d180 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -35,6 +35,7 @@ const std::array Config::default_button Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T, Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0, + Qt::Key_Q, Qt::Key_E, }; const std::array Config::default_motions = { diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 576f5b571..9259e2a5d 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -322,11 +322,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i setFocusPolicy(Qt::ClickFocus); button_map = { - ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, - ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, - ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, - ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, - ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, + ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, + ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, + ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, + ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, + ui->buttonSLLeft, ui->buttonSRLeft, ui->buttonHome, ui->buttonScreenshot, + ui->buttonSLRight, ui->buttonSRRight, }; analog_map_buttons = {{ @@ -1181,10 +1182,13 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { // List of all the widgets that will be hidden by any of the following layouts that need // "unhidden" after the controller type changes - const std::array layout_show = { - ui->buttonShoulderButtonsSLSR, + const std::array layout_show = { + ui->buttonShoulderButtonsSLSRLeft, + ui->buttonShoulderButtonsSLSRRight, ui->horizontalSpacerShoulderButtonsWidget, ui->horizontalSpacerShoulderButtonsWidget2, + ui->horizontalSpacerShoulderButtonsWidget3, + ui->horizontalSpacerShoulderButtonsWidget4, ui->buttonShoulderButtonsLeft, ui->buttonMiscButtonsMinusScreenshot, ui->bottomLeft, @@ -1202,16 +1206,19 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { std::vector layout_hidden; switch (layout) { case Core::HID::NpadStyleIndex::ProController: - case Core::HID::NpadStyleIndex::JoyconDual: case Core::HID::NpadStyleIndex::Handheld: layout_hidden = { - ui->buttonShoulderButtonsSLSR, + ui->buttonShoulderButtonsSLSRLeft, + ui->buttonShoulderButtonsSLSRRight, ui->horizontalSpacerShoulderButtonsWidget2, + ui->horizontalSpacerShoulderButtonsWidget4, }; break; case Core::HID::NpadStyleIndex::JoyconLeft: layout_hidden = { + ui->buttonShoulderButtonsSLSRRight, ui->horizontalSpacerShoulderButtonsWidget2, + ui->horizontalSpacerShoulderButtonsWidget3, ui->buttonShoulderButtonsRight, ui->buttonMiscButtonsPlusHome, ui->bottomRight, @@ -1219,16 +1226,17 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() { break; case Core::HID::NpadStyleIndex::JoyconRight: layout_hidden = { - ui->horizontalSpacerShoulderButtonsWidget, - ui->buttonShoulderButtonsLeft, - ui->buttonMiscButtonsMinusScreenshot, - ui->bottomLeft, + ui->buttonShoulderButtonsSLSRLeft, ui->horizontalSpacerShoulderButtonsWidget, + ui->horizontalSpacerShoulderButtonsWidget4, ui->buttonShoulderButtonsLeft, + ui->buttonMiscButtonsMinusScreenshot, ui->bottomLeft, }; break; case Core::HID::NpadStyleIndex::GameCube: layout_hidden = { - ui->buttonShoulderButtonsSLSR, + ui->buttonShoulderButtonsSLSRLeft, + ui->buttonShoulderButtonsSLSRRight, ui->horizontalSpacerShoulderButtonsWidget2, + ui->horizontalSpacerShoulderButtonsWidget4, ui->buttonMiscButtonsMinusGroup, ui->buttonMiscButtonsScreenshotGroup, }; diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui index 611a79477..5518cccd1 100644 --- a/src/yuzu/configuration/configure_input_player.ui +++ b/src/yuzu/configuration/configure_input_player.ui @@ -1208,6 +1208,159 @@ 3 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + SL + + + Qt::AlignCenter + + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 68 + 0 + + + + + 68 + 16777215 + + + + min-width: 68px; + + + SL + + + + + + + + + + SR + + + Qt::AlignCenter + + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 68 + 0 + + + + + 68 + 16777215 + + + + min-width: 68px; + + + SR + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + @@ -1830,125 +1983,125 @@ - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - SL - - - Qt::AlignCenter - - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - - - - 68 - 0 - - - - - 68 - 16777215 - - - - min-width: 68px; - - - SL - - - - - - - - - - SR - - - Qt::AlignCenter - - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - - - - 68 - 0 - - - - - 68 - 16777215 - - - - min-width: 68px; - - - SR - - - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + SL + + + Qt::AlignCenter + + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 68 + 0 + + + + + 68 + 16777215 + + + + min-width: 68px; + + + SL + + + + + + + + + + SR + + + Qt::AlignCenter + + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 68 + 0 + + + + + 68 + 16777215 + + + + min-width: 68px; + + + SR + + + + + + - - - - - + + diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index a188eef92..550cff9a0 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -297,8 +297,8 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) // Sideview SL and SR buttons button_color = colors.slider_button; - DrawRoundButton(p, center + QPoint(59, 52), button_values[SR], 5, 12, Direction::Left); - DrawRoundButton(p, center + QPoint(59, -69), button_values[SL], 5, 12, Direction::Left); + DrawRoundButton(p, center + QPoint(59, 52), button_values[SRLeft], 5, 12, Direction::Left); + DrawRoundButton(p, center + QPoint(59, -69), button_values[SLLeft], 5, 12, Direction::Left); DrawLeftBody(p, center); @@ -353,8 +353,10 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) // SR and SL buttons p.setPen(colors.outline); button_color = colors.slider_button; - DrawRoundButton(p, center + QPoint(155, 52), button_values[SR], 5.2f, 12, Direction::None, 4); - DrawRoundButton(p, center + QPoint(155, -69), button_values[SL], 5.2f, 12, Direction::None, 4); + DrawRoundButton(p, center + QPoint(155, 52), button_values[SRLeft], 5.2f, 12, Direction::None, + 4); + DrawRoundButton(p, center + QPoint(155, -69), button_values[SLLeft], 5.2f, 12, Direction::None, + 4); // SR and SL text p.setPen(colors.transparent); @@ -428,8 +430,10 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center // Sideview SL and SR buttons button_color = colors.slider_button; - DrawRoundButton(p, center + QPoint(-59, 52), button_values[SL], 5, 11, Direction::Right); - DrawRoundButton(p, center + QPoint(-59, -69), button_values[SR], 5, 11, Direction::Right); + DrawRoundButton(p, center + QPoint(-59, 52), button_values[SLRight], 5, 11, + Direction::Right); + DrawRoundButton(p, center + QPoint(-59, -69), button_values[SRRight], 5, 11, + Direction::Right); DrawRightBody(p, center); @@ -484,8 +488,10 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center // SR and SL buttons p.setPen(colors.outline); button_color = colors.slider_button; - DrawRoundButton(p, center + QPoint(-155, 52), button_values[SL], 5, 12, Direction::None, 4.0f); - DrawRoundButton(p, center + QPoint(-155, -69), button_values[SR], 5, 12, Direction::None, 4.0f); + DrawRoundButton(p, center + QPoint(-155, 52), button_values[SLRight], 5, 12, Direction::None, + 4.0f); + DrawRoundButton(p, center + QPoint(-155, -69), button_values[SRRight], 5, 12, Direction::None, + 4.0f); // SR and SL text p.setPen(colors.transparent); @@ -557,6 +563,19 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) DrawRoundButton(p, center + QPoint(-154, -72), button_values[Minus], 7, 4, Direction::Up, 1); + // Left SR and SL sideview buttons + button_color = colors.slider_button; + DrawRoundButton(p, center + QPoint(-20, -62), button_values[SLLeft], 4, 11, + Direction::Left); + DrawRoundButton(p, center + QPoint(-20, 47), button_values[SRLeft], 4, 11, Direction::Left); + + // Right SR and SL sideview buttons + button_color = colors.slider_button; + DrawRoundButton(p, center + QPoint(20, 47), button_values[SLRight], 4, 11, + Direction::Right); + DrawRoundButton(p, center + QPoint(20, -62), button_values[SRRight], 4, 11, + Direction::Right); + DrawDualBody(p, center); // Right trigger top view @@ -1792,16 +1811,6 @@ void PlayerControlPreview::DrawDualBody(QPainter& p, const QPointF center) { p.setBrush(colors.right); DrawPolygon(p, qright_joycon_topview); - // Right SR and SL sideview buttons - p.setPen(colors.outline); - p.setBrush(colors.slider_button); - DrawRoundRectangle(p, center + QPoint(19, 47), 7, 22, 1); - DrawRoundRectangle(p, center + QPoint(19, -62), 7, 22, 1); - - // Left SR and SL sideview buttons - DrawRoundRectangle(p, center + QPoint(-19, 47), 7, 22, 1); - DrawRoundRectangle(p, center + QPoint(-19, -62), 7, 22, 1); - // Right Sideview body p.setBrush(colors.slider); DrawPolygon(p, qright_joycon_slider); -- cgit v1.2.3 From efc50485b80e4fde656897b7c9c32f2dbb78977b Mon Sep 17 00:00:00 2001 From: GPUCode Date: Sat, 9 Sep 2023 17:28:06 +0300 Subject: renderer_vulkan: Introduce separate cmd buffer for uploads --- src/yuzu/configuration/configure_debug.cpp | 3 ++ src/yuzu/configuration/configure_debug.ui | 86 +++++++++++++++++------------- 2 files changed, 51 insertions(+), 38 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index ef421c754..1010038b7 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -51,6 +51,8 @@ void ConfigureDebug::SetConfiguration() { ui->enable_all_controllers->setChecked(Settings::values.enable_all_controllers.GetValue()); ui->enable_renderdoc_hotkey->setEnabled(runtime_lock); ui->enable_renderdoc_hotkey->setChecked(Settings::values.enable_renderdoc_hotkey.GetValue()); + ui->disable_buffer_reorder->setEnabled(runtime_lock); + ui->disable_buffer_reorder->setChecked(Settings::values.disable_buffer_reorder.GetValue()); ui->enable_graphics_debugging->setEnabled(runtime_lock); ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue()); ui->enable_shader_feedback->setEnabled(runtime_lock); @@ -96,6 +98,7 @@ void ConfigureDebug::ApplyConfiguration() { Settings::values.enable_all_controllers = ui->enable_all_controllers->isChecked(); Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); Settings::values.enable_renderdoc_hotkey = ui->enable_renderdoc_hotkey->isChecked(); + Settings::values.disable_buffer_reorder = ui->disable_buffer_reorder->isChecked(); Settings::values.renderer_shader_feedback = ui->enable_shader_feedback->isChecked(); Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked(); Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked(); diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 76fe98924..22b51f39c 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -271,19 +271,6 @@ - - - true - - - When checked, it disables the macro HLE functions. Enabling this makes games run slower - - - Disable Macro HLE - - - - true @@ -306,17 +293,27 @@ - - + + + + true + - When checked, yuzu will log statistics about the compiled pipeline cache + When checked, it will dump all the original assembler shaders from the disk shader cache or game as found - Enable Shader Feedback + Dump Game Shaders - + + + + Enable Renderdoc Hotkey + + + + true @@ -330,20 +327,17 @@ - - - Qt::Vertical + + + true - - QSizePolicy::Preferred + + When checked, it disables the macro HLE functions. Enabling this makes games run slower - - - 20 - 0 - + + Disable Macro HLE - + @@ -358,23 +352,39 @@ - - - - true + + + + Qt::Vertical + + + QSizePolicy::Preferred + + + 20 + 0 + + + + + + - When checked, it will dump all the original assembler shaders from the disk shader cache or game as found + When checked, yuzu will log statistics about the compiled pipeline cache - Dump Game Shaders + Enable Shader Feedback - - + + + + <html><head/><body><p>When checked, disables reording of mapped memory uploads which allows to associate uploads with specific draws. May reduce performance in some cases.</p></body></html> + - Enable Renderdoc Hotkey + Disable Buffer Reorder -- cgit v1.2.3 From c9cd938dfd8fc40ec58d61dc453bc31d3b811496 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Tue, 14 Nov 2023 21:34:27 -0600 Subject: service: hid: Split hid.cpp into individual interfaces --- src/yuzu/applets/qt_controller.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/yuzu') diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index 515cb7ce6..9e5319716 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp @@ -13,7 +13,6 @@ #include "core/hid/hid_core.h" #include "core/hid/hid_types.h" #include "core/hle/service/hid/controllers/npad.h" -#include "core/hle/service/hid/hid.h" #include "core/hle/service/sm/sm.h" #include "ui_qt_controller.h" #include "yuzu/applets/qt_controller.h" -- cgit v1.2.3 From 20a17607ae86321fc188c9a71ed72f8eb15cfadb Mon Sep 17 00:00:00 2001 From: Liam Date: Sun, 19 Nov 2023 11:49:51 -0500 Subject: qt: fix linux build --- src/yuzu/util/util.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/yuzu') diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp index 7b2a47496..e22cf84bf 100644 --- a/src/yuzu/util/util.cpp +++ b/src/yuzu/util/util.cpp @@ -4,7 +4,10 @@ #include #include #include + +#include "common/logging/log.h" #include "yuzu/util/util.h" + #ifdef _WIN32 #include #include "common/fs/file.h" -- cgit v1.2.3 From cb004d1ba1bde740ba10418ac3f3cfd2db8ffac7 Mon Sep 17 00:00:00 2001 From: FrozenAra Date: Wed, 1 Nov 2023 01:09:33 +0100 Subject: Implemented qlaunch version of the controller applet --- src/yuzu/main.cpp | 41 +++++++++++++++++++++++++++++++++-------- src/yuzu/main.h | 1 + src/yuzu/main.ui | 22 ++++++++++++++-------- 3 files changed, 48 insertions(+), 16 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f077d7f9c..b0e995c52 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1574,6 +1574,7 @@ void GMainWindow::ConnectMenuEvents() { connect_menu(ui->action_Load_Cabinet_Formatter, [this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); }); connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit); + connect_menu(ui->action_Open_Controller_Menu, &GMainWindow::OnOpenControllerMenu); connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot); // TAS @@ -1601,14 +1602,13 @@ void GMainWindow::UpdateMenuState() { ui->action_Pause, }; - const std::array applet_actions{ - ui->action_Load_Album, - ui->action_Load_Cabinet_Nickname_Owner, - ui->action_Load_Cabinet_Eraser, - ui->action_Load_Cabinet_Restorer, - ui->action_Load_Cabinet_Formatter, - ui->action_Load_Mii_Edit, - }; + const std::array applet_actions{ui->action_Load_Album, + ui->action_Load_Cabinet_Nickname_Owner, + ui->action_Load_Cabinet_Eraser, + ui->action_Load_Cabinet_Restorer, + ui->action_Load_Cabinet_Formatter, + ui->action_Load_Mii_Edit, + ui->action_Open_Controller_Menu}; for (QAction* action : running_actions) { action->setEnabled(emulation_running); @@ -4346,6 +4346,31 @@ void GMainWindow::OnMiiEdit() { BootGame(filename, MiiEditId); } +void GMainWindow::OnOpenControllerMenu() { + constexpr u64 ControllerAppletId = + static_cast(Service::AM::Applets::AppletProgramId::Controller); + auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); + if (!bis_system) { + QMessageBox::warning(this, tr("No firmware available"), + tr("Please install the firmware to use the Controller Menu.")); + return; + } + + auto controller_applet_nca = + bis_system->GetEntry(ControllerAppletId, FileSys::ContentRecordType::Program); + if (!controller_applet_nca) { + QMessageBox::warning(this, tr("Controller Applet"), + tr("Controller Menu is not available. Please reinstall firmware.")); + return; + } + + system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Controller); + + const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath())); + UISettings::values.roms_path = QFileInfo(filename).path(); + BootGame(filename, ControllerAppletId); +} + void GMainWindow::OnCaptureScreenshot() { if (emu_thread == nullptr || !emu_thread->IsRunning()) { return; diff --git a/src/yuzu/main.h b/src/yuzu/main.h index f9c6efe4f..19740cc52 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -402,6 +402,7 @@ private slots: void OnAlbum(); void OnCabinet(Service::NFP::CabinetMode mode); void OnMiiEdit(); + void OnOpenControllerMenu(); void OnCaptureScreenshot(); void OnReinitializeKeys(ReinitializeKeyBehavior behavior); void OnLanguageChanged(const QString& locale); diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 88684ffb5..e53f9951e 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui @@ -25,7 +25,7 @@ - + 0 @@ -36,7 +36,7 @@ 0 0 1280 - 26 + 21 @@ -162,6 +162,7 @@ + @@ -382,9 +383,9 @@ - - Open &Album - + + Open &Album + @@ -407,9 +408,9 @@ - - Open &Mii Editor - + + Open &Mii Editor + @@ -454,6 +455,11 @@ R&ecord + + + Open &Controller Menu + + -- cgit v1.2.3 From da14c7b8e47fcd5456d88a033a1fb154a0dcfa39 Mon Sep 17 00:00:00 2001 From: t895 Date: Sun, 12 Nov 2023 02:03:01 -0500 Subject: config: Unify config handling under frontend_common Replaces every way of handling config for each frontend with SimpleIni. frontend_common's Config class is at the center where it saves and loads all of the cross-platform settings and provides a set of pure virtual functions for platform specific settings. As a result of making config handling platform specific, several parts had to be moved to each platform's own config class or to other parts. Default keys were put in platform specific config classes and translatable strings for Qt were moved to shared_translation. Default hotkeys, default_theme, window geometry, and qt metatypes were moved to uisettings. Additionally, to reduce dependence on Qt, QStrings were converted to std::strings where applicable. --- src/yuzu/CMakeLists.txt | 6 +- src/yuzu/configuration/config.cpp | 1309 -------------------- src/yuzu/configuration/config.h | 179 --- src/yuzu/configuration/configure_camera.cpp | 2 +- src/yuzu/configuration/configure_dialog.cpp | 1 - src/yuzu/configuration/configure_hotkeys.cpp | 36 +- .../configuration/configure_input_per_game.cpp | 6 +- src/yuzu/configuration/configure_input_per_game.h | 5 +- src/yuzu/configuration/configure_input_player.cpp | 11 +- src/yuzu/configuration/configure_per_game.cpp | 7 +- src/yuzu/configuration/configure_per_game.h | 5 +- .../configuration/configure_per_game_addons.cpp | 1 - src/yuzu/configuration/configure_ringcon.cpp | 4 +- src/yuzu/configuration/configure_system.cpp | 1 - .../configure_touchscreen_advanced.cpp | 2 +- src/yuzu/configuration/configure_ui.cpp | 7 +- src/yuzu/configuration/input_profiles.cpp | 10 +- src/yuzu/configuration/input_profiles.h | 4 +- src/yuzu/configuration/qt_config.cpp | 548 ++++++++ src/yuzu/configuration/qt_config.h | 55 + src/yuzu/configuration/shared_translation.h | 43 + src/yuzu/debugger/wait_tree.cpp | 6 +- src/yuzu/game_list.cpp | 7 +- src/yuzu/game_list_p.h | 8 +- src/yuzu/game_list_worker.cpp | 16 +- src/yuzu/hotkeys.cpp | 28 +- src/yuzu/hotkeys.h | 16 +- src/yuzu/main.cpp | 112 +- src/yuzu/main.h | 7 +- src/yuzu/uisettings.cpp | 65 +- src/yuzu/uisettings.h | 79 +- 31 files changed, 939 insertions(+), 1647 deletions(-) delete mode 100644 src/yuzu/configuration/config.cpp delete mode 100644 src/yuzu/configuration/config.h create mode 100644 src/yuzu/configuration/qt_config.cpp create mode 100644 src/yuzu/configuration/qt_config.h (limited to 'src/yuzu') diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 33e1fb663..b251c9045 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -38,8 +38,6 @@ add_executable(yuzu compatdb.ui compatibility_list.cpp compatibility_list.h - configuration/config.cpp - configuration/config.h configuration/configuration_shared.cpp configuration/configuration_shared.h configuration/configure.ui @@ -147,6 +145,8 @@ add_executable(yuzu configuration/shared_translation.h configuration/shared_widget.cpp configuration/shared_widget.h + configuration/qt_config.cpp + configuration/qt_config.h debugger/console.cpp debugger/console.h debugger/controller.cpp @@ -344,7 +344,7 @@ endif() create_target_directory_groups(yuzu) -target_link_libraries(yuzu PRIVATE common core input_common network video_core) +target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core) target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets) target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp deleted file mode 100644 index c0ae6468b..000000000 --- a/src/yuzu/configuration/config.cpp +++ /dev/null @@ -1,1309 +0,0 @@ -// SPDX-FileCopyrightText: 2014 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include -#include -#include "common/fs/fs.h" -#include "common/fs/path_util.h" -#include "common/settings.h" -#include "common/settings_common.h" -#include "common/settings_enums.h" -#include "core/core.h" -#include "core/hle/service/acc/profile_manager.h" -#include "core/hle/service/hid/controllers/npad.h" -#include "input_common/main.h" -#include "network/network.h" -#include "yuzu/configuration/config.h" - -namespace FS = Common::FS; - -Config::Config(const std::string& config_name, ConfigType config_type) - : type(config_type), global{config_type == ConfigType::GlobalConfig} { - Initialize(config_name); -} - -Config::~Config() { - if (global) { - Save(); - } -} - -const std::array Config::default_buttons = { - Qt::Key_C, Qt::Key_X, Qt::Key_V, Qt::Key_Z, Qt::Key_F, - Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T, - Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, - Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0, - Qt::Key_Q, Qt::Key_E, -}; - -const std::array Config::default_motions = { - Qt::Key_7, - Qt::Key_8, -}; - -const std::array, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ - { - Qt::Key_W, - Qt::Key_S, - Qt::Key_A, - Qt::Key_D, - }, - { - Qt::Key_I, - Qt::Key_K, - Qt::Key_J, - Qt::Key_L, - }, -}}; - -const std::array Config::default_stick_mod = { - Qt::Key_Shift, - 0, -}; - -const std::array Config::default_ringcon_analogs{{ - Qt::Key_A, - Qt::Key_D, -}}; - -const std::map Config::anti_aliasing_texts_map = { - {Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))}, - {Settings::AntiAliasing::Fxaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FXAA"))}, - {Settings::AntiAliasing::Smaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SMAA"))}, -}; - -const std::map Config::scaling_filter_texts_map = { - {Settings::ScalingFilter::NearestNeighbor, - QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Nearest"))}, - {Settings::ScalingFilter::Bilinear, - QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bilinear"))}, - {Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bicubic"))}, - {Settings::ScalingFilter::Gaussian, - QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Gaussian"))}, - {Settings::ScalingFilter::ScaleForce, - QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))}, - {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))}, -}; - -const std::map Config::use_docked_mode_texts_map = { - {Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))}, - {Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))}, -}; - -const std::map Config::gpu_accuracy_texts_map = { - {Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))}, - {Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))}, - {Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))}, -}; - -const std::map Config::renderer_backend_texts_map = { - {Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Vulkan"))}, - {Settings::RendererBackend::OpenGL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "OpenGL"))}, - {Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))}, -}; - -const std::map Config::shader_backend_texts_map = { - {Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))}, - {Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))}, - {Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))}, -}; - -// This shouldn't have anything except static initializers (no functions). So -// QKeySequence(...).toString() is NOT ALLOWED HERE. -// This must be in alphabetical order according to action name as it must have the same order as -// UISetting::values.shortcuts, which is alphabetically ordered. -// clang-format off -const std::array Config::default_hotkeys{{ - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut, true}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("="), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut, true}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F9"), QStringLiteral("Home+R"), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F4"), QStringLiteral("Home+Plus"), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Esc"), QStringLiteral(""), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+Q"), QStringLiteral("Home+Minus"), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F11"), QStringLiteral("Home+B"), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+O"), QStringLiteral(""), Qt::WidgetWithChildrenShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F2"), QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F6"), QStringLiteral("R+Plus+Minus"), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"), QStringLiteral("L+Plus+Minus"), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F"), QStringLiteral(""), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+U"), QStringLiteral("Home+Y"), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F9"), QStringLiteral(""), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral(""), QStringLiteral(""), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+S"), QStringLiteral(""), Qt::WindowShortcut, false}}, -}}; -// clang-format on - -void Config::Initialize(const std::string& config_name) { - const auto fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir); - const auto config_file = fmt::format("{}.ini", config_name); - - switch (type) { - case ConfigType::GlobalConfig: - qt_config_loc = FS::PathToUTF8String(fs_config_loc / config_file); - void(FS::CreateParentDir(qt_config_loc)); - qt_config = std::make_unique(QString::fromStdString(qt_config_loc), - QSettings::IniFormat); - Reload(); - break; - case ConfigType::PerGameConfig: - qt_config_loc = - FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file)); - void(FS::CreateParentDir(qt_config_loc)); - qt_config = std::make_unique(QString::fromStdString(qt_config_loc), - QSettings::IniFormat); - Reload(); - break; - case ConfigType::InputProfile: - qt_config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file); - void(FS::CreateParentDir(qt_config_loc)); - qt_config = std::make_unique(QString::fromStdString(qt_config_loc), - QSettings::IniFormat); - break; - } -} - -bool Config::IsCustomConfig() { - return type == ConfigType::PerGameConfig; -} - -void Config::ReadPlayerValue(std::size_t player_index) { - const QString player_prefix = [this, player_index] { - if (type == ConfigType::InputProfile) { - return QString{}; - } else { - return QStringLiteral("player_%1_").arg(player_index); - } - }(); - - auto& player = Settings::values.players.GetValue()[player_index]; - if (IsCustomConfig()) { - const auto profile_name = - qt_config->value(QStringLiteral("%1profile_name").arg(player_prefix), QString{}) - .toString() - .toStdString(); - if (profile_name.empty()) { - // Use the global input config - player = Settings::values.players.GetValue(true)[player_index]; - return; - } - player.profile_name = profile_name; - } - - if (player_prefix.isEmpty() && Settings::IsConfiguringGlobal()) { - const auto controller = static_cast( - qt_config - ->value(QStringLiteral("%1type").arg(player_prefix), - static_cast(Settings::ControllerType::ProController)) - .toUInt()); - - if (controller == Settings::ControllerType::LeftJoycon || - controller == Settings::ControllerType::RightJoycon) { - player.controller_type = controller; - } - } else { - player.connected = - ReadSetting(QStringLiteral("%1connected").arg(player_prefix), player_index == 0) - .toBool(); - - player.controller_type = static_cast( - qt_config - ->value(QStringLiteral("%1type").arg(player_prefix), - static_cast(Settings::ControllerType::ProController)) - .toUInt()); - - player.vibration_enabled = - qt_config->value(QStringLiteral("%1vibration_enabled").arg(player_prefix), true) - .toBool(); - - player.vibration_strength = - qt_config->value(QStringLiteral("%1vibration_strength").arg(player_prefix), 100) - .toInt(); - - player.body_color_left = qt_config - ->value(QStringLiteral("%1body_color_left").arg(player_prefix), - Settings::JOYCON_BODY_NEON_BLUE) - .toUInt(); - player.body_color_right = - qt_config - ->value(QStringLiteral("%1body_color_right").arg(player_prefix), - Settings::JOYCON_BODY_NEON_RED) - .toUInt(); - player.button_color_left = - qt_config - ->value(QStringLiteral("%1button_color_left").arg(player_prefix), - Settings::JOYCON_BUTTONS_NEON_BLUE) - .toUInt(); - player.button_color_right = - qt_config - ->value(QStringLiteral("%1button_color_right").arg(player_prefix), - Settings::JOYCON_BUTTONS_NEON_RED) - .toUInt(); - } - - for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { - const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); - auto& player_buttons = player.buttons[i]; - - player_buttons = qt_config - ->value(QStringLiteral("%1").arg(player_prefix) + - QString::fromUtf8(Settings::NativeButton::mapping[i]), - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (player_buttons.empty()) { - player_buttons = default_param; - } - } - - for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { - const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( - default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], - default_analogs[i][3], default_stick_mod[i], 0.5f); - auto& player_analogs = player.analogs[i]; - - player_analogs = qt_config - ->value(QStringLiteral("%1").arg(player_prefix) + - QString::fromUtf8(Settings::NativeAnalog::mapping[i]), - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (player_analogs.empty()) { - player_analogs = default_param; - } - } - - for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { - const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); - auto& player_motions = player.motions[i]; - - player_motions = qt_config - ->value(QStringLiteral("%1").arg(player_prefix) + - QString::fromUtf8(Settings::NativeMotion::mapping[i]), - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (player_motions.empty()) { - player_motions = default_param; - } - } -} - -void Config::ReadDebugValues() { - for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { - const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); - auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i]; - - debug_pad_buttons = qt_config - ->value(QStringLiteral("debug_pad_") + - QString::fromUtf8(Settings::NativeButton::mapping[i]), - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (debug_pad_buttons.empty()) { - debug_pad_buttons = default_param; - } - } - - for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { - const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( - default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], - default_analogs[i][3], default_stick_mod[i], 0.5f); - auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i]; - - debug_pad_analogs = qt_config - ->value(QStringLiteral("debug_pad_") + - QString::fromUtf8(Settings::NativeAnalog::mapping[i]), - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (debug_pad_analogs.empty()) { - debug_pad_analogs = default_param; - } - } -} - -void Config::ReadTouchscreenValues() { - Settings::values.touchscreen.enabled = - ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool(); - - Settings::values.touchscreen.rotation_angle = - ReadSetting(QStringLiteral("touchscreen_angle"), 0).toUInt(); - Settings::values.touchscreen.diameter_x = - ReadSetting(QStringLiteral("touchscreen_diameter_x"), 15).toUInt(); - Settings::values.touchscreen.diameter_y = - ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt(); -} - -void Config::ReadHidbusValues() { - const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( - 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); - auto& ringcon_analogs = Settings::values.ringcon_analogs; - - ringcon_analogs = - qt_config->value(QStringLiteral("ring_controller"), QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (ringcon_analogs.empty()) { - ringcon_analogs = default_param; - } -} - -void Config::ReadAudioValues() { - qt_config->beginGroup(QStringLiteral("Audio")); - - ReadCategory(Settings::Category::Audio); - ReadCategory(Settings::Category::UiAudio); - - qt_config->endGroup(); -} - -void Config::ReadControlValues() { - qt_config->beginGroup(QStringLiteral("Controls")); - - ReadCategory(Settings::Category::Controls); - - Settings::values.players.SetGlobal(!IsCustomConfig()); - for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { - ReadPlayerValue(p); - } - - // Disable docked mode if handheld is selected - const auto controller_type = Settings::values.players.GetValue()[0].controller_type; - if (controller_type == Settings::ControllerType::Handheld) { - Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig()); - Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld); - } - - if (IsCustomConfig()) { - qt_config->endGroup(); - return; - } - ReadDebugValues(); - ReadTouchscreenValues(); - ReadMotionTouchValues(); - ReadHidbusValues(); - - qt_config->endGroup(); -} - -void Config::ReadMotionTouchValues() { - int num_touch_from_button_maps = - qt_config->beginReadArray(QStringLiteral("touch_from_button_maps")); - - if (num_touch_from_button_maps > 0) { - const auto append_touch_from_button_map = [this] { - Settings::TouchFromButtonMap map; - map.name = ReadSetting(QStringLiteral("name"), QStringLiteral("default")) - .toString() - .toStdString(); - const int num_touch_maps = qt_config->beginReadArray(QStringLiteral("entries")); - map.buttons.reserve(num_touch_maps); - for (int i = 0; i < num_touch_maps; i++) { - qt_config->setArrayIndex(i); - std::string touch_mapping = - ReadSetting(QStringLiteral("bind")).toString().toStdString(); - map.buttons.emplace_back(std::move(touch_mapping)); - } - qt_config->endArray(); // entries - Settings::values.touch_from_button_maps.emplace_back(std::move(map)); - }; - - for (int i = 0; i < num_touch_from_button_maps; ++i) { - qt_config->setArrayIndex(i); - append_touch_from_button_map(); - } - } else { - Settings::values.touch_from_button_maps.emplace_back( - Settings::TouchFromButtonMap{"default", {}}); - num_touch_from_button_maps = 1; - } - qt_config->endArray(); - - Settings::values.touch_from_button_map_index = std::clamp( - Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); -} - -void Config::ReadCoreValues() { - qt_config->beginGroup(QStringLiteral("Core")); - - ReadCategory(Settings::Category::Core); - - qt_config->endGroup(); -} - -void Config::ReadDataStorageValues() { - qt_config->beginGroup(QStringLiteral("Data Storage")); - - FS::SetYuzuPath( - FS::YuzuPath::NANDDir, - qt_config - ->value(QStringLiteral("nand_directory"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir))) - .toString() - .toStdString()); - FS::SetYuzuPath( - FS::YuzuPath::SDMCDir, - qt_config - ->value(QStringLiteral("sdmc_directory"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir))) - .toString() - .toStdString()); - FS::SetYuzuPath( - FS::YuzuPath::LoadDir, - qt_config - ->value(QStringLiteral("load_directory"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir))) - .toString() - .toStdString()); - FS::SetYuzuPath( - FS::YuzuPath::DumpDir, - qt_config - ->value(QStringLiteral("dump_directory"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir))) - .toString() - .toStdString()); - FS::SetYuzuPath(FS::YuzuPath::TASDir, - qt_config - ->value(QStringLiteral("tas_directory"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir))) - .toString() - .toStdString()); - - ReadCategory(Settings::Category::DataStorage); - - qt_config->endGroup(); -} - -void Config::ReadDebuggingValues() { - qt_config->beginGroup(QStringLiteral("Debugging")); - - // Intentionally not using the QT default setting as this is intended to be changed in the ini - Settings::values.record_frame_times = - qt_config->value(QStringLiteral("record_frame_times"), false).toBool(); - - ReadCategory(Settings::Category::Debugging); - ReadCategory(Settings::Category::DebuggingGraphics); - - qt_config->endGroup(); -} - -void Config::ReadServiceValues() { - qt_config->beginGroup(QStringLiteral("Services")); - - ReadCategory(Settings::Category::Services); - - qt_config->endGroup(); -} - -void Config::ReadDisabledAddOnValues() { - const auto size = qt_config->beginReadArray(QStringLiteral("DisabledAddOns")); - - for (int i = 0; i < size; ++i) { - qt_config->setArrayIndex(i); - const auto title_id = ReadSetting(QStringLiteral("title_id"), 0).toULongLong(); - std::vector out; - const auto d_size = qt_config->beginReadArray(QStringLiteral("disabled")); - for (int j = 0; j < d_size; ++j) { - qt_config->setArrayIndex(j); - out.push_back(ReadSetting(QStringLiteral("d"), QString{}).toString().toStdString()); - } - qt_config->endArray(); - Settings::values.disabled_addons.insert_or_assign(title_id, out); - } - - qt_config->endArray(); -} - -void Config::ReadMiscellaneousValues() { - qt_config->beginGroup(QStringLiteral("Miscellaneous")); - - ReadCategory(Settings::Category::Miscellaneous); - - qt_config->endGroup(); -} - -void Config::ReadPathValues() { - qt_config->beginGroup(QStringLiteral("Paths")); - - UISettings::values.roms_path = ReadSetting(QStringLiteral("romsPath")).toString(); - UISettings::values.symbols_path = ReadSetting(QStringLiteral("symbolsPath")).toString(); - UISettings::values.game_dir_deprecated = - ReadSetting(QStringLiteral("gameListRootDir"), QStringLiteral(".")).toString(); - UISettings::values.game_dir_deprecated_deepscan = - ReadSetting(QStringLiteral("gameListDeepScan"), false).toBool(); - const int gamedirs_size = qt_config->beginReadArray(QStringLiteral("gamedirs")); - for (int i = 0; i < gamedirs_size; ++i) { - qt_config->setArrayIndex(i); - UISettings::GameDir game_dir; - game_dir.path = ReadSetting(QStringLiteral("path")).toString(); - game_dir.deep_scan = ReadSetting(QStringLiteral("deep_scan"), false).toBool(); - game_dir.expanded = ReadSetting(QStringLiteral("expanded"), true).toBool(); - UISettings::values.game_dirs.append(game_dir); - } - qt_config->endArray(); - // create NAND and SD card directories if empty, these are not removable through the UI, - // also carries over old game list settings if present - if (UISettings::values.game_dirs.isEmpty()) { - UISettings::GameDir game_dir; - game_dir.path = QStringLiteral("SDMC"); - game_dir.expanded = true; - UISettings::values.game_dirs.append(game_dir); - game_dir.path = QStringLiteral("UserNAND"); - UISettings::values.game_dirs.append(game_dir); - game_dir.path = QStringLiteral("SysNAND"); - UISettings::values.game_dirs.append(game_dir); - if (UISettings::values.game_dir_deprecated != QStringLiteral(".")) { - game_dir.path = UISettings::values.game_dir_deprecated; - game_dir.deep_scan = UISettings::values.game_dir_deprecated_deepscan; - UISettings::values.game_dirs.append(game_dir); - } - } - UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList(); - UISettings::values.language = ReadSetting(QStringLiteral("language"), QString{}).toString(); - - qt_config->endGroup(); -} - -void Config::ReadCpuValues() { - qt_config->beginGroup(QStringLiteral("Cpu")); - - ReadCategory(Settings::Category::Cpu); - ReadCategory(Settings::Category::CpuDebug); - ReadCategory(Settings::Category::CpuUnsafe); - - qt_config->endGroup(); -} - -void Config::ReadRendererValues() { - qt_config->beginGroup(QStringLiteral("Renderer")); - - ReadCategory(Settings::Category::Renderer); - ReadCategory(Settings::Category::RendererAdvanced); - ReadCategory(Settings::Category::RendererDebug); - - qt_config->endGroup(); -} - -void Config::ReadScreenshotValues() { - qt_config->beginGroup(QStringLiteral("Screenshots")); - - ReadCategory(Settings::Category::Screenshots); - FS::SetYuzuPath( - FS::YuzuPath::ScreenshotsDir, - qt_config - ->value(QStringLiteral("screenshot_path"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir))) - .toString() - .toStdString()); - - qt_config->endGroup(); -} - -void Config::ReadShortcutValues() { - qt_config->beginGroup(QStringLiteral("Shortcuts")); - - for (const auto& [name, group, shortcut] : default_hotkeys) { - qt_config->beginGroup(group); - qt_config->beginGroup(name); - // No longer using ReadSetting for shortcut.second as it inaccurately returns a value of 1 - // for WidgetWithChildrenShortcut which is a value of 3. Needed to fix shortcuts the open - // a file dialog in windowed mode - UISettings::values.shortcuts.push_back( - {name, - group, - {ReadSetting(QStringLiteral("KeySeq"), shortcut.keyseq).toString(), - ReadSetting(QStringLiteral("Controller_KeySeq"), shortcut.controller_keyseq) - .toString(), - shortcut.context, ReadSetting(QStringLiteral("Repeat"), shortcut.repeat).toBool()}}); - qt_config->endGroup(); - qt_config->endGroup(); - } - - qt_config->endGroup(); -} - -void Config::ReadSystemValues() { - qt_config->beginGroup(QStringLiteral("System")); - - ReadCategory(Settings::Category::System); - ReadCategory(Settings::Category::SystemAudio); - - qt_config->endGroup(); -} - -void Config::ReadUIValues() { - qt_config->beginGroup(QStringLiteral("UI")); - - UISettings::values.theme = - ReadSetting( - QStringLiteral("theme"), - QString::fromUtf8(UISettings::themes[static_cast(default_theme)].second)) - .toString(); - - ReadUIGamelistValues(); - ReadUILayoutValues(); - ReadPathValues(); - ReadScreenshotValues(); - ReadShortcutValues(); - ReadMultiplayerValues(); - - ReadCategory(Settings::Category::Ui); - ReadCategory(Settings::Category::UiGeneral); - - qt_config->endGroup(); -} - -void Config::ReadUIGamelistValues() { - qt_config->beginGroup(QStringLiteral("UIGameList")); - - ReadCategory(Settings::Category::UiGameList); - - const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites")); - for (int i = 0; i < favorites_size; i++) { - qt_config->setArrayIndex(i); - UISettings::values.favorited_ids.append( - ReadSetting(QStringLiteral("program_id")).toULongLong()); - } - qt_config->endArray(); - - qt_config->endGroup(); -} - -void Config::ReadUILayoutValues() { - qt_config->beginGroup(QStringLiteral("UILayout")); - - UISettings::values.geometry = ReadSetting(QStringLiteral("geometry")).toByteArray(); - UISettings::values.state = ReadSetting(QStringLiteral("state")).toByteArray(); - UISettings::values.renderwindow_geometry = - ReadSetting(QStringLiteral("geometryRenderWindow")).toByteArray(); - UISettings::values.gamelist_header_state = - ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray(); - UISettings::values.microprofile_geometry = - ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray(); - - ReadCategory(Settings::Category::UiLayout); - - qt_config->endGroup(); -} - -void Config::ReadWebServiceValues() { - qt_config->beginGroup(QStringLiteral("WebService")); - - ReadCategory(Settings::Category::WebService); - - qt_config->endGroup(); -} - -void Config::ReadMultiplayerValues() { - qt_config->beginGroup(QStringLiteral("Multiplayer")); - - ReadCategory(Settings::Category::Multiplayer); - - // Read ban list back - int size = qt_config->beginReadArray(QStringLiteral("username_ban_list")); - UISettings::values.multiplayer_ban_list.first.resize(size); - for (int i = 0; i < size; ++i) { - qt_config->setArrayIndex(i); - UISettings::values.multiplayer_ban_list.first[i] = - ReadSetting(QStringLiteral("username")).toString().toStdString(); - } - qt_config->endArray(); - size = qt_config->beginReadArray(QStringLiteral("ip_ban_list")); - UISettings::values.multiplayer_ban_list.second.resize(size); - for (int i = 0; i < size; ++i) { - qt_config->setArrayIndex(i); - UISettings::values.multiplayer_ban_list.second[i] = - ReadSetting(QStringLiteral("ip")).toString().toStdString(); - } - qt_config->endArray(); - - qt_config->endGroup(); -} - -void Config::ReadNetworkValues() { - qt_config->beginGroup(QString::fromStdString("Services")); - - ReadCategory(Settings::Category::Network); - - qt_config->endGroup(); -} - -void Config::ReadValues() { - if (global) { - ReadDataStorageValues(); - ReadDebuggingValues(); - ReadDisabledAddOnValues(); - ReadNetworkValues(); - ReadServiceValues(); - ReadUIValues(); - ReadWebServiceValues(); - ReadMiscellaneousValues(); - } - ReadControlValues(); - ReadCoreValues(); - ReadCpuValues(); - ReadRendererValues(); - ReadAudioValues(); - ReadSystemValues(); -} - -void Config::SavePlayerValue(std::size_t player_index) { - const QString player_prefix = [this, player_index] { - if (type == ConfigType::InputProfile) { - return QString{}; - } else { - return QStringLiteral("player_%1_").arg(player_index); - } - }(); - - const auto& player = Settings::values.players.GetValue()[player_index]; - if (IsCustomConfig()) { - if (player.profile_name.empty()) { - // No custom profile selected - return; - } - WriteSetting(QStringLiteral("%1profile_name").arg(player_prefix), - QString::fromStdString(player.profile_name), QString{}); - } - - WriteSetting(QStringLiteral("%1type").arg(player_prefix), - static_cast(player.controller_type), - static_cast(Settings::ControllerType::ProController)); - - if (!player_prefix.isEmpty() || !Settings::IsConfiguringGlobal()) { - WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, - player_index == 0); - WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix), - player.vibration_enabled, true); - WriteSetting(QStringLiteral("%1vibration_strength").arg(player_prefix), - player.vibration_strength, 100); - WriteSetting(QStringLiteral("%1body_color_left").arg(player_prefix), player.body_color_left, - Settings::JOYCON_BODY_NEON_BLUE); - WriteSetting(QStringLiteral("%1body_color_right").arg(player_prefix), - player.body_color_right, Settings::JOYCON_BODY_NEON_RED); - WriteSetting(QStringLiteral("%1button_color_left").arg(player_prefix), - player.button_color_left, Settings::JOYCON_BUTTONS_NEON_BLUE); - WriteSetting(QStringLiteral("%1button_color_right").arg(player_prefix), - player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED); - } - - for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { - const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); - WriteSetting(QStringLiteral("%1").arg(player_prefix) + - QString::fromStdString(Settings::NativeButton::mapping[i]), - QString::fromStdString(player.buttons[i]), - QString::fromStdString(default_param)); - } - for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { - const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( - default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], - default_analogs[i][3], default_stick_mod[i], 0.5f); - WriteSetting(QStringLiteral("%1").arg(player_prefix) + - QString::fromStdString(Settings::NativeAnalog::mapping[i]), - QString::fromStdString(player.analogs[i]), - QString::fromStdString(default_param)); - } - for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { - const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); - WriteSetting(QStringLiteral("%1").arg(player_prefix) + - QString::fromStdString(Settings::NativeMotion::mapping[i]), - QString::fromStdString(player.motions[i]), - QString::fromStdString(default_param)); - } -} - -void Config::SaveDebugValues() { - for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { - const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); - WriteSetting(QStringLiteral("debug_pad_") + - QString::fromStdString(Settings::NativeButton::mapping[i]), - QString::fromStdString(Settings::values.debug_pad_buttons[i]), - QString::fromStdString(default_param)); - } - for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { - const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( - default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], - default_analogs[i][3], default_stick_mod[i], 0.5f); - WriteSetting(QStringLiteral("debug_pad_") + - QString::fromStdString(Settings::NativeAnalog::mapping[i]), - QString::fromStdString(Settings::values.debug_pad_analogs[i]), - QString::fromStdString(default_param)); - } -} - -void Config::SaveTouchscreenValues() { - const auto& touchscreen = Settings::values.touchscreen; - - WriteSetting(QStringLiteral("touchscreen_enabled"), touchscreen.enabled, true); - - WriteSetting(QStringLiteral("touchscreen_angle"), touchscreen.rotation_angle, 0); - WriteSetting(QStringLiteral("touchscreen_diameter_x"), touchscreen.diameter_x, 15); - WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15); -} - -void Config::SaveMotionTouchValues() { - qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps")); - for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { - qt_config->setArrayIndex(static_cast(p)); - WriteSetting(QStringLiteral("name"), - QString::fromStdString(Settings::values.touch_from_button_maps[p].name), - QStringLiteral("default")); - qt_config->beginWriteArray(QStringLiteral("entries")); - for (std::size_t q = 0; q < Settings::values.touch_from_button_maps[p].buttons.size(); - ++q) { - qt_config->setArrayIndex(static_cast(q)); - WriteSetting( - QStringLiteral("bind"), - QString::fromStdString(Settings::values.touch_from_button_maps[p].buttons[q])); - } - qt_config->endArray(); - } - qt_config->endArray(); -} - -void Config::SaveHidbusValues() { - const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( - 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); - WriteSetting(QStringLiteral("ring_controller"), - QString::fromStdString(Settings::values.ringcon_analogs), - QString::fromStdString(default_param)); -} - -void Config::SaveValues() { - if (global) { - SaveDataStorageValues(); - SaveDebuggingValues(); - SaveDisabledAddOnValues(); - SaveNetworkValues(); - SaveUIValues(); - SaveWebServiceValues(); - SaveMiscellaneousValues(); - } - SaveControlValues(); - SaveCoreValues(); - SaveCpuValues(); - SaveRendererValues(); - SaveAudioValues(); - SaveSystemValues(); - - qt_config->sync(); -} - -void Config::SaveAudioValues() { - qt_config->beginGroup(QStringLiteral("Audio")); - - WriteCategory(Settings::Category::Audio); - WriteCategory(Settings::Category::UiAudio); - - qt_config->endGroup(); -} - -void Config::SaveControlValues() { - qt_config->beginGroup(QStringLiteral("Controls")); - - WriteCategory(Settings::Category::Controls); - - Settings::values.players.SetGlobal(!IsCustomConfig()); - for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { - SavePlayerValue(p); - } - if (IsCustomConfig()) { - qt_config->endGroup(); - return; - } - SaveDebugValues(); - SaveTouchscreenValues(); - SaveMotionTouchValues(); - SaveHidbusValues(); - - qt_config->endGroup(); -} - -void Config::SaveCoreValues() { - qt_config->beginGroup(QStringLiteral("Core")); - - WriteCategory(Settings::Category::Core); - - qt_config->endGroup(); -} - -void Config::SaveDataStorageValues() { - qt_config->beginGroup(QStringLiteral("Data Storage")); - - WriteSetting(QStringLiteral("nand_directory"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); - WriteSetting(QStringLiteral("sdmc_directory"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir)), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::SDMCDir))); - WriteSetting(QStringLiteral("load_directory"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir)), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::LoadDir))); - WriteSetting(QStringLiteral("dump_directory"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); - WriteSetting(QStringLiteral("tas_directory"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir)), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::TASDir))); - - WriteCategory(Settings::Category::DataStorage); - - qt_config->endGroup(); -} - -void Config::SaveDebuggingValues() { - qt_config->beginGroup(QStringLiteral("Debugging")); - - // Intentionally not using the QT default setting as this is intended to be changed in the ini - qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times); - - WriteCategory(Settings::Category::Debugging); - WriteCategory(Settings::Category::DebuggingGraphics); - - qt_config->endGroup(); -} - -void Config::SaveNetworkValues() { - qt_config->beginGroup(QStringLiteral("Services")); - - WriteCategory(Settings::Category::Network); - - qt_config->endGroup(); -} - -void Config::SaveDisabledAddOnValues() { - qt_config->beginWriteArray(QStringLiteral("DisabledAddOns")); - - int i = 0; - for (const auto& elem : Settings::values.disabled_addons) { - qt_config->setArrayIndex(i); - WriteSetting(QStringLiteral("title_id"), QVariant::fromValue(elem.first), 0); - qt_config->beginWriteArray(QStringLiteral("disabled")); - for (std::size_t j = 0; j < elem.second.size(); ++j) { - qt_config->setArrayIndex(static_cast(j)); - WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]), QString{}); - } - qt_config->endArray(); - ++i; - } - - qt_config->endArray(); -} - -void Config::SaveMiscellaneousValues() { - qt_config->beginGroup(QStringLiteral("Miscellaneous")); - - WriteCategory(Settings::Category::Miscellaneous); - - qt_config->endGroup(); -} - -void Config::SavePathValues() { - qt_config->beginGroup(QStringLiteral("Paths")); - - WriteSetting(QStringLiteral("romsPath"), UISettings::values.roms_path); - WriteSetting(QStringLiteral("symbolsPath"), UISettings::values.symbols_path); - qt_config->beginWriteArray(QStringLiteral("gamedirs")); - for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) { - qt_config->setArrayIndex(i); - const auto& game_dir = UISettings::values.game_dirs[i]; - WriteSetting(QStringLiteral("path"), game_dir.path); - WriteSetting(QStringLiteral("deep_scan"), game_dir.deep_scan, false); - WriteSetting(QStringLiteral("expanded"), game_dir.expanded, true); - } - qt_config->endArray(); - WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files); - WriteSetting(QStringLiteral("language"), UISettings::values.language, QString{}); - - qt_config->endGroup(); -} - -void Config::SaveCpuValues() { - qt_config->beginGroup(QStringLiteral("Cpu")); - - WriteCategory(Settings::Category::Cpu); - WriteCategory(Settings::Category::CpuDebug); - WriteCategory(Settings::Category::CpuUnsafe); - - qt_config->endGroup(); -} - -void Config::SaveRendererValues() { - qt_config->beginGroup(QStringLiteral("Renderer")); - - WriteCategory(Settings::Category::Renderer); - WriteCategory(Settings::Category::RendererAdvanced); - WriteCategory(Settings::Category::RendererDebug); - - qt_config->endGroup(); -} - -void Config::SaveScreenshotValues() { - qt_config->beginGroup(QStringLiteral("Screenshots")); - - WriteSetting(QStringLiteral("screenshot_path"), - QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir))); - WriteCategory(Settings::Category::Screenshots); - - qt_config->endGroup(); -} - -void Config::SaveShortcutValues() { - qt_config->beginGroup(QStringLiteral("Shortcuts")); - - // Lengths of UISettings::values.shortcuts & default_hotkeys are same. - // However, their ordering must also be the same. - for (std::size_t i = 0; i < default_hotkeys.size(); i++) { - const auto& [name, group, shortcut] = UISettings::values.shortcuts[i]; - const auto& default_hotkey = default_hotkeys[i].shortcut; - - qt_config->beginGroup(group); - qt_config->beginGroup(name); - WriteSetting(QStringLiteral("KeySeq"), shortcut.keyseq, default_hotkey.keyseq); - WriteSetting(QStringLiteral("Controller_KeySeq"), shortcut.controller_keyseq, - default_hotkey.controller_keyseq); - WriteSetting(QStringLiteral("Context"), shortcut.context, default_hotkey.context); - WriteSetting(QStringLiteral("Repeat"), shortcut.repeat, default_hotkey.repeat); - qt_config->endGroup(); - qt_config->endGroup(); - } - - qt_config->endGroup(); -} - -void Config::SaveSystemValues() { - qt_config->beginGroup(QStringLiteral("System")); - - WriteCategory(Settings::Category::System); - WriteCategory(Settings::Category::SystemAudio); - - qt_config->endGroup(); -} - -void Config::SaveUIValues() { - qt_config->beginGroup(QStringLiteral("UI")); - - WriteCategory(Settings::Category::Ui); - WriteCategory(Settings::Category::UiGeneral); - - WriteSetting(QStringLiteral("theme"), UISettings::values.theme, - QString::fromUtf8(UISettings::themes[static_cast(default_theme)].second)); - - SaveUIGamelistValues(); - SaveUILayoutValues(); - SavePathValues(); - SaveScreenshotValues(); - SaveShortcutValues(); - SaveMultiplayerValues(); - - qt_config->endGroup(); -} - -void Config::SaveUIGamelistValues() { - qt_config->beginGroup(QStringLiteral("UIGameList")); - - WriteCategory(Settings::Category::UiGameList); - - qt_config->beginWriteArray(QStringLiteral("favorites")); - for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { - qt_config->setArrayIndex(i); - WriteSetting(QStringLiteral("program_id"), - QVariant::fromValue(UISettings::values.favorited_ids[i])); - } - qt_config->endArray(); - - qt_config->endGroup(); -} - -void Config::SaveUILayoutValues() { - qt_config->beginGroup(QStringLiteral("UILayout")); - - WriteSetting(QStringLiteral("geometry"), UISettings::values.geometry); - WriteSetting(QStringLiteral("state"), UISettings::values.state); - WriteSetting(QStringLiteral("geometryRenderWindow"), UISettings::values.renderwindow_geometry); - WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state); - WriteSetting(QStringLiteral("microProfileDialogGeometry"), - UISettings::values.microprofile_geometry); - - WriteCategory(Settings::Category::UiLayout); - - qt_config->endGroup(); -} - -void Config::SaveWebServiceValues() { - qt_config->beginGroup(QStringLiteral("WebService")); - - WriteCategory(Settings::Category::WebService); - - qt_config->endGroup(); -} - -void Config::SaveMultiplayerValues() { - qt_config->beginGroup(QStringLiteral("Multiplayer")); - - WriteCategory(Settings::Category::Multiplayer); - - // Write ban list - qt_config->beginWriteArray(QStringLiteral("username_ban_list")); - for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.first.size(); ++i) { - qt_config->setArrayIndex(static_cast(i)); - WriteSetting(QStringLiteral("username"), - QString::fromStdString(UISettings::values.multiplayer_ban_list.first[i])); - } - qt_config->endArray(); - qt_config->beginWriteArray(QStringLiteral("ip_ban_list")); - for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.second.size(); ++i) { - qt_config->setArrayIndex(static_cast(i)); - WriteSetting(QStringLiteral("ip"), - QString::fromStdString(UISettings::values.multiplayer_ban_list.second[i])); - } - qt_config->endArray(); - - qt_config->endGroup(); -} - -QVariant Config::ReadSetting(const QString& name) const { - return qt_config->value(name); -} - -QVariant Config::ReadSetting(const QString& name, const QVariant& default_value) const { - QVariant result; - if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) { - result = default_value; - } else { - result = qt_config->value(name, default_value); - } - return result; -} - -void Config::WriteSetting(const QString& name, const QVariant& value) { - qt_config->setValue(name, value); -} - -void Config::WriteSetting(const QString& name, const QVariant& value, - const QVariant& default_value) { - qt_config->setValue(name + QStringLiteral("/default"), value == default_value); - qt_config->setValue(name, value); -} - -void Config::WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value, - bool use_global) { - if (!global) { - qt_config->setValue(name + QStringLiteral("/use_global"), use_global); - } - if (global || !use_global) { - qt_config->setValue(name + QStringLiteral("/default"), value == default_value); - qt_config->setValue(name, value); - } -} - -void Config::Reload() { - ReadValues(); - // To apply default value changes - SaveValues(); -} - -void Config::Save() { - SaveValues(); -} - -void Config::ReadControlPlayerValue(std::size_t player_index) { - qt_config->beginGroup(QStringLiteral("Controls")); - ReadPlayerValue(player_index); - qt_config->endGroup(); -} - -void Config::SaveControlPlayerValue(std::size_t player_index) { - qt_config->beginGroup(QStringLiteral("Controls")); - SavePlayerValue(player_index); - qt_config->endGroup(); -} - -void Config::ClearControlPlayerValues() { - qt_config->beginGroup(QStringLiteral("Controls")); - // If key is an empty string, all keys in the current group() are removed. - qt_config->remove(QString{}); - qt_config->endGroup(); -} - -const std::string& Config::GetConfigFilePath() const { - return qt_config_loc; -} - -static auto FindRelevantList(Settings::Category category) { - auto& map = Settings::values.linkage.by_category; - if (map.contains(category)) { - return Settings::values.linkage.by_category[category]; - } - return UISettings::values.linkage.by_category[category]; -} - -void Config::ReadCategory(Settings::Category category) { - const auto& settings = FindRelevantList(category); - std::for_each(settings.begin(), settings.end(), - [&](const auto& setting) { ReadSettingGeneric(setting); }); -} - -void Config::WriteCategory(Settings::Category category) { - const auto& settings = FindRelevantList(category); - std::for_each(settings.begin(), settings.end(), - [&](const auto& setting) { WriteSettingGeneric(setting); }); -} - -void Config::ReadSettingGeneric(Settings::BasicSetting* const setting) { - if (!setting->Save() || (!setting->Switchable() && !global)) { - return; - } - const QString name = QString::fromStdString(setting->GetLabel()); - const auto default_value = - QVariant::fromValue(QString::fromStdString(setting->DefaultToString())); - - bool use_global = true; - if (setting->Switchable() && !global) { - use_global = qt_config->value(name + QStringLiteral("/use_global"), true).value(); - setting->SetGlobal(use_global); - } - - if (global || !use_global) { - const bool is_default = - qt_config->value(name + QStringLiteral("/default"), true).value(); - if (!is_default) { - setting->LoadString( - qt_config->value(name, default_value).value().toStdString()); - } else { - // Empty string resets the Setting to default - setting->LoadString(""); - } - } -} - -void Config::WriteSettingGeneric(Settings::BasicSetting* const setting) const { - if (!setting->Save()) { - return; - } - const QVariant value = QVariant::fromValue(QString::fromStdString(setting->ToString())); - const QVariant default_value = - QVariant::fromValue(QString::fromStdString(setting->DefaultToString())); - const QString label = QString::fromStdString(setting->GetLabel()); - if (setting->Switchable()) { - if (!global) { - qt_config->setValue(label + QStringLiteral("/use_global"), setting->UsingGlobal()); - } - if (global || !setting->UsingGlobal()) { - qt_config->setValue(label + QStringLiteral("/default"), value == default_value); - qt_config->setValue(label, value); - } - } else if (global) { - qt_config->setValue(label + QStringLiteral("/default"), value == default_value); - qt_config->setValue(label, value); - } -} diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h deleted file mode 100644 index 1589ba057..000000000 --- a/src/yuzu/configuration/config.h +++ /dev/null @@ -1,179 +0,0 @@ -// SPDX-FileCopyrightText: 2014 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include -#include -#include "common/settings.h" -#include "common/settings_enums.h" -#include "yuzu/uisettings.h" - -class QSettings; - -namespace Core { -class System; -} - -class Config { -public: - enum class ConfigType { - GlobalConfig, - PerGameConfig, - InputProfile, - }; - - explicit Config(const std::string& config_name = "qt-config", - ConfigType config_type = ConfigType::GlobalConfig); - ~Config(); - - void Reload(); - void Save(); - - void ReadControlPlayerValue(std::size_t player_index); - void SaveControlPlayerValue(std::size_t player_index); - void ClearControlPlayerValues(); - - const std::string& GetConfigFilePath() const; - - static const std::array default_buttons; - static const std::array default_motions; - static const std::array, Settings::NativeAnalog::NumAnalogs> default_analogs; - static const std::array default_stick_mod; - static const std::array default_ringcon_analogs; - static const std::array - default_mouse_buttons; - static const std::array default_keyboard_keys; - static const std::array default_keyboard_mods; - static const std::array default_hotkeys; - - static const std::map anti_aliasing_texts_map; - static const std::map scaling_filter_texts_map; - static const std::map use_docked_mode_texts_map; - static const std::map gpu_accuracy_texts_map; - static const std::map renderer_backend_texts_map; - static const std::map shader_backend_texts_map; - - static constexpr UISettings::Theme default_theme{ -#ifdef _WIN32 - UISettings::Theme::DarkColorful -#else - UISettings::Theme::DefaultColorful -#endif - }; - -private: - void Initialize(const std::string& config_name); - bool IsCustomConfig(); - - void ReadValues(); - void ReadPlayerValue(std::size_t player_index); - void ReadDebugValues(); - void ReadKeyboardValues(); - void ReadMouseValues(); - void ReadTouchscreenValues(); - void ReadMotionTouchValues(); - void ReadHidbusValues(); - void ReadIrCameraValues(); - - // Read functions bases off the respective config section names. - void ReadAudioValues(); - void ReadControlValues(); - void ReadCoreValues(); - void ReadDataStorageValues(); - void ReadDebuggingValues(); - void ReadServiceValues(); - void ReadDisabledAddOnValues(); - void ReadMiscellaneousValues(); - void ReadPathValues(); - void ReadCpuValues(); - void ReadRendererValues(); - void ReadScreenshotValues(); - void ReadShortcutValues(); - void ReadSystemValues(); - void ReadUIValues(); - void ReadUIGamelistValues(); - void ReadUILayoutValues(); - void ReadWebServiceValues(); - void ReadMultiplayerValues(); - void ReadNetworkValues(); - - void SaveValues(); - void SavePlayerValue(std::size_t player_index); - void SaveDebugValues(); - void SaveMouseValues(); - void SaveTouchscreenValues(); - void SaveMotionTouchValues(); - void SaveHidbusValues(); - void SaveIrCameraValues(); - - // Save functions based off the respective config section names. - void SaveAudioValues(); - void SaveControlValues(); - void SaveCoreValues(); - void SaveDataStorageValues(); - void SaveDebuggingValues(); - void SaveNetworkValues(); - void SaveDisabledAddOnValues(); - void SaveMiscellaneousValues(); - void SavePathValues(); - void SaveCpuValues(); - void SaveRendererValues(); - void SaveScreenshotValues(); - void SaveShortcutValues(); - void SaveSystemValues(); - void SaveUIValues(); - void SaveUIGamelistValues(); - void SaveUILayoutValues(); - void SaveWebServiceValues(); - void SaveMultiplayerValues(); - - /** - * Reads a setting from the qt_config. - * - * @param name The setting's identifier - * @param default_value The value to use when the setting is not already present in the config - */ - QVariant ReadSetting(const QString& name) const; - QVariant ReadSetting(const QString& name, const QVariant& default_value) const; - - /** - * Writes a setting to the qt_config. - * - * @param name The setting's idetentifier - * @param value Value of the setting - * @param default_value Default of the setting if not present in qt_config - * @param use_global Specifies if the custom or global config should be in use, for custom - * configs - */ - void WriteSetting(const QString& name, const QVariant& value); - void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); - void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value, - bool use_global); - - void ReadCategory(Settings::Category category); - void WriteCategory(Settings::Category category); - void ReadSettingGeneric(Settings::BasicSetting* const setting); - void WriteSettingGeneric(Settings::BasicSetting* const setting) const; - - const ConfigType type; - std::unique_ptr qt_config; - std::string qt_config_loc; - const bool global; -}; - -// These metatype declarations cannot be in common/settings.h because core is devoid of QT -Q_DECLARE_METATYPE(Settings::CpuAccuracy); -Q_DECLARE_METATYPE(Settings::GpuAccuracy); -Q_DECLARE_METATYPE(Settings::FullscreenMode); -Q_DECLARE_METATYPE(Settings::NvdecEmulation); -Q_DECLARE_METATYPE(Settings::ResolutionSetup); -Q_DECLARE_METATYPE(Settings::ScalingFilter); -Q_DECLARE_METATYPE(Settings::AntiAliasing); -Q_DECLARE_METATYPE(Settings::RendererBackend); -Q_DECLARE_METATYPE(Settings::ShaderBackend); -Q_DECLARE_METATYPE(Settings::AstcRecompression); -Q_DECLARE_METATYPE(Settings::AstcDecodeMode); diff --git a/src/yuzu/configuration/configure_camera.cpp b/src/yuzu/configuration/configure_camera.cpp index d95e96696..3368f53f3 100644 --- a/src/yuzu/configuration/configure_camera.cpp +++ b/src/yuzu/configuration/configure_camera.cpp @@ -10,10 +10,10 @@ #include #include +#include "common/settings.h" #include "input_common/drivers/camera.h" #include "input_common/main.h" #include "ui_configure_camera.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_camera.h" ConfigureCamera::ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_) diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 0ad95cc02..aab54a1cc 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -8,7 +8,6 @@ #include "core/core.h" #include "ui_configure.h" #include "vk_device_info.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_audio.h" #include "yuzu/configuration/configure_cpu.h" #include "yuzu/configuration/configure_debug_tab.h" diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index 68e21cd84..76fc33e49 100644 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp @@ -9,10 +9,11 @@ #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" +#include "frontend_common/config.h" #include "ui_configure_hotkeys.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_hotkeys.h" #include "yuzu/hotkeys.h" +#include "yuzu/uisettings.h" #include "yuzu/util/sequence_dialog/sequence_dialog.h" constexpr int name_column = 0; @@ -62,18 +63,21 @@ ConfigureHotkeys::~ConfigureHotkeys() = default; void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { for (const auto& group : registry.hotkey_groups) { + QString parent_item_data = QString::fromStdString(group.first); auto* parent_item = - new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(group.first))); + new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(parent_item_data))); parent_item->setEditable(false); - parent_item->setData(group.first); + parent_item->setData(parent_item_data); for (const auto& hotkey : group.second) { - auto* action = - new QStandardItem(QCoreApplication::translate("Hotkeys", qPrintable(hotkey.first))); + QString hotkey_action_data = QString::fromStdString(hotkey.first); + auto* action = new QStandardItem( + QCoreApplication::translate("Hotkeys", qPrintable(hotkey_action_data))); auto* keyseq = new QStandardItem(hotkey.second.keyseq.toString(QKeySequence::NativeText)); - auto* controller_keyseq = new QStandardItem(hotkey.second.controller_keyseq); + auto* controller_keyseq = + new QStandardItem(QString::fromStdString(hotkey.second.controller_keyseq)); action->setEditable(false); - action->setData(hotkey.first); + action->setData(hotkey_action_data); keyseq->setEditable(false); controller_keyseq->setEditable(false); parent_item->appendRow({action, keyseq, controller_keyseq}); @@ -301,13 +305,13 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) { const QStandardItem* controller_keyseq = parent->child(key_column_id, controller_column); for (auto& [group, sub_actions] : registry.hotkey_groups) { - if (group != parent->data()) + if (group != parent->data().toString().toStdString()) continue; for (auto& [action_name, hotkey] : sub_actions) { - if (action_name != action->data()) + if (action_name != action->data().toString().toStdString()) continue; hotkey.keyseq = QKeySequence(keyseq->text()); - hotkey.controller_keyseq = controller_keyseq->text(); + hotkey.controller_keyseq = controller_keyseq->text().toStdString(); } } } @@ -319,7 +323,7 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) { void ConfigureHotkeys::RestoreDefaults() { for (int r = 0; r < model->rowCount(); ++r) { const QStandardItem* parent = model->item(r, 0); - const int hotkey_size = static_cast(Config::default_hotkeys.size()); + const int hotkey_size = static_cast(UISettings::default_hotkeys.size()); if (hotkey_size != parent->rowCount()) { QMessageBox::warning(this, tr("Invalid hotkey settings"), @@ -330,10 +334,11 @@ void ConfigureHotkeys::RestoreDefaults() { for (int r2 = 0; r2 < parent->rowCount(); ++r2) { model->item(r, 0) ->child(r2, hotkey_column) - ->setText(Config::default_hotkeys[r2].shortcut.keyseq); + ->setText(QString::fromStdString(UISettings::default_hotkeys[r2].shortcut.keyseq)); model->item(r, 0) ->child(r2, controller_column) - ->setText(Config::default_hotkeys[r2].shortcut.controller_keyseq); + ->setText(QString::fromStdString( + UISettings::default_hotkeys[r2].shortcut.controller_keyseq)); } } } @@ -379,7 +384,7 @@ void ConfigureHotkeys::PopupContextMenu(const QPoint& menu_location) { void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) { const QString& default_key_sequence = - Config::default_hotkeys[index.row()].shortcut.controller_keyseq; + QString::fromStdString(UISettings::default_hotkeys[index.row()].shortcut.controller_keyseq); const auto [key_sequence_used, used_action] = IsUsedControllerKey(default_key_sequence); if (key_sequence_used && default_key_sequence != model->data(index).toString()) { @@ -393,7 +398,8 @@ void ConfigureHotkeys::RestoreControllerHotkey(QModelIndex index) { void ConfigureHotkeys::RestoreHotkey(QModelIndex index) { const QKeySequence& default_key_sequence = QKeySequence::fromString( - Config::default_hotkeys[index.row()].shortcut.keyseq, QKeySequence::NativeText); + QString::fromStdString(UISettings::default_hotkeys[index.row()].shortcut.keyseq), + QKeySequence::NativeText); const auto [key_sequence_used, used_action] = IsUsedKey(default_key_sequence); if (key_sequence_used && default_key_sequence != QKeySequence(model->data(index).toString())) { diff --git a/src/yuzu/configuration/configure_input_per_game.cpp b/src/yuzu/configuration/configure_input_per_game.cpp index 78e65d468..8d9f65a05 100644 --- a/src/yuzu/configuration/configure_input_per_game.cpp +++ b/src/yuzu/configuration/configure_input_per_game.cpp @@ -5,12 +5,12 @@ #include "core/core.h" #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" +#include "frontend_common/config.h" #include "ui_configure_input_per_game.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_input_per_game.h" #include "yuzu/configuration/input_profiles.h" -ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, Config* config_, +ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, QtConfig* config_, QWidget* parent) : QWidget(parent), ui(std::make_unique()), profiles(std::make_unique()), system{system_}, config{config_} { @@ -110,6 +110,6 @@ void ConfigureInputPerGame::SaveConfiguration() { // Clear all controls from the config in case the user reverted back to globals config->ClearControlPlayerValues(); for (size_t index = 0; index < Settings::values.players.GetValue().size(); ++index) { - config->SaveControlPlayerValue(index); + config->SaveQtControlPlayerValues(index); } } diff --git a/src/yuzu/configuration/configure_input_per_game.h b/src/yuzu/configuration/configure_input_per_game.h index 660faf574..4420e856c 100644 --- a/src/yuzu/configuration/configure_input_per_game.h +++ b/src/yuzu/configuration/configure_input_per_game.h @@ -9,6 +9,7 @@ #include "ui_configure_input_per_game.h" #include "yuzu/configuration/input_profiles.h" +#include "yuzu/configuration/qt_config.h" class QComboBox; @@ -22,7 +23,7 @@ class ConfigureInputPerGame : public QWidget { Q_OBJECT public: - explicit ConfigureInputPerGame(Core::System& system_, Config* config_, + explicit ConfigureInputPerGame(Core::System& system_, QtConfig* config_, QWidget* parent = nullptr); /// Load and Save configurations to settings file. @@ -41,5 +42,5 @@ private: std::array profile_comboboxes; Core::System& system; - Config* config; + QtConfig* config; }; diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 9259e2a5d..0f7b3714e 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -12,15 +12,16 @@ #include #include "common/assert.h" #include "common/param_package.h" +#include "configuration/qt_config.h" #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "core/hid/hid_types.h" +#include "frontend_common/config.h" #include "input_common/drivers/keyboard.h" #include "input_common/drivers/mouse.h" #include "input_common/main.h" #include "ui_configure_input_player.h" #include "yuzu/bootmanager.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_input_player.h" #include "yuzu/configuration/configure_input_player_widget.h" #include "yuzu/configuration/configure_mouse_panning.h" @@ -1397,25 +1398,25 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() { for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { emulated_controller->SetButtonParam( button_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam( - Config::default_buttons[button_id])}); + QtConfig::default_buttons[button_id])}); } for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { Common::ParamPackage analog_param{}; for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { Common::ParamPackage params{InputCommon::GenerateKeyboardParam( - Config::default_analogs[analog_id][sub_button_id])}; + QtConfig::default_analogs[analog_id][sub_button_id])}; SetAnalogParam(params, analog_param, analog_sub_buttons[sub_button_id]); } analog_param.Set("modifier", InputCommon::GenerateKeyboardParam( - Config::default_stick_mod[analog_id])); + QtConfig::default_stick_mod[analog_id])); emulated_controller->SetStickParam(analog_id, analog_param); } for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { emulated_controller->SetMotionParam( motion_id, Common::ParamPackage{InputCommon::GenerateKeyboardParam( - Config::default_motions[motion_id])}); + QtConfig::default_motions[motion_id])}); } // If mouse is selected we want to override with mappings from the driver diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index b91d6ad4a..b274a3321 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp @@ -25,8 +25,8 @@ #include "core/file_sys/patch_manager.h" #include "core/file_sys/xts_archive.h" #include "core/loader/loader.h" +#include "frontend_common/config.h" #include "ui_configure_per_game.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configure_audio.h" #include "yuzu/configuration/configure_cpu.h" @@ -50,8 +50,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name)); const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()) : fmt::format("{:016X}", title_id); - game_config = std::make_unique(config_file_name, Config::ConfigType::PerGameConfig); - + game_config = std::make_unique(config_file_name, Config::ConfigType::PerGameConfig); addons_tab = std::make_unique(system_, this); audio_tab = std::make_unique(system_, tab_group, *builder, this); cpu_tab = std::make_unique(system_, tab_group, *builder, this); @@ -108,7 +107,7 @@ void ConfigurePerGame::ApplyConfiguration() { system.ApplySettings(); Settings::LogSettings(); - game_config->Save(); + game_config->SaveAllValues(); } void ConfigurePerGame::changeEvent(QEvent* event) { diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index cc2513001..c8ee46c04 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.h @@ -12,9 +12,10 @@ #include "configuration/shared_widget.h" #include "core/file_sys/vfs_types.h" +#include "frontend_common/config.h" #include "vk_device_info.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configuration_shared.h" +#include "yuzu/configuration/qt_config.h" #include "yuzu/configuration/shared_translation.h" namespace Core { @@ -72,7 +73,7 @@ private: QGraphicsScene* scene; - std::unique_ptr game_config; + std::unique_ptr game_config; Core::System& system; std::unique_ptr builder; diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index 674a75a62..140a7fe5d 100644 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp @@ -19,7 +19,6 @@ #include "core/file_sys/xts_archive.h" #include "core/loader/loader.h" #include "ui_configure_per_game_addons.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_input.h" #include "yuzu/configuration/configure_per_game_addons.h" #include "yuzu/uisettings.h" diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp index f83705544..9572ff43c 100644 --- a/src/yuzu/configuration/configure_ringcon.cpp +++ b/src/yuzu/configuration/configure_ringcon.cpp @@ -8,6 +8,7 @@ #include #include +#include "configuration/qt_config.h" #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "input_common/drivers/keyboard.h" @@ -15,7 +16,6 @@ #include "input_common/main.h" #include "ui_configure_ringcon.h" #include "yuzu/bootmanager.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_ringcon.h" const std::array @@ -270,7 +270,7 @@ void ConfigureRingController::LoadConfiguration() { void ConfigureRingController::RestoreDefaults() { const std::string default_ring_string = InputCommon::GenerateAnalogParamFromKeys( - 0, 0, Config::default_ringcon_analogs[0], Config::default_ringcon_analogs[1], 0, 0.05f); + 0, 0, QtConfig::default_ringcon_analogs[0], QtConfig::default_ringcon_analogs[1], 0, 0.05f); emulated_controller->SetRingParam(Common::ParamPackage(default_ring_string)); UpdateUI(); } diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 0c8e5c8b4..7cbf43775 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -16,7 +16,6 @@ #include "core/core.h" #include "core/hle/service/time/time_manager.h" #include "ui_configure_system.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configure_system.h" #include "yuzu/configuration/shared_widget.h" diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.cpp b/src/yuzu/configuration/configure_touchscreen_advanced.cpp index 5a03e48df..94df6d9d3 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.cpp +++ b/src/yuzu/configuration/configure_touchscreen_advanced.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/settings.h" #include "ui_configure_touchscreen_advanced.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_touchscreen_advanced.h" ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent) diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index 82f3b6e78..dd43f0a0e 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp @@ -164,7 +164,7 @@ ConfigureUi::~ConfigureUi() = default; void ConfigureUi::ApplyConfiguration() { UISettings::values.theme = - ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); + ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString().toStdString(); UISettings::values.show_add_ons = ui->show_add_ons->isChecked(); UISettings::values.show_compat = ui->show_compat->isChecked(); UISettings::values.show_size = ui->show_size->isChecked(); @@ -191,9 +191,10 @@ void ConfigureUi::RequestGameListUpdate() { } void ConfigureUi::SetConfiguration() { - ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); + ui->theme_combobox->setCurrentIndex( + ui->theme_combobox->findData(QString::fromStdString(UISettings::values.theme))); ui->language_combobox->setCurrentIndex( - ui->language_combobox->findData(UISettings::values.language)); + ui->language_combobox->findData(QString::fromStdString(UISettings::values.language))); ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue()); ui->show_compat->setChecked(UISettings::values.show_compat.GetValue()); ui->show_size->setChecked(UISettings::values.show_size.GetValue()); diff --git a/src/yuzu/configuration/input_profiles.cpp b/src/yuzu/configuration/input_profiles.cpp index 41ef4250a..716efbccd 100644 --- a/src/yuzu/configuration/input_profiles.cpp +++ b/src/yuzu/configuration/input_profiles.cpp @@ -5,7 +5,7 @@ #include "common/fs/fs.h" #include "common/fs/path_util.h" -#include "yuzu/configuration/config.h" +#include "frontend_common/config.h" #include "yuzu/configuration/input_profiles.h" namespace FS = Common::FS; @@ -44,7 +44,7 @@ InputProfiles::InputProfiles() { if (IsINI(filename) && IsProfileNameValid(name_without_ext)) { map_profiles.insert_or_assign( name_without_ext, - std::make_unique(name_without_ext, Config::ConfigType::InputProfile)); + std::make_unique(name_without_ext, Config::ConfigType::InputProfile)); } return true; @@ -85,7 +85,7 @@ bool InputProfiles::CreateProfile(const std::string& profile_name, std::size_t p } map_profiles.insert_or_assign( - profile_name, std::make_unique(profile_name, Config::ConfigType::InputProfile)); + profile_name, std::make_unique(profile_name, Config::ConfigType::InputProfile)); return SaveProfile(profile_name, player_index); } @@ -113,7 +113,7 @@ bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t pla return false; } - map_profiles[profile_name]->ReadControlPlayerValue(player_index); + map_profiles[profile_name]->ReadQtControlPlayerValues(player_index); return true; } @@ -122,7 +122,7 @@ bool InputProfiles::SaveProfile(const std::string& profile_name, std::size_t pla return false; } - map_profiles[profile_name]->SaveControlPlayerValue(player_index); + map_profiles[profile_name]->SaveQtControlPlayerValues(player_index); return true; } diff --git a/src/yuzu/configuration/input_profiles.h b/src/yuzu/configuration/input_profiles.h index 2bf3e4250..023ec74a6 100644 --- a/src/yuzu/configuration/input_profiles.h +++ b/src/yuzu/configuration/input_profiles.h @@ -6,6 +6,8 @@ #include #include +#include "configuration/qt_config.h" + namespace Core { class System; } @@ -30,5 +32,5 @@ public: private: bool ProfileExistsInMap(const std::string& profile_name) const; - std::unordered_map> map_profiles; + std::unordered_map> map_profiles; }; diff --git a/src/yuzu/configuration/qt_config.cpp b/src/yuzu/configuration/qt_config.cpp new file mode 100644 index 000000000..82402ec70 --- /dev/null +++ b/src/yuzu/configuration/qt_config.cpp @@ -0,0 +1,548 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "input_common/main.h" +#include "qt_config.h" +#include "uisettings.h" + +const std::array QtConfig::default_buttons = { + Qt::Key_C, Qt::Key_X, Qt::Key_V, Qt::Key_Z, Qt::Key_F, + Qt::Key_G, Qt::Key_Q, Qt::Key_E, Qt::Key_R, Qt::Key_T, + Qt::Key_M, Qt::Key_N, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, + Qt::Key_Down, Qt::Key_Q, Qt::Key_E, 0, 0, + Qt::Key_Q, Qt::Key_E, +}; + +const std::array QtConfig::default_motions = { + Qt::Key_7, + Qt::Key_8, +}; + +const std::array, Settings::NativeAnalog::NumAnalogs> QtConfig::default_analogs{{ + { + Qt::Key_W, + Qt::Key_S, + Qt::Key_A, + Qt::Key_D, + }, + { + Qt::Key_I, + Qt::Key_K, + Qt::Key_J, + Qt::Key_L, + }, +}}; + +const std::array QtConfig::default_stick_mod = { + Qt::Key_Shift, + 0, +}; + +const std::array QtConfig::default_ringcon_analogs{{ + Qt::Key_A, + Qt::Key_D, +}}; + +QtConfig::QtConfig(const std::string& config_name, const ConfigType config_type) + : Config(config_type) { + Initialize(config_name); + if (config_type != ConfigType::InputProfile) { + ReadQtValues(); + SaveQtValues(); + } +} + +QtConfig::~QtConfig() { + if (global) { + QtConfig::SaveAllValues(); + } +} + +void QtConfig::ReloadAllValues() { + Reload(); + ReadQtValues(); + SaveQtValues(); +} + +void QtConfig::SaveAllValues() { + Save(); + SaveQtValues(); +} + +void QtConfig::ReadQtValues() { + if (global) { + ReadUIValues(); + } + ReadQtControlValues(); +} + +void QtConfig::ReadQtPlayerValues(const std::size_t player_index) { + std::string player_prefix; + if (type != ConfigType::InputProfile) { + player_prefix.append("player_").append(ToString(player_index)).append("_"); + } + + auto& player = Settings::values.players.GetValue()[player_index]; + if (IsCustomConfig()) { + const auto profile_name = + ReadStringSetting(std::string(player_prefix).append("profile_name")); + if (profile_name.empty()) { + // Use the global input config + player = Settings::values.players.GetValue(true)[player_index]; + return; + } + } + + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + auto& player_buttons = player.buttons[i]; + + player_buttons = ReadStringSetting( + std::string(player_prefix).append(Settings::NativeButton::mapping[i]), default_param); + if (player_buttons.empty()) { + player_buttons = default_param; + } + } + + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_stick_mod[i], 0.5f); + auto& player_analogs = player.analogs[i]; + + player_analogs = ReadStringSetting( + std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), default_param); + if (player_analogs.empty()) { + player_analogs = default_param; + } + } + + for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); + auto& player_motions = player.motions[i]; + + player_motions = ReadStringSetting( + std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), default_param); + if (player_motions.empty()) { + player_motions = default_param; + } + } +} + +void QtConfig::ReadHidbusValues() { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); + auto& ringcon_analogs = Settings::values.ringcon_analogs; + + ringcon_analogs = ReadStringSetting(std::string("ring_controller"), default_param); + if (ringcon_analogs.empty()) { + ringcon_analogs = default_param; + } +} + +void QtConfig::ReadDebugControlValues() { + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i]; + + debug_pad_buttons = ReadStringSetting( + std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), default_param); + if (debug_pad_buttons.empty()) { + debug_pad_buttons = default_param; + } + } + + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_stick_mod[i], 0.5f); + auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i]; + + debug_pad_analogs = ReadStringSetting( + std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), default_param); + if (debug_pad_analogs.empty()) { + debug_pad_analogs = default_param; + } + } +} + +void QtConfig::ReadQtControlValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); + + Settings::values.players.SetGlobal(!IsCustomConfig()); + for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { + ReadQtPlayerValues(p); + } + if (IsCustomConfig()) { + EndGroup(); + return; + } + ReadDebugControlValues(); + ReadHidbusValues(); + + EndGroup(); +} + +void QtConfig::ReadPathValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::Paths)); + + UISettings::values.roms_path = ReadStringSetting(std::string("romsPath")); + UISettings::values.symbols_path = ReadStringSetting(std::string("symbolsPath")); + UISettings::values.game_dir_deprecated = + ReadStringSetting(std::string("gameListRootDir"), std::string(".")); + UISettings::values.game_dir_deprecated_deepscan = + ReadBooleanSetting(std::string("gameListDeepScan"), std::make_optional(false)); + + const int gamedirs_size = BeginArray(std::string("gamedirs")); + for (int i = 0; i < gamedirs_size; ++i) { + SetArrayIndex(i); + UISettings::GameDir game_dir; + game_dir.path = ReadStringSetting(std::string("path")); + game_dir.deep_scan = + ReadBooleanSetting(std::string("deep_scan"), std::make_optional(false)); + game_dir.expanded = ReadBooleanSetting(std::string("expanded"), std::make_optional(true)); + UISettings::values.game_dirs.append(game_dir); + } + EndArray(); + + // Create NAND and SD card directories if empty, these are not removable through the UI, + // also carries over old game list settings if present + if (UISettings::values.game_dirs.empty()) { + UISettings::GameDir game_dir; + game_dir.path = std::string("SDMC"); + game_dir.expanded = true; + UISettings::values.game_dirs.append(game_dir); + game_dir.path = std::string("UserNAND"); + UISettings::values.game_dirs.append(game_dir); + game_dir.path = std::string("SysNAND"); + UISettings::values.game_dirs.append(game_dir); + if (UISettings::values.game_dir_deprecated != std::string(".")) { + game_dir.path = UISettings::values.game_dir_deprecated; + game_dir.deep_scan = UISettings::values.game_dir_deprecated_deepscan; + UISettings::values.game_dirs.append(game_dir); + } + } + UISettings::values.recent_files = + QString::fromStdString(ReadStringSetting(std::string("recentFiles"))) + .split(QStringLiteral(", "), Qt::SkipEmptyParts, Qt::CaseSensitive); + UISettings::values.language = ReadStringSetting(std::string("language"), std::string("")); + + EndGroup(); +} + +void QtConfig::ReadShortcutValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::Shortcuts)); + + for (const auto& [name, group, shortcut] : UISettings::default_hotkeys) { + BeginGroup(group); + BeginGroup(name); + + // No longer using ReadSetting for shortcut.second as it inaccurately returns a value of 1 + // for WidgetWithChildrenShortcut which is a value of 3. Needed to fix shortcuts the open + // a file dialog in windowed mode + UISettings::values.shortcuts.push_back( + {name, + group, + {ReadStringSetting(std::string("KeySeq"), shortcut.keyseq), + ReadStringSetting(std::string("Controller_KeySeq"), shortcut.controller_keyseq), + shortcut.context, + ReadBooleanSetting(std::string("Repeat"), std::optional(shortcut.repeat))}}); + + EndGroup(); // name + EndGroup(); // group + } + + EndGroup(); +} + +void QtConfig::ReadUIValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::Ui)); + + UISettings::values.theme = ReadStringSetting( + std::string("theme"), + std::string(UISettings::themes[static_cast(UISettings::default_theme)].second)); + + ReadUIGamelistValues(); + ReadUILayoutValues(); + ReadPathValues(); + ReadScreenshotValues(); + ReadShortcutValues(); + ReadMultiplayerValues(); + + ReadCategory(Settings::Category::Ui); + ReadCategory(Settings::Category::UiGeneral); + + EndGroup(); +} + +void QtConfig::ReadUIGamelistValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList)); + + ReadCategory(Settings::Category::UiGameList); + + const int favorites_size = BeginArray("favorites"); + for (int i = 0; i < favorites_size; i++) { + SetArrayIndex(i); + UISettings::values.favorited_ids.append(ReadIntegerSetting(std::string("program_id"))); + } + EndArray(); + + EndGroup(); +} + +void QtConfig::ReadUILayoutValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList)); + + ReadCategory(Settings::Category::UiLayout); + + EndGroup(); +} + +void QtConfig::ReadMultiplayerValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::Multiplayer)); + + ReadCategory(Settings::Category::Multiplayer); + + // Read ban list back + int size = BeginArray(std::string("username_ban_list")); + UISettings::values.multiplayer_ban_list.first.resize(size); + for (int i = 0; i < size; ++i) { + SetArrayIndex(i); + UISettings::values.multiplayer_ban_list.first[i] = + ReadStringSetting(std::string("username"), std::string("")); + } + EndArray(); + + size = BeginArray(std::string("ip_ban_list")); + UISettings::values.multiplayer_ban_list.second.resize(size); + for (int i = 0; i < size; ++i) { + UISettings::values.multiplayer_ban_list.second[i] = + ReadStringSetting("username", std::string("")); + } + EndArray(); + + EndGroup(); +} + +void QtConfig::SaveQtValues() { + if (global) { + SaveUIValues(); + } + SaveQtControlValues(); + + WriteToIni(); +} + +void QtConfig::SaveQtPlayerValues(const std::size_t player_index) { + std::string player_prefix; + if (type != ConfigType::InputProfile) { + player_prefix = std::string("player_").append(ToString(player_index)).append("_"); + } + + const auto& player = Settings::values.players.GetValue()[player_index]; + if (IsCustomConfig() && player.profile_name.empty()) { + // No custom profile selected + return; + } + + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + WriteSetting(std::string(player_prefix).append(Settings::NativeButton::mapping[i]), + player.buttons[i], std::make_optional(default_param)); + } + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_stick_mod[i], 0.5f); + WriteSetting(std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), + player.analogs[i], std::make_optional(default_param)); + } + for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); + WriteSetting(std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), + player.motions[i], std::make_optional(default_param)); + } +} + +void QtConfig::SaveDebugControlValues() { + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + WriteSetting(std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), + Settings::values.debug_pad_buttons[i], std::make_optional(default_param)); + } + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_stick_mod[i], 0.5f); + WriteSetting(std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), + Settings::values.debug_pad_analogs[i], std::make_optional(default_param)); + } +} + +void QtConfig::SaveHidbusValues() { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); + WriteSetting(std::string("ring_controller"), Settings::values.ringcon_analogs, + std::make_optional(default_param)); +} + +void QtConfig::SaveQtControlValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); + + Settings::values.players.SetGlobal(!IsCustomConfig()); + for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { + SaveQtPlayerValues(p); + } + if (IsCustomConfig()) { + EndGroup(); + return; + } + SaveDebugControlValues(); + SaveHidbusValues(); + + EndGroup(); +} + +void QtConfig::SavePathValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::Paths)); + + WriteSetting(std::string("romsPath"), UISettings::values.roms_path); + WriteSetting(std::string("symbolsPath"), UISettings::values.symbols_path); + BeginArray(std::string("gamedirs")); + for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) { + SetArrayIndex(i); + const auto& game_dir = UISettings::values.game_dirs[i]; + WriteSetting(std::string("path"), game_dir.path); + WriteSetting(std::string("deep_scan"), game_dir.deep_scan, std::make_optional(false)); + WriteSetting(std::string("expanded"), game_dir.expanded, std::make_optional(true)); + } + EndArray(); + + WriteSetting(std::string("recentFiles"), + UISettings::values.recent_files.join(QStringLiteral(", ")).toStdString()); + WriteSetting(std::string("language"), UISettings::values.language); + + EndGroup(); +} + +void QtConfig::SaveShortcutValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::Shortcuts)); + + // Lengths of UISettings::values.shortcuts & default_hotkeys are same. + // However, their ordering must also be the same. + for (std::size_t i = 0; i < UISettings::default_hotkeys.size(); i++) { + const auto& [name, group, shortcut] = UISettings::values.shortcuts[i]; + const auto& default_hotkey = UISettings::default_hotkeys[i].shortcut; + + BeginGroup(group); + BeginGroup(name); + + WriteSetting(std::string("KeySeq"), shortcut.keyseq, + std::make_optional(default_hotkey.keyseq)); + WriteSetting(std::string("Controller_KeySeq"), shortcut.controller_keyseq, + std::make_optional(default_hotkey.controller_keyseq)); + WriteSetting(std::string("Context"), shortcut.context, + std::make_optional(default_hotkey.context)); + WriteSetting(std::string("Repeat"), shortcut.repeat, + std::make_optional(default_hotkey.repeat)); + + EndGroup(); // name + EndGroup(); // group + } + + EndGroup(); +} + +void QtConfig::SaveUIValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::Ui)); + + WriteCategory(Settings::Category::Ui); + WriteCategory(Settings::Category::UiGeneral); + + WriteSetting(std::string("theme"), UISettings::values.theme, + std::make_optional(std::string( + UISettings::themes[static_cast(UISettings::default_theme)].second))); + + SaveUIGamelistValues(); + SaveUILayoutValues(); + SavePathValues(); + SaveScreenshotValues(); + SaveShortcutValues(); + SaveMultiplayerValues(); + + EndGroup(); +} + +void QtConfig::SaveUIGamelistValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList)); + + WriteCategory(Settings::Category::UiGameList); + + BeginArray(std::string("favorites")); + for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { + SetArrayIndex(i); + WriteSetting(std::string("program_id"), UISettings::values.favorited_ids[i]); + } + EndArray(); // favorites + + EndGroup(); +} + +void QtConfig::SaveUILayoutValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::UiLayout)); + + WriteCategory(Settings::Category::UiLayout); + + EndGroup(); +} + +void QtConfig::SaveMultiplayerValues() { + BeginGroup(std::string("Multiplayer")); + + WriteCategory(Settings::Category::Multiplayer); + + // Write ban list + BeginArray(std::string("username_ban_list")); + for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.first.size(); ++i) { + SetArrayIndex(static_cast(i)); + WriteSetting(std::string("username"), UISettings::values.multiplayer_ban_list.first[i]); + } + EndArray(); // username_ban_list + + BeginArray(std::string("ip_ban_list")); + for (std::size_t i = 0; i < UISettings::values.multiplayer_ban_list.second.size(); ++i) { + SetArrayIndex(static_cast(i)); + WriteSetting(std::string("ip"), UISettings::values.multiplayer_ban_list.second[i]); + } + EndArray(); // ip_ban_list + + EndGroup(); +} + +std::vector& QtConfig::FindRelevantList(Settings::Category category) { + auto& map = Settings::values.linkage.by_category; + if (map.contains(category)) { + return Settings::values.linkage.by_category[category]; + } + return UISettings::values.linkage.by_category[category]; +} + +void QtConfig::ReadQtControlPlayerValues(std::size_t player_index) { + BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); + + ReadPlayerValues(player_index); + ReadQtPlayerValues(player_index); + + EndGroup(); +} + +void QtConfig::SaveQtControlPlayerValues(std::size_t player_index) { + BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); + + SavePlayerValues(player_index); + SaveQtPlayerValues(player_index); + + EndGroup(); + + WriteToIni(); +} diff --git a/src/yuzu/configuration/qt_config.h b/src/yuzu/configuration/qt_config.h new file mode 100644 index 000000000..dc2dceb4d --- /dev/null +++ b/src/yuzu/configuration/qt_config.h @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "frontend_common/config.h" + +class QtConfig final : public Config { +public: + explicit QtConfig(const std::string& config_name = "qt-config", + ConfigType config_type = ConfigType::GlobalConfig); + ~QtConfig() override; + + void ReloadAllValues() override; + void SaveAllValues() override; + + void ReadQtControlPlayerValues(std::size_t player_index); + void SaveQtControlPlayerValues(std::size_t player_index); + +protected: + void ReadQtValues(); + void ReadQtPlayerValues(std::size_t player_index); + void ReadQtControlValues(); + void ReadHidbusValues() override; + void ReadDebugControlValues() override; + void ReadPathValues() override; + void ReadShortcutValues() override; + void ReadUIValues() override; + void ReadUIGamelistValues() override; + void ReadUILayoutValues() override; + void ReadMultiplayerValues() override; + + void SaveQtValues(); + void SaveQtPlayerValues(std::size_t player_index); + void SaveQtControlValues(); + void SaveHidbusValues() override; + void SaveDebugControlValues() override; + void SavePathValues() override; + void SaveShortcutValues() override; + void SaveUIValues() override; + void SaveUIGamelistValues() override; + void SaveUILayoutValues() override; + void SaveMultiplayerValues() override; + + std::vector& FindRelevantList(Settings::Category category) override; + +public: + static const std::array default_buttons; + static const std::array default_motions; + static const std::array, Settings::NativeAnalog::NumAnalogs> default_analogs; + static const std::array default_stick_mod; + static const std::array default_ringcon_analogs; +}; diff --git a/src/yuzu/configuration/shared_translation.h b/src/yuzu/configuration/shared_translation.h index 99a0e808c..d5fc3b8de 100644 --- a/src/yuzu/configuration/shared_translation.h +++ b/src/yuzu/configuration/shared_translation.h @@ -10,6 +10,7 @@ #include #include #include "common/common_types.h" +#include "common/settings.h" class QWidget; @@ -22,4 +23,46 @@ std::unique_ptr InitializeTranslations(QWidget* parent); std::unique_ptr ComboboxEnumeration(QWidget* parent); +static const std::map anti_aliasing_texts_map = { + {Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))}, + {Settings::AntiAliasing::Fxaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FXAA"))}, + {Settings::AntiAliasing::Smaa, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SMAA"))}, +}; + +static const std::map scaling_filter_texts_map = { + {Settings::ScalingFilter::NearestNeighbor, + QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Nearest"))}, + {Settings::ScalingFilter::Bilinear, + QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bilinear"))}, + {Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Bicubic"))}, + {Settings::ScalingFilter::Gaussian, + QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Gaussian"))}, + {Settings::ScalingFilter::ScaleForce, + QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "ScaleForce"))}, + {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))}, +}; + +static const std::map use_docked_mode_texts_map = { + {Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))}, + {Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))}, +}; + +static const std::map gpu_accuracy_texts_map = { + {Settings::GpuAccuracy::Normal, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Normal"))}, + {Settings::GpuAccuracy::High, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "High"))}, + {Settings::GpuAccuracy::Extreme, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Extreme"))}, +}; + +static const std::map renderer_backend_texts_map = { + {Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Vulkan"))}, + {Settings::RendererBackend::OpenGL, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "OpenGL"))}, + {Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Null"))}, +}; + +static const std::map shader_backend_texts_map = { + {Settings::ShaderBackend::Glsl, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLSL"))}, + {Settings::ShaderBackend::Glasm, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "GLASM"))}, + {Settings::ShaderBackend::SpirV, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "SPIRV"))}, +}; + } // namespace ConfigurationShared diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 7049c57b6..6d227ef8d 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -36,10 +36,8 @@ constexpr std::array, 10> WaitTreeColors{{ bool IsDarkTheme() { const auto& theme = UISettings::values.theme; - return theme == QStringLiteral("qdarkstyle") || - theme == QStringLiteral("qdarkstyle_midnight_blue") || - theme == QStringLiteral("colorful_dark") || - theme == QStringLiteral("colorful_midnight_blue"); + return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") || + theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue"); } } // namespace diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index f294dc23d..59b317135 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -278,7 +278,7 @@ void GameList::OnUpdateThemedIcons() { case GameListItemType::CustomDir: { const UISettings::GameDir& game_dir = UISettings::values.game_dirs[child->data(GameListDir::GameDirRole).toInt()]; - const QString icon_name = QFileInfo::exists(game_dir.path) + const QString icon_name = QFileInfo::exists(QString::fromStdString(game_dir.path)) ? QStringLiteral("folder") : QStringLiteral("bad_folder"); child->setData( @@ -727,7 +727,8 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) { }); connect(open_directory_location, &QAction::triggered, [this, game_dir_index] { - emit OpenDirectory(UISettings::values.game_dirs[game_dir_index].path); + emit OpenDirectory( + QString::fromStdString(UISettings::values.game_dirs[game_dir_index].path)); }); } @@ -869,7 +870,7 @@ const QStringList GameList::supported_file_extensions = { QStringLiteral("xci"), QStringLiteral("nsp"), QStringLiteral("kip")}; void GameList::RefreshGameDirectory() { - if (!UISettings::values.game_dirs.isEmpty() && current_worker != nullptr) { + if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) { LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list."); PopulateAsync(UISettings::values.game_dirs); } diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index 86a0c41d9..c330b574f 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h @@ -286,13 +286,13 @@ public: setData(QObject::tr("System Titles"), Qt::DisplayRole); break; case GameListItemType::CustomDir: { - const QString icon_name = QFileInfo::exists(game_dir->path) - ? QStringLiteral("folder") - : QStringLiteral("bad_folder"); + const QString path = QString::fromStdString(game_dir->path); + const QString icon_name = + QFileInfo::exists(path) ? QStringLiteral("folder") : QStringLiteral("bad_folder"); setData(QIcon::fromTheme(icon_name).pixmap(icon_size).scaled( icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::DecorationRole); - setData(game_dir->path, Qt::DisplayRole); + setData(path, Qt::DisplayRole); break; } default: diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 69be21027..ad3eada94 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -456,26 +456,26 @@ void GameListWorker::run() { break; } - if (game_dir.path == QStringLiteral("SDMC")) { + if (game_dir.path == std::string("SDMC")) { auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir); DirEntryReady(game_list_dir); AddTitlesToGameList(game_list_dir); - } else if (game_dir.path == QStringLiteral("UserNAND")) { + } else if (game_dir.path == std::string("UserNAND")) { auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir); DirEntryReady(game_list_dir); AddTitlesToGameList(game_list_dir); - } else if (game_dir.path == QStringLiteral("SysNAND")) { + } else if (game_dir.path == std::string("SysNAND")) { auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir); DirEntryReady(game_list_dir); AddTitlesToGameList(game_list_dir); } else { - watch_list.append(game_dir.path); + watch_list.append(QString::fromStdString(game_dir.path)); auto* const game_list_dir = new GameListDir(game_dir); DirEntryReady(game_list_dir); - ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(), - game_dir.deep_scan, game_list_dir); - ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(), - game_dir.deep_scan, game_list_dir); + ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path, game_dir.deep_scan, + game_list_dir); + ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path, game_dir.deep_scan, + game_list_dir); } } diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp index 6530186c1..eebfbf155 100644 --- a/src/yuzu/hotkeys.cpp +++ b/src/yuzu/hotkeys.cpp @@ -19,7 +19,7 @@ void HotkeyRegistry::SaveHotkeys() { for (const auto& hotkey : group.second) { UISettings::values.shortcuts.push_back( {hotkey.first, group.first, - UISettings::ContextualShortcut({hotkey.second.keyseq.toString(), + UISettings::ContextualShortcut({hotkey.second.keyseq.toString().toStdString(), hotkey.second.controller_keyseq, hotkey.second.context, hotkey.second.repeat})}); } @@ -31,12 +31,12 @@ void HotkeyRegistry::LoadHotkeys() { // beginGroup() for (auto shortcut : UISettings::values.shortcuts) { Hotkey& hk = hotkey_groups[shortcut.group][shortcut.name]; - if (!shortcut.shortcut.keyseq.isEmpty()) { - hk.keyseq = - QKeySequence::fromString(shortcut.shortcut.keyseq, QKeySequence::NativeText); + if (!shortcut.shortcut.keyseq.empty()) { + hk.keyseq = QKeySequence::fromString(QString::fromStdString(shortcut.shortcut.keyseq), + QKeySequence::NativeText); hk.context = static_cast(shortcut.shortcut.context); } - if (!shortcut.shortcut.controller_keyseq.isEmpty()) { + if (!shortcut.shortcut.controller_keyseq.empty()) { hk.controller_keyseq = shortcut.shortcut.controller_keyseq; } if (hk.shortcut) { @@ -51,7 +51,8 @@ void HotkeyRegistry::LoadHotkeys() { } } -QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) { +QShortcut* HotkeyRegistry::GetHotkey(const std::string& group, const std::string& action, + QWidget* widget) { Hotkey& hk = hotkey_groups[group][action]; if (!hk.shortcut) { @@ -62,7 +63,8 @@ QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action return hk.shortcut; } -ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const QString& group, const QString& action, +ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const std::string& group, + const std::string& action, Core::HID::EmulatedController* controller) { Hotkey& hk = hotkey_groups[group][action]; @@ -74,12 +76,12 @@ ControllerShortcut* HotkeyRegistry::GetControllerHotkey(const QString& group, co return hk.controller_shortcut; } -QKeySequence HotkeyRegistry::GetKeySequence(const QString& group, const QString& action) { +QKeySequence HotkeyRegistry::GetKeySequence(const std::string& group, const std::string& action) { return hotkey_groups[group][action].keyseq; } -Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const QString& group, - const QString& action) { +Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const std::string& group, + const std::string& action) { return hotkey_groups[group][action].context; } @@ -101,10 +103,10 @@ void ControllerShortcut::SetKey(const ControllerButtonSequence& buttons) { button_sequence = buttons; } -void ControllerShortcut::SetKey(const QString& buttons_shortcut) { +void ControllerShortcut::SetKey(const std::string& buttons_shortcut) { ControllerButtonSequence sequence{}; - name = buttons_shortcut.toStdString(); - std::istringstream command_line(buttons_shortcut.toStdString()); + name = buttons_shortcut; + std::istringstream command_line(buttons_shortcut); std::string line; while (std::getline(command_line, line, '+')) { if (line.empty()) { diff --git a/src/yuzu/hotkeys.h b/src/yuzu/hotkeys.h index 56eee8d82..e11332d2e 100644 --- a/src/yuzu/hotkeys.h +++ b/src/yuzu/hotkeys.h @@ -33,7 +33,7 @@ public: ~ControllerShortcut(); void SetKey(const ControllerButtonSequence& buttons); - void SetKey(const QString& buttons_shortcut); + void SetKey(const std::string& buttons_shortcut); ControllerButtonSequence ButtonSequence() const; @@ -88,8 +88,8 @@ public: * will be the same. Thus, you shouldn't rely on the caller really being the * QShortcut's parent. */ - QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget); - ControllerShortcut* GetControllerHotkey(const QString& group, const QString& action, + QShortcut* GetHotkey(const std::string& group, const std::string& action, QWidget* widget); + ControllerShortcut* GetControllerHotkey(const std::string& group, const std::string& action, Core::HID::EmulatedController* controller); /** @@ -98,7 +98,7 @@ public: * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger"). * @param action Name of the action (e.g. "Start Emulation", "Load Image"). */ - QKeySequence GetKeySequence(const QString& group, const QString& action); + QKeySequence GetKeySequence(const std::string& group, const std::string& action); /** * Returns a Qt::ShortcutContext object who can be connected to other @@ -108,20 +108,20 @@ public: * "Debugger"). * @param action Name of the action (e.g. "Start Emulation", "Load Image"). */ - Qt::ShortcutContext GetShortcutContext(const QString& group, const QString& action); + Qt::ShortcutContext GetShortcutContext(const std::string& group, const std::string& action); private: struct Hotkey { QKeySequence keyseq; - QString controller_keyseq; + std::string controller_keyseq; QShortcut* shortcut = nullptr; ControllerShortcut* controller_shortcut = nullptr; Qt::ShortcutContext context = Qt::WindowShortcut; bool repeat; }; - using HotkeyMap = std::map; - using HotkeyGroupMap = std::map; + using HotkeyMap = std::map; + using HotkeyGroupMap = std::map; HotkeyGroupMap hotkey_groups; }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f22db233b..defe45198 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -128,6 +128,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "core/loader/loader.h" #include "core/perf_stats.h" #include "core/telemetry_session.h" +#include "frontend_common/config.h" #include "input_common/drivers/tas_input.h" #include "input_common/drivers/virtual_amiibo.h" #include "input_common/main.h" @@ -140,9 +141,9 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "yuzu/bootmanager.h" #include "yuzu/compatdb.h" #include "yuzu/compatibility_list.h" -#include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_dialog.h" #include "yuzu/configuration/configure_input_per_game.h" +#include "yuzu/configuration/qt_config.h" #include "yuzu/debugger/console.h" #include "yuzu/debugger/controller.h" #include "yuzu/debugger/profiler.h" @@ -311,7 +312,7 @@ bool GMainWindow::CheckDarkMode() { #endif // __unix__ } -GMainWindow::GMainWindow(std::unique_ptr config_, bool has_broken_vulkan) +GMainWindow::GMainWindow(std::unique_ptr config_, bool has_broken_vulkan) : ui{std::make_unique()}, system{std::make_unique()}, input_subsystem{std::make_shared()}, config{std::move(config_)}, vfs{std::make_shared()}, @@ -676,7 +677,7 @@ void GMainWindow::ControllerSelectorReconfigureControllers( // Don't forget to apply settings. system->HIDCore().DisableAllControllerConfiguration(); system->ApplySettings(); - config->Save(); + config->SaveAllValues(); UpdateStatusButtons(); @@ -1129,7 +1130,7 @@ void GMainWindow::InitializeWidgets() { connect(aa_status_button, &QPushButton::customContextMenuRequested, [this](const QPoint& menu_location) { QMenu context_menu; - for (auto const& aa_text_pair : Config::anti_aliasing_texts_map) { + for (auto const& aa_text_pair : ConfigurationShared::anti_aliasing_texts_map) { context_menu.addAction(aa_text_pair.second, [this, aa_text_pair] { Settings::values.anti_aliasing.SetValue(aa_text_pair.first); UpdateAAText(); @@ -1153,7 +1154,7 @@ void GMainWindow::InitializeWidgets() { connect(filter_status_button, &QPushButton::customContextMenuRequested, [this](const QPoint& menu_location) { QMenu context_menu; - for (auto const& filter_text_pair : Config::scaling_filter_texts_map) { + for (auto const& filter_text_pair : ConfigurationShared::scaling_filter_texts_map) { context_menu.addAction(filter_text_pair.second, [this, filter_text_pair] { Settings::values.scaling_filter.SetValue(filter_text_pair.first); UpdateFilterText(); @@ -1176,7 +1177,7 @@ void GMainWindow::InitializeWidgets() { [this](const QPoint& menu_location) { QMenu context_menu; - for (auto const& pair : Config::use_docked_mode_texts_map) { + for (auto const& pair : ConfigurationShared::use_docked_mode_texts_map) { context_menu.addAction(pair.second, [this, &pair] { if (pair.first != Settings::values.use_docked_mode.GetValue()) { OnToggleDockedMode(); @@ -1200,7 +1201,7 @@ void GMainWindow::InitializeWidgets() { [this](const QPoint& menu_location) { QMenu context_menu; - for (auto const& gpu_accuracy_pair : Config::gpu_accuracy_texts_map) { + for (auto const& gpu_accuracy_pair : ConfigurationShared::gpu_accuracy_texts_map) { if (gpu_accuracy_pair.first == Settings::GpuAccuracy::Extreme) { continue; } @@ -1229,7 +1230,8 @@ void GMainWindow::InitializeWidgets() { [this](const QPoint& menu_location) { QMenu context_menu; - for (auto const& renderer_backend_pair : Config::renderer_backend_texts_map) { + for (auto const& renderer_backend_pair : + ConfigurationShared::renderer_backend_texts_map) { if (renderer_backend_pair.first == Settings::RendererBackend::Null) { continue; } @@ -1294,16 +1296,17 @@ void GMainWindow::InitializeRecentFileMenuActions() { void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name, const bool tas_allowed) { - static const QString main_window = QStringLiteral("Main Window"); - action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name)); - action->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, action_name)); + static const auto main_window = std::string("Main Window"); + action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name.toStdString())); + action->setShortcutContext( + hotkey_registry.GetShortcutContext(main_window, action_name.toStdString())); action->setAutoRepeat(false); this->addAction(action); auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); const auto* controller_hotkey = - hotkey_registry.GetControllerHotkey(main_window, action_name, controller); + hotkey_registry.GetControllerHotkey(main_window, action_name.toStdString(), controller); connect( controller_hotkey, &ControllerShortcut::Activated, this, [action, tas_allowed, this] { @@ -1335,10 +1338,11 @@ void GMainWindow::InitializeHotkeys() { static const QString main_window = QStringLiteral("Main Window"); const auto connect_shortcut = [&](const QString& action_name, const Fn& function) { - const auto* hotkey = hotkey_registry.GetHotkey(main_window, action_name, this); + const auto* hotkey = + hotkey_registry.GetHotkey(main_window.toStdString(), action_name.toStdString(), this); auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); - const auto* controller_hotkey = - hotkey_registry.GetControllerHotkey(main_window, action_name, controller); + const auto* controller_hotkey = hotkey_registry.GetControllerHotkey( + main_window.toStdString(), action_name.toStdString(), controller); connect(hotkey, &QShortcut::activated, this, function); connect(controller_hotkey, &ControllerShortcut::Activated, this, function, Qt::QueuedConnection); @@ -1918,7 +1922,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t // Save configurations UpdateUISettings(); game_list->SaveInterfaceLayout(); - config->Save(); + config->SaveAllValues(); u64 title_id{0}; @@ -1936,7 +1940,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()) : fmt::format("{:016X}", title_id); - Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig); + QtConfig per_game_config(config_file_name, Config::ConfigType::PerGameConfig); system->HIDCore().ReloadInputDevices(); system->ApplySettings(); } @@ -3135,7 +3139,7 @@ void GMainWindow::OnGameListAddDirectory() { return; } - UISettings::GameDir game_dir{dir_path, false, true}; + UISettings::GameDir game_dir{dir_path.toStdString(), false, true}; if (!UISettings::values.game_dirs.contains(game_dir)) { UISettings::values.game_dirs.append(game_dir); game_list->PopulateAsync(UISettings::values.game_dirs); @@ -3181,14 +3185,14 @@ void GMainWindow::OnMenuLoadFile() { "%1 is an identifier for the Switch executable file extensions.") .arg(extensions); const QString filename = QFileDialog::getOpenFileName( - this, tr("Load File"), UISettings::values.roms_path, file_filter); + this, tr("Load File"), QString::fromStdString(UISettings::values.roms_path), file_filter); is_load_file_select_active = false; if (filename.isEmpty()) { return; } - UISettings::values.roms_path = QFileInfo(filename).path(); + UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); BootGame(filename); } @@ -3221,7 +3225,8 @@ void GMainWindow::OnMenuInstallToNAND() { "Image (*.xci)"); QStringList filenames = QFileDialog::getOpenFileNames( - this, tr("Install Files"), UISettings::values.roms_path, file_filter); + this, tr("Install Files"), QString::fromStdString(UISettings::values.roms_path), + file_filter); if (filenames.isEmpty()) { return; @@ -3239,7 +3244,7 @@ void GMainWindow::OnMenuInstallToNAND() { } // Save folder location of the first selected file - UISettings::values.roms_path = QFileInfo(filenames[0]).path(); + UISettings::values.roms_path = QFileInfo(filenames[0]).path().toStdString(); int remaining = filenames.size(); @@ -3584,7 +3589,7 @@ void GMainWindow::OnExit() { void GMainWindow::OnSaveConfig() { system->ApplySettings(); - config->Save(); + config->SaveAllValues(); } void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) { @@ -3840,7 +3845,7 @@ void GMainWindow::OnConfigure() { Settings::values.disabled_addons.clear(); - config = std::make_unique(); + config = std::make_unique(); UISettings::values.reset_to_defaults = false; UISettings::values.game_dirs = std::move(old_game_dirs); @@ -3875,7 +3880,7 @@ void GMainWindow::OnConfigure() { UISettings::values.configuration_applied = false; - config->Save(); + config->SaveAllValues(); if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) { render_window->installEventFilter(render_window); @@ -4091,7 +4096,7 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file UISettings::values.configuration_applied = false; if (!is_powered_on) { - config->Save(); + config->SaveAllValues(); } } @@ -4324,7 +4329,7 @@ void GMainWindow::OnAlbum() { system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::PhotoViewer); const auto filename = QString::fromStdString(album_nca->GetFullPath()); - UISettings::values.roms_path = QFileInfo(filename).path(); + UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); BootGame(filename, AlbumId); } @@ -4348,7 +4353,7 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { system->GetAppletManager().SetCabinetMode(mode); const auto filename = QString::fromStdString(cabinet_nca->GetFullPath()); - UISettings::values.roms_path = QFileInfo(filename).path(); + UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); BootGame(filename, CabinetId); } @@ -4371,7 +4376,7 @@ void GMainWindow::OnMiiEdit() { system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit); const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); - UISettings::values.roms_path = QFileInfo(filename).path(); + UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); BootGame(filename, MiiEditId); } @@ -4396,7 +4401,7 @@ void GMainWindow::OnOpenControllerMenu() { system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Controller); const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath())); - UISettings::values.roms_path = QFileInfo(filename).path(); + UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); BootGame(filename, ControllerAppletId); } @@ -4590,7 +4595,8 @@ void GMainWindow::UpdateStatusBar() { void GMainWindow::UpdateGPUAccuracyButton() { const auto gpu_accuracy = Settings::values.gpu_accuracy.GetValue(); - const auto gpu_accuracy_text = Config::gpu_accuracy_texts_map.find(gpu_accuracy)->second; + const auto gpu_accuracy_text = + ConfigurationShared::gpu_accuracy_texts_map.find(gpu_accuracy)->second; gpu_accuracy_button->setText(gpu_accuracy_text.toUpper()); gpu_accuracy_button->setChecked(gpu_accuracy != Settings::GpuAccuracy::Normal); } @@ -4599,31 +4605,32 @@ void GMainWindow::UpdateDockedButton() { const auto console_mode = Settings::values.use_docked_mode.GetValue(); dock_status_button->setChecked(Settings::IsDockedMode()); dock_status_button->setText( - Config::use_docked_mode_texts_map.find(console_mode)->second.toUpper()); + ConfigurationShared::use_docked_mode_texts_map.find(console_mode)->second.toUpper()); } void GMainWindow::UpdateAPIText() { const auto api = Settings::values.renderer_backend.GetValue(); - const auto renderer_status_text = Config::renderer_backend_texts_map.find(api)->second; + const auto renderer_status_text = + ConfigurationShared::renderer_backend_texts_map.find(api)->second; renderer_status_button->setText( api == Settings::RendererBackend::OpenGL - ? tr("%1 %2").arg( - renderer_status_text.toUpper(), - Config::shader_backend_texts_map.find(Settings::values.shader_backend.GetValue()) - ->second) + ? tr("%1 %2").arg(renderer_status_text.toUpper(), + ConfigurationShared::shader_backend_texts_map + .find(Settings::values.shader_backend.GetValue()) + ->second) : renderer_status_text.toUpper()); } void GMainWindow::UpdateFilterText() { const auto filter = Settings::values.scaling_filter.GetValue(); - const auto filter_text = Config::scaling_filter_texts_map.find(filter)->second; + const auto filter_text = ConfigurationShared::scaling_filter_texts_map.find(filter)->second; filter_status_button->setText(filter == Settings::ScalingFilter::Fsr ? tr("FSR") : filter_text.toUpper()); } void GMainWindow::UpdateAAText() { const auto aa_mode = Settings::values.anti_aliasing.GetValue(); - const auto aa_text = Config::anti_aliasing_texts_map.find(aa_mode)->second; + const auto aa_text = ConfigurationShared::anti_aliasing_texts_map.find(aa_mode)->second; aa_status_button->setText(aa_mode == Settings::AntiAliasing::None ? QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "NO AA")) : aa_text.toUpper()); @@ -4926,6 +4933,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) { UpdateUISettings(); game_list->SaveInterfaceLayout(); + UISettings::SaveWindowState(); hotkey_registry.SaveHotkeys(); // Unload controllers early @@ -5080,9 +5088,9 @@ static void AdjustLinkColor() { } void GMainWindow::UpdateUITheme() { - const QString default_theme = - QString::fromUtf8(UISettings::themes[static_cast(Config::default_theme)].second); - QString current_theme = UISettings::values.theme; + const QString default_theme = QString::fromUtf8( + UISettings::themes[static_cast(UISettings::default_theme)].second); + QString current_theme = QString::fromStdString(UISettings::values.theme); if (current_theme.isEmpty()) { current_theme = default_theme; @@ -5110,7 +5118,7 @@ void GMainWindow::UpdateUITheme() { QFile f(theme_uri); if (!f.open(QFile::ReadOnly | QFile::Text)) { LOG_ERROR(Frontend, "Unable to open style \"{}\", fallback to the default theme", - UISettings::values.theme.toStdString()); + UISettings::values.theme); current_theme = default_theme; } } @@ -5123,7 +5131,7 @@ void GMainWindow::UpdateUITheme() { setStyleSheet(ts.readAll()); } else { LOG_ERROR(Frontend, "Unable to set style \"{}\", stylesheet file not found", - UISettings::values.theme.toStdString()); + UISettings::values.theme); qApp->setStyleSheet({}); setStyleSheet({}); } @@ -5132,27 +5140,28 @@ void GMainWindow::UpdateUITheme() { void GMainWindow::LoadTranslation() { bool loaded; - if (UISettings::values.language.isEmpty()) { + if (UISettings::values.language.empty()) { // If the selected language is empty, use system locale loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/")); } else { // Otherwise load from the specified file - loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/")); + loaded = translator.load(QString::fromStdString(UISettings::values.language), + QStringLiteral(":/languages/")); } if (loaded) { qApp->installTranslator(&translator); } else { - UISettings::values.language = QStringLiteral("en"); + UISettings::values.language = std::string("en"); } } void GMainWindow::OnLanguageChanged(const QString& locale) { - if (UISettings::values.language != QStringLiteral("en")) { + if (UISettings::values.language != std::string("en")) { qApp->removeTranslator(&translator); } - UISettings::values.language = locale; + UISettings::values.language = locale.toStdString(); LoadTranslation(); ui->retranslateUi(this); multiplayer_state->retranslateUi(); @@ -5178,7 +5187,7 @@ void GMainWindow::changeEvent(QEvent* event) { // UpdateUITheme is a decent work around if (event->type() == QEvent::PaletteChange) { const QPalette test_palette(qApp->palette()); - const QString current_theme = UISettings::values.theme; + const QString current_theme = QString::fromStdString(UISettings::values.theme); // Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too static QColor last_window_color; const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window); @@ -5272,7 +5281,8 @@ static void SetHighDPIAttributes() { } int main(int argc, char* argv[]) { - std::unique_ptr config = std::make_unique(); + std::unique_ptr config = std::make_unique(); + UISettings::RestoreWindowState(config); bool has_broken_vulkan = false; bool is_child = false; if (CheckEnvVars(&is_child)) { diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 49ee1e1d2..c989c079d 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -15,6 +15,7 @@ #include "common/announce_multiplayer_room.h" #include "common/common_types.h" +#include "configuration/qt_config.h" #include "input_common/drivers/tas_input.h" #include "yuzu/compatibility_list.h" #include "yuzu/hotkeys.h" @@ -26,7 +27,7 @@ #include #endif -class Config; +class QtConfig; class ClickableLabel; class EmuThread; class GameList; @@ -185,7 +186,7 @@ class GMainWindow : public QMainWindow { public: void filterBarSetChecked(bool state); void UpdateUITheme(); - explicit GMainWindow(std::unique_ptr config_, bool has_broken_vulkan); + explicit GMainWindow(std::unique_ptr config_, bool has_broken_vulkan); ~GMainWindow() override; bool DropAction(QDropEvent* event); @@ -521,7 +522,7 @@ private: QSlider* volume_slider = nullptr; QTimer status_bar_update_timer; - std::unique_ptr config; + std::unique_ptr config; // Whether emulation is currently running in yuzu. bool emulation_running = false; diff --git a/src/yuzu/uisettings.cpp b/src/yuzu/uisettings.cpp index 1c833767b..7bb7e95af 100644 --- a/src/yuzu/uisettings.cpp +++ b/src/yuzu/uisettings.cpp @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include +#include "common/fs/fs.h" +#include "common/fs/path_util.h" #include "yuzu/uisettings.h" #ifndef CANNOT_EXPLICITLY_INSTANTIATE @@ -15,6 +18,8 @@ template class Setting; } // namespace Settings #endif +namespace FS = Common::FS; + namespace UISettings { const Themes themes{{ @@ -28,10 +33,8 @@ const Themes themes{{ bool IsDarkTheme() { const auto& theme = UISettings::values.theme; - return theme == QStringLiteral("qdarkstyle") || - theme == QStringLiteral("qdarkstyle_midnight_blue") || - theme == QStringLiteral("colorful_dark") || - theme == QStringLiteral("colorful_midnight_blue"); + return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") || + theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue"); } Values values = {}; @@ -52,4 +55,58 @@ u32 CalculateWidth(u32 height, Settings::AspectRatio ratio) { return height * 16 / 9; } +void SaveWindowState() { + const auto window_state_config_loc = + FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "window_state.ini"); + + void(FS::CreateParentDir(window_state_config_loc)); + QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat); + + config.setValue(QStringLiteral("geometry"), values.geometry); + config.setValue(QStringLiteral("state"), values.state); + config.setValue(QStringLiteral("geometryRenderWindow"), values.renderwindow_geometry); + config.setValue(QStringLiteral("gameListHeaderState"), values.gamelist_header_state); + config.setValue(QStringLiteral("microProfileDialogGeometry"), values.microprofile_geometry); + + config.sync(); +} + +void RestoreWindowState(std::unique_ptr& qtConfig) { + const auto window_state_config_loc = + FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "window_state.ini"); + + // Migrate window state from old location + if (!FS::Exists(window_state_config_loc) && qtConfig->Exists("UI", "UILayout\\geometry")) { + const auto config_loc = + FS::PathToUTF8String(FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "qt-config.ini"); + QSettings config(QString::fromStdString(config_loc), QSettings::IniFormat); + + config.beginGroup(QStringLiteral("UI")); + config.beginGroup(QStringLiteral("UILayout")); + values.geometry = config.value(QStringLiteral("geometry")).toByteArray(); + values.state = config.value(QStringLiteral("state")).toByteArray(); + values.renderwindow_geometry = + config.value(QStringLiteral("geometryRenderWindow")).toByteArray(); + values.gamelist_header_state = + config.value(QStringLiteral("gameListHeaderState")).toByteArray(); + values.microprofile_geometry = + config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray(); + config.endGroup(); + config.endGroup(); + return; + } + + void(FS::CreateParentDir(window_state_config_loc)); + const QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat); + + values.geometry = config.value(QStringLiteral("geometry")).toByteArray(); + values.state = config.value(QStringLiteral("state")).toByteArray(); + values.renderwindow_geometry = + config.value(QStringLiteral("geometryRenderWindow")).toByteArray(); + values.gamelist_header_state = + config.value(QStringLiteral("gameListHeaderState")).toByteArray(); + values.microprofile_geometry = + config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray(); +} + } // namespace UISettings diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 3485a6347..549a39e1b 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -14,6 +14,7 @@ #include "common/common_types.h" #include "common/settings.h" #include "common/settings_enums.h" +#include "configuration/qt_config.h" using Settings::Category; using Settings::ConfirmStop; @@ -37,15 +38,15 @@ namespace UISettings { bool IsDarkTheme(); struct ContextualShortcut { - QString keyseq; - QString controller_keyseq; + std::string keyseq; + std::string controller_keyseq; int context; bool repeat; }; struct Shortcut { - QString name; - QString group; + std::string name; + std::string group; ContextualShortcut shortcut; }; @@ -58,11 +59,19 @@ enum class Theme { MidnightBlueColorful, }; +static constexpr Theme default_theme{ +#ifdef _WIN32 + Theme::DarkColorful +#else + Theme::DefaultColorful +#endif +}; + using Themes = std::array, 6>; extern const Themes themes; struct GameDir { - QString path; + std::string path; bool deep_scan = false; bool expanded = false; bool operator==(const GameDir& rhs) const { @@ -144,15 +153,15 @@ struct Values { Category::Screenshots}; Setting screenshot_height{linkage, 0, "screenshot_height", Category::Screenshots}; - QString roms_path; - QString symbols_path; - QString game_dir_deprecated; + std::string roms_path; + std::string symbols_path; + std::string game_dir_deprecated; bool game_dir_deprecated_deepscan; - QVector game_dirs; + QVector game_dirs; QStringList recent_files; - QString language; + std::string language; - QString theme; + std::string theme; // Shortcut name std::vector shortcuts; @@ -206,6 +215,54 @@ extern Values values; u32 CalculateWidth(u32 height, Settings::AspectRatio ratio); +void SaveWindowState(); +void RestoreWindowState(std::unique_ptr& qtConfig); + +// This shouldn't have anything except static initializers (no functions). So +// QKeySequence(...).toString() is NOT ALLOWED HERE. +// This must be in alphabetical order according to action name as it must have the same order as +// UISetting::values.shortcuts, which is alphabetically ordered. +// clang-format off +const std::array default_hotkeys{{ + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+M"), std::string("Home+Dpad_Right"), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("-"), std::string("Home+Dpad_Down"), Qt::ApplicationShortcut, true}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("="), std::string("Home+Dpad_Up"), Qt::ApplicationShortcut, true}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+P"), std::string("Screenshot"), Qt::WidgetWithChildrenShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F8"), std::string("Home+L"), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F10"), std::string("Home+X"), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F9"), std::string("Home+R"), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F4"), std::string("Home+Plus"), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Esc"), std::string(""), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+Q"), std::string("Home+Minus"), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F11"), std::string("Home+B"), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+O"), std::string(""), Qt::WidgetWithChildrenShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F2"), std::string("Home+A"), Qt::WidgetWithChildrenShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F6"), std::string("R+Plus+Minus"), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F5"), std::string("L+Plus+Minus"), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F7"), std::string(""), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F6"), std::string(""), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F5"), std::string(""), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F"), std::string(""), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+U"), std::string("Home+Y"), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F9"), std::string(""), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string(""), std::string(""), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+S"), std::string(""), Qt::WindowShortcut, false}}, +}}; +// clang-format on + } // namespace UISettings Q_DECLARE_METATYPE(UISettings::GameDir*); + +// These metatype declarations cannot be in common/settings.h because core is devoid of QT +Q_DECLARE_METATYPE(Settings::CpuAccuracy); +Q_DECLARE_METATYPE(Settings::GpuAccuracy); +Q_DECLARE_METATYPE(Settings::FullscreenMode); +Q_DECLARE_METATYPE(Settings::NvdecEmulation); +Q_DECLARE_METATYPE(Settings::ResolutionSetup); +Q_DECLARE_METATYPE(Settings::ScalingFilter); +Q_DECLARE_METATYPE(Settings::AntiAliasing); +Q_DECLARE_METATYPE(Settings::RendererBackend); +Q_DECLARE_METATYPE(Settings::ShaderBackend); +Q_DECLARE_METATYPE(Settings::AstcRecompression); +Q_DECLARE_METATYPE(Settings::AstcDecodeMode); -- cgit v1.2.3 From c4f6c3b00be9e735444a8067b652f35a70268f4a Mon Sep 17 00:00:00 2001 From: Merry Date: Tue, 21 Nov 2023 22:57:09 +0000 Subject: shared_widget: Explicit capture of 'this' --- src/yuzu/configuration/shared_widget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/shared_widget.cpp b/src/yuzu/configuration/shared_widget.cpp index ea8d7add4..941683a43 100644 --- a/src/yuzu/configuration/shared_widget.cpp +++ b/src/yuzu/configuration/shared_widget.cpp @@ -194,7 +194,7 @@ QWidget* Widget::CreateRadioGroup(std::function& serializer, return group; } - const auto get_selected = [=]() -> int { + const auto get_selected = [this]() -> int { for (const auto& [id, button] : radio_buttons) { if (button->isChecked()) { return id; @@ -203,7 +203,7 @@ QWidget* Widget::CreateRadioGroup(std::function& serializer, return -1; }; - const auto set_index = [=](u32 value) { + const auto set_index = [this](u32 value) { for (const auto& [id, button] : radio_buttons) { button->setChecked(id == value); } -- cgit v1.2.3 From b088a448cdc6ab66ea3a95fe40b158ab6030c2c2 Mon Sep 17 00:00:00 2001 From: Merry Date: Tue, 21 Nov 2023 22:57:47 +0000 Subject: game_list_worker: Explicit caputure of 'this' --- src/yuzu/game_list_worker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/yuzu') diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 69be21027..307eac02d 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -479,6 +479,6 @@ void GameListWorker::run() { } } - RecordEvent([=](GameList* game_list) { game_list->DonePopulating(watch_list); }); + RecordEvent([this](GameList* game_list) { game_list->DonePopulating(watch_list); }); processing_completed.Set(); } -- cgit v1.2.3 From d8f380961e2c7165ba296c246e002d16598942d4 Mon Sep 17 00:00:00 2001 From: t895 Date: Tue, 21 Nov 2023 20:46:27 -0500 Subject: frontend_common: Add option to read unsigned integers --- src/yuzu/configuration/qt_config.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/qt_config.cpp b/src/yuzu/configuration/qt_config.cpp index 82402ec70..5a8e69aa9 100644 --- a/src/yuzu/configuration/qt_config.cpp +++ b/src/yuzu/configuration/qt_config.cpp @@ -283,7 +283,8 @@ void QtConfig::ReadUIGamelistValues() { const int favorites_size = BeginArray("favorites"); for (int i = 0; i < favorites_size; i++) { SetArrayIndex(i); - UISettings::values.favorited_ids.append(ReadIntegerSetting(std::string("program_id"))); + UISettings::values.favorited_ids.append( + ReadUnsignedIntegerSetting(std::string("program_id"))); } EndArray(); -- cgit v1.2.3 From 2d4e7c826422fdbfa7e0ba837ab65f58801e3251 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Fri, 24 Nov 2023 11:53:31 -0600 Subject: yuzu: Display firmware version --- src/yuzu/main.cpp | 39 +++++++++++++++++++++++++++++++++++++-- src/yuzu/main.h | 2 ++ 2 files changed, 39 insertions(+), 2 deletions(-) (limited to 'src/yuzu') diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f22db233b..1848ac89f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -47,6 +47,7 @@ #include "core/hle/service/am/applet_ae.h" #include "core/hle/service/am/applet_oe.h" #include "core/hle/service/am/applets/applets.h" +#include "core/hle/service/set/set_sys.h" #include "yuzu/multiplayer/state.h" #include "yuzu/util/controller_navigation.h" @@ -1047,7 +1048,12 @@ void GMainWindow::InitializeWidgets() { statusBar()->addPermanentWidget(label); } - // TODO (flTobi): Add the widget when multiplayer is fully implemented + firmware_label = new QLabel(); + firmware_label->setObjectName(QStringLiteral("FirmwareLabel")); + firmware_label->setVisible(false); + firmware_label->setFocusPolicy(Qt::NoFocus); + statusBar()->addPermanentWidget(firmware_label); + statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0); statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0); @@ -2161,6 +2167,10 @@ void GMainWindow::OnEmulationStopped() { emu_frametime_label->setVisible(false); renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan); + if (!firmware_label->text().isEmpty()) { + firmware_label->setVisible(true); + } + current_game_path.clear(); // When closing the game, destroy the GLWindow to clear the context after the game is closed @@ -4586,6 +4596,7 @@ void GMainWindow::UpdateStatusBar() { emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); game_fps_label->setVisible(true); emu_frametime_label->setVisible(true); + firmware_label->setVisible(false); } void GMainWindow::UpdateGPUAccuracyButton() { @@ -4803,6 +4814,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { "games.")); } + SetFirmwareVersion(); + if (behavior == ReinitializeKeyBehavior::Warning) { game_list->PopulateAsync(UISettings::values.game_dirs); } @@ -4830,7 +4843,7 @@ bool GMainWindow::CheckSystemArchiveDecryption() { } bool GMainWindow::CheckFirmwarePresence() { - constexpr u64 MiiEditId = 0x0100000000001009ull; + constexpr u64 MiiEditId = static_cast(Service::AM::Applets::AppletProgramId::MiiEdit); auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); if (!bis_system) { @@ -4845,6 +4858,28 @@ bool GMainWindow::CheckFirmwarePresence() { return true; } +void GMainWindow::SetFirmwareVersion() { + Service::Set::FirmwareVersionFormat firmware_data{}; + const auto result = Service::Set::GetFirmwareVersionImpl( + firmware_data, *system, Service::Set::GetFirmwareVersionType::Version2); + + if (result.IsError() || !CheckFirmwarePresence()) { + LOG_INFO(Frontend, "Installed firmware: No firmware available"); + firmware_label->setVisible(false); + return; + } + + firmware_label->setVisible(true); + + const std::string display_version(firmware_data.display_version.data()); + const std::string display_title(firmware_data.display_title.data()); + + LOG_INFO(Frontend, "Installed firmware: {}", display_title); + + firmware_label->setText(QString::fromStdString(display_version)); + firmware_label->setToolTip(QString::fromStdString(display_title)); +} + bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id, u64* selected_title_id, u8* selected_content_record_type) { using ContentInfo = std::tuple; diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 49ee1e1d2..0c8b7606d 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -457,6 +457,7 @@ private: bool CheckDarkMode(); bool CheckSystemArchiveDecryption(); bool CheckFirmwarePresence(); + void SetFirmwareVersion(); void ConfigureFilesystemProvider(const std::string& filepath); /** * Open (or not) the right confirm dialog based on current setting and game exit lock @@ -511,6 +512,7 @@ private: QLabel* game_fps_label = nullptr; QLabel* emu_frametime_label = nullptr; QLabel* tas_label = nullptr; + QLabel* firmware_label = nullptr; QPushButton* gpu_accuracy_button = nullptr; QPushButton* renderer_status_button = nullptr; QPushButton* dock_status_button = nullptr; -- cgit v1.2.3