feat: bar bluetooth devices

This commit is contained in:
2 * r + 2 * t 2025-04-29 18:47:45 +10:00
parent a24e6f5b93
commit 169450aa2e
9 changed files with 127 additions and 11 deletions

View file

@ -35,9 +35,9 @@ Item {
vertical: BarConfig.vertical
anchors.left: root.get(osIcon.right, undefined)
anchors.leftMargin: root.get(Appearance.padding.normal, 0)
anchors.leftMargin: root.get(Appearance.padding.large, 0)
anchors.top: root.get(undefined, osIcon.bottom)
anchors.topMargin: root.get(0, Appearance.padding.normal)
anchors.topMargin: root.get(0, Appearance.padding.large)
anchors.horizontalCenter: root.get(undefined, parent.horizontalCenter)
anchors.verticalCenter: root.get(parent.verticalCenter, undefined)
@ -70,9 +70,9 @@ Item {
StatusIcons {
anchors.left: root.get(clock.right, undefined)
anchors.leftMargin: root.get(Appearance.padding.normal, 0)
anchors.leftMargin: root.get(Appearance.padding.large, 0)
anchors.top: root.get(undefined, clock.bottom)
anchors.topMargin: root.get(0, Appearance.padding.normal)
anchors.topMargin: root.get(0, Appearance.padding.large)
anchors.horizontalCenter: root.get(undefined, parent.horizontalCenter)
anchors.verticalCenter: root.get(parent.verticalCenter, undefined)

View file

@ -19,7 +19,7 @@ StyledRect {
prevAnchor: icon
horizontalAlignment: StyledText.AlignHCenter
text: root.vertical ? Time.format("hh\nmm") : Time.format("dd/MM/yy hh:mm")
text: root.vertical ? Time.format("hh\nmm") : Time.format("hh:mm • dddd, dd MMMM")
font.pointSize: Appearance.font.size.smaller
font.family: Appearance.font.family.mono
color: root.colour

View file

@ -3,6 +3,7 @@ import "root:/services"
import "root:/utils"
import "root:/config"
import QtQuick
import QtQuick.Controls
StyledRect {
id: root
@ -10,9 +11,44 @@ StyledRect {
readonly property color colour: Appearance.colours.rosewater
MaterialIcon {
id: icon
id: network
animate: true
text: Icons.getNetworkIcon(Network.active.strength)
color: root.colour
}
AnchorText {
id: bluetooth
prevAnchor: network
animate: true
text: Bluetooth.powered ? "bluetooth" : "bluetooth_disabled"
color: root.colour
font.family: Appearance.font.family.material
font.pointSize: Appearance.font.size.larger
}
BoxLayout {
anchors.left: vertical ? undefined : bluetooth.right
anchors.leftMargin: vertical ? 0 : Appearance.padding.smaller
anchors.top: vertical ? bluetooth.bottom : undefined
anchors.topMargin: vertical ? Appearance.padding.smaller : 0
anchors.horizontalCenter: vertical ? bluetooth.horizontalCenter : undefined
anchors.verticalCenter: vertical ? undefined : bluetooth.verticalCenter
Repeater {
model: Bluetooth.connected
MaterialIcon {
required property Bluetooth.Device modelData
animate: true
text: Icons.getBluetoothIcon(modelData.icon)
color: root.colour
}
}
}
}

70
services/Bluetooth.qml Normal file
View file

@ -0,0 +1,70 @@
pragma Singleton
import Quickshell
import Quickshell.Io
import QtQuick
Singleton {
id: root
property bool powered
property bool discovering
readonly property list<Device> devices: []
readonly property list<Device> connected: devices.filter(d => d.connected)
Process {
running: true
command: ["bluetoothctl"]
stdout: SplitParser {
onRead: getInfo.running = true
}
}
Process {
id: getInfo
running: true
command: ["sh", "-c", "bluetoothctl show | paste -s"]
stdout: SplitParser {
onRead: data => {
root.powered = data.includes("Powered: yes");
root.discovering = data.includes("Discovering: yes");
}
}
}
Process {
id: getDevices
running: true
command: ["fish", "-c", `for a in (bluetoothctl devices | cut -d ' ' -f 2); bluetoothctl info $a | jq -R 'reduce (inputs / ":") as [$key, $value] ({}; .[$key | ltrimstr("\t")] = ($value | ltrimstr(" ")))' | jq -c --arg addr $a '.Address = $addr'; end`]
stdout: SplitParser {
onRead: data => {
const d = JSON.parse(data);
root.devices.push(deviceComp.createObject(root, {
name: d.Name,
alias: d.Alias,
address: d.Address,
icon: d.Icon,
connected: d.Connected === "yes",
paired: d.Paired === "yes",
trusted: d.Trusted === "yes"
}));
}
}
}
component Device: QtObject {
property string name
property string alias
property string address
property string icon
property bool connected
property bool paired
property bool trusted
}
Component {
id: deviceComp
Device {}
}
}

View file

@ -39,7 +39,7 @@ Singleton {
Process {
id: getClients
command: ["bash", "-c", "hyprctl -j clients | jq -c"]
command: ["sh", "-c", "hyprctl -j clients | jq -c"]
stdout: SplitParser {
onRead: data => {
const clients = JSON.parse(data);
@ -58,7 +58,7 @@ Singleton {
Process {
id: getActiveClient
command: ["bash", "-c", "hyprctl -j activewindow | jq -c"]
command: ["sh", "-c", "hyprctl -j activewindow | jq -c"]
stdout: SplitParser {
onRead: data => {
const client = JSON.parse(data);

View file

@ -177,6 +177,16 @@ Singleton {
return "signal_wifi_0_bar";
}
function getBluetoothIcon(icon: string): string {
if (icon.includes("headset") || icon.includes("headphones"))
return "headphones";
if (icon.includes("audio"))
return "speaker";
if (icon.includes("phone"))
return "smartphone";
return "bluetooth";
}
FileView {
path: "/etc/os-release"
onLoaded: {

View file

@ -5,7 +5,7 @@ StyledText {
id: root
required property Item prevAnchor
property bool vertical
property bool vertical: parent.vertical ?? false
anchors.left: vertical ? undefined : prevAnchor.right
anchors.leftMargin: vertical ? 0 : Appearance.padding.smaller

View file

@ -2,7 +2,7 @@ import "root:/config"
import QtQuick.Layouts
GridLayout {
property bool vertical: false
property bool vertical: parent.vertical ?? false // Propagate from parent
property bool homogenous: false
property int spacing: Appearance.spacing.small

View file

@ -5,7 +5,7 @@ Rectangle {
id: root
property bool animate: false
property bool vertical: false // Convenience property for propagation to children
property bool vertical: parent.vertical ?? false // Convenience property for propagation to children
color: "transparent"
implicitWidth: childrenRect.width