summaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2025-07-12 18:15:32 +0800
committerlittleblack111 <littleblack11111@gmail.com>2025-07-12 18:15:32 +0800
commit299bf0bae8be6ab505f97d6aba4f82e4e6f96f62 (patch)
treee1a72a68b5c2fae7fab097a80462233878a3231c /services
parentce5f49a9324bceccab821c1d2ebf3f72bdfc09ea (diff)
lot of minor improvement added utils and working networkusage
Diffstat (limited to 'services')
-rw-r--r--services/Mpris.qml (renamed from services/SMpris.qml)2
-rw-r--r--services/Network.qml86
-rw-r--r--services/Resource.qml105
3 files changed, 192 insertions, 1 deletions
diff --git a/services/SMpris.qml b/services/Mpris.qml
index 012a354..9618459 100644
--- a/services/SMpris.qml
+++ b/services/Mpris.qml
@@ -1,5 +1,5 @@
pragma Singleton
-pragma ComponentBehavior: Bound
+// pragma ComponentBehavior: Bound
// From https://git.outfoxxed.me/outfoxxed/nixnew
// It does not have a license, but the author is okay with redistribution.
diff --git a/services/Network.qml b/services/Network.qml
new file mode 100644
index 0000000..52f15fa
--- /dev/null
+++ b/services/Network.qml
@@ -0,0 +1,86 @@
+pragma Singleton
+// pragma ComponentBehavior: Bound
+
+import Quickshell
+import Quickshell.Io
+import QtQuick
+
+import qs.config
+
+Singleton {
+ id: root
+
+ property bool wifi: true
+ property bool ethernet: false
+ property string networkName: ""
+ property int networkStrength
+ // property string materialSymbol: ethernet ? "lan" : (Network.networkName.length > 0 && Network.networkName != "lo") ? (Network.networkStrength > 80 ? "signal_wifi_4_bar" : Network.networkStrength > 60 ? "network_wifi_3_bar" : Network.networkStrength > 40 ? "network_wifi_2_bar" : Network.networkStrength > 20 ? "network_wifi_1_bar" : "signal_wifi_0_bar") : "signal_wifi_off"
+ property string state: ethernet ? Icons.resource.network.wifi : (networkName.length >= 0 && networkName !== "lo") ? (networkStrength >= 90 ? Icons.resource.network.wifi.max : networkStrength >= 80 ? Icons.resource.network.wifi.high : networkStrength >= 60 ? Icons.resource.network.wifi.mid : networkStrength >= 40 ? Icons.resource.network.wifi.low : networkStrength >= 20 ? Icons.resource.network.wifi.min : Icons.resource.network.disconnected) : Icons.resource.network.disconnected
+
+ function update() {
+ updateConnectionType.startCheck();
+ updateNetworkName.running = true;
+ updateNetworkStrength.running = true;
+ }
+
+ Timer {
+ interval: General.resourceUpdateInterval
+ running: true
+ repeat: true
+ onTriggered: {
+ root.update();
+ interval = General.resourceUpdateInterval * 1000;
+ }
+ }
+
+ Process {
+ id: updateConnectionType
+ property string buffer
+ command: ["nmcli", "-t", "-f", "NAME,TYPE,DEVICE", "c", "show", "--active"]
+ running: true
+ function startCheck() {
+ buffer = "";
+ updateConnectionType.running = true;
+ }
+ stdout: SplitParser {
+ onRead: data => {
+ updateConnectionType.buffer += data + "\n";
+ }
+ }
+ onExited: (exitCode, exitStatus) => {
+ const lines = updateConnectionType.buffer.trim().split('\n');
+ let hasEthernet = false;
+ let hasWifi = false;
+ lines.forEach(line => {
+ if (line.includes("ethernet"))
+ hasEthernet = true;
+ else if (line.includes("wireless"))
+ hasWifi = true;
+ });
+ root.ethernet = hasEthernet;
+ root.wifi = hasWifi;
+ }
+ }
+
+ Process {
+ id: updateNetworkName
+ command: ["sh", "-c", "nmcli -t -f NAME c show --active | head -1"]
+ running: true
+ stdout: SplitParser {
+ onRead: data => {
+ root.networkName = data;
+ }
+ }
+ }
+
+ Process {
+ id: updateNetworkStrength
+ running: true
+ command: ["sh", "-c", "nmcli -f IN-USE,SIGNAL,SSID device wifi | awk '/^\*/{if (NR!=1) {print $2}}'"]
+ stdout: SplitParser {
+ onRead: data => {
+ root.networkStrength = parseInt(data);
+ }
+ }
+ }
+}
diff --git a/services/Resource.qml b/services/Resource.qml
new file mode 100644
index 0000000..b45538b
--- /dev/null
+++ b/services/Resource.qml
@@ -0,0 +1,105 @@
+pragma Singleton
+// pragma ComponentBehavior: Bound
+
+import QtQuick
+import Quickshell
+import Quickshell.Io
+import qs.config
+
+Singleton {
+ id: root
+
+ property double memoryTotal: 1
+ property double memoryFree: 1
+ property double memoryUsed: memoryTotal - memoryFree
+ property double memoryUsedPercentage: memoryUsed / memoryTotal
+ property double swapTotal: 1
+ property double swapFree: 1
+ property double swapUsed: swapTotal - swapFree
+ property double swapUsedPercentage: swapTotal > 0 ? (swapUsed / swapTotal) : 0
+
+ property double cpuUsage: 0
+ property double cpuTemp: 0
+ property var previousCpuStats
+
+ property int gpuUsage: 0
+ property int gpuTemp: 0
+
+ Timer {
+ interval: General.resourceUpdateInterval
+ running: true
+ repeat: true
+ onTriggered: {
+ fileMeminfo.reload();
+ fileStat.reload();
+ fileCpuThermal.reload();
+
+ const textMeminfo = fileMeminfo.text();
+ memoryTotal = Number(textMeminfo.match(/MemTotal: *(\d+)/)[1] ?? 1);
+ memoryFree = Number(textMeminfo.match(/MemAvailable: *(\d+)/)[1] ?? 0);
+ memoryUsed = memoryTotal - memoryFree;
+ memoryUsedPercentage = memoryUsed / memoryTotal;
+ swapTotal = Number(textMeminfo.match(/SwapTotal: *(\d+)/)[1] ?? 1);
+ swapFree = Number(textMeminfo.match(/SwapFree: *(\d+)/)[1] ?? 0);
+
+ const textStat = fileStat.text();
+ const cpuLine = textStat.match(/^cpu\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/);
+ if (cpuLine) {
+ const stats = cpuLine.slice(1).map(Number);
+ const total = stats.reduce((a, b) => a + b, 0);
+ const idle = stats[3];
+
+ if (root.previousCpuStats) {
+ const totalDiff = total - root.previousCpuStats.total;
+ const idleDiff = idle - root.previousCpuStats.idle;
+ cpuUsage = totalDiff > 0 ? (1 - idleDiff / totalDiff) : 0;
+ }
+
+ root.previousCpuStats = {
+ total,
+ idle
+ };
+ }
+ const cpuTempText = fileCpuThermal.text();
+ cpuTemp = cpuTempText ? parseInt(cpuTempText.trim()) / 100000 : 0;
+
+ gpuUsageProcess.running = true;
+ gpuTempProcess.running = true;
+ interval = General.resourceUpdateInterval * 1000;
+ }
+ }
+
+ FileView {
+ id: fileMeminfo
+ path: "/proc/meminfo"
+ }
+ FileView {
+ id: fileStat
+ path: "/proc/stat"
+ }
+ FileView {
+ id: fileCpuThermal
+ path: General.cpuThermalPath
+ }
+ // nvidia-smi may be dead if firmware update so ABI break etc.
+ Process {
+ id: gpuUsageProcess
+ running: true
+ command: ["nvidia-smi", "--query-gpu=utilization.gpu", "--format=csv,noheader,nounits"]
+ stdout: StdioCollector {
+ onStreamFinished: {
+ root.gpuUsage = parseInt(this.text.trim());
+ }
+ }
+ }
+ Process {
+ id: gpuTempProcess
+ running: true
+ command: ["nvidia-smi", "--query-gpu=temperature.gpu", "--format=csv,noheader,nounits"]
+ stdout: StdioCollector {
+ onStreamFinished: {
+ root.gpuTemp = parseInt(this.text.trim());
+ }
+ }
+ }
+}