diff --git a/GlosSIConfig/UIModel.cpp b/GlosSIConfig/UIModel.cpp index 0fe35a7..873304c 100644 --- a/GlosSIConfig/UIModel.cpp +++ b/GlosSIConfig/UIModel.cpp @@ -16,11 +16,11 @@ limitations under the License. #include "UIModel.h" #include +#include #include #include #include #include -#include #include @@ -153,7 +153,7 @@ void UIModel::deleteTarget(int index) emit targetListChanged(); } -bool UIModel::isInSteam(QVariant shortcut) +bool UIModel::isInSteam(QVariant shortcut) const { const auto map = shortcut.toMap(); for (auto& steam_shortcut : shortcuts_vdf_) { @@ -167,7 +167,7 @@ bool UIModel::isInSteam(QVariant shortcut) return false; } -uint32_t UIModel::getAppId(QVariant shortcut) +uint32_t UIModel::getAppId(QVariant shortcut) const { if (!isInSteam(shortcut)) { return 0; @@ -411,7 +411,8 @@ QVariantMap UIModel::getDefaultConf() const obj[key] = defaults.value(key); } if (obj.value(key).isObject()) { - obj[key] = applyDefaultsFn(obj[key].toObject(), defaults.value(key).toObject(), applyDefaultsFn); + obj[key] = + applyDefaultsFn(obj[key].toObject(), defaults.value(key).toObject(), applyDefaultsFn); } } return obj; @@ -478,6 +479,33 @@ QVariantList UIModel::egsGamesList() const return {{"InstallLocation", "Error"}}; } + +QString UIModel::getGridImagePath(QVariant shortcut) const +{ + if (!foundSteam()) { + return ""; + } + const auto& app_id = getAppId(shortcut); + if (app_id == 0) { + return ""; + } + + const std::filesystem::path grid_dir = + std::wstring(getSteamPath()) + user_data_path_.toStdWString() + getSteamUserId() + L"/config/grid"; + if (!std::filesystem::exists(grid_dir)) { + return ""; + } + const std::vector extensions = {".png", ".jpg"}; + for (const auto& entry : std::filesystem::directory_iterator(grid_dir)) { + if (entry.is_regular_file() + && std::ranges::find(extensions, entry.path().extension().string()) != extensions.end() + && entry.path().filename().string().find(std::to_string(app_id)) != std::string::npos) { + return QString::fromStdString(entry.path().string()); + } + } + return ""; +} + bool UIModel::writeShortcutsVDF(const std::wstring& mode, const std::wstring& name, const std::wstring& shortcutspath, bool is_admin_try) const { diff --git a/GlosSIConfig/UIModel.h b/GlosSIConfig/UIModel.h index 93548bb..fa4c944 100644 --- a/GlosSIConfig/UIModel.h +++ b/GlosSIConfig/UIModel.h @@ -45,8 +45,8 @@ class UIModel : public QObject { Q_INVOKABLE void addTarget(QVariant shortcut); Q_INVOKABLE bool updateTarget(int index, QVariant shortcut); Q_INVOKABLE void deleteTarget(int index); - Q_INVOKABLE bool isInSteam(QVariant shortcut); - Q_INVOKABLE uint32_t getAppId(QVariant shortcut); + Q_INVOKABLE bool isInSteam(QVariant shortcut) const; + Q_INVOKABLE uint32_t getAppId(QVariant shortcut) const; Q_INVOKABLE bool addToSteam(QVariant shortcut, const QString& shortcutspath, bool from_cmd = false); bool addToSteam(const QString& name, const QString& shortcutspath, bool from_cmd = false); Q_INVOKABLE bool removeFromSteam(const QString& name, const QString& shortcutspath, bool from_cmd = false); @@ -65,6 +65,8 @@ class UIModel : public QObject { #endif Q_INVOKABLE QVariantList egsGamesList() const; + Q_INVOKABLE QString getGridImagePath(QVariant shortcut) const; + [[nodiscard]] bool writeShortcutsVDF(const std::wstring& mode, const std::wstring& name, const std::wstring& shortcutspath, bool is_admin_try = false) const; diff --git a/GlosSIConfig/qml/RPane.qml b/GlosSIConfig/qml/RPane.qml index 56748f6..8ada4b0 100644 --- a/GlosSIConfig/qml/RPane.qml +++ b/GlosSIConfig/qml/RPane.qml @@ -23,6 +23,8 @@ Pane { property int radius: 0 property color color: control.Material.backgroundColor property real bgOpacity: 1 + property string bgImgSource: null + property real bgImgOpacity: -1 background: Rectangle { color: parent.color opacity: parent.bgOpacity @@ -31,15 +33,19 @@ Pane { layer.enabled: control.enabled && control.Material.elevation > 0 layer.effect: ElevationEffect { elevation: control.Material.elevation + clip: true } + clip: true Image { + id: bgImage anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom - source: "qrc:/noise.png" - fillMode: Image.Tile - opacity: 0.035 + source: bgImgSource ? bgImgSource : "qrc:/noise.png" + fillMode: bgImgSource ? Image.PreserveAspectCrop : Image.Tile + opacity: bgImgOpacity < 0 ? 0.035 : bgImgOpacity + clip: true } } } \ No newline at end of file diff --git a/GlosSIConfig/qml/ShortcutCards.qml b/GlosSIConfig/qml/ShortcutCards.qml index 72e3f50..e0f634b 100644 --- a/GlosSIConfig/qml/ShortcutCards.qml +++ b/GlosSIConfig/qml/ShortcutCards.qml @@ -76,6 +76,8 @@ GridView { Material.elevation: 4 clip: true property bool isInSteam: uiModel.isInSteam(modelData); + bgImgSource: isInSteam ? "file:///" + uiModel.getGridImagePath(modelData) : null + bgImgOpacity: isInSteam ? 0.12 : -1 Image { anchors.top: parent.top @@ -88,6 +90,7 @@ GridView { : 'qrc:/svg/add_photo_alternate_white_24dp.svg' width: 48 height: 48 + fillMode: Image.PreserveAspectFit } Label { diff --git a/GlosSIConfig/qml/ShortcutProps.qml b/GlosSIConfig/qml/ShortcutProps.qml index 385a206..e2f5f3d 100644 --- a/GlosSIConfig/qml/ShortcutProps.qml +++ b/GlosSIConfig/qml/ShortcutProps.qml @@ -171,6 +171,7 @@ Item { flat: true contentItem: Image { id: maybeIcon + fillMode: Image.PreserveAspectFit source: shortcutInfo.icon ? shortcutInfo.icon.endsWith(".exe") ? "image://exe/" + shortcutInfo.icon