diff --git a/blueman/gui/manager/ManagerDeviceList.py b/blueman/gui/manager/ManagerDeviceList.py
index 15a1d4e3f..804780dba 100644
--- a/blueman/gui/manager/ManagerDeviceList.py
+++ b/blueman/gui/manager/ManagerDeviceList.py
@@ -5,6 +5,7 @@
import cairo
import os
+from blueman.bluez.Adapter import Adapter
from blueman.bluez.Battery import Battery
from blueman.bluez.Device import Device
from blueman.bluez.Manager import Manager
@@ -242,7 +243,7 @@ def on_event_clicked(self, _widget: Gtk.Widget, event: Gdk.Event) -> bool:
if self.menu.show_generic_connect_calc(row["device"]['UUIDs']):
if row["connected"]:
self.menu.disconnect_service(row["device"])
- else:
+ elif Adapter(obj_path=row["device"]["Adapter"])["Powered"]:
self.menu.connect_service(row["device"])
if event.type == Gdk.EventType.BUTTON_PRESS and cast(Gdk.EventButton, event).button == 3:
diff --git a/blueman/gui/manager/ManagerDeviceMenu.py b/blueman/gui/manager/ManagerDeviceMenu.py
index 3bed94c81..69d81c1d6 100644
--- a/blueman/gui/manager/ManagerDeviceMenu.py
+++ b/blueman/gui/manager/ManagerDeviceMenu.py
@@ -5,6 +5,7 @@
from typing import Dict, List, Tuple, Optional, TYPE_CHECKING, Union, Iterable
from blueman.Functions import create_menuitem, e_
+from blueman.bluez.Adapter import Adapter
from blueman.bluez.Network import AnyNetwork
from blueman.bluez.Device import AnyDevice, Device
from blueman.config.AutoConnectConfig import AutoConnectConfig
@@ -46,7 +47,13 @@ def __init__(self, item: Gtk.MenuItem, group: Group, position: int):
class MenuItemsProvider:
- def on_request_menu_items(self, _manager_menu: "ManagerDeviceMenu", _device: Device) -> List[DeviceMenuItem]:
+ def on_request_menu_items(
+ self,
+ _manager_menu:
+ "ManagerDeviceMenu",
+ _device: Device,
+ _powered: bool,
+ ) -> List[DeviceMenuItem]:
return []
@@ -282,13 +289,15 @@ def generate(self) -> None:
show_generic_connect = self.show_generic_connect_calc(self.SelectedDevice['UUIDs'])
- if not row["connected"] and show_generic_connect:
+ powered = Adapter(obj_path=self.SelectedDevice["Adapter"])["Powered"]
+
+ if not row["connected"] and show_generic_connect and powered:
connect_item = create_menuitem(_("_Connect"), "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:
+ elif row["connected"] and show_generic_connect:
connect_item = create_menuitem(_("_Disconnect"), "bluetooth-disabled-symbolic")
connect_item.props.tooltip_text = _("Forcefully disconnect the device")
connect_item.connect("activate", lambda _item: self.disconnect_service(self.SelectedDevice))
@@ -298,7 +307,7 @@ def generate(self) -> None:
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)]
+ for item in plugin.on_request_menu_items(self, self.SelectedDevice, powered)]
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]
@@ -332,7 +341,7 @@ def generate(self) -> None:
for it in sorted(autoconnect_items, key=attrgetter("position")):
self.append(it.item)
- if show_generic_connect or connect_items or disconnect_items or autoconnect_items:
+ if (powered and show_generic_connect) or connect_items or disconnect_items or autoconnect_items:
item = Gtk.SeparatorMenuItem()
item.show()
self.append(item)
@@ -340,18 +349,19 @@ def generate(self) -> None:
for it in sorted(action_items, key=attrgetter("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 powered:
+ 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
+ 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 = Gtk.SeparatorMenuItem()
+ item.show()
+ self.append(item)
item = create_menuitem(_("_Pair"), "blueman-pair-symbolic")
item.props.tooltip_text = _("Create pairing with the device")
diff --git a/blueman/gui/manager/ManagerMenu.py b/blueman/gui/manager/ManagerMenu.py
index 8364cd7f2..2c399dc9e 100644
--- a/blueman/gui/manager/ManagerMenu.py
+++ b/blueman/gui/manager/ManagerMenu.py
@@ -56,6 +56,8 @@ def __init__(self, blueman: "Blueman"):
item_unnamed = blueman.builder.get_widget("hide_unnamed_item", Gtk.CheckMenuItem)
self.blueman.Config.bind("hide-unnamed", item_unnamed, "active", Gio.SettingsBindFlags.DEFAULT)
+ self.device_menu: Optional[ManagerDeviceMenu] = None
+
self._sort_alias_item = blueman.builder.get_widget("sort_name_item", Gtk.CheckMenuItem)
self._sort_timestamp_item = blueman.builder.get_widget("sort_added_item", Gtk.CheckMenuItem)
@@ -105,8 +107,6 @@ def __init__(self, blueman: "Blueman"):
for adapter in self._manager.get_adapters():
self.on_adapter_added(None, adapter.get_object_path())
- self.device_menu: Optional[ManagerDeviceMenu] = 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")
@@ -229,6 +229,9 @@ def on_adapter_removed(self, _manager: Manager, adapter_path: str) -> None:
self._update_power()
def _update_power(self) -> None:
+ if self.device_menu is not None:
+ self.device_menu.generate()
+
if any(adapter["Powered"] for (_, adapter) in self.adapter_items.values()):
self.Search.props.visible = True
self._adapter_settings.props.visible = True
diff --git a/blueman/gui/manager/ManagerToolbar.py b/blueman/gui/manager/ManagerToolbar.py
index 9ecb4b6a7..c042b8d61 100644
--- a/blueman/gui/manager/ManagerToolbar.py
+++ b/blueman/gui/manager/ManagerToolbar.py
@@ -56,52 +56,39 @@ def on_action(self, _button: Gtk.ToolButton, func: Callable[[Device], None]) ->
if device is not None:
func(device)
- def on_adapter_property_changed(self, _lst: ManagerDeviceList, _adapter: Adapter,
+ def on_adapter_property_changed(self, _lst: ManagerDeviceList, adapter: Adapter,
key_value: Tuple[str, object]) -> None:
key, value = key_value
- if key == "Discovering":
- if value:
- self.b_search.props.sensitive = False
- else:
- self.b_search.props.sensitive = True
+ if key == "Discovering" or key == "Powered":
+ self._update_buttons(adapter)
def on_adapter_changed(self, _lst: ManagerDeviceList, adapter_path: Optional[str]) -> None:
logging.debug(f"toolbar adapter {adapter_path}")
- if adapter_path is None:
- self.b_search.props.sensitive = False
- self.b_send.props.sensitive = False
- else:
- self.b_search.props.sensitive = True
+ self._update_buttons(None if adapter_path is None else Adapter(obj_path=adapter_path))
+
+ def on_device_selected(self, dev_list: ManagerDeviceList, device: Device, _tree_iter: Gtk.TreeIter) -> None:
+ self._update_buttons(Adapter(obj_path=device["Adapter"]))
+
+ def _update_buttons(self, adapter: Optional[Adapter]) -> None:
+ powered = adapter is not None and adapter["Powered"]
+ self.b_search.props.sensitive = powered and not (adapter and adapter["Discovering"])
- def on_device_selected(self, dev_list: ManagerDeviceList, device: Device, tree_iter: Gtk.TreeIter) -> None:
- if device is None or tree_iter is None:
+ tree_iter = self.blueman.List.selected()
+ if tree_iter is None:
self.b_bond.props.sensitive = False
- self.b_remove.props.sensitive = False
self.b_trust.props.sensitive = False
+ self.b_remove.props.sensitive = False
+ self.b_send.props.sensitive = False
else:
- row = dev_list.get(tree_iter, "paired", "trusted", "objpush")
+ row = self.blueman.List.get(tree_iter, "paired", "trusted", "objpush")
+ self.b_bond.props.sensitive = powered and not row["paired"]
+ self.b_trust.props.sensitive = True
self.b_remove.props.sensitive = True
- if row["paired"]:
- self.b_bond.props.sensitive = False
- else:
- self.b_bond.props.sensitive = True
-
- if row["trusted"]:
- image = Gtk.Image(icon_name="blueman-untrust-symbolic", pixel_size=24, visible=True)
- self.b_trust.props.icon_widget = image
- self.b_trust.props.sensitive = True
- self.b_trust.props.label = _("Untrust")
-
- else:
- image = Gtk.Image(icon_name="blueman-trust-symbolic", pixel_size=24, visible=True)
- self.b_trust.props.icon_widget = image
- self.b_trust.props.sensitive = True
- self.b_trust.props.label = _("Trust")
-
- if row["objpush"]:
- self.b_send.props.sensitive = True
- else:
- self.b_send.props.sensitive = False
+ self.b_send.props.sensitive = powered and row["objpush"]
+
+ icon_name = "blueman-untrust-symbolic" if row["trusted"] else "blueman-trust-symbolic"
+ self.b_trust.props.icon_widget = Gtk.Image(icon_name=icon_name, pixel_size=24, visible=True)
+ self.b_trust.props.label = _("Untrust") if row["trusted"] else _("Trust")
def on_device_propery_changed(self, dev_list: ManagerDeviceList, device: Device, tree_iter: Gtk.TreeIter,
key_value: Tuple[str, object]) -> None:
diff --git a/blueman/plugins/manager/Info.py b/blueman/plugins/manager/Info.py
index e23342acc..b1a518609 100644
--- a/blueman/plugins/manager/Info.py
+++ b/blueman/plugins/manager/Info.py
@@ -116,7 +116,12 @@ def on_accel_activated(_group: Gtk.AccelGroup, _dialog: GObject, key: int, _modi
class Info(ManagerPlugin, MenuItemsProvider):
- def on_request_menu_items(self, manager_menu: ManagerDeviceMenu, device: Device) -> List[DeviceMenuItem]:
+ def on_request_menu_items(
+ self,
+ manager_menu: ManagerDeviceMenu,
+ device: Device,
+ _powered: bool,
+ ) -> List[DeviceMenuItem]:
item = create_menuitem(_("_Info"), "dialog-information-symbolic")
item.props.tooltip_text = _("Show device information")
_window = manager_menu.get_toplevel()
diff --git a/blueman/plugins/manager/Notes.py b/blueman/plugins/manager/Notes.py
index 9dc59a6a3..3222f186b 100644
--- a/blueman/plugins/manager/Notes.py
+++ b/blueman/plugins/manager/Notes.py
@@ -47,7 +47,15 @@ def send_note(device: Device, parent: Gtk.ApplicationWindow) -> None:
class Notes(ManagerPlugin, MenuItemsProvider):
- def on_request_menu_items(self, manager_menu: ManagerDeviceMenu, device: Device) -> List[DeviceMenuItem]:
+ def on_request_menu_items(
+ self,
+ manager_menu: ManagerDeviceMenu,
+ device: Device,
+ powered: bool,
+ ) -> List[DeviceMenuItem]:
+ if not powered:
+ return []
+
item = create_menuitem(_("Send _note"), "dialog-information-symbolic")
item.props.tooltip_text = _("Send a text note")
assert isinstance(manager_menu.Blueman.window, Gtk.ApplicationWindow)
diff --git a/blueman/plugins/manager/PulseAudioProfile.py b/blueman/plugins/manager/PulseAudioProfile.py
index 6c8f6beea..f1ffa34cf 100644
--- a/blueman/plugins/manager/PulseAudioProfile.py
+++ b/blueman/plugins/manager/PulseAudioProfile.py
@@ -110,7 +110,12 @@ def generate_menu(self, device: Device, item: Gtk.MenuItem) -> None:
item.set_submenu(sub)
item.show()
- def on_request_menu_items(self, manager_menu: ManagerDeviceMenu, device: Device) -> List[DeviceMenuItem]:
+ def on_request_menu_items(
+ self,
+ manager_menu: ManagerDeviceMenu,
+ device: Device,
+ _powered: bool,
+ ) -> List[DeviceMenuItem]:
audio_source = False
for uuid in device['UUIDs']:
if ServiceUUID(uuid).short_uuid in (AUDIO_SOURCE_SVCLASS_ID, AUDIO_SINK_SVCLASS_ID):
diff --git a/blueman/plugins/manager/Services.py b/blueman/plugins/manager/Services.py
index 4a975e0fa..5aaf6c7ba 100644
--- a/blueman/plugins/manager/Services.py
+++ b/blueman/plugins/manager/Services.py
@@ -39,21 +39,27 @@ def _make_x_icon(self, icon_name: str, size: int) -> cairo.ImageSurface:
return target
- def on_request_menu_items(self, manager_menu: ManagerDeviceMenu, device: Device) -> List[DeviceMenuItem]:
+ def on_request_menu_items(
+ self,
+ manager_menu: ManagerDeviceMenu,
+ device: Device,
+ powered: bool,
+ ) -> List[DeviceMenuItem]:
items: List[DeviceMenuItem] = []
appl = AppletService()
services = get_services(device)
- connectable_services = [service for service in services if service.connectable]
- for service in connectable_services:
- item: Gtk.MenuItem = create_menuitem(service.name, service.icon)
- if service.description:
- item.props.tooltip_text = service.description
- item.connect("activate", lambda _item: manager_menu.connect_service(service.device, service.uuid))
- items.append(DeviceMenuItem(item, DeviceMenuItem.Group.CONNECT, service.priority))
- item.props.sensitive = service.available
- item.show()
+ if powered:
+ connectable_services = [service for service in services if service.connectable]
+ for service in connectable_services:
+ item: Gtk.MenuItem = create_menuitem(service.name, service.icon)
+ if service.description:
+ item.props.tooltip_text = service.description
+ item.connect("activate", lambda _item: manager_menu.connect_service(service.device, service.uuid))
+ items.append(DeviceMenuItem(item, DeviceMenuItem.Group.CONNECT, service.priority))
+ item.props.sensitive = service.available
+ item.show()
connected_services = [service for service in services if service.connected_instances]
for service in connected_services: