262 lines
7.7 KiB
QML
262 lines
7.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 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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|