GlosSIConfig: Integrate SteamGrid

pull/192/head
Peter Repukat 2 years ago
parent 93026dfb75
commit 6e69b6ec1c

2
.gitignore vendored

@ -370,3 +370,5 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd
.visuallint
GlosSIConfig/steamgrid_api_keys.h
steamgrid.zip

@ -145,6 +145,7 @@
<None Include="qml\CollapsiblePane.qml" />
<None Include="qml\EGSSelectDialog.qml" />
<None Include="qml\GlobalConf.qml" />
<None Include="qml\SteamGridDialog.qml" />
<None Include="qml\SteamInputXboxDisabledDialog.qml" />
<None Include="qml\AddSelectTypeDialog.qml" />
<None Include="qml\FluentTextInput.qml" />
@ -163,6 +164,7 @@
<ItemGroup>
<ClInclude Include="ExeImageProvider.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="steamgrid_api_keys.h" />
<ClInclude Include="UWPFetch.h" />
<ClInclude Include="WinEventFilter.h" />
</ItemGroup>

@ -83,6 +83,9 @@
<None Include="qml\EGSSelectDialog.qml">
<Filter>qml</Filter>
</None>
<None Include="qml\SteamGridDialog.qml">
<Filter>qml</Filter>
</None>
</ItemGroup>
<ItemGroup>
<QtMoc Include="UIModel.h">
@ -102,6 +105,9 @@
<ClInclude Include="ExeImageProvider.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="steamgrid_api_keys.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Xml Include="manifest.xml">

