Bluetooth: revamped a lot of code
This commit is contained in:
parent
b2e9058a2f
commit
c3956c5894
4 changed files with 379 additions and 319 deletions
|
|
@ -20,16 +20,7 @@ NIconButton {
|
||||||
colorBorder: Color.transparent
|
colorBorder: Color.transparent
|
||||||
colorBorderHover: Color.transparent
|
colorBorderHover: Color.transparent
|
||||||
|
|
||||||
icon: {
|
icon: "bluetooth"
|
||||||
// Show different icons based on connection status
|
|
||||||
if (BluetoothService.pairedDevices.length > 0) {
|
|
||||||
return "bluetooth_connected"
|
|
||||||
} else if (BluetoothService.discovering) {
|
|
||||||
return "bluetooth_searching"
|
|
||||||
} else {
|
|
||||||
return "bluetooth"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tooltipText: "Bluetooth Devices"
|
tooltipText: "Bluetooth Devices"
|
||||||
onClicked: PanelService.getPanel("bluetoothPanel")?.toggle(screen, this)
|
onClicked: PanelService.getPanel("bluetoothPanel")?.toggle(screen, this)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
262
Modules/BluetoothPanel/BluetoothDevicesList.qml
Normal file
262
Modules/BluetoothPanel/BluetoothDevicesList.qml
Normal file
|
|
@ -0,0 +1,262 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Bluetooth
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import qs.Commons
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string label: ""
|
||||||
|
property var model: {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Style.marginM * scaling
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: root.label
|
||||||
|
font.pointSize: Style.fontSizeL * scaling
|
||||||
|
color: Color.mSecondary
|
||||||
|
font.weight: Style.fontWeightMedium
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: root.model.length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: root.model
|
||||||
|
visible: BluetoothService.adapter && BluetoothService.adapter.enabled
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
property bool canConnect: BluetoothService.canConnect(modelData)
|
||||||
|
property bool isBusy: BluetoothService.isDeviceBusy(modelData)
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 64 * scaling + (10 * scaling * modelData.batteryAvailable)
|
||||||
|
radius: Style.radiusM * scaling
|
||||||
|
|
||||||
|
color: {
|
||||||
|
if (availableDeviceArea.containsMouse && !isBusy)
|
||||||
|
return Color.mTertiary
|
||||||
|
|
||||||
|
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
||||||
|
return Color.mPrimary
|
||||||
|
|
||||||
|
if (modelData.blocked)
|
||||||
|
return Color.mError
|
||||||
|
|
||||||
|
return Color.mSurfaceVariant
|
||||||
|
}
|
||||||
|
border.color: Color.mOutline
|
||||||
|
border.width: Math.max(1, Style.borderS * scaling)
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Style.marginM * scaling
|
||||||
|
spacing: Style.marginS * scaling
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
|
// One device BT icon
|
||||||
|
NIcon {
|
||||||
|
text: BluetoothService.getDeviceIcon(modelData)
|
||||||
|
font.pointSize: Style.fontSizeXXL * scaling
|
||||||
|
color: {
|
||||||
|
if (availableDeviceArea.containsMouse)
|
||||||
|
return Color.mOnTertiary
|
||||||
|
|
||||||
|
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
||||||
|
return Color.mOnPrimary
|
||||||
|
|
||||||
|
if (modelData.blocked)
|
||||||
|
return Color.mOnError
|
||||||
|
|
||||||
|
return Color.mOnSurface
|
||||||
|
}
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Style.marginXXS * scaling
|
||||||
|
|
||||||
|
// Device name
|
||||||
|
NText {
|
||||||
|
text: modelData.name || modelData.deviceName
|
||||||
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
|
elide: Text.ElideRight
|
||||||
|
color: {
|
||||||
|
if (availableDeviceArea.containsMouse)
|
||||||
|
return Color.mOnTertiary
|
||||||
|
|
||||||
|
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
||||||
|
return Color.mOnPrimary
|
||||||
|
|
||||||
|
if (modelData.blocked)
|
||||||
|
return Color.mOnError
|
||||||
|
|
||||||
|
return Color.mOnSurface
|
||||||
|
}
|
||||||
|
font.weight: Style.fontWeightMedium
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal Strength
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Style.marginXS * scaling
|
||||||
|
|
||||||
|
// Device signal strength - "Unknown" when not connected
|
||||||
|
NText {
|
||||||
|
text: BluetoothService.getSignalStrength(modelData)
|
||||||
|
font.pointSize: Style.fontSizeXS * scaling
|
||||||
|
color: {
|
||||||
|
if (availableDeviceArea.containsMouse)
|
||||||
|
return Color.mOnTertiary
|
||||||
|
|
||||||
|
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
||||||
|
return Color.mOnPrimary
|
||||||
|
|
||||||
|
if (modelData.blocked)
|
||||||
|
return Color.mOnError
|
||||||
|
|
||||||
|
return Color.mOnSurfaceVariant
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NIcon {
|
||||||
|
text: BluetoothService.getSignalIcon(modelData)
|
||||||
|
font.pointSize: Style.fontSizeXS * scaling
|
||||||
|
color: {
|
||||||
|
if (availableDeviceArea.containsMouse)
|
||||||
|
return Color.mOnTertiary
|
||||||
|
|
||||||
|
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
||||||
|
return Color.mOnPrimary
|
||||||
|
|
||||||
|
if (modelData.blocked)
|
||||||
|
return Color.mOnError
|
||||||
|
|
||||||
|
return Color.mOnSurface
|
||||||
|
}
|
||||||
|
visible: modelData.signalStrength !== undefined && modelData.signalStrength > 0 && !modelData.pairing
|
||||||
|
&& !modelData.blocked
|
||||||
|
}
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: (modelData.signalStrength !== undefined
|
||||||
|
&& modelData.signalStrength > 0) ? modelData.signalStrength + "%" : ""
|
||||||
|
font.pointSize: Style.fontSizeXS * scaling
|
||||||
|
color: {
|
||||||
|
if (availableDeviceArea.containsMouse)
|
||||||
|
return Color.mOnTertiary
|
||||||
|
|
||||||
|
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
||||||
|
return Color.mOnPrimary
|
||||||
|
|
||||||
|
if (modelData.blocked)
|
||||||
|
return Color.mOnError
|
||||||
|
|
||||||
|
return Color.mOnSurface
|
||||||
|
}
|
||||||
|
visible: modelData.signalStrength !== undefined && modelData.signalStrength > 0 && !modelData.pairing
|
||||||
|
&& !modelData.blocked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NText {
|
||||||
|
visible: modelData.batteryAvailable
|
||||||
|
text: BluetoothService.getBattery(modelData)
|
||||||
|
font.pointSize: Style.fontSizeXS * scaling
|
||||||
|
color: {
|
||||||
|
if (availableDeviceArea.containsMouse)
|
||||||
|
return Color.mOnTertiary
|
||||||
|
|
||||||
|
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
||||||
|
return Color.mOnPrimary
|
||||||
|
|
||||||
|
if (modelData.blocked)
|
||||||
|
return Color.mOnError
|
||||||
|
|
||||||
|
return Color.mOnSurfaceVariant
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spacer to push connect button to the right
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call to action
|
||||||
|
Rectangle {
|
||||||
|
Layout.preferredWidth: 80 * scaling
|
||||||
|
Layout.preferredHeight: 28 * scaling
|
||||||
|
radius: Style.radiusM * scaling
|
||||||
|
visible: (modelData.state !== BluetoothDeviceState.Connecting)
|
||||||
|
color: Color.transparent
|
||||||
|
|
||||||
|
border.color: {
|
||||||
|
if (availableDeviceArea.containsMouse) {
|
||||||
|
return Color.mOnTertiary
|
||||||
|
} else {
|
||||||
|
return Color.mPrimary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
border.width: Math.max(1, Style.borderS * scaling)
|
||||||
|
opacity: canConnect || isBusy ? 1 : 0.5
|
||||||
|
|
||||||
|
NText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: {
|
||||||
|
if (modelData.pairing) {
|
||||||
|
return "Pairing..."
|
||||||
|
}
|
||||||
|
if (modelData.blocked) {
|
||||||
|
return "Blocked"
|
||||||
|
}
|
||||||
|
if (modelData.paired || modelData.trusted) {
|
||||||
|
return "Disconnect"
|
||||||
|
}
|
||||||
|
return "Connect"
|
||||||
|
}
|
||||||
|
font.pointSize: Style.fontSizeXS * scaling
|
||||||
|
font.weight: Style.fontWeightMedium
|
||||||
|
color: {
|
||||||
|
if (availableDeviceArea.containsMouse) {
|
||||||
|
return Color.mOnTertiary
|
||||||
|
} else {
|
||||||
|
return Color.mPrimary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: availableDeviceArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: canConnect && !isBusy ? Qt.PointingHandCursor : (isBusy ? Qt.BusyCursor : Qt.ArrowCursor)
|
||||||
|
enabled: canConnect && !isBusy
|
||||||
|
onClicked: {
|
||||||
|
if (!modelData || modelData.pairing) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modelData.paired || modelData.trusted) {
|
||||||
|
BluetoothService.disconnectDevice(modelData)
|
||||||
|
} else {
|
||||||
|
BluetoothService.connectDeviceWithTrust(modelData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -68,259 +68,56 @@ NPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollView {
|
ScrollView {
|
||||||
id: scrollView
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
clip: true
|
|
||||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||||
ScrollBar.vertical.policy: ScrollBar.AsNeeded
|
ScrollBar.vertical.policy: ScrollBar.AsNeeded
|
||||||
|
clip: true
|
||||||
|
contentWidth: availableWidth
|
||||||
|
|
||||||
// Available devices
|
ColumnLayout {
|
||||||
Column {
|
|
||||||
id: column
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
spacing: Style.marginM * scaling
|
|
||||||
visible: BluetoothService.adapter && BluetoothService.adapter.enabled
|
visible: BluetoothService.adapter && BluetoothService.adapter.enabled
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Style.marginM * scaling
|
spacing: Style.marginM * scaling
|
||||||
|
|
||||||
NText {
|
// Connected devices
|
||||||
text: "Available Devices"
|
BluetoothDevicesList {
|
||||||
font.pointSize: Style.fontSizeL * scaling
|
label: "Connected devices"
|
||||||
color: Color.mOnSurface
|
|
||||||
font.weight: Style.fontWeightMedium
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: {
|
model: {
|
||||||
if (!BluetoothService.adapter || !BluetoothService.adapter.discovering || !Bluetooth.devices)
|
if (!BluetoothService.adapter || !Bluetooth.devices)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
var filtered = Bluetooth.devices.values.filter(dev => {
|
var filtered = Bluetooth.devices.values.filter(dev => {
|
||||||
return dev && !dev.paired && !dev.pairing && !dev.blocked
|
return dev && !dev.blocked && (dev.paired || dev.trusted)
|
||||||
&& (dev.signalStrength === undefined
|
|
||||||
|| dev.signalStrength > 0)
|
|
||||||
})
|
})
|
||||||
return BluetoothService.sortDevices(filtered)
|
return BluetoothService.sortDevices(filtered)
|
||||||
}
|
}
|
||||||
|
Layout.fillWidth: true
|
||||||
Rectangle {
|
|
||||||
property bool canConnect: BluetoothService.canConnect(modelData)
|
|
||||||
property bool isBusy: BluetoothService.isDeviceBusy(modelData)
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
height: 70
|
|
||||||
radius: Style.radiusM * scaling
|
|
||||||
color: {
|
|
||||||
if (availableDeviceArea.containsMouse && !isBusy)
|
|
||||||
return Color.mTertiary
|
|
||||||
|
|
||||||
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
|
||||||
return Color.mPrimary
|
|
||||||
|
|
||||||
if (modelData.blocked)
|
|
||||||
return Color.mError
|
|
||||||
|
|
||||||
return Color.mSurfaceVariant
|
|
||||||
}
|
|
||||||
border.color: Color.mOutline
|
|
||||||
border.width: Math.max(1, Style.borderS * scaling)
|
|
||||||
|
|
||||||
Row {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Style.marginM * scaling
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: Style.marginS * scaling
|
|
||||||
|
|
||||||
// One device BT icon
|
|
||||||
NIcon {
|
|
||||||
text: BluetoothService.getDeviceIcon(modelData)
|
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
color: {
|
|
||||||
if (availableDeviceArea.containsMouse)
|
|
||||||
return Color.mOnTertiary
|
|
||||||
|
|
||||||
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
|
||||||
return Color.mOnPrimary
|
|
||||||
|
|
||||||
if (modelData.blocked)
|
|
||||||
return Color.mOnError
|
|
||||||
|
|
||||||
return Color.mOnSurface
|
|
||||||
}
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
// Available devices
|
||||||
spacing: Style.marginXXS * scaling
|
BluetoothDevicesList {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
label: "Available devices"
|
||||||
|
model: {
|
||||||
|
if (!BluetoothService.adapter || !Bluetooth.devices)
|
||||||
|
return []
|
||||||
|
|
||||||
// One device name
|
var filtered = Bluetooth.devices.values.filter(dev => {
|
||||||
NText {
|
return dev && !dev.blocked && !dev.paired && !dev.trusted
|
||||||
text: modelData.name || modelData.deviceName
|
})
|
||||||
font.pointSize: Style.fonttSizeMedium * scaling
|
return BluetoothService.sortDevices(filtered)
|
||||||
elide: Text.ElideRight
|
|
||||||
color: {
|
|
||||||
if (availableDeviceArea.containsMouse)
|
|
||||||
return Color.mOnTertiary
|
|
||||||
|
|
||||||
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
|
||||||
return Color.mOnPrimary
|
|
||||||
|
|
||||||
if (modelData.blocked)
|
|
||||||
return Color.mOnError
|
|
||||||
|
|
||||||
return Color.mOnSurface
|
|
||||||
}
|
}
|
||||||
font.weight: Style.fontWeightMedium
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
// Fallback
|
||||||
spacing: Style.marginXS * scaling
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
Row {
|
|
||||||
spacing: Style.marginS * spacing
|
|
||||||
|
|
||||||
// One device signal strength - "Unknown" when not connected
|
|
||||||
NText {
|
|
||||||
text: {
|
|
||||||
if (modelData.pairing)
|
|
||||||
return "Pairing..."
|
|
||||||
|
|
||||||
if (modelData.blocked)
|
|
||||||
return "Blocked"
|
|
||||||
|
|
||||||
return BluetoothService.getSignalStrength(modelData)
|
|
||||||
}
|
|
||||||
font.pointSize: Style.fontSizeXS * scaling
|
|
||||||
color: {
|
|
||||||
if (availableDeviceArea.containsMouse)
|
|
||||||
return Color.mOnTertiary
|
|
||||||
|
|
||||||
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
|
||||||
return Color.mOnPrimary
|
|
||||||
|
|
||||||
if (modelData.blocked)
|
|
||||||
return Color.mOnError
|
|
||||||
|
|
||||||
return Color.mOnSurface
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NIcon {
|
|
||||||
text: BluetoothService.getSignalIcon(modelData)
|
|
||||||
font.pointSize: Style.fontSizeXS * scaling
|
|
||||||
color: {
|
|
||||||
if (availableDeviceArea.containsMouse)
|
|
||||||
return Color.mOnTertiary
|
|
||||||
|
|
||||||
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
|
||||||
return Color.mOnPrimary
|
|
||||||
|
|
||||||
if (modelData.blocked)
|
|
||||||
return Color.mOnError
|
|
||||||
|
|
||||||
return Color.mOnSurface
|
|
||||||
}
|
|
||||||
visible: modelData.signalStrength !== undefined && modelData.signalStrength > 0
|
|
||||||
&& !modelData.pairing && !modelData.blocked
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: (modelData.signalStrength !== undefined
|
|
||||||
&& modelData.signalStrength > 0) ? modelData.signalStrength + "%" : ""
|
|
||||||
font.pointSize: Style.fontSizeXS * scaling
|
|
||||||
color: {
|
|
||||||
if (availableDeviceArea.containsMouse)
|
|
||||||
return Color.mOnTertiary
|
|
||||||
|
|
||||||
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
|
||||||
return Color.mOnPrimary
|
|
||||||
|
|
||||||
if (modelData.blocked)
|
|
||||||
return Color.mOnError
|
|
||||||
|
|
||||||
return Color.mOnSurface
|
|
||||||
}
|
|
||||||
visible: modelData.signalStrength !== undefined && modelData.signalStrength > 0
|
|
||||||
&& !modelData.pairing && !modelData.blocked
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 80 * scaling
|
|
||||||
height: 28 * scaling
|
|
||||||
radius: Style.radiusM * scaling
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: Style.marginM * scaling
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
visible: modelData.state !== BluetoothDeviceState.Connecting
|
|
||||||
color: Color.transparent
|
|
||||||
|
|
||||||
border.color: {
|
|
||||||
if (availableDeviceArea.containsMouse) {
|
|
||||||
return Color.mOnTertiary
|
|
||||||
} else {
|
|
||||||
return Color.mPrimary
|
|
||||||
}
|
|
||||||
}
|
|
||||||
border.width: Math.max(1, Style.borderS * scaling)
|
|
||||||
opacity: canConnect || isBusy ? 1 : 0.5
|
|
||||||
|
|
||||||
// On device connect button
|
|
||||||
NText {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: {
|
|
||||||
if (modelData.pairing)
|
|
||||||
return "Pairing..."
|
|
||||||
|
|
||||||
if (modelData.blocked)
|
|
||||||
return "Blocked"
|
|
||||||
|
|
||||||
return "Connect"
|
|
||||||
}
|
|
||||||
font.pointSize: Style.fontSizeXS * scaling
|
|
||||||
font.weight: Style.fontWeightMedium
|
|
||||||
color: {
|
|
||||||
if (availableDeviceArea.containsMouse) {
|
|
||||||
return Color.mOnTertiary
|
|
||||||
} else {
|
|
||||||
return Color.mPrimary
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: availableDeviceArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: canConnect && !isBusy ? Qt.PointingHandCursor : (isBusy ? Qt.BusyCursor : Qt.ArrowCursor)
|
|
||||||
enabled: canConnect && !isBusy
|
|
||||||
onClicked: {
|
|
||||||
if (modelData)
|
|
||||||
BluetoothService.connectDeviceWithTrust(modelData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback if nothing available
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Style.marginM * scaling
|
spacing: Style.marginM * scaling
|
||||||
visible: {
|
visible: {
|
||||||
if (!BluetoothService.adapter || !BluetoothService.adapter.discovering || !Bluetooth.devices)
|
if (!BluetoothService.adapter || !BluetoothService.adapter.discovering || !Bluetooth.devices) {
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
var availableCount = Bluetooth.devices.values.filter(dev => {
|
var availableCount = Bluetooth.devices.values.filter(dev => {
|
||||||
return dev && !dev.paired && !dev.pairing
|
return dev && !dev.paired && !dev.pairing
|
||||||
|
|
@ -328,18 +125,17 @@ NPanel {
|
||||||
&& (dev.signalStrength === undefined
|
&& (dev.signalStrength === undefined
|
||||||
|| dev.signalStrength > 0)
|
|| dev.signalStrength > 0)
|
||||||
}).length
|
}).length
|
||||||
return availableCount === 0
|
return (availableCount === 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
RowLayout {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
spacing: Style.marginM * scaling
|
spacing: Style.marginM * scaling
|
||||||
|
|
||||||
NIcon {
|
NIcon {
|
||||||
text: "sync"
|
text: "sync"
|
||||||
font.pointSize: Style.fontSizeXLL * 1.5 * scaling
|
font.pointSize: Style.fontSizeXLL * 1.5 * scaling
|
||||||
color: Color.mPrimary
|
color: Color.mPrimary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
|
|
||||||
RotationAnimation on rotation {
|
RotationAnimation on rotation {
|
||||||
running: true
|
running: true
|
||||||
|
|
@ -355,7 +151,6 @@ NPanel {
|
||||||
font.pointSize: Style.fontSizeL * scaling
|
font.pointSize: Style.fontSizeL * scaling
|
||||||
color: Color.mOnSurface
|
color: Color.mOnSurface
|
||||||
font.weight: Style.fontWeightMedium
|
font.weight: Style.fontWeightMedium
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,36 +158,15 @@ NPanel {
|
||||||
text: "Make sure your device is in pairing mode"
|
text: "Make sure your device is in pairing mode"
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
color: Color.mOnSurfaceVariant
|
color: Color.mOnSurfaceVariant
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "No devices found. Put your device in pairing mode and click Start Scanning."
|
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
|
||||||
color: Color.mOnSurfaceVariant
|
|
||||||
visible: {
|
|
||||||
if (!BluetoothService.adapter || !Bluetooth.devices)
|
|
||||||
return true
|
|
||||||
|
|
||||||
var availableCount = Bluetooth.devices.values.filter(dev => {
|
|
||||||
return dev && !dev.paired && !dev.pairing
|
|
||||||
&& !dev.blocked
|
|
||||||
&& (dev.signalStrength === undefined
|
|
||||||
|| dev.signalStrength > 0)
|
|
||||||
}).length
|
|
||||||
return availableCount === 0 && !BluetoothService.adapter.discovering
|
|
||||||
}
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
width: parent.width
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// This item takes up all the remaining vertical space.
|
|
||||||
Item {
|
Item {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,17 +13,17 @@ Singleton {
|
||||||
readonly property bool discovering: (adapter && adapter.discovering) ?? false
|
readonly property bool discovering: (adapter && adapter.discovering) ?? false
|
||||||
readonly property var devices: adapter ? adapter.devices : null
|
readonly property var devices: adapter ? adapter.devices : null
|
||||||
readonly property var pairedDevices: {
|
readonly property var pairedDevices: {
|
||||||
if (!adapter || !adapter.devices)
|
if (!adapter || !adapter.devices) {
|
||||||
return []
|
return []
|
||||||
|
}
|
||||||
return adapter.devices.values.filter(dev => {
|
return adapter.devices.values.filter(dev => {
|
||||||
return dev && (dev.paired || dev.trusted)
|
return dev && (dev.paired || dev.trusted)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
readonly property var allDevicesWithBattery: {
|
readonly property var allDevicesWithBattery: {
|
||||||
if (!adapter || !adapter.devices)
|
if (!adapter || !adapter.devices) {
|
||||||
return []
|
return []
|
||||||
|
}
|
||||||
return adapter.devices.values.filter(dev => {
|
return adapter.devices.values.filter(dev => {
|
||||||
return dev && dev.batteryAvailable && dev.battery > 0
|
return dev && dev.batteryAvailable && dev.battery > 0
|
||||||
})
|
})
|
||||||
|
|
@ -49,34 +49,36 @@ Singleton {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDeviceIcon(device) {
|
function getDeviceIcon(device) {
|
||||||
if (!device)
|
if (!device) {
|
||||||
return "bluetooth"
|
return "bluetooth"
|
||||||
|
}
|
||||||
|
|
||||||
var name = (device.name || device.deviceName || "").toLowerCase()
|
var name = (device.name || device.deviceName || "").toLowerCase()
|
||||||
var icon = (device.icon || "").toLowerCase()
|
var icon = (device.icon || "").toLowerCase()
|
||||||
if (icon.includes("headset") || icon.includes("audio") || name.includes("headphone") || name.includes("airpod")
|
if (icon.includes("headset") || icon.includes("audio") || name.includes("headphone") || name.includes("airpod")
|
||||||
|| name.includes("headset") || name.includes("arctis"))
|
|| name.includes("headset") || name.includes("arctis")) {
|
||||||
return "headset"
|
return "headset"
|
||||||
|
}
|
||||||
|
|
||||||
if (icon.includes("mouse") || name.includes("mouse"))
|
if (icon.includes("mouse") || name.includes("mouse")) {
|
||||||
return "mouse"
|
return "mouse"
|
||||||
|
}
|
||||||
if (icon.includes("keyboard") || name.includes("keyboard"))
|
if (icon.includes("keyboard") || name.includes("keyboard")) {
|
||||||
return "keyboard"
|
return "keyboard"
|
||||||
|
}
|
||||||
if (icon.includes("phone") || name.includes("phone") || name.includes("iphone") || name.includes("android")
|
if (icon.includes("phone") || name.includes("phone") || name.includes("iphone") || name.includes("android")
|
||||||
|| name.includes("samsung"))
|
|| name.includes("samsung")) {
|
||||||
return "smartphone"
|
return "smartphone"
|
||||||
|
}
|
||||||
if (icon.includes("watch") || name.includes("watch"))
|
if (icon.includes("watch") || name.includes("watch")) {
|
||||||
return "watch"
|
return "watch"
|
||||||
|
}
|
||||||
if (icon.includes("speaker") || name.includes("speaker"))
|
if (icon.includes("speaker") || name.includes("speaker")) {
|
||||||
return "speaker"
|
return "speaker"
|
||||||
|
}
|
||||||
if (icon.includes("display") || name.includes("tv"))
|
if (icon.includes("display") || name.includes("tv")) {
|
||||||
return "tv"
|
return "tv"
|
||||||
|
}
|
||||||
return "bluetooth"
|
return "bluetooth"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,60 +90,91 @@ Singleton {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSignalStrength(device) {
|
function getSignalStrength(device) {
|
||||||
if (!device || device.signalStrength === undefined || device.signalStrength <= 0)
|
if (device.pairing) {
|
||||||
return "Unknown"
|
return "Pairing..."
|
||||||
|
}
|
||||||
|
if (device.blocked) {
|
||||||
|
return "Blocked"
|
||||||
|
}
|
||||||
|
if (!device || device.signalStrength === undefined || device.signalStrength <= 0) {
|
||||||
|
return "Signal: Unknown"
|
||||||
|
}
|
||||||
var signal = device.signalStrength
|
var signal = device.signalStrength
|
||||||
if (signal >= 80)
|
if (signal >= 80) {
|
||||||
return "Excellent"
|
return "Signal: Excellent"
|
||||||
|
}
|
||||||
|
if (signal >= 60) {
|
||||||
|
return "Signal: Good"
|
||||||
|
}
|
||||||
|
if (signal >= 40) {
|
||||||
|
return "Signal: Fair"
|
||||||
|
}
|
||||||
|
if (signal >= 20) {
|
||||||
|
return "Signal: Poor"
|
||||||
|
}
|
||||||
|
return "Signal: Very Poor"
|
||||||
|
}
|
||||||
|
|
||||||
if (signal >= 60)
|
function getBattery(device) {
|
||||||
return "Good"
|
return `Battery: ${Math.round(device.battery * 100)}`
|
||||||
|
|
||||||
if (signal >= 40)
|
|
||||||
return "Fair"
|
|
||||||
|
|
||||||
if (signal >= 20)
|
|
||||||
return "Poor"
|
|
||||||
|
|
||||||
return "Very Poor"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSignalIcon(device) {
|
function getSignalIcon(device) {
|
||||||
if (!device || device.signalStrength === undefined || device.signalStrength <= 0)
|
if (!device || device.signalStrength === undefined || device.signalStrength <= 0) {
|
||||||
return "signal_cellular_null"
|
return "signal_cellular_null"
|
||||||
|
}
|
||||||
var signal = device.signalStrength
|
var signal = device.signalStrength
|
||||||
if (signal >= 80)
|
if (signal >= 80) {
|
||||||
return "signal_cellular_4_bar"
|
return "signal_cellular_4_bar"
|
||||||
|
}
|
||||||
if (signal >= 60)
|
if (signal >= 60) {
|
||||||
return "signal_cellular_3_bar"
|
return "signal_cellular_3_bar"
|
||||||
|
}
|
||||||
if (signal >= 40)
|
if (signal >= 40) {
|
||||||
return "signal_cellular_2_bar"
|
return "signal_cellular_2_bar"
|
||||||
|
}
|
||||||
if (signal >= 20)
|
if (signal >= 20) {
|
||||||
return "signal_cellular_1_bar"
|
return "signal_cellular_1_bar"
|
||||||
|
}
|
||||||
return "signal_cellular_0_bar"
|
return "signal_cellular_0_bar"
|
||||||
}
|
}
|
||||||
|
|
||||||
function isDeviceBusy(device) {
|
function isDeviceBusy(device) {
|
||||||
if (!device)
|
if (!device) {
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return device.pairing || device.state === BluetoothDeviceState.Disconnecting
|
return device.pairing || device.state === BluetoothDeviceState.Disconnecting
|
||||||
|| device.state === BluetoothDeviceState.Connecting
|
|| device.state === BluetoothDeviceState.Connecting
|
||||||
}
|
}
|
||||||
|
|
||||||
function connectDeviceWithTrust(device) {
|
function connectDeviceWithTrust(device) {
|
||||||
if (!device)
|
if (!device) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
device.trusted = true
|
device.trusted = true
|
||||||
device.connect()
|
device.connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function disconnectDevice(device) {
|
||||||
|
if (!device) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
device.trusted = false
|
||||||
|
device.disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
function forgetDevice(device) {
|
||||||
|
if (!device) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
device.trusted = false
|
||||||
|
device.forget()
|
||||||
|
}
|
||||||
|
|
||||||
function setBluetoothEnabled(enabled) {
|
function setBluetoothEnabled(enabled) {
|
||||||
if (!adapter) {
|
if (!adapter) {
|
||||||
Logger.warn("Bluetooth", "No adapter available")
|
Logger.warn("Bluetooth", "No adapter available")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue