126 lines
4.5 KiB
Python
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
|