diff --git a/emmental/tracklist/buttons.py b/emmental/tracklist/buttons.py index f46e1ce..a0daff4 100644 --- a/emmental/tracklist/buttons.py +++ b/emmental/tracklist/buttons.py @@ -8,16 +8,26 @@ from .. import buttons from .. import factory -class VisibleSwitch(factory.ListRow): - """A list row containing a Gtk.Switch.""" +class VisibleRow(Gtk.ListBoxRow): + """A ListBoxRow containing a Gtk.Switch and a title Label.""" - def __init__(self, listitem: Gtk.ListItem): - """Initialize a VisibleSwitch ListRow.""" - super().__init__(listitem=listitem, child=Gtk.Switch()) + active = GObject.Property(type=bool, default=True) + title = GObject.Property(type=str) - def do_bind(self) -> None: - """Bind the visible property to the switch active property.""" - self.bind_and_set_property("visible", "active", bidirectional=True) + def __init__(self, title: str, active: bool): + """Initialize a VisibleRow ListBoxRow.""" + 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): @@ -29,20 +39,19 @@ class VisibleColumns(buttons.PopoverButton): """Initialize the VisibleColumns button.""" super().__init__(columns=columns, icon_name="columns-symbolic", has_frame=False, **kwargs) - self._selection = Gtk.NoSelection(model=self.columns) - self.popover_child = Gtk.ColumnView(model=self._selection, - show_row_separators=True) - self.__append_column(factory.InscriptionFactory("title"), - "Column", width=125) - self.__append_column(factory.Factory(row_type=VisibleSwitch), - "Visible") - self.popover_child.add_css_class("data-table") + self.popover_child = Gtk.ListBox(selection_mode=Gtk.SelectionMode.NONE) + self.popover_child.bind_model(columns, self.__create_func) + self.popover_child.connect("row-activated", self.__row_activated) + self.popover_child.add_css_class("boxed-list") - def __append_column(self, factory: factory.Factory, - title: str, *, width: int = -1) -> None: - column = Gtk.ColumnViewColumn(factory=factory, title=title, - fixed_width=width) - self.popover_child.append_column(column) + def __create_func(self, column: Gtk.ColumnViewColumn) -> VisibleRow: + row = VisibleRow(column.get_title(), column.get_visible()) + row.bind_property("active", column, "visible", + GObject.BindingFlags.BIDIRECTIONAL) + return row + + def __row_activated(self, box: Gtk.ListBox, row: Gtk.ListBoxRow) -> None: + row.active = not row.active class LoopButton(buttons.ImageToggle): diff --git a/tests/tracklist/test_buttons.py b/tests/tracklist/test_buttons.py index 65e8777..fd85573 100644 --- a/tests/tracklist/test_buttons.py +++ b/tests/tracklist/test_buttons.py @@ -7,12 +7,62 @@ from gi.repository import Gio 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): """Test the Visible Columns button.""" def setUp(self): """Set up common variables.""" 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) def test_init(self): @@ -24,51 +74,37 @@ class TestVisibleColumns(unittest.TestCase): def test_popover_child(self): """Test that the popover_child was set up properly.""" - self.assertIsInstance(self.button.popover_child, Gtk.ColumnView) - self.assertIsInstance(self.button._selection, Gtk.NoSelection) - self.assertTrue(self.button.popover_child.get_show_row_separators()) - self.assertTrue(self.button.popover_child.has_css_class("data-table")) + self.assertIsInstance(self.button.popover_child, Gtk.ListBox) + self.assertEqual(self.button.popover_child.props.selection_mode, + Gtk.SelectionMode.NONE) + self.assertTrue(self.button.popover_child.has_css_class("boxed-list")) - self.assertEqual(self.button.popover_child.get_model(), - self.button._selection) - self.assertEqual(self.button._selection.get_model(), - self.button.columns) + def test_create_func(self): + """Test that the Gtk.ListBox creates VisibleRows correctly.""" + row = self.button.popover_child.get_row_at_index(0) + self.assertIsInstance(row, emmental.tracklist.buttons.VisibleRow) + self.assertEqual(row.title, "title") + self.assertTrue(row.active) - def test_columns(self): - """Test the popover_child columns.""" - columns = self.button.popover_child.get_columns() - self.assertEqual(len(columns), 2) + row.active = False + self.assertFalse(self.columns[0].get_visible()) + row.active = True + self.assertTrue(self.columns[0].get_visible()) + self.columns[0].set_visible(False) + self.assertFalse(row.active) - self.assertIsInstance(columns[0].get_factory(), - emmental.factory.InscriptionFactory) - self.assertEqual(columns[0].get_title(), "Column") - self.assertEqual(columns[0].get_fixed_width(), 125) + row = self.button.popover_child.get_row_at_index(1) + self.assertIsInstance(row, emmental.tracklist.buttons.VisibleRow) + self.assertEqual(row.title, "title2") + self.assertFalse(row.active) - self.assertIsInstance(columns[1].get_factory(), - emmental.factory.Factory) - self.assertEqual(columns[1].get_factory().row_type, - emmental.tracklist.buttons.VisibleSwitch) - self.assertEqual(columns[1].get_title(), "Visible") - self.assertEqual(columns[1].get_fixed_width(), -1) - - 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) + def test_activate(self): + """Test activating a Gtk.ListBox row.""" + row = self.button.popover_child.get_row_at_index(0) + self.button.popover_child.emit("row-activated", row) + self.assertFalse(row.active) + self.button.popover_child.emit("row-activated", row) + self.assertTrue(row.active) class TestLoopButton(unittest.TestCase):