diff options
| author | 2023-10-17 02:57:35 -0300 | |
|---|---|---|
| committer | 2023-10-17 02:57:35 -0300 | |
| commit | 9908434c14d68faa7fde933258aafd7da15b3b3b (patch) | |
| tree | 554f22f093dbac67d9e58f67dba63f0a3ffcd22b /src | |
| parent | Merge branch 'yuzu-emu:master' into new-shortcut (diff) | |
| download | yuzu-9908434c14d68faa7fde933258aafd7da15b3b3b.tar.gz yuzu-9908434c14d68faa7fde933258aafd7da15b3b3b.tar.xz yuzu-9908434c14d68faa7fde933258aafd7da15b3b3b.zip | |
Final refactorization
Diffstat (limited to 'src')
| -rw-r--r-- | src/yuzu/main.cpp | 131 |
1 files changed, 45 insertions, 86 deletions
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, | |||
| 2846 | const std::filesystem::path& command, | 2846 | const std::filesystem::path& command, |
| 2847 | const std::string& arguments, const std::string& categories, | 2847 | const std::string& arguments, const std::string& categories, |
| 2848 | const std::string& keywords, const std::string& name) try { | 2848 | const std::string& keywords, const std::string& name) try { |
| 2849 | |||
| 2850 | #if defined(__linux__) || defined(__FreeBSD__) || defined(_WIN32) // Linux, FreeBSD and Windows | ||
| 2851 | // Plus 'name' is required | ||
| 2852 | if (name.empty()) { | ||
| 2853 | LOG_ERROR(Frontend, "Name is empty"); | ||
| 2854 | return false; | ||
| 2855 | } | ||
| 2856 | |||
| 2857 | // Copy characters if they are not illegal in Windows filenames | ||
| 2858 | std::string filename = ""; | ||
| 2859 | const std::string illegal_chars = "<>:\"/\\|?*"; | ||
| 2860 | filename.reserve(name.size()); | ||
| 2861 | std::copy_if(name.begin(), name.end(), std::back_inserter(filename), | ||
| 2862 | [&illegal_chars](char c) { return illegal_chars.find(c) == std::string::npos; }); | ||
| 2863 | |||
| 2864 | if (filename.empty()) { | ||
| 2865 | LOG_ERROR(Frontend, "Filename is empty"); | ||
| 2866 | return false; | ||
| 2867 | } | ||
| 2868 | |||
| 2869 | if (!std::filesystem::is_regular_file(command)) { | ||
| 2870 | LOG_ERROR(Frontend, "Command is not a regular file"); | ||
| 2871 | return false; | ||
| 2872 | } | ||
| 2873 | |||
| 2874 | std::filesystem::path shortcut_path_full = shortcut_path / filename; | ||
| 2875 | #endif | ||
| 2876 | |||
| 2877 | #if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD | 2849 | #if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD |
| 2878 | // Reference for the desktop file template: | 2850 | std::filesystem::path shortcut_path_full = shortcut_path / (name + ".desktop"); |
| 2879 | // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html | ||
| 2880 | |||
| 2881 | // Append .desktop extension | ||
| 2882 | shortcut_path_full += ".desktop"; | ||
| 2883 | |||
| 2884 | // Create shortcut file | ||
| 2885 | std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); | 2851 | std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); |
| 2886 | if (!shortcut_stream.is_open()) { | 2852 | if (!shortcut_stream.is_open()) { |
| 2887 | LOG_ERROR(Frontend, "Failed to create shortcut"); | 2853 | LOG_ERROR(Frontend, "Failed to create shortcut"); |
| 2888 | return false; | 2854 | return false; |
| 2889 | } | 2855 | } |
| 2890 | |||
| 2891 | fmt::print(shortcut_stream, "[Desktop Entry]\n"); | 2856 | fmt::print(shortcut_stream, "[Desktop Entry]\n"); |
| 2892 | fmt::print(shortcut_stream, "Type=Application\n"); | 2857 | fmt::print(shortcut_stream, "Type=Application\n"); |
| 2893 | fmt::print(shortcut_stream, "Version=1.0\n"); | 2858 | fmt::print(shortcut_stream, "Version=1.0\n"); |
| @@ -2899,11 +2864,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, | |||
| 2899 | fmt::print(shortcut_stream, "Icon={}\n", icon_path.string()); | 2864 | fmt::print(shortcut_stream, "Icon={}\n", icon_path.string()); |
| 2900 | } | 2865 | } |
| 2901 | fmt::print(shortcut_stream, "TryExec={}\n", command.string()); | 2866 | fmt::print(shortcut_stream, "TryExec={}\n", command.string()); |
| 2902 | fmt::print(shortcut_stream, "Exec={}", command.string()); | 2867 | fmt::print(shortcut_stream, "Exec={} {}\n", command.string(), arguments); |
| 2903 | if (!arguments.empty()) { | ||
| 2904 | fmt::print(shortcut_stream, " {}", arguments); | ||
| 2905 | } | ||
| 2906 | fmt::print(shortcut_stream, "\n"); | ||
| 2907 | if (!categories.empty()) { | 2868 | if (!categories.empty()) { |
| 2908 | fmt::print(shortcut_stream, "Categories={}\n", categories); | 2869 | fmt::print(shortcut_stream, "Categories={}\n", categories); |
| 2909 | } | 2870 | } |
| @@ -2912,15 +2873,14 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, | |||
| 2912 | } | 2873 | } |
| 2913 | return true; | 2874 | return true; |
| 2914 | #elif defined(_WIN32) // Windows | 2875 | #elif defined(_WIN32) // Windows |
| 2915 | HRESULT hr = CoInitialize(NULL); | 2876 | HRESULT hr = CoInitialize(nullptr); |
| 2916 | if (FAILED(hr)) { | 2877 | if (FAILED(hr)) { |
| 2917 | LOG_ERROR(Frontend, "CoInitialize failed"); | 2878 | LOG_ERROR(Frontend, "CoInitialize failed"); |
| 2918 | return false; | 2879 | return false; |
| 2919 | } | 2880 | } |
| 2920 | 2881 | SCOPE_EXIT({ CoUninitialize(); }); | |
| 2921 | IShellLinkW* ps1 = nullptr; | 2882 | IShellLinkW* ps1 = nullptr; |
| 2922 | IPersistFile* persist_file = nullptr; | 2883 | IPersistFile* persist_file = nullptr; |
| 2923 | |||
| 2924 | SCOPE_EXIT({ | 2884 | SCOPE_EXIT({ |
| 2925 | if (persist_file != nullptr) { | 2885 | if (persist_file != nullptr) { |
| 2926 | persist_file->Release(); | 2886 | persist_file->Release(); |
| @@ -2928,40 +2888,50 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, | |||
| 2928 | if (ps1 != nullptr) { | 2888 | if (ps1 != nullptr) { |
| 2929 | ps1->Release(); | 2889 | ps1->Release(); |
| 2930 | } | 2890 | } |
| 2931 | |||
| 2932 | CoUninitialize(); | ||
| 2933 | }); | 2891 | }); |
| 2934 | 2892 | HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW, | |
| 2935 | HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, | 2893 | reinterpret_cast<void**>(&ps1)); |
| 2936 | (void**)&ps1); | 2894 | if (FAILED(hres)) { |
| 2937 | 2895 | LOG_ERROR(Frontend, "Failed to create IShellLinkW instance"); | |
| 2938 | if (SUCCEEDED(hres)) { | ||
| 2939 | hres = ps1->SetPath(Common::UTF8ToUTF16W(command.string()).data()); | ||
| 2940 | } else { | ||
| 2941 | LOG_ERROR(Frontend, "Failed to create CoCreateInstance"); | ||
| 2942 | return false; | 2896 | return false; |
| 2943 | } | 2897 | } |
| 2944 | if (SUCCEEDED(hres) && !arguments.empty()) { | 2898 | hres = ps1->SetPath(command.c_str()); |
| 2899 | if (FAILED(hres)) { | ||
| 2900 | LOG_ERROR(Frontend, "Failed to set path"); | ||
| 2901 | return false; | ||
| 2902 | } | ||
| 2903 | if (!arguments.empty()) { | ||
| 2945 | hres = ps1->SetArguments(Common::UTF8ToUTF16W(arguments).data()); | 2904 | hres = ps1->SetArguments(Common::UTF8ToUTF16W(arguments).data()); |
| 2905 | if (FAILED(hres)) { | ||
| 2906 | LOG_ERROR(Frontend, "Failed to set arguments"); | ||
| 2907 | return false; | ||
| 2908 | } | ||
| 2946 | } | 2909 | } |
| 2947 | if (SUCCEEDED(hres) && !comment.empty()) { | 2910 | if (!comment.empty()) { |
| 2948 | hres = ps1->SetDescription(Common::UTF8ToUTF16W(comment).data()); | 2911 | hres = ps1->SetDescription(Common::UTF8ToUTF16W(comment).data()); |
| 2912 | if (FAILED(hres)) { | ||
| 2913 | LOG_ERROR(Frontend, "Failed to set description"); | ||
| 2914 | return false; | ||
| 2915 | } | ||
| 2949 | } | 2916 | } |
| 2950 | if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) { | 2917 | if (std::filesystem::is_regular_file(icon_path)) { |
| 2951 | hres = ps1->SetIconLocation(Common::UTF8ToUTF16W(icon_path.string()).data(), 0); | 2918 | hres = ps1->SetIconLocation(icon_path.c_str(), 0); |
| 2952 | } | 2919 | if (FAILED(hres)) { |
| 2953 | if (SUCCEEDED(hres)) { | 2920 | LOG_ERROR(Frontend, "Failed to set icon location"); |
| 2954 | hres = ps1->QueryInterface(IID_IPersistFile, (void**)&persist_file); | 2921 | return false; |
| 2922 | } | ||
| 2955 | } | 2923 | } |
| 2956 | if (SUCCEEDED(hres) && persist_file != nullptr) { | 2924 | hres = ps1->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&persist_file)); |
| 2957 | hres = persist_file->Save( | 2925 | if (FAILED(hres)) { |
| 2958 | Common::UTF8ToUTF16W((shortcut_path_full).string() + ".lnk").data(), TRUE); | 2926 | LOG_ERROR(Frontend, "Failed to get IPersistFile interface"); |
| 2927 | return false; | ||
| 2959 | } | 2928 | } |
| 2960 | if (SUCCEEDED(hres)) { | 2929 | hres = persist_file->Save(std::filesystem::path{shortcut_path / (name + ".lnk")}.c_str(), TRUE); |
| 2961 | return true; | 2930 | if (FAILED(hres)) { |
| 2931 | LOG_ERROR(Frontend, "Failed to save shortcut"); | ||
| 2932 | return false; | ||
| 2962 | } | 2933 | } |
| 2963 | LOG_ERROR(Frontend, "Failed to create shortcut"); | 2934 | return true; |
| 2964 | return false; | ||
| 2965 | #else // Unsupported platform | 2935 | #else // Unsupported platform |
| 2966 | return false; | 2936 | return false; |
| 2967 | #endif | 2937 | #endif |
| @@ -2969,7 +2939,6 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, | |||
| 2969 | LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); | 2939 | LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); |
| 2970 | return false; | 2940 | return false; |
| 2971 | } | 2941 | } |
| 2972 | |||
| 2973 | // Messages in pre-defined message boxes for less code spaghetti | 2942 | // Messages in pre-defined message boxes for less code spaghetti |
| 2974 | bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) { | 2943 | bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) { |
| 2975 | int result = 0; | 2944 | int result = 0; |
| @@ -3009,7 +2978,6 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt | |||
| 3009 | 2978 | ||
| 3010 | bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, | 2979 | bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, |
| 3011 | std::filesystem::path& out_icon_path) { | 2980 | std::filesystem::path& out_icon_path) { |
| 3012 | |||
| 3013 | // Get path to Yuzu icons directory & icon extension | 2981 | // Get path to Yuzu icons directory & icon extension |
| 3014 | std::string ico_extension = "png"; | 2982 | std::string ico_extension = "png"; |
| 3015 | #if defined(_WIN32) | 2983 | #if defined(_WIN32) |
| @@ -3038,20 +3006,16 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi | |||
| 3038 | 3006 | ||
| 3039 | void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path, | 3007 | void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path, |
| 3040 | GameListShortcutTarget target) { | 3008 | GameListShortcutTarget target) { |
| 3041 | |||
| 3042 | std::string game_title; | 3009 | std::string game_title; |
| 3043 | QString qt_game_title; | 3010 | QString qt_game_title; |
| 3044 | std::filesystem::path out_icon_path; | 3011 | std::filesystem::path out_icon_path; |
| 3045 | |||
| 3046 | // Get path to yuzu executable | 3012 | // Get path to yuzu executable |
| 3047 | const QStringList args = QApplication::arguments(); | 3013 | const QStringList args = QApplication::arguments(); |
| 3048 | std::filesystem::path yuzu_command = args[0].toStdString(); | 3014 | std::filesystem::path yuzu_command = args[0].toStdString(); |
| 3049 | |||
| 3050 | // If relative path, make it an absolute path | 3015 | // If relative path, make it an absolute path |
| 3051 | if (yuzu_command.c_str()[0] == '.') { | 3016 | if (yuzu_command.c_str()[0] == '.') { |
| 3052 | yuzu_command = Common::FS::GetCurrentDir() / yuzu_command; | 3017 | yuzu_command = Common::FS::GetCurrentDir() / yuzu_command; |
| 3053 | } | 3018 | } |
| 3054 | |||
| 3055 | // Shortcut path | 3019 | // Shortcut path |
| 3056 | std::filesystem::path shortcut_path{}; | 3020 | std::filesystem::path shortcut_path{}; |
| 3057 | if (target == GameListShortcutTarget::Desktop) { | 3021 | if (target == GameListShortcutTarget::Desktop) { |
| @@ -3061,7 +3025,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 3061 | shortcut_path = | 3025 | shortcut_path = |
| 3062 | QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString(); | 3026 | QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString(); |
| 3063 | } | 3027 | } |
| 3064 | |||
| 3065 | // Icon path and title | 3028 | // Icon path and title |
| 3066 | if (std::filesystem::exists(shortcut_path)) { | 3029 | if (std::filesystem::exists(shortcut_path)) { |
| 3067 | // Get title from game file | 3030 | // Get title from game file |
| @@ -3070,17 +3033,20 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 3070 | const auto control = pm.GetControlMetadata(); | 3033 | const auto control = pm.GetControlMetadata(); |
| 3071 | const auto loader = | 3034 | const auto loader = |
| 3072 | Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read)); | 3035 | Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read)); |
| 3073 | |||
| 3074 | game_title = fmt::format("{:016X}", program_id); | 3036 | game_title = fmt::format("{:016X}", program_id); |
| 3075 | |||
| 3076 | if (control.first != nullptr) { | 3037 | if (control.first != nullptr) { |
| 3077 | game_title = control.first->GetApplicationName(); | 3038 | game_title = control.first->GetApplicationName(); |
| 3078 | } else { | 3039 | } else { |
| 3079 | loader->ReadTitle(game_title); | 3040 | loader->ReadTitle(game_title); |
| 3080 | } | 3041 | } |
| 3081 | 3042 | // Delete illegal characters from title | |
| 3043 | const std::string illegal_chars = "<>:\"/\\|?*."; | ||
| 3044 | for (auto it = game_title.rbegin(); it != game_title.rend(); ++it) { | ||
| 3045 | if (illegal_chars.find(*it) != std::string::npos) { | ||
| 3046 | game_title.erase(it.base() - 1); | ||
| 3047 | } | ||
| 3048 | } | ||
| 3082 | qt_game_title = QString::fromStdString(game_title); | 3049 | qt_game_title = QString::fromStdString(game_title); |
| 3083 | |||
| 3084 | // Get icon from game file | 3050 | // Get icon from game file |
| 3085 | std::vector<u8> icon_image_file{}; | 3051 | std::vector<u8> icon_image_file{}; |
| 3086 | if (control.second != nullptr) { | 3052 | if (control.second != nullptr) { |
| @@ -3088,23 +3054,19 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 3088 | } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) { | 3054 | } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) { |
| 3089 | LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path); | 3055 | LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path); |
| 3090 | } | 3056 | } |
| 3091 | |||
| 3092 | QImage icon_data = | 3057 | QImage icon_data = |
| 3093 | QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size())); | 3058 | QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size())); |
| 3094 | |||
| 3095 | if (GMainWindow::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) { | 3059 | if (GMainWindow::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) { |
| 3096 | if (!SaveIconToFile(out_icon_path, icon_data)) { | 3060 | if (!SaveIconToFile(out_icon_path, icon_data)) { |
| 3097 | LOG_ERROR(Frontend, "Could not write icon to file"); | 3061 | LOG_ERROR(Frontend, "Could not write icon to file"); |
| 3098 | } | 3062 | } |
| 3099 | } | 3063 | } |
| 3100 | |||
| 3101 | } else { | 3064 | } else { |
| 3102 | GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, | 3065 | GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, |
| 3103 | qt_game_title); | 3066 | qt_game_title); |
| 3104 | LOG_ERROR(Frontend, "Invalid shortcut target"); | 3067 | LOG_ERROR(Frontend, "Invalid shortcut target"); |
| 3105 | return; | 3068 | return; |
| 3106 | } | 3069 | } |
| 3107 | |||
| 3108 | #if defined(_WIN32) | 3070 | #if defined(_WIN32) |
| 3109 | if (!IsUserAnAdmin() && target == GameListShortcutTarget::Applications) { | 3071 | if (!IsUserAnAdmin() && target == GameListShortcutTarget::Applications) { |
| 3110 | GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN, | 3072 | GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN, |
| @@ -3125,7 +3087,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 3125 | UISettings::values.shortcut_already_warned = true; | 3087 | UISettings::values.shortcut_already_warned = true; |
| 3126 | } | 3088 | } |
| 3127 | #endif // __linux__ | 3089 | #endif // __linux__ |
| 3128 | |||
| 3129 | // Create shortcut | 3090 | // Create shortcut |
| 3130 | std::string arguments = fmt::format("-g \"{:s}\"", game_path); | 3091 | std::string arguments = fmt::format("-g \"{:s}\"", game_path); |
| 3131 | if (GMainWindow::CreateShortcutMessagesGUI( | 3092 | if (GMainWindow::CreateShortcutMessagesGUI( |
| @@ -3142,7 +3103,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 3142 | qt_game_title); | 3103 | qt_game_title); |
| 3143 | return; | 3104 | return; |
| 3144 | } | 3105 | } |
| 3145 | |||
| 3146 | GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, | 3106 | GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, |
| 3147 | qt_game_title); | 3107 | qt_game_title); |
| 3148 | } | 3108 | } |
| @@ -4177,7 +4137,6 @@ void GMainWindow::OnLoadAmiibo() { | |||
| 4177 | bool GMainWindow::question(QWidget* parent, const QString& title, const QString& text, | 4137 | bool GMainWindow::question(QWidget* parent, const QString& title, const QString& text, |
| 4178 | QMessageBox::StandardButtons buttons, | 4138 | QMessageBox::StandardButtons buttons, |
| 4179 | QMessageBox::StandardButton defaultButton) { | 4139 | QMessageBox::StandardButton defaultButton) { |
| 4180 | |||
| 4181 | QMessageBox* box_dialog = new QMessageBox(parent); | 4140 | QMessageBox* box_dialog = new QMessageBox(parent); |
| 4182 | box_dialog->setWindowTitle(title); | 4141 | box_dialog->setWindowTitle(title); |
| 4183 | box_dialog->setText(text); | 4142 | box_dialog->setText(text); |