refactor(cleanup): add active_in dialog

This commit is contained in:
PancakeTAS 2025-12-23 21:13:40 +01:00
parent 9fa79b7b94
commit 98c1e8587d
7 changed files with 161 additions and 15 deletions

View file

@ -6,13 +6,14 @@ set(UI_SOURCES
"src/utils.cpp")
set(UI_RESOURCES
"rsc/panes/CenteredDialog.qml"
"rsc/dialogs/CenteredDialog.qml"
"rsc/dialogs/LargeDialog.qml"
"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/widgets/List.qml"
"rsc/UI.qml")
qt_add_executable(lsfg-vk-ui ${UI_SOURCES})

View file

@ -2,6 +2,7 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import "dialogs"
import "panes"
import "widgets"
@ -51,6 +52,49 @@ ApplicationWindow {
}
}
LargeDialog {
id: active_in_dialog
onConfirm: backend.createProfile(create_name.text)
List {
Layout.fillWidth: true
Layout.fillHeight: true
model: backend.active_in
selected: backend.active_in_index
onSelect: (index) => {
backend.active_in_index = index
var idx = backend.active_in.index(index, 0);
active_in_name.text = backend.active_in.data(idx);
}
}
RowLayout {
spacing: 8
TextField {
Layout.fillWidth: true
id: active_in_name
placeholderText: "Specify linux binary / exe file / process name"
focus: true
}
Button {
icon.name: "find-location"
onClicked: {
// TODO :3
}
}
Button {
icon.name: "list-add"
onClicked: backend.addActiveIn(active_in_name.text)
}
Button {
icon.name: "list-remove"
onClicked: backend.removeActiveIn()
}
}
}
SplitView {
anchors.fill: parent
orientation: Qt.Horizontal
@ -67,7 +111,7 @@ ApplicationWindow {
horizontalAlignment: Text.AlignHCenter
}
ProfileList {
List {
model: backend.profiles
selected: backend.profile_index
onSelect: (index) => backend.profile_index = index
@ -137,6 +181,18 @@ ApplicationWindow {
name: "Profile Settings"
enabled: backend.available
GroupEntry {
title: "Active In"
description: "Specify which applications this profile is active in"
Button {
Layout.alignment: Qt.AlignRight
text: "Edit..."
onClicked: active_in_dialog.open()
}
}
GroupEntry {
title: "Multiplier"
description: "Control the amount of generated frames"
@ -169,7 +225,7 @@ ApplicationWindow {
GroupEntry {
title: "Performance Mode"
description: "Use a significantly lighter frame generation modeln"
description: "Use a significantly lighter frame generation model"
CheckBox {
Layout.alignment: Qt.AlignRight

View file

@ -9,7 +9,7 @@ Dialog {
id: root
title: name
standardButtons: Dialog.Ok | Dialog.Cancel
standardButtons: Dialog.Ok
onAccepted: root.confirm()
modal: true

View file

@ -0,0 +1,28 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Dialog {
property string name
default property alias content: inner.children
signal confirm()
id: root
title: name
onAccepted: root.confirm()
modal: true
dim: true
x: (parent.width - width) / 2
y: (parent.height - height) / 2
width: parent.width * 0.75
height: parent.height * 0.75
contentItem: ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
id: inner
spacing: 8
}
}

View file

@ -13,6 +13,7 @@ Rectangle {
border.color: palette.light
border.width: 1
radius: 4
clip: true
ListView {
anchors.fill: parent
@ -24,6 +25,7 @@ Rectangle {
delegate: Rectangle {
width: view.width
height: 32
radius: 4
color: ListView.isCurrentItem ? palette.highlight : "transparent"
Text {

View file

@ -41,6 +41,16 @@ Backend::Backend() {
this->m_profile_list_model = new QStringListModel(profiles, this);
// create active_in list models
this->m_active_in_list_models.reserve(this->m_profiles.size());
for (const auto& profile : this->m_profiles) {
QStringList active_in; // NOLINT (IWYU)
for (const auto& path : profile.active_in)
active_in.append(QString::fromStdString(path));
this->m_active_in_list_models.push_back(new QStringListModel(active_in, this));
}
// try to select first profile
if (!this->m_profiles.empty())
this->m_profile_index = 0;

View file

@ -7,6 +7,7 @@
#include <QString>
#include <atomic>
#include <qstringlistmodel.h>
#include <qtmetamacros.h>
#include <utility>
#define getters public
@ -18,34 +19,30 @@ namespace lsfgvk::ui {
class Backend : public QObject {
Q_OBJECT
Q_PROPERTY(QStringList gpus READ calculateGPUList NOTIFY refreshUI)
Q_PROPERTY(QStringListModel* profiles READ calculateProfileListModel NOTIFY refreshUI)
Q_PROPERTY(int profile_index READ getProfileIndex WRITE profileSelected NOTIFY refreshUI)
Q_PROPERTY(bool available READ isValidProfileIndex NOTIFY refreshUI)
Q_PROPERTY(QString dll READ getDll WRITE dllUpdated NOTIFY refreshUI)
Q_PROPERTY(bool allow_fp16 READ getAllowFP16 WRITE allowFP16Updated NOTIFY refreshUI)
Q_PROPERTY(bool available READ isValidProfileIndex NOTIFY refreshUI)
Q_PROPERTY(QStringListModel* active_in READ calculateActiveInModel NOTIFY refreshUI)
Q_PROPERTY(int active_in_index READ getActiveInIndex WRITE activeInSelected NOTIFY refreshUI)
Q_PROPERTY(size_t multiplier READ getMultiplier WRITE multiplierUpdated NOTIFY refreshUI)
Q_PROPERTY(float flow_scale READ getFlowScale WRITE flowScaleUpdated NOTIFY refreshUI)
Q_PROPERTY(bool performance_mode READ getPerformanceMode WRITE performanceModeUpdated NOTIFY refreshUI)
Q_PROPERTY(QString pacing_mode READ getPacingMode WRITE pacingModeUpdated NOTIFY refreshUI)
Q_PROPERTY(QStringList gpus READ calculateGPUList NOTIFY refreshUI)
Q_PROPERTY(QString gpu READ getGPU WRITE gpuUpdated NOTIFY refreshUI)
public:
explicit Backend();
getters:
[[nodiscard]] QStringList calculateGPUList() const {
return this->m_gpu_list;
}
[[nodiscard]] QStringListModel* calculateProfileListModel() const {
return this->m_profile_list_model;
}
[[nodiscard]] bool isValidProfileIndex() const {
return this->m_profile_index >= 0 && std::cmp_less(this->m_profile_index, this->m_profiles.size());
}
[[nodiscard]] int getProfileIndex() const {
return this->m_profile_index;
}
@ -61,6 +58,18 @@ namespace lsfgvk::ui {
if (!isValidProfileIndex()) return default; \
auto& conf = this->m_profiles[static_cast<size_t>(this->m_profile_index)];
[[nodiscard]] bool isValidProfileIndex() const {
return this->m_profile_index >= 0 && std::cmp_less(this->m_profile_index, this->m_profiles.size());
}
[[nodiscard]] QStringListModel* calculateActiveInModel() const {
if (!isValidProfileIndex()) return nullptr;
return this->m_active_in_list_models.at(static_cast<size_t>(this->m_profile_index));
}
[[nodiscard]] int getActiveInIndex() const {
if (!isValidProfileIndex()) return -1;
return static_cast<int>(this->m_active_in_index);
}
[[nodiscard]] size_t getMultiplier() const {
VALIDATE_AND_GET_PROFILE(2)
return conf.multiplier;
@ -80,6 +89,9 @@ namespace lsfgvk::ui {
}
throw std::runtime_error("Unknown pacing type in backend");
}
[[nodiscard]] QStringList calculateGPUList() const {
return this->m_gpu_list;
}
[[nodiscard]] QString getGPU() const {
VALIDATE_AND_GET_PROFILE("Default")
return QString::fromStdString(conf.gpu.value_or("Default"));
@ -93,6 +105,11 @@ namespace lsfgvk::ui {
emit refreshUI();
}
void activeInSelected(int idx) {
this->m_active_in_index = idx;
emit refreshUI();
}
#define MARK_DIRTY() \
this->m_dirty.store(true, std::memory_order_relaxed); \
emit refreshUI();
@ -145,6 +162,34 @@ namespace lsfgvk::ui {
MARK_DIRTY()
}
Q_INVOKABLE void addActiveIn(const QString& name) {
VALIDATE_AND_GET_PROFILE()
auto& active_in = conf.active_in;
active_in.push_back(name.toStdString());
auto& model = this->m_active_in_list_models
.at(static_cast<size_t>(this->m_profile_index));
model->insertRow(model->rowCount());
model->setData(model->index(model->rowCount() - 1), name);
MARK_DIRTY()
}
Q_INVOKABLE void removeActiveIn() {
VALIDATE_AND_GET_PROFILE()
if (this->m_active_in_index < 0 || std::cmp_greater_equal(static_cast<size_t>(this->m_active_in_index), conf.active_in.size()))
return;
auto& active_in = conf.active_in;
active_in.erase(active_in.begin() + this->m_active_in_index);
auto& model = this->m_active_in_list_models
.at(static_cast<size_t>(this->m_profile_index));
model->removeRow(this->m_active_in_index);
if (!active_in.empty())
this->m_active_in_index = 0;
else
this->m_active_in_index = -1;
MARK_DIRTY()
}
Q_INVOKABLE void createProfile(const QString& name) {
ls::GameConf conf;
conf.name = name.toStdString();
@ -189,10 +234,14 @@ namespace lsfgvk::ui {
ls::GlobalConf m_global;
std::vector<ls::GameConf> m_profiles;
QStringList m_gpu_list;
QStringListModel* m_profile_list_model;
int m_profile_index{-1};
std::vector<QStringListModel*> m_active_in_list_models;
int m_active_in_index{-1};
QStringList m_gpu_list;
std::atomic_bool m_dirty{false};
};