refactor(cleanup): begin ui rewrite in qt

This commit is contained in:
PancakeTAS 2025-12-22 20:39:46 +01:00
parent 333ddc9dec
commit 21070f9b86
No known key found for this signature in database
39 changed files with 373 additions and 2592 deletions

View file

@ -4,6 +4,8 @@ project(lsfg-vk LANGUAGES CXX)
# === user facing options
option(LSFGVK_BUILD_VULKAN_LAYER
"Build the Vulkan layer" ON)
option(LSFGVK_BUILD_USER_INTERFACE
"Build the user interface" ON)
option(LSFGVK_BUILD_DEBUG_TOOL
"Build the debug tool for testing and debugging" OFF)
@ -47,6 +49,9 @@ add_subdirectory(lsfg-vk-backend)
if(LSFGVK_BUILD_VULKAN_LAYER)
add_subdirectory(lsfg-vk-layer)
endif()
if(LSFGVK_BUILD_USER_INTERFACE)
add_subdirectory(lsfg-vk-ui)
endif()
if(LSFGVK_BUILD_DEBUG_TOOL)
add_subdirectory(lsfg-vk-debug)
endif()

38
lsfg-vk-ui/.clang-tidy Normal file
View file

@ -0,0 +1,38 @@
Checks:
# enable basic checks
- "clang-analyzer-*"
# configure performance checks
- "performance-*"
- "-performance-enum-size"
# configure readability and bugprone checks
- "readability-*"
- "bugprone-*"
- "misc-*"
- "-readability-braces-around-statements"
- "-readability-function-cognitive-complexity"
- "-readability-identifier-length"
- "-readability-implicit-bool-conversion"
- "-readability-magic-numbers"
- "-readability-math-missing-parentheses"
- "-readability-named-parameter"
- "-bugprone-easily-swappable-parameters"
# configure modernization
- "modernize-*"
- "-modernize-use-trailing-return-type"
# configure cppcoreguidelines
- "cppcoreguidelines-*"
- "-cppcoreguidelines-avoid-magic-numbers"
- "-cppcoreguidelines-pro-type-reinterpret-cast"
- "-cppcoreguidelines-macro-usage"
- "-cppcoreguidelines-pro-type-member-init"
- "-cppcoreguidelines-prefer-member-initializer"
# disable slow and pointless checks
- "-modernize-use-std-numbers"
- "-modernize-type-traits"
- "-cppcoreguidelines-owning-memory"
- "-cppcoreguidelines-macro-to-enum"
- "-readability-container-contains"
- "-bugprone-reserved-identifier"
- "-bugprone-stringview-nullptr"
- "-bugprone-standalone-empty"
- "-misc-unused-using-decls"

32
lsfg-vk-ui/CMakeLists.txt Normal file
View file

@ -0,0 +1,32 @@
find_package(Qt6 REQUIRED COMPONENTS Quick)
set(UI_SOURCES
"src/ui.cpp"
"src/main.cpp")
set(UI_RESOURCES
"rsc/panes/Group.qml"
"rsc/panes/GroupEntry.qml"
"rsc/panes/Pane.qml"
"rsc/panes/ProfileList.qml"
"rsc/widgets/FileEdit.qml"
"rsc/widgets/FlowSlider.qml"
"rsc/UI.qml")
qt_add_executable(lsfg-vk-ui ${UI_SOURCES})
qt_add_resources(lsfg-vk-ui RESOURCES
PREFIX "/"
FILES ${UI_RESOURCES})
set_target_properties(lsfg-vk-ui PROPERTIES
AUTOMOC ON
AUTOUIC ON)
add_compile_options(
-Wno-ctad-maybe-unsupported
-Wno-unsafe-buffer-usage-in-libc-call
-Wno-global-constructors)
target_link_libraries(lsfg-vk-ui PRIVATE
Qt6::Quick)

115
lsfg-vk-ui/rsc/UI.qml Normal file
View file

