diff --git a/emmental/__init__.py b/emmental/__init__.py index b82bf2e..b1801f6 100644 --- a/emmental/__init__.py +++ b/emmental/__init__.py @@ -195,6 +195,8 @@ class Application(Adw.Application): self.db.settings.bind_setting(f"tracklist.{name}.visible", column, "visible") self.factory.bind_property("visible-playlist", track_list, "playlist") + + self.__add_accelerators(track_list.accelerators) return track_list def build_window(self) -> window.Window: diff --git a/emmental/header/__init__.py b/emmental/header/__init__.py index cdf23b0..25528a0 100644 --- a/emmental/header/__init__.py +++ b/emmental/header/__init__.py @@ -124,9 +124,9 @@ class Header(Gtk.HeaderBar): """Get a list of accelerators for the Header.""" res = [ActionEntry("open-file", self._open.activate, "o"), ActionEntry("decrease-volume", self._volume.decrement, - "Down"), + "Down"), ActionEntry("increase-volume", self._volume.increment, - "Up"), + "Up"), ActionEntry("toggle-bg-mode", self._background.activate, "b")] if __debug__: diff --git a/emmental/tracklist/__init__.py b/emmental/tracklist/__init__.py index 5b8fa1a..b83f44f 100644 --- a/emmental/tracklist/__init__.py +++ b/emmental/tracklist/__init__.py @@ -4,6 +4,7 @@ from gi.repository import GObject from gi.repository import GLib from gi.repository import Gio from gi.repository import Gtk +from ..action import ActionEntry from ..playlist.playlist import Playlist from ..playlist.previous import Previous from .. import db @@ -143,3 +144,18 @@ class Card(Gtk.Box): self._top_right.set_sensitive(not isinstance(newval, Previous)) self.__set_button_state() newval.connect("notify", self.__playlist_notify) + + @property + def accelerators(self) -> list[ActionEntry]: + """Get a list of accelerators for the Tracklist.""" + return [ActionEntry("focus-search-track", self._filter.grab_focus, + "slash"), + ActionEntry("clear-selected-tracks", self._unselect.activate, + "Escape", enabled=(self._unselect, "sensitive")), + ActionEntry("cycle-loop", self._loop.activate, + "l", enabled=(self._top_right, + "sensitive")), + ActionEntry("toggle-shuffle", self._shuffle.activate, + "s", enabled=(self._top_right, + "sensitive"))] + \ + self._osd.accelerators diff --git a/emmental/tracklist/selection.py b/emmental/tracklist/selection.py index 6817df1..2132264 100644 --- a/emmental/tracklist/selection.py +++ b/emmental/tracklist/selection.py @@ -4,6 +4,7 @@ from gi.repository import GObject from gi.repository import Gdk from gi.repository import Gtk from gi.repository import Adw +from ..action import ActionEntry from ..buttons import PopoverButton from .. import db from .. import playlist @@ -257,3 +258,15 @@ class OSD(Gtk.Overlay): self.__selection_changed(self.selection, 0, 0) if self.playlist is not None: self._add.popover_child.playlist = self.playlist.playlist + + @property + def accelerators(self) -> list[ActionEntry]: + """Get a list of accelerators for the OSD.""" + return [ActionEntry("remove-selected-tracks", self._remove.activate, + "Delete", enabled=(self._remove, "visible")), + ActionEntry("move-track-up", self._move._up.activate, + "Up", + enabled=(self._move, "can-move-up")), + ActionEntry("move-track-down", self._move._down.activate, + "Down", + enabled=(self._move, "can-move-down"))] diff --git a/tests/header/test_header.py b/tests/header/test_header.py index acf67b7..65eb268 100644 --- a/tests/header/test_header.py +++ b/tests/header/test_header.py @@ -185,9 +185,9 @@ class TestHeader(tests.util.TestCase): """Check that the accelerators list is set up properly.""" entries = [("open-file", self.header._open.activate, "o"), ("decrease-volume", self.header._volume.decrement, - "Down"), + "Down"), ("increase-volume", self.header._volume.increment, - "Up"), + "Up"), ("toggle-bg-mode", self.header._background.activate, "b"), ("edit-settings", self.header._settings.activate, diff --git a/tests/test_emmental.py b/tests/test_emmental.py index 5aea7c6..042fa62 100644 --- a/tests/test_emmental.py +++ b/tests/test_emmental.py @@ -128,8 +128,8 @@ class TestEmmental(unittest.TestCase): self.application.build_window() for action, accel in [("app.open-file", "o"), - ("app.decrease-volume", "Down"), - ("app.increase-volume", "Up"), + ("app.decrease-volume", "Down"), + ("app.increase-volume", "Up"), ("app.toggle-bg-mode", "b"), ("app.edit-settings", "s")]: self.assertEqual(self.application.get_accels_for_action(action), @@ -227,6 +227,16 @@ class TestEmmental(unittest.TestCase): self.application.player = emmental.audio.Player() win = self.application.build_window() + for action, accel in [("app.focus-search-track", "slash"), + ("app.clear-selected-tracks", "Escape"), + ("app.cycle-loop", "l"), + ("app.toggle-shuffle", "s"), + ("app.remove-selected-tracks", "Delete"), + ("app.move-track-up", "Up"), + ("app.move-track-down", "Down")]: + self.assertEqual(self.application.get_accels_for_action(action), + [accel]) + self.assertEqual(win.tracklist.sql, self.application.db) playlist = self.application.db.playlists.create("Test Playlist") diff --git a/tests/tracklist/test_selection.py b/tests/tracklist/test_selection.py index 3a7f03e..5d28076 100644 --- a/tests/tracklist/test_selection.py +++ b/tests/tracklist/test_selection.py @@ -456,3 +456,28 @@ class TestOsd(tests.util.TestCase): self.osd.reset() mock_unselect.assert_called() self.assertFalse(self.osd.have_selected) + + def test_accelerators(self): + """Test that the accelerators list is set up properly.""" + entries = [("remove-selected-tracks", self.osd._remove.activate, + ["Delete"], self.osd._remove, "visible"), + ("move-track-up", self.osd._move._up.activate, + ["Up"], self.osd._move, "can-move-up"), + ("move-track-down", self.osd._move._down.activate, + ["Down"], self.osd._move, "can-move-down")] + + accels = self.osd.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.assertEqual(accels[i].accels, accel) + + if gobject and prop: + enabled = gobject.get_property(prop) + self.assertEqual(accels[i].enabled, enabled) + gobject.set_property(prop, not enabled) + self.assertEqual(accels[i].enabled, not enabled) diff --git a/tests/tracklist/test_tracklist.py b/tests/tracklist/test_tracklist.py index df85997..dd1ebba 100644 --- a/tests/tracklist/test_tracklist.py +++ b/tests/tracklist/test_tracklist.py @@ -250,3 +250,40 @@ class TestTracklist(tests.util.TestCase): self.assertEqual(self.tracklist._Card__scroll_idle(None), GLib.SOURCE_REMOVE) mock_scroll.assert_called_with(None) + + def test_accelerators(self): + """Check that the accelerators list is set up properly.""" + entries = [("focus-search-track", self.tracklist._filter.grab_focus, + ["slash"], None, None), + ("clear-selected-tracks", self.tracklist._unselect.activate, + ["Escape"], self.tracklist._unselect, "sensitive"), + ("cycle-loop", self.tracklist._loop.activate, + ["l"], self.tracklist._top_right, "sensitive"), + ("toggle-shuffle", self.tracklist._shuffle.activate, + ["s"], self.tracklist._top_right, "sensitive")] + + accels = self.tracklist.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) + + if gobject and prop: + enabled = gobject.get_property(prop) + self.assertEqual(accels[i].enabled, enabled) + gobject.set_property(prop, not enabled) + self.assertEqual(accels[i].enabled, not enabled) + + start = len(entries) + osd_accels = self.tracklist._osd.accelerators + for i, accel in enumerate(osd_accels): + with self.subTest(name=accel.name): + self.assertIsInstance(accels[start + i], + emmental.action.ActionEntry) + self.assertEqual(accels[start + i].name, accel.name) + self.assertEqual(accels[start + i].func, accel.func) + self.assertListEqual(accels[start + i].accels, accel.accels)