From 70790768572963822e63ccc3890924421b918a7f Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Thu, 8 Jun 2023 11:44:47 -0400 Subject: [PATCH] nowplaying: Add keyboard accelerators I add accelerators for play, pause, next track, previous track, setting autopause, adding the current track to the favorites playlist, and scrolling to the current track in the tracklist. Signed-off-by: Anna Schumaker --- emmental/__init__.py | 2 ++ emmental/nowplaying/__init__.py | 24 +++++++++++++++++++ tests/nowplaying/test_nowplaying.py | 36 +++++++++++++++++++++++++++++ tests/test_emmental.py | 13 +++++++++++ 4 files changed, 75 insertions(+) diff --git a/emmental/__init__.py b/emmental/__init__.py index 72ce0f9..8256869 100644 --- a/emmental/__init__.py +++ b/emmental/__init__.py @@ -167,6 +167,8 @@ class Application(Adw.Application): self.db.settings.bind_setting("now-playing.prefer-artist", playing, "prefer-artist") + self.__add_accelerators(playing.accelerators) + playing.connect("jump", self.__on_jump) playing.connect("play", self.player.play) playing.connect("pause", self.player.pause) diff --git a/emmental/nowplaying/__init__.py b/emmental/nowplaying/__init__.py index 38fa906..f2e647c 100644 --- a/emmental/nowplaying/__init__.py +++ b/emmental/nowplaying/__init__.py @@ -2,6 +2,7 @@ """A card for displaying information about the currently playing track.""" from gi.repository import GObject from gi.repository import Gtk +from ..action import ActionEntry from .. import buttons from . import artwork from . import controls @@ -95,6 +96,29 @@ class Card(Gtk.Box): value: float) -> None: self.emit("seek", value) + @property + def accelerators(self) -> list[ActionEntry]: + """Get a list of accelerators for the Now Playing card.""" + return [ActionEntry("toggle-favorite", self._favorite.activate, + "f", enabled=(self, "have-db-track")), + ActionEntry("goto-current-track", self._jump.activate, + "g", enabled=(self, "have-db-track")), + ActionEntry("next-track", self._controls.activate_next, + "Return", enabled=(self._controls, + "can-activate-next")), + ActionEntry("previous-track", self._controls.activate_previous, + "BackSpace", enabled=(self._controls, + "can-activate-prev")), + ActionEntry("play-pause", self._controls.activate_play_pause, + "space", enabled=(self._controls, + "can-activate-play-pause")), + ActionEntry("inc-autopause", self._controls.increase_autopause, + "plus", "KP_Add", + enabled=(self, "playing")), + ActionEntry("dec-autopause", self._controls.decrease_autopause, + "minus", "KP_Subtract", + enabled=(self, "playing"))] + @GObject.Signal def jump(self) -> None: """Signal that the Tracklist should be scrolled.""" diff --git a/tests/nowplaying/test_nowplaying.py b/tests/nowplaying/test_nowplaying.py index ef00c0e..7804044 100644 --- a/tests/nowplaying/test_nowplaying.py +++ b/tests/nowplaying/test_nowplaying.py @@ -190,3 +190,39 @@ class TestNowPlaying(unittest.TestCase): self.assertEqual(self.card.position, 0) self.card.position = 0.5 self.assertEqual(self.card._seeker.position, 0.5) + + def test_accelerators(self): + """Check that the accelerators list is set up properly.""" + entries = [("toggle-favorite", self.card._favorite.activate, + ["f"], self.card, "have-db-track"), + ("goto-current-track", self.card._jump.activate, + ["g"], self.card, "have-db-track"), + ("next-track", self.card._controls.activate_next, + ["Return"], self.card._controls, "can-activate-next"), + ("previous-track", self.card._controls.activate_previous, + ["BackSpace"], self.card._controls, "can-activate-prev"), + ("play-pause", self.card._controls.activate_play_pause, + ["space"], self.card._controls, "can-activate-play-pause"), + ("inc-autopause", self.card._controls.increase_autopause, + ["plus", "KP_Add"], + self.card, "playing"), + ("dec-autopause", self.card._controls.decrease_autopause, + ["minus", "KP_Subtract"], + self.card, "playing")] + + accels = self.card.accelerators + self.assertIsInstance(accels, list) + + for i, (name, func, accel, gobject, prop) in enumerate(entries): + with self.subTest(action=name): + self.assertIsInstance(accels[i], emmental.action.ActionEntry) + self.assertEqual(accels[i].name, name) + self.assertEqual(accels[i].func, func) + self.assertListEqual(accels[i].accels, accel) + + enabled = gobject.get_property(prop) + self.assertEqual(accels[i].enabled, enabled) + gobject.set_property(prop, not enabled) + self.assertEqual(accels[i].enabled, not enabled) + + self.assertEqual(len(accels), i + 1) diff --git a/tests/test_emmental.py b/tests/test_emmental.py index 7627cec..36357bf 100644 --- a/tests/test_emmental.py +++ b/tests/test_emmental.py @@ -148,6 +148,19 @@ class TestEmmental(unittest.TestCase): self.application.player = emmental.audio.Player() win = self.application.build_window() + for action, accel in [("app.toggle-favorite", ["f"]), + ("app.goto-current-track", ["g"]), + ("app.next-track", ["Return"]), + ("app.previous-track", ["BackSpace"]), + ("app.play-pause", ["space"]), + ("app.inc-autopause", ["plus", + "KP_Add"]), + ("app.dec-autopause", ["minus", + "KP_Subtract"])]: + with self.subTest(action=action): + accels = self.application.get_accels_for_action(action) + self.assertListEqual(accels, accel) + for (property, value) in [("have-track", True), ("playing", True), ("duration", 10), ("position", 5), ("artwork", "/a/b/c.jpg")]: