Compare commits

..

2 commits

Author SHA1 Message Date
Benjamin Palko
49ec4d8502 styled list view 2025-08-01 23:21:29 -04:00
Benjamin Palko
bac125abb0 guess i dont need bluetooth service? 2025-07-31 12:30:34 -04:00
6 changed files with 96 additions and 96 deletions

View file

@ -10,7 +10,7 @@ import Quickshell.Widgets
StyledLabel { StyledLabel {
id: root id: root
property BluetoothDevice device required property BluetoothDevice modelData
RowLayout { RowLayout {
id: row id: row
@ -18,20 +18,20 @@ StyledLabel {
spacing: 8 spacing: 8
Loader { Loader {
active: root.device?.icon != undefined active: root.modelData?.icon != undefined
sourceComponent: IconImage { sourceComponent: IconImage {
implicitSize: 22 implicitSize: 22
source: Quickshell.iconPath(root.device.icon, "device-support-unknown-symbolic") source: Quickshell.iconPath(root.modelData.icon, "device-support-unknown-symbolic")
} }
} }
StyledText { StyledText {
text: root.device.deviceName text: root.modelData.deviceName
} }
StyledButton { StyledButton {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
hoverEnabled: !root.device.pairing hoverEnabled: !root.modelData.pairing
color: containsMouse ? Theme.palette.primary : Theme.palette.base200 color: containsMouse ? Theme.palette.primary : Theme.palette.base200
content: StyledText { content: StyledText {
text: 'Pair' text: 'Pair'
@ -41,8 +41,8 @@ StyledLabel {
if (!hoverEnabled) { if (!hoverEnabled) {
return; return;
} }
root.device.trusted = true; root.modelData.trusted = true;
root.device.pair(); root.modelData.pair();
} }
} }
} }

View file

@ -1,11 +1,12 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import qs.config import qs.config
import qs.services
import qs.widgets import qs.widgets
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell
import Quickshell.Bluetooth
import Quickshell.Widgets import Quickshell.Widgets
StyledPopupWindow { StyledPopupWindow {
@ -29,7 +30,8 @@ StyledPopupWindow {
} }
Switch { Switch {
checked: Bluetooth.defaultAdapter.enabled checkable: !!Bluetooth.defaultAdapter
checked: Bluetooth.defaultAdapter?.enabled ?? false
onClicked: Bluetooth.defaultAdapter.enabled = checked onClicked: Bluetooth.defaultAdapter.enabled = checked
} }
} }
@ -41,7 +43,8 @@ StyledPopupWindow {
} }
Switch { Switch {
checked: Bluetooth.defaultAdapter.discovering checkable: !!Bluetooth.defaultAdapter
checked: Bluetooth.defaultAdapter?.discovering ?? false
onClicked: Bluetooth.defaultAdapter.discovering = checked onClicked: Bluetooth.defaultAdapter.discovering = checked
} }
} }
@ -63,26 +66,29 @@ StyledPopupWindow {
text: "Connected Devices" text: "Connected Devices"
} }
ColumnLayout { StyledListView {
Loader { id: list1
active: Bluetooth.connectedDevices.length == 0 Layout.fillWidth: true
sourceComponent: StyledText { spacing: 8
font.italic: true implicitHeight: 20 + Math.min(40 * count, 160)
text: "No devices connected..." header: Loader {
} active: list1.count == 0
} sourceComponent: Loader {
Repeater { active: list1.count == 0
model: Bluetooth.connectedDevices sourceComponent: StyledText {
delegate: Loader { font.italic: true
id: connectedDeviceLoader text: "No devices connected..."
required property var modelData
Layout.fillWidth: true
active: modelData != null
sourceComponent: ConnectedDevice {
device: connectedDeviceLoader.modelData
} }
} }
} }
clip: true
model: ScriptModel {
values: Bluetooth.devices.values.filter(device => device.state == BluetoothDeviceState.Connected)
}
delegate: ConnectedDevice {
anchors.left: parent.left
anchors.right: parent.right
}
} }
StyledText { StyledText {
@ -92,25 +98,25 @@ StyledPopupWindow {
text: "Paired Devices" text: "Paired Devices"
} }
ColumnLayout { StyledListView {
Loader { id: list2
active: Bluetooth.availableDevices.length == 0 Layout.fillWidth: true
spacing: 8
implicitHeight: 20 + Math.min(40 * count, 160)
header: Loader {
active: list2.count == 0
sourceComponent: StyledText { sourceComponent: StyledText {
font.italic: true font.italic: true
text: "No paired devices..." text: "No paired devices..."
} }
} }
Repeater { clip: true
model: Bluetooth.pairedDevices model: ScriptModel {
delegate: Loader { values: Bluetooth.defaultAdapter.devices.values.filter(device => device.bonded && device.state == BluetoothDeviceState.Disconnected)
id: pairedDeviceLoader }
required property var modelData delegate: PairedDevice {
Layout.fillWidth: true anchors.left: parent.left
active: modelData != null anchors.right: parent.right
sourceComponent: PairedDevice {
device: pairedDeviceLoader.modelData
}
}
} }
} }
@ -121,25 +127,25 @@ StyledPopupWindow {
text: "Available Devices" text: "Available Devices"
} }
ColumnLayout { StyledListView {
Loader { id: list3
active: Bluetooth.availableDevices.length == 0 Layout.fillWidth: true
spacing: 8
clip: true
implicitHeight: 20 + Math.min(40 * count, 160)
header: Loader {
active: list3.count == 0
sourceComponent: StyledText { sourceComponent: StyledText {
font.italic: true font.italic: true
text: Bluetooth.defaultAdapter.discovering ? "No devices found..." : "Scan to find devices..." text: Bluetooth.defaultAdapter.discovering ? "No devices found..." : "Scan to find devices..."
} }
} }
Repeater { model: ScriptModel {
model: Bluetooth.availableDevices values: Bluetooth.devices.values.filter(device => !device.bonded && device.deviceName != "")
delegate: Loader { }
id: availableDeviceLoader delegate: AvailableDevice {
required property var modelData anchors.left: parent.left
Layout.fillWidth: true anchors.right: parent.right
active: modelData != null
sourceComponent: AvailableDevice {
device: availableDeviceLoader.modelData
}
}
} }
} }
} }

