Exemple #1
0
    def notify(self, object_path, uuid):
        device = Device(object_path)
        logging.info("%s %s" % (device, uuid))
        item = {}
        try:
            adapter = Adapter(device['Adapter'])
        except:
            logging.warning("adapter not found")
            return

        item["adapter"] = adapter["Address"]
        item["address"] = device['Address']
        item["alias"] = device['Alias']
        item["icon"] = device['Icon']
        item["name"] = ServiceUUID(uuid).name
        item["uuid"] = uuid
        item["time"] = time.time()
        item["device"] = object_path
        item["mitem"] = None  #menu item object

        for i in self.items:
            if i["adapter"] == item["adapter"] and \
                            i["address"] == item["address"] and \
                            i["uuid"] == item["uuid"]:
                i["time"] = item["time"]

                i["device"] = item["device"]
                self.initialize()
                return

        self.items.append(item)
        self.initialize()

        self.store_state()
Exemple #2
0
    def notify(self, object_path, uuid):
        device = Device(obj_path=object_path)
        logging.info(f"{device} {uuid}")
        item = {}
        try:
            adapter = self.parent.Manager.get_adapter(device['Adapter'])
        except DBusNoSuchAdapterError:
            logging.warning("adapter not found")
            return

        item["adapter"] = adapter["Address"]
        item["address"] = device['Address']
        item["alias"] = device['Alias']
        item["icon"] = device['Icon']
        item["name"] = ServiceUUID(uuid).name
        item["uuid"] = uuid
        item["time"] = time.time()
        item["device"] = object_path
        item["mitem"] = None  # menu item object

        for i in self.items:
            if i["adapter"] == item["adapter"] and \
                    i["address"] == item["address"] and \
                    i["uuid"] == item["uuid"]:
                i["time"] = item["time"]

                i["device"] = item["device"]
                self.initialize()
                return

        self.items.append(item)
        self.initialize()

        self.store_state()
Exemple #3
0
    def on_request_menu_items(self, manager_menu: ManagerDeviceMenu, device: Device) -> List[DeviceMenuItem]:
        audio_source = False
        for uuid in device['UUIDs']:
            if ServiceUUID(uuid).short_uuid in (AUDIO_SOURCE_SVCLASS_ID, AUDIO_SINK_SVCLASS_ID):
                audio_source = True
                break

        if device['Connected'] and audio_source:

            pa = PulseAudioUtils()
            if not pa.connected:
                self.deferred.append(device)
                return []

            item = create_menuitem(_("Audio Profile"), "audio-card")
            item.props.tooltip_text = _("Select audio profile for PulseAudio")

            if not device['Address'] in self.devices:
                self.query_pa(device, item)
            else:
                self.generate_menu(device, item)

        else:
            return []

        return [DeviceMenuItem(item, DeviceMenuItem.Group.ACTIONS, 300)]
Exemple #4
0
    def notify(self, object_path: str, uuid: str) -> None:
        device = Device(obj_path=object_path)
        logging.info(f"{device} {uuid}")
        try:
            adapter = self.parent.Manager.get_adapter(device['Adapter'])
        except DBusNoSuchAdapterError:
            logging.warning("adapter not found")
            return

        item: "Item" = {
            "adapter": adapter["Address"],
            "address": device['Address'],
            "alias": device['Alias'],
            "icon": device['Icon'],
            "name": ServiceUUID(uuid).name,
            "uuid": uuid,
            "time": time.time(),
            "device": object_path,
            "mitem": None
        }

        for i in self.items:
            if i["adapter"] == item["adapter"] and \
                    i["address"] == item["address"] and \
                    i["uuid"] == item["uuid"]:
                i["time"] = item["time"]

                i["device"] = item["device"]
                self.initialize()
                return

        self.items.append(item)
        self.initialize()

        self._store_state()
Exemple #5
0
    def _on_authorize_service(
            self, device: str, uuid: str, ok: Callable[[], None],
            err: Callable[[BluezErrorRejected], None]) -> None:
        def on_auth_action(action: str) -> None:
            logging.info(action)

            if action == "always":
                Device(obj_path=device).set("Trusted", True)
            if action == "always" or action == "accept":
                ok()
            else:
                err(BluezErrorRejected("Rejected"))

        logging.info("Agent.Authorize")
        dev_str = self.get_device_string(device)
        service = ServiceUUID(uuid).name
        notify_message = \
            _("Authorization request for:") + f"\n{dev_str}\n" + _("Service:") + f" <b>{service}</b>"
        actions = [("always", _("Always accept")), ("accept", _("Accept")),
                   ("deny", _("Deny"))]

        n = Notification(_("Bluetooth Authentication"),
                         notify_message,
                         0,
                         actions,
                         on_auth_action,
                         icon_name="blueman")
        n.show()
Exemple #6
0
    def _on_authorize_service(self, parameters, invocation):
        def on_auth_action(action):
            logging.info(action)

            if action == "always":
                device = bluez.Device(n._device)
                device.set("Trusted", True)
            if action == "always" or action == "accept":
                invocation.return_value(GLib.Variant('()', ()))
            else:
                invocation.return_dbus_error('org.bluez.Error.Rejected',
                                             'Rejected')

            self.n = None

        device, uuid = parameters.unpack()

        logging.info("Agent.Authorize")
        dev_str = self.get_device_string(device)
        service = ServiceUUID(uuid).name
        notify_message = \
            (_("Authorization request for:") + "\n%s\n" + _("Service:") + " <b>%s</b>") % (dev_str, service)
        actions = [["always", _("Always accept")], ["accept",
                                                    _("Accept")],
                   ["deny", _("Deny")]]

        n = Notification(_("Bluetooth Authentication"),
                         notify_message,
                         0,
                         actions,
                         on_auth_action,
                         icon_name="blueman")
        n.show()
        n._device = device
Exemple #7
0
    def _on_authorize_service(self, device, uuid, ok, err):
        def on_auth_action(action):
            logging.info(action)

            if action == "always":
                device = Device(obj_path=n._device)
                device.set("Trusted", True)
            if action == "always" or action == "accept":
                ok()
            else:
                err(BluezErrorRejected("Rejected"))

        logging.info("Agent.Authorize")
        dev_str = self.get_device_string(device)
        service = ServiceUUID(uuid).name
        notify_message = \
            (_("Authorization request for:") + "\n%s\n" + _("Service:") + " <b>%s</b>") % (dev_str, service)
        actions = [["always", _("Always accept")], ["accept",
                                                    _("Accept")],
                   ["deny", _("Deny")]]

        n = Notification(_("Bluetooth Authentication"),
                         notify_message,
                         0,
                         actions,
                         on_auth_action,
                         icon_name="blueman")
        n.show()
        n._device = device
Exemple #8
0
    def notify(self, object_path: str, uuid: str) -> None:
        device = Device(obj_path=object_path)
        logging.info(f"{device} {uuid}")
        try:
            adapter = self.parent.Manager.get_adapter(device['Adapter'])
        except DBusNoSuchAdapterError:
            logging.warning("adapter not found")
            return

        item = {
            "adapter": adapter["Address"],
            "address": device['Address'],
            "alias": device['Alias'],
            "icon": device['Icon'],
            "name": ServiceUUID(uuid).name,
            "uuid": uuid,
            "time": str(time.time()),
        }

        stored_items = self.get_option("recent-connections")

        for i in stored_items:
            if i["adapter"] == item["adapter"] and \
                    i["address"] == item["address"] and \
                    i["uuid"] == item["uuid"]:
                i["time"] = item["time"]
                i["device"] = object_path
                break
        else:
            stored_items.append(item)

        self.set_option("recent-connections", stored_items)

        self._rebuild()
Exemple #9
0
    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
Exemple #10
0
 def reply(*_args):
     Notification(
         _("Connected"),
         _("Automatically connected to %(service)s on %(device)s") %
         {
             "service": ServiceUUID(uuid).name,
             "device": device["Alias"]
         },
         icon_name=device["Icon"]).show()
Exemple #11
0
 def reply(dev: Optional[Device] = device,
           service_name: str = ServiceUUID(uuid).name) -> None:
     assert isinstance(
         dev, Device)  # https://github.com/python/mypy/issues/2608
     Notification(
         _("Connected"),
         _("Automatically connected to %(service)s on %(device)s") %
         {
             "service": service_name,
             "device": dev["Alias"]
         },
         icon_name=dev["Icon"]).show()
Exemple #12
0
 def show_generic_connect_calc(self, device_uuids: Iterable[str]) -> bool:
     # Generic (dis)connect
     for uuid in device_uuids:
         service_uuid = ServiceUUID(uuid)
         if service_uuid.short_uuid in (
                 AUDIO_SOURCE_SVCLASS_ID, AUDIO_SINK_SVCLASS_ID, HANDSFREE_AGW_SVCLASS_ID, HANDSFREE_SVCLASS_ID,
                 HEADSET_SVCLASS_ID, HID_SVCLASS_ID, 0x1812
         ):
             return True
         elif not service_uuid.reserved:
             if uuid == '03b80e5a-ede8-4b33-a751-6ce34ec4c700':
                 return True
     # LE devices do not appear to expose certain properties like uuids until connect to at least once.
     return not device_uuids
    def request_device_profile_menu(self, device: "Device") -> None:
        audio_source = False
        for uuid in device['UUIDs']:
            if ServiceUUID(uuid).short_uuid in (AUDIO_SOURCE_SVCLASS_ID, AUDIO_SINK_SVCLASS_ID):
                audio_source = True
                break

        if device['Connected'] and audio_source:
            pa = PulseAudioUtils()
            if not pa.connected:
                return

            if not device['Address'] in self._devices:
                self.query_pa(device)
            else:
                self.add_device_profile_menu(device)
Exemple #14
0
    def _update_power_levels(self, tree_iter: Gtk.TreeIter, device: Device, cinfo: conn_info) -> None:
        row = self.get(tree_iter, "cell_fader", "battery", "rssi", "lq", "tpl")

        bars = {}

        if device["ServicesResolved"] and any(ServiceUUID(uuid).short_uuid == BATTERY_SERVICE_SVCLASS_ID
                                              for uuid in device["UUIDs"]):
            bars["battery"] = Battery(obj_path=device.get_object_path())["Percentage"]

        # cinfo init may fail for bluetooth devices version 4 and up
        # FIXME Workaround is horrible and we should show something better
        if cinfo.failed:
            if not bars:
                bars = {"rssi": 100.0, "tpl": 100.0, "lq": 100.0}
        else:
            try:
                bars["rssi"] = max(50 + float(cinfo.get_rssi()) / 127 * 50, 10)
            except ConnInfoReadError:
                bars["rssi"] = 50
            try:
                bars["lq"] = max(50 + float(cinfo.get_lq()) / 127 * 50, 10)
            except ConnInfoReadError:
                bars["lq"] = 50
            try:
                bars["tpl"] = max(float(cinfo.get_tpl()) / 255 * 100, 10)
            except ConnInfoReadError:
                bars["tpl"] = 0

        if row["battery"] == row["rssi"] == row["tpl"] == row["lq"] == 0:
            self._prepare_fader(row["cell_fader"]).animate(start=0.0, end=1.0, duration=400)

        w = 14 * self.get_scale_factor()
        h = 48 * self.get_scale_factor()

        for (name, perc) in bars.items():
            if round(row[name], -1) != round(perc, -1):
                icon_name = f"blueman-{name}-{int(round(perc, -1))}.png"
                icon = GdkPixbuf.Pixbuf.new_from_file_at_scale(os.path.join(PIXMAP_PATH, icon_name), w, h, True)
                self.set(tree_iter, **{name: perc, f"{name}_pb": icon})
