diff --git a/src/Eden/Config/GlobalConfigureDialog.qml b/src/Eden/Config/GlobalConfigureDialog.qml index 0d5fc68abb..f2edf2d180 100644 --- a/src/Eden/Config/GlobalConfigureDialog.qml +++ b/src/Eden/Config/GlobalConfigureDialog.qml @@ -40,6 +40,9 @@ Dialog { if (EdenApplication.shouldReload) { EdenApplication.shouldReload = false + + // TODO(crueter): Warn the user. + // TODO(crueter): Configurable game icon size for carousel EdenApplication.reload() } } @@ -72,8 +75,8 @@ Dialog { height: Math.min(contentHeight * count + 20, parent.height - tabBar.topMargin) - contentWidth: 85 - contentHeight: 55 + contentWidth: 110 + contentHeight: 45 position: TabBar.Footer @@ -88,6 +91,9 @@ Dialog { "Graphics"), qsTr("Audio"), qsTr("Debug"), qsTr("Controls")] CarboxylTabButton { + font.pixelSize: 15 + font.weight: 600 + text: modelData coloredIcon: true inlineIcon: true diff --git a/src/Eden/Config/pages/global/GlobalTab.qml b/src/Eden/Config/pages/global/GlobalTab.qml index 0fe8c3bee4..6d141fced5 100644 --- a/src/Eden/Config/pages/global/GlobalTab.qml +++ b/src/Eden/Config/pages/global/GlobalTab.qml @@ -28,6 +28,7 @@ Item { CarboxylTabButton { font.pixelSize: 14 + font.weight: 600 text: modelData } } diff --git a/src/Eden/Constants/Constants.qml b/src/Eden/Constants/Constants.qml index c7937b5f60..510931f399 100644 --- a/src/Eden/Constants/Constants.qml +++ b/src/Eden/Constants/Constants.qml @@ -3,6 +3,6 @@ pragma Singleton import QtQuick QtObject { - readonly property int width: 1200 - readonly property int height: 1000 + readonly property int width: 900 + readonly property int height: 600 } diff --git a/src/Eden/Interface/CMakeLists.txt b/src/Eden/Interface/CMakeLists.txt index d4fa2e6b1e..8af7e048cf 100644 --- a/src/Eden/Interface/CMakeLists.txt +++ b/src/Eden/Interface/CMakeLists.txt @@ -17,4 +17,5 @@ EdenModule( LIBRARIES Qt6::Quick Qt6::Core + frontend_common ) diff --git a/src/Eden/Models/CMakeLists.txt b/src/Eden/Models/CMakeLists.txt index 5aad3758f0..dc3f4b00ac 100644 --- a/src/Eden/Models/CMakeLists.txt +++ b/src/Eden/Models/CMakeLists.txt @@ -13,10 +13,7 @@ qt_add_library(EdenModels STATIC GameIconProvider.h GameIconProvider.cpp ) -target_link_libraries(EdenModels - PRIVATE - Qt6::Gui -) -target_link_libraries(EdenModels PRIVATE Qt6::Core Qt6::Quick) +target_link_libraries(EdenModels PRIVATE Qt6::Core Qt6::Quick Qt6::Gui) +target_link_libraries(EdenModels PUBLIC frontend_common) add_library(Eden::Models ALIAS EdenModels) diff --git a/src/Eden/Native/EdenApplication.cpp b/src/Eden/Native/EdenApplication.cpp index a7614d2e16..bd5f7a1379 100644 --- a/src/Eden/Native/EdenApplication.cpp +++ b/src/Eden/Native/EdenApplication.cpp @@ -67,7 +67,7 @@ int EdenApplication::run() { CarboxylApplication *carboxylApp = new CarboxylApplication(*this, &engine, style, - QStringLiteral("Trioxide")); + QStringLiteral("Helios")); carboxylApp->setParent(this); /// CONTEXT diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index 212f76f476..b576882a8b 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -409,7 +409,8 @@ std::unique_ptr InitializeTranslations(QObject* parent) INSERT(UISettings, carboxyl_theme, tr("Theme"), tr("The palette to use throughout the application.")); // TODO: brief explanations, link to Carboxyl? - INSERT(UISettings, carboxyl_style, tr("Style"), tr("The control style to use throughout the application.")); + INSERT(UISettings, carboxyl_style, tr("Style"), tr("The control style to use throughout the application.\n" + "Eden will restart when this is changed.")); #endif // Ui General diff --git a/src/qt_common/config/uisettings.h b/src/qt_common/config/uisettings.h index 0c2688f289..9e5c12f0bb 100644 --- a/src/qt_common/config/uisettings.h +++ b/src/qt_common/config/uisettings.h @@ -160,7 +160,7 @@ struct Values { // TODO: native-like style default Setting carboxyl_theme{linkage, Settings::Theme::System , "carboxyl_theme", Category::UiLayout}; Setting carboxyl_style{linkage, - Settings::Style::Trioxide, + Settings::Style::Helios, "carboxyl_style", Category::UiLayout}; Setting carboxyl_accent{linkage, Settings::Accent::System , "carboxyl_accent", Category::UiLayout}; diff --git a/src/qt_common/externals/cpmfile.json b/src/qt_common/externals/cpmfile.json index e9ea6c98fb..2af23ad36d 100644 --- a/src/qt_common/externals/cpmfile.json +++ b/src/qt_common/externals/cpmfile.json @@ -19,8 +19,8 @@ "package": "Carboxyl", "repo": "crueter/Carboxyl", "git_host": "git.crueter.xyz", - "sha": "6789e1b2c9", - "hash": "e067c5a5ddb4ef77fee58afd4fb47ef4058b68213a33bc52a349b597aa25b8eb9cbb695c580ae59b82373531d0c96c24f192ada11dc7e198c9c33364a213b90d", + "sha": "cb73477b37", + "hash": "da0fd04f111e1c94d16bf57a3bbc29d5a3f1a8255c55eed0160e487acc827f190e6abcd1e38258d127493c0919b3685de24735866bb6d7820cafa6ed80b4f393", "bundled": "true", "options": [ "CARBOXYL_DEMO OFF" diff --git a/src/qt_common/qt_common.cpp b/src/qt_common/qt_common.cpp index ade4731658..7ea278acd3 100644 --- a/src/qt_common/qt_common.cpp +++ b/src/qt_common/qt_common.cpp @@ -43,6 +43,8 @@ #ifdef _WIN32 #include #include +#include "core/core_timing.h" +#include "common/windows/timer_resolution.h" #endif using namespace Common::Literals; diff --git a/src/qt_common/util/game.cpp b/src/qt_common/util/game.cpp index e34a388993..8949d21892 100644 --- a/src/qt_common/util/game.cpp +++ b/src/qt_common/util/game.cpp @@ -22,6 +22,7 @@ #include "common/string_util.h" #include #include +#include "common/fs/file.h" #else #include "fmt/ostream.h" #include @@ -581,4 +582,110 @@ void CreateHomeMenuShortcut(ShortcutTarget target) CreateShortcut(game_path, QLaunchId, "Switch Home Menu", target, "-qlaunch", false); } +bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image) { +#if defined(WIN32) +#pragma pack(push, 2) + struct IconDir { + WORD id_reserved; + WORD id_type; + WORD id_count; + }; + + struct IconDirEntry { + BYTE width; + BYTE height; + BYTE color_count; + BYTE reserved; + WORD planes; + WORD bit_count; + DWORD bytes_in_res; + DWORD image_offset; + }; +#pragma pack(pop) + + const QImage source_image = image.convertToFormat(QImage::Format_RGB32); + constexpr std::array scale_sizes{256, 128, 64, 48, 32, 24, 16}; + constexpr int bytes_per_pixel = 4; + + const IconDir icon_dir{ + .id_reserved = 0, + .id_type = 1, + .id_count = static_cast(scale_sizes.size()), + }; + + Common::FS::IOFile icon_file(icon_path.string(), Common::FS::FileAccessMode::Write, + Common::FS::FileType::BinaryFile); + if (!icon_file.IsOpen()) { + return false; + } + + if (!icon_file.Write(icon_dir)) { + return false; + } + + std::size_t image_offset = sizeof(IconDir) + (sizeof(IconDirEntry) * scale_sizes.size()); + for (std::size_t i = 0; i < scale_sizes.size(); i++) { + const int image_size = scale_sizes[i] * scale_sizes[i] * bytes_per_pixel; + const IconDirEntry icon_entry{ + .width = static_cast(scale_sizes[i]), + .height = static_cast(scale_sizes[i]), + .color_count = 0, + .reserved = 0, + .planes = 1, + .bit_count = bytes_per_pixel * 8, + .bytes_in_res = static_cast(sizeof(BITMAPINFOHEADER) + image_size), + .image_offset = static_cast(image_offset), + }; + image_offset += icon_entry.bytes_in_res; + if (!icon_file.Write(icon_entry)) { + return false; + } + } + + for (std::size_t i = 0; i < scale_sizes.size(); i++) { + const QImage scaled_image = source_image.scaled( + scale_sizes[i], scale_sizes[i], Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + const BITMAPINFOHEADER info_header{ + .biSize = sizeof(BITMAPINFOHEADER), + .biWidth = scaled_image.width(), + .biHeight = scaled_image.height() * 2, + .biPlanes = 1, + .biBitCount = bytes_per_pixel * 8, + .biCompression = BI_RGB, + .biSizeImage{}, + .biXPelsPerMeter{}, + .biYPelsPerMeter{}, + .biClrUsed{}, + .biClrImportant{}, + }; + + if (!icon_file.Write(info_header)) { + return false; + } + + for (int y = 0; y < scaled_image.height(); y++) { + const auto* line = scaled_image.scanLine(scaled_image.height() - 1 - y); + std::vector line_data(scaled_image.width() * bytes_per_pixel); + std::memcpy(line_data.data(), line, line_data.size()); + if (!icon_file.Write(line_data)) { + return false; + } + } + } + icon_file.Close(); + + return true; +#elif defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) + // 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; +#else + return false; +#endif +} + } // namespace QtCommon::Game diff --git a/src/qt_common/util/game.h b/src/qt_common/util/game.h index 2a7c77ef2d..849002f468 100644 --- a/src/qt_common/util/game.h +++ b/src/qt_common/util/game.h @@ -81,6 +81,14 @@ void CreateShortcut(const std::string& game_path, std::string GetShortcutPath(ShortcutTarget target); void CreateHomeMenuShortcut(ShortcutTarget target); +// uh // +/** + * Saves a windows icon to a file + * @param path The icons path + * @param image The image to save + * @return bool If the operation succeeded + */ +[[nodiscard]] bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image); } #endif // QT_GAME_UTIL_H diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp index 307f121a49..81e05aecb1 100644 --- a/src/yuzu/util/util.cpp +++ b/src/yuzu/util/util.cpp @@ -15,11 +15,6 @@ #include "qt_common/qt_common.h" #include "yuzu/util/util.h" -#ifdef _WIN32 -#include -#include "common/fs/file.h" -#endif - QFont GetMonospaceFont() { QFont font(QStringLiteral("monospace")); // Automatic fallback to a monospace font on on platforms without a font called "monospace" @@ -43,111 +38,6 @@ QPixmap CreateCirclePixmapFromColor(const QColor& color) { return circle_pixmap; } -bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image) { -#if defined(WIN32) -#pragma pack(push, 2) - struct IconDir { - WORD id_reserved; - WORD id_type; - WORD id_count; - }; - - struct IconDirEntry { - BYTE width; - BYTE height; - BYTE color_count; - BYTE reserved; - WORD planes; - WORD bit_count; - DWORD bytes_in_res; - DWORD image_offset; - }; -#pragma pack(pop) - - const QImage source_image = image.convertToFormat(QImage::Format_RGB32); - constexpr std::array scale_sizes{256, 128, 64, 48, 32, 24, 16}; - constexpr int bytes_per_pixel = 4; - - const IconDir icon_dir{ - .id_reserved = 0, - .id_type = 1, - .id_count = static_cast(scale_sizes.size()), - }; - - Common::FS::IOFile icon_file(icon_path.string(), Common::FS::FileAccessMode::Write, - Common::FS::FileType::BinaryFile); - if (!icon_file.IsOpen()) { - return false; - } - - if (!icon_file.Write(icon_dir)) { - return false; - } - - std::size_t image_offset = sizeof(IconDir) + (sizeof(IconDirEntry) * scale_sizes.size()); - for (std::size_t i = 0; i < scale_sizes.size(); i++) { - const int image_size = scale_sizes[i] * scale_sizes[i] * bytes_per_pixel; - const IconDirEntry icon_entry{ - .width = static_cast(scale_sizes[i]), - .height = static_cast(scale_sizes[i]), - .color_count = 0, - .reserved = 0, - .planes = 1, - .bit_count = bytes_per_pixel * 8, - .bytes_in_res = static_cast(sizeof(BITMAPINFOHEADER) + image_size), - .image_offset = static_cast(image_offset), - }; - image_offset += icon_entry.bytes_in_res; - if (!icon_file.Write(icon_entry)) { - return false; - } - } - - for (std::size_t i = 0; i < scale_sizes.size(); i++) { - const QImage scaled_image = source_image.scaled( - scale_sizes[i], scale_sizes[i], Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - const BITMAPINFOHEADER info_header{ - .biSize = sizeof(BITMAPINFOHEADER), - .biWidth = scaled_image.width(), - .biHeight = scaled_image.height() * 2, - .biPlanes = 1, - .biBitCount = bytes_per_pixel * 8, - .biCompression = BI_RGB, - .biSizeImage{}, - .biXPelsPerMeter{}, - .biYPelsPerMeter{}, - .biClrUsed{}, - .biClrImportant{}, - }; - - if (!icon_file.Write(info_header)) { - return false; - } - - for (int y = 0; y < scaled_image.height(); y++) { - const auto* line = scaled_image.scanLine(scaled_image.height() - 1 - y); - std::vector line_data(scaled_image.width() * bytes_per_pixel); - std::memcpy(line_data.data(), line, line_data.size()); - if (!icon_file.Write(line_data)) { - return false; - } - } - } - icon_file.Close(); - - return true; -#elif defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) - // 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; -#else - return false; -#endif -} const std::optional GetProfileID() { // if there's only a single profile, the user probably wants to use that... right? const auto& profiles = QtCommon::system->GetProfileManager().FindExistingProfileUUIDs(); diff --git a/src/yuzu/util/util.h b/src/yuzu/util/util.h index 7b482aa11d..9920aa9c78 100644 --- a/src/yuzu/util/util.h +++ b/src/yuzu/util/util.h @@ -6,7 +6,6 @@ #pragma once -#include #include #include #include "common/uuid.h" @@ -24,14 +23,6 @@ */ [[nodiscard]] QPixmap CreateCirclePixmapFromColor(const QColor& color); -/** - * Saves a windows icon to a file - * @param path The icons path - * @param image The image to save - * @return bool If the operation succeeded - */ -[[nodiscard]] bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image); - /** * Prompt the user for a profile ID. If there is only one valid profile, returns that profile. * @return The selected profile, or an std::nullopt if none were selected