def test_change(shortcut_engine, mocker): callback = mocker.Mock(return_value=True) old_shortcut = Shortcut("start", "<control>a") new_shortcut = Shortcut("start", "<control>b") shortcut_engine.connect(old_shortcut, callback) shortcut_engine.change(new_shortcut) assert active_shortcut(shortcut_engine, old_shortcut) is False assert active_shortcut(shortcut_engine, new_shortcut) is True key, mod = Gtk.accelerator_parse(new_shortcut.value) callback.assert_called_once_with(shortcut_engine.accel_group, mocker.ANY, key, mod)
def test_disconnect(shortcut_engine, mocker): shortcut = Shortcut("start", "<control>s") shortcut_engine.connect(shortcut, mocker.Mock()) shortcut_engine.disconnect(shortcut) assert active_shortcut(shortcut_engine, shortcut) is False
class Menu(Subscriber): PREFERENCE_SHORTCUT = Shortcut("session.settings", "<control>comma") @inject( bus="focusyn.bus", about="focusyn.ui.about", preference="focusyn.ui.preference", shortcuts="focusyn.ui.shortcut", ) def __init__(self, bus: Bus, about, preference, shortcuts: ShortcutEngine): self.connect(bus) self.widget = Gtk.Menu(halign=Gtk.Align.CENTER) self.widget.add( self._create_menu_item("header.menu.preference", _("Preferences"), preference.widget)) self.widget.add( self._create_menu_item("header.menu.about", _("About"), about.widget)) self.widget.show_all() shortcuts.connect(Menu.PREFERENCE_SHORTCUT, lambda *_: preference.widget.run()) def _create_menu_item(self, name: str, label: str, dialog: Gtk.Dialog) -> Gtk.MenuItem: menu_item = Gtk.MenuItem.new_with_label(label) menu_item.props.name = name menu_item.connect("activate", lambda *_: dialog.run()) return menu_item
def test_connect(shortcut_engine, mocker): callback = mocker.Mock(return_value=True) shortcut = Shortcut("start", "<control>s") shortcut_engine.connect(shortcut, callback) assert active_shortcut(shortcut_engine, shortcut) is True key, mod = Gtk.accelerator_parse(shortcut.value) callback.assert_called_once_with(shortcut_engine.accel_group, mocker.ANY, key, mod)
class SessionButton(Subscriber): POMODORO_SHORTCUT = Shortcut("session.pomodoro", "<control>1") SHORT_BREAK_SHORTCUT = Shortcut("session.short_break", "<control>2") LONG_BREAK_SHORTCUT = Shortcut("session.long_break", "<control>3") @inject( bus="focusyn.bus", session="focusyn.session", shortcuts="focusyn.ui.shortcut", ) def __init__(self, bus: Bus, session: Session, shortcuts: ShortcutEngine): self.connect(bus) self._session = session self.widget = ModeButton( can_focus=False, homogeneous=True, margin_bottom=12, margin_left=12, margin_right=12, ) self.widget.append_text( _("Pomodoro"), tooltip_text=_("Pomodoro ({})".format( shortcuts.label(SessionButton.POMODORO_SHORTCUT))), name=SessionButton.POMODORO_SHORTCUT.name, ) shortcuts.connect(SessionButton.POMODORO_SHORTCUT, self._change_session(SessionType.POMODORO)) self.widget.append_text( _("Short Break"), tooltip_text=_("Short Break ({})".format( shortcuts.label(SessionButton.SHORT_BREAK_SHORTCUT))), name=SessionButton.SHORT_BREAK_SHORTCUT.name, ) shortcuts.connect(SessionButton.SHORT_BREAK_SHORTCUT, self._change_session(SessionType.SHORT_BREAK)) self.widget.append_text( _("Long Break"), tooltip_text=_("Long Break ({})".format( shortcuts.label(SessionButton.LONG_BREAK_SHORTCUT))), name=SessionButton.LONG_BREAK_SHORTCUT.name, ) shortcuts.connect(SessionButton.LONG_BREAK_SHORTCUT, self._change_session(SessionType.LONG_BREAK)) self.widget.connect("mode_changed", self._on_button_clicked) def _change_session(self, session_type: SessionType) -> Callable[[], bool]: def callback(*_) -> bool: logger.debug("action=change session=%s", session_type) self.widget.set_selected(session_type.value) return True return callback def _on_button_clicked(self, _, number): session_type = SessionType.of(number) logger.debug("action=mode_changed session=%s", session_type) self._session.change(session=session_type) def init(self): self.widget.set_sensitive(True) self.widget.set_selected(SessionType.POMODORO.value) @on(Events.SESSION_START) def _on_session_start(self, *_, **__): logger.debug("action=disable") self.widget.set_sensitive(False) @on(Events.SESSION_INTERRUPT, Events.SESSION_END) def _on_session_stop(self, _, payload: Union[SessionPayload, SessionEndPayload]): logger.debug("action=enable session=%s", payload.type) self.widget.set_sensitive(True) self.widget.set_selected(payload.type.value)
def test_label_with_fallback(shortcut_engine): label = shortcut_engine.label(Shortcut("", "<control>p")) assert label == "Ctrl+P"
def test_label(shortcut_engine): label = shortcut_engine.label(Shortcut("test", "")) assert label == "Ctrl+S"
class HeaderBar(Subscriber): START_SHORTCUT = Shortcut("session.start", "<control>s") STOP_SHORTCUT = Shortcut("session.stop", "<control>p") RESET_SHORTCUT = Shortcut("session.reset", "<control>r") @inject( bus="focusyn.bus", menu="focusyn.ui.headerbar.menu", session="focusyn.session", shortcuts="focusyn.ui.shortcut", ) def __init__(self, bus: Bus, menu: Menu, session: Session, shortcuts: ShortcutEngine): self.connect(bus) self.widget = Gtk.HeaderBar( show_close_button=True, title=_("No session yet"), decoration_layout=":close", ) self._start_button = self._create_button( Gtk.STOCK_MEDIA_PLAY, ("Starts the session ({})".format( shortcuts.label(HeaderBar.START_SHORTCUT))), lambda *_: session.start(), name=HeaderBar.START_SHORTCUT.name, ) self.widget.pack_start(self._start_button) shortcuts.connect(HeaderBar.START_SHORTCUT, lambda *_: session.start()) self._stop_button = self._create_button( Gtk.STOCK_MEDIA_STOP, ("Stops the session ({})".format( shortcuts.label(HeaderBar.STOP_SHORTCUT))), lambda *_: session.stop(), name=HeaderBar.STOP_SHORTCUT.name, no_show_all=True, visible=False, ) self.widget.pack_start(self._stop_button) shortcuts.connect(HeaderBar.STOP_SHORTCUT, lambda *_: session.stop()) self._reset_button = self._create_button( Gtk.STOCK_CLEAR, ("Clear session count ({})".format( shortcuts.label(HeaderBar.RESET_SHORTCUT))), lambda *_: session.reset(), name=HeaderBar.RESET_SHORTCUT.name, sensitive=False, ) self.widget.pack_start(self._reset_button) shortcuts.connect(HeaderBar.RESET_SHORTCUT, lambda *_: session.reset()) icon = Gtk.Image.new_from_icon_name(Gtk.STOCK_PREFERENCES, Gtk.IconSize.BUTTON) button = Gtk.MenuButton( name=Menu.PREFERENCE_SHORTCUT.name, popup=menu.widget, tooltip_text=_("Open preferences ({})".format( shortcuts.label(Menu.PREFERENCE_SHORTCUT))), ) button.add(icon) self.widget.pack_end(button) def _create_button(self, icon: str, tooltip_text: str, on_clicked, **props) -> Gtk.Button: image = Gtk.Image.new_from_icon_name(icon, Gtk.IconSize.BUTTON) image.show() button = Gtk.Button(tooltip_text=tooltip_text, **props) button.add(image) button.connect("clicked", on_clicked) return button @on(Events.SESSION_START) def _on_session_start(self, *_, **__): logger.debug("action=enable_stop") self._start_button.props.visible = False self._stop_button.props.visible = True self._reset_button.props.sensitive = False @on(Events.SESSION_INTERRUPT, Events.SESSION_END) def _on_session_stop( self, _, payload: Union[SessionEndPayload, SessionPayload]) -> None: logger.debug("action=enable_start pomodoros=%d", payload.pomodoros) self._start_button.props.visible = True self._stop_button.props.visible = False self._reset_button.props.sensitive = bool(payload.pomodoros) self._update_title(payload.pomodoros) @on(Events.SESSION_RESET) def _on_session_reset(self, *_, **__): logger.debug("action=disable_reset") self._reset_button.props.sensitive = False self._update_title(0) def _update_title(self, pomodoros: int) -> None: self.widget.props.title = _("Session {}".format( pomodoros)) if pomodoros else _("No session yet")