Files
illogical-impulse/dots/.config/quickshell/ii/modules/overlay/fpsLimiter/FpsLimiterContent.qml
T
2025-11-07 16:28:45 +01:00

112 lines
3.5 KiB
QML

import qs.services
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Io
import qs.modules.common
import qs.modules.common.widgets
Rectangle {
id: root
color: Appearance.m3colors.m3surfaceContainer
property real padding: 16
property string iconState: "normal"
implicitWidth: contentColumn.implicitWidth + padding * 2
implicitHeight: contentColumn.implicitHeight + padding * 2
Timer {
id: iconResetTimer
interval: 1000
onTriggered: {
root.iconState = "normal";
}
}
function applyLimit() {
var fpsValue = parseInt(fpsField.text);
if (isNaN(fpsValue) || fpsValue < 0) {
root.iconState = "error";
iconResetTimer.restart();
fpsField.text = "";
return;
}
var cfgPaths = [
"~/.config/MangoHud/MangoHud.conf",
]; // MangoHud config files
var updateCommands = cfgPaths.map(path => {
return "if grep -q '^fps_limit=' " + path + "; " +
"then sed -i 's/^fps_limit=.*/fps_limit=" + fpsValue + "/' " + path + "; " +
"else echo 'fps_limit=" + fpsValue + "' >> " + path + "; fi";
}).join("; ");
var cmd = updateCommands + "; pkill -SIGUSR2 mangohud";
fpsSetter.command = ["bash", "-c", cmd];
fpsSetter.startDetached();
root.iconState = "success";
iconResetTimer.restart();
// Clear the field after applying
fpsField.text = "";
}
ColumnLayout {
id: contentColumn
anchors.centerIn: parent
spacing: 15
RowLayout {
Layout.fillWidth: true
spacing: 10
ToolbarTextField {
id: fpsField
Layout.fillWidth: true
Layout.preferredWidth: 180
placeholderText: root.iconState === "error" ? Translation.tr("Insert a valid number") : Translation.tr("Set FPS limit (e.g. 80)")
inputMethodHints: Qt.ImhDigitsOnly
focus: true
onAccepted: {
root.applyLimit();
event.accepted = true;
}
}
RippleButton {
id: applyButton
implicitWidth: 25
implicitHeight: 25
buttonRadius: Appearance.rounding.full
onClicked: {
root.applyLimit();
}
contentItem: MaterialSymbol {
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
font.pixelSize: Appearance.font.pixelSize.title
text: root.iconState === "error" ? "close" : (root.iconState === "success" ? "check" : "save")
rotation: root.iconState !== "normal" ? 360 : 0
color: root.iconState === "error" ? "#ef5350" : (root.iconState === "success" ? Appearance.m3colors.m3primary : Appearance.m3colors.m3onSurface)
Behavior on rotation {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
}
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
}
}
Process {
id: fpsSetter
}
}
}