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 <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2023-04-17 11:34:54 -04:00
parent edaa275ba5
commit 45ddb22cc7
2 changed files with 94 additions and 0 deletions

View File

@ -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:

View File

@ -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)