emmental/emmental/db/__init__.py

110 lines
3.4 KiB
Python

# Copyright 2022 (c) Anna Schumaker
"""Easily work with our underlying sqlite3 database."""
import pathlib
from gi.repository import GObject
from typing import Generator
from . import albums
from . import artists
from . import connection
from . import decades
from . import genres
from . import libraries
from . import playlist
from . import media
from . import playlists
from . import settings
from . import table
from . import tracks
from . import years
SQL_V1_SCRIPT = pathlib.Path(__file__).parent / "emmental.sql"
SQL_V2_SCRIPT = pathlib.Path(__file__).parent / "upgrade-v2.sql"
class Connection(connection.Connection):
"""Connect to the database."""
active_playlist = GObject.Property(type=playlist.Playlist)
loaded = GObject.Property(type=bool, default=False)
def __init__(self):
"""Initialize a sqlite connection."""
super().__init__()
self.__check_version()
self.settings = settings.Table(self)
self.playlists = playlists.Table(self)
self.artists = artists.Table(self)
self.albums = albums.Table(self, queue=self.artists.queue)
self.media = media.Table(self, queue=self.artists.queue)
self.genres = genres.Table(self)
self.decades = decades.Table(self)
self.years = years.Table(self, queue=self.decades.queue)
self.libraries = libraries.Table(self)
self.tracks = tracks.Table(self)
def __check_loaded(self) -> None:
for tbl in list(self.playlist_tables()) + [self.tracks]:
if tbl.loaded is False:
return
self.loaded = True
def __check_version(self) -> None:
user_version = self("PRAGMA user_version").fetchone()["user_version"]
match user_version:
case 0:
self.executescript(SQL_V1_SCRIPT)
self.executescript(SQL_V2_SCRIPT)
case 1:
self.executescript(SQL_V2_SCRIPT)
case 2: pass
case _:
raise Exception(f"Unsupported data version: {user_version}")
def close(self) -> None:
"""Close the database connection."""
self.settings.stop()
for tbl in self.playlist_tables():
tbl.stop()
self.tracks.stop()
super().close()
def filter(self, glob: str) -> None:
"""Filter the playlist tables."""
for tbl in self.playlist_tables():
tbl.filter(glob)
def load(self) -> None:
"""Load the database tables."""
self.settings.load()
for tbl in self.playlist_tables():
tbl.load()
self.tracks.load()
def playlist_tables(self) -> Generator[playlist.Table, None, None]:
"""Iterate over each playlist table."""
for tbl in [self.playlists, self.artists, self.albums, self.media,
self.genres, self.decades, self.years, self.libraries]:
yield tbl
def set_active_playlist(self, plist: playlist.Playlist) -> None:
"""Set the currently active playlist."""
if self.active_playlist == plist:
return
if self.active_playlist is not None:
self.active_playlist.active = False
self.active_playlist = plist
if plist is not None:
plist.active = True
@GObject.Signal(arg_types=(table.Table,))
def table_loaded(self, tbl: table.Table) -> None:
"""Signal that a table has been loaded."""
tbl.loaded = True
self.__check_loaded()