Skip to content

Commit 31590b1

Browse files
committed
rework override to be compatible with any version
that has an 'explanation-label' buildable id
1 parent 9dfa198 commit 31590b1

File tree

1 file changed

+92
-38
lines changed

1 file changed

+92
-38
lines changed

usr/lib/blueberry/blueberry.py

Lines changed: 92 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import gi
1010
gi.require_version('Gtk', '3.0')
1111
gi.require_version('GnomeBluetooth', '1.0')
12-
from gi.repository import Gtk, GnomeBluetooth, Gio
12+
from gi.repository import Gtk, GnomeBluetooth, Gio, GLib
13+
14+
APPLICATION_ID = 'com.linuxmint.blueberry'
1315

1416
BLUETOOTH_RFKILL_ERR = "rfkill-err"
1517
BLUETOOTH_DISABLED_PAGE = "disabled-page"
@@ -22,11 +24,79 @@
2224

2325
setproctitle.setproctitle("blueberry")
2426

27+
# similar to g_warning by default, can specify any log level though
28+
def log(text, log_level=GLib.LogLevelFlags.LEVEL_WARNING):
29+
variant = GLib.Variant("a{sv}", { "MESSAGE": GLib.Variant("s", text) })
30+
GLib.log_variant(APPLICATION_ID, log_level, variant)
31+
32+
# searches a widget and its children for a specific buildable id or widget type
33+
# note: stops at first match
34+
def find_widget(parent, name="", widgetClass=None):
35+
p_name = Gtk.Buildable.get_name(parent)
36+
if p_name and name and p_name.strip() == name.strip():
37+
return parent
38+
39+
if widgetClass and isinstance(parent, widgetClass):
40+
return parent
41+
42+
if hasattr(parent, "get_children"):
43+
children = parent.get_children()
44+
for child in children:
45+
res = find_widget(child, name, widgetClass)
46+
if res is not None:
47+
return res
48+
49+
return None
50+
51+
# We attempt to override the widget style to replace
52+
# the explanation label text and stop the spinner.
53+
# gnome_bluetooth_settings_widget doesn't give explicit access
54+
# to its label via gi so we recurse its child widgets to try
55+
# to find the parts we want to modify.
56+
57+
# if the override fails for any reason it is disabled. update
58+
# signals in the main class are only connected if a test call
59+
# to this succeeds the first time
60+
override_failed = False
61+
62+
def apply_widget_override(widget, adapter_name, obex_enabled):
63+
global override_failed
64+
if override_failed:
65+
return False
66+
67+
try:
68+
# not finding the label is fatal as it's our main purpose here
69+
label = find_widget(widget, "explanation-label")
70+
if label is None:
71+
raise LookupError("unable to find label to override")
72+
73+
# not finding the spinner is non-fatal
74+
spinner = find_widget(widget, widgetClass=Gtk.Spinner)
75+
if spinner and spinner.props.active:
76+
spinner.stop()
77+
78+
if adapter_name is not None:
79+
if obex_enabled:
80+
text = _("Visible as %s and available for Bluetooth file transfers.")
81+
else:
82+
text = _("Visible as %s.")
83+
text = "%s\n" % text
84+
label.set_markup(text % "\"%s\"" % adapter_name)
85+
else:
86+
label.set_label("")
87+
88+
except Exception as e:
89+
log("apply_widget_override failed: {}".format(e))
90+
override_failed = True
91+
return False
92+
93+
return True
94+
95+
2596
class Blueberry(Gtk.Application):
2697
''' Create the UI '''
2798
def __init__(self):
28-
29-
Gtk.Application.__init__(self, application_id='com.linuxmint.blueberry', flags=Gio.ApplicationFlags.FLAGS_NONE)
99+
Gtk.Application.__init__(self, application_id=APPLICATION_ID, flags=Gio.ApplicationFlags.FLAGS_NONE)
30100
self.window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
31101
self.detect_desktop_environment()
32102
self.connect("activate", self.on_activate)
@@ -70,7 +140,7 @@ def detect_desktop_environment(self):
70140
self.configuration_tools = {"sound": "pavucontrol", "keyboard": "lxinput", "mouse": "lxinput"}
71141
else:
72142
self.de = "Unknown"
73-
print("Warning: DE could not be detected!")
143+
log("DE could not be detected!")
74144
self.configuration_tools = {}
75145
if os.path.exists("/usr/bin/pavucontrol"):
76146
self.configuration_tools["sound"] = "pavucontrol"
@@ -188,16 +258,20 @@ def create_window(self):
188258
self.add_window(self.window)
189259
self.window.show_all()
190260

