playlist: Give the Playlist model a sort-order property
And make sure we re-sort the tracks when it changes to match the new order. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
298b58a54e
commit
edaa275ba5
|
@ -4,6 +4,8 @@ from gi.repository import GObject
|
|||
from . import model
|
||||
from .. import db
|
||||
|
||||
FLAGS = GObject.ParamFlags.READWRITE | GObject.ParamFlags.EXPLICIT_NOTIFY
|
||||
|
||||
|
||||
class Playlist(model.TrackidModel):
|
||||
"""A TrackidModel with extra Playlist features."""
|
||||
|
@ -12,11 +14,42 @@ class Playlist(model.TrackidModel):
|
|||
playlist: db.playlist.Playlist = None):
|
||||
"""Initialize the Playlist instance."""
|
||||
super().__init__(sql=sql)
|
||||
self.__sort_keys = {}
|
||||
|
||||
self.__playlist = None
|
||||
self.__sort_order = None
|
||||
|
||||
if playlist is not None:
|
||||
self.playlist = playlist
|
||||
|
||||
def __playlist_notify(self, plist: db.playlist.Playlist, param) -> None:
|
||||
match param.name:
|
||||
case "sort-order":
|
||||
self.__sort_order = plist.sort_order
|
||||
self.on_trackids_reset(plist.tracks)
|
||||
self.notify("sort-order")
|
||||
|
||||
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:
|
||||
if self.__playlist is not None:
|
||||
self.__sort_keys = self.__playlist.get_track_order()
|
||||
key = self.__sort_keys.get(trackid, 0)
|
||||
else:
|
||||
return trackid
|
||||
return key
|
||||
|
||||
def on_trackid_removed(self, set: db.tracks.TrackidSet,
|
||||
trackid: int) -> None:
|
||||
"""Handle the TrackidSet::trackid-removed signal."""
|
||||
super().on_trackid_removed(set, trackid)
|
||||
self.__sort_keys.pop(trackid, None)
|
||||
|
||||
def on_trackids_reset(self, set: db.tracks.TrackidSet) -> None:
|
||||
"""Handle the TrackidSet::trackids-reset signal."""
|
||||
self.__sort_keys.clear()
|
||||
super().on_trackids_reset(set)
|
||||
|
||||
def add_track(self, track: db.tracks.Track) -> None:
|
||||
"""Add a track to the playlist."""
|
||||
if self.__playlist is not None:
|
||||
|
@ -40,5 +73,27 @@ class Playlist(model.TrackidModel):
|
|||
@playlist.setter
|
||||
def playlist(self, new: db.playlist.Playlist | None) -> None:
|
||||
"""Set a new db playlist to the playlist."""
|
||||
if self.__playlist:
|
||||
self.__playlist.disconnect_by_func(self.__playlist_notify)
|
||||
|
||||
self.__playlist = new
|
||||
self.trackid_set = None if new is None else new.tracks
|
||||
|
||||
if new is not None:
|
||||
self.__playlist.connect("notify", self.__playlist_notify)
|
||||
self.__sort_order = new.sort_order
|
||||
self.trackid_set = new.tracks
|
||||
else:
|
||||
self.__sort_order = None
|
||||
self.trackid_set = None
|
||||
|
||||
self.notify("sort-order")
|
||||
|
||||
@GObject.Property(type=str, flags=FLAGS)
|
||||
def sort_order(self) -> str:
|
||||
"""Get the current sort order."""
|
||||
return self.__sort_order
|
||||
|
||||
@sort_order.setter
|
||||
def sort_order(self, new_order: str) -> None:
|
||||
if self.__playlist is not None:
|
||||
self.__playlist.sort_order = new_order
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
# Copyright 2023 (c) Anna Schumaker.
|
||||
"""Tests our PlaylistModel."""
|
||||
import pathlib
|
||||
import unittest.mock
|
||||
import tests.util
|
||||
import emmental.playlist.playlist
|
||||
from gi.repository import GObject
|
||||
|
||||
|
||||
class TestPlaylist(tests.util.TestCase):
|
||||
|
@ -21,17 +23,32 @@ class TestPlaylist(tests.util.TestCase):
|
|||
|
||||
self.track1 = self.sql.tracks.create(self.library,
|
||||
pathlib.Path("/a/b/1.ogg"),
|
||||
self.medium, self.year, number=1)
|
||||
self.medium, self.year,
|
||||
number=1, length=10)
|
||||
self.track2 = self.sql.tracks.create(self.library,
|
||||
pathlib.Path("/a/b/2.ogg"),
|
||||
self.medium, self.year, number=2)
|
||||
self.medium, self.year,
|
||||
number=2, length=20)
|
||||
self.track3 = self.sql.tracks.create(self.library,
|
||||
pathlib.Path("/a/b/3.ogg"),
|
||||
self.medium, self.year,
|
||||
number=3, length=30)
|
||||
|
||||
def test_property_flags(self):
|
||||
"""Test the FLAGS constant."""
|
||||
self.assertEqual(emmental.playlist.playlist.FLAGS,
|
||||
GObject.ParamFlags.READWRITE |
|
||||
GObject.ParamFlags.EXPLICIT_NOTIFY)
|
||||
|
||||
def test_init(self):
|
||||
"""Test that the Playlist was set up correctly."""
|
||||
self.assertIsInstance(self.playlist,
|
||||
emmental.playlist.model.TrackidModel)
|
||||
self.assertEqual(self.playlist.sql, self.sql)
|
||||
self.assertDictEqual(self.playlist._Playlist__sort_keys, {})
|
||||
|
||||
self.assertIsNone(self.playlist._Playlist__playlist)
|
||||
self.assertIsNone(self.playlist._Playlist__sort_order)
|
||||
|
||||
plist2 = emmental.playlist.playlist.Playlist(self.sql, self.db_plist)
|
||||
self.assertEqual(plist2.playlist, self.db_plist)
|
||||
|
@ -53,6 +70,7 @@ class TestPlaylist(tests.util.TestCase):
|
|||
|
||||
self.assertEqual(self.playlist.index(self.track1), 0)
|
||||
self.assertIsNone(self.playlist.index(self.track2))
|
||||
self.assertIsNone(super(type(self.playlist), self.playlist).index(0))
|
||||
self.assertIsNone(self.playlist.index(None))
|
||||
|
||||
def test_remove_track(self):
|
||||
|
@ -72,7 +90,56 @@ class TestPlaylist(tests.util.TestCase):
|
|||
self.assertEqual(self.playlist._Playlist__playlist, self.db_plist)
|
||||
self.assertEqual(self.playlist.playlist, self.db_plist)
|
||||
self.assertEqual(self.playlist.trackid_set, self.db_plist.tracks)
|
||||
self.assertEqual(self.playlist.sort_order, self.db_plist.sort_order)
|
||||
|
||||
self.playlist.playlist = None
|
||||
self.assertIsNone(self.playlist.playlist)
|
||||
self.assertIsNone(self.playlist.trackid_set)
|
||||
|
||||
def test_sort_order(self):
|
||||
"""Test the sort-order property."""
|
||||
notify = unittest.mock.Mock()
|
||||
self.playlist.connect("notify::sort-order", notify)
|
||||
|
||||
self.assertIsNone(self.playlist.sort_order)
|
||||
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
|
||||
self.assertEqual(self.playlist.sort_order, self.db_plist.sort_order)
|
||||
notify.assert_called()
|
||||
|
||||
self.playlist.sort_order = "length DESC"
|
||||
self.assertEqual(self.db_plist.sort_order, "length DESC")
|
||||
self.assertDictEqual(self.playlist._Playlist__sort_keys,
|
||||
{self.track3.trackid: 0,
|
||||
self.track2.trackid: 1,
|
||||
self.track1.trackid: 2})
|
||||
self.assertListEqual(self.playlist.trackids,
|
||||
[self.track3.trackid,
|
||||
self.track2.trackid,
|
||||
self.track1.trackid])
|
||||
|
||||
self.db_plist.remove_track(self.track2)
|
||||
self.assertDictEqual(self.playlist._Playlist__sort_keys,
|
||||
{self.track3.trackid: 0,
|
||||
self.track1.trackid: 2})
|
||||
|
||||
notify.reset_mock()
|
||||
self.db_plist.sort_order = "user"
|
||||
self.assertEqual(self.playlist.sort_order, "user")
|
||||
notify.assert_called()
|
||||
|
||||
notify.reset_mock()
|
||||
self.playlist.playlist = None
|
||||
notify.assert_called()
|
||||
|
||||
notify.reset_mock()
|
||||
self.db_plist.sort_order = "length"
|
||||
self.assertIsNone(self.playlist.sort_order)
|
||||
notify.assert_not_called()
|
||||
|
||||
self.playlist.sort_order = "length"
|
||||
self.assertIsNone(self.playlist.sort_order)
|
||||
notify.assert_not_called()
|
||||
|
|
Loading…
Reference in New Issue