Merge lp:~robert-ancell/indicator-bluetooth/dont-hide-on-rfkill into lp:indicator-bluetooth/14.04

Proposed by Sir Charlemagne on 2013-12-02
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) 2013-12-02 Needs Fixing on 2013-12-06
Review via email: mp+197346@code.launchpad.net
To post a comment you must log in.
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 on 2013-04-01

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

Subscribers

People subscribed via source and target branches