191-
self.client = GnomeBluetooth.Client()
192-
self.model = self.client.get_model()
193-
self.model.connect('row-changed', self.update_status)
194-
self.model.connect('row-deleted', self.update_status)
195-
self.model.connect('row-inserted', self.update_status)
196-
self.update_status()
261+
# attempt to apply overrides and if we fail don't setup update hooks
262+
name = self.get_default_adapter_name()
263+
obex_enabled = self.settings.get_boolean("obex-enabled")
264+
if apply_widget_override(self.lib_widget, name, obex_enabled):
265+
self.client = GnomeBluetooth.Client()
266+
self.model = self.client.get_model()
267+
self.model.connect('row-changed', self.update_status)
268+
self.model.connect('row-deleted', self.update_status)
269+
self.model.connect('row-inserted', self.update_status)
270+
self.update_status()
197271

198272
def panel_changed(self, widget, panel):
199273
if not panel in self.configuration_tools:
200-
print("Warning, no configuration tool known for panel '%s'" % panel)
274+
log("No configuration tool known for panel '{}'".format(panel))
201275
else:
202276
os.system("%s &" % self.configuration_tools[panel])
203277

@@ -241,36 +315,16 @@ def get_default_adapter_name(self):
241315
name = line.replace("Alias: ", "").replace(" [rw]", "").replace(" [ro]", "")
242316
break
243317
except Exception as cause:
244-
print ("Could not retrieve the BT adapter name with 'bt-adapter -i': %s" % cause)
318+
log("Could not retrieve the BT adapter name with 'bt-adapter -i': {}".format(cause))
245319
return name
246320

247321
def update_status(self, path=None, iter=None, data=None):
248-
try:
249-
# In version 3.18, gnome_bluetooth_settings_widget
250-
# doesn't give explicit access to its label via gi
251-
# but it's a composite widget and its hierarchy is:
252-
# scrolledwindow -> viewport -> vbox -> explanation-label
253-
scrolledwindow = self.lib_widget.get_children()[0]
254-
scrolledwindow.set_shadow_type(Gtk.ShadowType.NONE)
255-
viewport = scrolledwindow.get_children()[0]
256-
vbox = viewport.get_children()[0]
257-
spinner = vbox.get_children()[1].get_children()[0].get_children()[1]
258-
if spinner.props.active:
259-
spinner.stop()
260-
explanation_label = vbox.get_children()[0]
261-
name = self.get_default_adapter_name()
262-
if name is not None:
263-
if self.settings.get_boolean('obex-enabled'):
264-
text = _("Visible as %s and available for Bluetooth file transfers.")
265-
else:
266-
text = _("Visible as %s.")
267-
text = "%s\n" % text
268-
explanation_label.set_markup(text % "\"%s\"" % name)
269-
else:
270-
explanation_label.set_label("")
271-
except Exception as e:
272-
print(e)
273-
return None
322+
if override_failed:
323+
return
324+
325+
name = self.get_default_adapter_name()
326+
obex_enabled = self.settings.get_boolean("obex-enabled")
327+
apply_widget_override(self.lib_widget, name, obex_enabled)
274328

275329
def update_ui_callback(self):
276330
powered = False

0 commit comments

Comments
 (0)