nova-shell/shell/services/SystemdService.qml

100 lines
3.8 KiB
QML

pragma Singleton
import QtQuick
import Quickshell.Io
import "." as S
import NovaStats as NS
QtObject {
id: root
property string systemState: "unknown"
property string userState: "unknown"
property var systemUnits: []
property var userUnits: []
readonly property int totalFailedCount: systemUnits.length + userUnits.length
signal journalReady(string unitName, bool isUser, string text)
function refresh() {
if (!_pollProc.running)
_pollProc.running = true;
}
// Per-fetch journal state: kept here (not on the Process) so qmllint can see them.
property string _journalUnitName: ""
property bool _journalIsUser: false
function fetchJournal(unitName, isUser) {
_journalProc.command = isUser ? ["journalctl", "--user", "-u", unitName, "-n", "80", "--no-pager", "--output=short-precise"] : ["journalctl", "-u", unitName, "-n", "80", "--no-pager", "--output=short-precise"];
root._journalUnitName = unitName;
root._journalIsUser = isUser;
if (_journalProc.running)
_journalProc.running = false;
_journalProc.running = true;
}
function restartUnit(unitName, isUser) {
_restartProc.command = isUser ? ["systemctl", "--user", "restart", unitName] : ["pkexec", "systemctl", "restart", unitName];
if (_restartProc.running)
_restartProc.running = false;
_restartProc.running = true;
}
function _parseState(json) {
try {
return JSON.parse(json).data || "unknown";
} catch (e) {
return "unknown";
}
}
function _parseUnits(json) {
try {
const parsed = JSON.parse(json);
return (parsed.data?.[0] || []).map(u => ({
name: u[0],
description: u[1],
loadState: u[2],
activeState: u[3],
subState: u[4]
}));
} catch (e) {
return [];
}
}
property Timer _poll: Timer {
interval: NS.ModulesService.systemdInterval ?? 15000
running: NS.ModulesService.systemdEnable
repeat: true
triggeredOnStart: true
onTriggered: if (!root._pollProc.running)
root._pollProc.running = true
}
// 4 lines of output: systemState, systemUnits, userState, userUnits
property Process _pollProc: Process {
command: ["sh", "-c", "busctl get-property --json=short org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager SystemState 2>/dev/null || echo '{}'; " + "busctl call --json=short org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager ListUnitsFiltered as 1 failed 2>/dev/null || echo '{}'; " + "busctl --user get-property --json=short org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager SystemState 2>/dev/null || echo '{}'; " + "busctl --user call --json=short org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager ListUnitsFiltered as 1 failed 2>/dev/null || echo '{}'"]
stdout: StdioCollector {
onStreamFinished: {
const lines = text.trim().split("\n");
root.systemState = root._parseState(lines[0] ?? "");
root.systemUnits = root._parseUnits(lines[1] ?? "");
root.userState = root._parseState(lines[2] ?? "");
root.userUnits = root._parseUnits(lines[3] ?? "");
}
}
}
property Process _journalProc: Process {
stdout: StdioCollector {
onStreamFinished: root.journalReady(root._journalUnitName, root._journalIsUser, text)
}
}
property Process _restartProc: Process {
onRunningChanged: if (!running)
root.refresh()
}
}