diff --git a/GlosSIConfig/GlosSIConfig.vcxproj b/GlosSIConfig/GlosSIConfig.vcxproj index bf60a3a..28bde64 100644 --- a/GlosSIConfig/GlosSIConfig.vcxproj +++ b/GlosSIConfig/GlosSIConfig.vcxproj @@ -106,8 +106,13 @@ + + + + + @@ -116,6 +121,7 @@ + diff --git a/GlosSIConfig/GlosSIConfig.vcxproj.filters b/GlosSIConfig/GlosSIConfig.vcxproj.filters index f6e8476..7abfc2c 100644 --- a/GlosSIConfig/GlosSIConfig.vcxproj.filters +++ b/GlosSIConfig/GlosSIConfig.vcxproj.filters @@ -34,6 +34,9 @@ Source Files + + Source Files + @@ -42,11 +45,26 @@ qml + + qml + + + qml + + + qml + + + Source Files + Header Files + + Header Files + diff --git a/GlosSIConfig/TargetConfig.cpp b/GlosSIConfig/TargetConfig.cpp new file mode 100644 index 0000000..0b2e3e1 --- /dev/null +++ b/GlosSIConfig/TargetConfig.cpp @@ -0,0 +1,112 @@ +/* +Copyright 2021 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. +*/ +#include "TargetConfig.h" + +TargetConfig::TargetConfig() : QObject(nullptr) +{ + +} + +QString TargetConfig::getName() const +{ + return name_; +} + +void TargetConfig::setName(const QString& name) +{ + name_ = name; + emit nameChanged(); +} + +bool TargetConfig::getLaunch() const +{ + return launch_; +} + +void TargetConfig::setLaunch(const bool launch) +{ + launch_ = launch; +} + +QString TargetConfig::getLaunchPath() const +{ + return launch_path_; +} + +void TargetConfig::setLaunchPath(const QString& launch_path) +{ + launch_path_ = launch_path; +} + +QString TargetConfig::getLaunchAppArgs() const +{ + return launch_app_args_; +} + +void TargetConfig::setLaunchAppArgs(const QString& launch_app_args) +{ + launch_app_args_ = launch_app_args; +} + +bool TargetConfig::getCloseOnExit() const +{ + return close_on_exit_; +} + +void TargetConfig::setCloseOnExit(const bool close_on_exit) +{ + close_on_exit_ = close_on_exit; +} + +bool TargetConfig::getHideDevices() const +{ + return hide_devices_; +} + +void TargetConfig::setHideDevices(const bool hide_devices) +{ + hide_devices_ = hide_devices; +} + +bool TargetConfig::getWindowMode() const +{ + return window_mode_; +} + +void TargetConfig::setWindowMode(const bool window_mode) +{ + window_mode_ = window_mode; +} + +int TargetConfig::getMaxFps() const +{ + return max_fps_; +} + +void TargetConfig::setMaxFps(const int max_fps) +{ + max_fps_ = max_fps; +} + +float TargetConfig::getScale() const +{ + return scale_; +} + +void TargetConfig::setScale(const float scale) +{ + scale_ = scale; +} diff --git a/GlosSIConfig/TargetConfig.h b/GlosSIConfig/TargetConfig.h new file mode 100644 index 0000000..f199391 --- /dev/null +++ b/GlosSIConfig/TargetConfig.h @@ -0,0 +1,80 @@ +/* +Copyright 2021 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. +*/ +#pragma once +#include +#include +class TargetConfig : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged) + Q_PROPERTY(bool launch READ getLaunch WRITE setLaunch NOTIFY launchChanged) + Q_PROPERTY(QString launchPath READ getLaunchPath WRITE setLaunchPath NOTIFY launchPathChanged) + Q_PROPERTY(QString launchAppArgs READ getLaunchAppArgs WRITE setLaunchAppArgs NOTIFY launchAppArgsChanged) + Q_PROPERTY(bool closeOnExit READ getCloseOnExit WRITE setCloseOnExit NOTIFY closeOnExitChanged) + Q_PROPERTY(bool hideDevices READ getHideDevices WRITE setHideDevices NOTIFY hideDevicesChanged) + Q_PROPERTY(bool windowMode READ getWindowMode WRITE setWindowMode NOTIFY windowModeChanged) + Q_PROPERTY(int maxFps READ getMaxFps WRITE setMaxFps NOTIFY maxFpsChanged) + Q_PROPERTY(float scale READ getScale WRITE setScale NOTIFY scaleChanged) +public: + TargetConfig(); + + [[nodiscard]] QString getName() const; + void setName(const QString& name); + [[nodiscard]] bool getLaunch() const; + void setLaunch(const bool launch); + [[nodiscard]] QString getLaunchPath() const; + void setLaunchPath(const QString& launch_path); + [[nodiscard]] QString getLaunchAppArgs() const; + void setLaunchAppArgs(const QString& launch_app_args); + [[nodiscard]] bool getCloseOnExit() const; + void setCloseOnExit(const bool close_on_exit); + [[nodiscard]] bool getHideDevices() const; + void setHideDevices(const bool hide_devices); + [[nodiscard]] bool getWindowMode() const; + void setWindowMode(const bool window_mode); + [[nodiscard]] int getMaxFps() const; + void setMaxFps(const int max_fps); + [[nodiscard]] float getScale() const; + void setScale(const float scale); + + +signals: + void nameChanged(); + void launchChanged(); + void launchPathChanged(); + void launchAppArgsChanged(); + void closeOnExitChanged(); + void hideDevicesChanged(); + void windowModeChanged(); + void maxFpsChanged(); + void scaleChanged(); + + +private: + static inline constexpr int version_ = 1; + QString name_; + bool launch_ = true; + QString launch_path_; + QString launch_app_args_; + bool close_on_exit_ = true; + bool hide_devices_ = true; + bool window_mode_ = false; + int max_fps_ = 0; + float scale_ = 0; + +}; + diff --git a/GlosSIConfig/UIModel.cpp b/GlosSIConfig/UIModel.cpp index 00c974f..235293d 100644 --- a/GlosSIConfig/UIModel.cpp +++ b/GlosSIConfig/UIModel.cpp @@ -1,8 +1,25 @@ +/* +Copyright 2021 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. +*/ #include "UIModel.h" #include -UIModel::UIModel() +#include "TargetConfig.h" + +UIModel::UIModel() : QObject(nullptr) { auto path = std::filesystem::temp_directory_path() .parent_path() @@ -18,20 +35,71 @@ UIModel::UIModel() config_dir_name_ = (path /= "Targets").string().data(); } -QStringList UIModel::getTargetList() const +void UIModel::readConfigs() { QDir dir(config_dir_name_); auto entries = dir.entryList(QDir::Files, QDir::SortFlag::Name); entries.removeIf([](const auto& entry) { return entry.endsWith(".json"); }); - QStringList res; - std::ranges::transform(entries, std::back_inserter(res), [](const auto& entry) + QStringList fileNames; + std::ranges::transform(fileNames, std::back_inserter(fileNames), [](const auto& entry) { return entry.mid(0, entry.lastIndexOf(".json")); }); - res.push_back("Debug"); - return res; + + std::ranges::for_each(fileNames, [this](const auto& name) + { + targets_.append(QMap{ { "name", name }}); + }); + + + emit targetListChanged(); +} + +QVariantList UIModel::getTargetList() const +{ + return targets_; +} + +void UIModel::addTarget(QVariant shortcut) +{ + // TODO: write config + auto map = shortcut.toMap(); + + QVariantMap copy; + copy.insert("name", map["name"].toString()); + copy.insert("launch", map["launch"].toBool()); + copy.insert("launchPath", map["launchPath"].toString()); + copy.insert("launchAppArgs", map["launchAppArgs"].toString()); + copy.insert("closeOnExit", map["closeOnExit"].toBool()); + copy.insert("hideDevices", map["hideDevices"].toBool()); + copy.insert("windowMode", map["windowMode"].toBool()); + copy.insert("maxFps", map["maxFps"].toInt()); + copy.insert("scale", map["scale"].toInt()); + + targets_.append(copy); + emit targetListChanged(); +} + +void UIModel::updateTarget(int index, QVariant shortcut) +{ + + auto map = shortcut.toMap(); + + QVariantMap copy; + copy.insert("name", map["name"].toString()); + copy.insert("launch", map["launch"].toBool()); + copy.insert("launchPath", map["launchPath"].toString()); + copy.insert("launchAppArgs", map["launchAppArgs"].toString()); + copy.insert("closeOnExit", map["closeOnExit"].toBool()); + copy.insert("hideDevices", map["hideDevices"].toBool()); + copy.insert("windowMode", map["windowMode"].toBool()); + copy.insert("maxFps", map["maxFps"].toInt()); + copy.insert("scale", map["scale"].toInt()); + + targets_.replace(index, copy); + emit targetListChanged(); } bool UIModel::getIsWindows() const diff --git a/GlosSIConfig/UIModel.h b/GlosSIConfig/UIModel.h index 090d887..e763123 100644 --- a/GlosSIConfig/UIModel.h +++ b/GlosSIConfig/UIModel.h @@ -16,6 +16,7 @@ limitations under the License. #pragma once #include #include +#include class UIModel : public QObject { @@ -23,11 +24,15 @@ class UIModel : public QObject Q_PROPERTY(bool isWindows READ getIsWindows CONSTANT) Q_PROPERTY(bool hasAcrlyicEffect READ hasAcrylicEffect NOTIFY acrylicChanged) + Q_PROPERTY(QVariantList targetList READ getTargetList NOTIFY targetListChanged) public: UIModel(); - Q_INVOKABLE QStringList getTargetList() const; + Q_INVOKABLE void readConfigs(); + Q_INVOKABLE QVariantList getTargetList() const; + Q_INVOKABLE void addTarget(QVariant shortcut); + Q_INVOKABLE void updateTarget(int index, QVariant shortcut); bool getIsWindows() const; [[nodiscard]] bool hasAcrylicEffect() const; @@ -35,10 +40,14 @@ public: signals: void acrylicChanged(); + void targetListChanged(); private: std::filesystem::path config_path_; QString config_dir_name_; + + QVariantList targets_; + #ifdef _WIN32 bool is_windows_ = true; #else diff --git a/GlosSIConfig/qml.qrc b/GlosSIConfig/qml.qrc index 0106af5..b86653f 100644 --- a/GlosSIConfig/qml.qrc +++ b/GlosSIConfig/qml.qrc @@ -2,5 +2,9 @@ qml/main.qml qml/RPane.qml + qml/AddSelectTypeDialog.qml + qml/ShortcutCards.qml + qml/ShortcutProps.qml + qml/FluentTextInput.qml diff --git a/GlosSIConfig/qml/AddSelectTypeDialog.qml b/GlosSIConfig/qml/AddSelectTypeDialog.qml new file mode 100644 index 0000000..ce2c259 --- /dev/null +++ b/GlosSIConfig/qml/AddSelectTypeDialog.qml @@ -0,0 +1,102 @@ +/* +Copyright 2021 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 +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 + + 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 + readonly property real spacing: 16 + implicitWidth: row.width + implicitHeight: title.height + row.height + spacing + Label { + id: title + anchors.top: parent.top + anchors.left: parent.left + text: qsTr("Shortcut type") + font.bold: true + font.pixelSize: 24 + } + Row { + id: row + anchors.top: title.bottom + anchors.topMargin: parent.spacing + spacing: 16 + Button { + text: qsTr("Add manually") + highlighted: true + onClicked: function(){ + close() + confirmed("uwp") + } + } + Button { + text: qsTr("Win32 Program") + highlighted: true + onClicked: function(){ + close() + confirmed("uwp") + } + } + Button { + text: qsTr("UWP App") + highlighted: true + onClicked: function(){ + close() + confirmed("uwp") + } + } + } + } + +} diff --git a/GlosSIConfig/qml/FluentTextInput.qml b/GlosSIConfig/qml/FluentTextInput.qml new file mode 100644 index 0000000..e0fbeb6 --- /dev/null +++ b/GlosSIConfig/qml/FluentTextInput.qml @@ -0,0 +1,31 @@ +/* +Copyright 2021 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.Controls.Material 6.2 + +TextField { + id: control + selectByMouse: true + padding: 16 + bottomInset: padding/2 + background: Rectangle { + implicitWidth: control.width + control.padding*2 + radius: 4 + color: control.enabled ? Qt.rgba(0,0,0,0.3) : Qt.rgba(0.2,0.2,0.2,0.3) + border.color: control.enabled ? Qt.rgba(0.5,0.5,0.5,0.5) : Qt.rgba(0.3,0.3,0.3,0.5) + } +} \ No newline at end of file diff --git a/GlosSIConfig/qml/RPane.qml b/GlosSIConfig/qml/RPane.qml index eae2d70..c376df3 100644 --- a/GlosSIConfig/qml/RPane.qml +++ b/GlosSIConfig/qml/RPane.qml @@ -1,4 +1,19 @@ -import QtQuick 2.9 +/* +Copyright 2021 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 2.9 import QtQuick.Controls 2.9 import QtQuick.Controls.Material 2.9 import QtQuick.Controls.Material.impl 2.9 diff --git a/GlosSIConfig/qml/ShortcutCards.qml b/GlosSIConfig/qml/ShortcutCards.qml new file mode 100644 index 0000000..88fd242 --- /dev/null +++ b/GlosSIConfig/qml/ShortcutCards.qml @@ -0,0 +1,60 @@ +/* +Copyright 2021 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.Layouts 6.2 +import QtQuick.Controls 6.2 +import QtQuick.Controls.Material 6.2 + +GridView { + id: shortcutgrid + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + anchors.topMargin: margins + visible: model.length > 0 + signal editClicked(var index, var shortcutInfo) + + property real margins: 16 + cellWidth: 242 + 8 + cellHeight: 149 + 8 + readonly property real displayedItems: Math.floor((parent.width - margins*2) / cellWidth) + width: displayedItems * cellWidth + model: uiModel.targetList; + delegate: RPane { + color: Qt.lighter(Material.background, 1.6) + bgOpacity: 0.3 + radius: 8 + width: 242 + height: 149 + Material.elevation: 4 + + Label { + anchors.top: parent.top + anchors.left: parent.left + text: modelData.name + font.bold: true + font.pixelSize: 16 + } + + Button { + text: qsTr("Edit") + anchors.right: parent.right + anchors.bottom: parent.bottom + onClicked: editClicked(index, modelData) + } + + } +} \ No newline at end of file diff --git a/GlosSIConfig/qml/ShortcutProps.qml b/GlosSIConfig/qml/ShortcutProps.qml new file mode 100644 index 0000000..acdbd10 --- /dev/null +++ b/GlosSIConfig/qml/ShortcutProps.qml @@ -0,0 +1,280 @@ +/* +Copyright 2021 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 +import QtQuick.Dialogs 6.2 + + +Item { + id: propsContent + anchors.fill: parent + + signal cancel() + signal done(var shortcut) + + property var shortcutInfo: ({ + version: 1, + name: null, + launch: false, + launchPath: null, + launchAppArgs: null, + closeOnExit: true, + hideDevices: true, + windowMode: false, + maxFps: null, + scale: null + }) + + function resetInfo() { + shortcutInfo = ({ + version: 1, + name: null, + launch: false, + launchPath: null, + launchAppArgs: null, + closeOnExit: true, + hideDevices: true, + windowMode: false, + maxFps: null, + scale: null + }) + } + + onShortcutInfoChanged: function() { + nameInput.text = shortcutInfo.name || "" + launchApp.checked = shortcutInfo.launch || false + pathInput.text = shortcutInfo.launchPath || "" + argsInput.text = shortcutInfo.launchAppArgs || "" + closeOnExit.checked = shortcutInfo.closeOnExit || false + hideDevices.checked = shortcutInfo.hideDevices || false + windowMode.checked = shortcutInfo.windowMode || false + } + + + Column { + anchors.margins: 64 + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + spacing: 4 + Item { + id: namewrapper + width: parent.width / 3 + height: 64 + Label { + anchors.left: parent.left + anchors.leftMargin: 4 + id: nameLabel + font.bold: true + text: qsTr("Name") + } + FluentTextInput { + width: parent.width + anchors.top: nameLabel.bottom + anchors.topMargin: 4 + id: nameInput + placeholderText: qsTr("...") + text: shortcutInfo.name + onTextChanged: shortcutInfo.name = text + } + } + Item { + width: 1 + height: 28 + } + Row { + spacing: 32 + width: parent.width + height: closeOnExitCol.height + CheckBox { + id: launchApp + text: qsTr("Launch app") + checked: shortcutInfo.launch + onCheckedChanged: shortcutInfo.launch = checked + } + Column { + id: closeOnExitCol + spacing: 2 + CheckBox { + id: closeOnExit + text: qsTr("Close when launched app quits") + checked: shortcutInfo.closeOnExit + onCheckedChanged: shortcutInfo.closeOnExit = checked + } + Label { + text: qsTr("Recommended to disable for launcher-games") + wrapMode: Text.WordWrap + width: parent.width + } + } + } + RowLayout { + id: launchlayout + spacing: 4 + width: parent.width + Item { + Layout.preferredWidth: parent.width / 2 + Layout.fillWidth: true + height: 64 + Label { + anchors.left: parent.left + anchors.leftMargin: 4 + id: pathLabel + font.bold: true + text: qsTr("Path") + } + FluentTextInput { + width: parent.width + anchors.top: pathLabel.bottom + anchors.topMargin: 4 + id: pathInput + placeholderText: qsTr("...") + enabled: launchApp.checked + text: shortcutInfo.launchPath || "" + onTextChanged: shortcutInfo.launchPath = text + } + } + Button { + Layout.preferredWidth: 64 + Layout.alignment: Qt.AlignBottom + text: qsTr("...") + onClicked: fileDialog.open(); + } + Button { + Layout.preferredWidth: 64 + Layout.alignment: Qt.AlignBottom + text: qsTr("UWP") + visible: uiModel.isWindows + } + Item { + height: 1 + Layout.preferredWidth: 12 + } + Item { + Layout.preferredWidth: parent.width / 2.5 + height: 64 + Label { + anchors.left: parent.left + anchors.leftMargin: 4 + id: argslabel + font.bold: true + text: qsTr("Launch Arguments") + } + FluentTextInput { + width: parent.width + anchors.top: argslabel.bottom + anchors.topMargin: 4 + id: argsInput + enabled: launchApp.checked + text: shortcutInfo.launchAppArgs + onTextChanged: shortcutInfo.launchAppArgs = text + } + } + } + Item { + width: 1 + height: 28 + } + Row { + spacing: 64 + width: parent.width + Column { + spacing: 2 + width: parent.width/2 - 64 + CheckBox { + id: hideDevices + text: qsTr("Hide (Real) Controllers") + checked: shortcutInfo.hideDevices + onCheckedChanged: shortcutInfo.hideDevices = checked + } + Label { + text: qsTr("Hides real game controllers from the system\nThis may prevent doubled inputs") + wrapMode: Text.WordWrap + width: parent.width + } + Label { + text: qsTr("You can change this setting and which devices are hidden in the GlosSI overlay") + wrapMode: Text.WordWrap + width: parent.width + } + } + Column { + spacing: 2 + width: parent.width/2 - 64 + CheckBox { + id: windowMode + text: qsTr("Steam/GlosSI overlay as separate window") + checked: shortcutInfo.windowMode + onCheckedChanged: shortcutInfo.windowMode = checked + } + Label { + text: qsTr("Doesn't show overlay on top, but as separate window") + wrapMode: Text.WordWrap + width: parent.width + } + Label { + text: qsTr("Use if blackscreen-issues are encountered.") + wrapMode: Text.WordWrap + width: parent.width + } + } + } + } + + Row { + spacing: 8 + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.margins: 32 + Button { + text: qsTr("Cancel") + onClicked: function() { + cancel() + } + } + Button { + text: qsTr("Done") + highlighted: true + onClicked: function() { + done(shortcutInfo) + } + } + } + + FileDialog { + id: fileDialog + title: qsTr("Please choose a Program to Launch") + nameFilters: uiModel.isWindows ? ["Executable files (*.exe *.bat *.ps1)"] : [] + onAccepted: { + if (fileDialog.selectedFile != null) { + pathInput.text = fileDialog.selectedFile.toString().replace("file:///", "") + if (nameInput.text == "") { + nameInput.text = pathInput.text.replace(/.*(\\|\/)/,"").replace(/\.[0-z]*$/, "") + } + launchApp.checked = true + } + } + onRejected: { + + } + } + + // UWPSelectDialog {} + +} diff --git a/GlosSIConfig/qml/WinEventFilter.h b/GlosSIConfig/qml/WinEventFilter.h index b8a8fff..d5ddf44 100644 --- a/GlosSIConfig/qml/WinEventFilter.h +++ b/GlosSIConfig/qml/WinEventFilter.h @@ -1,3 +1,18 @@ +/* +Copyright 2021 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. +*/ #pragma once #include #include @@ -21,6 +36,7 @@ public: if (QString(eventType) == "windows_generic_MSG") { auto msg = static_cast(message)->message; auto lParam = static_cast(message)->lParam; + auto hwnd = static_cast(message)->hwnd; if (msg == WM_NCCALCSIZE) { auto sz = reinterpret_cast(lParam); diff --git a/GlosSIConfig/qml/main.qml b/GlosSIConfig/qml/main.qml index 6ffe626..bf4611a 100644 --- a/GlosSIConfig/qml/main.qml +++ b/GlosSIConfig/qml/main.qml @@ -16,13 +16,12 @@ limitations under the License. import QtQuick 6.2 import QtQuick.Layouts 6.2 import QtQuick.Controls.Material 6.2 -import QtQuick.Dialogs Window { id: window visible: true - width: 1280 - height: 719 + width: 1049 + height: 700 Material.theme: Material.Dark Material.accent: Material.color(Material.Blue, Material.Shade900) @@ -30,7 +29,7 @@ Window { title: qsTr("GlosSI - Config") - color: uiModel.hasAcrlyicEffect ? "transparent" : colorAlpha(Material.background, 0.9) + color: uiModel.hasAcrlyicEffect ? colorAlpha(Qt.darker(Material.background, 2), 0.7) : colorAlpha(Qt.darker(Material.background, 1.5), 0.98) function toggleMaximized() { if (window.visibility === Window.Maximized || window.visibility === Window.FullScreen) { @@ -104,92 +103,127 @@ Window { } Item { + id: windowContent anchors.left: parent.left anchors.right: parent.right anchors.top: titleBar.bottom anchors.bottom: parent.bottom + clip: true + + property int editedIndex: -1 + + Item { + id: homeContent + anchors.fill: parent + opacity: 1 + visible: opacity === 0 ? false : true + Behavior on opacity { + NumberAnimation { + duration: 300 + easing.type: opacity === 0 ? Easing.OutQuad : Easing.InOutQuad + } + } + Label { + anchors.centerIn: parent + text: qsTr("No shortcuts yet.\nClick \"+\" to get started") + font.bold: true + font.pixelSize: 24 + horizontalAlignment: Text.AlignHCenter + visible: shortcutgrid.model.length == 0 + } - RPane { - id: existingTargetsPane - anchors.left: parent.left - width:window.width / 3.301 + 16 - Component.onCompleted: console.log(width) - anchors.top: parent.top - anchors.bottom: parent.bottom - Material.elevation: 6 - anchors.leftMargin: -16 - radius: 16 - color: Qt.lighter(Material.background, 1.6) - bgOpacity: 0.3 - - Item { + ShortcutCards { + id: shortcutgrid anchors.top: parent.top anchors.bottom: parent.bottom - anchors.left: parent.left + anchors.horizontalCenter: parent.horizontalCenter + anchors.topMargin: margins + visible: model.length > 0 + margins: 16 + model: uiModel.targetList + onEditClicked: function(index, shortcutInfo){ + shortcutProps.opacity = 1; + homeContent.opacity = 0; + console.log(index) + Object.keys(shortcutInfo).forEach((key) => console.log(key, shortcutInfo[key])) + props.shortcutInfo = shortcutInfo + windowContent.editedIndex = index; + } + } + RoundButton { + id: addBtn anchors.right: parent.right - anchors.leftMargin: 16 - clip: true - ListView { - anchors.fill: parent - spacing: 0 - model: uiModel.getTargetList(); - delegate: Item { - width: parent.width - height: lbl.height + lbl.anchors.topMargin + lbl.anchors.bottomMargin - // TODO: Left size App icon - Label { - id: lbl - anchors.left: parent.left - anchors.right: parent.right - anchors.rightMargin: 48 - anchors.topMargin: 8 - anchors.bottomMargin: 8 - anchors.leftMargin: 4 - anchors.verticalCenter: parent.verticalCenter - text: modelData - font.pixelSize: 16 - } - // TODO: Right side icon if in steam - Rectangle { - width: parent.width - height: 1 - anchors.bottom: parent.bottom - color: Qt.rgba(1,1,1,0.3) - } - } + anchors.bottom: parent.bottom + anchors.margins: 24 + 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 } + highlighted: true + onClicked: selectTypeDialog.open() } } - RoundButton { - id: addBtn - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: 24 - 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 + Item { + id: shortcutProps + height: parent.height + width: parent.width + opacity: 0 + property real animMarg: opacity == 0 ? parent.height : 0 + y: animMarg + visible: opacity === 0 ? false : true + Behavior on opacity { + ParallelAnimation { + NumberAnimation { + duration: 300 + property: "opacity" + easing.type: opacity === 0 ? Easing.OutQuad : Easing.InOutQuad + } + PropertyAnimation { + duration: 300 + target: shortcutProps + property: "animMarg"; + from: shortcutProps.animMarg + to: shortcutProps.animMarg > 0 ? 0 : shortcutProps.parent.height; + easing.type: opacity === 0 ? Easing.OutQuad : Easing.InOutQuad + } + } + } + ShortcutProps { + id: props + anchors.fill: parent + onCancel: function() { + shortcutProps.opacity = 0; + homeContent.opacity = 1; + } + onDone: function(shortcut) { + shortcutProps.opacity = 0; + homeContent.opacity = 1; + if (windowContent.editedIndex < 0) { + uiModel.addTarget(shortcut) + } else { + uiModel.updateTarget(windowContent.editedIndex, shortcut) + } + } } - highlighted: true - onClicked: fileDialog.open(); } - FileDialog { - id: fileDialog - title: qsTr("Please choose a Program to Launch") - nameFilters: uiModel.isWindows ? ["Executable files (*.exe *.bat *.ps1)"] : [] - onAccepted: { - console.log("You chose: " + fileDialog.selectedFile) - } - onRejected: { - console.log("Canceled") + AddSelectTypeDialog { + id: selectTypeDialog + visible: false + onConfirmed: function(param) { + shortcutProps.opacity = 1; + homeContent.opacity = 0; + // TODO Which dialog + props.resetInfo() + windowContent.editedIndex = -1 } } diff --git a/GlosSITarget/Resource.rc b/GlosSITarget/Resource.rc index cb1054d..be1fe8d 100644 --- a/GlosSITarget/Resource.rc +++ b/GlosSITarget/Resource.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,0,0,104000800535 - PRODUCTVERSION 0,0,0,104000800535 + FILEVERSION 0,0,0,0190104 + PRODUCTVERSION 0,0,0,0190104 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "Peter Repukat - FlatspotSoftware" VALUE "FileDescription", "GlosSI - SteamTarget" - VALUE "FileVersion", "0.0.0.1-4-gd80a535" + VALUE "FileVersion", "0.0.0.c19b1e4" VALUE "InternalName", "GlosSITarget" VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware" VALUE "OriginalFilename", "GlosSITarget.exe" VALUE "ProductName", "GlosSI" - VALUE "ProductVersion", "0.0.0.1-4-gd80a535" + VALUE "ProductVersion", "0.0.0.c19b1e4" END END BLOCK "VarFileInfo" @@ -171,6 +171,10 @@ END + + + +