class GsmSettings(Gtk.Dialog): def __init__(self, bd_address): super(GsmSettings, self).__init__() self.set_name("GsmSettings") self.device = bd_address self.Builder = Gtk.Builder() self.Builder.set_translation_domain("blueman") bind_textdomain_codeset("blueman", "UTF-8") self.Builder.add_from_file(UI_PATH + "/gsm-settings.ui") gsm_grid = self.Builder.get_object("gsm_grid") self.config = Config("org.blueman.gsmsetting", "/org/blueman/gsmsettings/%s/" % bd_address) self.props.icon_name = "network-wireless" self.props.title = _("GSM Settings") self.props.resizable = False a = self.get_content_area() a.pack_start(gsm_grid, True, True, 0) gsm_grid.show() self.e_apn = self.Builder.get_object("e_apn") self.e_number = self.Builder.get_object("e_number") self.config.bind_to_widget("apn", self.e_apn, "text") self.config.bind_to_widget("number", self.e_number, "text") self.add_button("_Close", Gtk.ResponseType.CLOSE)
class Networking(AppletPlugin): __icon__ = "network" __description__ = _("Manages local network services, like NAP bridges") __author__ = "Walmis" _signal = None def on_load(self, applet): self.Applet = applet self.Config = Config("org.blueman.network") self.Config.connect("changed", self.on_config_changed) self.load_nap_settings() def on_manager_state_changed(self, state): if state: self.update_status() def load_nap_settings(self): dprint("Loading NAP settings") def reply(): pass def err(excp): d = NetworkErrorDialog(excp, "You might not be able to connect to the Bluetooth network via this machine") d.expander.props.margin_left = 9 d.run() d.destroy() m = Mechanism() m.ReloadNetwork(reply_handler=reply, error_handler=err) def on_unload(self): del self.Config def on_adapter_added(self, path): self.update_status() def update_status(self): self.set_nap(self.Config["nap-enable"]) def on_config_changed(self, config, key): if key == "nap-enable": self.set_nap(config[key]) def set_nap(self, on): dprint("set nap", on) if self.Applet.Manager != None: adapters = self.Applet.Manager.list_adapters() for adapter in adapters: s = NetworkServer(adapter.get_object_path()) if on: s.register("nap", "pan1") else: s.unregister("nap")
class PersistentPluginManager(PluginManager): def __init__(self, *args): super(PersistentPluginManager, self).__init__(*args) self.__config = Config("org.blueman.general") self.__config.connect("changed::plugin-list", self.on_property_changed) def disable_plugin(self, plugin): plugins = self.__config["plugin-list"] return "!" + plugin in plugins def enable_plugin(self, plugin): plugins = self.__config["plugin-list"] return plugin in plugins def set_config(self, plugin, state): plugins = self.__config["plugin-list"] if plugin in plugins: plugins.remove(plugin) elif "!" + plugin in plugins: plugins.remove("!" + plugin) plugins.append(str("!" + plugin) if not state else str(plugin)) self.__config["plugin-list"] = plugins @property def config_list(self): return self.__config["plugin-list"] def on_property_changed(self, config, key): for item in config[key]: disable = item.startswith("!") if disable: item = item.lstrip("!") try: cls = self.get_classes()[item] if not cls.__unloadable__ and disable: logging.warning("warning: %s is not unloadable" % item) elif item in self.get_loaded() and disable: self.unload_plugin(item) elif item not in self.get_loaded() and not disable: try: self.load_plugin(item, user_action=True) except Exception as e: logging.exception(e) self.set_config(item, False) except KeyError: logging.warning("warning: Plugin %s not found" % item) continue
class PersistentPluginManager(PluginManager): def __init__(self, *args): super(PersistentPluginManager, self).__init__(*args) self.__config = Config("org.blueman.general") self.__config.connect("changed::plugin-list", self.on_property_changed) def Disabled(self, plugin): plugins = self.__config["plugin-list"] return "!" + plugin in plugins def Enabled(self, plugin): plugins = self.__config["plugin-list"] return plugin in plugins def SetConfig(self, plugin, state): plugins = self.__config["plugin-list"] if plugin in plugins: plugins.remove(plugin) elif "!" + plugin in plugins: plugins.remove("!" + plugin) plugins.append(str("!" + plugin) if not state else str(plugin)) self.__config["plugin-list"] = plugins @property def config_list(self): return self.__config["plugin-list"] def on_property_changed(self, config, key): for item in config[key]: disable = item.startswith("!") if disable: item = item.lstrip("!") try: cls = self.GetClasses()[item] if not cls.__unloadable__ and disable: print(YELLOW("warning:"), item, "is not unloadable") elif item in self.GetLoaded() and disable: self.Unload(item) elif item not in self.GetLoaded() and not disable: try: self.Load(item, user_action=True) except: self.SetConfig(item, False) except KeyError: print(YELLOW("warning:"), "Plugin %s not found" % item) continue
def setup_transfer(self): self.TransConf = Config("transfer") self.TransConf.connect("property-changed", self.on_property_changed) opp_enabled = self.Builder.get_object("opp_enabled") ftp_enabled = self.Builder.get_object("ftp_enabled") ftp_allow_write = self.Builder.get_object("ftp_allow_write") opp_accept = self.Builder.get_object("opp_accept") shared_path = self.Builder.get_object("shared_path") obex_cmd = self.Builder.get_object("e_obex_cmd") opp_enabled.props.active = self.TransConf.props.opp_enabled ftp_enabled.props.active = self.TransConf.props.ftp_enabled ftp_allow_write.props.active = self.TransConf.props.ftp_allow_write opp_accept.props.active = self.TransConf.props.opp_accept if self.TransConf.props.browse_command: obex_cmd.props.text = self.TransConf.props.browse_command if self.TransConf.props.shared_path is not None: shared_path.set_current_folder(self.TransConf.props.shared_path) obex_cmd.connect("changed", lambda x: setattr(self.TransConf.props, "browse_command", x.props.text)) opp_enabled.connect("toggled", lambda x: setattr(self.TransConf.props, "opp_enabled", x.props.active)) ftp_enabled.connect("toggled", lambda x: setattr(self.TransConf.props, "ftp_enabled", x.props.active)) ftp_allow_write.connect("toggled", lambda x: setattr(self.TransConf.props, "ftp_allow_write", x.props.active)) opp_accept.connect("toggled", lambda x: setattr(self.TransConf.props, "opp_accept", x.props.active)) shared_path.connect("current-folder-changed", lambda x: setattr(self.TransConf.props, "shared_path", x.get_filename()))
def setup_transfer(self): a = AppletService() status = a.TransferStatus("opp") if status == -1: self.widget.props.sensitive = False self.widget.props.tooltip_text = _("obex-data-server not available") self.TransConf = Config("transfer") self.TransConf.connect("property-changed", self.on_property_changed) opp_enabled = self.Builder.get_object("opp_enabled") ftp_enabled = self.Builder.get_object("ftp_enabled") ftp_allow_write = self.Builder.get_object("ftp_allow_write") opp_accept = self.Builder.get_object("opp_accept") shared_path = self.Builder.get_object("shared_path") obex_cmd = self.Builder.get_object("e_obex_cmd") opp_enabled.props.active = self.TransConf.props.opp_enabled ftp_enabled.props.active = self.TransConf.props.ftp_enabled ftp_allow_write.props.active = self.TransConf.props.ftp_allow_write opp_accept.props.active = self.TransConf.props.opp_accept if self.TransConf.props.browse_command == None: self.TransConf.props.browse_command = DEF_BROWSE_COMMAND obex_cmd.props.text = self.TransConf.props.browse_command if self.TransConf.props.shared_path != None: shared_path.set_current_folder(self.TransConf.props.shared_path) obex_cmd.connect("changed", lambda x: setattr(self.TransConf.props, "browse_command", x.props.text)) opp_enabled.connect("toggled", lambda x: setattr(self.TransConf.props, "opp_enabled", x.props.active)) ftp_enabled.connect("toggled", lambda x: setattr(self.TransConf.props, "ftp_enabled", x.props.active)) ftp_allow_write.connect("toggled", lambda x: setattr(self.TransConf.props, "ftp_allow_write", x.props.active)) opp_accept.connect("toggled", lambda x: setattr(self.TransConf.props, "opp_accept", x.props.active)) shared_path.connect("current-folder-changed", lambda x: setattr(self.TransConf.props, "shared_path", x.get_filename()))
def on_load(self): self._registered = {} self.Config = Config("org.blueman.network") self.Config.connect("changed", self.on_config_changed) self.load_nap_settings()
def __init__(self, bd_address): GObject.GObject.__init__(self) self.device = bd_address self.Builder = Gtk.Builder() self.Builder.set_translation_domain("blueman") self.Builder.add_from_file(UI_PATH + "/gsm-settings.ui") vbox = self.Builder.get_object("vbox1") self.config = Config("org.blueman.gsmsetting", "/org/blueman/gsmsettings/%s/" % bd_address) self.props.icon_name = "network-wireless" self.props.title = _("GSM Settings") self.props.resizable = False a = self.get_content_area() a.pack_start(vbox, True, True, 0) vbox.show() self.e_apn = self.Builder.get_object("e_apn") self.e_number = self.Builder.get_object("e_number") self.config.bind_to_widget("apn", self.e_apn, "text") self.config.bind_to_widget("number", self.e_number, "text") self.add_button("_Close", Gtk.ResponseType.CLOSE)
def on_load(self, applet): self.Applet = applet self.Config = Config("org.blueman.network") self.Config.connect("changed", self.on_config_changed) self.load_nap_settings()
def __init__(self, adapter=None, inst=None): cr = Gtk.CellRendererText() cr.props.ellipsize = Pango.EllipsizeMode.END tabledata = [ # device picture {"id": "device_surface", "type": str, "renderer": Gtk.CellRendererPixbuf(), "render_attrs": {}, "celldata_func": (self._set_device_cell_data, None)}, # device caption {"id": "caption", "type": str, "renderer": cr, "render_attrs": {"markup": 1}, "view_props": {"expand": True}}, {"id": "rssi_pb", "type": GdkPixbuf.Pixbuf, "renderer": Gtk.CellRendererPixbuf(), "render_attrs": {"pixbuf": 2}, "view_props": {"spacing": 0}}, {"id": "lq_pb", "type": GdkPixbuf.Pixbuf, "renderer": Gtk.CellRendererPixbuf(), "render_attrs": {"pixbuf": 3}, "view_props": {"spacing": 0}}, {"id": "tpl_pb", "type": GdkPixbuf.Pixbuf, "renderer": Gtk.CellRendererPixbuf(), "render_attrs": {"pixbuf": 4}, "view_props": {"spacing": 0}}, {"id": "alias", "type": str}, # used for quick access instead of device.GetProperties {"id": "connected", "type": bool}, # used for quick access instead of device.GetProperties {"id": "paired", "type": bool}, # used for quick access instead of device.GetProperties {"id": "trusted", "type": bool}, # used for quick access instead of device.GetProperties {"id": "objpush", "type": bool}, # used to set Send File button {"id": "rssi", "type": float}, {"id": "lq", "type": float}, {"id": "tpl", "type": float}, {"id": "icon_info", "type": Gtk.IconInfo}, {"id": "cell_fader", "type": GObject.TYPE_PYOBJECT}, {"id": "row_fader", "type": GObject.TYPE_PYOBJECT}, {"id": "levels_visible", "type": bool}, {"id": "initial_anim", "type": bool}, ] super(ManagerDeviceList, self).__init__(adapter, tabledata) self.set_name("ManagerDeviceList") self.set_headers_visible(False) self.props.has_tooltip = True self.Blueman = inst self.Config = Config("org.blueman.general") self.Config.connect('changed', self._on_settings_changed) # Set the correct sorting self._on_settings_changed(self.Config, "sort-by") self._on_settings_changed(self.Config, "sort-type") self.connect("query-tooltip", self.tooltip_query) self.tooltip_row = None self.tooltip_col = None self.connect("button_press_event", self.on_event_clicked) self.connect("button_release_event", self.on_event_clicked) self.menu = None self.connect("drag_data_received", self.drag_recv) self.connect("drag-motion", self.drag_motion) Gtk.Widget.drag_dest_set(self, Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY | Gdk.DragAction.DEFAULT) Gtk.Widget.drag_dest_add_uri_targets(self) self.set_search_equal_func(self.search_func, None)
def __init__(self, *args): super(PersistentPluginManager, self).__init__(*args) self.__config = Config() if getattr(self.__config.props, self.plugin_class.__name__) == None: setattr(self.__config.props, self.plugin_class.__name__, []) self.__config.connect("property-changed", self.on_property_changed)
def _setup_transfer(self): self._config = Config("org.blueman.transfer") self._config.connect("changed", self.on_property_changed) opp_accept = self.Builder.get_object("opp-accept") shared_path = self.Builder.get_object("shared-path") opp_accept.props.active = self._config["opp-accept"] if self._config["shared-path"]: shared_path.set_current_folder(self._config["shared-path"]) opp_accept.connect("toggled", lambda x: self._config.set_boolean("opp-accept", x.props.active)) shared_path.connect("file-set", lambda x: self._config.set_string("shared-path", x.get_filename()))
class PersistentPluginManager(PluginManager): def __init__(self, *args): super(PersistentPluginManager, self).__init__(*args) self.__config = Config() if getattr(self.__config.props, self.plugin_class.__name__) == None: setattr(self.__config.props, self.plugin_class.__name__, []) self.__config.connect("property-changed", self.on_property_changed) def Disabled(self, plugin): plugins = getattr(self.__config.props, self.plugin_class.__name__) return "!" + plugin in plugins def Enabled(self, plugin): plugins = getattr(self.__config.props, self.plugin_class.__name__) return plugin in plugins def SetConfig(self, plugin, state): plugins = self.__config.get(self.plugin_class.__name__) if plugin in plugins: plugins.remove(plugin) elif "!" + plugin in plugins: plugins.remove("!" + plugin) plugins.append(str("!" + plugin) if not state else str(plugin)) self.__config.set(self.plugin_class.__name__, plugins) @property def config_list(self): return self.__config.get(self.plugin_class.__name__) def on_property_changed(self, config, key, value): if key == self.plugin_class.__name__: if type(value) == list: for item in value: disable = item[0] == "!" if disable: item = item[1:] try: cls = self.GetClasses()[item] if not cls.__unloadable__ and disable: print(YELLOW("warning:"), item, "is not unloadable") elif item in self.GetLoaded() and disable: self.Unload(item) elif item not in self.GetLoaded() and not disable: try: self.Load(item, user_action=True) except: self.SetConfig(item, False) except KeyError: print(YELLOW("warning:"), "Plugin %s not found" % item) continue
class Transfer(ServicePlugin): __plugin_info__ = (_("Transfer"), "document-open") def on_load(self, container): self.Builder = Gtk.Builder() self.Builder.set_translation_domain("blueman") bind_textdomain_codeset("blueman", "UTF-8") self.Builder.add_from_file(UI_PATH + "/services-transfer.ui") self.widget = self.Builder.get_object("transfer") self.ignored_keys = [] container.pack_start(self.widget, True, True, 0) a = AppletService() if "TransferService" in a.QueryPlugins(): self._setup_transfer() else: self.widget.props.sensitive = False self.widget.props.tooltip_text = _("Applet's transfer service plugin is disabled") return True def on_enter(self): self.widget.props.visible = True def on_leave(self): self.widget.props.visible = False def on_property_changed(self, config, key): value = config[key] if key == "shared-path": self.Builder.get_object(key).set_current_folder(value) self.option_changed_notify(key, False) def on_apply(self): if self.on_query_apply_state(): self.clear_options() logging.info("transfer apply") def on_query_apply_state(self): opts = self.get_options() if not opts: return False else: return True def _setup_transfer(self): self._config = Config("org.blueman.transfer") self._config.connect("changed", self.on_property_changed) opp_accept = self.Builder.get_object("opp-accept") shared_path = self.Builder.get_object("shared-path") opp_accept.props.active = self._config["opp-accept"] if self._config["shared-path"]: shared_path.set_current_folder(self._config["shared-path"]) opp_accept.connect("toggled", lambda x: self._config.set_boolean("opp-accept", x.props.active)) shared_path.connect("file-set", lambda x: self._config.set_string("shared-path", x.get_filename()))
class ManagerDeviceList(DeviceList): def __init__(self, adapter=None, inst=None): cr = Gtk.CellRendererText() cr.props.ellipsize = Pango.EllipsizeMode.END tabledata = [ # device picture {"id": "device_surface", "type": str, "renderer": Gtk.CellRendererPixbuf(), "render_attrs": {}, "celldata_func": (self._set_device_cell_data, None)}, # device caption {"id": "caption", "type": str, "renderer": cr, "render_attrs": {"markup": 1}, "view_props": {"expand": True}}, {"id": "rssi_pb", "type": GdkPixbuf.Pixbuf, "renderer": Gtk.CellRendererPixbuf(), "render_attrs": {"pixbuf": 2}, "view_props": {"spacing": 0}}, {"id": "lq_pb", "type": GdkPixbuf.Pixbuf, "renderer": Gtk.CellRendererPixbuf(), "render_attrs": {"pixbuf": 3}, "view_props": {"spacing": 0}}, {"id": "tpl_pb", "type": GdkPixbuf.Pixbuf, "renderer": Gtk.CellRendererPixbuf(), "render_attrs": {"pixbuf": 4}, "view_props": {"spacing": 0}}, {"id": "alias", "type": str}, # used for quick access instead of device.GetProperties {"id": "connected", "type": bool}, # used for quick access instead of device.GetProperties {"id": "paired", "type": bool}, # used for quick access instead of device.GetProperties {"id": "trusted", "type": bool}, # used for quick access instead of device.GetProperties {"id": "objpush", "type": bool}, # used to set Send File button {"id": "rssi", "type": float}, {"id": "lq", "type": float}, {"id": "tpl", "type": float}, {"id": "icon_info", "type": Gtk.IconInfo}, {"id": "cell_fader", "type": GObject.TYPE_PYOBJECT}, {"id": "row_fader", "type": GObject.TYPE_PYOBJECT}, {"id": "levels_visible", "type": bool}, {"id": "initial_anim", "type": bool}, ] super(ManagerDeviceList, self).__init__(adapter, tabledata) self.set_name("ManagerDeviceList") self.set_headers_visible(False) self.props.has_tooltip = True self.Blueman = inst self.Config = Config("org.blueman.general") self.Config.connect('changed', self._on_settings_changed) # Set the correct sorting self._on_settings_changed(self.Config, "sort-by") self._on_settings_changed(self.Config, "sort-type") self.connect("query-tooltip", self.tooltip_query) self.tooltip_row = None self.tooltip_col = None self.connect("button_press_event", self.on_event_clicked) self.connect("button_release_event", self.on_event_clicked) self.menu = None self.connect("drag_data_received", self.drag_recv) self.connect("drag-motion", self.drag_motion) Gtk.Widget.drag_dest_set(self, Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY | Gdk.DragAction.DEFAULT) Gtk.Widget.drag_dest_add_uri_targets(self) self.set_search_equal_func(self.search_func, None) def _on_settings_changed(self, settings, key): if key in ('sort-by', 'sort-order'): sort_by = settings['sort-by'] sort_order = settings['sort-order'] if sort_order == 'ascending': sort_type = Gtk.SortType.ASCENDING else: sort_type = Gtk.SortType.DESCENDING column_id = self.ids.setdefault(sort_by, None) if column_id: self.liststore.set_sort_column_id(column_id, sort_type) def on_icon_theme_changed(self, widget): for row in self.liststore: device = self.get(row.iter, "device")["device"] self.row_setup_event(row.iter, device) def do_device_found(self, device): tree_iter = self.find_device(device) if tree_iter: anim = TreeRowColorFade(self, self.props.model.get_path(tree_iter), Gdk.RGBA(0, 0, 1, 1)) anim.animate(start=0.8, end=1.0) def search_func(self, model, column, key, tree_iter): row = self.get(tree_iter, "caption") if key.lower() in row["caption"].lower(): return False logging.info("%s %s %s %s" % (model, column, key, tree_iter)) return True def drag_recv(self, widget, context, x, y, selection, target_type, time): uris = list(selection.get_uris()) context.finish(True, False, time) path = self.get_path_at_pos(x, y) if path: tree_iter = self.get_iter(path[0]) device = self.get(tree_iter, "device")["device"] command = "blueman-sendto --device=%s" % device['Address'] launch(command, uris, False, "blueman", _("File Sender")) context.finish(True, False, time) else: context.finish(False, False, time) return True def drag_motion(self, widget, drag_context, x, y, timestamp): result = self.get_path_at_pos(x, y) if result is not None: path = result[0] if not self.selection.path_is_selected(path): tree_iter = self.get_iter(path) has_obj_push = self._has_objpush(self.get(tree_iter, "device")["device"]) if has_obj_push: Gdk.drag_status(drag_context, Gdk.DragAction.COPY, timestamp) self.set_cursor(path) return True else: Gdk.drag_status(drag_context, Gdk.DragAction.DEFAULT, timestamp) return False else: Gdk.drag_status(drag_context, Gdk.DragAction.DEFAULT, timestamp) return False def on_event_clicked(self, widget, event): if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3: path = self.get_path_at_pos(int(event.x), int(event.y)) if path is not None: row = self.get(path[0], "device") if row: if self.Blueman is not None: if self.menu is None: self.menu = ManagerDeviceMenu(self.Blueman) self.menu.popup(None, None, None, None, event.button, event.time) def get_icon_info(self, icon_name, size=48, fallback=True): if icon_name is None and not fallback: return None elif icon_name is None and fallback: icon_name = "image-missing" icon_info = self.icon_theme.lookup_icon_for_scale(icon_name, size, self.get_scale_factor(), Gtk.IconLookupFlags.FORCE_SIZE) return icon_info def make_device_icon(self, icon_info, is_paired=False, is_trusted=False): window = self.get_window() scale = self.get_scale_factor() target = icon_info.load_surface(window) ctx = cairo.Context(target) if is_paired: icon_info = self.get_icon_info("dialog-password", 16, False) paired_surface = icon_info.load_surface(window) ctx.set_source_surface(paired_surface, 1 / scale, 1 / scale) ctx.paint_with_alpha(0.8) if is_trusted: icon_info = self.get_icon_info("blueman-trust", 16, False) trusted_surface = icon_info.load_surface(window) height = target.get_height() mini_height = trusted_surface.get_height() y = height / scale - mini_height / scale - 1 / scale ctx.set_source_surface(trusted_surface, 1 / scale, y) ctx.paint_with_alpha(0.8) return target def device_remove_event(self, device, tree_iter): row_fader = self.get(tree_iter, "row_fader")["row_fader"] def on_finished(fader): fader.disconnect(signal) fader.freeze() super(ManagerDeviceList, self).device_remove_event(device, tree_iter) signal = row_fader.connect("animation-finished", on_finished) row_fader.thaw() self.emit("device-selected", None, None) row_fader.animate(start=row_fader.get_state(), end=0.0, duration=400) def device_add_event(self, device): self.add_device(device) def make_caption(self, name, klass, address): return "<span size='x-large'>%(0)s</span>\n<span size='small'>%(1)s</span>\n<i>%(2)s</i>" \ % {"0": html.escape(name), "1": klass.capitalize(), "2": address} def get_device_class(self, device): klass = get_minor_class(device['Class']) if klass != "uncategorized": return get_minor_class(device['Class'], True) else: return get_major_class(device['Class']) def row_setup_event(self, tree_iter, device): if not self.get(tree_iter, "initial_anim")["initial_anim"]: cell_fader = CellFade(self, self.props.model.get_path(tree_iter), [2, 3, 4]) row_fader = TreeRowFade(self, self.props.model.get_path(tree_iter)) has_objpush = self._has_objpush(device) self.set(tree_iter, row_fader=row_fader, cell_fader=cell_fader, levels_visible=False, objpush=has_objpush) cell_fader.freeze() def on_finished(fader): fader.disconnect(signal) fader.freeze() signal = row_fader.connect("animation-finished", on_finished) row_fader.set_state(0.0) row_fader.animate(start=0.0, end=1.0, duration=500) self.set(tree_iter, initial_anim=True) klass = get_minor_class(device['Class']) # Bluetooth >= 4 devices use Appearance property appearance = device["Appearance"] if klass != "uncategorized" and klass != "unknown": # get translated version description = get_minor_class(device['Class'], True).capitalize() elif klass == "unknown" and appearance: description = gatt_appearance_to_name(appearance) else: description = get_major_class(device['Class']).capitalize() icon_info = self.get_icon_info(device["Icon"], 48, False) caption = self.make_caption(device['Alias'], description, device['Address']) self.set(tree_iter, caption=caption, icon_info=icon_info, alias=device['Alias']) try: self.row_update_event(tree_iter, "Trusted", device['Trusted']) except Exception as e: logging.exception(e) try: self.row_update_event(tree_iter, "Paired", device['Paired']) except Exception as e: logging.exception(e) try: self.row_update_event(tree_iter, "Connected", device["Connected"]) except Exception as e: logging.exception(e) def row_update_event(self, tree_iter, key, value): logging.info("%s %s" % (key, value)) if key == "Trusted": if value: self.set(tree_iter, trusted=True) else: self.set(tree_iter, trusted=False) elif key == "Paired": if value: self.set(tree_iter, paired=True) else: self.set(tree_iter, paired=False) elif key == "Alias": device = self.get(tree_iter, "device")["device"] c = self.make_caption(value, self.get_device_class(device), device['Address']) self.set(tree_iter, caption=c, alias=value) elif key == "UUIDs": device = self.get(tree_iter, "device")["device"] has_objpush = self._has_objpush(device) self.set(tree_iter, objpush=has_objpush) elif key == "Connected": self.set(tree_iter, connected=value) def level_setup_event(self, row_ref, device, cinfo): if not row_ref.valid(): return tree_iter = self.get_iter(row_ref.get_path()) row = self.get(tree_iter, "levels_visible", "cell_fader", "rssi", "lq", "tpl") if cinfo is not None: # cinfo init may fail for bluetooth devices version 4 and up # FIXME Workaround is horrible and we should show something better if cinfo.failed: rssi_perc = tpl_perc = lq_perc = 100 else: try: rssi = float(cinfo.get_rssi()) except ConnInfoReadError: rssi = 0 try: lq = float(cinfo.get_lq()) except ConnInfoReadError: lq = 0 try: tpl = float(cinfo.get_tpl()) except ConnInfoReadError: tpl = 0 rssi_perc = 50 + (rssi / 127 / 2 * 100) tpl_perc = 50 + (tpl / 127 / 2 * 100) lq_perc = lq / 255 * 100 if lq_perc < 10: lq_perc = 10 if rssi_perc < 10: rssi_perc = 10 if tpl_perc < 10: tpl_perc = 10 if not row["levels_visible"]: logging.info("animating up") self.set(tree_iter, levels_visible=True) fader = row["cell_fader"] fader.thaw() fader.set_state(0.0) fader.animate(start=0.0, end=1.0, duration=400) def on_finished(fader): fader.freeze() fader.disconnect(signal) signal = fader.connect("animation-finished", on_finished) to_store = {} if round(row["rssi"], -1) != round(rssi_perc, -1): icon_name = "blueman-rssi-%d.png" % round(rssi_perc, -1) icon = GdkPixbuf.Pixbuf.new_from_file(os.path.join(PIXMAP_PATH, icon_name)) to_store.update({"rssi": rssi_perc, "rssi_pb": icon}) if round(row["lq"], -1) != round(lq_perc, -1): icon_name = "blueman-lq-%d.png" % round(lq_perc, -1) icon = GdkPixbuf.Pixbuf.new_from_file(os.path.join(PIXMAP_PATH, icon_name)) to_store.update({"lq": lq_perc, "lq_pb": icon}) if round(row["tpl"], -1) != round(tpl_perc, -1): icon_name = "blueman-tpl-%d.png" % round(tpl_perc, -1) icon = GdkPixbuf.Pixbuf.new_from_file(os.path.join(PIXMAP_PATH, icon_name)) to_store.update({"tpl": tpl_perc, "tpl_pb": icon}) if to_store: self.set(tree_iter, **to_store) else: if row["levels_visible"]: logging.info("animating down") self.set(tree_iter, levels_visible=False, rssi=-1, lq=-1, tpl=-1) fader = row["cell_fader"] fader.thaw() fader.set_state(1.0) fader.animate(start=fader.get_state(), end=0.0, duration=400) def on_finished(fader): fader.disconnect(signal) fader.freeze() if row_ref.valid(): self.set(tree_iter, rssi_pb=None, lq_pb=None, tpl_pb=None) signal = fader.connect("animation-finished", on_finished) def tooltip_query(self, tw, x, y, kb, tooltip): path = self.get_path_at_pos(x, y) if path is not None: if path[0] != self.tooltip_row or path[1] != self.tooltip_col: self.tooltip_row = path[0] self.tooltip_col = path[1] return False if path[1] == self.columns["device_surface"]: tree_iter = self.get_iter(path[0]) row = self.get(tree_iter, "trusted", "paired") trusted = row["trusted"] paired = row["paired"] if trusted and paired: tooltip.set_markup(_("<b>Trusted and Paired</b>")) elif paired: tooltip.set_markup(_("<b>Paired</b>")) elif trusted: tooltip.set_markup(_("<b>Trusted</b>")) else: return False self.tooltip_row = path[0] self.tooltip_col = path[1] return True if path[1] == self.columns["tpl_pb"] \ or path[1] == self.columns["lq_pb"] \ or path[1] == self.columns["rssi_pb"]: tree_iter = self.get_iter(path[0]) dt = self.get(tree_iter, "connected")["connected"] if dt: rssi = self.get(tree_iter, "rssi")["rssi"] lq = self.get(tree_iter, "lq")["lq"] tpl = self.get(tree_iter, "tpl")["tpl"] if rssi < 30: rssi_state = _("Poor") elif rssi < 40: rssi_state = _("Sub-optimal") elif rssi < 60: rssi_state = _("Optimal") elif rssi < 70: rssi_state = _("Much") else: rssi_state = _("Too much") if tpl < 30: tpl_state = _("Low") elif tpl < 40: tpl_state = _("Sub-optimal") elif tpl < 60: tpl_state = _("Optimal") elif tpl < 70: tpl_state = _("High") else: tpl_state = _("Very High") tooltip_template = None if path[1] == self.columns["tpl_pb"]: tooltip_template = \ "<b>Connected</b>\nReceived Signal Strength: %(rssi)u%% <i>(%(rssi_state)s)</i>\n" \ "Link Quality: %(lq)u%%\n<b>Transmit Power Level: %(tpl)u%%</b> <i>(%(tpl_state)s)</i>" elif path[1] == self.columns["lq_pb"]: tooltip_template = \ "<b>Connected</b>\nReceived Signal Strength: %(rssi)u%% <i>(%(rssi_state)s)</i>\n" \ "<b>Link Quality: %(lq)u%%</b>\nTransmit Power Level: %(tpl)u%% <i>(%(tpl_state)s)</i>" elif path[1] == self.columns["rssi_pb"]: tooltip_template = \ "<b>Connected</b>\n<b>Received Signal Strength: %(rssi)u%%</b> <i>(%(rssi_state)s)</i>\n" \ "Link Quality: %(lq)u%%\nTransmit Power Level: %(tpl)u%% <i>(%(tpl_state)s)</i>" state_dict = {"rssi_state": rssi_state, "rssi": rssi, "lq": lq, "tpl": tpl, "tpl_state": tpl_state} tooltip.set_markup(tooltip_template % state_dict) self.tooltip_row = path[0] self.tooltip_col = path[1] return True return False def _has_objpush(self, device): if device is None: return False for uuid in device["UUIDs"]: if ServiceUUID(uuid).short_uuid == OBEX_OBJPUSH_SVCLASS_ID: return True return False def _set_device_cell_data(self, col, cell, model, tree_iter, data): row = self.get(tree_iter, "icon_info", "trusted", "paired") surface = self.make_device_icon(row["icon_info"], row["paired"], row["trusted"]) cell.set_property("surface", surface)
class Transfer(ServicePlugin): __plugin_info__ = (_("Transfer"), "document-open") def on_load(self, container): self.Builder = Gtk.Builder() self.Builder.set_translation_domain("blueman") self.Builder.add_from_file(UI_PATH + "/services-transfer.ui") self.widget = self.Builder.get_object("transfer") self.ignored_keys = [] container.pack_start(self.widget, True, True, 0) a = AppletService() if "TransferService" in a.QueryPlugins(): self._setup_transfer() else: self.widget.props.sensitive = False self.widget.props.tooltip_text = _("Applet's transfer service plugin is disabled") return True def on_enter(self): self.widget.props.visible = True def on_leave(self): self.widget.props.visible = False def on_property_changed(self, config, key): value = config[key] if key == "shared-path": self.Builder.get_object(key).set_current_folder(value) self.option_changed_notify(key, False) def on_apply(self): if self.on_query_apply_state(): self.clear_options() dprint("transfer apply") def on_query_apply_state(self): opts = self.get_options() if not opts: return False else: return True def _setup_transfer(self): self._config = Config("org.blueman.transfer") self._config.connect("changed", self.on_property_changed) opp_accept = self.Builder.get_object("opp-accept") shared_path = self.Builder.get_object("shared-path") opp_accept.props.active = self._config["opp-accept"] if self._config["shared-path"]: shared_path.set_current_folder(self._config["shared-path"]) opp_accept.connect("toggled", lambda x: self._config.set_boolean("opp-accept", x.props.active)) shared_path.connect("file-set", lambda x: self._config.set_string("shared-path", x.get_filename()))
class Network(ServicePlugin): __plugin_info__ = (_("Network"), "network-workgroup") def on_load(self, container): self.Builder = Gtk.Builder() self.Builder.set_translation_domain("blueman") bind_textdomain_codeset("blueman", "UTF-8") self.Builder.add_from_file(UI_PATH + "/services-network.ui") self.widget = self.Builder.get_object("network_frame") container.pack_start(self.widget, True, True, 0) self.interfaces = [] for iface in get_net_interfaces(): if iface != "lo" and iface != "pan1": print(iface) ip = inet_aton(get_net_address(iface)) mask = inet_aton(get_net_netmask(iface)) self.interfaces.append((iface, ip, mask, mask_ip4_address(ip, mask))) self.setup_network() try: self.ip_check() except: pass return (_("Network"), "network-workgroup") def on_enter(self): self.widget.props.visible = True def on_leave(self): self.widget.props.visible = False def on_apply(self): if self.on_query_apply_state(): dprint("network apply") m = Mechanism() nap_enable = self.Builder.get_object("nap-enable") if nap_enable.props.active: if self.Builder.get_object("r_dhcpd").props.active: stype = "DhcpdHandler" elif self.Builder.get_object("r_dnsmasq").props.active: stype = "DnsMasqHandler" elif self.Builder.get_object("r_udhcpd").props.active: stype = "UdhcpdHandler" net_ip = self.Builder.get_object("net_ip") try: m.EnableNetwork('(ayays)', inet_aton(net_ip.props.text), inet_aton("255.255.255.0"), stype) if not self.Config["nap-enable"]: self.Config["nap-enable"] = True except Exception as e: d = NetworkErrorDialog(e, parent=self.widget.get_toplevel()) d.run() d.destroy() return else: self.Config["nap-enable"] = False m.DisableNetwork() self.clear_options() def ip_check(self): e = self.Builder.get_object("net_ip") address = e.props.text try: if address.count(".") != 3: raise Exception a = inet_aton(address) except: e.props.secondary_icon_name = "dialog-error" e.props.secondary_icon_tooltip_text = _("Invalid IP address") raise a_netmask = inet_aton("255.255.255.0") a_masked = mask_ip4_address(a, a_netmask) for iface, ip, netmask, masked in self.interfaces: # print mask_ip4_address(a, netmask).encode("hex_codec"), masked.encode("hex_codec") if a == ip: e.props.secondary_icon_name = "dialog-error" e.props.secondary_icon_tooltip_text = _("IP address conflicts with interface %s which has the same address" % iface) raise Exception elif mask_ip4_address(a, netmask) == masked: e.props.secondary_icon_name = "dialog-warning" e.props.secondary_icon_tooltip_text = _("IP address overlaps with subnet of interface" " %s, which has the following configuration %s/%s\nThis may cause incorrect network behavior" % (iface, inet_ntoa(ip), inet_ntoa(netmask))) return e.props.secondary_icon_name = None def on_query_apply_state(self): changed = False opts = self.get_options() if not opts: return False else: if "ip" in opts: try: self.ip_check() except Exception as e: print(e) return -1 return True def setup_network(self): self.Config = Config("org.blueman.network") nap_enable = self.Builder.get_object("nap-enable") r_dnsmasq = self.Builder.get_object("r_dnsmasq") r_dhcpd = self.Builder.get_object("r_dhcpd") r_udhcpd = self.Builder.get_object("r_udhcpd") net_ip = self.Builder.get_object("net_ip") rb_nm = self.Builder.get_object("rb_nm") rb_blueman = self.Builder.get_object("rb_blueman") rb_dun_nm = self.Builder.get_object("rb_dun_nm") rb_dun_blueman = self.Builder.get_object("rb_dun_blueman") nap_frame = self.Builder.get_object("nap_frame") warning = self.Builder.get_object("warning") rb_blueman.props.active = self.Config["dhcp-client"] if not self.Config["nap-enable"]: nap_frame.props.sensitive = False nc = NetConf.get_default() if nc.ip4_address is not None: net_ip.props.text = inet_ntoa(nc.ip4_address) nap_enable.props.active = True else: net_ip.props.text = "10.%d.%d.1" % (randint(0, 255), randint(0, 255)) if nc.get_dhcp_handler() is None: nap_frame.props.sensitive = False nap_enable.props.active = False r_dnsmasq.props.active = True self.Config["nap-enable"] = False if nc.get_dhcp_handler() == DnsMasqHandler: r_dnsmasq.props.active = True elif nc.get_dhcp_handler() == DhcpdHandler: r_dhcpd.props.active = True elif nc.get_dhcp_handler() == UdhcpdHandler: r_udhcpd.props.active = True if not have("dnsmasq") and not have("dhcpd3") and not have("dhcpd") and not have("udhcpd"): nap_frame.props.sensitive = False warning.props.visible = True warning.props.sensitive = True nap_enable.props.sensitive = False self.Config["nap-enable"] = False if not have("dnsmasq"): r_dnsmasq.props.sensitive = False r_dnsmasq.props.active = False if not have("dhcpd3") and not have("dhcpd"): r_dhcpd.props.sensitive = False r_dhcpd.props.active = False if not have("udhcpd"): r_udhcpd.props.sensitive = False r_udhcpd.props.active = False r_dnsmasq.connect("toggled", lambda x: self.option_changed_notify("dnsmasq")) r_udhcpd.connect("toggled", lambda x: self.option_changed_notify("udhcpd")) net_ip.connect("changed", lambda x: self.option_changed_notify("ip", False)) nap_enable.connect("toggled", lambda x: self.option_changed_notify("nap_enable")) self.Config.bind_to_widget("nap-enable", nap_enable, "active", Gio.SettingsBindFlags.GET) nap_enable.bind_property("active", nap_frame, "sensitive", 0) applet = AppletService() avail_plugins = applet.QueryAvailablePlugins() active_plugins = applet.QueryPlugins() def dun_support_toggled(rb, x): if rb.props.active and x == "nm": applet.SetPluginConfig('(sb)', "PPPSupport", False) applet.SetPluginConfig('(sb)', "NMDUNSupport", True) elif rb.props.active and x == "blueman": applet.SetPluginConfig('(sb)', "NMDUNSupport", False) applet.SetPluginConfig('(sb)', "PPPSupport", True) def pan_support_toggled(rb, x): if rb.props.active and x == "nm": applet.SetPluginConfig('(sb)', "DhcpClient", False) applet.SetPluginConfig('(sb)', "NMPANSupport", True) elif rb.props.active and x == "blueman": applet.SetPluginConfig('(sb)', "NMPANSupport", False) applet.SetPluginConfig('(sb)', "DhcpClient", True) if "PPPSupport" in active_plugins: rb_dun_blueman.props.active = True if "NMDUNSupport" in avail_plugins: rb_dun_nm.props.sensitive = True else: rb_dun_nm.props.sensitive = False rb_dun_nm.props.tooltip_text = _("Not currently supported with this setup") if "NMPANSupport" in avail_plugins: rb_nm.props.sensitive = True else: rb_nm.props.sensitive = False rb_nm.props.tooltip_text = _("Not currently supported with this setup") if "NMPANSupport" in active_plugins: rb_nm.props.active = True if "NMDUNSupport" in active_plugins: rb_dun_nm.props.active = True rb_nm.connect("toggled", pan_support_toggled, "nm") rb_blueman.connect("toggled", pan_support_toggled, "blueman") rb_dun_nm.connect("toggled", dun_support_toggled, "nm") rb_dun_blueman.connect("toggled", dun_support_toggled, "blueman")
def __init__(self, parent): if not Dialog.running: Dialog.running = True else: return self.config = None self.parent = parent builder = gtk.Builder() builder.add_from_file(UI_PATH + "/net-usage.ui") builder.set_translation_domain("blueman") self.dialog = builder.get_object("dialog") self.dialog.connect("response", self.on_response) cr1 = gtk.CellRendererText() cr1.props.ellipsize = pango.ELLIPSIZE_END self.devices = {} self.signals = SignalTracker() self.signals.Handle(parent, "monitor-added", self.monitor_added) self.signals.Handle(parent, "monitor-removed", self.monitor_removed) self.signals.Handle(parent, "stats", self.on_stats) cr2 = gtk.CellRendererText() cr2.props.sensitive = False cr2.props.style = pango.STYLE_ITALIC self.liststore = gtk.ListStore(str, str, str, object) self.e_ul = builder.get_object("e_ul") self.e_dl = builder.get_object("e_dl") self.e_total = builder.get_object("e_total") self.l_started = builder.get_object("l_started") self.l_duration = builder.get_object("l_duration") self.b_reset = builder.get_object("b_reset") self.b_reset.connect("clicked", self.on_reset) self.cb_device = builder.get_object("cb_device") self.cb_device.props.model = self.liststore self.cb_device.connect("changed", self.on_selection_changed) self.cb_device.pack_start(cr1, True) self.cb_device.add_attribute(cr1, 'markup', 1) self.cb_device.pack_start(cr2, False) self.cb_device.add_attribute(cr2, 'markup', 2) c = Config("plugins/NetUsage") devs = c.list_dirs() added = False for d in devs: d = os.path.basename(d) for m in parent.monitors: if d == m.device.Address: iter = self.liststore.append([d, self.get_caption(m.device.Alias, m.device.Address), _("Connected:") + " " + m.interface, m]) if self.cb_device.get_active() == -1: self.cb_device.set_active_iter(iter) added = True break if not added: name = d if self.parent.Applet.Manager: for a in self.parent.Applet.Manager.ListAdapters(): try: device = a.FindDevice(d) device = Device(device) name = self.get_caption(device.Alias, device.Address) except: pass self.liststore.append([d, name, _("Not Connected"), None]) added = False if len(self.liststore) > 0: if self.cb_device.get_active() == -1: self.cb_device.set_active(0) else: d = gtk.MessageDialog(parent=self.dialog, flags=gtk.DIALOG_MODAL, type=gtk.MESSAGE_INFO, buttons=gtk.BUTTONS_CLOSE, message_format=_("No usage statistics are available yet. Try establishing a connection first and then check this page.")) d.props.icon_name = "blueman" d.run() d.destroy() self.on_response(None, None) return self.dialog.show()
def __init__(self, parent): if not Dialog.running: Dialog.running = True else: return self.config = None self.parent = parent builder = Gtk.Builder() builder.add_from_file(UI_PATH + "/net-usage.ui") builder.set_translation_domain("blueman") self.dialog = builder.get_object("dialog") self.dialog.connect("response", self.on_response) cr1 = Gtk.CellRendererText() cr1.props.ellipsize = Pango.EllipsizeMode.END self.devices = {} self.signals = SignalTracker() self.signals.Handle(parent, "monitor-added", self.monitor_added) self.signals.Handle(parent, "monitor-removed", self.monitor_removed) self.signals.Handle(parent, "stats", self.on_stats) cr2 = Gtk.CellRendererText() cr2.props.sensitive = False cr2.props.style = Pango.Style.ITALIC self.liststore = Gtk.ListStore(str, str, str, object) self.e_ul = builder.get_object("e_ul") self.e_dl = builder.get_object("e_dl") self.e_total = builder.get_object("e_total") self.l_started = builder.get_object("l_started") self.l_duration = builder.get_object("l_duration") self.b_reset = builder.get_object("b_reset") self.b_reset.connect("clicked", self.on_reset) self.cb_device = builder.get_object("cb_device") self.cb_device.props.model = self.liststore self.cb_device.connect("changed", self.on_selection_changed) self.cb_device.pack_start(cr1, True) self.cb_device.add_attribute(cr1, 'markup', 1) self.cb_device.pack_start(cr2, False) self.cb_device.add_attribute(cr2, 'markup', 2) c = Config("plugins/NetUsage") devs = c.list_dirs() added = False for d in devs: d = os.path.basename(d) for m in parent.monitors: if d == m.device.Address: iter = self.liststore.append( [d, self.get_caption(m.device.Alias, m.device.Address), _("Connected:") + " " + m.interface, m]) if self.cb_device.get_active() == -1: self.cb_device.set_active_iter(iter) added = True break if not added: name = d if self.parent.Applet.Manager: for a in self.parent.Applet.Manager.list_adapters(): try: device = a.find_device(d) device = Device(device) name = self.get_caption(device.Alias, device.Address) except: pass self.liststore.append([d, name, _("Not Connected"), None]) added = False if len(self.liststore) > 0: if self.cb_device.get_active() == -1: self.cb_device.set_active(0) else: d = Gtk.MessageDialog(parent=self.dialog, flags=Gtk.DialogFlags.MODAL, type=Gtk.MessageType.INFO, buttons=Gtk.ButtonsType.CLOSE, message_format=_( "No usage statistics are available yet. Try establishing a connection first and then check this page.")) d.props.icon_name = "blueman" d.run() d.destroy() self.on_response(None, None) return self.dialog.show()
class Blueman(Gtk.Window): def __init__(self): super(Blueman, self).__init__(title=_("Bluetooth Devices")) self._applet_sig = None self.Config = Config("org.blueman.general") self.Builder = Gtk.Builder() self.Builder.set_translation_domain("blueman") bind_textdomain_codeset("blueman", "UTF-8") self.Builder.add_from_file(UI_PATH + "/manager-main.ui") grid = self.Builder.get_object("grid") self.add(grid) self.set_name("BluemanManager") self.Plugins = PluginManager(ManagerPlugin, blueman.plugins.manager, self) self.Plugins.load_plugin() area = MessageArea() grid.attach(area, 0, 3, 1, 1) # Add margin for resize grip or it will overlap if self.get_has_resize_grip(): statusbar = self.Builder.get_object("statusbar") margin_right = statusbar.get_margin_right() statusbar.set_margin_right(margin_right + 10) def do_present(time): if self.props.visible: self.present_with_time(time) check_single_instance("blueman-manager", do_present) def on_window_delete(window, event): w, h = self.get_size() x, y = self.get_position() self.Config["window-properties"] = [w, h, x, y] Gtk.main_quit() def bt_status_changed(status): if not status: self.hide() check_bluetooth_status(_("Bluetooth needs to be turned on for the device manager to function"), lambda: Gtk.main_quit()) else: self.show() def on_applet_signal(_proxy, _sender, signal_name, params): if signal_name == 'BluetoothStatusChanged': status = params.unpack() bt_status_changed(status) def on_dbus_name_vanished(_connection, name): logging.info(name) if self._applet_sig is not None: self.Applet.disconnect(self._applet_sig) self._applet_sig = None self.hide() d = ErrorDialog( _("Connection to BlueZ failed"), _("Bluez daemon is not running, blueman-manager cannot continue.\n" "This probably means that there were no Bluetooth adapters detected " "or Bluetooth daemon was not started."), icon_name="blueman") d.run() d.destroy() # FIXME ui can handle BlueZ start/stop but we should inform user Gtk.main_quit() def on_dbus_name_appeared(_connection, name, owner): logging.info("%s %s" % (name, owner)) setup_icon_path() try: self.Applet = AppletService() except DBusProxyFailed: print("Blueman applet needs to be running") exit() if 'PowerManager' in self.Applet.QueryPlugins(): if not self.Applet.get_bluetooth_status(): bt_status_changed(False) self._applet_sig = self.Applet.connect('g-signal', on_applet_signal) self.connect("delete-event", on_window_delete) self.props.icon_name = "blueman" w, h, x, y = self.Config["window-properties"] if w and h: self.resize(w, h) if x and y: self.move(x, y) sw = self.Builder.get_object("scrollview") # Disable overlay scrolling if Gtk.get_minor_version() >= 16: sw.props.overlay_scrolling = False self.List = ManagerDeviceList(adapter=self.Config["last-adapter"], inst=self) self.List.show() sw.add(self.List) self.Toolbar = ManagerToolbar(self) self.Menu = ManagerMenu(self) self.Stats = ManagerStats(self) if self.List.is_valid_adapter(): self.List.display_known_devices(autoselect=True) self.List.connect("adapter-changed", self.on_adapter_changed) toolbar = self.Builder.get_object("toolbar") statusbar = self.Builder.get_object("statusbar") self.Config.bind_to_widget("show-toolbar", toolbar, "visible") self.Config.bind_to_widget("show-statusbar", statusbar, "visible") self.show() bluez.Manager.watch_name_owner(on_dbus_name_appeared, on_dbus_name_vanished) def on_adapter_changed(self, lst, adapter): if adapter is not None: self.List.display_known_devices(autoselect=True) def inquiry(self): def prop_changed(lst, adapter, key_value): key, value = key_value if key == "Discovering" and not value: prog.finalize() self.List.disconnect(s1) self.List.disconnect(s2) def on_progress(lst, frac): if abs(1.0 - frac) <= 0.00001: if not prog.started(): prog.start() else: prog.fraction(frac) prog = ManagerProgressbar(self, text=_("Searching")) prog.connect("cancelled", lambda x: self.List.stop_discovery()) try: self.List.discover_devices() except Exception as e: prog.finalize() MessageArea.show_message(*e_(e)) s1 = self.List.connect("discovery-progress", on_progress) s2 = self.List.connect("adapter-property-changed", prop_changed) def setup(self, device): command = "blueman-assistant --device=%s" % device['Address'] launch(command, None, False, "blueman", _("Bluetooth Assistant")) def bond(self, device): def error_handler(e): logging.exception(e) message = 'Pairing failed for:\n%s (%s)' % (device['Alias'], device['Address']) Notification('Bluetooth', message, icon_name="blueman").show() device.pair(error_handler=error_handler) def adapter_properties(self): launch("blueman-adapters", None, False, "blueman", _("Adapter Preferences")) def toggle_trust(self, device): device['Trusted'] = not device['Trusted'] def send(self, device, f=None): adapter = self.List.Adapter command = "blueman-sendto --source=%s --device=%s" % (adapter["Address"], device['Address']) launch(command, None, False, "blueman", _("File Sender")) def remove(self, device): self.List.Adapter.remove_device(device)
def __init__(self, blueman): self.blueman = blueman self.Config = Config("org.blueman.general") self.adapter_items: Dict[str, Tuple[Gtk.RadioMenuItem, Adapter]] = {} self._adapters_group: List[Gtk.RadioMenuItem] = [] self._insert_adapter_item_pos = 2 self.Search = None self.item_adapter = self.blueman.Builder.get_object("item_adapter") self.item_device = self.blueman.Builder.get_object("item_device") self.item_view = self.blueman.Builder.get_object("item_view") self.item_help = self.blueman.Builder.get_object("item_help") help_menu = Gtk.Menu() self.item_help.set_submenu(help_menu) help_menu.show() report_item = create_menuitem(_("_Report a Problem"), "dialog-warning") report_item.show() help_menu.append(report_item) report_item.connect("activate", lambda x: launch("xdg-open %s/issues" % WEBSITE)) sep = Gtk.SeparatorMenuItem() sep.show() help_menu.append(sep) help_item = create_menuitem("_Help", "help-about") help_item.show() help_menu.append(help_item) help_item.connect( "activate", lambda x: show_about_dialog('Blueman ' + _('Device Manager'), parent=self.blueman.get_toplevel())) view_menu = Gtk.Menu() self.item_view.set_submenu(view_menu) view_menu.show() item_toolbar = Gtk.CheckMenuItem.new_with_mnemonic(_("Show _Toolbar")) item_toolbar.show() view_menu.append(item_toolbar) self.blueman.Config.bind_to_widget("show-toolbar", item_toolbar, "active") item_statusbar = Gtk.CheckMenuItem.new_with_mnemonic( _("Show _Statusbar")) item_statusbar.show() view_menu.append(item_statusbar) self.blueman.Config.bind_to_widget("show-statusbar", item_statusbar, "active") item_services = Gtk.SeparatorMenuItem() view_menu.append(item_services) item_services.show() sorting_group: List[Gtk.RadioMenuItem] = [] item_sort = Gtk.MenuItem.new_with_mnemonic(_("S_ort By")) view_menu.append(item_sort) item_sort.show() sorting_menu = Gtk.Menu() item_sort.set_submenu(sorting_menu) self._sort_alias_item = Gtk.RadioMenuItem.new_with_mnemonic( sorting_group, _("_Name")) self._sort_alias_item.show() sorting_group = self._sort_alias_item.get_group() sorting_menu.append(self._sort_alias_item) self._sort_timestamp_item = Gtk.RadioMenuItem.new_with_mnemonic( sorting_group, _("_Added")) self._sort_timestamp_item.show() sorting_menu.append(self._sort_timestamp_item) sort_config = self.Config['sort-by'] if sort_config == "alias": self._sort_alias_item.props.active = True else: self._sort_timestamp_item.props.active = True sort_sep = Gtk.SeparatorMenuItem() sort_sep.show() sorting_menu.append(sort_sep) self._sort_type_item = Gtk.CheckMenuItem.new_with_mnemonic( _("_Descending")) self._sort_type_item.show() sorting_menu.append(self._sort_type_item) if self.Config['sort-order'] == "ascending": self._sort_type_item.props.active = False else: self._sort_type_item.props.active = True sep = Gtk.SeparatorMenuItem() sep.show() view_menu.append(sep) item_plugins = create_menuitem(_("_Plugins"), 'blueman-plugin') item_plugins.show() view_menu.append(item_plugins) item_plugins.connect('activate', self._on_plugin_dialog_activate) item_services = create_menuitem( _("_Local Services") + "...", "preferences-desktop") item_services.connect( 'activate', lambda *args: launch("blueman-services", name=_("Service Preferences"))) view_menu.append(item_services) item_services.show() adapter_menu = Gtk.Menu() self.item_adapter.set_submenu(adapter_menu) self.item_adapter.props.sensitive = False search_item = create_menuitem(_("_Search"), "edit-find") search_item.connect("activate", lambda x: self.blueman.inquiry()) search_item.show() adapter_menu.prepend(search_item) self.Search = search_item sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) adapter_settings = create_menuitem("_Preferences", "preferences-system") adapter_settings.connect("activate", lambda x: self.blueman.adapter_properties()) adapter_settings.show() adapter_menu.append(adapter_settings) sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) exit_item = create_menuitem("_Exit", "application-exit") exit_item.connect("activate", lambda x: Gtk.main_quit()) exit_item.show() adapter_menu.append(exit_item) self.item_adapter.show() self.item_view.show() self.item_help.show() self.item_device.show() self.item_device.props.sensitive = False self._manager = Manager() self._manager.connect_signal("adapter-added", self.on_adapter_added) self._manager.connect_signal("adapter-removed", self.on_adapter_removed) blueman.List.connect("device-selected", self.on_device_selected) for adapter in self._manager.get_adapters(): self.on_adapter_added(None, adapter.get_object_path()) self.device_menu = None self.Config.connect("changed", self._on_settings_changed) self._sort_alias_item.connect("activate", self._on_sorting_changed, "alias") self._sort_timestamp_item.connect("activate", self._on_sorting_changed, "timestamp") self._sort_type_item.connect("activate", self._on_sorting_changed, "sort-type")
def setup_network(self): self.NetConf = Config("network") self.NetConf.connect("property-changed", self.on_property_changed) gn_enable = self.Builder.get_object("gn_enable") # latest bluez does not support GN, apparently gn_enable.props.visible = False nap_enable = self.Builder.get_object("nap_enable") r_dnsmasq = self.Builder.get_object("r_dnsmasq") r_dhcpd = self.Builder.get_object("r_dhcpd") net_ip = self.Builder.get_object("net_ip") net_nat = self.Builder.get_object("net_nat") rb_nm = self.Builder.get_object("rb_nm") rb_blueman = self.Builder.get_object("rb_blueman") rb_dun_nm = self.Builder.get_object("rb_dun_nm") rb_dun_blueman = self.Builder.get_object("rb_dun_blueman") nap_frame = self.Builder.get_object("nap_frame") warning = self.Builder.get_object("warning") rb_blueman.props.active = self.NetConf.props.dhcp_client nap_enable.props.active = self.NetConf.props.nap_enable gn_enable.props.active = self.NetConf.props.gn_enable net_ip.props.text = "10.%d.%d.1" % (randint(0, 255), randint(0, 255)) if not self.NetConf.props.nap_enable: nap_frame.props.sensitive = False nc = NetConf.get_default() if nc.ip4_address != None: net_ip.props.text = inet_ntoa(nc.ip4_address) #if not self.NetConf.props.nap_enable: # self.ignored_keys.append("nap_enable") self.NetConf.props.nap_enable = True #if ns["masq"] != 0: # net_nat.props.active = ns["masq"] if nc.get_dhcp_handler() == None: nap_frame.props.sensitive = False nap_enable.props.active = False if self.NetConf.props.nap_enable or self.NetConf.props.nap_enable == None: self.ignored_keys.append("nap_enable") self.NetConf.props.nap_enable = False else: if nc.get_dhcp_handler() == DnsMasqHandler: r_dnsmasq.props.active = True else: r_dhcpd.props.active = True if not have("dnsmasq") and not have("dhcpd3") and not have("dhcpd"): nap_frame.props.sensitive = False warning.props.visible = True warning.props.sensitive = True nap_enable.props.sensitive = False if self.NetConf.props.nap_enable or self.NetConf.props.nap_enable == None: self.ignored_keys.append("nap_enable") self.NetConf.props.nap_enable = False if not have("dnsmasq"): r_dnsmasq.props.sensitive = False r_dnsmasq.props.active = False r_dhcpd.props.active = True if not have("dhcpd3") and not have("dhcpd"): r_dhcpd.props.sensitive = False r_dhcpd.props.active = False r_dnsmasq.props.active = True r_dnsmasq.connect("toggled", lambda x: self.option_changed_notify("dnsmasq")) net_nat.connect("toggled", lambda x: self.on_property_changed(self.NetConf, "nat", x.props.active)) net_ip.connect("changed", lambda x: self.on_property_changed(self.NetConf, "ip", x.props.text)) gn_enable.connect("toggled", lambda x: setattr(self.NetConf.props, "gn_enable", x.props.active)) nap_enable.connect("toggled", lambda x: self.on_property_changed(self.NetConf, "nap_enable", x.props.active)) applet = AppletService() avail_plugins = applet.QueryAvailablePlugins() active_plugins = applet.QueryPlugins() def dun_support_toggled(rb, x): if rb.props.active and x == "nm": applet.SetPluginConfig("PPPSupport", False) applet.SetPluginConfig("NMDUNSupport", True) elif rb.props.active and x == "blueman": applet.SetPluginConfig("NMDUNSupport", False) applet.SetPluginConfig("PPPSupport", True) def pan_support_toggled(rb, x): if rb.props.active and x == "nm": applet.SetPluginConfig("DhcpClient", False) applet.SetPluginConfig("NMPANSupport", True) elif rb.props.active and x == "blueman": applet.SetPluginConfig("NMPANSupport", False) applet.SetPluginConfig("DhcpClient", True) if "PPPSupport" in active_plugins: rb_dun_blueman.props.active = True if "NMDUNSupport" in avail_plugins: rb_dun_nm.props.sensitive = True else: rb_dun_nm.props.sensitive = False rb_dun_nm.props.tooltip_text = _("Not currently supported with this setup") if "NMPANSupport" in avail_plugins: rb_nm.props.sensitive = True else: rb_nm.props.sensitive = False rb_nm.props.tooltip_text = _("Not currently supported with this setup") if "NMPANSupport" in active_plugins: rb_nm.props.active = True if "NMDUNSupport" in active_plugins: rb_dun_nm.props.active = True rb_nm.connect("toggled", pan_support_toggled, "nm") rb_blueman.connect("toggled", pan_support_toggled, "blueman") rb_dun_nm.connect("toggled", dun_support_toggled, "nm") rb_dun_blueman.connect("toggled", dun_support_toggled, "blueman")
class Network(ServicePlugin): __plugin_info__ = (_("Network"), "network-workgroup") def on_load(self, container): self.Builder = Gtk.Builder() self.Builder.set_translation_domain("blueman") self.Builder.add_from_file(UI_PATH + "/services-network.ui") self.widget = self.Builder.get_object("network") self.ignored_keys = [] container.pack_start(self.widget, True, True, 0) self.interfaces = [] for iface in get_net_interfaces(): if iface != "lo" and iface != "pan1": print(iface) ip = inet_aton(get_net_address(iface)) mask = inet_aton(get_net_netmask(iface)) self.interfaces.append((iface, ip, mask, mask_ip4_address(ip, mask))) self.setup_network() try: self.ip_check() except: pass return (_("Network"), "network-workgroup") def on_enter(self): self.widget.props.visible = True def on_leave(self): self.widget.props.visible = False def on_property_changed(self, netconf, key, value): dprint(self.ignored_keys) if key in self.ignored_keys: self.ignored_keys.remove(key) return if key == "rb_blueman" or key == "dhcp_client": if value: self.Builder.get_object("rb_blueman").props.active = True else: self.Builder.get_object("rb_nm").props.active = True return if key == "rb_nm": return if key == "gn_enable": self.Builder.get_object(key).props.active = value return if key == "nap_enable": dprint("nap_enable", value) self.Builder.get_object(key).props.active = value nap_frame = self.Builder.get_object("nap_frame") if value: nap_frame.props.sensitive = True else: nap_frame.props.sensitive = False if key == "ip": self.option_changed_notify(key, False) else: self.option_changed_notify(key) def on_apply(self): if self.on_query_apply_state() == True: dprint("network apply") m = Mechanism() nap_enable = self.Builder.get_object("nap_enable") if nap_enable.props.active: r_dnsmasq = self.Builder.get_object("r_dnsmasq") if r_dnsmasq.props.active: stype = "DnsMasqHandler" else: stype = "DhcpdHandler" net_ip = self.Builder.get_object("net_ip") net_nat = self.Builder.get_object("net_nat") try: m.EnableNetwork(inet_aton(net_ip.props.text), inet_aton("255.255.255.0"), stype) if not self.NetConf.props.nap_enable: # race condition workaround self.ignored_keys.append("nap_enable") self.NetConf.props.nap_enable = True except Exception as e: lines = str(e).splitlines() d = Gtk.MessageDialog(None, buttons=Gtk.ButtonsType.OK, type=Gtk.MessageType.ERROR) d.props.icon_name = "dialog-error" d.props.text = _("Failed to apply network settings") d.props.secondary_text = lines[-1] d.run() d.destroy() return else: if self.NetConf.props.nap_enable: # race condition workaround self.ignored_keys.append("nap_enable") self.NetConf.props.nap_enable = False m.DisableNetwork() self.clear_options() def ip_check(self): e = self.Builder.get_object("net_ip") address = e.props.text try: if address.count(".") != 3: raise Exception a = inet_aton(address) except: e.props.secondary_icon_name = "dialog-error" e.props.secondary_icon_tooltip_text = _("Invalid IP address") raise a_netmask = "\xff\xff\xff\0" a_masked = mask_ip4_address(a, a_netmask) for iface, ip, netmask, masked in self.interfaces: # print mask_ip4_address(a, netmask).encode("hex_codec"), masked.encode("hex_codec") if a == ip: e.props.secondary_icon_name = "dialog-error" e.props.secondary_icon_tooltip_text = _("IP address conflicts with interface %s which has the same address" % iface) raise Exception elif mask_ip4_address(a, netmask) == masked: e.props.secondary_icon_name = "dialog-warning" e.props.secondary_icon_tooltip_text = _("IP address overlaps with subnet of interface" " %s, which has the following configuration %s/%s\nThis may cause incorrect network behavior" % (iface, inet_ntoa(ip), inet_ntoa(netmask))) return e.props.secondary_icon_name = None def on_query_apply_state(self): changed = False opts = self.get_options() if opts == []: return False else: if "ip" in opts: try: self.ip_check() except Exception as e: print(e) return -1 return True def setup_network(self): self.NetConf = Config("network") self.NetConf.connect("property-changed", self.on_property_changed) gn_enable = self.Builder.get_object("gn_enable") # latest bluez does not support GN, apparently gn_enable.props.visible = False nap_enable = self.Builder.get_object("nap_enable") r_dnsmasq = self.Builder.get_object("r_dnsmasq") r_dhcpd = self.Builder.get_object("r_dhcpd") net_ip = self.Builder.get_object("net_ip") net_nat = self.Builder.get_object("net_nat") rb_nm = self.Builder.get_object("rb_nm") rb_blueman = self.Builder.get_object("rb_blueman") rb_dun_nm = self.Builder.get_object("rb_dun_nm") rb_dun_blueman = self.Builder.get_object("rb_dun_blueman") nap_frame = self.Builder.get_object("nap_frame") warning = self.Builder.get_object("warning") rb_blueman.props.active = self.NetConf.props.dhcp_client nap_enable.props.active = self.NetConf.props.nap_enable gn_enable.props.active = self.NetConf.props.gn_enable net_ip.props.text = "10.%d.%d.1" % (randint(0, 255), randint(0, 255)) if not self.NetConf.props.nap_enable: nap_frame.props.sensitive = False nc = NetConf.get_default() if nc.ip4_address != None: net_ip.props.text = inet_ntoa(nc.ip4_address) #if not self.NetConf.props.nap_enable: # self.ignored_keys.append("nap_enable") self.NetConf.props.nap_enable = True #if ns["masq"] != 0: # net_nat.props.active = ns["masq"] if nc.get_dhcp_handler() == None: nap_frame.props.sensitive = False nap_enable.props.active = False if self.NetConf.props.nap_enable or self.NetConf.props.nap_enable == None: self.ignored_keys.append("nap_enable") self.NetConf.props.nap_enable = False else: if nc.get_dhcp_handler() == DnsMasqHandler: r_dnsmasq.props.active = True else: r_dhcpd.props.active = True if not have("dnsmasq") and not have("dhcpd3") and not have("dhcpd"): nap_frame.props.sensitive = False warning.props.visible = True warning.props.sensitive = True nap_enable.props.sensitive = False if self.NetConf.props.nap_enable or self.NetConf.props.nap_enable == None: self.ignored_keys.append("nap_enable") self.NetConf.props.nap_enable = False if not have("dnsmasq"): r_dnsmasq.props.sensitive = False r_dnsmasq.props.active = False r_dhcpd.props.active = True if not have("dhcpd3") and not have("dhcpd"): r_dhcpd.props.sensitive = False r_dhcpd.props.active = False r_dnsmasq.props.active = True r_dnsmasq.connect("toggled", lambda x: self.option_changed_notify("dnsmasq")) net_nat.connect("toggled", lambda x: self.on_property_changed(self.NetConf, "nat", x.props.active)) net_ip.connect("changed", lambda x: self.on_property_changed(self.NetConf, "ip", x.props.text)) gn_enable.connect("toggled", lambda x: setattr(self.NetConf.props, "gn_enable", x.props.active)) nap_enable.connect("toggled", lambda x: self.on_property_changed(self.NetConf, "nap_enable", x.props.active)) applet = AppletService() avail_plugins = applet.QueryAvailablePlugins() active_plugins = applet.QueryPlugins() def dun_support_toggled(rb, x): if rb.props.active and x == "nm": applet.SetPluginConfig("PPPSupport", False) applet.SetPluginConfig("NMDUNSupport", True) elif rb.props.active and x == "blueman": applet.SetPluginConfig("NMDUNSupport", False) applet.SetPluginConfig("PPPSupport", True) def pan_support_toggled(rb, x): if rb.props.active and x == "nm": applet.SetPluginConfig("DhcpClient", False) applet.SetPluginConfig("NMPANSupport", True) elif rb.props.active and x == "blueman": applet.SetPluginConfig("NMPANSupport", False) applet.SetPluginConfig("DhcpClient", True) if "PPPSupport" in active_plugins: rb_dun_blueman.props.active = True if "NMDUNSupport" in avail_plugins: rb_dun_nm.props.sensitive = True else: rb_dun_nm.props.sensitive = False rb_dun_nm.props.tooltip_text = _("Not currently supported with this setup") if "NMPANSupport" in avail_plugins: rb_nm.props.sensitive = True else: rb_nm.props.sensitive = False rb_nm.props.tooltip_text = _("Not currently supported with this setup") if "NMPANSupport" in active_plugins: rb_nm.props.active = True if "NMDUNSupport" in active_plugins: rb_dun_nm.props.active = True rb_nm.connect("toggled", pan_support_toggled, "nm") rb_blueman.connect("toggled", pan_support_toggled, "blueman") rb_dun_nm.connect("toggled", dun_support_toggled, "nm") rb_dun_blueman.connect("toggled", dun_support_toggled, "blueman")
class Networking(AppletPlugin): __icon__ = "network-workgroup" __description__ = _("Manages local network services, like NAP bridges") __author__ = "Walmis" _signal = None def on_load(self) -> None: self._registered: Dict[str, bool] = {} self.Config = Config("org.blueman.network") self.Config.connect("changed", self.on_config_changed) self.load_nap_settings() def on_manager_state_changed(self, state: bool) -> None: if state: self.update_status() def load_nap_settings(self) -> None: logging.info("Loading NAP settings") def reply(_obj: Mechanism, _result: None, _user_data: None) -> None: pass def err(_obj: Mechanism, result: GLib.Error, _user_data: None) -> None: d = ErrorDialog( "<b>Failed to apply network settings</b>", "You might not be able to connect to the Bluetooth network via this machine", result, margin_left=9) d.run() d.destroy() m = Mechanism() m.ReloadNetwork(result_handler=reply, error_handler=err) def on_unload(self) -> None: for adapter_path in self._registered: s = NetworkServer(obj_path=adapter_path) s.unregister("nap") self._registered = {} del self.Config def on_adapter_added(self, path: str) -> None: self.update_status() def update_status(self) -> None: self.set_nap(self.Config["nap-enable"]) def on_config_changed(self, config: Config, key: str) -> None: if key == "nap-enable": self.set_nap(config[key]) def set_nap(self, on: bool) -> None: logging.info("set nap %s" % on) if self.parent.manager_state: adapters = self.parent.Manager.get_adapters() for adapter in adapters: object_path = adapter.get_object_path() registered = self._registered.setdefault(object_path, False) s = NetworkServer(obj_path=object_path) if on and not registered: s.register("nap", "pan1") self._registered[object_path] = True elif not on and registered: s.unregister("nap") self._registered[object_path] = False
def on_selection_changed(self, cb): titer = cb.get_active_iter() (addr,) = self.liststore.get(titer, 0) self.config = Config("org.blueman.plugins.netusage", "/org/blueman/plugins/netusages/%s/" % addr) self.update_counts(self.config["tx"], self.config["rx"]) self.update_time()
def __init__(self, plugin): if not Dialog.running: Dialog.running = True else: return self.config = None self.plugin = plugin builder = Gtk.Builder() builder.add_from_file(UI_PATH + "/net-usage.ui") builder.set_translation_domain("blueman") bind_textdomain_codeset("blueman", "UTF-8") self.dialog = builder.get_object("dialog") self.dialog.connect("response", self.on_response) cr1 = Gtk.CellRendererText() cr1.props.ellipsize = Pango.EllipsizeMode.END self._signals = [ plugin.connect("monitor-added", self.monitor_added), plugin.connect("monitor-removed", self.monitor_removed), plugin.connect("stats", self.on_stats) ] cr2 = Gtk.CellRendererText() cr2.props.sensitive = False cr2.props.style = Pango.Style.ITALIC self.liststore = Gtk.ListStore(str, str, str, object) self.e_ul = builder.get_object("e_ul") self.e_dl = builder.get_object("e_dl") self.e_total = builder.get_object("e_total") self.l_started = builder.get_object("l_started") self.l_duration = builder.get_object("l_duration") self.b_reset = builder.get_object("b_reset") self.b_reset.connect("clicked", self.on_reset) self.cb_device = builder.get_object("cb_device") self.cb_device.props.model = self.liststore self.cb_device.connect("changed", self.on_selection_changed) self.cb_device.pack_start(cr1, True) self.cb_device.add_attribute(cr1, 'markup', 1) self.cb_device.pack_start(cr2, False) self.cb_device.add_attribute(cr2, 'markup', 2) general_config = Config("org.blueman.general") added = False for d in general_config["netusage-dev-list"]: for m in plugin.monitors: if d == m.device["Address"]: titer = self.liststore.append([ d, self.get_caption(m.device["Alias"], m.device["Address"]), _("Connected:") + " " + m.interface, m ]) if self.cb_device.get_active() == -1: self.cb_device.set_active_iter(titer) added = True break if not added: name = d if self.plugin.parent.Manager: device = self.plugin.parent.Manager.find_device(d) if device is None: pass else: name = self.get_caption(device["Alias"], device["Address"]) self.liststore.append([d, name, _("Not Connected"), None]) added = False if len(self.liststore) > 0: if self.cb_device.get_active() == -1: self.cb_device.set_active(0) else: msg = _( "No usage statistics are available yet. Try establishing a connection first and " "then check this page.") d = Gtk.MessageDialog(parent=self.dialog, flags=Gtk.DialogFlags.MODAL, type=Gtk.MessageType.INFO, buttons=Gtk.ButtonsType.CLOSE, message_format=msg) d.props.icon_name = "blueman" d.run() d.destroy() self.on_response(None, None) return self.dialog.show()
def on_selection_changed(self, cb): iter = cb.get_active_iter() (addr,) = self.liststore.get(iter, 0) self.config = Config("plugins/NetUsage/" + addr) self.update_counts(self.config.props.tx, self.config.props.rx) self.update_time()
class Transfer(ServicePlugin): __plugin_info__ = (_("Transfer"), "gtk-open") def on_load(self, container): self.Builder = gtk.Builder() self.Builder.set_translation_domain("blueman") self.Builder.add_from_file(UI_PATH + "/services-transfer.ui") self.widget = self.Builder.get_object("transfer") self.ignored_keys = [] container.pack_start(self.widget) a = AppletService() if "TransferService" in a.QueryPlugins(): self.setup_transfer() else: self.widget.props.sensitive = False self.widget.props.tooltip_text = _("Applet's transfer service plugin is disabled") return True def on_enter(self): self.widget.props.visible = True def on_leave(self): self.widget.props.visible = False def on_property_changed(self, config, key, value): if key == "opp_enabled": self.Builder.get_object(key).props.active = value if key == "ftp_enabled": self.Builder.get_object(key).props.active = value if key == "ftp_allow_write": self.Builder.get_object(key).props.active = value if key == "shared_path": self.Builder.get_object(key).set_current_folder(value) if key == "browse_command": return if key == "shared_path": self.option_changed_notify(key, False) else: self.option_changed_notify(key) def on_apply(self): if self.on_query_apply_state() == True: try: a = AppletService() except: dprint("failed to connect to applet") else: c = self.get_options() if "opp_enabled" in c: if not self.TransConf.props.opp_enabled: a.TransferControl("opp", "destroy") if "ftp_enabled" in c: if not self.TransConf.props.ftp_enabled: a.TransferControl("ftp", "destroy") if "opp_accept" in c or "shared_path" in c or "opp_enabled" in c: if self.TransConf.props.opp_enabled: state = a.TransferStatus("opp") if state == 0: # destroyed a.TransferControl("opp", "create") elif state == 2: # running a.TransferControl("opp", "stop") a.TransferControl("opp", "start") elif state == 1: a.TransferControl("opp", "start") if "ftp_allow_write" in c or "shared_path" in c or "ftp_enabled" in c: if self.TransConf.props.ftp_enabled: state = a.TransferStatus("ftp") if state == 0: # destroyed a.TransferControl("ftp", "create") elif state == 2: # running a.TransferControl("ftp", "stop") a.TransferControl("ftp", "start") elif state == 1: a.TransferControl("ftp", "start") self.clear_options() dprint("transfer apply") def on_query_apply_state(self): opts = self.get_options() if opts == []: return False else: return True def setup_transfer(self): a = AppletService() status = a.TransferStatus("opp") if status == -1: self.widget.props.sensitive = False self.widget.props.tooltip_text = _("obex-data-server not available") self.TransConf = Config("transfer") self.TransConf.connect("property-changed", self.on_property_changed) opp_enabled = self.Builder.get_object("opp_enabled") ftp_enabled = self.Builder.get_object("ftp_enabled") ftp_allow_write = self.Builder.get_object("ftp_allow_write") opp_accept = self.Builder.get_object("opp_accept") shared_path = self.Builder.get_object("shared_path") obex_cmd = self.Builder.get_object("e_obex_cmd") opp_enabled.props.active = self.TransConf.props.opp_enabled ftp_enabled.props.active = self.TransConf.props.ftp_enabled ftp_allow_write.props.active = self.TransConf.props.ftp_allow_write opp_accept.props.active = self.TransConf.props.opp_accept if self.TransConf.props.browse_command == None: self.TransConf.props.browse_command = DEF_BROWSE_COMMAND obex_cmd.props.text = self.TransConf.props.browse_command if self.TransConf.props.shared_path != None: shared_path.set_current_folder(self.TransConf.props.shared_path) obex_cmd.connect("changed", lambda x: setattr(self.TransConf.props, "browse_command", x.props.text)) opp_enabled.connect("toggled", lambda x: setattr(self.TransConf.props, "opp_enabled", x.props.active)) ftp_enabled.connect("toggled", lambda x: setattr(self.TransConf.props, "ftp_enabled", x.props.active)) ftp_allow_write.connect("toggled", lambda x: setattr(self.TransConf.props, "ftp_allow_write", x.props.active)) opp_accept.connect("toggled", lambda x: setattr(self.TransConf.props, "opp_accept", x.props.active)) shared_path.connect( "current-folder-changed", lambda x: setattr(self.TransConf.props, "shared_path", x.get_filename()) )
class ManagerMenu: def __init__(self, blueman): self.blueman = blueman self.Config = Config("org.blueman.general") self.adapter_items = {} self._adapters_group = [] self._insert_adapter_item_pos = 2 self.Search = None self.item_adapter = self.blueman.Builder.get_object("item_adapter") self.item_device = self.blueman.Builder.get_object("item_device") self.item_view = self.blueman.Builder.get_object("item_view") self.item_help = self.blueman.Builder.get_object("item_help") help_menu = Gtk.Menu() self.item_help.set_submenu(help_menu) help_menu.show() report_item = create_menuitem(_("_Report a Problem"), get_icon("dialog-warning", 16)) report_item.show() help_menu.append(report_item) report_item.connect("activate", lambda x: launch("xdg-open %s/issues" % WEBSITE, None, True)) sep = Gtk.SeparatorMenuItem() sep.show() help_menu.append(sep) help_item = create_menuitem("_Help", get_icon("help-about")) help_item.show() help_menu.append(help_item) help_item.connect("activate", lambda x: show_about_dialog('Blueman ' + _('Device Manager'))) view_menu = Gtk.Menu() self.item_view.set_submenu(view_menu) view_menu.show() item_toolbar = Gtk.CheckMenuItem.new_with_mnemonic(_("Show _Toolbar")) item_toolbar.show() view_menu.append(item_toolbar) self.blueman.Config.bind_to_widget("show-toolbar", item_toolbar, "active") item_statusbar = Gtk.CheckMenuItem.new_with_mnemonic(_("Show _Statusbar")) item_statusbar.show() view_menu.append(item_statusbar) self.blueman.Config.bind_to_widget("show-statusbar", item_statusbar, "active") item_services = Gtk.SeparatorMenuItem() view_menu.append(item_services) item_services.show() sorting_group = [] item_sort = Gtk.MenuItem.new_with_mnemonic(_("S_ort By")) view_menu.append(item_sort) item_sort.show() sorting_menu = Gtk.Menu() item_sort.set_submenu(sorting_menu) self._sort_alias_item = Gtk.RadioMenuItem.new_with_mnemonic(sorting_group, _("_Name")) self._sort_alias_item.show() sorting_group = self._sort_alias_item.get_group() sorting_menu.append(self._sort_alias_item) self._sort_timestamp_item = Gtk.RadioMenuItem.new_with_mnemonic(sorting_group, _("_Added")) self._sort_timestamp_item.show() sorting_group = self._sort_timestamp_item.get_group() sorting_menu.append(self._sort_timestamp_item) sort_config = self.Config['sort-by'] if sort_config == "alias": self._sort_alias_item.props.active = True else: self._sort_timestamp_item.props.active = True sort_sep = Gtk.SeparatorMenuItem() sort_sep.show() sorting_menu.append(sort_sep) self._sort_type_item = Gtk.CheckMenuItem.new_with_mnemonic(_("_Descending")) self._sort_type_item.show() sorting_menu.append(self._sort_type_item) if self.Config['sort-order'] == "ascending": self._sort_type_item.props.active = False else: self._sort_type_item.props.active = True sep = Gtk.SeparatorMenuItem() sep.show() view_menu.append(sep) item_plugins = create_menuitem(_("Plugins"), get_icon('blueman-plugin', 16)) item_plugins.show() view_menu.append(item_plugins) item_plugins.connect('activate', lambda *args: self.blueman.Applet.open_plugin_dialog(ignore_reply=True)) item_services = create_menuitem(_("_Local Services") + "...", get_icon("preferences-desktop", 16)) item_services.connect('activate', lambda *args: launch("blueman-services", None, False, "blueman", _("Service Preferences"))) view_menu.append(item_services) item_services.show() adapter_menu = Gtk.Menu() self.item_adapter.set_submenu(adapter_menu) self.item_adapter.props.sensitive = False search_item = create_menuitem(_("_Search"), get_icon("edit-find", 16)) search_item.connect("activate", lambda x: self.blueman.inquiry()) search_item.show() adapter_menu.prepend(search_item) self.Search = search_item sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) adapter_settings = create_menuitem("_Preferences", get_icon("preferences-system", 16)) adapter_settings.connect("activate", lambda x: self.blueman.adapter_properties()) adapter_settings.show() adapter_menu.append(adapter_settings) sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) exit_item = create_menuitem("_Exit", get_icon("application-exit", 16)) exit_item.connect("activate", lambda x: Gtk.main_quit()) exit_item.show() adapter_menu.append(exit_item) self.item_adapter.show() self.item_view.show() self.item_help.show() self.item_device.show() self.item_device.props.sensitive = False self._manager = bluez.Manager() self._manager.connect_signal("adapter-added", self.on_adapter_added) self._manager.connect_signal("adapter-removed", self.on_adapter_removed) blueman.List.connect("device-selected", self.on_device_selected) for adapter in self._manager.list_adapters(): self.on_adapter_added(None, adapter.get_object_path()) self.device_menu = None self.Config.connect("changed", self._on_settings_changed) self._sort_alias_item.connect("activate", self._on_sorting_changed, "alias") self._sort_timestamp_item.connect("activate", self._on_sorting_changed, "timestamp") self._sort_type_item.connect("activate", self._on_sorting_changed, "sort-type") def _on_sorting_changed(self, btn, sort_opt): if sort_opt == 'alias' and btn.props.active: self.Config['sort-by'] = "alias" elif sort_opt == "timestamp" and btn.props.active: self.Config['sort-by'] = "timestamp" elif sort_opt == 'sort-type': # FIXME bind widget to gsetting if btn.props.active: self.Config["sort-order"] = "descending" else: self.Config["sort-order"] = "ascending" def _on_settings_changed(self, settings, key): value = settings[key] if key == 'sort-by': if value == "alias": if not self._sort_alias_item.props.active: self._sort_alias_item.props.active = True elif value == "timestamp": if not self._sort_timestamp_item.props.active: self._sort_timestamp_item.props.active = True elif key == "sort-type": if value == "ascending": if not self._sort_type_item.props.active: self._sort_type_item.props.active = True else: if not self._sort_type_item.props.active: self._sort_type_item.props.active = False def on_device_selected(self, List, device, tree_iter): if tree_iter and device: self.item_device.props.sensitive = True if self.device_menu is None: self.device_menu = ManagerDeviceMenu(self.blueman) self.item_device.set_submenu(self.device_menu) else: GLib.idle_add(self.device_menu.Generate, priority=GLib.PRIORITY_LOW) else: self.item_device.props.sensitive = False def on_adapter_property_changed(self, _adapter, name, value, path): if name == "Name" or name == "Alias": item = self.adapter_items[path][0] item.set_label(value) elif name == "Discovering": if self.Search: if value: self.Search.props.sensitive = False else: self.Search.props.sensitive = True def on_adapter_selected(self, menuitem, adapter_path): if menuitem.props.active: if adapter_path != self.blueman.List.Adapter.get_object_path(): dprint("selected", adapter_path) self.blueman.Config["last-adapter"] = adapter_path_to_name(adapter_path) self.blueman.List.SetAdapter(adapter_path) def on_adapter_added(self, _manager, adapter_path): adapter = bluez.Adapter(adapter_path) menu = self.item_adapter.get_submenu() object_path = adapter.get_object_path() item = Gtk.RadioMenuItem.new_with_label(self._adapters_group, adapter.get_name()) item.show() self._adapters_group = item.get_group() item_sig = item.connect("activate", self.on_adapter_selected, object_path) adapter_sig = adapter.connect_signal("property-changed", self.on_adapter_property_changed) menu.insert(item, self._insert_adapter_item_pos) self._insert_adapter_item_pos += 1 self.adapter_items[object_path] = (item, item_sig, adapter, adapter_sig) if adapter_path == self.blueman.List.Adapter.get_object_path(): item.props.active = True if len(self.adapter_items) > 0: self.item_adapter.props.sensitive = True def on_adapter_removed(self, _manager, adapter_path): item, item_sig, adapter, adapter_sig = self.adapter_items.pop(adapter_path) menu = self.item_adapter.get_submenu() item.disconnect(item_sig) adapter.disconnect_signal(adapter_sig) menu.remove(item) self._insert_adapter_item_pos -= 1 if len(self.adapter_items) == 0: self.item_adapter.props.sensitive = False
def __init__(self): super(Blueman, self).__init__(title=_("Bluetooth Devices")) self._applet_sig = None self.Config = Config("org.blueman.general") self.Builder = Gtk.Builder() self.Builder.set_translation_domain("blueman") bind_textdomain_codeset("blueman", "UTF-8") self.Builder.add_from_file(UI_PATH + "/manager-main.ui") grid = self.Builder.get_object("grid") self.add(grid) self.set_name("BluemanManager") self.Plugins = PluginManager(ManagerPlugin, blueman.plugins.manager, self) self.Plugins.load_plugin() area = MessageArea() grid.attach(area, 0, 3, 1, 1) # Add margin for resize grip or it will overlap if self.get_has_resize_grip(): statusbar = self.Builder.get_object("statusbar") margin_right = statusbar.get_margin_right() statusbar.set_margin_right(margin_right + 10) def do_present(time): if self.props.visible: self.present_with_time(time) check_single_instance("blueman-manager", do_present) def on_window_delete(window, event): w, h = self.get_size() x, y = self.get_position() self.Config["window-properties"] = [w, h, x, y] Gtk.main_quit() def bt_status_changed(status): if not status: self.hide() check_bluetooth_status(_("Bluetooth needs to be turned on for the device manager to function"), lambda: Gtk.main_quit()) else: self.show() def on_applet_signal(_proxy, _sender, signal_name, params): if signal_name == 'BluetoothStatusChanged': status = params.unpack() bt_status_changed(status) def on_dbus_name_vanished(_connection, name): logging.info(name) if self._applet_sig is not None: self.Applet.disconnect(self._applet_sig) self._applet_sig = None self.hide() d = ErrorDialog( _("Connection to BlueZ failed"), _("Bluez daemon is not running, blueman-manager cannot continue.\n" "This probably means that there were no Bluetooth adapters detected " "or Bluetooth daemon was not started."), icon_name="blueman") d.run() d.destroy() # FIXME ui can handle BlueZ start/stop but we should inform user Gtk.main_quit() def on_dbus_name_appeared(_connection, name, owner): logging.info("%s %s" % (name, owner)) setup_icon_path() try: self.Applet = AppletService() except DBusProxyFailed: print("Blueman applet needs to be running") exit() if 'PowerManager' in self.Applet.QueryPlugins(): if not self.Applet.get_bluetooth_status(): bt_status_changed(False) self._applet_sig = self.Applet.connect('g-signal', on_applet_signal) self.connect("delete-event", on_window_delete) self.props.icon_name = "blueman" w, h, x, y = self.Config["window-properties"] if w and h: self.resize(w, h) if x and y: self.move(x, y) sw = self.Builder.get_object("scrollview") # Disable overlay scrolling if Gtk.get_minor_version() >= 16: sw.props.overlay_scrolling = False self.List = ManagerDeviceList(adapter=self.Config["last-adapter"], inst=self) self.List.show() sw.add(self.List) self.Toolbar = ManagerToolbar(self) self.Menu = ManagerMenu(self) self.Stats = ManagerStats(self) if self.List.is_valid_adapter(): self.List.display_known_devices(autoselect=True) self.List.connect("adapter-changed", self.on_adapter_changed) toolbar = self.Builder.get_object("toolbar") statusbar = self.Builder.get_object("statusbar") self.Config.bind_to_widget("show-toolbar", toolbar, "visible") self.Config.bind_to_widget("show-statusbar", statusbar, "visible") self.show() bluez.Manager.watch_name_owner(on_dbus_name_appeared, on_dbus_name_vanished)
def __init__(self, blueman): self.blueman = blueman self.Config = Config("org.blueman.general") self.adapter_items = {} self._adapters_group = [] self._insert_adapter_item_pos = 2 self.Search = None self.item_adapter = self.blueman.Builder.get_object("item_adapter") self.item_device = self.blueman.Builder.get_object("item_device") self.item_view = self.blueman.Builder.get_object("item_view") self.item_help = self.blueman.Builder.get_object("item_help") help_menu = Gtk.Menu() self.item_help.set_submenu(help_menu) help_menu.show() report_item = create_menuitem(_("_Report a Problem"), get_icon("dialog-warning", 16)) report_item.show() help_menu.append(report_item) report_item.connect("activate", lambda x: launch("xdg-open %s/issues" % WEBSITE, None, True)) sep = Gtk.SeparatorMenuItem() sep.show() help_menu.append(sep) help_item = create_menuitem("_Help", get_icon("help-about")) help_item.show() help_menu.append(help_item) help_item.connect("activate", lambda x: show_about_dialog('Blueman ' + _('Device Manager'))) view_menu = Gtk.Menu() self.item_view.set_submenu(view_menu) view_menu.show() item_toolbar = Gtk.CheckMenuItem.new_with_mnemonic(_("Show _Toolbar")) item_toolbar.show() view_menu.append(item_toolbar) self.blueman.Config.bind_to_widget("show-toolbar", item_toolbar, "active") item_statusbar = Gtk.CheckMenuItem.new_with_mnemonic(_("Show _Statusbar")) item_statusbar.show() view_menu.append(item_statusbar) self.blueman.Config.bind_to_widget("show-statusbar", item_statusbar, "active") item_services = Gtk.SeparatorMenuItem() view_menu.append(item_services) item_services.show() sorting_group = [] item_sort = Gtk.MenuItem.new_with_mnemonic(_("S_ort By")) view_menu.append(item_sort) item_sort.show() sorting_menu = Gtk.Menu() item_sort.set_submenu(sorting_menu) self._sort_alias_item = Gtk.RadioMenuItem.new_with_mnemonic(sorting_group, _("_Name")) self._sort_alias_item.show() sorting_group = self._sort_alias_item.get_group() sorting_menu.append(self._sort_alias_item) self._sort_timestamp_item = Gtk.RadioMenuItem.new_with_mnemonic(sorting_group, _("_Added")) self._sort_timestamp_item.show() sorting_group = self._sort_timestamp_item.get_group() sorting_menu.append(self._sort_timestamp_item) sort_config = self.Config['sort-by'] if sort_config == "alias": self._sort_alias_item.props.active = True else: self._sort_timestamp_item.props.active = True sort_sep = Gtk.SeparatorMenuItem() sort_sep.show() sorting_menu.append(sort_sep) self._sort_type_item = Gtk.CheckMenuItem.new_with_mnemonic(_("_Descending")) self._sort_type_item.show() sorting_menu.append(self._sort_type_item) if self.Config['sort-order'] == "ascending": self._sort_type_item.props.active = False else: self._sort_type_item.props.active = True sep = Gtk.SeparatorMenuItem() sep.show() view_menu.append(sep) item_plugins = create_menuitem(_("Plugins"), get_icon('blueman-plugin', 16)) item_plugins.show() view_menu.append(item_plugins) item_plugins.connect('activate', lambda *args: self.blueman.Applet.open_plugin_dialog(ignore_reply=True)) item_services = create_menuitem(_("_Local Services") + "...", get_icon("preferences-desktop", 16)) item_services.connect('activate', lambda *args: launch("blueman-services", None, False, "blueman", _("Service Preferences"))) view_menu.append(item_services) item_services.show() adapter_menu = Gtk.Menu() self.item_adapter.set_submenu(adapter_menu) self.item_adapter.props.sensitive = False search_item = create_menuitem(_("_Search"), get_icon("edit-find", 16)) search_item.connect("activate", lambda x: self.blueman.inquiry()) search_item.show() adapter_menu.prepend(search_item) self.Search = search_item sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) adapter_settings = create_menuitem("_Preferences", get_icon("preferences-system", 16)) adapter_settings.connect("activate", lambda x: self.blueman.adapter_properties()) adapter_settings.show() adapter_menu.append(adapter_settings) sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) exit_item = create_menuitem("_Exit", get_icon("application-exit", 16)) exit_item.connect("activate", lambda x: Gtk.main_quit()) exit_item.show() adapter_menu.append(exit_item) self.item_adapter.show() self.item_view.show() self.item_help.show() self.item_device.show() self.item_device.props.sensitive = False self._manager = bluez.Manager() self._manager.connect_signal("adapter-added", self.on_adapter_added) self._manager.connect_signal("adapter-removed", self.on_adapter_removed) blueman.List.connect("device-selected", self.on_device_selected) for adapter in self._manager.list_adapters(): self.on_adapter_added(None, adapter.get_object_path()) self.device_menu = None self.Config.connect("changed", self._on_settings_changed) self._sort_alias_item.connect("activate", self._on_sorting_changed, "alias") self._sort_timestamp_item.connect("activate", self._on_sorting_changed, "timestamp") self._sort_type_item.connect("activate", self._on_sorting_changed, "sort-type")
def __init__(self, *args): super(PersistentPluginManager, self).__init__(*args) self.__config = Config("org.blueman.general") self.__config.connect("changed::plugin-list", self.on_property_changed)
class Networking(AppletPlugin): __icon__ = "network-workgroup" __description__ = _("Manages local network services, like NAP bridges") __author__ = "Walmis" _signal = None def on_load(self): self._registered = {} self.Config = Config("org.blueman.network") self.Config.connect("changed", self.on_config_changed) self.load_nap_settings() def on_manager_state_changed(self, state): if state: self.update_status() def load_nap_settings(self): logging.info("Loading NAP settings") def reply(*_): pass def err(_obj, result, _user_data): d = ErrorDialog("<b>Failed to apply network settings</b>", "You might not be able to connect to the Bluetooth network via this machine", result, margin_left=9) d.run() d.destroy() m = Mechanism() m.ReloadNetwork(result_handler=reply, error_handler=err) def on_unload(self): for adapter_path in self._registered: s = NetworkServer(adapter_path) s.unregister("nap") self._registered = {} del self.Config def on_adapter_added(self, path): self.update_status() def update_status(self): self.set_nap(self.Config["nap-enable"]) def on_config_changed(self, config, key): if key == "nap-enable": self.set_nap(config[key]) def set_nap(self, on): logging.info("set nap %s" % on) if self.parent.manager_state: adapters = self.parent.Manager.get_adapters() for adapter in adapters: object_path = adapter.get_object_path() registered = self._registered.setdefault(object_path, False) s = NetworkServer(object_path) if on and not registered: s.register("nap", "pan1") self._registered[object_path] = True elif not on and registered: s.unregister("nap") self._registered[object_path] = False
def setup_network(self): self.Config = Config("org.blueman.network") nap_enable = self.Builder.get_object("nap-enable") r_dnsmasq = self.Builder.get_object("r_dnsmasq") r_dhcpd = self.Builder.get_object("r_dhcpd") r_udhcpd = self.Builder.get_object("r_udhcpd") net_ip = self.Builder.get_object("net_ip") rb_nm = self.Builder.get_object("rb_nm") rb_blueman = self.Builder.get_object("rb_blueman") rb_dun_nm = self.Builder.get_object("rb_dun_nm") rb_dun_blueman = self.Builder.get_object("rb_dun_blueman") nap_frame = self.Builder.get_object("nap_frame") warning = self.Builder.get_object("warning") rb_blueman.props.active = self.Config["dhcp-client"] if not self.Config["nap-enable"]: nap_frame.props.sensitive = False nc = NetConf.get_default() if nc.ip4_address is not None: net_ip.props.text = inet_ntoa(nc.ip4_address) nap_enable.props.active = True else: net_ip.props.text = "10.%d.%d.1" % (randint(0, 255), randint(0, 255)) if nc.get_dhcp_handler() is None: nap_frame.props.sensitive = False nap_enable.props.active = False r_dnsmasq.props.active = True self.Config["nap-enable"] = False if nc.get_dhcp_handler() == DnsMasqHandler: r_dnsmasq.props.active = True elif nc.get_dhcp_handler() == DhcpdHandler: r_dhcpd.props.active = True elif nc.get_dhcp_handler() == UdhcpdHandler: r_udhcpd.props.active = True if not have("dnsmasq") and not have("dhcpd3") and not have("dhcpd") and not have("udhcpd"): nap_frame.props.sensitive = False warning.props.visible = True warning.props.sensitive = True nap_enable.props.sensitive = False self.Config["nap-enable"] = False if not have("dnsmasq"): r_dnsmasq.props.sensitive = False r_dnsmasq.props.active = False if not have("dhcpd3") and not have("dhcpd"): r_dhcpd.props.sensitive = False r_dhcpd.props.active = False if not have("udhcpd"): r_udhcpd.props.sensitive = False r_udhcpd.props.active = False r_dnsmasq.connect("toggled", lambda x: self.option_changed_notify("dnsmasq")) r_udhcpd.connect("toggled", lambda x: self.option_changed_notify("udhcpd")) net_ip.connect("changed", lambda x: self.option_changed_notify("ip", False)) nap_enable.connect("toggled", lambda x: self.option_changed_notify("nap_enable")) self.Config.bind_to_widget("nap-enable", nap_enable, "active", Gio.SettingsBindFlags.GET) nap_enable.bind_property("active", nap_frame, "sensitive", 0) applet = AppletService() avail_plugins = applet.QueryAvailablePlugins() active_plugins = applet.QueryPlugins() def dun_support_toggled(rb, x): if rb.props.active and x == "nm": applet.SetPluginConfig('(sb)', "PPPSupport", False) applet.SetPluginConfig('(sb)', "NMDUNSupport", True) elif rb.props.active and x == "blueman": applet.SetPluginConfig('(sb)', "NMDUNSupport", False) applet.SetPluginConfig('(sb)', "PPPSupport", True) def pan_support_toggled(rb, x): if rb.props.active and x == "nm": applet.SetPluginConfig('(sb)', "DhcpClient", False) applet.SetPluginConfig('(sb)', "NMPANSupport", True) elif rb.props.active and x == "blueman": applet.SetPluginConfig('(sb)', "NMPANSupport", False) applet.SetPluginConfig('(sb)', "DhcpClient", True) if "PPPSupport" in active_plugins: rb_dun_blueman.props.active = True if "NMDUNSupport" in avail_plugins: rb_dun_nm.props.sensitive = True else: rb_dun_nm.props.sensitive = False rb_dun_nm.props.tooltip_text = _("Not currently supported with this setup") if "NMPANSupport" in avail_plugins: rb_nm.props.sensitive = True else: rb_nm.props.sensitive = False rb_nm.props.tooltip_text = _("Not currently supported with this setup") if "NMPANSupport" in active_plugins: rb_nm.props.active = True if "NMDUNSupport" in active_plugins: rb_dun_nm.props.active = True rb_nm.connect("toggled", pan_support_toggled, "nm") rb_blueman.connect("toggled", pan_support_toggled, "blueman") rb_dun_nm.connect("toggled", dun_support_toggled, "nm") rb_dun_blueman.connect("toggled", dun_support_toggled, "blueman")
class Networking(AppletPlugin): __icon__ = "network" __description__ = _("Manages local network services, like NAP bridges") __author__ = "Walmis" _signal = None def on_load(self, applet): self._registered = {} self.Applet = applet self.Config = Config("org.blueman.network") self.Config.connect("changed", self.on_config_changed) self.load_nap_settings() def on_manager_state_changed(self, state): if state: self.update_status() def load_nap_settings(self): dprint("Loading NAP settings") def reply(): pass def err(excp): d = NetworkErrorDialog( excp, "You might not be able to connect to the Bluetooth network via this machine" ) d.expander.props.margin_left = 9 d.run() d.destroy() m = Mechanism() m.ReloadNetwork(reply_handler=reply, error_handler=err) def on_unload(self): del self.Config def on_adapter_added(self, path): self.update_status() def update_status(self): self.set_nap(self.Config["nap-enable"]) def on_config_changed(self, config, key): if key == "nap-enable": self.set_nap(config[key]) def set_nap(self, on): dprint("set nap", on) if self.Applet.Manager is not None: adapters = self.Applet.Manager.list_adapters() for adapter in adapters: object_path = adapter.get_object_path() registered = self._registered.setdefault(object_path, False) s = NetworkServer(object_path) if on and not registered: s.register("nap", "pan1") self._registered[object_path] = True elif not on and registered: s.unregister("nap") self._registered[object_path] = False
def bluez_to_friendly_name(svc): if svc == "audiosink": return uuid_names[0x110b] elif svc == "audiosource": return uuid_names[0x110a] else: raise Exception from blueman.main.Config import Config import pickle import base64 import zlib sdp_cache = {} sdp_conf = Config("sdp") def on_sdp_changed(c, key, value): if value and key in sdp_cache: s = pickle.loads(zlib.decompress(base64.b64decode(value))) sdp_cache[key] = s sdp_conf.connect("property-changed", on_sdp_changed) def sdp_get_cached(address): if not address in sdp_cache: d = sdp_conf.get(address)
class ManagerMenu: def __init__(self, blueman): self.blueman = blueman self.Config = Config("org.blueman.general") self.adapter_items: Dict[str, Tuple[Gtk.RadioMenuItem, Adapter]] = {} self._adapters_group: List[Gtk.RadioMenuItem] = [] self._insert_adapter_item_pos = 2 self.Search = None self.item_adapter = self.blueman.Builder.get_object("item_adapter") self.item_device = self.blueman.Builder.get_object("item_device") self.item_view = self.blueman.Builder.get_object("item_view") self.item_help = self.blueman.Builder.get_object("item_help") help_menu = Gtk.Menu() self.item_help.set_submenu(help_menu) help_menu.show() report_item = create_menuitem(_("_Report a Problem"), "dialog-warning") report_item.show() help_menu.append(report_item) report_item.connect("activate", lambda x: launch("xdg-open %s/issues" % WEBSITE)) sep = Gtk.SeparatorMenuItem() sep.show() help_menu.append(sep) help_item = create_menuitem("_Help", "help-about") help_item.show() help_menu.append(help_item) help_item.connect( "activate", lambda x: show_about_dialog('Blueman ' + _('Device Manager'), parent=self.blueman.get_toplevel())) view_menu = Gtk.Menu() self.item_view.set_submenu(view_menu) view_menu.show() item_toolbar = Gtk.CheckMenuItem.new_with_mnemonic(_("Show _Toolbar")) item_toolbar.show() view_menu.append(item_toolbar) self.blueman.Config.bind_to_widget("show-toolbar", item_toolbar, "active") item_statusbar = Gtk.CheckMenuItem.new_with_mnemonic( _("Show _Statusbar")) item_statusbar.show() view_menu.append(item_statusbar) self.blueman.Config.bind_to_widget("show-statusbar", item_statusbar, "active") item_services = Gtk.SeparatorMenuItem() view_menu.append(item_services) item_services.show() sorting_group: List[Gtk.RadioMenuItem] = [] item_sort = Gtk.MenuItem.new_with_mnemonic(_("S_ort By")) view_menu.append(item_sort) item_sort.show() sorting_menu = Gtk.Menu() item_sort.set_submenu(sorting_menu) self._sort_alias_item = Gtk.RadioMenuItem.new_with_mnemonic( sorting_group, _("_Name")) self._sort_alias_item.show() sorting_group = self._sort_alias_item.get_group() sorting_menu.append(self._sort_alias_item) self._sort_timestamp_item = Gtk.RadioMenuItem.new_with_mnemonic( sorting_group, _("_Added")) self._sort_timestamp_item.show() sorting_menu.append(self._sort_timestamp_item) sort_config = self.Config['sort-by'] if sort_config == "alias": self._sort_alias_item.props.active = True else: self._sort_timestamp_item.props.active = True sort_sep = Gtk.SeparatorMenuItem() sort_sep.show() sorting_menu.append(sort_sep) self._sort_type_item = Gtk.CheckMenuItem.new_with_mnemonic( _("_Descending")) self._sort_type_item.show() sorting_menu.append(self._sort_type_item) if self.Config['sort-order'] == "ascending": self._sort_type_item.props.active = False else: self._sort_type_item.props.active = True sep = Gtk.SeparatorMenuItem() sep.show() view_menu.append(sep) item_plugins = create_menuitem(_("_Plugins"), 'blueman-plugin') item_plugins.show() view_menu.append(item_plugins) item_plugins.connect('activate', self._on_plugin_dialog_activate) item_services = create_menuitem( _("_Local Services") + "...", "preferences-desktop") item_services.connect( 'activate', lambda *args: launch("blueman-services", name=_("Service Preferences"))) view_menu.append(item_services) item_services.show() adapter_menu = Gtk.Menu() self.item_adapter.set_submenu(adapter_menu) self.item_adapter.props.sensitive = False search_item = create_menuitem(_("_Search"), "edit-find") search_item.connect("activate", lambda x: self.blueman.inquiry()) search_item.show() adapter_menu.prepend(search_item) self.Search = search_item sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) adapter_settings = create_menuitem("_Preferences", "preferences-system") adapter_settings.connect("activate", lambda x: self.blueman.adapter_properties()) adapter_settings.show() adapter_menu.append(adapter_settings) sep = Gtk.SeparatorMenuItem() sep.show() adapter_menu.append(sep) exit_item = create_menuitem("_Exit", "application-exit") exit_item.connect("activate", lambda x: Gtk.main_quit()) exit_item.show() adapter_menu.append(exit_item) self.item_adapter.show() self.item_view.show() self.item_help.show() self.item_device.show() self.item_device.props.sensitive = False self._manager = Manager() self._manager.connect_signal("adapter-added", self.on_adapter_added) self._manager.connect_signal("adapter-removed", self.on_adapter_removed) blueman.List.connect("device-selected", self.on_device_selected) for adapter in self._manager.get_adapters(): self.on_adapter_added(None, adapter.get_object_path()) self.device_menu = None self.Config.connect("changed", self._on_settings_changed) self._sort_alias_item.connect("activate", self._on_sorting_changed, "alias") self._sort_timestamp_item.connect("activate", self._on_sorting_changed, "timestamp") self._sort_type_item.connect("activate", self._on_sorting_changed, "sort-type") def _on_sorting_changed(self, btn, sort_opt): if sort_opt == 'alias' and btn.props.active: self.Config['sort-by'] = "alias" elif sort_opt == "timestamp" and btn.props.active: self.Config['sort-by'] = "timestamp" elif sort_opt == 'sort-type': # FIXME bind widget to gsetting if btn.props.active: self.Config["sort-order"] = "descending" else: self.Config["sort-order"] = "ascending" def _on_settings_changed(self, settings, key): value = settings[key] if key == 'sort-by': if value == "alias": if not self._sort_alias_item.props.active: self._sort_alias_item.props.active = True elif value == "timestamp": if not self._sort_timestamp_item.props.active: self._sort_timestamp_item.props.active = True elif key == "sort-type": if value == "ascending": if not self._sort_type_item.props.active: self._sort_type_item.props.active = True else: if not self._sort_type_item.props.active: self._sort_type_item.props.active = False def on_device_selected(self, lst, device, tree_iter): if tree_iter and device: self.item_device.props.sensitive = True if self.device_menu is None: self.device_menu = ManagerDeviceMenu(self.blueman) self.item_device.set_submenu(self.device_menu) else: GLib.idle_add(self.device_menu.generate, priority=GLib.PRIORITY_LOW) else: self.item_device.props.sensitive = False def on_adapter_property_changed(self, _adapter, name, value, path): if name == "Name" or name == "Alias": item = self.adapter_items[path][0] item.set_label(value) elif name == "Discovering": if self.Search: if value: self.Search.props.sensitive = False else: self.Search.props.sensitive = True def on_adapter_selected(self, menuitem, adapter_path): if menuitem.props.active: if adapter_path != self.blueman.List.Adapter.get_object_path(): logging.info("selected %s", adapter_path) self.blueman.Config["last-adapter"] = adapter_path_to_name( adapter_path) self.blueman.List.set_adapter(adapter_path) def on_adapter_added(self, _manager, adapter_path): adapter = Adapter(obj_path=adapter_path) menu = self.item_adapter.get_submenu() object_path = adapter.get_object_path() item = Gtk.RadioMenuItem.new_with_label(self._adapters_group, adapter.get_name()) item.show() self._adapters_group = item.get_group() self._itemhandler = item.connect("activate", self.on_adapter_selected, object_path) self._adapterhandler = adapter.connect_signal( "property-changed", self.on_adapter_property_changed) menu.insert(item, self._insert_adapter_item_pos) self._insert_adapter_item_pos += 1 self.adapter_items[object_path] = (item, adapter) if adapter_path == self.blueman.List.Adapter.get_object_path(): item.props.active = True if len(self.adapter_items) > 0: self.item_adapter.props.sensitive = True def on_adapter_removed(self, _manager, adapter_path): item, adapter = self.adapter_items.pop(adapter_path) menu = self.item_adapter.get_submenu() item.disconnect(self._itemhandler) adapter.disconnect(self._adapterhandler) menu.remove(item) self._insert_adapter_item_pos -= 1 if len(self.adapter_items) == 0: self.item_adapter.props.sensitive = False def _on_plugin_dialog_activate(self, *args): def cb(*args): pass self.blueman.Applet.OpenPluginDialog(result_handler=cb)
class Network(ServicePlugin): __plugin_info__ = (_("Network"), "network-workgroup") def on_load(self, container): self.Builder = Gtk.Builder() self.Builder.set_translation_domain("blueman") bind_textdomain_codeset("blueman", "UTF-8") self.Builder.add_from_file(UI_PATH + "/services-network.ui") self.widget = self.Builder.get_object("network_frame") container.pack_start(self.widget, True, True, 0) self.interfaces = [] for iface in get_net_interfaces(): if iface != "lo" and iface != "pan1": logging.info(iface) ipiface = ipaddress.ip_interface('/'.join((get_net_address(iface), get_net_netmask(iface)))) self.interfaces.append((iface, ipiface)) self.setup_network() try: self.ip_check() except (ValueError, ipaddress.AddressValueError) as e: logging.exception(e) return _("Network"), "network-workgroup" def on_enter(self): self.widget.props.visible = True def on_leave(self): self.widget.props.visible = False def on_apply(self): if self.on_query_apply_state(): logging.info("network apply") m = Mechanism() nap_enable = self.Builder.get_object("nap-enable") if nap_enable.props.active: if self.Builder.get_object("r_dhcpd").props.active: stype = "DhcpdHandler" elif self.Builder.get_object("r_dnsmasq").props.active: stype = "DnsMasqHandler" elif self.Builder.get_object("r_udhcpd").props.active: stype = "UdhcpdHandler" net_ip = self.Builder.get_object("net_ip") try: m.EnableNetwork('(sss)', net_ip.props.text, "255.255.255.0", stype) if not self.Config["nap-enable"]: self.Config["nap-enable"] = True except Exception as e: d = ErrorDialog("<b>Failed to apply network settings</b>", excp=e, parent=self.widget.get_toplevel()) d.run() d.destroy() return else: self.Config["nap-enable"] = False m.DisableNetwork() self.clear_options() def ip_check(self): entry = self.Builder.get_object("net_ip") try: nap_ipiface = ipaddress.ip_interface('/'.join((entry.props.text, '255.255.255.0'))) except (ValueError, ipaddress.AddressValueError): entry.props.secondary_icon_name = "dialog-error" entry.props.secondary_icon_tooltip_text = _("Invalid IP address") raise for iface, ipiface in self.interfaces: if nap_ipiface.ip == ipiface.ip: error_message = _("IP address conflicts with interface %s which has the same address" % iface) tooltip_text = error_message entry.props.secondary_icon_name = "dialog-error" entry.props.secondary_icon_tooltip_text = tooltip_text raise ValueError(error_message) elif nap_ipiface.network == ipiface.network: tooltip_text = _( "IP address overlaps with subnet of interface %s, which has the following configuration %s/%s\n" "This may cause incorrect network behavior" % (iface, ipiface.ip, ipiface.netmask)) entry.props.secondary_icon_name = "dialog-warning" entry.props.secondary_icon_tooltip_text = tooltip_text return entry.props.secondary_icon_name = None def on_query_apply_state(self): opts = self.get_options() if not opts: return False if "ip" in opts: try: self.ip_check() except (ValueError, ipaddress.AddressValueError) as e: logging.exception(e) return -1 return True def setup_network(self): self.Config = Config("org.blueman.network") nap_enable = self.Builder.get_object("nap-enable") r_dnsmasq = self.Builder.get_object("r_dnsmasq") r_dhcpd = self.Builder.get_object("r_dhcpd") r_udhcpd = self.Builder.get_object("r_udhcpd") net_ip = self.Builder.get_object("net_ip") rb_nm = self.Builder.get_object("rb_nm") rb_blueman = self.Builder.get_object("rb_blueman") rb_dun_nm = self.Builder.get_object("rb_dun_nm") rb_dun_blueman = self.Builder.get_object("rb_dun_blueman") nap_frame = self.Builder.get_object("nap_frame") warning = self.Builder.get_object("warning") if not self.Config["nap-enable"]: nap_frame.props.sensitive = False nc = NetConf.get_default() if nc.ip4_address is not None: # previously we stored a bytearray, ipaddress module reads both net_ip.props.text = str(ipaddress.ip_address(nc.ip4_address)) nap_enable.props.active = True else: net_ip.props.text = "10.%d.%d.1" % (randint(0, 255), randint(0, 255)) if nc.get_dhcp_handler() is None: nap_frame.props.sensitive = False nap_enable.props.active = False r_dnsmasq.props.active = True self.Config["nap-enable"] = False have_dhcpd = have("dhcpd3") or have("dhcpd") have_dnsmasq = have("dnsmasq") have_udhcpd = have("udhcpd") if nc.get_dhcp_handler() == DnsMasqHandler and have_dnsmasq: r_dnsmasq.props.active = True elif nc.get_dhcp_handler() == DhcpdHandler and have_dhcpd: r_dhcpd.props.active = True elif nc.get_dhcp_handler() == UdhcpdHandler and have_udhcpd: r_udhcpd.props.active = True else: r_dnsmasq.props.active = True if not have_dnsmasq and not have_dhcpd and not have_udhcpd: nap_frame.props.sensitive = False warning.props.visible = True warning.props.sensitive = True nap_enable.props.sensitive = False self.Config["nap-enable"] = False if not have_dnsmasq: r_dnsmasq.props.sensitive = False r_dnsmasq.props.active = False if not have_dhcpd: r_dhcpd.props.sensitive = False r_dhcpd.props.active = False if not have_udhcpd: r_udhcpd.props.sensitive = False r_udhcpd.props.active = False r_dnsmasq.connect("toggled", lambda x: self.option_changed_notify("dnsmasq")) r_dhcpd.connect("toggled", lambda x: self.option_changed_notify("dhcpd")) r_udhcpd.connect("toggled", lambda x: self.option_changed_notify("udhcpd")) net_ip.connect("changed", lambda x: self.option_changed_notify("ip", False)) nap_enable.connect("toggled", lambda x: self.option_changed_notify("nap_enable")) self.Config.bind_to_widget("nap-enable", nap_enable, "active", Gio.SettingsBindFlags.GET) nap_enable.bind_property("active", nap_frame, "sensitive", 0) applet = AppletService() avail_plugins = applet.QueryAvailablePlugins() active_plugins = applet.QueryPlugins() def dun_support_toggled(rb, x): if rb.props.active and x == "nm": applet.SetPluginConfig('(sb)', "PPPSupport", False) applet.SetPluginConfig('(sb)', "NMDUNSupport", True) elif rb.props.active and x == "blueman": applet.SetPluginConfig('(sb)', "NMDUNSupport", False) applet.SetPluginConfig('(sb)', "PPPSupport", True) def pan_support_toggled(rb, x): if rb.props.active and x == "nm": applet.SetPluginConfig('(sb)', "DhcpClient", False) applet.SetPluginConfig('(sb)', "NMPANSupport", True) elif rb.props.active and x == "blueman": applet.SetPluginConfig('(sb)', "NMPANSupport", False) applet.SetPluginConfig('(sb)', "DhcpClient", True) if "PPPSupport" in active_plugins: rb_dun_blueman.props.active = True if "NMDUNSupport" in avail_plugins: rb_dun_nm.props.sensitive = True else: rb_dun_nm.props.sensitive = False rb_dun_nm.props.tooltip_text = _("Not currently supported with this setup") if "DhcpClient" in active_plugins: rb_blueman.props.active = True if "NMPANSupport" in avail_plugins: rb_nm.props.sensitive = True else: rb_nm.props.sensitive = False rb_nm.props.tooltip_text = _("Not currently supported with this setup") if "NMPANSupport" in active_plugins: rb_nm.props.active = True if "NMDUNSupport" in active_plugins: rb_dun_nm.props.active = True rb_nm.connect("toggled", pan_support_toggled, "nm") rb_blueman.connect("toggled", pan_support_toggled, "blueman") rb_dun_nm.connect("toggled", dun_support_toggled, "nm") rb_dun_blueman.connect("toggled", dun_support_toggled, "blueman")