From 45ddb22cc7ce688e418e44eb64896512d206846c Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Mon, 17 Apr 2023 11:34:54 -0400 Subject: [PATCH] playlist: Give playlists functions for moving individual tracks The move_track_up() and move_track_down() functions are used to manually arrange the tracks in a playlist. Signed-off-by: Anna Schumaker --- emmental/playlist/playlist.py | 26 +++++++++++++ tests/playlist/test_playlist.py | 68 +++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/emmental/playlist/playlist.py b/emmental/playlist/playlist.py index 84625bf..c866011 100644 --- a/emmental/playlist/playlist.py +++ b/emmental/playlist/playlist.py @@ -29,6 +29,18 @@ class Playlist(model.TrackidModel): self.on_trackids_reset(plist.tracks) self.notify("sort-order") + def __track_moved(self, track: db.tracks.Track, *, offset: int) -> None: + index = self.index(track) + new_pos = index + offset + n_changed = abs(offset) + 1 + + del self.trackids[index] + self.trackids.insert(new_pos, track.trackid) + + self.__sort_keys = self.__playlist.get_track_order() + self.items_changed(position=min(index, new_pos), + removed=n_changed, added=n_changed) + def do_get_sort_key(self, trackid: int) -> int: """Get a sort key for the given trackid.""" if (key := self.__sort_keys.get(trackid)) is None: @@ -60,6 +72,20 @@ class Playlist(model.TrackidModel): if track is not None: return super().index(track.trackid) + def move_track_down(self, track: db.tracks.Track) -> None: + """Move a track earlier in the sort order.""" + if self.__playlist is not None: + need_handling = self.__sort_order == "user" + if self.__playlist.move_track_down(track) and need_handling: + self.__track_moved(track, offset=1) + + def move_track_up(self, track: db.tracks.Track) -> None: + """Move a track earlier in the sort order.""" + if self.__playlist is not None: + need_handling = self.__sort_order == "user" + if self.__playlist.move_track_up(track) and need_handling: + self.__track_moved(track, offset=-1) + def remove_track(self, track: db.tracks.Track) -> None: """Remove a track from the playlist.""" if self.__playlist is not None: diff --git a/tests/playlist/test_playlist.py b/tests/playlist/test_playlist.py index 6783d28..66e6db6 100644 --- a/tests/playlist/test_playlist.py +++ b/tests/playlist/test_playlist.py @@ -73,6 +73,74 @@ class TestPlaylist(tests.util.TestCase): self.assertIsNone(super(type(self.playlist), self.playlist).index(0)) self.assertIsNone(self.playlist.index(None)) + def test_move_track_down(self): + """Test the playlist move_track_down() function.""" + self.playlist.move_track_down(self.track1) + + self.db_plist.add_track(self.track1) + self.db_plist.add_track(self.track2) + self.db_plist.add_track(self.track3) + self.playlist.playlist = self.db_plist + + items_changed = unittest.mock.Mock() + self.playlist.connect("items-changed", items_changed) + + self.playlist.move_track_down(self.track2) + self.assertEqual(self.db_plist.sort_order, "user") + self.assertDictEqual(self.playlist._Playlist__sort_keys, + {self.track1.trackid: 0, + self.track3.trackid: 1, + self.track2.trackid: 2}) + self.assertListEqual(self.playlist.trackids, [self.track1.trackid, + self.track3.trackid, + self.track2.trackid]) + items_changed.assert_called_once_with(self.playlist, 0, 3, 3) + + items_changed.reset_mock() + self.playlist.move_track_down(self.track1) + self.assertDictEqual(self.playlist._Playlist__sort_keys, + {self.track3.trackid: 0, + self.track1.trackid: 1, + self.track2.trackid: 2}) + self.assertListEqual(self.playlist.trackids, [self.track3.trackid, + self.track1.trackid, + self.track2.trackid]) + items_changed.assert_called_once_with(self.playlist, 0, 2, 2) + + def test_move_track_up(self): + """Test the playlist move_track_up() function.""" + self.playlist.move_track_up(self.track1) + + self.db_plist.add_track(self.track1) + self.db_plist.add_track(self.track2) + self.db_plist.add_track(self.track3) + self.playlist.playlist = self.db_plist + + items_changed = unittest.mock.Mock() + self.playlist.connect("items-changed", items_changed) + + self.playlist.move_track_up(self.track2) + self.assertEqual(self.db_plist.sort_order, "user") + self.assertDictEqual(self.playlist._Playlist__sort_keys, + {self.track2.trackid: 0, + self.track1.trackid: 1, + self.track3.trackid: 2}) + self.assertListEqual(self.playlist.trackids, [self.track2.trackid, + self.track1.trackid, + self.track3.trackid]) + items_changed.assert_called_once_with(self.playlist, 0, 3, 3) + + items_changed.reset_mock() + self.playlist.move_track_up(self.track3) + self.assertDictEqual(self.playlist._Playlist__sort_keys, + {self.track2.trackid: 0, + self.track3.trackid: 1, + self.track1.trackid: 2}) + self.assertListEqual(self.playlist.trackids, [self.track2.trackid, + self.track3.trackid, + self.track1.trackid]) + items_changed.assert_called_once_with(self.playlist, 1, 2, 2) + def test_remove_track(self): """Test the playlist remove_track() function.""" self.playlist.remove_track(self.track1)