db: Add a base class for Playlist Objects

This object inherits from the table.Row base class. It adds in
properties for name, active state, and propertyid and a rename()
function for updating the Table sort order during a rename.

Additionally, child playlists can be enabled by calling add_children().
This will set up a Gtk.FilterListModel using the provide child Table and
Filter.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2022-08-10 11:19:29 -04:00
parent 9944d07bba
commit d22b3c0ce2
2 changed files with 104 additions and 0 deletions

43
emmental/db/playlist.py Normal file
View File

@ -0,0 +1,43 @@
# Copyright 2022 (c) Anna Schumaker
"""A customized Gio.ListStore for tracking Playlist GObjects."""
from gi.repository import GObject
from gi.repository import Gio
from gi.repository import Gtk
from . import table
class Playlist(table.Row):
"""Our shared Playlist Row object."""
propertyid = GObject.Property(type=int)
name = GObject.Property(type=str)
active = GObject.Property(type=bool, default=False)
n_tracks = GObject.Property(type=int)
children = GObject.Property(type=Gtk.FilterListModel)
def __init__(self, table: Gio.ListModel, propertyid: int,
name: str = "", active: bool = False, **kwargs):
"""Initialize a Playlist object."""
super().__init__(table=table, propertyid=propertyid,
name=name, active=active, **kwargs)
def add_children(self, child_table: table.Table,
child_filter: Gtk.Filter) -> None:
"""Create a FilterListModel for this playlist's children."""
self.children = Gtk.FilterListModel.new(child_table, child_filter)
self.children.set_incremental(True)
def do_update(self, column: str) -> bool:
"""Update a Playlist object."""
match column:
case "propertyid" | "name" | "n-tracks" | "children": pass
case _: return super().do_update(column)
return True
@GObject.Property(type=table.Row)
def parent(self) -> table.Row | None:
"""Get this playlist's parent playlist."""
return None

61
tests/db/test_playlist.py Normal file
View File

@ -0,0 +1,61 @@
# Copyright 2022 (c) Anna Schumaker
"""Tests our ListStore and Playlist objects."""
import unittest
import unittest.mock
import emmental.db.playlist
from gi.repository import Gio
from gi.repository import Gtk
class TestPlaylistRow(unittest.TestCase):
"""Tests our shared Playlist Row."""
def setUp(self):
"""Set up common variables."""
self.table = Gio.ListStore()
self.table.update = unittest.mock.Mock(return_value=True)
self.playlist = emmental.db.playlist.Playlist(table=self.table,
propertyid=0)
def test_init(self):
"""Test that the Playlist object is configured correctly."""
self.assertIsInstance(self.playlist, emmental.db.table.Row)
self.assertEqual(self.playlist.table, self.table)
self.assertEqual(self.playlist.propertyid, 0)
self.assertEqual(self.playlist.name, "")
self.assertEqual(self.playlist.n_tracks, 0)
self.assertFalse(self.playlist.active)
playlist2 = emmental.db.playlist.Playlist(table=self.table,
propertyid=1,
name="Test Name", active=1)
self.assertEqual(playlist2.propertyid, 1)
self.assertEqual(playlist2.name, "Test Name")
self.assertTrue(playlist2.active)
def test_children(self):
"""Test the child playlist properties."""
self.assertIsNone(self.playlist.children)
filter = Gtk.Filter()
self.playlist.add_children(self.table, filter)
self.assertIsInstance(self.playlist.children, Gtk.FilterListModel)
self.assertEqual(self.playlist.children.get_filter(), filter)
self.assertEqual(self.playlist.children.get_model(), self.table)
self.assertTrue(self.playlist.children.get_incremental())
def test_parent(self):
"""Test the parent playlist property."""
self.assertIsNone(self.playlist.parent)
def test_do_update(self):
"""Test the do_update() function."""
for (prop, value) in [("name", "New Name"), ("propertyid", 12345),
("children", Gtk.FilterListModel()),
("n-tracks", 42)]:
with self.subTest(property=prop):
self.playlist.set_property(prop, value)
self.table.update.assert_not_called()
self.playlist.active = True
self.table.update.assert_called_with(self.playlist, "active", True)