emmental/emmental/db/libraries.py
Anna Schumaker 24c1a31367 db: Add a Library Table
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>
2023-04-12 10:44:34 -04:00

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."""