diff options
| -rw-r--r-- | src/common/fs/fs_paths.h | 1 | ||||
| -rw-r--r-- | src/common/fs/path_util.cpp | 1 | ||||
| -rw-r--r-- | src/common/fs/path_util.h | 1 | ||||
| -rw-r--r-- | src/yuzu/game_list.cpp | 4 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 85 | ||||
| -rw-r--r-- | src/yuzu/util/util.cpp | 77 | ||||
| -rw-r--r-- | src/yuzu/util/util.h | 14 |
7 files changed, 157 insertions, 26 deletions
diff --git a/src/common/fs/fs_paths.h b/src/common/fs/fs_paths.h index 61bac9eba..c54ce7654 100644 --- a/src/common/fs/fs_paths.h +++ b/src/common/fs/fs_paths.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #define SDMC_DIR "sdmc" | 22 | #define SDMC_DIR "sdmc" |
| 23 | #define SHADER_DIR "shader" | 23 | #define SHADER_DIR "shader" |
| 24 | #define TAS_DIR "tas" | 24 | #define TAS_DIR "tas" |
| 25 | #define ICONS_DIR "icons" | ||
| 25 | 26 | ||
| 26 | // yuzu-specific files | 27 | // yuzu-specific files |
| 27 | 28 | ||
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index dce219fcf..461c170f7 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp | |||
| @@ -128,6 +128,7 @@ public: | |||
| 128 | GenerateYuzuPath(YuzuPath::SDMCDir, yuzu_path / SDMC_DIR); | 128 | GenerateYuzuPath(YuzuPath::SDMCDir, yuzu_path / SDMC_DIR); |
| 129 | GenerateYuzuPath(YuzuPath::ShaderDir, yuzu_path / SHADER_DIR); | 129 | GenerateYuzuPath(YuzuPath::ShaderDir, yuzu_path / SHADER_DIR); |
| 130 | GenerateYuzuPath(YuzuPath::TASDir, yuzu_path / TAS_DIR); | 130 | GenerateYuzuPath(YuzuPath::TASDir, yuzu_path / TAS_DIR); |
| 131 | GenerateYuzuPath(YuzuPath::IconsDir, yuzu_path / ICONS_DIR); | ||
| 131 | } | 132 | } |
| 132 | 133 | ||
| 133 | private: | 134 | private: |
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h index ba28964d0..61593bdf7 100644 --- a/src/common/fs/path_util.h +++ b/src/common/fs/path_util.h | |||
| @@ -24,6 +24,7 @@ enum class YuzuPath { | |||
| 24 | SDMCDir, // Where the emulated SDMC is stored. | 24 | SDMCDir, // Where the emulated SDMC is stored. |
| 25 | ShaderDir, // Where shaders are stored. | 25 | ShaderDir, // Where shaders are stored. |
| 26 | TASDir, // Where TAS scripts are stored. | 26 | TASDir, // Where TAS scripts are stored. |
| 27 | IconsDir, // Where Icons for Windows shortcuts are stored. | ||
| 27 | }; | 28 | }; |
| 28 | 29 | ||
| 29 | /** | 30 | /** |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index f254c1e1c..a9f19e316 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -560,9 +560,9 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri | |||
| 560 | QAction* verify_integrity = context_menu.addAction(tr("Verify Integrity")); | 560 | QAction* verify_integrity = context_menu.addAction(tr("Verify Integrity")); |
| 561 | QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard")); | 561 | QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard")); |
| 562 | QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry")); | 562 | QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry")); |
| 563 | #ifndef WIN32 | ||
| 564 | QMenu* shortcut_menu = context_menu.addMenu(tr("Create Shortcut")); | 563 | QMenu* shortcut_menu = context_menu.addMenu(tr("Create Shortcut")); |
| 565 | QAction* create_desktop_shortcut = shortcut_menu->addAction(tr("Add to Desktop")); | 564 | QAction* create_desktop_shortcut = shortcut_menu->addAction(tr("Add to Desktop")); |
| 565 | #ifndef WIN32 | ||
| 566 | QAction* create_applications_menu_shortcut = | 566 | QAction* create_applications_menu_shortcut = |
| 567 | shortcut_menu->addAction(tr("Add to Applications Menu")); | 567 | shortcut_menu->addAction(tr("Add to Applications Menu")); |
| 568 | #endif | 568 | #endif |
| @@ -638,10 +638,10 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri | |||
| 638 | connect(navigate_to_gamedb_entry, &QAction::triggered, [this, program_id]() { | 638 | connect(navigate_to_gamedb_entry, &QAction::triggered, [this, program_id]() { |
| 639 | emit NavigateToGamedbEntryRequested(program_id, compatibility_list); | 639 | emit NavigateToGamedbEntryRequested(program_id, compatibility_list); |
| 640 | }); | 640 | }); |
| 641 | #ifndef WIN32 | ||
| 642 | connect(create_desktop_shortcut, &QAction::triggered, [this, program_id, path]() { | 641 | connect(create_desktop_shortcut, &QAction::triggered, [this, program_id, path]() { |
| 643 | emit CreateShortcut(program_id, path, GameListShortcutTarget::Desktop); | 642 | emit CreateShortcut(program_id, path, GameListShortcutTarget::Desktop); |
| 644 | }); | 643 | }); |
| 644 | #ifndef WIN32 | ||
| 645 | connect(create_applications_menu_shortcut, &QAction::triggered, [this, program_id, path]() { | 645 | connect(create_applications_menu_shortcut, &QAction::triggered, [this, program_id, path]() { |
| 646 | emit CreateShortcut(program_id, path, GameListShortcutTarget::Applications); | 646 | emit CreateShortcut(program_id, path, GameListShortcutTarget::Applications); |
| 647 | }); | 647 | }); |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 16fa92e2c..7a93921d7 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -98,6 +98,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 98 | #include "common/scm_rev.h" | 98 | #include "common/scm_rev.h" |
| 99 | #include "common/scope_exit.h" | 99 | #include "common/scope_exit.h" |
| 100 | #ifdef _WIN32 | 100 | #ifdef _WIN32 |
| 101 | #include <shlobj.h> | ||
| 101 | #include "common/windows/timer_resolution.h" | 102 | #include "common/windows/timer_resolution.h" |
| 102 | #endif | 103 | #endif |
| 103 | #ifdef ARCHITECTURE_x86_64 | 104 | #ifdef ARCHITECTURE_x86_64 |
| @@ -2825,7 +2826,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 2825 | const QStringList args = QApplication::arguments(); | 2826 | const QStringList args = QApplication::arguments(); |
| 2826 | std::filesystem::path yuzu_command = args[0].toStdString(); | 2827 | std::filesystem::path yuzu_command = args[0].toStdString(); |
| 2827 | 2828 | ||
| 2828 | #if defined(__linux__) || defined(__FreeBSD__) | ||
| 2829 | // If relative path, make it an absolute path | 2829 | // If relative path, make it an absolute path |
| 2830 | if (yuzu_command.c_str()[0] == '.') { | 2830 | if (yuzu_command.c_str()[0] == '.') { |
| 2831 | yuzu_command = Common::FS::GetCurrentDir() / yuzu_command; | 2831 | yuzu_command = Common::FS::GetCurrentDir() / yuzu_command; |
| @@ -2848,12 +2848,14 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 2848 | UISettings::values.shortcut_already_warned = true; | 2848 | UISettings::values.shortcut_already_warned = true; |
| 2849 | } | 2849 | } |
| 2850 | #endif // __linux__ | 2850 | #endif // __linux__ |
| 2851 | #endif // __linux__ || __FreeBSD__ | ||
| 2852 | 2851 | ||
| 2853 | std::filesystem::path target_directory{}; | 2852 | std::filesystem::path target_directory{}; |
| 2854 | // Determine target directory for shortcut | 2853 | // Determine target directory for shortcut |
| 2855 | #if defined(__linux__) || defined(__FreeBSD__) | 2854 | #if defined(WIN32) |
| 2855 | const char* home = std::getenv("USERPROFILE"); | ||
| 2856 | #else | ||
| 2856 | const char* home = std::getenv("HOME"); | 2857 | const char* home = std::getenv("HOME"); |
| 2858 | #endif | ||
| 2857 | const std::filesystem::path home_path = (home == nullptr ? "~" : home); | 2859 | const std::filesystem::path home_path = (home == nullptr ? "~" : home); |
| 2858 | const char* xdg_data_home = std::getenv("XDG_DATA_HOME"); | 2860 | const char* xdg_data_home = std::getenv("XDG_DATA_HOME"); |
| 2859 | 2861 | ||
| @@ -2863,7 +2865,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 2863 | QMessageBox::critical( | 2865 | QMessageBox::critical( |
| 2864 | this, tr("Create Shortcut"), | 2866 | this, tr("Create Shortcut"), |
| 2865 | tr("Cannot create shortcut on desktop. Path \"%1\" does not exist.") | 2867 | tr("Cannot create shortcut on desktop. Path \"%1\" does not exist.") |
| 2866 | .arg(QString::fromStdString(target_directory)), | 2868 | .arg(QString::fromStdString(target_directory.generic_string())), |
| 2867 | QMessageBox::StandardButton::Ok); | 2869 | QMessageBox::StandardButton::Ok); |
| 2868 | return; | 2870 | return; |
| 2869 | } | 2871 | } |
| @@ -2871,15 +2873,15 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 2871 | target_directory = (xdg_data_home == nullptr ? home_path / ".local/share" : xdg_data_home) / | 2873 | target_directory = (xdg_data_home == nullptr ? home_path / ".local/share" : xdg_data_home) / |
| 2872 | "applications"; | 2874 | "applications"; |
| 2873 | if (!Common::FS::CreateDirs(target_directory)) { | 2875 | if (!Common::FS::CreateDirs(target_directory)) { |
| 2874 | QMessageBox::critical(this, tr("Create Shortcut"), | 2876 | QMessageBox::critical( |
| 2875 | tr("Cannot create shortcut in applications menu. Path \"%1\" " | 2877 | this, tr("Create Shortcut"), |
| 2876 | "does not exist and cannot be created.") | 2878 | tr("Cannot create shortcut in applications menu. Path \"%1\" " |
| 2877 | .arg(QString::fromStdString(target_directory)), | 2879 | "does not exist and cannot be created.") |
| 2878 | QMessageBox::StandardButton::Ok); | 2880 | .arg(QString::fromStdString(target_directory.generic_string())), |
| 2881 | QMessageBox::StandardButton::Ok); | ||
| 2879 | return; | 2882 | return; |
| 2880 | } | 2883 | } |
| 2881 | } | 2884 | } |
| 2882 | #endif | ||
| 2883 | 2885 | ||
| 2884 | const std::string game_file_name = std::filesystem::path(game_path).filename().string(); | 2886 | const std::string game_file_name = std::filesystem::path(game_path).filename().string(); |
| 2885 | // Determine full paths for icon and shortcut | 2887 | // Determine full paths for icon and shortcut |
| @@ -2901,9 +2903,14 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 2901 | const std::filesystem::path shortcut_path = | 2903 | const std::filesystem::path shortcut_path = |
| 2902 | target_directory / (program_id == 0 ? fmt::format("yuzu-{}.desktop", game_file_name) | 2904 | target_directory / (program_id == 0 ? fmt::format("yuzu-{}.desktop", game_file_name) |
| 2903 | : fmt::format("yuzu-{:016X}.desktop", program_id)); | 2905 | : fmt::format("yuzu-{:016X}.desktop", program_id)); |
| 2906 | #elif defined(WIN32) | ||
| 2907 | std::filesystem::path icons_path = | ||
| 2908 | Common::FS::GetYuzuPathString(Common::FS::YuzuPath::IconsDir); | ||
| 2909 | std::filesystem::path icon_path = | ||
| 2910 | icons_path / ((program_id == 0 ? fmt::format("yuzu-{}.ico", game_file_name) | ||
| 2911 | : fmt::format("yuzu-{:016X}.ico", program_id))); | ||
| 2904 | #else | 2912 | #else |
| 2905 | const std::filesystem::path icon_path{}; | 2913 | std::string icon_extension; |
| 2906 | const std::filesystem::path shortcut_path{}; | ||
| 2907 | #endif | 2914 | #endif |
| 2908 | 2915 | ||
| 2909 | // Get title from game file | 2916 | // Get title from game file |
| @@ -2928,29 +2935,37 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga | |||
| 2928 | LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path); | 2935 | LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path); |
| 2929 | } | 2936 | } |
| 2930 | 2937 | ||
| 2931 | QImage icon_jpeg = | 2938 | QImage icon_data = |
| 2932 | QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size())); | 2939 | QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size())); |
| 2933 | #if defined(__linux__) || defined(__FreeBSD__) | 2940 | #if defined(__linux__) || defined(__FreeBSD__) |
| 2934 | // Convert and write the icon as a PNG | 2941 | // Convert and write the icon as a PNG |
| 2935 | if (!icon_jpeg.save(QString::fromStdString(icon_path.string()))) { | 2942 | if (!icon_data.save(QString::fromStdString(icon_path.string()))) { |
| 2936 | LOG_ERROR(Frontend, "Could not write icon as PNG to file"); | 2943 | LOG_ERROR(Frontend, "Could not write icon as PNG to file"); |
| 2937 | } else { | 2944 | } else { |
| 2938 | LOG_INFO(Frontend, "Wrote an icon to {}", icon_path.string()); | 2945 | LOG_INFO(Frontend, "Wrote an icon to {}", icon_path.string()); |
| 2939 | } | 2946 | } |
| 2947 | #elif defined(WIN32) | ||
| 2948 | if (!SaveIconToFile(icon_path.string(), icon_data)) { | ||
| 2949 | LOG_ERROR(Frontend, "Could not write icon to file"); | ||
| 2950 | return; | ||
| 2951 | } | ||
| 2940 | #endif // __linux__ | 2952 | #endif // __linux__ |
| 2941 | 2953 | ||
| 2942 | #if defined(__linux__) || defined(__FreeBSD__) | 2954 | #ifdef _WIN32 |
| 2955 | // Replace characters that are illegal in Windows filenames by a dash | ||
| 2956 | const std::string illegal_chars = "<>:\"/\\|?*"; | ||
| 2957 | for (char c : illegal_chars) { | ||
| 2958 | std::replace(title.begin(), title.end(), c, '_'); | ||
| 2959 | } | ||
| 2960 | const std::filesystem::path shortcut_path = target_directory / (title + ".lnk").c_str(); | ||
| 2961 | #endif | ||
| 2962 | |||
| 2943 | const std::string comment = | 2963 | const std::string comment = |
| 2944 | tr("Start %1 with the yuzu Emulator").arg(QString::fromStdString(title)).toStdString(); | 2964 | tr("Start %1 with the yuzu Emulator").arg(QString::fromStdString(title)).toStdString(); |
| 2945 | const std::string arguments = fmt::format("-g \"{:s}\"", game_path); | 2965 | const std::string arguments = fmt::format("-g \"{:s}\"", game_path); |
| 2946 | const std::string categories = "Game;Emulator;Qt;"; | 2966 | const std::string categories = "Game;Emulator;Qt;"; |
| 2947 | const std::string keywords = "Switch;Nintendo;"; | 2967 | const std::string keywords = "Switch;Nintendo;"; |
| 2948 | #else | 2968 | |
| 2949 | const std::string comment{}; | ||
| 2950 | const std::string arguments{}; | ||
| 2951 | const std::string categories{}; | ||
| 2952 | const std::string keywords{}; | ||
| 2953 | #endif | ||
| 2954 | if (!CreateShortcut(shortcut_path.string(), title, comment, icon_path.string(), | 2969 | if (!CreateShortcut(shortcut_path.string(), title, comment, icon_path.string(), |
| 2955 | yuzu_command.string(), arguments, categories, keywords)) { | 2970 | yuzu_command.string(), arguments, categories, keywords)) { |
| 2956 | QMessageBox::critical(this, tr("Create Shortcut"), | 2971 | QMessageBox::critical(this, tr("Create Shortcut"), |
| @@ -3965,6 +3980,34 @@ bool GMainWindow::CreateShortcut(const std::string& shortcut_path, const std::st | |||
| 3965 | shortcut_stream.close(); | 3980 | shortcut_stream.close(); |
| 3966 | 3981 | ||
| 3967 | return true; | 3982 | return true; |
| 3983 | #elif defined(WIN32) | ||
| 3984 | IShellLinkW* shell_link; | ||
| 3985 | auto hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, | ||
| 3986 | (void**)&shell_link); | ||
| 3987 | if (FAILED(hres)) { | ||
| 3988 | return false; | ||
| 3989 | } | ||
| 3990 | shell_link->SetPath( | ||
| 3991 | Common::UTF8ToUTF16W(command).data()); // Path to the object we are referring to | ||
| 3992 | shell_link->SetArguments(Common::UTF8ToUTF16W(arguments).data()); | ||
| 3993 | shell_link->SetDescription(Common::UTF8ToUTF16W(comment).data()); | ||
| 3994 | shell_link->SetIconLocation(Common::UTF8ToUTF16W(icon_path).data(), 0); | ||
| 3995 | |||
| 3996 | IPersistFile* persist_file; | ||
| 3997 | hres = shell_link->QueryInterface(IID_IPersistFile, (void**)&persist_file); | ||
| 3998 | if (FAILED(hres)) { | ||
| 3999 | return false; | ||
| 4000 | } | ||
| 4001 | |||
| 4002 | hres = persist_file->Save(Common::UTF8ToUTF16W(shortcut_path).data(), TRUE); | ||
| 4003 | if (FAILED(hres)) { | ||
| 4004 | return false; | ||
| 4005 | } | ||
| 4006 | |||
| 4007 | persist_file->Release(); | ||
| 4008 | shell_link->Release(); | ||
| 4009 | |||
| 4010 | return true; | ||
| 3968 | #endif | 4011 | #endif |
| 3969 | return false; | 4012 | return false; |
| 3970 | } | 4013 | } |
diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp index 5c3e4589e..61cf00176 100644 --- a/src/yuzu/util/util.cpp +++ b/src/yuzu/util/util.cpp | |||
| @@ -5,6 +5,10 @@ | |||
| 5 | #include <cmath> | 5 | #include <cmath> |
| 6 | #include <QPainter> | 6 | #include <QPainter> |
| 7 | #include "yuzu/util/util.h" | 7 | #include "yuzu/util/util.h" |
| 8 | #ifdef _WIN32 | ||
| 9 | #include <windows.h> | ||
| 10 | #include "common/fs/file.h" | ||
| 11 | #endif | ||
| 8 | 12 | ||
| 9 | QFont GetMonospaceFont() { | 13 | QFont GetMonospaceFont() { |
| 10 | QFont font(QStringLiteral("monospace")); | 14 | QFont font(QStringLiteral("monospace")); |
| @@ -37,3 +41,76 @@ QPixmap CreateCirclePixmapFromColor(const QColor& color) { | |||
| 37 | painter.drawEllipse({circle_pixmap.width() / 2.0, circle_pixmap.height() / 2.0}, 7.0, 7.0); | 41 | painter.drawEllipse({circle_pixmap.width() / 2.0, circle_pixmap.height() / 2.0}, 7.0, 7.0); |
| 38 | return circle_pixmap; | 42 | return circle_pixmap; |
| 39 | } | 43 | } |
| 44 | |||
| 45 | bool SaveIconToFile(const std::string_view path, const QImage& image) { | ||
| 46 | #if defined(WIN32) | ||
| 47 | #pragma pack(push, 2) | ||
| 48 | struct IconDir { | ||
| 49 | WORD id_reserved; | ||
| 50 | WORD id_type; | ||
| 51 | WORD id_count; | ||
| 52 | }; | ||
| 53 | |||
| 54 | struct IconDirEntry { | ||
| 55 | BYTE width; | ||
| 56 | BYTE height; | ||
| 57 | BYTE color_count; | ||
| 58 | BYTE reserved; | ||
| 59 | WORD planes; | ||
| 60 | WORD bit_count; | ||
| 61 | DWORD bytes_in_res; | ||
| 62 | DWORD image_offset; | ||
| 63 | }; | ||
| 64 | #pragma pack(pop) | ||
| 65 | |||
| 66 | QImage source_image = image.convertToFormat(QImage::Format_RGB32); | ||
| 67 | constexpr int bytes_per_pixel = 4; | ||
| 68 | const int image_size = source_image.width() * source_image.height() * bytes_per_pixel; | ||
| 69 | |||
| 70 | BITMAPINFOHEADER info_header{}; | ||
| 71 | info_header.biSize = sizeof(BITMAPINFOHEADER), info_header.biWidth = source_image.width(), | ||
| 72 | info_header.biHeight = source_image.height() * 2, info_header.biPlanes = 1, | ||
| 73 | info_header.biBitCount = bytes_per_pixel * 8, info_header.biCompression = BI_RGB; | ||
| 74 | |||
| 75 | const IconDir icon_dir{.id_reserved = 0, .id_type = 1, .id_count = 1}; | ||
| 76 | const IconDirEntry icon_entry{.width = static_cast<BYTE>(source_image.width()), | ||
| 77 | .height = static_cast<BYTE>(source_image.height() * 2), | ||
| 78 | .color_count = 0, | ||
| 79 | .reserved = 0, | ||
| 80 | .planes = 1, | ||
| 81 | .bit_count = bytes_per_pixel * 8, | ||
| 82 | .bytes_in_res = | ||
| 83 | static_cast<DWORD>(sizeof(BITMAPINFOHEADER) + image_size), | ||
| 84 | .image_offset = sizeof(IconDir) + sizeof(IconDirEntry)}; | ||
| 85 | |||
| 86 | Common::FS::IOFile icon_file(path, Common::FS::FileAccessMode::Write, | ||
| 87 | Common::FS::FileType::BinaryFile); | ||
| 88 | if (!icon_file.IsOpen()) { | ||
| 89 | return false; | ||
| 90 | } | ||
| 91 | |||
| 92 | if (!icon_file.Write(icon_dir)) { | ||
| 93 | return false; | ||
| 94 | } | ||
| 95 | if (!icon_file.Write(icon_entry)) { | ||
| 96 | return false; | ||
| 97 | } | ||
| 98 | if (!icon_file.Write(info_header)) { | ||
| 99 | return false; | ||
| 100 | } | ||
| 101 | |||
| 102 | for (int y = 0; y < image.height(); y++) { | ||
| 103 | const auto* line = source_image.scanLine(source_image.height() - 1 - y); | ||
| 104 | std::vector<u8> line_data(source_image.width() * bytes_per_pixel); | ||
| 105 | std::memcpy(line_data.data(), line, line_data.size()); | ||
| 106 | if (!icon_file.Write(line_data)) { | ||
| 107 | return false; | ||
| 108 | } | ||
| 109 | } | ||
| 110 | icon_file.Close(); | ||
| 111 | |||
| 112 | return true; | ||
| 113 | #else | ||
| 114 | return false; | ||
| 115 | #endif | ||
| 116 | } | ||
diff --git a/src/yuzu/util/util.h b/src/yuzu/util/util.h index 39dd2d895..09c14ce3f 100644 --- a/src/yuzu/util/util.h +++ b/src/yuzu/util/util.h | |||
| @@ -7,14 +7,22 @@ | |||
| 7 | #include <QString> | 7 | #include <QString> |
| 8 | 8 | ||
| 9 | /// Returns a QFont object appropriate to use as a monospace font for debugging widgets, etc. | 9 | /// Returns a QFont object appropriate to use as a monospace font for debugging widgets, etc. |
| 10 | QFont GetMonospaceFont(); | 10 | [[nodiscard]] QFont GetMonospaceFont(); |
| 11 | 11 | ||
| 12 | /// Convert a size in bytes into a readable format (KiB, MiB, etc.) | 12 | /// Convert a size in bytes into a readable format (KiB, MiB, etc.) |
| 13 | QString ReadableByteSize(qulonglong size); | 13 | [[nodiscard]] QString ReadableByteSize(qulonglong size); |
| 14 | 14 | ||
| 15 | /** | 15 | /** |
| 16 | * Creates a circle pixmap from a specified color | 16 | * Creates a circle pixmap from a specified color |
| 17 | * @param color The color the pixmap shall have | 17 | * @param color The color the pixmap shall have |
| 18 | * @return QPixmap circle pixmap | 18 | * @return QPixmap circle pixmap |
| 19 | */ | 19 | */ |
| 20 | QPixmap CreateCirclePixmapFromColor(const QColor& color); | 20 | [[nodiscard]] QPixmap CreateCirclePixmapFromColor(const QColor& color); |
| 21 | |||
| 22 | /** | ||
| 23 | * Saves a windows icon to a file | ||
| 24 | * @param path The icons path | ||
| 25 | * @param image The image to save | ||
| 26 | * @return bool If the operation succeeded | ||
| 27 | */ | ||
| 28 | [[nodiscard]] bool SaveIconToFile(const std::string_view path, const QImage& image); | ||