diff --git a/GlosSIConfig/GlosSIConfig.vcxproj b/GlosSIConfig/GlosSIConfig.vcxproj
index 0ba8142..b649a7b 100644
--- a/GlosSIConfig/GlosSIConfig.vcxproj
+++ b/GlosSIConfig/GlosSIConfig.vcxproj
@@ -143,6 +143,7 @@
+
diff --git a/GlosSIConfig/GlosSIConfig.vcxproj.filters b/GlosSIConfig/GlosSIConfig.vcxproj.filters
index f7483fd..08d81b8 100644
--- a/GlosSIConfig/GlosSIConfig.vcxproj.filters
+++ b/GlosSIConfig/GlosSIConfig.vcxproj.filters
@@ -80,6 +80,9 @@
qml
+
+ qml
+
diff --git a/GlosSIConfig/Resource.rc b/GlosSIConfig/Resource.rc
index 9f6cc17..73c56a6 100644
--- a/GlosSIConfig/Resource.rc
+++ b/GlosSIConfig/Resource.rc
@@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,0,9,1037005000102
- PRODUCTVERSION 0,0,9,1037005000102
+ 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 - Config"
- VALUE "FileVersion", "0.0.9.1-37-g5ebe102"
+ VALUE "FileVersion", "0.1.0.2-33-g929abfe"
VALUE "InternalName", "GlosSIConfig"
VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware"
VALUE "OriginalFilename", "GlosSIConfig.exe"
VALUE "ProductName", "GlosSI"
- VALUE "ProductVersion", "0.0.9.1-37-g5ebe102"
+ VALUE "ProductVersion", "0.1.0.2-33-g929abfe"
END
END
BLOCK "VarFileInfo"
@@ -1092,6 +1092,166 @@ IDI_ICON1 ICON "..\GlosSI_Icon.ico"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GlosSIConfig/UIModel.cpp b/GlosSIConfig/UIModel.cpp
index 24e08f3..f4ba80a 100644
--- a/GlosSIConfig/UIModel.cpp
+++ b/GlosSIConfig/UIModel.cpp
@@ -416,6 +416,31 @@ void UIModel::saveDefaultConf(QVariantMap conf) const
QVariantList UIModel::uwpApps() { return UWPFetch::UWPAppList(); }
#endif
+QVariantList UIModel::egsGamesList() const
+{
+ wchar_t* program_data_path_str;
+ std::filesystem::path path;
+ if (SHGetKnownFolderPath(FOLDERID_ProgramData, KF_FLAG_CREATE, NULL, &program_data_path_str) != S_OK) {
+ qDebug() << "Couldn't get ProgramDataPath";
+ return {{"InstallLocation", "Error"}};
+ }
+ path = std::filesystem::path(program_data_path_str);
+ path /= egs_games_json_path_;
+
+ QFile file(path);
+ if (file.open(QIODevice::ReadOnly)) {
+ const auto data = file.readAll();
+ file.close();
+ auto json = QJsonDocument::fromJson(data).object();
+ if (json["InstallationList"].isArray()) {
+ return json["InstallationList"].toVariant().toList();
+ }
+ qDebug() << "InstallationList does not exist!";
+ }
+ qDebug() << "Couldn't read EGS LauncherInstalled.dat " << path;
+ return {{"InstallLocation", "Error"}};
+}
+
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 8943d27..96eae0d 100644
--- a/GlosSIConfig/UIModel.h
+++ b/GlosSIConfig/UIModel.h
@@ -29,6 +29,7 @@ class UIModel : public QObject {
Q_PROPERTY(bool hasAcrlyicEffect READ hasAcrylicEffect NOTIFY acrylicChanged)
Q_PROPERTY(QVariantList targetList READ getTargetList NOTIFY targetListChanged)
Q_PROPERTY(QVariantList uwpList READ uwpApps CONSTANT)
+ Q_PROPERTY(QVariantList egsList READ egsGamesList CONSTANT)
Q_PROPERTY(bool foundSteam READ foundSteam CONSTANT)
Q_PROPERTY(bool steamInputXboxSupportEnabled READ isSteamInputXboxSupportEnabled CONSTANT)
@@ -60,6 +61,7 @@ class UIModel : public QObject {
#ifdef _WIN32
Q_INVOKABLE QVariantList uwpApps();
#endif
+ Q_INVOKABLE QVariantList egsGamesList() const;
[[nodiscard]] bool writeShortcutsVDF(const std::wstring& mode, const std::wstring& name,
const std::wstring& shortcutspath, bool is_admin_try = false) const;
@@ -92,6 +94,9 @@ class UIModel : public QObject {
QString user_data_path_ = "/userdata/";
QString steam_executable_name_ = "steam.exe";
+ const std::wstring_view egs_games_json_path_ =
+ L"Epic/UnrealEngineLauncher/LauncherInstalled.dat";
+
QVariantList targets_;
QString new_version_name_;
diff --git a/GlosSIConfig/qml.qrc b/GlosSIConfig/qml.qrc
index d3945e1..c9a5eaa 100644
--- a/GlosSIConfig/qml.qrc
+++ b/GlosSIConfig/qml.qrc
@@ -22,5 +22,6 @@
qml/AdvancedTargetSettings.qml
qml/GlobalConf.qml
svg/settings_fill_white_24dp.svg
+ qml/EGSSelectDialog.qml
diff --git a/GlosSIConfig/qml/AddSelectTypeDialog.qml b/GlosSIConfig/qml/AddSelectTypeDialog.qml
index 8ecc10e..42b36a3 100644
--- a/GlosSIConfig/qml/AddSelectTypeDialog.qml
+++ b/GlosSIConfig/qml/AddSelectTypeDialog.qml
@@ -89,7 +89,7 @@ Dialog {
}
}
Button {
- visible: uiModel.isWindows
+ visible: uiModel.isWindows
text: qsTr("UWP App")
highlighted: true
onClicked: function(){
@@ -97,6 +97,15 @@ Dialog {
confirmed("uwp")
}
}
+ Button {
+ visible: uiModel.isWindows
+ text: qsTr("EGS Game")
+ highlighted: true
+ onClicked: function(){
+ close()
+ confirmed("egs")
+ }
+ }
}
}
diff --git a/GlosSIConfig/qml/EGSSelectDialog.qml b/GlosSIConfig/qml/EGSSelectDialog.qml
new file mode 100644
index 0000000..5fce0bd
--- /dev/null
+++ b/GlosSIConfig/qml/EGSSelectDialog.qml
@@ -0,0 +1,230 @@
+/*
+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 6.2
+import QtQuick.Controls 6.2
+import QtQuick.Layouts 6.2
+import QtQuick.Controls.Material 6.2
+
+Dialog {
+ id: dlg
+ 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 var unfilteredModel: null;
+ property var filteredModel: [];
+
+
+ onOpened: function() {
+ unfilteredModel = null;
+ unfilteredModel = uiModel.egsList;
+ listview.model = null;
+ filteredModel = [];
+ for(let i = 0; i < unfilteredModel.length; i++)
+ {
+ filteredModel.push(unfilteredModel[i])
+ }
+ listview.model = filteredModel
+ }
+
+ onClosed: function() {
+ listview.model = null;
+ unfilteredModel = null;
+ filteredModel = null;
+ }
+
+ 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: dlg; 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: dlg; 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("Select Epic Games Launcher Game...")
+ font.pixelSize: 24
+ font.bold: true
+ }
+
+ FluentTextInput {
+ width: listview.width - 2
+ x: 1
+ anchors.top: titlelabel.bottom
+ anchors.topMargin: 8
+ id: searchBar
+ enabled: true
+ placeholderText: qsTr("Search...")
+ text: ""
+ onTextChanged: function() {
+ listview.model = null;
+ filteredModel = [];
+ for(let i = 0; i < unfilteredModel.length; i++)
+ {
+ if(unfilteredModel[i].AppName.toLowerCase().includes(searchBar.text.toLowerCase())) {
+ filteredModel.push(unfilteredModel[i])
+ }
+ }
+ listview.model = filteredModel
+ }
+ }
+
+ BusyIndicator {
+ running: visible
+ anchors.centerIn: parent
+ opacity: (!unfilteredModel || unfilteredModel.length == 0) ? 1 : 0
+ Behavior on opacity {
+ NumberAnimation {
+ duration: 350
+ easing.type: Easing.InOutQuad
+ }
+ }
+ 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
+ id: listview
+ width: window.width * 0.45
+ height: window.height * 0.66
+ spacing: 0
+ clip: true
+ model: filteredModel
+ ScrollBar.vertical: ScrollBar {
+ }
+
+ opacity: (!unfilteredModel || unfilteredModel.length == 0) ? 0 : 1
+ 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: textcolumn.implicitHeight > 72 ? 500 : 72
+
+ /*Image {
+ id: maybeIcon
+ width: textcolumn.implicitHeight > 72 ? 0 : 56
+ height: 56
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ source: "file:///" + modelData.IconPath
+ mipmap: true
+ smooth: true
+ }*/
+
+ Column {
+ id: textcolumn
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.leftMargin: 16
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 2
+ Label {
+ text: modelData.InstallLocation.split('/').pop().split('\\').pop()
+ font.pixelSize: 18
+ font.bold: true
+ }
+ Label {
+ id: appNameLabel
+ text: "AppName: " + modelData.AppName
+ font.pixelSize: 12
+ wrapMode: Text.WordWrap
+ width: parent.width
+ }
+ Label {
+ id: fullPathLabel
+ text: modelData.InstallLocation
+ font.pixelSize: 12
+ color: '#888888'
+ wrapMode: Text.WordWrap
+ width: parent.width
+ }
+ }
+
+ Rectangle {
+ anchors.bottom: parent.bottom
+ height: 1
+ width: parent.width
+ color: Qt.rgba(1,1,1,0.25)
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: function(){
+ confirmed(modelData)
+ dlg.close();
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GlosSIConfig/qml/ShortcutProps.qml b/GlosSIConfig/qml/ShortcutProps.qml
index ecf7b3a..30862f5 100644
--- a/GlosSIConfig/qml/ShortcutProps.qml
+++ b/GlosSIConfig/qml/ShortcutProps.qml
@@ -26,6 +26,7 @@ Item {
property alias fileDialog: fileDialog
property alias uwpSelectDialog: uwpSelectDialog
+ property alias egsSelectDialog: egsSelectDialog
signal cancel()
signal done(var shortcut)
@@ -309,6 +310,21 @@ Item {
launchApp.checked = true
}
}
+ EGSSelectDialog {
+ id: egsSelectDialog
+ onConfirmed: function(modelData) {
+ if (nameInput.text == "") {
+ nameInput.text = modelData.InstallLocation.split('/').pop().split('\\').pop()
+ }
+ pathInput.text = "com.epicgames.launcher://apps/"
+ + modelData.NamespaceId
+ + "%3A"
+ + modelData.ItemId
+ + "%3A"
+ + modelData.ArtifactId + "?action=launch&silent=true"
+ launchApp.checked = true
+ }
+ }
InfoDialog {
id: helpInfoDialog
diff --git a/GlosSIConfig/qml/main.qml b/GlosSIConfig/qml/main.qml
index 3894e96..579cdfb 100644
--- a/GlosSIConfig/qml/main.qml
+++ b/GlosSIConfig/qml/main.qml
@@ -387,6 +387,9 @@ Window {
if (param == "uwp") {
props.uwpSelectDialog.open();
}
+ if (param == "egs") {
+ props.egsSelectDialog.open();
+ }
}
}
}