@ -0,0 +1,115 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import "panes"
import "widgets"
ApplicationWindow {
title: "lsfg-vk Configuration Window"
width: 900
height: 475
minimumWidth: 700
minimumHeight: 400
visible: true
SplitView {
anchors.fill: parent
orientation: Qt.Horizontal
Pane {
SplitView.minimumWidth: 200
SplitView.preferredWidth: 250
SplitView.maximumWidth: 300
Label {
text: "Profiles"
Layout.fillWidth: true
font.bold: true
horizontalAlignment: Text.AlignHCenter
}
ProfileList {
}
Button {
text: "Create New Profile"
Layout.fillWidth: true
}
Button {
text: "Rename Profile"
Layout.fillWidth: true
}
Button {
text: "Delete Profile"
Layout.fillWidth: true
}
}
Pane {
SplitView.fillWidth: true
Group {
name: "Global Settings"
GroupEntry {
title: "Browse for Lossless.dll"
description: "Change the location of Lossless.dll"
FileEdit {}
}
GroupEntry {
title: "Allow half-precision"
description: "Allow acceleration through half-precision"
CheckBox {}
}
}
Group {
name: "Profile Settings"
GroupEntry {
title: "Multiplier"
description: "Control the amount of generated frames"
SpinBox { from: 2; to: 100 }
}
GroupEntry {
title: "Flow Scale"
description: "Lower the internal motion estimation resolution"
FlowSlider { from: 0.25; to: 1.00 }
}
GroupEntry {
title: "Performance Mode"
description: "Use a significantly lighter frame generation modeln"
CheckBox {}
}
GroupEntry {
title: "Pacing Mode"
description: "Change how frames are presented to the display"
ComboBox { model: ["None"] }
}
GroupEntry {
title: "GPU"
description: "Select which GPU to use for frame generation"
ComboBox { model: ["Auto"] }
}
}
Item {
Layout.fillHeight: true
}
}
}
}

View file

@ -0,0 +1,32 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
GroupBox {
property string name
default property alias content: inner.children
Layout.fillWidth: true
id: root
topPadding: label.implicitHeight + 8
label: Label {
text: root.name
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 4
padding: 4
}
background: Rectangle {
color: palette.alternateBase
border.color: palette.light
radius: 4
}
ColumnLayout {
id: inner
anchors.fill: parent
spacing: 12
}
}

View file

@ -0,0 +1,34 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
RowLayout {
property string title
property string description
id: root
spacing: 12
ColumnLayout {
spacing: 0
Label {
text: root.title
font.bold: true
}
Label {
text: root.description
color: Qt.rgba(
palette.text.r,
palette.text.g,
palette.text.b,
0.7
)
}
}
Item {
Layout.fillWidth: true
}
}

View file

@ -0,0 +1,16 @@
import QtQuick
import QtQuick.Layouts
Rectangle {
default property alias content: inner.children
id: root
color: "transparent"
ColumnLayout {
id: inner
anchors.fill: parent
anchors.margins: 12
spacing: 4
}
}

View file

@ -0,0 +1,16 @@
import QtQuick
import QtQuick.Layouts
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
id: root
color: palette.dark
border.color: palette.light
border.width: 1
radius: 4
ListView {
anchors.fill: parent
}
}

View file

@ -0,0 +1,17 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
RowLayout {
id: root
spacing: 4
TextField {
Layout.fillWidth: true;
Layout.maximumWidth: 450;
}
Button {
icon.name: "folder-open"
}
}

View file

@ -0,0 +1,21 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
RowLayout {
property real from
property real to
id: root
spacing: 4
Slider {
Layout.fillWidth: true;
Layout.maximumWidth: 450;
}
Label {
Layout.preferredWidth: 40;
text: "0%"
horizontalAlignment: Text.AlignHCenter
}
}

21
lsfg-vk-ui/src/main.cpp Normal file
View file

@ -0,0 +1,21 @@
#include "ui.hpp"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QUrl>
using namespace lsfgvk::ui;
int main(int argc, char* argv[]) {
const QGuiApplication app(argc, argv);
QGuiApplication::setApplicationName("lsfg-vk-ui");
QGuiApplication::setApplicationDisplayName("lsfg-vk-ui");
QQmlApplicationEngine engine;
UI ui;
engine.rootContext()->setContextProperty("ui", &ui);
engine.load("qrc:/rsc/UI.qml");
return QGuiApplication::exec();
}

