-
-
Notifications
You must be signed in to change notification settings - Fork 42
/
Copy pathbluetooth.py
152 lines (134 loc) · 5.95 KB
/
bluetooth.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
from fabric.widgets.box import Box
from fabric.widgets.label import Label
from fabric.widgets.image import Image
from fabric.widgets.button import Button
from fabric.widgets.centerbox import CenterBox
from fabric.widgets.scrolledwindow import ScrolledWindow
from fabric.bluetooth import BluetoothClient, BluetoothDevice
import modules.icons as icons
class BluetoothDeviceSlot(CenterBox):
def __init__(self, device: BluetoothDevice, **kwargs):
super().__init__(name="bluetooth-device", **kwargs)
self.device = device
self.device.connect("changed", self.on_changed)
self.device.connect(
"notify::closed", lambda *_: self.device.closed and self.destroy()
)
self.connection_label = Label(name="bluetooth-connection", markup=icons.bluetooth_disconnected)
self.connect_button = Button(
name="bluetooth-connect",
label="Connect",
on_clicked=lambda *_: self.device.set_connecting(not self.device.connected),
)
self.start_children = [
Box(
spacing=8,
children=[
Image(icon_name=device.icon_name + "-symbolic", size=32),
Label(label=device.name),
self.connection_label,
],
)
]
self.end_children = self.connect_button
self.device.emit("changed") # to update display status
def on_changed(self, *_):
self.connection_label.set_markup(
icons.bluetooth_connected if self.device.connected else icons.bluetooth_disconnected
)
if self.device.connecting:
self.connect_button.set_label(
"Connecting..." if not self.device.connecting else "Disconnecting..."
)
else:
self.connect_button.set_label(
"Connect" if not self.device.connected else "Disconnect"
)
return
class BluetoothConnections(Box):
def __init__(self, **kwargs):
super().__init__(
name="bluetooth",
spacing=4,
orientation="vertical",
**kwargs,
)
self.widgets = kwargs["widgets"]
self.buttons = self.widgets.buttons.bluetooth_button
self.bt_status_text = self.buttons.bluetooth_status_text
self.bt_status_button = self.buttons.bluetooth_status_button
self.bt_icon = self.buttons.bluetooth_icon
self.bt_label = self.buttons.bluetooth_label
self.bt_menu_button = self.buttons.bluetooth_menu_button
self.bt_menu_label = self.buttons.bluetooth_menu_label
self.client = BluetoothClient(on_device_added=self.on_device_added)
self.scan_label = Label(name="bluetooth-scan-label", markup=icons.radar)
self.scan_button = Button(
name="bluetooth-scan",
child=self.scan_label,
tooltip_text="Scan for Bluetooth devices",
on_clicked=lambda *_: self.client.toggle_scan()
)
self.back_button = Button(
name="bluetooth-back",
child=Label(name="bluetooth-back-label", markup=icons.chevron_left),
on_clicked=lambda *_: self.widgets.show_notif()
)
self.client.connect("notify::enabled", lambda *_: self.status_label())
self.client.connect(
"notify::scanning",
lambda *_: self.update_scan_label()
)
self.paired_box = Box(spacing=2, orientation="vertical")
self.available_box = Box(spacing=2, orientation="vertical")
# Create a single content container with the required structure:
# [Paired label] [Paired devices list] [Available label] [Available devices list]
content_box = Box(spacing=4, orientation="vertical")
content_box.add(self.paired_box)
content_box.add(Label(name="bluetooth-section", label="Available"))
content_box.add(self.available_box)
self.children = [
CenterBox(
name="bluetooth-header",
start_children=self.back_button,
center_children=Label(name="bluetooth-text", label="Bluetooth Devices"),
end_children=self.scan_button
),
ScrolledWindow(
name="bluetooth-devices",
min_content_size=(-1, -1),
child=content_box,
v_expand=True
),
]
# Trigger initial notifications to update status without delay.
self.client.notify("scanning")
self.client.notify("enabled")
def status_label(self):
print(self.client.enabled)
if self.client.enabled:
self.bt_status_text.set_label("Enabled")
for i in [self.bt_status_button, self.bt_status_text, self.bt_icon, self.bt_label, self.bt_menu_button, self.bt_menu_label]:
i.remove_style_class("disabled")
self.bt_icon.set_markup(icons.bluetooth)
else:
self.bt_status_text.set_label("Disabled")
for i in [self.bt_status_button, self.bt_status_text, self.bt_icon, self.bt_label, self.bt_menu_button, self.bt_menu_label]:
i.add_style_class("disabled")
self.bt_icon.set_markup(icons.bluetooth_off)
def on_device_added(self, client: BluetoothClient, address: str):
if not (device := client.get_device(address)):
return
slot = BluetoothDeviceSlot(device)
if device.paired:
return self.paired_box.add(slot)
return self.available_box.add(slot)
def update_scan_label(self):
if self.client.scanning:
self.scan_label.add_style_class("scanning")
self.scan_button.add_style_class("scanning")
self.scan_button.set_tooltip_text("Stop scanning for Bluetooth devices")
else:
self.scan_label.remove_style_class("scanning")
self.scan_button.remove_style_class("scanning")
self.scan_button.set_tooltip_text("Scan for Bluetooth devices")