db: Give playlist tables a refilter() function

This is used to notify the model that the rows have changed when it's
not automatically being detected. I first noticed this when attempting
to disable incremental filtering, due to the Artist list not getting
refiltered when new child Albums were added to the Artist.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2023-06-25 10:53:01 -04:00
parent 725619faf5
commit 1d0813f217
2 changed files with 54 additions and 7 deletions

View File

@ -69,6 +69,8 @@ class Playlist(table.Row):
def add_child(self, child: typing.Self) -> None:
"""Add a child Playlist to this Playlist."""
self.child_set.add_row(child)
if self.child_set.keyset.n_keys == 1:
self.table.refilter(Gtk.FilterChange.LESS_STRICT)
def add_track(self, track: Track, *, idle: bool = False) -> None:
"""Add a Track to this Playlist."""
@ -110,6 +112,8 @@ class Playlist(table.Row):
def remove_child(self, child: typing.Self) -> None:
"""Remove a child Playlist from this Playlist."""
self.child_set.remove_row(child)
if self.child_set.keyset.n_keys == 0:
self.table.refilter(Gtk.FilterChange.MORE_STRICT)
def remove_track(self, track: table.Row, *, idle: bool = False) -> None:
"""Remove a Track from this Playlist."""
@ -154,6 +158,10 @@ class Table(table.Table):
def __create_tree(self, plist: Playlist) -> Gtk.FilterListModel | None:
return plist.children
def __refilter(self, change_how: Gtk.FilterChange) -> bool:
self.get_filter().changed(change_how)
return True
def do_add_track(self, playlist: Playlist, track: Track) -> bool:
"""Add a Track to the Playlist."""
raise NotImplementedError
@ -255,6 +263,11 @@ class Table(table.Table):
playlist.sort_order = "user"
return res
def refilter(self, change_how: Gtk.FilterChange) -> None:
"""Schedule refiltering the Table."""
self.queue.cancel_task(self.__refilter)
self.queue.push(self.__refilter, change_how, first=True)
def remove_system_track(self, playlist: Playlist, track: Track) -> bool:
"""Remove a Track from a system Playlist."""
return self.sql("""DELETE FROM system_tracks

View File

@ -21,6 +21,7 @@ class TestPlaylistRow(unittest.TestCase):
self.table.move_track_up = unittest.mock.Mock(return_value=True)
self.table.get_trackids = unittest.mock.Mock(return_value={1, 2, 3})
self.table.get_track_order = unittest.mock.Mock()
self.table.refilter = unittest.mock.Mock()
self.table.queue = emmental.db.idle.Queue()
self.table.update = unittest.mock.Mock(return_value=True)
@ -114,11 +115,16 @@ class TestPlaylistRow(unittest.TestCase):
def test_add_child(self):
"""Test adding a child playlist to the playlist."""
table = emmental.db.table.Table(None)
child = tests.util.table.MockRow(table=table, number=1)
child1 = tests.util.table.MockRow(table=table, number=1)
child2 = tests.util.table.MockRow(table=table, number=2)
self.playlist.add_children(table, set())
self.playlist.add_child(child)
self.assertIn(child, self.playlist.child_set)
self.playlist.add_child(child1)
self.assertIn(child1, self.playlist.child_set)
self.table.refilter.assert_called_with(Gtk.FilterChange.LESS_STRICT)
self.playlist.add_child(child2)
self.table.refilter.assert_called_once()
def test_add_track(self):
"""Test adding a track to the playlist."""
@ -179,12 +185,19 @@ class TestPlaylistRow(unittest.TestCase):
def test_remove_child(self):
"""Test removing a child playlist from the playlist."""
table = emmental.db.table.Table(None)
child = tests.util.table.MockRow(table=table, number=1)
child1 = tests.util.table.MockRow(table=table, number=1)
child2 = tests.util.table.MockRow(table=table, number=2)
self.playlist.add_children(table, set())
self.playlist.add_child(child1)
self.playlist.add_child(child2)
self.table.refilter.reset_mock()
self.playlist.add_child(child)
self.playlist.remove_child(child)
self.assertFalse(child in self.playlist.child_set)
self.playlist.remove_child(child1)
self.assertFalse(child1 in self.playlist.child_set)
self.table.refilter.assert_not_called()
self.playlist.remove_child(child2)
self.table.refilter.assert_called_with(Gtk.FilterChange.MORE_STRICT)
def test_remove_track(self):
"""Test removing a track from the playlist."""
@ -403,6 +416,27 @@ class TestPlaylistTable(tests.util.TestCase):
self.table.move_track_up(plist, self.track)
self.assertEqual(plist.sort_order, "user")
def test_refilter(self):
"""Test refiltering the playlist table."""
self.table.queue.push(unittest.mock.Mock())
with unittest.mock.patch.object(self.table.get_filter(),
"changed") as mock_changed:
self.table.refilter(Gtk.FilterChange.MORE_STRICT)
self.assertEqual(self.table.queue[0],
(self.table._Table__refilter,
Gtk.FilterChange.MORE_STRICT))
mock_changed.assert_not_called()
self.table.refilter(Gtk.FilterChange.LESS_STRICT)
self.assertEqual(self.table.queue[0],
(self.table._Table__refilter,
Gtk.FilterChange.LESS_STRICT))
mock_changed.assert_not_called()
self.table.queue.complete()
mock_changed.assert_called_with(Gtk.FilterChange.LESS_STRICT)
def test_remove_track(self):
"""Test adding a track to a playlist."""
self.assertTrue(self.table.system_tracks)