factory: Create a TreeRow
The TreeRow is used to display rows from a Gtk.TreeListModel. I adjust the TreeRow "item" and "child" properties so they still access the underlying item or child widget instead of the Gtk.TreeRow or Gtk.TreeExpander. I also give the TreeRow widget "n-children" and "have-children" properties which are used to dynamically show or hide the expander arrow when there aren't any children. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
40c463da81
commit
9d7763a730
|
@ -2,6 +2,7 @@
|
|||
"""A customized Gtk.SignalListItemFactory for easier use."""
|
||||
import typing
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gio
|
||||
from gi.repository import Gtk
|
||||
|
||||
|
||||
|
@ -86,6 +87,54 @@ class InscriptionRow(ListRow):
|
|||
self.bind_and_set_property(self.item_property, "text")
|
||||
|
||||
|
||||
class TreeRow(ListRow):
|
||||
"""A ListRow for displaying child widgets in a Tree."""
|
||||
|
||||
n_children = GObject.Property(type=int)
|
||||
have_children = GObject.Property(type=bool, default=False)
|
||||
indented = GObject.Property(type=bool, default=True)
|
||||
|
||||
def __init__(self, listitem: Gtk.ListItem, **kwargs) -> None:
|
||||
"""Create a new TreeRow."""
|
||||
super().__init__(listitem, **kwargs)
|
||||
listitem.set_child(Gtk.TreeExpander(hide_expander=True,
|
||||
indent_for_icon=self.indented))
|
||||
self.bind_property("n-children", self, "have-children")
|
||||
self.bind_property("have-children", listitem.get_child(),
|
||||
"hide-expander",
|
||||
GObject.BindingFlags.INVERT_BOOLEAN)
|
||||
self.bind_property("indented", listitem.get_child(), "indent-for-icon")
|
||||
|
||||
def bind(self) -> None:
|
||||
"""Bind a TreeRow to the TreeExpander."""
|
||||
self.listitem.get_child().set_list_row(self.listitem.get_item())
|
||||
super().bind()
|
||||
|
||||
def bind_n_children(self, children: Gio.ListModel | None) -> None:
|
||||
"""Bind to the n-items property of the child listmodel."""
|
||||
if children is not None:
|
||||
self.bind_and_set(children, "n-items", self, "n-children")
|
||||
|
||||
def unbind(self) -> None:
|
||||
"""Unbind a TreeRow from the TreeExpander."""
|
||||
self.listitem.get_child().set_list_row(None)
|
||||
super().unbind()
|
||||
|
||||
@GObject.Property(type=Gtk.Widget)
|
||||
def child(self) -> Gtk.Widget | None:
|
||||
"""Get the child widget displayed by this Row."""
|
||||
return self.listitem.get_child().get_child()
|
||||
|
||||
@child.setter
|
||||
def child(self, newval=Gtk.Widget) -> None:
|
||||
self.listitem.get_child().set_child(newval)
|
||||
|
||||
@GObject.Property(type=GObject.TYPE_PYOBJECT)
|
||||
def item(self) -> GObject.TYPE_PYOBJECT:
|
||||
"""Get the list item for this Row."""
|
||||
return self.listitem.get_item().get_item()
|
||||
|
||||
|
||||
class Factory(Gtk.SignalListItemFactory):
|
||||
"""A customized Factory for making list row widgets."""
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import unittest
|
||||
import unittest.mock
|
||||
import emmental.factory
|
||||
from gi.repository import Gio
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GObject
|
||||
|
||||
|
@ -102,6 +103,74 @@ class TestInscriptionRow(unittest.TestCase):
|
|||
self.assertTrue(row.child.has_css_class("numeric"))
|
||||
|
||||
|
||||
class TestTreeRow(unittest.TestCase):
|
||||
"""Test our pre-configured TreeRow."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up common variables."""
|
||||
self.item = Gtk.Label(label="Test")
|
||||
self.child = Gtk.Label()
|
||||
|
||||
self.treerow = Gtk.TreeListRow()
|
||||
self.treerow.get_item = unittest.mock.Mock(return_value=self.item)
|
||||
|
||||
self.listitem = Gtk.ListItem()
|
||||
self.listitem.get_item = unittest.mock.Mock(return_value=self.treerow)
|
||||
self.row = emmental.factory.TreeRow(self.listitem)
|
||||
|
||||
def test_tree_row(self):
|
||||
"""Test that the TreeRow works as expected."""
|
||||
self.assertIsInstance(self.row, emmental.factory.ListRow)
|
||||
self.assertIsInstance(self.listitem.get_child(), Gtk.TreeExpander)
|
||||
self.assertEqual(self.row.item, self.item)
|
||||
|
||||
self.row.child = self.child
|
||||
self.assertEqual(self.listitem.get_child().get_child(), self.child)
|
||||
self.assertEqual(self.row.child, self.child)
|
||||
|
||||
self.row.bind()
|
||||
self.assertEqual(self.listitem.get_child().get_list_row(),
|
||||
self.treerow)
|
||||
self.row.unbind()
|
||||
self.assertIsNone(self.listitem.get_child().get_list_row())
|
||||
|
||||
def test_indented(self):
|
||||
"""Test the indended property."""
|
||||
self.assertTrue(self.row.indented)
|
||||
self.assertTrue(self.listitem.get_child().get_indent_for_icon())
|
||||
|
||||
self.row.indented = False
|
||||
self.assertFalse(self.listitem.get_child().get_indent_for_icon())
|
||||
|
||||
row2 = emmental.factory.TreeRow(self.listitem, indented=False)
|
||||
self.assertFalse(row2.indented)
|
||||
self.assertFalse(self.listitem.get_child().get_indent_for_icon())
|
||||
|
||||
def test_bind_n_children(self):
|
||||
"""Test binding to the n_children property."""
|
||||
expander = self.listitem.get_child()
|
||||
liststore = Gio.ListStore()
|
||||
|
||||
self.assertEqual(self.row.n_children, 0)
|
||||
self.assertFalse(self.row.have_children)
|
||||
self.assertTrue(expander.get_hide_expander())
|
||||
|
||||
self.row.n_children = 1
|
||||
self.assertTrue(self.row.have_children)
|
||||
self.assertFalse(expander.get_hide_expander())
|
||||
|
||||
self.row.bind_n_children(None)
|
||||
self.assertEqual(len(self.row.bindings), 0)
|
||||
|
||||
self.row.bind_n_children(liststore)
|
||||
self.assertEqual(self.row.n_children, 0)
|
||||
self.assertTrue(expander.get_hide_expander())
|
||||
|
||||
liststore.append(Gtk.Label())
|
||||
self.assertEqual(self.row.n_children, 1)
|
||||
self.assertFalse(expander.get_hide_expander())
|
||||
|
||||
|
||||
class TestFactory(unittest.TestCase):
|
||||
"""Test a Factory."""
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user