221 lines
6.7 KiB
QML
221 lines
6.7 KiB
QML
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 string tooltipText: ""
|
|
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 {
|
|
id: deviceList
|
|
Layout.fillWidth: true
|
|
model: root.model
|
|
visible: BluetoothService.adapter && BluetoothService.adapter.enabled
|
|
|
|
Rectangle {
|
|
id: device
|
|
|
|
readonly property bool canConnect: BluetoothService.canConnect(modelData)
|
|
readonly property bool canDisconnect: BluetoothService.canDisconnect(modelData)
|
|
readonly property bool isBusy: BluetoothService.isDeviceBusy(modelData)
|
|
|
|
function getContentColor(defaultColor = Color.mOnSurface) {
|
|
if (modelData.pairing || modelData.state === BluetoothDeviceState.Connecting)
|
|
return Color.mPrimary
|
|
if (modelData.blocked)
|
|
return Color.mError
|
|
return defaultColor
|
|
}
|
|
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: deviceLayout.implicitHeight + (Style.marginM * scaling * 2)
|
|
radius: Style.radiusM * scaling
|
|
color: Color.mSurface
|
|
border.width: Math.max(1, Style.borderS * scaling)
|
|
border.color: getContentColor(Color.mOutline)
|
|
|
|
RowLayout {
|
|
id: deviceLayout
|
|
anchors.fill: parent
|
|
anchors.margins: Style.marginM * scaling
|
|
spacing: Style.marginM * scaling
|
|
Layout.alignment: Qt.AlignVCenter
|
|
|
|
// One device BT icon
|
|
NIcon {
|
|
icon: BluetoothService.getDeviceIcon(modelData)
|
|
font.pointSize: Style.fontSizeXXL * scaling
|
|
color: getContentColor(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
|
|
font.weight: Style.fontWeightMedium
|
|
elide: Text.ElideRight
|
|
color: getContentColor(Color.mOnSurface)
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
// Status
|
|
NText {
|
|
text: BluetoothService.getStatusString(modelData)
|
|
visible: text !== ""
|
|
font.pointSize: Style.fontSizeXS * scaling
|
|
color: getContentColor(Color.mOnSurfaceVariant)
|
|
}
|
|
|
|
// Signal Strength
|
|
RowLayout {
|
|
visible: modelData.signalStrength !== undefined
|
|
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: getContentColor(Color.mOnSurfaceVariant)
|
|
}
|
|
|
|
NIcon {
|
|
visible: modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked
|
|
text: BluetoothService.getSignalIcon(modelData)
|
|
font.pointSize: Style.fontSizeXS * scaling
|
|
color: getContentColor(Color.mOnSurface)
|
|
}
|
|
|
|
NText {
|
|
visible: modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked
|
|
text: (modelData.signalStrength !== undefined && modelData.signalStrength > 0) ? modelData.signalStrength + "%" : ""
|
|
font.pointSize: Style.fontSizeXS * scaling
|
|
color: getContentColor(Color.mOnSurface)
|
|
}
|
|
}
|
|
|
|
// Battery
|
|
NText {
|
|
visible: modelData.batteryAvailable
|
|
text: BluetoothService.getBattery(modelData)
|
|
font.pointSize: Style.fontSizeXS * scaling
|
|
color: getContentColor(Color.mOnSurfaceVariant)
|
|
}
|
|
}
|
|
|
|
// Spacer to push connect button to the right
|
|
Item {
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
// Call to action
|
|
NButton {
|
|
id: button
|
|
visible: (modelData.state !== BluetoothDeviceState.Connecting)
|
|
enabled: (canConnect || canDisconnect) && !isBusy
|
|
outlined: !button.hovered
|
|
fontSize: Style.fontSizeXS * scaling
|
|
fontWeight: Style.fontWeightMedium
|
|
backgroundColor: {
|
|
if (device.canDisconnect && !isBusy) {
|
|
return Color.mError
|
|
}
|
|
return Color.mPrimary
|
|
}
|
|
tooltipText: root.tooltipText
|
|
text: {
|
|
if (modelData.pairing) {
|
|
return "Pairing..."
|
|
}
|
|
if (modelData.blocked) {
|
|
return "Blocked"
|
|
}
|
|
if (modelData.connected) {
|
|
return "Disconnect"
|
|
}
|
|
return "Connect"
|
|
}
|
|
icon: (isBusy ? "hourglass-split" : null)
|
|
onClicked: {
|
|
if (modelData.connected) {
|
|
BluetoothService.disconnectDevice(modelData)
|
|
} else {
|
|
BluetoothService.connectDeviceWithTrust(modelData)
|
|
}
|
|
}
|
|
onRightClicked: {
|
|
BluetoothService.forgetDevice(modelData)
|
|
}
|
|
}
|
|
}
|
|
|
|
// MouseArea {
|
|
|
|
// id: availableDeviceArea
|
|
// acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
// anchors.fill: parent
|
|
// hoverEnabled: true
|
|
// cursorShape: (canConnect || canDisconnect)
|
|
// && !isBusy ? Qt.PointingHandCursor : (isBusy ? Qt.BusyCursor : Qt.ArrowCursor)
|
|
// onEntered: {
|
|
// if (root.tooltipText && !isBusy) {
|
|
// tooltip.show()
|
|
// }
|
|
// }
|
|
// onExited: {
|
|
// if (root.tooltipText && !isBusy) {
|
|
// tooltip.hide()
|
|
// }
|
|
// }
|
|
// onClicked: function (mouse) {
|
|
|
|
// if (!modelData || modelData.pairing) {
|
|
// return
|
|
// }
|
|
|
|
// if (root.tooltipText && !isBusy) {
|
|
// tooltip.hide()
|
|
// }
|
|
|
|
// if (mouse.button === Qt.LeftButton) {
|
|
// if (modelData.connected) {
|
|
// BluetoothService.disconnectDevice(modelData)
|
|
// } else {
|
|
// BluetoothService.connectDeviceWithTrust(modelData)
|
|
// }
|
|
// } else if (mouse.button === Qt.RightButton) {
|
|
// BluetoothService.forgetDevice(modelData)
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
}
|
|
}
|