From 77c56f9945ba1f279f48020a157cb0e10a1cf69d Mon Sep 17 00:00:00 2001 From: tux Date: Fri, 4 Sep 2026 01:36:50 +0530 Subject: [PATCH] feat(bar): add network widget and service --- assets/icons/network.svg | 1 + config/BarLayout.qml | 2 +- modules/bar/NetworkWidget.qml | 11 +++++ services/Network.qml | 81 +++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 assets/icons/network.svg create mode 100644 modules/bar/NetworkWidget.qml create mode 100644 services/Network.qml diff --git a/assets/icons/network.svg b/assets/icons/network.svg new file mode 100644 index 0000000..76eca52 --- /dev/null +++ b/assets/icons/network.svg @@ -0,0 +1 @@ + diff --git a/config/BarLayout.qml b/config/BarLayout.qml index ff12c9e..0627f42 100644 --- a/config/BarLayout.qml +++ b/config/BarLayout.qml @@ -11,7 +11,7 @@ Singleton { return `${Quickshell.shellPath("modules/bar")}/${name}.qml`; } - property var left: [root.widget("LauncherButton"), root.widget("PowerProfileWidget"), root.widget("GPUWidget"), root.widget("HomeWidget"), root.widget("MusicWidget")] + property var left: [root.widget("LauncherButton"), root.widget("NetworkWidget"), root.widget("PowerProfileWidget"), root.widget("GPUWidget"), root.widget("HomeWidget"), root.widget("MusicWidget")] property var center: [root.widget("CavaVisualizer"), root.widget("Workspaces"), root.widget("CavaVisualizer"),] diff --git a/modules/bar/NetworkWidget.qml b/modules/bar/NetworkWidget.qml new file mode 100644 index 0000000..fa4a49f --- /dev/null +++ b/modules/bar/NetworkWidget.qml @@ -0,0 +1,11 @@ +pragma ComponentBehavior: Bound + +import qs.ui +import qs.services + +BarButton { + hoverHighlight: false + pointerCursor: false + label: Network.statusText + iconSource: Network.icon +} diff --git a/services/Network.qml b/services/Network.qml new file mode 100644 index 0000000..6572631 --- /dev/null +++ b/services/Network.qml @@ -0,0 +1,81 @@ +pragma Singleton + +import QtQuick +import Quickshell +import Quickshell.Networking + +Singleton { + id: root + + readonly property url icon: `${Quickshell.shellPath("assets")}/icons/network.svg` + + property var wifiDevice: { + for (const device of Networking.devices.values) { + if (device.type === DeviceType.Wifi) + return device; + } + return null; + } + + property var wiredDevice: { + for (const device of Networking.devices.values) { + if (device.type === DeviceType.Wired) + return device; + } + return null; + } + + readonly property bool ethernetConnected: !!(root.wiredDevice && root.wiredDevice.connected) + + readonly property bool wifiConnected: !!(root.wifiDevice && root.wifiDevice.connected) + + readonly property bool wifiConnecting: !!(root.wifiDevice && root.wifiDevice.state === ConnectionState.Connecting) + + property var activeNetwork: null + + function refreshActiveNetwork() { + root.activeNetwork = null; + + if (!root.wifiDevice || !root.wifiDevice.networks) + return; + + for (const network of root.wifiDevice.networks.values) { + if (network.connected) { + root.activeNetwork = network; + return; + } + } + } + + readonly property string statusText: { + if (root.ethernetConnected) + return "Wired"; + + if (root.wifiConnecting) + return "Connecting"; + + if (root.wifiConnected && root.activeNetwork) + return root.activeNetwork.name; + + return "NA"; + } + + Connections { + target: root.wifiDevice ? root.wifiDevice.networks : null + + function onValuesChanged() { + root.refreshActiveNetwork(); + } + } + + Timer { + interval: 1000 + running: true + repeat: true + triggeredOnStart: true + + onTriggered: { + root.refreshActiveNetwork(); + } + } +}