tracklist: Rework the VisibleColumns button to use a ListBox
I create a custom Gtk.ListBoxRow for displaying each individual column name and visibility status. I then bind it to a listbox placed as the popover button's popover child. This lets me set the 'boxed-list' style class on the listbox to give it a nicer appearance, and clicking the label will also toggle column visibility. Implements: #57 ("Rework visible columns button") Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
3d6350d7bd
commit
f6481f0182
|
@ -8,16 +8,26 @@ from .. import buttons
|
||||||
from .. import factory
|
from .. import factory
|
||||||
|
|
||||||
|
|
||||||
class VisibleSwitch(factory.ListRow):
|
class VisibleRow(Gtk.ListBoxRow):
|
||||||
"""A list row containing a Gtk.Switch."""
|
"""A ListBoxRow containing a Gtk.Switch and a title Label."""
|
||||||
|
|
||||||
def __init__(self, listitem: Gtk.ListItem):
|
active = GObject.Property(type=bool, default=True)
|
||||||
"""Initialize a VisibleSwitch ListRow."""
|
title = GObject.Property(type=str)
|
||||||
super().__init__(listitem=listitem, child=Gtk.Switch())
|
|
||||||
|
|
||||||
def do_bind(self) -> None:
|
def __init__(self, title: str, active: bool):
|
||||||
"""Bind the visible property to the switch active property."""
|
"""Initialize a VisibleRow ListBoxRow."""
|
||||||
self.bind_and_set_property("visible", "active", bidirectional=True)
|
super().__init__(title=title, active=active,
|
||||||
|
child=Gtk.Box(margin_start=6, margin_end=6,
|
||||||
|
margin_top=6, margin_bottom=6,
|
||||||
|
spacing=6))
|
||||||
|
self._switch = Gtk.Switch(active=active)
|
||||||
|
self._label = Gtk.Label.new(title)
|
||||||
|
|
||||||
|
self.bind_property("active", self._switch, "active",
|
||||||
|
GObject.BindingFlags.BIDIRECTIONAL)
|
||||||
|
|
||||||
|
self.props.child.append(self._switch)
|
||||||
|
self.props.child.append(self._label)
|
||||||
|
|
||||||
|
|
||||||
class VisibleColumns(buttons.PopoverButton):
|
class VisibleColumns(buttons.PopoverButton):
|
||||||
|
@ -29,20 +39,19 @@ class VisibleColumns(buttons.PopoverButton):
|
||||||
"""Initialize the VisibleColumns button."""
|
"""Initialize the VisibleColumns button."""
|
||||||
super().__init__(columns=columns, icon_name="columns-symbolic",
|
super().__init__(columns=columns, icon_name="columns-symbolic",
|
||||||
has_frame=False, **kwargs)
|
has_frame=False, **kwargs)
|
||||||
self._selection = Gtk.NoSelection(model=self.columns)
|
self.popover_child = Gtk.ListBox(selection_mode=Gtk.SelectionMode.NONE)
|
||||||
self.popover_child = Gtk.ColumnView(model=self._selection,
|
self.popover_child.bind_model(columns, self.__create_func)
|
||||||
show_row_separators=True)
|
self.popover_child.connect("row-activated", self.__row_activated)
|
||||||
self.__append_column(factory.InscriptionFactory("title"),
|
self.popover_child.add_css_class("boxed-list")
|
||||||
"Column", width=125)
|
|
||||||
self.__append_column(factory.Factory(row_type=VisibleSwitch),
|
|
||||||
"Visible")
|
|
||||||
self.popover_child.add_css_class("data-table")
|
|
||||||
|
|
||||||
def __append_column(self, factory: factory.Factory,
|
def __create_func(self, column: Gtk.ColumnViewColumn) -> VisibleRow:
|
||||||
title: str, *, width: int = -1) -> None:
|
row = VisibleRow(column.get_title(), column.get_visible())
|
||||||
column = Gtk.ColumnViewColumn(factory=factory, title=title,
|
row.bind_property("active", column, "visible",
|
||||||
fixed_width=width)
|
GObject.BindingFlags.BIDIRECTIONAL)
|
||||||
self.popover_child.append_column(column)
|
return row
|
||||||
|
|
||||||
|
def __row_activated(self, box: Gtk.ListBox, row: Gtk.ListBoxRow) -> None:
|
||||||
|
row.active = not row.active
|
||||||
|
|
||||||
|
|
||||||
class LoopButton(buttons.ImageToggle):
|
class LoopButton(buttons.ImageToggle):
|
||||||
|
|
|
@ -7,12 +7,62 @@ from gi.repository import Gio
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
|
||||||
|
class TestVisibleColumnRow(unittest.TestCase):
|
||||||
|
"""Test the Visible Column ListBoxRow."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Set up common variables."""
|
||||||
|
self.row = emmental.tracklist.buttons.VisibleRow("title", True)
|
||||||
|
|
||||||
|
def test_init(self):
|
||||||
|
"""Test that the VisibleRow was set up properly."""
|
||||||
|
self.assertIsInstance(self.row, Gtk.ListBoxRow)
|
||||||
|
self.assertIsInstance(self.row.props.child, Gtk.Box)
|
||||||
|
|
||||||
|
self.assertEqual(self.row.title, "title")
|
||||||
|
self.assertTrue(self.row.active)
|
||||||
|
|
||||||
|
self.assertEqual(self.row.props.child.props.margin_start, 6)
|
||||||
|
self.assertEqual(self.row.props.child.props.margin_end, 6)
|
||||||
|
self.assertEqual(self.row.props.child.props.margin_top, 6)
|
||||||
|
self.assertEqual(self.row.props.child.props.margin_bottom, 6)
|
||||||
|
self.assertEqual(self.row.props.child.props.spacing, 6)
|
||||||
|
|
||||||
|
row2 = emmental.tracklist.buttons.VisibleRow("title2", False)
|
||||||
|
self.assertEqual(row2.title, "title2")
|
||||||
|
self.assertFalse(row2.active)
|
||||||
|
|
||||||
|
def test_switch(self):
|
||||||
|
"""Test the VisibleRow switch."""
|
||||||
|
self.assertIsInstance(self.row._switch, Gtk.Switch)
|
||||||
|
self.assertEqual(self.row._switch.props.parent, self.row.props.child)
|
||||||
|
|
||||||
|
self.assertTrue(self.row._switch.props.active)
|
||||||
|
self.row.active = False
|
||||||
|
self.assertFalse(self.row._switch.props.active)
|
||||||
|
self.row._switch.props.active = True
|
||||||
|
self.assertTrue(self.row.active)
|
||||||
|
|
||||||
|
row2 = emmental.tracklist.buttons.VisibleRow("title2", False)
|
||||||
|
self.assertFalse(row2._switch.props.active)
|
||||||
|
|
||||||
|
def test_label(self):
|
||||||
|
"""Test the VisibleRow title label."""
|
||||||
|
self.assertIsInstance(self.row._label, Gtk.Label)
|
||||||
|
self.assertEqual(self.row._label.props.label, "title")
|
||||||
|
self.assertEqual(self.row._switch.get_next_sibling(),
|
||||||
|
self.row._label)
|
||||||
|
|
||||||
|
|
||||||
class TestVisibleColumns(unittest.TestCase):
|
class TestVisibleColumns(unittest.TestCase):
|
||||||
"""Test the Visible Columns button."""
|
"""Test the Visible Columns button."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Set up common variables."""
|
"""Set up common variables."""
|
||||||
self.columns = Gio.ListStore()
|
self.columns = Gio.ListStore()
|
||||||
|
self.columns.append(Gtk.ColumnViewColumn(title="title", visible=True))
|
||||||
|
self.columns.append(Gtk.ColumnViewColumn(title="title2",
|
||||||
|
visible=False))
|
||||||
self.button = emmental.tracklist.buttons.VisibleColumns(self.columns)
|
self.button = emmental.tracklist.buttons.VisibleColumns(self.columns)
|
||||||
|
|
||||||
def test_init(self):
|
def test_init(self):
|
||||||
|
@ -24,51 +74,37 @@ class TestVisibleColumns(unittest.TestCase):
|
||||||
|
|
||||||
def test_popover_child(self):
|
def test_popover_child(self):
|
||||||
"""Test that the popover_child was set up properly."""
|
"""Test that the popover_child was set up properly."""
|
||||||
self.assertIsInstance(self.button.popover_child, Gtk.ColumnView)
|
self.assertIsInstance(self.button.popover_child, Gtk.ListBox)
|
||||||
self.assertIsInstance(self.button._selection, Gtk.NoSelection)
|
self.assertEqual(self.button.popover_child.props.selection_mode,
|
||||||
self.assertTrue(self.button.popover_child.get_show_row_separators())
|
Gtk.SelectionMode.NONE)
|
||||||
self.assertTrue(self.button.popover_child.has_css_class("data-table"))
|
self.assertTrue(self.button.popover_child.has_css_class("boxed-list"))
|
||||||
|
|
||||||
self.assertEqual(self.button.popover_child.get_model(),
|
def test_create_func(self):
|
||||||
self.button._selection)
|
"""Test that the Gtk.ListBox creates VisibleRows correctly."""
|
||||||
self.assertEqual(self.button._selection.get_model(),
|
row = self.button.popover_child.get_row_at_index(0)
|
||||||
self.button.columns)
|
self.assertIsInstance(row, emmental.tracklist.buttons.VisibleRow)
|
||||||
|
self.assertEqual(row.title, "title")
|
||||||
|
self.assertTrue(row.active)
|
||||||
|
|
||||||
def test_columns(self):
|
row.active = False
|
||||||
"""Test the popover_child columns."""
|
self.assertFalse(self.columns[0].get_visible())
|
||||||
columns = self.button.popover_child.get_columns()
|
row.active = True
|
||||||
self.assertEqual(len(columns), 2)
|
self.assertTrue(self.columns[0].get_visible())
|
||||||
|
self.columns[0].set_visible(False)
|
||||||
|
self.assertFalse(row.active)
|
||||||
|
|
||||||
self.assertIsInstance(columns[0].get_factory(),
|
row = self.button.popover_child.get_row_at_index(1)
|
||||||
emmental.factory.InscriptionFactory)
|
self.assertIsInstance(row, emmental.tracklist.buttons.VisibleRow)
|
||||||
self.assertEqual(columns[0].get_title(), "Column")
|
self.assertEqual(row.title, "title2")
|
||||||
self.assertEqual(columns[0].get_fixed_width(), 125)
|
self.assertFalse(row.active)
|
||||||
|
|
||||||
self.assertIsInstance(columns[1].get_factory(),
|
def test_activate(self):
|
||||||
emmental.factory.Factory)
|
"""Test activating a Gtk.ListBox row."""
|
||||||
self.assertEqual(columns[1].get_factory().row_type,
|
row = self.button.popover_child.get_row_at_index(0)
|
||||||
emmental.tracklist.buttons.VisibleSwitch)
|
self.button.popover_child.emit("row-activated", row)
|
||||||
self.assertEqual(columns[1].get_title(), "Visible")
|
self.assertFalse(row.active)
|
||||||
self.assertEqual(columns[1].get_fixed_width(), -1)
|
self.button.popover_child.emit("row-activated", row)
|
||||||
|
self.assertTrue(row.active)
|
||||||
def test_visible_switch(self):
|
|
||||||
"""Test the visible switch widget."""
|
|
||||||
item = Gtk.Label()
|
|
||||||
listitem = Gtk.ListItem()
|
|
||||||
listitem.get_item = unittest.mock.Mock(return_value=item)
|
|
||||||
switch = emmental.tracklist.buttons.VisibleSwitch(listitem)
|
|
||||||
|
|
||||||
self.assertIsInstance(switch, emmental.factory.ListRow)
|
|
||||||
self.assertIsInstance(switch.child, Gtk.Switch)
|
|
||||||
|
|
||||||
switch.bind()
|
|
||||||
self.assertEqual(len(switch.bindings), 1)
|
|
||||||
self.assertTrue(switch.child.get_active())
|
|
||||||
|
|
||||||
item.set_visible(False)
|
|
||||||
self.assertFalse(switch.child.get_active())
|
|
||||||
switch.child.set_active(True)
|
|
||||||
item.set_visible(True)
|
|
||||||
|
|
||||||
|
|
||||||
class TestLoopButton(unittest.TestCase):
|
class TestLoopButton(unittest.TestCase):
|
||||||
|
|
Loading…
Reference in New Issue