Merge lp:~robert-ancell/indicator-bluetooth/dont-hide-on-rfkill into lp:indicator-bluetooth/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
Reviewer Review Type Date Requested Status
Charles Kerr (community) Needs Fixing
Review via email: mp+197346@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Charles Kerr (charlesk) wrote :

This MR has conflicts with trunk and appears to reintroduce a Gnome dependency, even on the phone...?

review: Needs Fixing

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

Subscribers

People subscribed via source and target branches