diff --git a/modules/bar/components/bluetooth/AvailableDevice.qml b/modules/bar/components/bluetooth/AvailableDevice.qml index df0c85f..51a54f4 100644 --- a/modules/bar/components/bluetooth/AvailableDevice.qml +++ b/modules/bar/components/bluetooth/AvailableDevice.qml @@ -10,7 +10,7 @@ import Quickshell.Widgets StyledLabel { id: root - required property BluetoothDevice modelData + property BluetoothDevice device RowLayout { id: row @@ -18,20 +18,20 @@ StyledLabel { spacing: 8 Loader { - active: root.modelData?.icon != undefined + active: root.device?.icon != undefined sourceComponent: IconImage { implicitSize: 22 - source: Quickshell.iconPath(root.modelData.icon, "device-support-unknown-symbolic") + source: Quickshell.iconPath(root.device.icon, "device-support-unknown-symbolic") } } StyledText { - text: root.modelData.deviceName + text: root.device.deviceName } StyledButton { Layout.alignment: Qt.AlignRight - hoverEnabled: !root.modelData.pairing + hoverEnabled: !root.device.pairing color: containsMouse ? Theme.palette.primary : Theme.palette.base200 content: StyledText { text: 'Pair' @@ -41,8 +41,8 @@ StyledLabel { if (!hoverEnabled) { return; } - root.modelData.trusted = true; - root.modelData.pair(); + root.device.trusted = true; + root.device.pair(); } } } diff --git a/modules/bar/components/bluetooth/BluetoothMenu.qml b/modules/bar/components/bluetooth/BluetoothMenu.qml index 22d1899..90186c8 100644 --- a/modules/bar/components/bluetooth/BluetoothMenu.qml +++ b/modules/bar/components/bluetooth/BluetoothMenu.qml @@ -1,12 +1,11 @@ pragma ComponentBehavior: Bound import qs.config +import qs.services import qs.widgets import QtQuick import QtQuick.Controls import QtQuick.Layouts -import Quickshell -import Quickshell.Bluetooth import Quickshell.Widgets StyledPopupWindow { @@ -30,8 +29,7 @@ StyledPopupWindow { } Switch { - checkable: !!Bluetooth.defaultAdapter - checked: Bluetooth.defaultAdapter?.enabled ?? false + checked: Bluetooth.defaultAdapter.enabled onClicked: Bluetooth.defaultAdapter.enabled = checked } } @@ -43,8 +41,7 @@ StyledPopupWindow { } Switch { - checkable: !!Bluetooth.defaultAdapter - checked: Bluetooth.defaultAdapter?.discovering ?? false + checked: Bluetooth.defaultAdapter.discovering onClicked: Bluetooth.defaultAdapter.discovering = checked } } @@ -66,28 +63,25 @@ StyledPopupWindow { text: "Connected Devices" } - StyledListView { - id: list1 - Layout.fillWidth: true - spacing: 8 - implicitHeight: 20 + Math.min(40 * count, 160) - header: Loader { - active: list1.count == 0 - sourceComponent: Loader { - active: list1.count == 0 - sourceComponent: StyledText { - font.italic: true - text: "No devices connected..." - } + ColumnLayout { + Loader { + active: Bluetooth.connectedDevices.length == 0 + sourceComponent: StyledText { + font.italic: true + text: "No devices connected..." } } - clip: true - model: ScriptModel { - values: Bluetooth.devices.values.filter(device => device.state == BluetoothDeviceState.Connected) - } - delegate: ConnectedDevice { - anchors.left: parent.left - anchors.right: parent.right + Repeater { + model: Bluetooth.connectedDevices + delegate: Loader { + id: connectedDeviceLoader + required property var modelData + Layout.fillWidth: true + active: modelData != null + sourceComponent: ConnectedDevice { + device: connectedDeviceLoader.modelData + } + } } } @@ -98,25 +92,25 @@ StyledPopupWindow { text: "Paired Devices" } - StyledListView { - id: list2 - Layout.fillWidth: true - spacing: 8 - implicitHeight: 20 + Math.min(40 * count, 160) - header: Loader { - active: list2.count == 0 + ColumnLayout { + Loader { + active: Bluetooth.availableDevices.length == 0 sourceComponent: StyledText { font.italic: true text: "No paired devices..." } } - clip: true - model: ScriptModel { - values: Bluetooth.defaultAdapter.devices.values.filter(device => device.bonded && device.state == BluetoothDeviceState.Disconnected) - } - delegate: PairedDevice { - anchors.left: parent.left - anchors.right: parent.right + Repeater { + model: Bluetooth.pairedDevices + delegate: Loader { + id: pairedDeviceLoader + required property var modelData + Layout.fillWidth: true + active: modelData != null + sourceComponent: PairedDevice { + device: pairedDeviceLoader.modelData + } + } } } @@ -127,25 +121,25 @@ StyledPopupWindow { text: "Available Devices" } - StyledListView { - id: list3 - Layout.fillWidth: true - spacing: 8 - clip: true - implicitHeight: 20 + Math.min(40 * count, 160) - header: Loader { - active: list3.count == 0 + ColumnLayout { + Loader { + active: Bluetooth.availableDevices.length == 0 sourceComponent: StyledText { font.italic: true text: Bluetooth.defaultAdapter.discovering ? "No devices found..." : "Scan to find devices..." } } - model: ScriptModel { - values: Bluetooth.devices.values.filter(device => !device.bonded && device.deviceName != "") - } - delegate: AvailableDevice { - anchors.left: parent.left - anchors.right: parent.right + Repeater { + model: Bluetooth.availableDevices + delegate: Loader { + id: availableDeviceLoader + required property var modelData + Layout.fillWidth: true + active: modelData != null + sourceComponent: AvailableDevice { + device: availableDeviceLoader.modelData + } + } } } } diff --git a/modules/bar/components/bluetooth/ConnectedDevice.qml b/modules/bar/components/bluetooth/ConnectedDevice.qml index ed23fd6..0c46886 100644 --- a/modules/bar/components/bluetooth/ConnectedDevice.qml +++ b/modules/bar/components/bluetooth/ConnectedDevice.qml @@ -11,7 +11,7 @@ import Quickshell.Widgets StyledLabel { id: root - required property BluetoothDevice modelData + required property BluetoothDevice device RowLayout { id: row @@ -19,19 +19,19 @@ StyledLabel { spacing: 8 Loader { - active: root.modelData?.icon != undefined + active: root.device?.icon != undefined sourceComponent: IconImage { implicitSize: 22 - source: Quickshell.iconPath(root.modelData.icon, "device-support-unknown-symbolic") + source: Quickshell.iconPath(root.device.icon, "device-support-unknown-symbolic") } } StyledText { - text: root.modelData.deviceName + text: root.device.deviceName } Loader { - active: root.modelData.batteryAvailable + active: root.device.batteryAvailable sourceComponent: RowLayout { StyledText { id: icon @@ -42,11 +42,11 @@ StyledLabel { states: [ State { name: "full" - when: root.modelData.battery > 0.66 + when: root.device.battery > 0.66 }, State { name: "medium" - when: root.modelData.battery > 0.33 + when: root.device.battery > 0.33 PropertyChanges { icon { text: Icons.batteryFull @@ -55,7 +55,7 @@ StyledLabel { }, State { name: "low" - when: root.modelData.battery > 0.10 + when: root.device.battery > 0.10 PropertyChanges { icon { text: Icons.batteryFull @@ -64,7 +64,7 @@ StyledLabel { }, State { name: "critical" - when: root.modelData.battery > 0.10 + when: root.device.battery > 0.10 PropertyChanges { icon { text: Icons.batteryWarning @@ -85,10 +85,10 @@ StyledLabel { font.pixelSize: 12 } onClicked: { - if (root.modelData.state != BluetoothDeviceState.Connected) { + if (root.device.state != BluetoothDeviceState.Connected) { return; } - root.modelData.connected = false; + root.device.connected = false; } } } diff --git a/modules/bar/components/bluetooth/PairedDevice.qml b/modules/bar/components/bluetooth/PairedDevice.qml index aa479b3..b2979ee 100644 --- a/modules/bar/components/bluetooth/PairedDevice.qml +++ b/modules/bar/components/bluetooth/PairedDevice.qml @@ -10,7 +10,7 @@ import Quickshell.Widgets StyledLabel { id: root - required property BluetoothDevice modelData + required property BluetoothDevice device RowLayout { id: row @@ -18,21 +18,21 @@ StyledLabel { spacing: 8 Loader { - active: root.modelData?.icon != undefined + active: root.device?.icon != undefined sourceComponent: IconImage { implicitSize: 22 - source: Quickshell.iconPath(root.modelData.icon, "device-support-unknown-symbolic") + source: Quickshell.iconPath(root.device.icon, "device-support-unknown-symbolic") } } StyledText { - text: root.modelData.deviceName + text: root.device.deviceName } RowLayout { Layout.alignment: Qt.AlignRight StyledButton { - hoverEnabled: root.modelData.state == BluetoothDeviceState.Disconnected + hoverEnabled: root.device.state == BluetoothDeviceState.Disconnected color: containsMouse ? Theme.palette.primary : Theme.palette.base200 content: StyledText { text: 'Connect' @@ -42,12 +42,12 @@ StyledLabel { if (!hoverEnabled) { return; } - root.modelData.connect(); + root.device.connect(); } } StyledButton { - hoverEnabled: root.modelData.state == BluetoothDeviceState.Disconnected + hoverEnabled: root.device.state == BluetoothDeviceState.Disconnected color: containsMouse ? Theme.palette.error : Theme.palette.base200 content: StyledText { text: 'Unpair' @@ -57,7 +57,7 @@ StyledLabel { if (!hoverEnabled) { return; } - root.modelData.forget(); + root.device.forget(); } } } diff --git a/services/Bluetooth.qml b/services/Bluetooth.qml new file mode 100644 index 0000000..65363ed --- /dev/null +++ b/services/Bluetooth.qml @@ -0,0 +1,22 @@ +pragma Singleton + +import QtQuick +import Quickshell +import Quickshell.Bluetooth + +Singleton { + id: root + + property BluetoothAdapter defaultAdapter: Bluetooth.defaultAdapter + property list connectedDevices: defaultAdapter?.devices.values.filter(device => device.state == BluetoothDeviceState.Connected) + property list pairedDevices: defaultAdapter?.devices.values.filter(device => device.bonded && device.state == BluetoothDeviceState.Disconnected) + property list availableDevices: defaultAdapter?.devices.values.filter(device => !device.bonded && device.deviceName != "") + + function isConnected(BluetoothDevice: device) { + return device.state == BluetoothDeviceState.Connected; + } + + function isConnecting(BluetoothDevice: device) { + return device.state == BluetoothDeviceState.Connecting; + } +} diff --git a/widgets/StyledListView.qml b/widgets/StyledListView.qml deleted file mode 100644 index 6f937df..0000000 --- a/widgets/StyledListView.qml +++ /dev/null @@ -1,16 +0,0 @@ -import QtQuick - -ListView { - id: root - - maximumFlickVelocity: 3000 - - rebound: Transition { - NumberAnimation { - properties: "x,y" - duration: 400 - easing.type: Easing.BezierSpline - easing.bezierCurve: [0.2, 0, 0, 1, 1, 1] - } - } -}