Show discovered devices and shrink bluetooth header buttons
- Scan and Manage are now small icon-only buttons in the header beside the On/Off pill, with hover tooltips via the new PillButton.tooltipText prop (backed by QtQuick.Controls ToolTip). - New discoveredDevices list pulls everything in Bluetooth.devices that isn't paired/connected/bonded/trusted. While scanning, those appear under a 'Discovered' header. Click pairs and connects. - Empty-state text only shows when there are no known and no discovered devices, otherwise it would push down real entries.
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string text: ""
|
property string text: ""
|
||||||
property string iconText: ""
|
property string iconText: ""
|
||||||
|
property string tooltipText: ""
|
||||||
property color foreground: "#cacccc"
|
property color foreground: "#cacccc"
|
||||||
property color background: "transparent"
|
property color background: "transparent"
|
||||||
property color hoverBackground: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.12)
|
property color hoverBackground: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.12)
|
||||||
@@ -17,6 +19,10 @@ Rectangle {
|
|||||||
property bool active: false
|
property bool active: false
|
||||||
property color activeBackground: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.18)
|
property color activeBackground: Qt.rgba(foreground.r, foreground.g, foreground.b, 0.18)
|
||||||
|
|
||||||
|
ToolTip.visible: tooltipText !== "" && mouseArea.containsMouse
|
||||||
|
ToolTip.text: tooltipText
|
||||||
|
ToolTip.delay: 400
|
||||||
|
|
||||||
signal clicked()
|
signal clicked()
|
||||||
signal rightClicked()
|
signal rightClicked()
|
||||||
|
|
||||||
|
|||||||
@@ -92,48 +92,49 @@ Item {
|
|||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
|
|
||||||
Common.PillButton {
|
Row {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
iconText: root.adapter && root.adapter.enabled ? "" : ""
|
spacing: 4
|
||||||
text: root.adapter && root.adapter.enabled ? "On" : "Off"
|
|
||||||
foreground: root.bar.foreground
|
|
||||||
horizontalPadding: 10
|
|
||||||
verticalPadding: 4
|
|
||||||
active: root.adapter && root.adapter.enabled
|
|
||||||
onClicked: if (root.adapter) root.adapter.enabled = !root.adapter.enabled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Action row: scan toggle and TUI launcher.
|
Common.PillButton {
|
||||||
Row {
|
iconText: ""
|
||||||
width: parent.width
|
tooltipText: !root.adapter ? "" : !root.adapter.enabled ? "Bluetooth is off"
|
||||||
spacing: 8
|
: root.adapter.discovering ? "Stop scanning" : "Scan for devices"
|
||||||
|
foreground: root.bar.foreground
|
||||||
|
horizontalPadding: 6
|
||||||
|
verticalPadding: 4
|
||||||
|
iconSize: 14
|
||||||
|
enabled: root.adapter !== null && root.adapter.enabled
|
||||||
|
opacity: enabled ? 1 : 0.4
|
||||||
|
active: root.adapter && root.adapter.discovering
|
||||||
|
onClicked: if (root.adapter) root.adapter.discovering = !root.adapter.discovering
|
||||||
|
}
|
||||||
|
|
||||||
Common.PillButton {
|
Common.PillButton {
|
||||||
width: (parent.width - parent.spacing) / 2
|
iconText: ""
|
||||||
iconText: ""
|
tooltipText: "Open Impala (TUI)"
|
||||||
text: root.adapter && root.adapter.discovering ? "Scanning…" : "Scan"
|
foreground: root.bar.foreground
|
||||||
foreground: root.bar.foreground
|
horizontalPadding: 6
|
||||||
horizontalPadding: 10
|
verticalPadding: 4
|
||||||
verticalPadding: 6
|
iconSize: 14
|
||||||
enabled: root.adapter !== null && root.adapter.enabled
|
onClicked: { root.bar.run("omarchy-launch-bluetooth"); root.popupOpen = false }
|
||||||
opacity: enabled ? 1 : 0.4
|
}
|
||||||
active: root.adapter && root.adapter.discovering
|
|
||||||
onClicked: if (root.adapter) root.adapter.discovering = !root.adapter.discovering
|
|
||||||
}
|
|
||||||
|
|
||||||
Common.PillButton {
|
Common.PillButton {
|
||||||
width: (parent.width - parent.spacing) / 2
|
iconText: root.adapter && root.adapter.enabled ? "" : ""
|
||||||
iconText: ""
|
text: root.adapter && root.adapter.enabled ? "On" : "Off"
|
||||||
text: "Manage…"
|
tooltipText: root.adapter && root.adapter.enabled ? "Turn Bluetooth off" : "Turn Bluetooth on"
|
||||||
foreground: root.bar.foreground
|
foreground: root.bar.foreground
|
||||||
horizontalPadding: 10
|
horizontalPadding: 10
|
||||||
verticalPadding: 6
|
verticalPadding: 4
|
||||||
onClicked: { root.bar.run("omarchy-launch-bluetooth"); root.popupOpen = false }
|
active: root.adapter && root.adapter.enabled
|
||||||
|
onClicked: if (root.adapter) root.adapter.enabled = !root.adapter.enabled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Paired / known devices.
|
||||||
Repeater {
|
Repeater {
|
||||||
model: root.knownDevices
|
model: root.knownDevices
|
||||||
|
|
||||||
@@ -147,6 +148,8 @@ Item {
|
|||||||
if (modelData && modelData.batteryAvailable) label += " " + Math.round(modelData.battery * 100) + "%"
|
if (modelData && modelData.batteryAvailable) label += " " + Math.round(modelData.battery * 100) + "%"
|
||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
|
tooltipText: modelData && modelData.connected ? "Click to disconnect · right-click to forget"
|
||||||
|
: "Click to connect · right-click to forget"
|
||||||
foreground: root.bar.foreground
|
foreground: root.bar.foreground
|
||||||
horizontalPadding: 10
|
horizontalPadding: 10
|
||||||
verticalPadding: 6
|
verticalPadding: 6
|
||||||
@@ -161,12 +164,44 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Discovered (unpaired) devices, only shown while scanning.
|
||||||
|
Text {
|
||||||
|
visible: root.adapter && root.adapter.discovering && root.discoveredDevices.length > 0
|
||||||
|
text: "Discovered"
|
||||||
|
color: Qt.darker(root.bar.foreground, 1.4)
|
||||||
|
font.family: root.bar.fontFamily
|
||||||
|
font.pixelSize: 10
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: root.adapter && root.adapter.discovering ? root.discoveredDevices : []
|
||||||
|
|
||||||
|
Common.PillButton {
|
||||||
|
required property var modelData
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
iconText: ""
|
||||||
|
text: modelData ? (modelData.deviceName || modelData.name || modelData.address || "Unknown") : ""
|
||||||
|
tooltipText: "Click to pair and connect"
|
||||||
|
foreground: Qt.darker(root.bar.foreground, 1.2)
|
||||||
|
horizontalPadding: 10
|
||||||
|
verticalPadding: 6
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (!modelData) return
|
||||||
|
modelData.pair()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
visible: root.knownDevices.length === 0
|
visible: root.knownDevices.length === 0
|
||||||
|
&& (!root.adapter || !root.adapter.discovering || root.discoveredDevices.length === 0)
|
||||||
text: !root.adapter ? "No Bluetooth adapter"
|
text: !root.adapter ? "No Bluetooth adapter"
|
||||||
: !root.adapter.enabled ? "Turn Bluetooth on to scan"
|
: !root.adapter.enabled ? "Turn Bluetooth on to scan"
|
||||||
: root.adapter.discovering ? "Scanning for devices…"
|
: root.adapter.discovering ? "Scanning for devices…"
|
||||||
: "No paired devices. Hit Scan to find new ones."
|
: "No paired devices. Tap the scan icon to find new ones."
|
||||||
color: Qt.darker(root.bar.foreground, 1.5)
|
color: Qt.darker(root.bar.foreground, 1.5)
|
||||||
font.family: root.bar.fontFamily
|
font.family: root.bar.fontFamily
|
||||||
font.pixelSize: 11
|
font.pixelSize: 11
|
||||||
|
|||||||
Reference in New Issue
Block a user