View file

@ -11,7 +11,7 @@ import Quickshell.Widgets
StyledLabel { StyledLabel {
id: root id: root
required property BluetoothDevice device required property BluetoothDevice modelData
RowLayout { RowLayout {
id: row id: row
@ -19,19 +19,19 @@ StyledLabel {
spacing: 8 spacing: 8
Loader { Loader {
active: root.device?.icon != undefined active: root.modelData?.icon != undefined
sourceComponent: IconImage { sourceComponent: IconImage {
implicitSize: 22 implicitSize: 22
source: Quickshell.iconPath(root.device.icon, "device-support-unknown-symbolic") source: Quickshell.iconPath(root.modelData.icon, "device-support-unknown-symbolic")
} }
} }
StyledText { StyledText {
text: root.device.deviceName text: root.modelData.deviceName
} }
Loader { Loader {
active: root.device.batteryAvailable active: root.modelData.batteryAvailable
sourceComponent: RowLayout { sourceComponent: RowLayout {
StyledText { StyledText {
id: icon id: icon
@ -42,11 +42,11 @@ StyledLabel {
states: [ states: [
State { State {
name: "full" name: "full"
when: root.device.battery > 0.66 when: root.modelData.battery > 0.66
}, },
State { State {
name: "medium" name: "medium"
when: root.device.battery > 0.33 when: root.modelData.battery > 0.33
PropertyChanges { PropertyChanges {
icon { icon {
text: Icons.batteryFull text: Icons.batteryFull
@ -55,7 +55,7 @@ StyledLabel {
}, },
State { State {
name: "low" name: "low"
when: root.device.battery > 0.10 when: root.modelData.battery > 0.10
PropertyChanges { PropertyChanges {
icon { icon {
text: Icons.batteryFull text: Icons.batteryFull
@ -64,7 +64,7 @@ StyledLabel {
}, },
State { State {
name: "critical" name: "critical"
when: root.device.battery > 0.10 when: root.modelData.battery > 0.10
PropertyChanges { PropertyChanges {
icon { icon {
text: Icons.batteryWarning text: Icons.batteryWarning
@ -85,10 +85,10 @@ StyledLabel {
font.pixelSize: 12 font.pixelSize: 12
} }
onClicked: { onClicked: {
if (root.device.state != BluetoothDeviceState.Connected) { if (root.modelData.state != BluetoothDeviceState.Connected) {
return; return;
} }
root.device.connected = false; root.modelData.connected = false;
} }
} }
} }

View file

@ -10,7 +10,7 @@ import Quickshell.Widgets
StyledLabel { StyledLabel {
id: root id: root
required property BluetoothDevice device required property BluetoothDevice modelData
RowLayout { RowLayout {
id: row id: row
@ -18,21 +18,21 @@ StyledLabel {
spacing: 8 spacing: 8
Loader { Loader {
active: root.device?.icon != undefined active: root.modelData?.icon != undefined
sourceComponent: IconImage { sourceComponent: IconImage {
implicitSize: 22 implicitSize: 22
source: Quickshell.iconPath(root.device.icon, "device-support-unknown-symbolic") source: Quickshell.iconPath(root.modelData.icon, "device-support-unknown-symbolic")
} }
} }
StyledText { StyledText {
text: root.device.deviceName text: root.modelData.deviceName
} }
RowLayout { RowLayout {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
StyledButton { StyledButton {
hoverEnabled: root.device.state == BluetoothDeviceState.Disconnected hoverEnabled: root.modelData.state == BluetoothDeviceState.Disconnected
color: containsMouse ? Theme.palette.primary : Theme.palette.base200 color: containsMouse ? Theme.palette.primary : Theme.palette.base200
content: StyledText { content: StyledText {
text: 'Connect' text: 'Connect'
@ -42,12 +42,12 @@ StyledLabel {
if (!hoverEnabled) { if (!hoverEnabled) {
return; return;
} }
root.device.connect(); root.modelData.connect();
} }
} }
StyledButton { StyledButton {
hoverEnabled: root.device.state == BluetoothDeviceState.Disconnected hoverEnabled: root.modelData.state == BluetoothDeviceState.Disconnected
color: containsMouse ? Theme.palette.error : Theme.palette.base200 color: containsMouse ? Theme.palette.error : Theme.palette.base200
content: StyledText { content: StyledText {
text: 'Unpair' text: 'Unpair'
@ -57,7 +57,7 @@ StyledLabel {
if (!hoverEnabled) { if (!hoverEnabled) {
return; return;
} }
root.device.forget(); root.modelData.forget();
} }
} }
} }

View file

@ -1,22 +0,0 @@
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Bluetooth
Singleton {
id: root
property BluetoothAdapter defaultAdapter: Bluetooth.defaultAdapter
property list<BluetoothDevice> connectedDevices: defaultAdapter?.devices.values.filter(device => device.state == BluetoothDeviceState.Connected)
property list<BluetoothDevice> pairedDevices: defaultAdapter?.devices.values.filter(device => device.bonded && device.state == BluetoothDeviceState.Disconnected)
property list<BluetoothDevice> 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;
}
}

View file

@ -0,0 +1,16 @@
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]
}
}
}