diff --git a/lib/solaar/ui/__init__.py b/lib/solaar/ui/__init__.py index 290c5b8f80..8b18416673 100644 --- a/lib/solaar/ui/__init__.py +++ b/lib/solaar/ui/__init__.py @@ -17,6 +17,7 @@ import logging +from enum import Enum from typing import Callable import gi @@ -48,6 +49,12 @@ APP_ID = "io.github.pwr_solaar.solaar" +class GtkSignal(Enum): + ACTIVATE = "activate" + COMMAND_LINE = "command-line" + SHUTDOWN = "shutdown" + + def _startup(app, startup_hook, use_tray, show_window): if logger.isEnabledFor(logging.DEBUG): logger.debug("startup registered=%s, remote=%s", app.get_is_registered(), app.get_is_remote()) @@ -108,9 +115,9 @@ def run_loop( lambda app, startup_hook: _startup(app, startup_hook, use_tray, show_window), startup_hook, ) - application.connect("command-line", _command_line) - application.connect("activate", _activate) - application.connect("shutdown", _shutdown, shutdown_hook) + application.connect(GtkSignal.COMMAND_LINE.value, _command_line) + application.connect(GtkSignal.ACTIVATE.value, _activate) + application.connect(GtkSignal.SHUTDOWN.value, _shutdown, shutdown_hook) application.register() if application.get_is_remote(): diff --git a/lib/solaar/ui/about/view.py b/lib/solaar/ui/about/view.py index 6670ac4625..74dc0611aa 100644 --- a/lib/solaar/ui/about/view.py +++ b/lib/solaar/ui/about/view.py @@ -13,8 +13,7 @@ ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - +from enum import Enum from typing import List from typing import Tuple from typing import Union @@ -24,6 +23,10 @@ from solaar import NAME +class GtkSignal(Enum): + RESPONSE = "response" + + class AboutView: def __init__(self) -> None: self.view: Union[Gtk.AboutDialog, None] = None @@ -34,7 +37,7 @@ def init_ui(self) -> None: self.view.set_icon_name(NAME.lower()) self.view.set_license_type(Gtk.License.GPL_2_0) - self.view.connect("response", lambda x, y: self.handle_close(x)) + self.view.connect(GtkSignal.RESPONSE.value, lambda x, y: self.handle_close(x)) def update_version_info(self, version: str) -> None: self.view.set_version(version) diff --git a/lib/solaar/ui/action.py b/lib/solaar/ui/action.py index 0015f55371..58f6dc1a4b 100644 --- a/lib/solaar/ui/action.py +++ b/lib/solaar/ui/action.py @@ -14,6 +14,7 @@ ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +from enum import Enum from gi.repository import Gdk from gi.repository import Gtk @@ -24,6 +25,10 @@ from . import pair_window +class GtkSignal(Enum): + ACTIVATE = "activate" + + def make_image_menu_item(label, icon_name, function, *args): box = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 6) label = Gtk.Label(label=label) @@ -33,7 +38,7 @@ def make_image_menu_item(label, icon_name, function, *args): menu_item = Gtk.MenuItem() menu_item.add(box) menu_item.show_all() - menu_item.connect("activate", function, *args) + menu_item.connect(GtkSignal.ACTIVATE.value, function, *args) menu_item.label = label menu_item.icon = icon return menu_item @@ -45,7 +50,7 @@ def make(name, label, function, stock_id=None, *args): if stock_id is not None: action.set_stock_id(stock_id) if function: - action.connect("activate", function, *args) + action.connect(GtkSignal.ACTIVATE.value, function, *args) return action @@ -54,7 +59,7 @@ def make_toggle(name, label, function, stock_id=None, *args): action.set_icon_name(name) if stock_id is not None: action.set_stock_id(stock_id) - action.connect("activate", function, *args) + action.connect(GtkSignal.ACTIVATE.value, function, *args) return action diff --git a/lib/solaar/ui/config_panel.py b/lib/solaar/ui/config_panel.py index d4a88f874f..b52ae10cff 100644 --- a/lib/solaar/ui/config_panel.py +++ b/lib/solaar/ui/config_panel.py @@ -18,6 +18,7 @@ import logging import traceback +from enum import Enum from threading import Timer import gi @@ -38,6 +39,16 @@ logger = logging.getLogger(__name__) +class GtkSignal(Enum): + ACTIVATE = "activate" + CHANGED = "changed" + CLICKED = "clicked" + MATCH_SELECTED = "match_selected" + NOTIFY_ACTIVE = "notify::active" + TOGGLED = "toggled" + VALUE_CHANGED = "value-changed" + + def _read_async(setting, force_read, sbox, device_is_online, sensitive): def _do_read(s, force, sb, online, sensitive): try: @@ -116,7 +127,7 @@ class ToggleControl(Gtk.Switch, Control): def __init__(self, sbox, delegate=None): super().__init__(halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER) self.init(sbox, delegate) - self.connect("notify::active", self.changed) + self.connect(GtkSignal.NOTIFY_ACTIVE.value, self.changed) def set_value(self, value): if value is not None: @@ -135,7 +146,7 @@ def __init__(self, sbox, delegate=None): self.set_round_digits(0) self.set_digits(0) self.set_increments(1, 5) - self.connect("value-changed", self.changed) + self.connect(GtkSignal.VALUE_CHANGED.value, self.changed) def get_value(self): return int(super().get_value()) @@ -167,7 +178,7 @@ def __init__(self, sbox, delegate=None, choices=None): self.choices = choices if choices is not None else sbox.setting.choices for entry in self.choices: self.append(str(int(entry)), str(entry)) - self.connect("changed", self.changed) + self.connect(GtkSignal.CHANGED.value, self.changed) def get_value(self): return int(self.get_active_id()) if self.get_active_id() is not None else None @@ -205,9 +216,9 @@ def norm(s): completion.set_match_func(lambda completion, key, it: norm(key) in norm(completion.get_model()[it][1])) completion.set_text_column(1) self.set_completion(completion) - self.connect("changed", self.changed) - self.connect("activate", self.activate) - completion.connect("match_selected", self.select) + self.connect(GtkSignal.CHANGED.value, self.changed) + self.connect(GtkSignal.ACTIVATE.value, self.activate) + completion.connect(GtkSignal.MATCH_SELECTED.value, self.select) def get_value(self): choice = self.get_choice() @@ -253,7 +264,7 @@ def __init__(self, sbox, delegate=None): self.valueBox = _create_choice_control(sbox.setting, choices=self.value_choices, delegate=self) self.pack_start(self.keyBox, False, False, 0) self.pack_end(self.valueBox, False, False, 0) - self.keyBox.connect("changed", self.map_value_notify_key) + self.keyBox.connect(GtkSignal.CHANGED.value, self.map_value_notify_key) def get_value(self): key_choice = int(self.keyBox.get_active_id()) @@ -301,7 +312,7 @@ def __init__(self, sbox, change, button_label="...", delegate=None): self._showing = True self.setup(sbox.setting) # set up the data and boxes for the sub-controls btn = Gtk.Button(label=button_label) - btn.connect("clicked", self.toggle_display) + btn.connect(GtkSignal.CLICKED.value, self.toggle_display) self._button = btn hbox = Gtk.HBox(homogeneous=False, spacing=6) hbox.pack_end(change, False, False, 0) @@ -349,7 +360,7 @@ def setup(self, setting): h.set_tooltip_text(lbl_tooltip or " ") control = Gtk.Switch() control._setting_key = int(k) - control.connect("notify::active", self.toggle_notify) + control.connect(GtkSignal.NOTIFY_ACTIVE.value, self.toggle_notify) h.pack_start(lbl, False, False, 0) h.pack_end(control, False, False, 0) lbl.set_margin_start(30) @@ -426,7 +437,7 @@ def setup(self, setting): h.pack_end(control, False, False, 0) else: raise NotImplementedError - control.connect("value-changed", self.changed, item, sub_item) + control.connect(GtkSignal.VALUE_CHANGED.value, self.changed, item, sub_item) item_lb.add(h) h._setting_sub_item = sub_item h._label, h._control = sub_item_lbl, control @@ -487,7 +498,7 @@ def setup(self, setting): control = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, validator.min_value, validator.max_value, 1) control.set_round_digits(0) control.set_digits(0) - control.connect("value-changed", self.changed, validator.keys[item]) + control.connect(GtkSignal.VALUE_CHANGED.value, self.changed, validator.keys[item]) h.pack_start(lbl, False, False, 0) h.pack_end(control, True, True, 0) h._setting_item = validator.keys[item] @@ -548,7 +559,7 @@ def __init__(self, sbox, delegate=None): for entry in item["choices"]: item_box.append(str(int(entry)), str(entry)) item_box.set_active(0) - item_box.connect("changed", self.changed) + item_box.connect(GtkSignal.CHANGED.value, self.changed) self.pack_start(item_box, False, False, 0) elif item["kind"] == settings.Kind.RANGE: item_box = Scale() @@ -556,7 +567,7 @@ def __init__(self, sbox, delegate=None): item_box.set_round_digits(0) item_box.set_digits(0) item_box.set_increments(1, 5) - item_box.connect("value-changed", self.changed) + item_box.connect(GtkSignal.VALUE_CHANGED.value, self.changed) self.pack_start(item_box, True, True, 0) item_box.set_visible(False) self._items[str(item["name"])] = (item_lblbox, item_box) @@ -664,7 +675,7 @@ def _create_sbox(s, _device): change.set_relief(Gtk.ReliefStyle.NONE) change.add(change_icon) change.set_sensitive(True) - change.connect("clicked", _change_click, sbox) + change.connect(GtkSignal.CLICKED.value, _change_click, sbox) if s.kind == settings.Kind.TOGGLE: control = ToggleControl(sbox) diff --git a/lib/solaar/ui/diversion_rules.py b/lib/solaar/ui/diversion_rules.py index 788eab241b..2e3b90de92 100644 --- a/lib/solaar/ui/diversion_rules.py +++ b/lib/solaar/ui/diversion_rules.py @@ -56,6 +56,18 @@ _rule_component_clipboard = None +class GtkSignal(Enum): + ACTIVATE = "activate" + BUTTON_RELEASE_EVENT = "button-release-event" + CHANGED = "changed" + CLICKED = "clicked" + DELETE_EVENT = "delete-event" + KEY_PRESS_EVENT = "key-press-event" + NOTIFY_ACTIVE = "notify::active" + TOGGLED = "toggled" + VALUE_CHANGED = "value_changed" + + def create_all_settings(all_settings: list[Setting]) -> dict[str, list[Setting]]: settings = {} for s in sorted(all_settings, key=lambda setting: setting.label): @@ -333,7 +345,7 @@ def menu_do_flatten(self, _mitem, m, it): def _menu_flatten(self, m, it): menu_flatten = Gtk.MenuItem(_("Flatten")) - menu_flatten.connect("activate", self.menu_do_flatten, m, it) + menu_flatten.connect(GtkSignal.ACTIVATE.value, self.menu_do_flatten, m, it) menu_flatten.show() return menu_flatten @@ -416,7 +428,7 @@ def build(spec): label, feature, *args = spec item = Gtk.MenuItem(label) args = [a.copy() if isinstance(a, list) else a for a in args] - item.connect("activate", self._menu_do_insert_new, m, it, feature, *args, below) + item.connect(GtkSignal.ACTIVATE.value, self._menu_do_insert_new, m, it, feature, *args, below) return item else: return None @@ -427,7 +439,7 @@ def build(spec): def _menu_create_rule(self, m, it, below=False) -> Gtk.MenuItem: menu_create_rule = Gtk.MenuItem(_("Insert new rule")) - menu_create_rule.connect("activate", self._menu_do_insert_new, m, it, diversion.Rule, [], below) + menu_create_rule.connect(GtkSignal.ACTIVATE.value, self._menu_do_insert_new, m, it, diversion.Rule, [], below) menu_create_rule.show() return menu_create_rule @@ -447,7 +459,7 @@ def menu_do_delete(self, _mitem, m, it): def _menu_delete(self, m, it) -> Gtk.MenuItem: menu_delete = Gtk.MenuItem(_("Delete")) - menu_delete.connect("activate", self.menu_do_delete, m, it) + menu_delete.connect(GtkSignal.ACTIVATE.value, self.menu_do_delete, m, it) menu_delete.show() return menu_delete @@ -469,7 +481,7 @@ def menu_do_negate(self, _mitem, m, it): def _menu_negate(self, m, it) -> Gtk.MenuItem: menu_negate = Gtk.MenuItem(_("Negate")) - menu_negate.connect("activate", self.menu_do_negate, m, it) + menu_negate.connect(GtkSignal.ACTIVATE.value, self.menu_do_negate, m, it) menu_negate.show() return menu_negate @@ -497,9 +509,9 @@ def _menu_wrap(self, m, it) -> Gtk.MenuItem: menu_sub_rule = Gtk.MenuItem(_("Sub-rule")) menu_and = Gtk.MenuItem(_("And")) menu_or = Gtk.MenuItem(_("Or")) - menu_sub_rule.connect("activate", self.menu_do_wrap, m, it, diversion.Rule) - menu_and.connect("activate", self.menu_do_wrap, m, it, diversion.And) - menu_or.connect("activate", self.menu_do_wrap, m, it, diversion.Or) + menu_sub_rule.connect(GtkSignal.ACTIVATE.value, self.menu_do_wrap, m, it, diversion.Rule) + menu_and.connect(GtkSignal.ACTIVATE.value, self.menu_do_wrap, m, it, diversion.And) + menu_or.connect(GtkSignal.ACTIVATE.value, self.menu_do_wrap, m, it, diversion.Or) submenu_wrap.append(menu_sub_rule) submenu_wrap.append(menu_and) submenu_wrap.append(menu_or) @@ -523,7 +535,7 @@ def menu_do_cut(self, _mitem, m, it): def _menu_cut(self, m, it): menu_cut = Gtk.MenuItem(_("Cut")) - menu_cut.connect("activate", self.menu_do_cut, m, it) + menu_cut.connect(GtkSignal.ACTIVATE.value, self.menu_do_cut, m, it) menu_cut.show() return menu_cut @@ -539,13 +551,13 @@ def menu_do_paste(self, _mitem, m, it, below=False): def _menu_paste(self, m, it, below=False): menu_paste = Gtk.MenuItem(_("Paste")) - menu_paste.connect("activate", self.menu_do_paste, m, it, below) + menu_paste.connect(GtkSignal.ACTIVATE.value, self.menu_do_paste, m, it, below) menu_paste.show() return menu_paste def _menu_copy(self, m, it): menu_copy = Gtk.MenuItem(_("Copy")) - menu_copy.connect("activate", self.menu_do_copy, m, it) + menu_copy.connect(GtkSignal.ACTIVATE.value, self.menu_do_copy, m, it) menu_copy.show() return menu_copy @@ -554,7 +566,7 @@ class DiversionDialog: def __init__(self, action_menu): window = Gtk.Window() window.set_title(_("Solaar Rule Editor")) - window.connect("delete-event", self._closing) + window.connect(GtkSignal.DELETE_EVENT.value, self._closing) vbox = Gtk.VBox() self.top_panel, self.view = self._create_top_panel() @@ -597,7 +609,7 @@ def __init__(self, action_menu): window.show_all() - window.connect("delete-event", lambda w, e: w.hide_on_delete() or True) + window.connect(GtkSignal.DELETE_EVENT.value, lambda w, e: w.hide_on_delete() or True) style = window.get_style_context() style.add_class("solaar") @@ -645,9 +657,9 @@ def _create_top_panel(self): view.set_enable_tree_lines(True) view.set_reorderable(False) - view.connect("key-press-event", self._event_key_pressed) - view.connect("button-release-event", self._event_button_released) - view.get_selection().connect("changed", self._selection_changed) + view.connect(GtkSignal.KEY_PRESS_EVENT.value, self._event_key_pressed) + view.connect(GtkSignal.BUTTON_RELEASE_EVENT.value, self._event_button_released) + view.get_selection().connect(GtkSignal.CHANGED.value, self._selection_changed) sw.add(view) sw.set_size_request(0, 300) # don't ask for so much height @@ -662,8 +674,8 @@ def _create_top_panel(self): self.discard_btn.set_always_show_image(True) self.discard_btn.set_sensitive(False) self.discard_btn.set_valign(Gtk.Align.CENTER) - self.save_btn.connect("clicked", lambda *_args: self._save_yaml_file()) - self.discard_btn.connect("clicked", lambda *_args: self._reload_yaml_file()) + self.save_btn.connect(GtkSignal.CLICKED.value, lambda *_args: self._save_yaml_file()) + self.discard_btn.connect(GtkSignal.CLICKED.value, lambda *_args: self._reload_yaml_file()) button_box.pack_start(self.save_btn, False, False, 0) button_box.pack_start(self.discard_btn, False, False, 0) button_box.set_halign(Gtk.Align.CENTER) @@ -869,7 +881,7 @@ def replace_with(value): if name != self.get_child().get_text(): self.get_child().set_text(name) - self.connect("changed", lambda *a: replace_with(self.get_value(invalid_as_str=False))) + self.connect(GtkSignal.CHANGED.value, lambda *a: replace_with(self.get_value(invalid_as_str=False))) self.set_id_column(0) if self.get_has_entry(): @@ -1158,7 +1170,7 @@ def create_widgets(self): self.field.set_halign(Gtk.Align.CENTER) self.field.set_valign(Gtk.Align.CENTER) self.field.set_hexpand(True) - self.field.connect("value-changed", self._on_update) + self.field.connect(GtkSignal.VALUE_CHANGED.value, self._on_update) self.widgets[self.field] = (0, 1, 1, 1) def show(self, component, editable): @@ -1226,15 +1238,15 @@ def __init__(self, on_change, *args, accept_toggle=True, **kwargs): ], case_insensitive=True, ) - self.toggle_widget.connect("changed", self._changed) + self.toggle_widget.connect(GtkSignal.CHANGED.value, self._changed) self.range_widget = Gtk.SpinButton.new_with_range(0, 0xFFFF, 1) - self.range_widget.connect("value-changed", self._changed) + self.range_widget.connect(GtkSignal.VALUE_CHANGED.value, self._changed) self.choice_widget = SmartComboBox( [], completion=True, has_entry=True, case_insensitive=True, replace_with_default_name=True ) - self.choice_widget.connect("changed", self._changed) + self.choice_widget.connect(GtkSignal.CHANGED.value, self._changed) self.sub_key_widget = SmartComboBox([]) - self.sub_key_widget.connect("changed", self._changed) + self.sub_key_widget.connect(GtkSignal.CHANGED.value, self._changed) self.unsupported_label = Gtk.Label(label=_("Unsupported setting")) self.pack_start(self.sub_key_widget, False, False, 0) self.sub_key_widget.set_hexpand(False) @@ -1385,7 +1397,7 @@ def create_widgets(self): self.device_field.set_value("") self.device_field.set_valign(Gtk.Align.CENTER) self.device_field.set_size_request(400, 0) - self.device_field.connect("changed", self._on_update) + self.device_field.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.device_field] = (1, 1, 1, 1) def update_devices(self): @@ -1436,7 +1448,7 @@ def create_widgets(self): self.widgets[self.label] = (0, 0, 1, 1) self.field = Gtk.Entry(halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER, hexpand=True) self.field.set_size_request(600, 0) - self.field.connect("changed", self._on_update) + self.field.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.field] = (0, 1, 1, 1) def show(self, component, editable): @@ -1483,8 +1495,8 @@ def create_widgets(self): self.device_field.set_valign(Gtk.Align.CENTER) self.device_field.set_size_request(400, 0) self.device_field.set_margin_top(m) - self.device_field.connect("changed", self._changed_device) - self.device_field.connect("changed", self._on_update) + self.device_field.connect(GtkSignal.CHANGED.value, self._changed_device) + self.device_field.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.device_field] = (1, 1, 1, 1) lbl = Gtk.Label( @@ -1497,8 +1509,8 @@ def create_widgets(self): self.widgets[lbl] = (0, 2, 1, 1) self.setting_field = SmartComboBox([(s[0].name, s[0].label) for s in ALL_SETTINGS.values()]) self.setting_field.set_valign(Gtk.Align.CENTER) - self.setting_field.connect("changed", self._changed_setting) - self.setting_field.connect("changed", self._on_update) + self.setting_field.connect(GtkSignal.CHANGED.value, self._changed_setting) + self.setting_field.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.setting_field] = (1, 2, 1, 1) self.value_lbl = Gtk.Label( @@ -1521,8 +1533,8 @@ def create_widgets(self): self.key_field.set_margin_top(m) self.key_field.hide() self.key_field.set_valign(Gtk.Align.CENTER) - self.key_field.connect("changed", self._changed_key) - self.key_field.connect("changed", self._on_update) + self.key_field.connect(GtkSignal.CHANGED.value, self._changed_key) + self.key_field.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.key_field] = (3, 1, 1, 1) @classmethod diff --git a/lib/solaar/ui/pair_window.py b/lib/solaar/ui/pair_window.py index 84b6353993..9e9eb27316 100644 --- a/lib/solaar/ui/pair_window.py +++ b/lib/solaar/ui/pair_window.py @@ -17,6 +17,8 @@ import logging +from enum import Enum + from gi.repository import GLib from gi.repository import Gtk from logitech_receiver import hidpp10_constants @@ -32,6 +34,11 @@ _STATUS_CHECK = 500 # milliseconds +class GtkSignal(Enum): + CANCEL = "cancel" + CLOSE = "close" + + def create(receiver): receiver.reset_pairing() # clear out any information on previous pairing title = _("%(receiver_name)s: pair new device") % {"receiver_name": receiver.name} @@ -207,8 +214,8 @@ def _create_assistant(receiver, ok, finish, title, text): assistant.set_page_complete(page_intro, True) else: page_intro = _create_failure_page(assistant, receiver.pairing.error) - assistant.connect("cancel", finish, receiver) - assistant.connect("close", finish, receiver) + assistant.connect(GtkSignal.CANCEL.value, finish, receiver) + assistant.connect(GtkSignal.CLOSE.value, finish, receiver) return assistant diff --git a/lib/solaar/ui/rule_actions.py b/lib/solaar/ui/rule_actions.py index 347947b7a1..0a738a6787 100644 --- a/lib/solaar/ui/rule_actions.py +++ b/lib/solaar/ui/rule_actions.py @@ -13,7 +13,7 @@ ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - +from enum import Enum from shlex import quote as shlex_quote from gi.repository import Gtk @@ -29,6 +29,12 @@ from solaar.ui.rule_base import RuleComponentUI +class GtkSignal(Enum): + CHANGED = "changed" + CLICKED = "clicked" + TOGGLED = "toggled" + + class ActionUI(RuleComponentUI): CLASS = diversion.Action @@ -51,21 +57,21 @@ def create_widgets(self): self.widgets[self.label] = (0, 0, 5, 1) self.del_btns = [] self.add_btn = Gtk.Button(label=_("Add key"), halign=Gtk.Align.CENTER, valign=Gtk.Align.END, hexpand=True) - self.add_btn.connect("clicked", self._clicked_add) + self.add_btn.connect(GtkSignal.CLICKED.value, self._clicked_add) self.widgets[self.add_btn] = (1, 1, 1, 1) self.action_clicked_radio = Gtk.RadioButton.new_with_label_from_widget(None, _("Click")) - self.action_clicked_radio.connect("toggled", self._on_update, CLICK) + self.action_clicked_radio.connect(GtkSignal.TOGGLED.value, self._on_update, CLICK) self.widgets[self.action_clicked_radio] = (0, 3, 1, 1) self.action_pressed_radio = Gtk.RadioButton.new_with_label_from_widget(self.action_clicked_radio, _("Depress")) - self.action_pressed_radio.connect("toggled", self._on_update, DEPRESS) + self.action_pressed_radio.connect(GtkSignal.TOGGLED.value, self._on_update, DEPRESS) self.widgets[self.action_pressed_radio] = (1, 3, 1, 1) self.action_released_radio = Gtk.RadioButton.new_with_label_from_widget(self.action_pressed_radio, _("Release")) - self.action_released_radio.connect("toggled", self._on_update, RELEASE) + self.action_released_radio.connect(GtkSignal.TOGGLED.value, self._on_update, RELEASE) self.widgets[self.action_released_radio] = (2, 3, 1, 1) def _create_field(self): field_entry = CompletionEntry(self.KEY_NAMES, halign=Gtk.Align.CENTER, valign=Gtk.Align.END, hexpand=True) - field_entry.connect("changed", self._on_update) + field_entry.connect(GtkSignal.CHANGED.value, self._on_update) self.fields.append(field_entry) self.widgets[field_entry] = (len(self.fields) - 1, 1, 1, 1) return field_entry @@ -74,7 +80,7 @@ def _create_del_btn(self): btn = Gtk.Button(label=_("Delete"), halign=Gtk.Align.CENTER, valign=Gtk.Align.START, hexpand=True) self.del_btns.append(btn) self.widgets[btn] = (len(self.del_btns) - 1, 2, 1, 1) - btn.connect("clicked", self._clicked_del, len(self.del_btns) - 1) + btn.connect(GtkSignal.CLICKED.value, self._clicked_del, len(self.del_btns) - 1) return btn def _clicked_add(self, _btn): @@ -153,8 +159,8 @@ def create_widgets(self): for f in [self.field_x, self.field_y]: f.set_halign(Gtk.Align.CENTER) f.set_valign(Gtk.Align.START) - self.field_x.connect("changed", self._on_update) - self.field_y.connect("changed", self._on_update) + self.field_x.connect(GtkSignal.CHANGED.value, self._on_update) + self.field_y.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.label_x] = (0, 1, 1, 1) self.widgets[self.field_x] = (1, 1, 1, 1) self.widgets[self.label_y] = (2, 1, 1, 1) @@ -210,9 +216,9 @@ def create_widgets(self): for f in [self.field_b, self.field_c]: f.set_halign(Gtk.Align.CENTER) f.set_valign(Gtk.Align.START) - self.field_b.connect("changed", self._on_update) - self.field_c.connect("changed", self._on_update) - self.field_d.connect("changed", self._on_update) + self.field_b.connect(GtkSignal.CHANGED.value, self._on_update) + self.field_c.connect(GtkSignal.CHANGED.value, self._on_update) + self.field_d.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.label_b] = (0, 1, 1, 1) self.widgets[self.field_b] = (1, 1, 1, 1) self.widgets[self.label_c] = (2, 1, 1, 1) @@ -257,13 +263,13 @@ def create_widgets(self): self.fields = [] self.add_btn = Gtk.Button(label=_("Add argument"), halign=Gtk.Align.CENTER, valign=Gtk.Align.END, hexpand=True) self.del_btns = [] - self.add_btn.connect("clicked", self._clicked_add) + self.add_btn.connect(GtkSignal.CLICKED.value, self._clicked_add) self.widgets[self.add_btn] = (1, 1, 1, 1) def _create_field(self): field_entry = Gtk.Entry(halign=Gtk.Align.CENTER, valign=Gtk.Align.END, hexpand=True) field_entry.set_size_request(150, 0) - field_entry.connect("changed", self._on_update) + field_entry.connect(GtkSignal.CHANGED.value, self._on_update) self.fields.append(field_entry) self.widgets[field_entry] = (len(self.fields) - 1, 1, 1, 1) return field_entry @@ -273,7 +279,7 @@ def _create_del_btn(self): btn.set_size_request(150, 0) self.del_btns.append(btn) self.widgets[btn] = (len(self.del_btns) - 1, 2, 1, 1) - btn.connect("clicked", self._clicked_del, len(self.del_btns) - 1) + btn.connect(GtkSignal.CLICKED.value, self._clicked_del, len(self.del_btns) - 1) return btn def _clicked_add(self, *_args): diff --git a/lib/solaar/ui/rule_conditions.py b/lib/solaar/ui/rule_conditions.py index 82fb8429e5..5ef5133514 100644 --- a/lib/solaar/ui/rule_conditions.py +++ b/lib/solaar/ui/rule_conditions.py @@ -14,6 +14,7 @@ ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. from dataclasses import dataclass +from enum import Enum from gi.repository import Gtk from logitech_receiver import diversion @@ -26,6 +27,14 @@ from solaar.ui.rule_base import RuleComponentUI +class GtkSignal(Enum): + CHANGED = "changed" + CLICKED = "clicked" + NOTIFY_ACTIVE = "notify::active" + TOGGLED = "toggled" + VALUE_CHANGED = "value-changed" + + class ConditionUI(RuleComponentUI): CLASS = diversion.Condition @@ -44,7 +53,7 @@ def create_widgets(self): self.widgets[self.label] = (0, 0, 1, 1) self.field = Gtk.Entry(halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER, hexpand=True) self.field.set_size_request(600, 0) - self.field.connect("changed", self._on_update) + self.field.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.field] = (0, 1, 1, 1) def show(self, component, editable=True): @@ -74,7 +83,7 @@ def create_widgets(self): self.widgets[self.label] = (0, 0, 1, 1) self.field = Gtk.Entry(halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER, hexpand=True) self.field.set_size_request(600, 0) - self.field.connect("changed", self._on_update) + self.field.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.field] = (0, 1, 1, 1) def show(self, component, editable=True): @@ -119,7 +128,7 @@ def create_widgets(self): self.field.append(feature, feature) self.field.set_valign(Gtk.Align.CENTER) self.field.set_size_request(600, 0) - self.field.connect("changed", self._on_update) + self.field.connect(GtkSignal.CHANGED.value, self._on_update) all_features = [str(f) for f in SupportedFeature] CompletionEntry.add_completion_to_entry(self.field.get_child(), all_features) self.widgets[self.field] = (0, 1, 1, 1) @@ -163,7 +172,7 @@ def create_widgets(self): self.field.set_halign(Gtk.Align.CENTER) self.field.set_valign(Gtk.Align.CENTER) self.field.set_hexpand(True) - self.field.connect("changed", self._on_update) + self.field.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.field] = (0, 1, 1, 1) def show(self, component, editable=True): @@ -200,7 +209,7 @@ def create_widgets(self): self.widgets[switch] = (i, 2, 1, 1) self.labels[m] = label self.switches[m] = switch - switch.connect("notify::active", self._on_update) + switch.connect(GtkSignal.NOTIFY_ACTIVE.value, self._on_update) def show(self, component, editable=True): super().show(component, editable) @@ -236,13 +245,13 @@ def create_widgets(self): self.widgets[self.label] = (0, 0, 5, 1) self.key_field = CompletionEntry(self.KEY_NAMES, halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER, hexpand=True) self.key_field.set_size_request(600, 0) - self.key_field.connect("changed", self._on_update) + self.key_field.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.key_field] = (0, 1, 2, 1) self.action_pressed_radio = Gtk.RadioButton.new_with_label_from_widget(None, _("Key down")) - self.action_pressed_radio.connect("toggled", self._on_update, Key.DOWN) + self.action_pressed_radio.connect(GtkSignal.TOGGLED.value, self._on_update, Key.DOWN) self.widgets[self.action_pressed_radio] = (2, 1, 1, 1) self.action_released_radio = Gtk.RadioButton.new_with_label_from_widget(self.action_pressed_radio, _("Key up")) - self.action_released_radio.connect("toggled", self._on_update, Key.UP) + self.action_released_radio.connect(GtkSignal.TOGGLED.value, self._on_update, Key.UP) self.widgets[self.action_released_radio] = (3, 1, 1, 1) def show(self, component, editable=True): @@ -288,7 +297,7 @@ def create_widgets(self): self.widgets[self.label] = (0, 0, 5, 1) self.key_field = CompletionEntry(self.KEY_NAMES, halign=Gtk.Align.CENTER, valign=Gtk.Align.CENTER, hexpand=True) self.key_field.set_size_request(600, 0) - self.key_field.connect("changed", self._on_update) + self.key_field.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.key_field] = (0, 1, 1, 1) def show(self, component, editable=True): @@ -335,12 +344,12 @@ def create_widgets(self): self.test.set_hexpand(False) self.test.set_size_request(300, 0) CompletionEntry.add_completion_to_entry(self.test.get_child(), diversion.TESTS) - self.test.connect("changed", self._on_update) + self.test.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.test] = (1, 1, 1, 1) self.parameter = Gtk.Entry(halign=Gtk.Align.CENTER, valign=Gtk.Align.END, hexpand=True) self.parameter.set_size_request(150, 0) - self.parameter.connect("changed", self._on_update) + self.parameter.connect(GtkSignal.CHANGED.value, self._on_update) self.widgets[self.parameter] = (3, 1, 1, 1) def show(self, component, editable=True): @@ -444,14 +453,14 @@ def create_widgets(self): field = Gtk.SpinButton.new_with_range(element.min, element.max, 1) field.set_value(0) field.set_size_request(150, 0) - field.connect("value-changed", self._on_update) + field.connect(GtkSignal.VALUE_CHANGED.value, self._on_update) label = Gtk.Label(label=element.label, margin_top=20) self.fields[element.id] = field self.field_labels[element.id] = label self.widgets[label] = (col, 1, 1, 1) self.widgets[field] = (col, 2, 1, 1) col += 1 if col != mode_col - 1 else 2 - self.mode_field.connect("changed", lambda cb: (self._on_update(), self._only_mode(cb.get_active_id()))) + self.mode_field.connect(GtkSignal.CHANGED.value, lambda cb: (self._on_update(), self._only_mode(cb.get_active_id()))) self.mode_field.set_active_id("range") def show(self, component, editable=True): @@ -529,7 +538,7 @@ def create_widgets(self): self.widgets[self.label] = (0, 0, 5, 1) self.del_btns = [] self.add_btn = Gtk.Button(label=_("Add movement"), halign=Gtk.Align.CENTER, valign=Gtk.Align.END, hexpand=True) - self.add_btn.connect("clicked", self._clicked_add) + self.add_btn.connect(GtkSignal.CLICKED.value, self._clicked_add) self.widgets[self.add_btn] = (1, 1, 1, 1) def _create_field(self): @@ -537,7 +546,7 @@ def _create_field(self): for g in self.MOUSE_GESTURE_NAMES: field.append(g, g) CompletionEntry.add_completion_to_entry(field.get_child(), self.MOVE_NAMES) - field.connect("changed", self._on_update) + field.connect(GtkSignal.CHANGED.value, self._on_update) self.fields.append(field) self.widgets[field] = (len(self.fields) - 1, 1, 1, 1) return field @@ -546,7 +555,7 @@ def _create_del_btn(self): btn = Gtk.Button(label=_("Delete"), halign=Gtk.Align.CENTER, valign=Gtk.Align.START, hexpand=True) self.del_btns.append(btn) self.widgets[btn] = (len(self.del_btns) - 1, 2, 1, 1) - btn.connect("clicked", self._clicked_del, len(self.del_btns) - 1) + btn.connect(GtkSignal.CLICKED.value, self._clicked_del, len(self.del_btns) - 1) return btn def _clicked_add(self, _btn): diff --git a/lib/solaar/ui/tray.py b/lib/solaar/ui/tray.py index f89855c749..ef08a94c96 100644 --- a/lib/solaar/ui/tray.py +++ b/lib/solaar/ui/tray.py @@ -18,6 +18,7 @@ import logging import os +from enum import Enum from time import time import gi @@ -42,6 +43,11 @@ _MENU_ICON_SIZE = Gtk.IconSize.LARGE_TOOLBAR +class GtkSignal(Enum): + ACTIVATE = "activate" + SCROLL_EVENT = "scroll-event" + + def _create_menu(quit_handler): # per-device menu entries will be generated as-needed menu = Gtk.Menu() @@ -172,7 +178,7 @@ def _create(menu): # ind.set_label(NAME.lower(), NAME.lower()) ind.set_menu(menu) - ind.connect("scroll-event", _scroll) + ind.connect(GtkSignal.SCROLL_EVENT.value, _scroll) return ind @@ -214,8 +220,8 @@ def _create(menu): icon.set_name(NAME.lower()) icon.set_title(NAME) icon.set_tooltip_text(NAME) - icon.connect("activate", window.toggle) - icon.connect("scroll-event", _scroll) + icon.connect(GtkSignal.ACTIVATE.value, window.toggle) + icon.connect(GtkSignal.SCROLL_EVENT.value, _scroll) icon.connect( "popup-menu", lambda icon, button, time: menu.popup(None, None, icon.position_menu, icon, button, time), diff --git a/lib/solaar/ui/window.py b/lib/solaar/ui/window.py index 594a529a6d..e26cb7af00 100644 --- a/lib/solaar/ui/window.py +++ b/lib/solaar/ui/window.py @@ -17,6 +17,7 @@ import logging +from enum import Enum from enum import IntEnum import gi @@ -75,6 +76,12 @@ class Column(IntEnum): assert len(_COLUMN_TYPES) == len(Column) +class GtkSignal(Enum): + CHANGED = "changed" + CLICKED = "clicked" + DELETE_EVENT = "delete-event" + + def _new_button(label, icon_name=None, icon_size=_NORMAL_BUTTON_ICON_SIZE, tooltip=None, toggle=False, clicked=None): b = Gtk.ToggleButton() if toggle else Gtk.Button() c = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 5) @@ -84,7 +91,7 @@ def _new_button(label, icon_name=None, icon_size=_NORMAL_BUTTON_ICON_SIZE, toolt c.pack_start(Gtk.Label(label=label), True, True, 0) b.add(c) if clicked is not None: - b.connect("clicked", clicked) + b.connect(GtkSignal.CLICKED.value, clicked) if tooltip: b.set_tooltip_text(tooltip) if not label and icon_size < _NORMAL_BUTTON_ICON_SIZE: @@ -296,7 +303,7 @@ def _create_window_layout(): assert _empty is not None assert _tree.get_selection().get_mode() == Gtk.SelectionMode.SINGLE - _tree.get_selection().connect("changed", _device_selected) + _tree.get_selection().connect(GtkSignal.CHANGED.value, _device_selected) tree_scroll = Gtk.ScrolledWindow() tree_scroll.add(_tree) @@ -341,7 +348,7 @@ def _create(delete_action): window = Gtk.Window() window.set_title(NAME) window.set_role("status-window") - window.connect("delete-event", delete_action) + window.connect(GtkSignal.DELETE_EVENT.value, delete_action) vbox = _create_window_layout() window.add(vbox)