10
lsfg-vk-ui/src/ui.cpp Normal file
View file

@ -0,0 +1,10 @@
#include "ui.hpp"
#include <QObject>
#include <iostream>
using namespace lsfgvk::ui;
UI::UI(QObject* parent) : QObject(parent) {
std::cerr << "Hello, world!" << '\n';
}

16
lsfg-vk-ui/src/ui.hpp Normal file
View file

@ -0,0 +1,16 @@
#pragma once
#include <QObject>
namespace lsfgvk::ui {
class UI : public QObject {
Q_OBJECT
public:
explicit UI(QObject* parent = nullptr);
private:
};
}

1411
ui/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,15 +0,0 @@
[package]
name = "lsfg-vk-ui"
edition = "2021"
[dependencies]
gtk = { version = "0.10.0", package = "gtk4", features = ["v4_10"] }
adw = { version = "0.8.0", package = "libadwaita", features = ["v1_4"] }
serde = { version = "1.0", features = ["derive"] }
toml = "0.9.2"
anyhow = "1.0"
procfs = "0.17.0"
proc-maps = "0.4.0"
[build-dependencies]
glib-build-tools = "0.21.0"

View file

@ -1,7 +0,0 @@
fn main() {
glib_build_tools::compile_resources(
&["rsc"],
"rsc/lsfg-vk.xml",
"lsfg-vk.gresource",
);
}

View file

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSEntry" parent="GtkListBoxRow">
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<property name="spacing">8</property>
<child>
<object class="GtkLabel">
<property name="halign">start</property>
<property name="hexpand">true</property>
<property name="label"
bind-source="LSEntry" bind-property="exe" bind-flags="sync-create"/>
</object>
</child>
<child>
<object class="GtkButton" id="delete">
<property name="icon-name">user-trash-symbolic</property>
<style>
<class name="flat"/>
<class name="circular"/>
<class name="destructive-action"/>
</style>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/gay/pancake/lsfg-vk/">
<file compressed="true" preprocess="xml-stripblanks">entry/entry.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pane/main.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pane/sidebar.ui</file>
<file compressed="true" preprocess="xml-stripblanks">popup/process.ui</file>
<file compressed="true" preprocess="xml-stripblanks">popup/process_entry.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pref/dropdown.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pref/number.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pref/entry.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pref/slider.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pref/switch.ui</file>
<file compressed="true" preprocess="xml-stripblanks">window.ui</file>
</gresource>
</gresources>

View file

@ -1,126 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSPaneMain" parent="AdwNavigationPage">
<property name="title">lsfg-vk Configuration Menu</property>
<child>
<object class="AdwToolbarView">
<!-- Header -->
<child type="top">
<object class="AdwHeaderBar">
<property name="title-widget">
<object class="AdwWindowTitle">
<property name="title">lsfg-vk Configuration Menu</property>
</object>
</property>
</object>
</child>
<!-- Content -->
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkBox" id="main_box">
<property name="orientation">vertical</property>
<property name="margin-start">48</property>
<property name="margin-end">48</property>
<property name="margin-top">32</property>
<property name="margin-bottom">32</property>
<property name="spacing">32</property>
<!-- General Properties -->
<child>
<object class="AdwPreferencesGroup">
<property name="title">General Properties</property>
<!--General Properties: Path to Lossless.dll -->
<child>
<object class="LSPrefEntry" id="dll">
<property name="opt-name">Path to Lossless.dll</property>
<property name="opt-subtitle">(Global Option) Change the location of Lossless.dll</property>
<property name="tooltip-text">~/.local/share/Steam/steamapps/common/Lossless Scaling/Lossless.dll</property>
<property name="icon-name">folder-symbolic</property>
</object>
</child>
<!--General Properties: FP16 Override -->
<child>
<object class="LSPrefSwitch" id="no_fp16">
<property name="opt-name">Force-disable FP16</property>
<property name="opt-subtitle">(Global Option) Force-disable FP16 acceleration (use on older NVIDIA GPUs)</property>
<property name="default-state">false</property>
</object>
</child>
<!--General Properties: Profile name -->
<child>
<object class="LSPrefEntry" id="profile_name">
<property name="opt-name">Profile name</property>
<property name="opt-subtitle">Command name used for automatically activating in games.</property>
<property name="icon-name">system-search-symbolic</property>
</object>
</child>
</object>
</child>
<!-- Frame Generation -->
<child>
<object class="AdwPreferencesGroup">
<property name="title">Frame Generation</property>
<!-- Frame Generation: Multiplier -->
<child>
<object class="LSPrefNumber" id="multiplier">
<property name="opt-name">Multiplier</property>
<property name="opt-subtitle">Double, triple or quadruple your FPS.</property>
</object>
</child>
<!-- Frame Generation: Flow Scale -->
<child>
<object class="LSPrefSlider" id="flow_scale">
<property name="opt-name">Flow Scale</property>
<property name="opt-subtitle">Lower the internal motion estimation resolution</property>
</object>
</child>
<!-- Frame Generation: Performance Mode -->
<child>
<object class="LSPrefSwitch" id="performance_mode">
<property name="opt-name">Performance Mode</property>
<property name="opt-subtitle">Massively improve performance at the cost of quality.</property>
<property name="default-state">false</property>
</object>
</child>
</object>
</child>
<!-- Misc -->
<child>
<object class="AdwPreferencesGroup">
<property name="title">Misc</property>
<!-- Misc: HDR Mode -->
<child>
<object class="LSPrefSwitch" id="hdr_mode">
<property name="opt-name">HDR Mode</property>
<property name="opt-subtitle">Enable special HDR-only behavior.</property>
<property name="default-state">false</property>
</object>
</child>
<!-- Misc: Experimental Present Mode -->
<child>
<object class="LSPrefDropdown" id="experimental_present_mode">
<property name="opt-name">Present Mode</property>
<property name="opt-subtitle">(Experimental) Override the present mode to immediate or mailbox.</property>
<property name="default-selection">0</property>
<property name="options">
<object class="GtkStringList">
<items>
<item>VSync/FIFO (Default, Recommended)</item>
<item>Mailbox</item>
<item>Immediate</item>
</items>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</child>
</template>
</interface>

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSPaneSidebar" parent="AdwNavigationPage">
<property name="title">Profiles</property>
<child>
<object class="AdwToolbarView">
<!-- Header -->
<child type="top">
<object class="AdwHeaderBar">
<property name="title-widget">
<object class="AdwWindowTitle">
<property name="title">Profiles</property>
</object>
</property>
</object>
</child>
<!-- Content -->
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<child>
<object class="GtkListBox" id="profiles">
<property name="selection-mode">browse</property>
<property name="css-classes">navigation-sidebar</property>
</object>
</child>
</object>
</child>
</object>
</property>
<!-- Footer -->
<child type="bottom">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<child>
<object class="GtkButton" id="create">
<property name="label">Create New Profile</property>
<property name="css-classes">suggested-action</property>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSPrefDropdown" parent="AdwPreferencesRow">
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">16</property>
<property name="valign">center</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<property name="valign">center</property>
<property name="hexpand">true</property>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefDropdown" bind-property="opt-name" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefDropdown" bind-property="opt-subtitle" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
<style>
<class name="dim-label"/>
<class name="caption"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkDropDown" id="dropdown">
<property name="selected"
bind-source="LSPrefDropdown" bind-property="default-selection" bind-flags="sync-create"/>
<property name="model"
bind-source="LSPrefDropdown" bind-property="options" bind-flags="sync-create"/>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSPrefEntry" parent="AdwPreferencesRow">
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">16</property>
<property name="valign">center</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<property name="valign">center</property>
<property name="hexpand">true</property>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefEntry" bind-property="opt-name" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefEntry" bind-property="opt-subtitle" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
<style>
<class name="dim-label"/>
<class name="caption"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkEntry" id="entry">
<property name="text"
bind-source="LSPrefEntry" bind-property="default-text" bind-flags="sync-create"/>
<property name="placeholder-text"
bind-source="LSPrefEntry" bind-property="tooltip-text" bind-flags="sync-create"/>
<property name="css-classes">compact</property>
<property name="width-chars">30</property>
<property name="max-width-chars">60</property>
</object>
</child>
<child>
<object class="GtkButton" id="btn">
<property name="icon-name"
bind-source="LSPrefEntry" bind-property="icon-name" bind-flags="sync-create"/>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSPrefNumber" parent="AdwPreferencesRow">
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">16</property>
<property name="valign">center</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<property name="valign">center</property>
<property name="hexpand">true</property>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefNumber" bind-property="opt-name" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefNumber" bind-property="opt-subtitle" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
<style>
<class name="dim-label"/>
<class name="caption"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSpinButton" id="number">
<property name="digits">0</property>
<property name="climb-rate">1</property>
<property name="numeric">true</property>
<property name="value">2</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="lower">1</property>
<property name="upper">20</property>
<property name="step-increment">1</property>
<property name="page-increment">1</property>
<property name="value">2</property>
</object>
</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSPrefSlider" parent="AdwPreferencesRow">
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">16</property>
<property name="valign">center</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<property name="valign">center</property>
<property name="hexpand">true</property>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefSlider" bind-property="opt-name" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefSlider" bind-property="opt-subtitle" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
<style>
<class name="dim-label"/>
<class name="caption"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScale" id="slider">
<property name="digits">0</property>
<property name="draw-value">true</property>
<property name="value-pos">right</property>
<property name="hexpand">true</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="lower">25</property>
<property name="upper">100</property>
<property name="step-increment">5</property>
<property name="page-increment">10</property>
<property name="value">100</property>
</object>
</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSPrefSwitch" parent="AdwPreferencesRow">
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">16</property>
<property name="valign">center</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<property name="valign">center</property>
<property name="hexpand">true</property>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefSwitch" bind-property="opt-name" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefSwitch" bind-property="opt-subtitle" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
<style>
<class name="dim-label"/>
<class name="caption"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSwitch" id="switch">
<property name="active"
bind-source="LSPrefSwitch" bind-property="default-state" bind-flags="sync-create"/>
<property name="css-classes">compact</property>
<property name="width-request">70</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSApplicationWindow" parent="AdwApplicationWindow">
<property name="title">lsfg-vk Configuration Window</property>
<property name="default-width">1300</property>
<property name="default-height">750</property>
<property name="content">
<!-- Split View -->
<object class="AdwNavigationSplitView">
<property name="min-sidebar-width">200</property>
<property name="max-sidebar-width">300</property>
<!-- Split View: Left Sidebar -->
<property name="sidebar">
<object class="LSPaneSidebar" id="sidebar"/>
</property>
<!-- Split View: Main Content -->
<property name="content">
<object class="LSPaneMain" id="main"/>
</property>
</object>
</property>
</template>
</interface>

