tracklist: Add a SortButton
This is a Popover Button containing a Gtk.ListView to display the Sort Order Model for the currently visible Playlist. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
ed4a484a31
commit
ee1152bcc4
|
@ -34,12 +34,14 @@ class Card(Gtk.Box):
|
|||
has_frame=False, sensitive=False)
|
||||
self._loop = buttons.LoopButton()
|
||||
self._shuffle = buttons.ShuffleButton()
|
||||
self._sort = buttons.SortButton()
|
||||
|
||||
self._top_left.append(self._visible_cols)
|
||||
self._top_left.append(self._unselect)
|
||||
|
||||
self._top_right.append(self._loop)
|
||||
self._top_right.append(self._shuffle)
|
||||
self._top_right.append(self._sort)
|
||||
|
||||
self._top_box.set_start_widget(self._top_left)
|
||||
self._top_box.set_center_widget(self._filter)
|
||||
|
@ -55,6 +57,7 @@ class Card(Gtk.Box):
|
|||
self._unselect.connect("clicked", self.__clear_selection)
|
||||
self._loop.connect("notify::state", self.__update_loop_state)
|
||||
self._shuffle.connect("notify::active", self.__update_shuffle_state)
|
||||
self._sort.connect("notify::sort-order", self.__update_sort_order)
|
||||
|
||||
self.add_css_class("card")
|
||||
|
||||
|
@ -69,12 +72,15 @@ class Card(Gtk.Box):
|
|||
self.__set_button_state()
|
||||
case "shuffle":
|
||||
self._shuffle.active = playlist.shuffle
|
||||
case "sort-order":
|
||||
self._sort.sort_order = playlist.sort_order
|
||||
|
||||
def __set_button_state(self) -> None:
|
||||
can_disable = self.playlist.playlist != self.sql.playlists.collection
|
||||
self._loop.can_disable = can_disable
|
||||
self._loop.state = self.playlist.loop
|
||||
self._shuffle.active = self.playlist.shuffle
|
||||
self._sort.set_sort_order(self.playlist.sort_order)
|
||||
|
||||
def __update_loop_state(self, loop: buttons.LoopButton, param) -> None:
|
||||
if self.playlist.loop != loop.state:
|
||||
|
@ -85,6 +91,10 @@ class Card(Gtk.Box):
|
|||
if self.playlist.shuffle != shuffle.active:
|
||||
self.playlist.shuffle = shuffle.active
|
||||
|
||||
def __update_sort_order(self, sort: buttons.SortButton, param) -> None:
|
||||
if self.playlist.sort_order != sort.sort_order:
|
||||
self.playlist.sort_order = sort.sort_order
|
||||
|
||||
def __search_changed(self, filter: entry.Filter) -> None:
|
||||
self.sql.tracks.filter(filter.get_query())
|
||||
|
||||
|
|
|
@ -162,3 +162,41 @@ class SortFieldWidget(Gtk.Box):
|
|||
self._name.set_text(field.name if field is not None else "")
|
||||
self._enabled.set_active(field is not None and field.enabled)
|
||||
self._reverse.active = field is not None and field.reversed
|
||||
|
||||
|
||||
class SortRow(factory.ListRow):
|
||||
"""A row for managing Sort Order."""
|
||||
|
||||
def __init__(self, listitem: Gtk.ListItem):
|
||||
"""Initialize a Sort Row."""
|
||||
super().__init__(listitem=listitem, child=SortFieldWidget())
|
||||
|
||||
def do_bind(self) -> None:
|
||||
"""Bind Sort Field properties to the Widget."""
|
||||
self.child.set_sort_field(self.item)
|
||||
|
||||
def do_unbind(self) -> None:
|
||||
"""Unbind properties from the widget."""
|
||||
self.child.set_sort_field(None)
|
||||
|
||||
|
||||
class SortButton(buttons.PopoverButton):
|
||||
"""Shows a Popover Menu to sort playlists."""
|
||||
|
||||
model = GObject.Property(type=sorter.SortOrderModel)
|
||||
sort_order = GObject.Property(type=str)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""Initialize the Sort button."""
|
||||
super().__init__(has_frame=False, model=sorter.SortOrderModel(),
|
||||
icon_name="view-list-ordered-symbolic", **kwargs)
|
||||
self._selection = Gtk.NoSelection(model=self.model)
|
||||
self._factory = factory.Factory(row_type=SortRow)
|
||||
self.popover_child = Gtk.ListView(model=self._selection,
|
||||
factory=self._factory,
|
||||
show_separators=True)
|
||||
self.model.bind_property("sort-order", self, "sort-order")
|
||||
|
||||
def set_sort_order(self, newval: str) -> None:
|
||||
"""Directly set the sort order."""
|
||||
self.model.set_sort_order(newval)
|
||||
|
|
|
@ -275,3 +275,63 @@ class TestSortFieldWidget(unittest.TestCase):
|
|||
self.assertFalse(self.model[0].reversed)
|
||||
self.sort._reverse.emit("clicked")
|
||||
self.assertTrue(self.model[0].reversed)
|
||||
|
||||
|
||||
class TestSortButton(unittest.TestCase):
|
||||
"""Test the Sort button."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up common variables."""
|
||||
self.sort = emmental.tracklist.buttons.SortButton()
|
||||
|
||||
def test_init(self):
|
||||
"""Test that the Sort button is configured correctly."""
|
||||
self.assertIsInstance(self.sort, emmental.buttons.PopoverButton)
|
||||
|
||||
self.assertEqual(self.sort.get_icon_name(),
|
||||
"view-list-ordered-symbolic")
|
||||
self.assertFalse(self.sort.get_has_frame())
|
||||
|
||||
def test_popover_child(self):
|
||||
"""Test that the popover_child is configured correctly."""
|
||||
self.assertIsInstance(self.sort.popover_child, Gtk.ListView)
|
||||
self.assertIsInstance(self.sort.model,
|
||||
emmental.tracklist.sorter.SortOrderModel)
|
||||
self.assertIsInstance(self.sort._selection, Gtk.NoSelection)
|
||||
self.assertIsInstance(self.sort._factory, emmental.factory.Factory)
|
||||
|
||||
self.assertTrue(self.sort.popover_child.get_show_separators())
|
||||
|
||||
self.assertEqual(self.sort.popover_child.get_model(),
|
||||
self.sort._selection)
|
||||
self.assertEqual(self.sort._selection.get_model(), self.sort.model)
|
||||
self.assertEqual(self.sort.popover_child.get_factory(),
|
||||
self.sort._factory)
|
||||
self.assertEqual(self.sort._factory.row_type,
|
||||
emmental.tracklist.buttons.SortRow)
|
||||
|
||||
def test_sort_row(self):
|
||||
"""Test the Sort Row object."""
|
||||
(field := self.sort.model[0]).enable()
|
||||
listitem = Gtk.ListItem()
|
||||
listitem.get_item = lambda: field
|
||||
self.sort.model[1].enable()
|
||||
|
||||
row = emmental.tracklist.buttons.SortRow(listitem)
|
||||
self.assertIsInstance(row, emmental.factory.ListRow)
|
||||
self.assertIsInstance(row.child,
|
||||
emmental.tracklist.buttons.SortFieldWidget)
|
||||
|
||||
row.bind()
|
||||
self.assertEqual(row.child.sort_field, field)
|
||||
row.unbind()
|
||||
self.assertIsNone(row.child.sort_field)
|
||||
|
||||
def test_sort_order(self):
|
||||
"""Test the sort-order property."""
|
||||
self.assertEqual(self.sort.sort_order, "")
|
||||
self.sort.model[0].enable()
|
||||
self.assertEqual(self.sort.sort_order, self.sort.model.sort_order)
|
||||
|
||||
self.sort.set_sort_order("artist")
|
||||
self.assertEqual(self.sort.model.sort_order, "artist")
|
||||
|
|
|
@ -136,6 +136,27 @@ class TestTracklist(tests.util.TestCase):
|
|||
self.tracklist._shuffle.active = False
|
||||
self.assertFalse(self.playlist.shuffle)
|
||||
|
||||
def test_sort_button(self):
|
||||
"""Test the sort button."""
|
||||
self.assertIsInstance(self.tracklist._sort,
|
||||
emmental.tracklist.buttons.SortButton)
|
||||
self.assertEqual(self.tracklist._shuffle.get_next_sibling(),
|
||||
self.tracklist._sort)
|
||||
|
||||
self.tracklist.playlist = self.playlist
|
||||
self.assertEqual(self.tracklist._sort.sort_order,
|
||||
self.playlist.sort_order)
|
||||
|
||||
self.playlist.playlist = self.sql.playlists.collection
|
||||
self.assertEqual(self.tracklist._sort.sort_order,
|
||||
self.sql.playlists.collection.sort_order)
|
||||
|
||||
self.playlist.sort_order = "album"
|
||||
self.assertEqual(self.tracklist._sort.sort_order, "album")
|
||||
|
||||
self.tracklist._sort.sort_order = "artist"
|
||||
self.assertEqual(self.playlist.sort_order, "artist")
|
||||
|
||||
def test_trackview(self):
|
||||
"""Test the Trackview widget."""
|
||||
self.assertIsInstance(self.tracklist._trackview,
|
||||
|
|
Loading…
Reference in New Issue