Anna Schumaker
24c1a31367
This table allows us to work with Library playlists that are represented by a filesystem path. The user can manually enable or disable library paths to prevent their tracks from showing up in the Collection playlist. Additionally, library paths have an online property to determine if the library still exists in the filesystem to prevent us from removing tracks due to a broken NFS mount or symlink. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
94 lines
3.3 KiB
Python
94 lines
3.3 KiB
Python
# Copyright 2022 (c) Anna Schumaker
|
|
"""A custom Gio.ListModel for working with libraries."""
|
|
import pathlib
|
|
import sqlite3
|
|
from gi.repository import GObject
|
|
from . import idle
|
|
from . import playlist
|
|
|
|
|
|
class Library(playlist.Playlist):
|
|
"""Our custom Library with path and enabled properties."""
|
|
|
|
libraryid = GObject.Property(type=int)
|
|
path = GObject.Property(type=GObject.TYPE_PYOBJECT)
|
|
enabled = GObject.Property(type=bool, default=True)
|
|
deleting = GObject.Property(type=bool, default=False)
|
|
|
|
queue = GObject.Property(type=idle.Queue)
|
|
online = GObject.Property(type=bool, default=False)
|
|
|
|
def __init__(self, **kwargs):
|
|
"""Initialize our Library object."""
|
|
super().__init__(queue=idle.Queue(), **kwargs)
|
|
|
|
def __queue_delete(self) -> bool:
|
|
self.table.delete(self)
|
|
return True
|
|
|
|
def do_update(self, column: str) -> bool:
|
|
"""Update a Library playlist."""
|
|
match column:
|
|
case "online": self.table.notify_online(self)
|
|
case _: return super().do_update(column)
|
|
return True
|
|
|
|
def delete(self) -> bool:
|
|
"""Delete this Library."""
|
|
if self.deleting is False:
|
|
self.deleting = True
|
|
self.queue.push(self.__queue_delete)
|
|
return True
|
|
return False
|
|
|
|
@property
|
|
def primary_key(self) -> int:
|
|
"""Get this library's primary key."""
|
|
return self.libraryid
|
|
|
|
|
|
class Table(playlist.Table):
|
|
"""Our Library ListModel."""
|
|
|
|
def do_construct(self, **kwargs) -> Library:
|
|
"""Construct a new library."""
|
|
return Library(**kwargs)
|
|
|
|
def do_sql_delete(self, library: Library) -> sqlite3.Cursor:
|
|
"""Delete a library."""
|
|
return self.sql("DELETE FROM libraries WHERE libraryid=?",
|
|
library.libraryid)
|
|
|
|
def do_sql_insert(self, path: pathlib.Path) -> sqlite3.Cursor:
|
|
"""Create a new library."""
|
|
if cur := self.sql("INSERT INTO libraries (path) VALUES (?)", path):
|
|
return self.sql("SELECT * FROM libraries_view WHERE libraryid=?",
|
|
cur.lastrowid)
|
|
|
|
def do_sql_glob(self, glob: str) -> sqlite3.Cursor:
|
|
"""Search for libraries matching the search text."""
|
|
return self.sql("""SELECT libraryid FROM libraries_view
|
|
WHERE name GLOB ?""", glob)
|
|
|
|
def do_sql_select_all(self) -> sqlite3.Cursor:
|
|
"""Load libraries from the database."""
|
|
return self.sql("SELECT * FROM libraries_view")
|
|
|
|
def do_sql_select_one(self, path: pathlib.Path) -> sqlite3.Cursor:
|
|
"""Look up a library by path."""
|
|
return self.sql("SELECT libraryid FROM libraries WHERE path=?", path)
|
|
|
|
def do_sql_update(self, library: Library, column: str, newval) -> bool:
|
|
"""Update a Library playlist."""
|
|
return self.sql(f"UPDATE libraries SET {column}=? WHERE rowid=?",
|
|
newval, library.libraryid)
|
|
|
|
def notify_online(self, library: Library) -> None:
|
|
"""Notify that a library's online status has changed."""
|
|
if not library.online or self.loaded:
|
|
self.emit("library-online", library)
|
|
|
|
@GObject.Signal(arg_types=(Library,))
|
|
def library_online(self, library: Library) -> None:
|
|
"""Signal that a library online status has changed."""
|