View file

@ -1,37 +0,0 @@
use std::sync::{Arc, OnceLock, RwLock};
use gtk::{gio, prelude::*};
use adw;
mod ui;
mod wrapper;
mod config;
mod utils;
const APP_ID: &str = "gay.pancake.lsfg-vk-ui";
#[derive(Debug)]
struct State {
selected_game: Option<usize>
}
static STATE: OnceLock<Arc<RwLock<State>>> = OnceLock::new();
fn main() {
gio::resources_register_include!("lsfg-vk.gresource")
.expect("Failed to register resources");
config::load_config()
.expect("Failed to load configuration");
// prepare the application state
STATE.set(Arc::new(RwLock::new(State {
selected_game: None
}))).expect("Failed to set application state");
// start the application
let app = adw::Application::builder()
.application_id(APP_ID)
.build();
app.connect_activate(ui::build);
app.run();
}

View file

@ -1,79 +0,0 @@
use gtk::glib;
use gtk;
use adw;
use gtk::glib::types::StaticTypeExt;
pub mod entry;
pub mod pane;
pub mod pref;
pub mod popup;
pub mod imp {
use gtk::subclass::prelude::*;
use adw::subclass::prelude::*;
use crate::wrapper::pane::*;
use gtk::{glib, CompositeTemplate};
#[derive(CompositeTemplate, Default)]
#[template(resource = "/gay/pancake/lsfg-vk/window.ui")]
pub struct Window {
#[template_child]
pub main: TemplateChild<PaneMain>,
#[template_child]
pub sidebar: TemplateChild<PaneSidebar>,
}
#[glib::object_subclass]
impl ObjectSubclass for Window {
const NAME: &'static str = "LSApplicationWindow";
type Type = super::Window;
type ParentType = adw::ApplicationWindow;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
impl ObjectImpl for Window {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for Window {}
impl WindowImpl for Window {}
impl ApplicationWindowImpl for Window {}
impl AdwWindowImpl for Window {}
impl AdwApplicationWindowImpl for Window {}
}
glib::wrapper! {
pub struct Window(ObjectSubclass<imp::Window>)
@extends
adw::ApplicationWindow, adw::Window,
gtk::ApplicationWindow, gtk::Window, gtk::Widget,
@implements
gtk::gio::ActionGroup, gtk::gio::ActionMap,
gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget,
gtk::Native, gtk::Root, gtk::ShortcutManager;
}
impl Window {
pub fn new(app: &adw::Application) -> Self {
pref::PrefDropdown::ensure_type();
pref::PrefEntry::ensure_type();
pref::PrefNumber::ensure_type();
pref::PrefSlider::ensure_type();
pref::PrefSwitch::ensure_type();
pane::PaneMain::ensure_type();
pane::PaneSidebar::ensure_type();
glib::Object::builder()
.property("application", app)
.build()
}
}

View file

@ -1,18 +0,0 @@
use gtk::glib;
use gtk;
pub mod entry;
glib::wrapper! {
pub struct Entry(ObjectSubclass<entry::Entry>)
@extends
gtk::ListBoxRow, gtk::Widget,
@implements
gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
impl Entry {
pub fn new() -> Self {
glib::Object::new()
}
}

View file

@ -1,41 +0,0 @@
use std::cell::RefCell;
use gtk::glib;
use gtk::subclass::prelude::*;
use gtk::prelude::*;
#[derive(gtk::CompositeTemplate, glib::Properties, Default)]
#[properties(wrapper_type = super::Entry)]
#[template(resource = "/gay/pancake/lsfg-vk/entry/entry.ui")]
pub struct Entry {
#[property(get, set)]
exe: RefCell<String>,
#[template_child]
pub delete: TemplateChild<gtk::Button>,
}
#[glib::object_subclass]
impl ObjectSubclass for Entry {
const NAME: &'static str = "LSEntry";
type Type = super::Entry;
type ParentType = gtk::ListBoxRow;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for Entry {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for Entry {}
impl ListBoxRowImpl for Entry {}

View file

@ -1,35 +0,0 @@
use gtk::glib;
use gtk;
use adw;
pub mod main;
pub mod sidebar;
glib::wrapper! {
pub struct PaneMain(ObjectSubclass<main::PaneMain>)
@extends
adw::NavigationPage, gtk::Widget,
@implements
gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
glib::wrapper! {
pub struct PaneSidebar(ObjectSubclass<sidebar::PaneSidebar>)
@extends
adw::NavigationPage, gtk::Widget,
@implements
gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
impl PaneMain {
pub fn new() -> Self {
glib::Object::new()
}
}
impl PaneSidebar {
pub fn new() -> Self {
glib::Object::new()
}
}

View file

@ -1,49 +0,0 @@
use gtk::glib;
use gtk::subclass::prelude::*;
use adw::subclass::prelude::*;
use crate::wrapper::pref::*;
#[derive(gtk::CompositeTemplate, Default)]
#[template(resource = "/gay/pancake/lsfg-vk/pane/main.ui")]
pub struct PaneMain {
#[template_child]
pub dll: TemplateChild<PrefEntry>,
#[template_child]
pub no_fp16: TemplateChild<PrefSwitch>,
#[template_child]
pub profile_name: TemplateChild<PrefEntry>,
#[template_child]
pub multiplier: TemplateChild<PrefNumber>,
#[template_child]
pub flow_scale: TemplateChild<PrefSlider>,
#[template_child]
pub performance_mode: TemplateChild<PrefSwitch>,
#[template_child]
pub hdr_mode: TemplateChild<PrefSwitch>,
#[template_child]
pub experimental_present_mode: TemplateChild<PrefDropdown>
}
#[glib::object_subclass]
impl ObjectSubclass for PaneMain {
const NAME: &'static str = "LSPaneMain";
type Type = super::PaneMain;
type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
impl ObjectImpl for PaneMain {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for PaneMain {}
impl NavigationPageImpl for PaneMain {}

View file

@ -1,36 +0,0 @@
use gtk::glib;
use gtk::subclass::prelude::*;
use adw::subclass::prelude::*;
#[derive(gtk::CompositeTemplate, Default)]
#[template(resource = "/gay/pancake/lsfg-vk/pane/sidebar.ui")]
pub struct PaneSidebar {
#[template_child]
pub profiles: TemplateChild<gtk::ListBox>,
#[template_child]
pub create: TemplateChild<gtk::Button>
}
#[glib::object_subclass]
impl ObjectSubclass for PaneSidebar {
const NAME: &'static str = "LSPaneSidebar";
type Type = super::PaneSidebar;
type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
impl ObjectImpl for PaneSidebar {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for PaneSidebar {}
impl NavigationPageImpl for PaneSidebar {}

View file

@ -1,79 +0,0 @@
use gtk::glib;
use gtk;
use adw;
pub mod dropdown;
pub mod entry;
pub mod number;
pub mod slider;
pub mod switch;
glib::wrapper! {
pub struct PrefDropdown(ObjectSubclass<dropdown::PrefDropdown>)
@extends
adw::PreferencesRow, gtk::ListBoxRow, gtk::Widget,
@implements
gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
glib::wrapper! {
pub struct PrefSwitch(ObjectSubclass<switch::PrefSwitch>)
@extends
adw::PreferencesRow, gtk::ListBoxRow, gtk::Widget,
@implements
gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
glib::wrapper! {
pub struct PrefNumber(ObjectSubclass<number::PrefNumber>)
@extends
adw::PreferencesRow, gtk::ListBoxRow, gtk::Widget,
@implements
gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
glib::wrapper! {
pub struct PrefSlider(ObjectSubclass<slider::PrefSlider>)
@extends
adw::PreferencesRow, gtk::ListBoxRow, gtk::Widget,
@implements
gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
glib::wrapper! {
pub struct PrefEntry(ObjectSubclass<entry::PrefEntry>)
@extends
adw::PreferencesRow, gtk::ListBoxRow, gtk::Widget,
@implements
gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
impl PrefDropdown {
pub fn new() -> Self {
glib::Object::new()
}
}
impl PrefSwitch {
pub fn new() -> Self {
glib::Object::new()
}
}
impl PrefNumber {
pub fn new() -> Self {
glib::Object::new()
}
}
impl PrefSlider {
pub fn new() -> Self {
glib::Object::new()
}
}
impl PrefEntry {
pub fn new() -> Self {
glib::Object::new()
}
}

View file

@ -1,49 +0,0 @@
use std::cell::RefCell;
use gtk::glib;
use gtk::subclass::prelude::*;
use adw::subclass::prelude::*;
use adw::prelude::*;
#[derive(gtk::CompositeTemplate, glib::Properties, Default)]
#[properties(wrapper_type = super::PrefDropdown)]
#[template(resource = "/gay/pancake/lsfg-vk/pref/dropdown.ui")]
pub struct PrefDropdown {
#[property(get, set)]
opt_name: RefCell<String>,
#[property(get, set)]
opt_subtitle: RefCell<String>,
#[property(get, set)]
default_selection: RefCell<u32>,
#[property(get, set)]
options: RefCell<gtk::StringList>,
#[template_child]
pub dropdown: TemplateChild<gtk::DropDown>,
}
#[glib::object_subclass]
impl ObjectSubclass for PrefDropdown {
const NAME: &'static str = "LSPrefDropdown";
type Type = super::PrefDropdown;
type ParentType = adw::PreferencesRow;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for PrefDropdown {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for PrefDropdown {}
impl ListBoxRowImpl for PrefDropdown {}
impl PreferencesRowImpl for PrefDropdown {}

View file

@ -1,53 +0,0 @@
use std::cell::RefCell;
use gtk::glib;
use gtk::subclass::prelude::*;
use adw::subclass::prelude::*;
use adw::prelude::*;
#[derive(gtk::CompositeTemplate, glib::Properties, Default)]
#[properties(wrapper_type = super::PrefEntry)]
#[template(resource = "/gay/pancake/lsfg-vk/pref/entry.ui")]
pub struct PrefEntry {
#[property(get, set)]
opt_name: RefCell<String>,
#[property(get, set)]
opt_subtitle: RefCell<String>,
#[property(get, set)]
default_text: RefCell<String>,
#[property(get, set)]
tooltip_text: RefCell<String>,
#[property(get, set)]
icon_name: RefCell<String>,
#[template_child]
pub entry: TemplateChild<gtk::Entry>,
#[template_child]
pub btn: TemplateChild<gtk::Button>,
}
#[glib::object_subclass]
impl ObjectSubclass for PrefEntry {
const NAME: &'static str = "LSPrefEntry";
type Type = super::PrefEntry;
type ParentType = adw::PreferencesRow;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for PrefEntry {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for PrefEntry {}
impl ListBoxRowImpl for PrefEntry {}
impl PreferencesRowImpl for PrefEntry {}

View file

@ -1,45 +0,0 @@
use std::cell::RefCell;
use gtk::glib;
use gtk::subclass::prelude::*;
use adw::subclass::prelude::*;
use adw::prelude::*;
#[derive(gtk::CompositeTemplate, glib::Properties, Default)]
#[properties(wrapper_type = super::PrefNumber)]
#[template(resource = "/gay/pancake/lsfg-vk/pref/number.ui")]
pub struct PrefNumber {
#[property(get, set)]
opt_name: RefCell<String>,
#[property(get, set)]
opt_subtitle: RefCell<String>,
#[template_child]
pub number: TemplateChild<gtk::SpinButton>,
}
#[glib::object_subclass]
impl ObjectSubclass for PrefNumber {
const NAME: &'static str = "LSPrefNumber";
type Type = super::PrefNumber;
type ParentType = adw::PreferencesRow;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for PrefNumber {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for PrefNumber {}
impl ListBoxRowImpl for PrefNumber {}
impl PreferencesRowImpl for PrefNumber {}

View file

@ -1,45 +0,0 @@
use std::cell::RefCell;
use gtk::glib;
use gtk::subclass::prelude::*;
use adw::subclass::prelude::*;
use adw::prelude::*;
#[derive(gtk::CompositeTemplate, glib::Properties, Default)]
#[properties(wrapper_type = super::PrefSlider)]
#[template(resource = "/gay/pancake/lsfg-vk/pref/slider.ui")]
pub struct PrefSlider {
#[property(get, set)]
opt_name: RefCell<String>,
#[property(get, set)]
opt_subtitle: RefCell<String>,
#[template_child]
pub slider: TemplateChild<gtk::Scale>,
}
#[glib::object_subclass]
impl ObjectSubclass for PrefSlider {
const NAME: &'static str = "LSPrefSlider";
type Type = super::PrefSlider;
type ParentType = adw::PreferencesRow;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for PrefSlider {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for PrefSlider {}
impl ListBoxRowImpl for PrefSlider {}
impl PreferencesRowImpl for PrefSlider {}

View file

@ -1,47 +0,0 @@
use std::cell::RefCell;
use gtk::glib;
use gtk::subclass::prelude::*;
use adw::subclass::prelude::*;
use adw::prelude::*;
#[derive(gtk::CompositeTemplate, glib::Properties, Default)]
#[properties(wrapper_type = super::PrefSwitch)]
#[template(resource = "/gay/pancake/lsfg-vk/pref/switch.ui")]
pub struct PrefSwitch {
#[property(get, set)]
opt_name: RefCell<String>,
#[property(get, set)]
opt_subtitle: RefCell<String>,
#[property(get, set)]
default_state: RefCell<bool>,
#[template_child]
pub switch: TemplateChild<gtk::Switch>,
}
#[glib::object_subclass]
impl ObjectSubclass for PrefSwitch {
const NAME: &'static str = "LSPrefSwitch";
type Type = super::PrefSwitch;
type ParentType = adw::PreferencesRow;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for PrefSwitch {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for PrefSwitch {}
impl ListBoxRowImpl for PrefSwitch {}
impl PreferencesRowImpl for PrefSwitch {}