emmental/emmental/playlist/playlist.py

126 lines
4.5 KiB
Python

# Copyright 2023 (c) Anna Schumaker.
"""A TrackidModel with extra features."""
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."""
def __init__(self, sql: db.Connection,
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 __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:
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:
self.__playlist.add_track(track)
def index(self, track: db.tracks.Track) -> int | None:
"""Find the index of a track in the list."""
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:
self.__playlist.remove_track(track)
@GObject.Property(type=db.playlist.Playlist)
def playlist(self) -> db.playlist.Playlist | None:
"""Get the current db playlist."""
return self.__playlist
@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
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