@ -33,6 +33,7 @@ limitations under the License.
#endif
#include "../version.hpp"
#include "steamgrid_api_keys.h"
UIModel::UIModel() : QObject(nullptr)
{
@ -479,6 +480,17 @@ QVariantList UIModel::egsGamesList() const
return {{"InstallLocation", "Error"}};
}
void UIModel::loadSteamGridImages()
{
std::filesystem::path path = QCoreApplication::applicationDirPath().toStdWString();
path /= "steamgrid.exe";
steamgrid_proc_.setProgram(path.string().c_str());
steamgrid_proc_.setArguments({"-nonsteamonly", "--onlymissingartwork", "--steamgriddb", steamgridb_key});
connect(&steamgrid_proc_, &QProcess::readyReadStandardOutput, this, &UIModel::onSteamGridReadReady);
steamgrid_proc_.start();
steamgrid_proc_.write("\n");
}
QString UIModel::getGridImagePath(QVariant shortcut) const
{
@ -497,9 +509,9 @@ QString UIModel::getGridImagePath(QVariant shortcut) const
}
const std::vector<std::string> 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) {
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());
}
}
@ -586,6 +598,8 @@ void UIModel::setAcrylicEffect(bool has_acrylic_affect)
emit acrylicChanged();
}
QStringList UIModel::getSteamgridOutput() const { return steamgrid_output_; }
void UIModel::onAvailFilesResponse(QNetworkReply* reply)
{
@ -658,6 +672,12 @@ void UIModel::onAvailFilesResponse(QNetworkReply* reply)
}
}
void UIModel::onSteamGridReadReady()
{
steamgrid_output_.push_back(QString::fromLocal8Bit(steamgrid_proc_.readAllStandardOutput()));
emit steamgridOutputChanged();
}
void UIModel::writeTarget(const QJsonObject& json, const QString& name) const
{
auto path = config_path_;

@ -17,6 +17,7 @@ limitations under the License.
#include <QJsonObject>
#include <QObject>
#include <QVariant>
#include <QProcess>
#include <filesystem>
#include <shortcuts_vdf.hpp>
@ -37,6 +38,8 @@ class UIModel : public QObject {
Q_PROPERTY(QString versionString READ getVersionString CONSTANT)
Q_PROPERTY(QString newVersionName READ getNewVersionName NOTIFY newVersionAvailable)
Q_PROPERTY(QStringList steamgridOutput READ getSteamgridOutput NOTIFY steamgridOutputChanged)
public:
UIModel();
@ -65,6 +68,7 @@ class UIModel : public QObject {
#endif
Q_INVOKABLE QVariantList egsGamesList() const;
Q_INVOKABLE void loadSteamGridImages();
Q_INVOKABLE QString getGridImagePath(QVariant shortcut) const;
[[nodiscard]] bool writeShortcutsVDF(const std::wstring& mode, const std::wstring& name,
@ -75,13 +79,17 @@ class UIModel : public QObject {
[[nodiscard]] bool hasAcrylicEffect() const;
void setAcrylicEffect(bool has_acrylic_affect);
QStringList getSteamgridOutput() const;
signals:
void acrylicChanged();
void targetListChanged();
void newVersionAvailable();
void steamgridOutputChanged();
public slots:
void onAvailFilesResponse(QNetworkReply* reply);
void onSteamGridReadReady();
private:
#ifdef _WIN32
@ -107,6 +115,9 @@ class UIModel : public QObject {
QString new_version_name_;
bool notify_on_snapshots_ = false;
QProcess steamgrid_proc_;
QStringList steamgrid_output_;
std::vector<VDFParser::Shortcut> shortcuts_vdf_;
void writeTarget(const QJsonObject& json, const QString& name) const;

@ -24,5 +24,6 @@
<file>svg/settings_fill_white_24dp.svg</file>
<file>qml/EGSSelectDialog.qml</file>
<file>svg/add_photo_alternate_white_24dp.svg</file>
<file>qml/SteamGridDialog.qml</file>
</qresource>
</RCC>

@ -0,0 +1,156 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Controls.Material
Dialog {
id: gridDialog
anchors.centerIn: parent
signal confirmed(var param)
visible: false
modal: true
dim: true
parent: Overlay.overlay
Overlay.modal: Rectangle {
color: Qt.rgba(0,0,0,0.4)
opacity: backdropOpacity
Behavior on opacity {
NumberAnimation {
duration: 300
}
}
}
property real backdropOpacity: 1.0
property bool loading: true
onOpened: function() {
loading = true;
uiModel.loadSteamGridImages();
}
onClosed: function() {
}
enter: Transition {
NumberAnimation{target: content; property: "y"; from: parent.height; to: 16; duration: 300; easing.type: Easing.OutQuad }
NumberAnimation{target: background; property: "y"; from: parent.height; to: 0; duration: 300; easing.type: Easing.OutQuad }
NumberAnimation{target: gridDialog; property: "backdropOpacity"; from: 0; to: 1; duration: 300; easing.type: Easing.OutQuad }
}
exit: Transition {
NumberAnimation{target: content; property: "y"; from: 16; to: parent.height; duration: 300; easing.type: Easing.InQuad }
NumberAnimation{target: background; property: "y"; from: 0; to: parent.height; duration: 300; easing.type: Easing.InQuad }
NumberAnimation{target: gridDialog; property: "backdropOpacity"; from: 1; to: 0; duration: 300; easing.type: Easing.InQuad }
}
background: RPane {
id: background
radius: 4
Material.elevation: 64
bgOpacity: 0.97
}
contentItem: Item {
id: content
implicitWidth: listview.width
implicitHeight: listview.height + titlelabel.height + 16 + 64
clip: true
Label {
id: titlelabel
text: qsTr("Loading Grid images...")
font.pixelSize: 24
font.bold: true
}
BusyIndicator {
id: busyIndicator
running: visible
anchors.top: titlelabel.bottom
anchors.topMargin: 8
anchors.horizontalCenter: parent.horizontalCenter
opacity: loading ? 1 : 0
height: loading ? 72 : 0
Behavior on opacity {
NumberAnimation {
duration: 350
easing.type: Easing.InOutQuad
}
}
visible: loading
}
ListView {
anchors.top: busyIndicator.bottom
anchors.topMargin: 16
anchors.bottom: parent.bottom
anchors.bottomMargin: 16
id: listview
width: window.width * 0.45
height: window.height * 0.66
spacing: 0
clip: true
model: uiModel.steamgridOutput
ScrollBar.vertical: ScrollBar {
}
onCountChanged: {
listview.positionViewAtIndex(listview.count - 1, ListView.Visible)
loading = !listview.model[listview.count - 1].includes("Press enter")
}
Behavior on opacity {
ParallelAnimation {
NumberAnimation {
duration: 350
easing.type: Easing.InOutQuad
}
PropertyAnimation {
target: listview
property: "anchors.topMargin"
from: window.height * 0.75
to: 16
duration: 350
easing.type: Easing.InOutQuad
}
}
}
delegate: /* Item {
width: listview.width
height: outputLabel.implicitHeight */
Label {
id: outputLabel
text: modelData
}
// }
}
Button {
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 2
anchors.rightMargin: 2
text: qsTr("Ok")
onClicked: gridDialog.close()
}
}
}

@ -126,15 +126,6 @@ Dialog {
visible: opacity == 0 ? false : true
}
Button {
anchors.right: parent.right
anchors.top: listview.bottom
anchors.topMargin: 16
anchors.rightMargin: 2
text: qsTr("Cancel")
onClicked: dlg.close()
}
ListView {
anchors.top: searchBar.bottom
anchors.topMargin: 16
@ -218,5 +209,14 @@ Dialog {
}
}
}
Button {
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 2
anchors.rightMargin: 2
text: qsTr("Cancel")
onClicked: dlg.close()
}
}
}

@ -48,6 +48,12 @@ Window {
}
property bool steamShortcutsChanged: false
onSteamShortcutsChanged: function() {
shouldShowLoadGridImagesButton = uiModel.targetList.some((shortcut) => uiModel.isInSteam(shortcut))
}
property bool shouldShowLoadGridImagesButton: false
Component.onCompleted: function() {
if (!uiModel.foundSteam) {
@ -57,6 +63,7 @@ Window {
if (!uiModel.steamInputXboxSupportEnabled) {
steamXboxDisabledDialog.open();
}
shouldShowLoadGridImagesButton = uiModel.targetList.some((shortcut) => uiModel.isInSteam(shortcut))
}
Image {
@ -370,47 +377,64 @@ Window {
windowContent.editedIndex = index;
}
}
Column {
Row {
spacing: 8
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: 24
RoundButton {
id: optionsBtn
width: 64
height: 64
text: ""
contentItem: Item {
Image {
Column {
spacing: 8
RoundButton {
id: optionsBtn
anchors.right: parent.right
width: 64
height: 64
text: ""
contentItem: Item {
Image {
anchors.centerIn: parent
source: "qrc:/svg/settings_fill_white_24dp.svg"
width: 24
height: 24
}
}
highlighted: true
onClicked: function() {
globalConf.opacity = 1;
homeContent.opacity = 0;
}
}
RoundButton {
id: addBtn
anchors.right: parent.right
width: 64
height: 64
text: "+"
contentItem: Label {
anchors.centerIn: parent
source: "qrc:/svg/settings_fill_white_24dp.svg"
width: 24
height: 24
text: addBtn.text
font.pixelSize: 32
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
}
highlighted: true
onClicked: function() {
globalConf.opacity = 1;
homeContent.opacity = 0;
highlighted: true
onClicked: selectTypeDialog.open()
}
}
RoundButton {
id: addBtn
width: 64
height: 64
text: "+"
contentItem: Label {
anchors.centerIn: parent
text: addBtn.text
font.pixelSize: 32
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
Button {
visible: shouldShowLoadGridImagesButton || steamShortcutsChanged
id: loadGridImagesBtn
text: qsTr("🖼️ Load steam grid images")
highlighted: true
onClicked: function() {
steamGridDialog.open()
}
}
highlighted: true
onClicked: selectTypeDialog.open()
}
}
}
Item {
@ -532,5 +556,10 @@ Window {
}
}
}
SteamGridDialog {
id: steamGridDialog
}
}
}

@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,1,0,203000008020
PRODUCTVERSION 0,1,0,203000008020
FILEVERSION 0,1,0,2033009290000
PRODUCTVERSION 0,1,0,2033009290000
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Peter Repukat - FlatspotSoftware"
VALUE "FileDescription", "GlosSI - SteamTarget"
VALUE "FileVersion", "0.1.0.2-3-gcea802b"
VALUE "FileVersion", "0.1.0.2-33-g929abfe"
VALUE "InternalName", "GlosSITarget"
VALUE "LegalCopyright", "Copyright (C) 2021-2022 Peter Repukat - FlatspotSoftware"
VALUE "OriginalFilename", "GlosSITarget.exe"
VALUE "ProductName", "GlosSI"
VALUE "ProductVersion", "0.1.0.2-3-gcea802b"
VALUE "ProductVersion", "0.1.0.2-33-g929abfe"
END
END
BLOCK "VarFileInfo"

@ -18,6 +18,7 @@ Copy-Item "..\..\vc_redist.x64.exe" -Destination "."
Copy-Item "..\..\LICENSE" -Destination "./LICENSE"
Copy-Item "..\..\QT_License" -Destination "./QT_License"
Copy-Item "..\..\THIRD_PARTY_LICENSES.txt" -Destination "./THIRD_PARTY_LICENSES.txt"
Copy-Item "..\..\steamgrid.exe" -Destination "./steamgrid.exe"
Copy-Item "C:\Qt\Tools\OpenSSL\Win_x64\bin\libcrypto-1_1-x64.dll" -Destination "./libcrypto-1_1-x64.dll"
Copy-Item "C:\Qt\Tools\OpenSSL\Win_x64\bin\libssl-1_1-x64.dll" -Destination "./libssl-1_1-x64.dll"

@ -14,4 +14,20 @@ cd .\GlosSIConfig\
..\version_help.ps1
cd ../
$apiKeyText = "
/* Autogenerated version info file */
#pragma once
inline const char* steamgridb_key = ""$env:STEAMGRIDDB_KEY"";
"
if (!(Test-Path 'steamgrid_api_keys.h')) {
New-Item -Path "." -Name "steamgrid_api_keys.h" -ItemType "file" -Value $apiKeyText
}
cd ../
if (!(Test-Path 'steamgrid.exe')) {
Invoke-WebRequest -o steamgrid.zip https://github.com/boppreh/steamgrid/releases/download/v3.4.0/steamgrid_windows.zip
7z e steamgrid.zip steamgrid.exe
}

Loading…
Cancel
Save