merge systemd + machinectl into one module/applet (step 1)
This commit is contained in:
parent
96bfc1fd5a
commit
6fc7e8bc8a
16 changed files with 261 additions and 1029 deletions
|
|
@ -1,100 +1,53 @@
|
|||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import Quickshell.Io
|
||||
import "." as S
|
||||
import NovaStats as NS
|
||||
|
||||
// Thin wrapper around NS.SystemdService: drives the poll Timer and parses the
|
||||
// JSON-encoded list properties into JS arrays for QML consumers. Restart helper
|
||||
// proxies through to the Rust singleton.
|
||||
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
|
||||
readonly property string hostname: NS.SystemdService.hostname
|
||||
readonly property string systemState: NS.SystemdService.systemState
|
||||
readonly property string userState: NS.SystemdService.userState
|
||||
readonly property int failedCount: NS.SystemdService.failedCount
|
||||
|
||||
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) {
|
||||
// Parsed [{ name, description, subState, scope, machine }, ...]
|
||||
readonly property var failedUnits: {
|
||||
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]
|
||||
}));
|
||||
return JSON.parse(NS.SystemdService.failedUnitsJson);
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
property Timer _poll: Timer {
|
||||
interval: NS.ModulesService.systemdInterval ?? 15000
|
||||
// Parsed [{ name, class, service, systemState, failedUnits: [...] }, ...]
|
||||
readonly property var containers: {
|
||||
try {
|
||||
return JSON.parse(NS.SystemdService.containersJson);
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function restartUnit(name, scope, machine) {
|
||||
NS.SystemdService.restartUnit(name, scope ?? "system", machine ?? "");
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
NS.SystemdService.poll();
|
||||
}
|
||||
|
||||
property Timer _pollTimer: Timer {
|
||||
interval: {
|
||||
const ms = NS.ModulesService.systemdInterval;
|
||||
return ms > 0 ? ms : 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()
|
||||
triggeredOnStart: false
|
||||
onTriggered: NS.SystemdService.poll()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue