Merge lp:~robert-ancell/indicator-bluetooth/dont-hide-on-rfkill into lp:indicator-bluetooth/14.04
- dont-hide-on-rfkill
- Merge into trunk.14.04
Proposed by
Sir Charlemagne
Status: | Work in progress |
---|---|
Proposed branch: | lp:~robert-ancell/indicator-bluetooth/dont-hide-on-rfkill |
Merge into: | lp:indicator-bluetooth/14.04 |
Diff against target: |
427 lines (+411/-0) (has conflicts) 1 file modified
src/service.vala (+411/-0) Text conflict in src/service.vala |
To merge this branch: | bzr merge lp:~robert-ancell/indicator-bluetooth/dont-hide-on-rfkill |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Charles Kerr (community) | Needs Fixing | ||
Review via email: mp+197346@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Unmerged revisions
- 51. By Robert Ancell
-
Show the bluetooth indicator if bluetooth is disabled - assume there are devices present
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/service.vala' |
2 | --- src/service.vala 2013-08-09 23:18:59 +0000 |
3 | +++ src/service.vala 2013-12-02 11:30:31 +0000 |
4 | @@ -18,6 +18,7 @@ |
5 | * Robert Ancell <robert.ancell@canonical.com> |
6 | */ |
7 | |
8 | +<<<<<<< TREE |
9 | /** |
10 | * Boilerplate class to own the name on the bus, |
11 | * to create the profiles, and to export them on the bus. |
12 | @@ -61,6 +62,416 @@ |
13 | if (loop != null) |
14 | { |
15 | warning ("service is already running"); |
16 | +======= |
17 | +public class BluetoothIndicator |
18 | +{ |
19 | + private Settings settings; |
20 | + private DBusConnection bus; |
21 | + private Indicator.Service indicator_service; |
22 | + private Dbusmenu.Server menu_server; |
23 | + private BluetoothService bluetooth_service; |
24 | + private GnomeBluetooth.Client client; |
25 | + private GnomeBluetooth.Killswitch killswitch; |
26 | + private bool updating_killswitch = false; |
27 | + private Dbusmenu.Menuitem enable_item; |
28 | + private Dbusmenu.Menuitem visible_item; |
29 | + private bool updating_visible = false; |
30 | + private Dbusmenu.Menuitem devices_separator; |
31 | + private List<BluetoothMenuItem> device_items; |
32 | + private Dbusmenu.Menuitem menu; |
33 | + |
34 | + public BluetoothIndicator () throws Error |
35 | + { |
36 | + settings = new Settings ("com.canonical.indicator.bluetooth"); |
37 | + settings.changed.connect ((key) => |
38 | + { |
39 | + if (key == "visible") |
40 | + update_visible (); |
41 | + }); |
42 | + |
43 | + bus = Bus.get_sync (BusType.SESSION); |
44 | + |
45 | + indicator_service = new Indicator.Service ("com.canonical.indicator.bluetooth"); |
46 | + menu_server = new Dbusmenu.Server ("/com/canonical/indicator/bluetooth/menu"); |
47 | + |
48 | + bluetooth_service = new BluetoothService (); |
49 | + bus.register_object ("/com/canonical/indicator/bluetooth/service", bluetooth_service); |
50 | + |
51 | + killswitch = new GnomeBluetooth.Killswitch (); |
52 | + killswitch.state_changed.connect (killswitch_state_changed_cb); |
53 | + |
54 | + client = new GnomeBluetooth.Client (); |
55 | + |
56 | + menu = new Dbusmenu.Menuitem (); |
57 | + menu_server.set_root (menu); |
58 | + |
59 | + enable_item = new Dbusmenu.Menuitem (); |
60 | + enable_item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, _("Bluetooth")); |
61 | + enable_item.property_set (Dbusmenu.MENUITEM_PROP_TYPE, "x-canonical-switch"); |
62 | + enable_item.item_activated.connect (() => |
63 | + { |
64 | + if (updating_killswitch) |
65 | + return; |
66 | + if (killswitch.state == GnomeBluetooth.KillswitchState.UNBLOCKED) |
67 | + killswitch.state = GnomeBluetooth.KillswitchState.SOFT_BLOCKED; |
68 | + else |
69 | + killswitch.state = GnomeBluetooth.KillswitchState.UNBLOCKED; |
70 | + }); |
71 | + menu.child_append (enable_item); |
72 | + |
73 | + visible_item = new Dbusmenu.Menuitem (); |
74 | + visible_item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, _("Visible")); |
75 | + visible_item.property_set (Dbusmenu.MENUITEM_PROP_TYPE, "x-canonical-switch"); |
76 | + bool discoverable; |
77 | + client.get ("default-adapter-discoverable", out discoverable); |
78 | + visible_item.property_set_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE, discoverable ? Dbusmenu.MENUITEM_TOGGLE_STATE_CHECKED : Dbusmenu.MENUITEM_TOGGLE_STATE_UNCHECKED); |
79 | + client.notify["default-adapter-discoverable"].connect (() => |
80 | + { |
81 | + updating_visible = true; |
82 | + bool is_discoverable; |
83 | + client.get ("default-adapter-discoverable", out is_discoverable); |
84 | + visible_item.property_set_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE, is_discoverable ? Dbusmenu.MENUITEM_TOGGLE_STATE_CHECKED : Dbusmenu.MENUITEM_TOGGLE_STATE_UNCHECKED); |
85 | + updating_visible = false; |
86 | + }); |
87 | + visible_item.item_activated.connect (() => |
88 | + { |
89 | + if (updating_visible) |
90 | + return; |
91 | + client.set ("default-adapter-discoverable", visible_item.property_get_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE) != Dbusmenu.MENUITEM_TOGGLE_STATE_CHECKED); |
92 | + }); |
93 | + menu.child_append (visible_item); |
94 | + |
95 | + devices_separator = new Dbusmenu.Menuitem (); |
96 | + devices_separator.property_set (Dbusmenu.MENUITEM_PROP_TYPE, Dbusmenu.CLIENT_TYPES_SEPARATOR); |
97 | + menu.child_append (devices_separator); |
98 | + |
99 | + device_items = new List<BluetoothMenuItem> (); |
100 | + |
101 | + client.model.row_inserted.connect (device_changed_cb); |
102 | + client.model.row_changed.connect (device_changed_cb); |
103 | + client.model.row_deleted.connect (device_removed_cb); |
104 | + Gtk.TreeIter iter; |
105 | + var have_iter = client.model.get_iter_first (out iter); |
106 | + while (have_iter) |
107 | + { |
108 | + Gtk.TreeIter child_iter; |
109 | + var have_child_iter = client.model.iter_children (out child_iter, iter); |
110 | + while (have_child_iter) |
111 | + { |
112 | + device_changed_cb (null, child_iter); |
113 | + have_child_iter = client.model.iter_next (ref child_iter); |
114 | + } |
115 | + have_iter = client.model.iter_next (ref iter); |
116 | + } |
117 | + |
118 | + var sep = new Dbusmenu.Menuitem (); |
119 | + sep.property_set (Dbusmenu.MENUITEM_PROP_TYPE, Dbusmenu.CLIENT_TYPES_SEPARATOR); |
120 | + menu.child_append (sep); |
121 | + |
122 | + var item = new Dbusmenu.Menuitem (); |
123 | + item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, _("Set Up New Device…")); |
124 | + item.item_activated.connect (() => { set_up_new_device (); }); |
125 | + menu.child_append (item); |
126 | + |
127 | + item = new Dbusmenu.Menuitem (); |
128 | + item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, _("Bluetooth Settings…")); |
129 | + item.item_activated.connect (() => { show_control_center ("bluetooth"); }); |
130 | + menu.child_append (item); |
131 | + |
132 | + killswitch_state_changed_cb (killswitch.state); |
133 | + |
134 | + client.adapter_model.row_inserted.connect (update_visible); |
135 | + client.adapter_model.row_deleted.connect (update_visible); |
136 | + update_visible (); |
137 | + } |
138 | + |
139 | + private BluetoothMenuItem? find_menu_item (string address) |
140 | + { |
141 | + foreach (var item in device_items) |
142 | + if (item.address == address) |
143 | + return item; |
144 | + |
145 | + return null; |
146 | + } |
147 | + |
148 | + private void device_changed_cb (Gtk.TreePath? path, Gtk.TreeIter iter) |
149 | + { |
150 | + /* Ignore adapters */ |
151 | + Gtk.TreeIter parent_iter; |
152 | + if (!client.model.iter_parent (out parent_iter, iter)) |
153 | + return; |
154 | + |
155 | + DBusProxy proxy; |
156 | + string address; |
157 | + string alias; |
158 | + GnomeBluetooth.Type type; |
159 | + string icon; |
160 | + bool connected; |
161 | + HashTable services; |
162 | + string[] uuids; |
163 | + client.model.get (iter, |
164 | + GnomeBluetooth.Column.PROXY, out proxy, |
165 | + GnomeBluetooth.Column.ADDRESS, out address, |
166 | + GnomeBluetooth.Column.ALIAS, out alias, |
167 | + GnomeBluetooth.Column.TYPE, out type, |
168 | + GnomeBluetooth.Column.ICON, out icon, |
169 | + GnomeBluetooth.Column.CONNECTED, out connected, |
170 | + GnomeBluetooth.Column.SERVICES, out services, |
171 | + GnomeBluetooth.Column.UUIDS, out uuids); |
172 | + |
173 | + /* Skip if haven't actually got any information yet */ |
174 | + if (proxy == null) |
175 | + return; |
176 | + |
177 | + /* Find or create menu item */ |
178 | + var item = find_menu_item (address); |
179 | + if (item == null) |
180 | + { |
181 | + item = new BluetoothMenuItem (client, address); |
182 | + item.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, killswitch.state == GnomeBluetooth.KillswitchState.UNBLOCKED); |
183 | + var last_item = devices_separator as Dbusmenu.Menuitem; |
184 | + if (device_items != null) |
185 | + last_item = device_items.last ().data; |
186 | + device_items.append (item); |
187 | + menu.child_add_position (item, last_item.get_position (menu) + 1); |
188 | + } |
189 | + |
190 | + item.update (type, proxy, alias, icon, connected, services, uuids); |
191 | + } |
192 | + |
193 | + private void update_visible () |
194 | + { |
195 | + /* Show if: |
196 | + * - There are bluetooth devices |
197 | + * - Bluetooth is disabled (for some hardware this means there are no devices reported but we should assume there are if it is disabled) |
198 | + * - It has been enabled in settings |
199 | + */ |
200 | + bluetooth_service._visible = (client.adapter_model.iter_n_children (null) > 0 || killswitch.state != GnomeBluetooth.KillswitchState.UNBLOCKED) && settings.get_boolean ("visible"); |
201 | + var builder = new VariantBuilder (VariantType.ARRAY); |
202 | + builder.add ("{sv}", "Visible", new Variant.boolean (bluetooth_service._visible)); |
203 | + try |
204 | + { |
205 | + var properties = new Variant ("(sa{sv}as)", "com.canonical.indicator.bluetooth.service", builder, null); |
206 | + bus.emit_signal (null, |
207 | + "/com/canonical/indicator/bluetooth/service", |
208 | + "org.freedesktop.DBus.Properties", |
209 | + "PropertiesChanged", |
210 | + properties); |
211 | + } |
212 | + catch (Error e) |
213 | + { |
214 | + warning ("Failed to emit signal: %s", e.message); |
215 | + } |
216 | + } |
217 | + |
218 | + private void device_removed_cb (Gtk.TreePath path) |
219 | + { |
220 | + Gtk.TreeIter iter; |
221 | + if (!client.model.get_iter (out iter, path)) |
222 | + return; |
223 | + |
224 | + string address; |
225 | + client.model.get (iter, GnomeBluetooth.Column.ADDRESS, out address); |
226 | + |
227 | + var item = find_menu_item (address); |
228 | + if (item == null) |
229 | + return; |
230 | + |
231 | + device_items.remove (item); |
232 | + menu.child_delete (item); |
233 | + } |
234 | + |
235 | + private void killswitch_state_changed_cb (GnomeBluetooth.KillswitchState state) |
236 | + { |
237 | + updating_killswitch = true; |
238 | + |
239 | + var enabled = state == GnomeBluetooth.KillswitchState.UNBLOCKED; |
240 | + |
241 | + bluetooth_service._icon_name = enabled ? "bluetooth-active" : "bluetooth-disabled"; |
242 | + bluetooth_service._accessible_description = enabled ? _("Bluetooth: On") : _("Bluetooth: Off"); |
243 | + |
244 | + var builder = new VariantBuilder (VariantType.ARRAY); |
245 | + builder.add ("{sv}", "IconName", new Variant.string (bluetooth_service._icon_name)); |
246 | + builder.add ("{sv}", "AccessibleDescription", new Variant.string (bluetooth_service._accessible_description)); |
247 | + try |
248 | + { |
249 | + var properties = new Variant ("(sa{sv}as)", "com.canonical.indicator.bluetooth.service", builder, null); |
250 | + bus.emit_signal (null, |
251 | + "/com/canonical/indicator/bluetooth/service", |
252 | + "org.freedesktop.DBus.Properties", |
253 | + "PropertiesChanged", |
254 | + properties); |
255 | + } |
256 | + catch (Error e) |
257 | + { |
258 | + warning ("Failed to emit signal: %s", e.message); |
259 | + } |
260 | + |
261 | + enable_item.property_set_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE, enabled ? Dbusmenu.MENUITEM_TOGGLE_STATE_CHECKED : Dbusmenu.MENUITEM_TOGGLE_STATE_UNCHECKED); |
262 | + |
263 | + /* Disable devices when locked */ |
264 | + visible_item.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, enabled); |
265 | + devices_separator.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, enabled); |
266 | + foreach (var item in device_items) |
267 | + item.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, enabled && item.get_children () != null); |
268 | + |
269 | + updating_killswitch = false; |
270 | + } |
271 | +} |
272 | + |
273 | +private class BluetoothMenuItem : Dbusmenu.Menuitem |
274 | +{ |
275 | + private GnomeBluetooth.Client client; |
276 | + public string address; |
277 | + private Dbusmenu.Menuitem? connect_item = null; |
278 | + private bool make_submenu = false; |
279 | + |
280 | + public BluetoothMenuItem (GnomeBluetooth.Client client, string address) |
281 | + { |
282 | + this.client = client; |
283 | + this.address = address; |
284 | + } |
285 | + |
286 | + public void update (GnomeBluetooth.Type type, DBusProxy proxy, string alias, string icon, bool connected, HashTable? services, string[] uuids) |
287 | + { |
288 | + property_set (Dbusmenu.MENUITEM_PROP_LABEL, alias); |
289 | + property_set (Dbusmenu.MENUITEM_PROP_ICON_NAME, icon); |
290 | + if (connect_item != null) |
291 | + connect_item.property_set_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE, connected ? Dbusmenu.MENUITEM_TOGGLE_STATE_CHECKED : Dbusmenu.MENUITEM_TOGGLE_STATE_UNCHECKED); |
292 | + |
293 | + /* FIXME: Not sure if the GUI elements below can change over time */ |
294 | + if (make_submenu) |
295 | + return; |
296 | + make_submenu = true; |
297 | + |
298 | + if (services != null) |
299 | + { |
300 | + connect_item = new Dbusmenu.Menuitem (); |
301 | + connect_item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, _("Connection")); |
302 | + connect_item.property_set (Dbusmenu.MENUITEM_PROP_TYPE, "x-canonical-switch"); |
303 | + connect_item.property_set_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE, connected ? Dbusmenu.MENUITEM_TOGGLE_STATE_CHECKED : Dbusmenu.MENUITEM_TOGGLE_STATE_UNCHECKED); |
304 | + connect_item.item_activated.connect (() => { connect_service (proxy.get_object_path (), connect_item.property_get_int (Dbusmenu.MENUITEM_PROP_TOGGLE_STATE) != Dbusmenu.MENUITEM_TOGGLE_STATE_CHECKED); }); |
305 | + child_append (connect_item); |
306 | + } |
307 | + |
308 | + var can_send = false; |
309 | + var can_browse = false; |
310 | + if (uuids != null) |
311 | + { |
312 | + for (var i = 0; uuids[i] != null; i++) |
313 | + { |
314 | + if (uuids[i] == "OBEXObjectPush") |
315 | + can_send = true; |
316 | + if (uuids[i] == "OBEXFileTransfer") |
317 | + can_browse = true; |
318 | + } |
319 | + } |
320 | + |
321 | + if (can_send) |
322 | + { |
323 | + var send_item = new Dbusmenu.Menuitem (); |
324 | + send_item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, _("Send files…")); |
325 | + send_item.item_activated.connect (() => { GnomeBluetooth.send_to_address (address, alias); }); |
326 | + child_append (send_item); |
327 | + } |
328 | + |
329 | + if (can_browse) |
330 | + { |
331 | + var browse_item = new Dbusmenu.Menuitem (); |
332 | + browse_item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, _("Browse files…")); |
333 | + browse_item.item_activated.connect (() => { GnomeBluetooth.browse_address (null, address, Gdk.CURRENT_TIME, null); }); |
334 | + child_append (browse_item); |
335 | + } |
336 | + |
337 | + switch (type) |
338 | + { |
339 | + case GnomeBluetooth.Type.KEYBOARD: |
340 | + var keyboard_item = new Dbusmenu.Menuitem (); |
341 | + keyboard_item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, _("Keyboard Settings…")); |
342 | + keyboard_item.item_activated.connect (() => { show_control_center ("keyboard"); }); |
343 | + child_append (keyboard_item); |
344 | + break; |
345 | + |
346 | + case GnomeBluetooth.Type.MOUSE: |
347 | + case GnomeBluetooth.Type.TABLET: |
348 | + var mouse_item = new Dbusmenu.Menuitem (); |
349 | + mouse_item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, _("Mouse and Touchpad Settings…")); |
350 | + mouse_item.item_activated.connect (() => { show_control_center ("mouse"); }); |
351 | + child_append (mouse_item); |
352 | + break; |
353 | + |
354 | + case GnomeBluetooth.Type.HEADSET: |
355 | + case GnomeBluetooth.Type.HEADPHONES: |
356 | + case GnomeBluetooth.Type.OTHER_AUDIO: |
357 | + var sound_item = new Dbusmenu.Menuitem (); |
358 | + sound_item.property_set (Dbusmenu.MENUITEM_PROP_LABEL, _("Sound Settings…")); |
359 | + sound_item.item_activated.connect (() => { show_control_center ("sound"); }); |
360 | + child_append (sound_item); |
361 | + break; |
362 | + } |
363 | + |
364 | + property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, get_children () != null); |
365 | + } |
366 | + |
367 | + private void connect_service (string device, bool connect) |
368 | + { |
369 | + client.connect_service.begin (device, connect, null, (object, result) => |
370 | + { |
371 | + var connected = false; |
372 | + try |
373 | + { |
374 | + connected = client.connect_service.end (result); |
375 | + } |
376 | + catch (Error e) |
377 | + { |
378 | + warning ("Failed to connect service: %s", e.message); |
379 | + } |
380 | + }); |
381 | + } |
382 | +} |
383 | + |
384 | +private void set_up_new_device () |
385 | +{ |
386 | + try |
387 | + { |
388 | + Process.spawn_command_line_async ("bluetooth-wizard"); |
389 | + } |
390 | + catch (GLib.SpawnError e) |
391 | + { |
392 | + warning ("Failed to open bluetooth-wizard: %s", e.message); |
393 | + } |
394 | +} |
395 | + |
396 | +private void show_control_center (string panel) |
397 | +{ |
398 | + try |
399 | + { |
400 | + Process.spawn_command_line_async ("gnome-control-center %s".printf (panel)); |
401 | + } |
402 | + catch (GLib.SpawnError e) |
403 | + { |
404 | + warning ("Failed to open control center: %s", e.message); |
405 | + } |
406 | +} |
407 | + |
408 | +public static int main (string[] args) |
409 | +{ |
410 | + Intl.setlocale (LocaleCategory.ALL, ""); |
411 | + Intl.bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); |
412 | + Intl.bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); |
413 | + Intl.textdomain (GETTEXT_PACKAGE); |
414 | + |
415 | + var loop = new MainLoop (); |
416 | + |
417 | + BluetoothIndicator indicator; |
418 | + try |
419 | + { |
420 | + indicator = new BluetoothIndicator (); |
421 | + } |
422 | + catch (Error e) |
423 | + { |
424 | + warning ("Failed to start bluetooth indicator service: %s", e.message); |
425 | +>>>>>>> MERGE-SOURCE |
426 | return Posix.EXIT_FAILURE; |
427 | } |
428 |
This MR has conflicts with trunk and appears to reintroduce a Gnome dependency, even on the phone...?