import QtQuick import Quickshell import Quickshell.Io import "." as M M.BarSection { id: root spacing: M.Theme.moduleSpacing opacity: M.Modules.bluetooth.enable && root.state !== "unavailable" ? 1 : 0 visible: opacity > 0 tooltip: { if (root.state === "off") return "Bluetooth: off"; if (root.state === "connected") return "Bluetooth: " + root.device + (root.batteryPct >= 0 ? "\nBattery: " + root.batteryPct + "%" : ""); return "Bluetooth: on"; } property string state: "unavailable" property string device: "" property int batteryPct: -1 function _parse(text) { const lines = text.trim().split("\n"); const t = lines[0] || ""; const sep = t.indexOf(":"); root.state = sep === -1 ? t : t.slice(0, sep); root.device = sep === -1 ? "" : t.slice(sep + 1); root.batteryPct = -1; for (let i = 1; i < lines.length; i++) { if (lines[i].startsWith("bat:")) root.batteryPct = parseInt(lines[i].slice(4)) || -1; } } Process { id: proc running: M.Modules.bluetooth.enable command: ["sh", "-c", "s=$(bluetoothctl show 2>/dev/null); " + "[ -z \"$s\" ] && echo unavailable && exit; " + "echo \"$s\" | grep -q 'Powered: yes' || { echo off:; exit; }; " + "info=$(bluetoothctl info 2>/dev/null); " + "d=$(echo \"$info\" | awk -F': ' '/\\tName:/{n=$2}/Connected: yes/{c=1}END{if(c)print n}'); " + "[ -n \"$d\" ] && echo \"connected:$d\" || { echo on:; exit; }; " + "bat=$(echo \"$info\" | awk -F': ' '/Battery Percentage.*\\(/{gsub(/[^0-9]/,\"\",$2);print $2}'); " + "[ -n \"$bat\" ] && echo \"bat:$bat\""] stdout: StdioCollector { onStreamFinished: root._parse(text) } } // Event-driven: watch BlueZ DBus property changes Process { id: btMonitor running: M.Modules.bluetooth.enable command: ["sh", "-c", "dbus-monitor --system \"interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path_namespace='/org/bluez'\" 2>/dev/null"] stdout: SplitParser { splitMarker: "\n" onRead: _debounce.restart() } } Timer { id: _debounce interval: 500 onTriggered: proc.running = true } Timer { interval: 60000 running: M.Modules.bluetooth.enable repeat: true onTriggered: proc.running = true } M.BarIcon { icon: "\uF294" color: root.state === "off" ? M.Theme.base04 : root.accentColor anchors.verticalCenter: parent.verticalCenter TapHandler { cursorShape: Qt.PointingHandCursor onTapped: { M.FlyoutState.visible = false; btLoader.active = true; } } } M.BarLabel { visible: root.state === "connected" label: root.device + (root.batteryPct >= 0 ? " " + root.batteryPct + "%" : "") anchors.verticalCenter: parent.verticalCenter TapHandler { cursorShape: Qt.PointingHandCursor onTapped: { M.FlyoutState.visible = false; btLoader.active = true; } } } required property var bar LazyLoader { id: btLoader active: false M.BluetoothMenu { accentColor: root.accentColor screen: QsWindow.window?.screen ?? null anchorX: root.mapToGlobal(root.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0) onDismissed: btLoader.active = false } } }