Files
nvrl add12ccc76 refactor(quickshell): drop the Persona names from the primitives
P5Panel, P5Button, P5Slider and P5Tooltip become Panel, ActionButton,
LevelSlider and Tooltip. ActionButton and LevelSlider avoid clashing
with QtQuick.Controls, which the ask panel imports.
2026-10-04 23:39:51 +02:00

117 lines
3.7 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Bluetooth
import "root:/config"
import "root:/components"
import "root:/services"
// Adapter toggle, scan, and the device list with battery levels where BlueZ
// reports them.
Popout {
id: root
contentWidth: 340
contentHeight: 280
// Discovery is expensive; run it only while the panel is open.
onShownChanged: {
if (!shown && Bt.discovering && Bt.adapter) Bt.adapter.discovering = false;
}
PopoutSurface {
anchors.fill: parent
tone: Bt.enabled ? Theme.accent : Theme.muted
PopoutHeader {
id: header
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
title: "Bluetooth"
icon: Bt.icon
accent: Theme.accent
subtitle: Bt.adapter ? Bt.adapter.name : "NO ADAPTER"
}
Row {
id: controls
anchors.top: header.bottom
anchors.topMargin: Theme.padM
anchors.left: parent.left
spacing: Theme.padS
ActionButton {
text: Bt.enabled ? "On" : "Off"
icon: Bt.enabled ? "󰂯" : "󰂲"
accent: Bt.enabled ? Theme.accent : Theme.muted
onClicked: Bt.toggle()
}
ActionButton {
text: Bt.discovering ? "Scanning" : "Scan"
icon: "󰐷"
accent: Bt.discovering ? Theme.accent : Theme.primary
onClicked: Bt.toggleScan()
}
}
SectionRule {
id: listLabel
anchors.top: controls.bottom
anchors.topMargin: Theme.padM
anchors.left: parent.left
anchors.right: parent.right
text: Bt.devices.length > 0 ? "Devices" : "No devices"
}
ListView {
anchors.top: listLabel.bottom
anchors.topMargin: Theme.padS
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
clip: true
spacing: 2
model: Bt.devices
delegate: ListRow {
id: devRow
required property BluetoothDevice modelData
width: ListView.view.width
icon: Bt.deviceIcon(modelData)
label: Bt.deviceLabel(modelData)
detail: {
if (modelData.pairing) return "pairing…";
if (modelData.connected) return "connected";
if (modelData.paired || modelData.bonded) return "paired";
return modelData.address;
}
current: modelData.connected
onClicked: Bt.toggleDevice(modelData)
onRightClicked: if (modelData.paired) modelData.forget()
// Device battery, where BlueZ exposes it.
Icon {
anchors.verticalCenter: parent.verticalCenter
visible: devRow.modelData.batteryAvailable
text: "󰥉"
color: devRow.modelData.battery > 0.25 ? Theme.subtext : Theme.alarm
font.pixelSize: Theme.fsSmall
}
Text {
anchors.verticalCenter: parent.verticalCenter
visible: devRow.modelData.batteryAvailable
text: Math.round(devRow.modelData.battery * 100) + "%"
color: Theme.subtext
font.family: Theme.fontMono
font.pixelSize: Theme.fsMicro
renderType: Text.NativeRendering
}
}
}
}
}