Exemple #15
0
    def generate(self):
        self.clear()

        items = []

        if not self.is_popup or self.props.visible:
            selected = self.Blueman.List.selected()
            if not selected:
                return
            row = self.Blueman.List.get(selected, "alias", "paired",
                                        "connected", "trusted", "objpush",
                                        "device")
        else:
            (x, y) = self.Blueman.List.get_pointer()
            path = self.Blueman.List.get_path_at_pos(x, y)
            if path is not None:
                row = self.Blueman.List.get(path[0], "alias", "paired",
                                            "connected", "trusted", "objpush",
                                            "device")
            else:
                return

        self.SelectedDevice = row["device"]

        op = self.get_op(self.SelectedDevice)

        if op is not None:
            item = create_menuitem(op, "network-transmit-recieve")
            item.props.sensitive = False
            item.show()
            self.append(item)
            return

        # Generic (dis)connect
        # LE devices do not appear to expose certain properties like uuids until connect to at least once.
        # show generic connect for these as we will not show any way to connect otherwise.
        device_uuids = self.SelectedDevice['UUIDs']
        show_generic_connect = not device_uuids
        for uuid in device_uuids:
            service_uuid = ServiceUUID(uuid)
            if service_uuid.short_uuid in (AUDIO_SOURCE_SVCLASS_ID,
                                           AUDIO_SINK_SVCLASS_ID,
                                           HANDSFREE_AGW_SVCLASS_ID,
                                           HANDSFREE_SVCLASS_ID,
                                           HEADSET_SVCLASS_ID, HID_SVCLASS_ID,
                                           0x1812):
                show_generic_connect = True
                break
            elif not service_uuid.reserved:
                if uuid == '03b80e5a-ede8-4b33-a751-6ce34ec4c700':
                    show_generic_connect = True
                    break

        if not row["connected"] and show_generic_connect:
            connect_item = create_menuitem(_("_Connect"), "blueman")
            connect_item.connect("activate", self._generic_connect,
                                 self.SelectedDevice, True)
            connect_item.props.tooltip_text = _(
                "Connects auto connect profiles A2DP source, A2DP sink, and HID"
            )
            connect_item.show()
            self.append(connect_item)
        elif show_generic_connect:
            connect_item = create_menuitem(_("_Disconnect"), "network-offline")
            connect_item.props.tooltip_text = _(
                "Forcefully disconnect the device")
            connect_item.connect("activate", self._generic_connect,
                                 self.SelectedDevice, False)
            connect_item.show()
            self.append(connect_item)

        rets = self.Blueman.Plugins.run("on_request_menu_items", self,
                                        self.SelectedDevice)

        for ret in rets:
            if ret:
                for (item, pos) in ret:
                    items.append((pos, item))

        logging.debug(row["alias"])

        have_disconnectables = False
        have_connectables = False

        if True in map(lambda x: 100 <= x[0] < 200, items):
            have_disconnectables = True

        if True in map(lambda x: x[0] < 100, items):
            have_connectables = True

        if True in map(lambda x: x[0] >= 200,
                       items) and (have_connectables or have_disconnectables):
            item = Gtk.SeparatorMenuItem()
            item.show()
            items.append((199, item))

        if have_connectables:
            item = Gtk.MenuItem()
            label = Gtk.Label()
            label.set_markup(_("<b>Connect To:</b>"))
            label.props.xalign = 0.0

            label.show()
            item.add(label)
            item.props.sensitive = False
            item.show()
            items.append((0, item))

        if have_disconnectables:
            item = Gtk.MenuItem()
            label = Gtk.Label()
            label.set_markup(_("<b>Disconnect:</b>"))
            label.props.xalign = 0.0

            label.show()
            item.add(label)
            item.props.sensitive = False
            item.show()
            items.append((99, item))

        items.sort(key=itemgetter(0))
        for priority, item in items:
            self.append(item)

        if items:
            item = Gtk.SeparatorMenuItem()
            item.show()
            self.append(item)

        del items

        send_item = create_menuitem(_("Send a _File..."), "edit-copy")
        send_item.props.sensitive = False
        self.append(send_item)
        send_item.show()

        if row["objpush"]:
            send_item.connect("activate",
                              lambda x: self.Blueman.send(self.SelectedDevice))
            send_item.props.sensitive = True

        item = Gtk.SeparatorMenuItem()
        item.show()
        self.append(item)

        item = create_menuitem(_("_Pair"), "dialog-password")
        item.props.tooltip_text = _("Create pairing with the device")
        self.append(item)
        item.show()
        if not row["paired"]:
            item.connect("activate",
                         lambda x: self.Blueman.bond(self.SelectedDevice))
        else:
            item.props.sensitive = False

        if not row["trusted"]:
            item = create_menuitem(_("_Trust"), "blueman-trust")
            item.connect(
                "activate",
                lambda x: self.Blueman.toggle_trust(self.SelectedDevice))
            self.append(item)
            item.show()
        else:
            item = create_menuitem(_("_Untrust"), "blueman-untrust")
            self.append(item)
            item.connect(
                "activate",
                lambda x: self.Blueman.toggle_trust(self.SelectedDevice))
            item.show()
        item.props.tooltip_text = _("Mark/Unmark this device as trusted")

        item = create_menuitem(_("_Setup..."), "document-properties")
        self.append(item)
        item.connect("activate",
                     lambda x: self.Blueman.setup(self.SelectedDevice))
        item.show()
        item.props.tooltip_text = _("Run the setup assistant for this device")

        def on_rename(_item, device):
            def on_response(dialog, response_id):
                if response_id == Gtk.ResponseType.ACCEPT:
                    device.set('Alias', alias_entry.get_text())
                elif response_id == 1:
                    device.set('Alias', '')
                dialog.destroy()

            builder = Gtk.Builder()
            builder.set_translation_domain("blueman")
            bind_textdomain_codeset("blueman", "UTF-8")
            builder.add_from_file(UI_PATH + "/rename-device.ui")
            dialog = builder.get_object("dialog")
            dialog.set_transient_for(self.Blueman)
            dialog.props.icon_name = "blueman"
            alias_entry = builder.get_object("alias_entry")
            alias_entry.set_text(device['Alias'])
            dialog.connect("response", on_response)
            dialog.present()

        item = Gtk.MenuItem.new_with_mnemonic("R_ename device...")
        item.connect('activate', on_rename, self.SelectedDevice)
        self.append(item)
        item.show()

        item = Gtk.SeparatorMenuItem()
        item.show()
        self.append(item)

        item = create_menuitem(_("_Remove..."), "edit-delete")
        item.connect("activate",
                     lambda x: self.Blueman.remove(self.SelectedDevice))
        self.append(item)
        item.show()
        item.props.tooltip_text = _(
            "Remove this device from the known devices list")
Exemple #16
0
 def applicable(device: Device) -> bool:
     return any(
         ServiceUUID(uuid).short_uuid == BATTERY_SERVICE_SVCLASS_ID
         for uuid in device["UUIDs"])
Exemple #17
0
 def format_uuids(uuids):
     return "\n".join(
         [uuid + ' ' + ServiceUUID(uuid).name for uuid in uuids])
Exemple #18
0
def get_service(device, uuid):
    for name, cls in inspect.getmembers(blueman.services, inspect.isclass):
        if ServiceUUID(uuid).short_uuid == cls.__svclass_id__:
            return cls(device, uuid)
Exemple #19
0
 def format_uuids(uuids: Iterable[str]) -> str:
     return "\n".join([uuid + ' ' + ServiceUUID(uuid).name for uuid in uuids])
Exemple #20
0
 def short_uuid(self):
     return ServiceUUID(self.__uuid).short_uuid
Exemple #21
0
 def name(self):
     return ServiceUUID(self.__uuid).name
Exemple #22
0
def get_service(device: Device, uuid: str) -> Optional[Service]:
    for name, cls in inspect.getmembers(blueman.services, inspect.isclass):
        if ServiceUUID(uuid).short_uuid == cls.__svclass_id__:
            svc: Service = cls(device, uuid)
            return svc
    return None
Exemple #23
0
    def generate(self) -> None:
        self.clear()

        if not self.is_popup or self.props.visible:
            selected = self.Blueman.List.selected()
            if not selected:
                return
            row = self.Blueman.List.get(selected, "alias", "paired", "connected", "trusted", "objpush", "device",
                                        "blocked")
        else:
            (x, y) = self.Blueman.List.get_pointer()
            path = self.Blueman.List.get_path_at_pos(x, y)
            if path is not None:
                assert path[0] is not None
                row = self.Blueman.List.get(path[0], "alias", "paired", "connected", "trusted", "objpush", "device",
                                            "blocked")
            else:
                return

        self.SelectedDevice = row["device"]

        op = self.get_op(self.SelectedDevice)

        if op is not None:
            item: Gtk.MenuItem = create_menuitem(op, "network-transmit-receive-symbolic")
            item.props.sensitive = False
            item.show()
            self.append(item)
            return

        show_generic_connect = self.show_generic_connect_calc(self.SelectedDevice['UUIDs'])

        if not row["connected"] and show_generic_connect:
            connect_item = create_menuitem(_("<b>_Connect</b>"), "bluetooth-symbolic")
            connect_item.connect("activate", lambda _item: self.connect_service(self.SelectedDevice))
            connect_item.props.tooltip_text = _("Connects auto connect profiles A2DP source, A2DP sink, and HID")
            connect_item.show()
            self.append(connect_item)
        elif show_generic_connect:
            connect_item = create_menuitem(_("<b>_Disconnect</b>"), "bluetooth-disabled-symbolic")
            connect_item.props.tooltip_text = _("Forcefully disconnect the device")
            connect_item.connect("activate", lambda _item: self.disconnect_service(self.SelectedDevice))
            connect_item.show()
            self.append(connect_item)

        logging.debug(row["alias"])

        items = [item for plugin in self.Blueman.Plugins.get_loaded_plugins(MenuItemsProvider)
                 for item in plugin.on_request_menu_items(self, self.SelectedDevice)]

        connect_items = [i for i in items if i.group == DeviceMenuItem.Group.CONNECT]
        disconnect_items = [i for i in items if i.group == DeviceMenuItem.Group.DISCONNECT]
        autoconnect_items = [item for item in items if item.group == DeviceMenuItem.Group.AUTOCONNECT]
        action_items = [i for i in items if i.group == DeviceMenuItem.Group.ACTIONS]

        if connect_items:
            self.append(self._create_header(_("<b>Connect To:</b>")))
            for it in sorted(connect_items, key=lambda i: i.position):
                self.append(it.item)

        if disconnect_items:
            self.append(self._create_header(_("<b>Disconnect:</b>")))
            for it in sorted(disconnect_items, key=lambda i: i.position):
                self.append(it.item)

        config = AutoConnectConfig()
        generic_service = ServiceUUID("00000000-0000-0000-0000-000000000000")
        generic_autoconnect = (self.SelectedDevice.get_object_path(), str(generic_service)) in set(config["services"])

        if row["connected"] or generic_autoconnect or autoconnect_items:
            self.append(self._create_header(_("<b>Auto-connect:</b>")))

            if row["connected"] or generic_autoconnect:
                item = Gtk.CheckMenuItem(label=generic_service.name)
                config.bind_to_menuitem(item, self.SelectedDevice, str(generic_service))
                item.show()
                self.append(item)

            for it in sorted(autoconnect_items, key=lambda i: i.position):
                self.append(it.item)

        if show_generic_connect or connect_items or disconnect_items or autoconnect_items:
            item = Gtk.SeparatorMenuItem()
            item.show()
            self.append(item)

        for it in sorted(action_items, key=lambda i: i.position):
            self.append(it.item)

        send_item = create_menuitem(_("Send a _File…"), "blueman-send-symbolic")
        send_item.props.sensitive = False
        self.append(send_item)
        send_item.show()

        if row["objpush"]:
            send_item.connect("activate", lambda x: self.Blueman.send(self.SelectedDevice))
            send_item.props.sensitive = True

        item = Gtk.SeparatorMenuItem()
        item.show()
        self.append(item)

        item = create_menuitem(_("_Pair"), "blueman-pair-symbolic")
        item.props.tooltip_text = _("Create pairing with the device")
        self.append(item)
        item.show()
        if not row["paired"]:
            item.connect("activate", lambda x: self.Blueman.bond(self.SelectedDevice))
        else:
            item.props.sensitive = False

        if not row["trusted"]:
            item = create_menuitem(_("_Trust"), "blueman-trust-symbolic")
            item.connect("activate", lambda x: self.Blueman.toggle_trust(self.SelectedDevice))
            self.append(item)
            item.show()
        else:
            item = create_menuitem(_("_Untrust"), "blueman-untrust-symbolic")
            self.append(item)
            item.connect("activate", lambda x: self.Blueman.toggle_trust(self.SelectedDevice))
            item.show()
        item.props.tooltip_text = _("Mark/Unmark this device as trusted")

        if not row["blocked"]:
            item = create_menuitem(_("_Block"), "blueman-block-symbolic")
            item.connect("activate", lambda x: self.Blueman.toggle_blocked(self.SelectedDevice))
            self.append(item)
            item.show()
        else:
            item = create_menuitem(_("_Unblock"), "blueman-block-symbolic")
            self.append(item)
            item.connect("activate", lambda x: self.Blueman.toggle_blocked(self.SelectedDevice))
            item.show()
        item.props.tooltip_text = _("Block/Unblock this device")

        def on_rename(_item: Gtk.MenuItem, device: Device) -> None:
            def on_response(dialog: Gtk.Dialog, response_id: int) -> None:
                if response_id == Gtk.ResponseType.ACCEPT:
                    assert isinstance(alias_entry, Gtk.Entry)  # https://github.com/python/mypy/issues/2608
                    device.set('Alias', alias_entry.get_text())
                elif response_id == 1:
                    device.set('Alias', '')
                dialog.destroy()

            builder = Builder("rename-device.ui")
            dialog = builder.get_widget("dialog", Gtk.Dialog)
            dialog.set_transient_for(self.Blueman.window)
            dialog.props.icon_name = "blueman"
            alias_entry = builder.get_widget("alias_entry", Gtk.Entry)
            alias_entry.set_text(device['Alias'])
            dialog.connect("response", on_response)
            dialog.present()

        item = Gtk.MenuItem.new_with_mnemonic(_("R_ename device…"))
        item.connect('activate', on_rename, self.SelectedDevice)
        self.append(item)
        item.show()

        item = Gtk.SeparatorMenuItem()
        item.show()
        self.append(item)

        item = create_menuitem(_("_Remove…"), "list-remove-symbolic")
        item.connect("activate", lambda x: self.Blueman.remove(self.SelectedDevice))
        self.append(item)
        item.show()
        item.props.tooltip_text = _("Remove this device from the known devices list")
Exemple #24
0
 def short_uuid(self) -> Optional[int]:
     return ServiceUUID(self.__uuid).short_uuid