pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts import qs.hyprchrome.theme import qs.hyprchrome.widgets.panels import qs.widgets.vitals // Host vitals in the hyprchrome panel chrome, in both of BarPanel's densities. // // Expanded: CPU load and temperature, memory usage, GPU load and temperature, // each as a segmented meter with its readout. // Collapsed: the same five numbers as percentages behind Nerd Font glyphs. // // Both bodies read the same properties below, so the two densities cannot // disagree — they are one set of numbers rendered twice. // // The scrape comes from the shared VitalsData (node_exporter over loopback); // GPU busy is the one reading that scrape does not carry, so it comes off // sysfs through GpuBusy. BarPanel { id: panel panelId: "MON" title: "RESOURCE MONITOR" meta: vitals.failed ? "OFFLINE" : vitals.ready ? "REALTIME" : "PRIMING" // Poll only while the panel exists on screen; both sources idle otherwise. property bool polling: true // Temperatures are metered against a 0–100 °C span so a bar means the same // thing on every row. readonly property real tempCeiling: 100 readonly property real memoryFraction: vitals.memTotal > 0 ? vitals.memUsed / vitals.memTotal : 0 readonly property bool cpuTempReady: isFinite(vitals.cpuTemp) readonly property bool gpuTempReady: isFinite(vitals.gpuTemp) function pct(value, ready) { return ready ? Math.round(Math.max(0, Math.min(1, value)) * 100) + "%" : "--"; } function tempFraction(celsius) { return isFinite(celsius) ? Math.max(0, Math.min(1, celsius / panel.tempCeiling)) : 0; } VitalsData { id: vitals active: panel.polling } GpuBusy { id: gpu active: panel.polling } // Collapsed: glyph + percentage, in the same order as the rows below. // Codepoints are Nerd Fonts v3 — oct-cpu, fa-thermometer-half, // md-memory, md-expansion-card-variant — all present in DepartureMono. summary: RowLayout { spacing: 12 Item { Layout.fillWidth: true } Readout { icon: "CPU:"; value: panel.pct(vitals.cpu, vitals.ratesReady) } Readout { icon: "CPU Temp:"; value: vitals.fmtTemp(vitals.cpuTemp) } Readout { icon: "Mem:"; value: panel.pct(panel.memoryFraction, vitals.ready) } Readout { icon: "GPU:"; value: panel.pct(gpu.value, gpu.ready) } Readout { icon: "GPU Temp:"; value: vitals.fmtTemp(vitals.gpuTemp) } Item { Layout.fillWidth: true } } // Expanded: the same five, metered. Column { width: parent.width spacing: 5 VitalRow { width: parent.width label: "CPU" value: vitals.cpu ready: vitals.ratesReady && !vitals.failed readout: panel.pct(vitals.cpu, vitals.ratesReady) } VitalRow { width: parent.width label: "CPU TMP" value: panel.tempFraction(vitals.cpuTemp) ready: panel.cpuTempReady readout: vitals.fmtTemp(vitals.cpuTemp) warn: 0.85 } VitalRow { width: parent.width label: "MEM" value: panel.memoryFraction ready: vitals.ready && !vitals.failed readout: panel.pct(panel.memoryFraction, vitals.ready) } VitalRow { width: parent.width label: "GPU" value: gpu.value ready: gpu.ready readout: panel.pct(gpu.value, gpu.ready) } VitalRow { width: parent.width label: "GPU TMP" value: panel.tempFraction(vitals.gpuTemp) ready: panel.gpuTempReady readout: vitals.fmtTemp(vitals.gpuTemp) warn: 0.85 } } component Readout: Row { property string icon: "" property string value: "--" spacing: 4 Text { text: parent.icon color: Theme.accent font.family: Theme.displayFont font.pixelSize: 12 } Text { text: parent.value color: Theme.text font.family: Theme.displayFont font.pixelSize: 12 font.bold: true } } }