Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions blueman/Functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,18 +186,19 @@
icon_name: str | None = None,
pixbuf: GdkPixbuf.Pixbuf | None = None,
surface: cairo.Surface | None = None,
action_name: str | None = None,
) -> Gtk.ImageMenuItem:
image = Gtk.Image(pixel_size=16)
if icon_name:
image.set_from_icon_name(icon_name, Gtk.IconSize.MENU)
image = Gtk.Image(icon_name=icon_name, icon_size=Gtk.IconSize.MENU, pixel_size=16)
elif surface:
image.set_from_surface(surface)
image = Gtk.Image(surface=surface, icon_size=Gtk.IconSize.MENU, pixel_size=16)
elif pixbuf:
image.set_from_pixbuf(pixbuf)
image = Gtk.Image(pixbuf=pixbuf, icon_size=Gtk.IconSize.MENU, pixel_size=16)
else:
raise ValueError("At least provide one of, icon name, surface or pixbuf")
image = None

item = Gtk.ImageMenuItem(label=text, image=image, use_underline=True)
item.set_action_name(action_name)
child = item.get_child()
assert isinstance(child, Gtk.AccelLabel)
child.set_use_markup(True)
Expand Down Expand Up @@ -327,7 +328,7 @@
mask = _netmask_for_ifacename(name, sock)
ip_dict[name] = (ipaddr, mask)
except OSError:
logging.error('Socket creation failed', exc_info=True)

Check failure on line 331 in blueman/Functions.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use "logging.exception()" instead.

See more on https://sonarcloud.io/project/issues?id=blueman-project_blueman&issues=AZ41dTBkGVej_5GpMI7e&open=AZ41dTBkGVej_5GpMI7e&pullRequest=2820
return {}

return ip_dict
Expand Down
16 changes: 9 additions & 7 deletions blueman/gui/manager/ManagerDeviceList.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@
else:
return True

def drag_recv(self, _widget: Gtk.Widget, context: Gdk.DragContext, x: int, y: int, selection: Gtk.SelectionData,
_info: int, time: int) -> None:
def drag_recv(self, _list: "ManagerDeviceList", context: Gdk.DragContext, x: int, y: int,
selection: Gtk.SelectionData, _info: int, time: int) -> None:

uris = list(selection.get_uris())

Expand All @@ -180,7 +180,8 @@
else:
context.finish(False, False, time)

def drag_motion(self, _widget: Gtk.Widget, drag_context: Gdk.DragContext, x: int, y: int, timestamp: int) -> bool:
def drag_motion(self, _list: "ManagerDeviceList", drag_context: Gdk.DragContext, x: int, y: int,
timestamp: int) -> bool:
result = self.get_path_at_pos(x, y)
if result is not None:
path = result[0]
Expand All @@ -205,7 +206,8 @@
Gdk.drag_status(drag_context, Gdk.DragAction.DEFAULT, timestamp)
return False

def _on_popup_menu(self, _widget: Gtk.Widget) -> bool:
def _on_popup_menu(self, _list: "ManagerDeviceList") -> bool:

if self.menu is None:
self.menu = ManagerDeviceMenu(self.Blueman)

Expand All @@ -218,7 +220,7 @@

return True

def _on_event_clicked(self, _widget: Gtk.Widget, event: Gdk.Event) -> bool:
def _on_event_clicked(self, _list: "ManagerDeviceList", event: Gdk.Event) -> bool:

Check failure on line 223 in blueman/gui/manager/ManagerDeviceList.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to not always return the same value.

See more on https://sonarcloud.io/project/issues?id=blueman-project_blueman&issues=AZ41dTA_GVej_5GpMI7c&open=AZ41dTA_GVej_5GpMI7c&pullRequest=2820
if event.type not in (Gdk.EventType._2BUTTON_PRESS, Gdk.EventType.BUTTON_PRESS):
return False

Expand Down Expand Up @@ -252,7 +254,7 @@

return False

def _on_key_pressed(self, _widget: Gtk.Widget, event: Gdk.EventKey) -> bool:
def _on_key_pressed(self, _list: "ManagerDeviceList", event: Gdk.EventKey) -> bool:
if not (event.state & Gdk.ModifierType.CONTROL_MASK and event.keyval == Gdk.KEY_c):
return False

Expand Down Expand Up @@ -550,7 +552,7 @@
handler = fader.connect("animation-finished", on_finished)
return fader

def tooltip_query(self, _tw: Gtk.Widget, x: int, y: int, _kb: bool, tooltip: Gtk.Tooltip) -> bool:
def tooltip_query(self, _list: "ManagerDeviceList", x: int, y: int, _kb: bool, tooltip: Gtk.Tooltip) -> bool:

Check failure on line 555 in blueman/gui/manager/ManagerDeviceList.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 51 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=blueman-project_blueman&issues=AZ41dTA_GVej_5GpMI7d&open=AZ41dTA_GVej_5GpMI7d&pullRequest=2820
path = self.get_path_at_pos(x, y)
if path is None:
return False
Expand Down
185 changes: 77 additions & 108 deletions blueman/gui/manager/ManagerDeviceMenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from blueman.bluez.Device import AnyDevice, Device
from blueman.config.AutoConnectConfig import AutoConnectConfig
from blueman.gui.manager.ManagerProgressbar import ManagerProgressbar
from blueman.main.Builder import Builder
from blueman.main.DBusProxies import AppletService, DBusProxyFailed
from blueman.Sdp import (
ServiceUUID,
Expand Down Expand Up @@ -86,9 +85,12 @@
try:
self._appl: AppletService | None = AppletService()
except DBusProxyFailed:
logging.error("** Failed to connect to applet", exc_info=True)

Check failure on line 88 in blueman/gui/manager/ManagerDeviceMenu.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use "logging.exception()" instead.

See more on https://sonarcloud.io/project/issues?id=blueman-project_blueman&issues=AZ41dS-jGVej_5GpMI7b&open=AZ41dS-jGVej_5GpMI7b&pullRequest=2820
self._appl = None

# Popup is not associated with our window which has the Gio.Action
self.attach_to_widget(blueman.window, None)

self.generate()

def __del__(self) -> None:
Expand Down Expand Up @@ -256,15 +258,26 @@
# LE devices do not appear to expose certain properties like uuids until connect to at least once.
return not device_uuids

def _add_seperator(self) -> None:
sep_item = Gtk.SeparatorMenuItem(visible=True)
self.append(sep_item)

def _add_menu_item(self, label: str, icon_name: str | None = None, sensitive: bool = True,
tooltip: str | None = None, action_name: str | None = None) -> Gtk.ImageMenuItem:
item = create_menuitem(text=label, icon_name=icon_name, action_name=action_name)
item.set_sensitive(sensitive)
if tooltip is not None:
item.set_tooltip_text(tooltip)
self.append(item)
return item

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()
posdata = self.Blueman.List.get_path_at_pos(x, y)
Expand All @@ -277,39 +290,36 @@

tree_iter = self.Blueman.List.filter.get_iter(path)
assert tree_iter is not None
child_iter = self.Blueman.List.filter.convert_iter_to_child_iter(tree_iter)
assert child_iter is not None

row = self.Blueman.List.get(child_iter, "alias", "paired", "connected", "trusted", "objpush", "device",
"blocked")
selected = self.Blueman.List.filter.convert_iter_to_child_iter(tree_iter)
assert selected is not None

row = self.Blueman.List.get(selected, "alias", "paired", "connected", "trusted", "objpush", "device", "blocked")
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)
self._add_menu_item(label=op, icon_name="network-transmit-receive-symbolic", sensitive=False)
return

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

powered = Adapter(obj_path=self.SelectedDevice["Adapter"])["Powered"]

if not row["connected"] and show_generic_connect and powered:
connect_item = create_menuitem(_("<b>_Connect</b>"), "bluetooth-symbolic")
connect_item = self._add_menu_item(
label=_("<b>_Connect</b>"),
icon_name="bluetooth-symbolic",
tooltip=_("Connects auto connect profiles A2DP source, A2DP sink, and HID")
)
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 row["connected"] and show_generic_connect:
connect_item = create_menuitem(_("<b>_Disconnect</b>"), "bluetooth-disabled-symbolic")
connect_item.props.tooltip_text = _("Forcefully disconnect the device")
connect_item = self._add_menu_item(
label=_("<b>_Disconnect</b>"),
icon_name="bluetooth-disabled-symbolic",
tooltip=_("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"])

Expand All @@ -331,113 +341,72 @@
for it in sorted(disconnect_items, key=attrgetter("position")):
self.append(it.item)

config = AutoConnectConfig()
auto_connect_config = AutoConnectConfig()
generic_service = ServiceUUID("00000000-0000-0000-0000-000000000000")
object_path = self.SelectedDevice.get_object_path()
btaddress: BtAddress = self.SelectedDevice["Address"]
generic_autoconnect = (object_path, str(generic_service)) in set(config["services"])
generic_autoconnect = (object_path, str(generic_service)) in set(auto_connect_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, (btaddress, str(generic_service)))
item.show()
self.append(item)
auto_connect_item = Gtk.CheckMenuItem(label=generic_service.name)
auto_connect_config.bind_to_menuitem(auto_connect_item, (btaddress, str(generic_service)))
auto_connect_item.show()
self.append(auto_connect_item)

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

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

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

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

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()
if powered and row["objpush"]:
self._add_menu_item(
label=_("Send a _File…"),
icon_name="blueman-send-symbolic",
action_name="app.send"
)

self._add_seperator()

self._add_menu_item(
label=_("_Pair"),
icon_name="blueman-pair-symbolic",
tooltip=_("Create pairing with the device"),
sensitive=not row["paired"],
action_name="app.bond"
)

self._add_menu_item(
label=_("_Untrust") if row["trusted"] else _("_Trust"),
icon_name="blueman-untrust-symbolic" if row["trusted"] else "blueman-trust-symbolic",
tooltip=_("Mark/Unmark this device as trusted"),
action_name="app.trust-toggle"
)

self._add_menu_item(
label=_("_Unblock") if row["blocked"] else _("_Block"),
icon_name="blueman-block-symbolic",
tooltip=_("Block/Unblock this device"),
action_name="app.block-toggle"
)

self._add_menu_item(label=_("R_ename device…"), action_name="app.rename")

if powered:
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")

self._add_seperator()

self._add_menu_item(
label=_("_Remove…"),
icon_name="list-remove-symbolic",
tooltip=_("Remove this device from the known devices list"),
action_name="app.remove"
)
@staticmethod
def _create_header(text: str) -> Gtk.MenuItem:
item = Gtk.MenuItem()
Expand Down
2 changes: 0 additions & 2 deletions blueman/gui/manager/ManagerProgressbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ def __init__(self, blueman: "Blueman", cancellable: bool = True, text: str = _("
ManagerProgressbar.__instances__.append(self)

def _get_window(self) -> Gdk.Window:
assert self.Blueman.window is not None
window = self.Blueman.window.get_window()
assert window is not None
return window
Expand All @@ -81,7 +80,6 @@ def _on_enter(self, _evbox: Gtk.EventBox, _event: Gdk.Event) -> bool:
return False

def _on_leave(self, _evbox: Gtk.EventBox, _event: Gdk.Event) -> bool:
assert self.Blueman.window is not None
self._get_window().set_cursor(None)
return False

Expand Down
Loading
Loading