xfstestsdb/xfstestsdb/gtk/view.py

196 lines
7.5 KiB
Python

# Copyright 2023 (c) Anna Schumaker.
"""A view widget used to display our TestCaseModel."""
from gi.repository import GObject
from gi.repository import Gtk
from .model import PropertyList
from .model import PropertyFilter
from .model import TestCaseList
from .model import TestCaseFilter
from .model import SummaryList
from . import button
from . import row
class PropertyView(Gtk.ScrolledWindow):
"""Displays our PropertyList model to the user."""
def __init__(self):
"""Initialize a PropertyView."""
super().__init__(child=Gtk.ColumnView(model=Gtk.NoSelection(),
show_row_separators=True,
show_column_separators=True,
hexpand=True),
vscrollbar_policy=Gtk.PolicyType.NEVER)
self._property = Gtk.ColumnViewColumn(title="property",
factory=row.LabelFactory("name"))
self._propfilter = PropertyFilter()
self._filtermodel = Gtk.FilterListModel(filter=self._propfilter)
self.props.child.get_model().set_model(self._filtermodel)
self.props.child.add_css_class("data-table")
self.add_css_class("card")
def __property_column(self, xunit: str) -> None:
return Gtk.ColumnViewColumn(title=xunit, expand=True,
factory=row.PropertyFactory(xunit))
@GObject.Property(type=PropertyList)
def model(self) -> PropertyList:
"""Get the PropertyList shown by the View."""
return self._filtermodel.props.model
@model.setter
def model(self, new: PropertyList) -> None:
for col in [col for col in self.props.child.get_columns()]:
self.props.child.remove_column(col)
self._filtermodel.props.model = new
if new is not None:
self.props.child.append_column(self._property)
for xunit in new.get_xunits():
self.props.child.append_column(self.__property_column(xunit))
class FilterButtons(Gtk.Box):
"""Buttons for controlling the TestCaseFilter."""
passed = GObject.Property(type=bool, default=False)
skipped = GObject.Property(type=bool, default=False)
failure = GObject.Property(type=bool, default=True)
def __init__(self):
"""Initialize the FilterButtons."""
super().__init__()
self.add_css_class("linked")
self._passed = button.StatusToggle("test-pass", "passed")
self._skipped = button.StatusToggle("test-skip", "skipped")
self._failure = button.StatusToggle("test-fail", "failure",
active=True)
self._passed.bind_property("active", self, "passed")
self._skipped.bind_property("active", self, "skipped")
self._failure.bind_property("active", self, "failure")
self.append(self._passed)
self.append(self._skipped)
self.append(self._failure)
class TestCaseView(Gtk.ScrolledWindow):
"""Displays our TestCaseList model to the user."""
filterbuttons = GObject.Property(type=FilterButtons)
def __init__(self):
"""Initialize a TestCaseView."""
super().__init__(child=Gtk.ColumnView(model=Gtk.NoSelection(),
show_row_separators=True,
show_column_separators=True,
hexpand=True, vexpand=True),
filterbuttons=FilterButtons())
self._testcase = Gtk.ColumnViewColumn(title="testcase",
factory=row.LabelFactory("name"))
self._testfilter = TestCaseFilter()
self._filtermodel = Gtk.FilterListModel(filter=self._testfilter)
for prop in ["passed", "skipped", "failure"]:
self.filterbuttons.bind_property(prop, self._testfilter, prop)
self.props.child.get_model().set_model(self._filtermodel)
self.add_css_class("card")
def __xunit_column(self, xunit: str) -> None:
return Gtk.ColumnViewColumn(title=xunit, expand=True,
factory=row.ResultFactory(xunit))
def make_buttons(self) -> FilterButtons:
"""Make a new FilterButtons instance connected to this View."""
return FilterButtons()
@GObject.Property(type=TestCaseList)
def model(self) -> TestCaseList:
"""Get the TestCaseList shown by the View."""
return self._filtermodel.props.model
@model.setter
def model(self, new: TestCaseList) -> None:
for col in [col for col in self.props.child.get_columns()]:
self.props.child.remove_column(col)
self._filtermodel.props.model = new
if new is not None:
self.props.child.append_column(self._testcase)
for xunit in new.get_xunits():
self.props.child.append_column(self.__xunit_column(xunit))
class SummaryView(Gtk.ScrolledWindow):
"""Displays our SummaryList model to the user."""
def __init__(self):
"""Initialize a SummaryView."""
super().__init__(child=Gtk.ColumnView(model=Gtk.NoSelection(),
show_row_separators=True,
show_column_separators=True,
hexpand=True),
vscrollbar_policy=Gtk.PolicyType.NEVER)
self._summary = Gtk.ColumnViewColumn(title="summary",
factory=row.LabelFactory("name"))
self.add_css_class("card")
def __summary_column(self, xunit: str) -> None:
return Gtk.ColumnViewColumn(title=xunit, expand=True,
factory=row.SummaryFactory(xunit))
@GObject.Property(type=SummaryList)
def model(self) -> SummaryList:
"""Get the SummaryList shown by the View."""
return self.props.child.get_model().get_model()
@model.setter
def model(self, new: SummaryList) -> None:
for col in [col for col in self.props.child.get_columns()]:
self.props.child.remove_column(col)
self.props.child.get_model().set_model(new)
if new is not None:
self.props.child.append_column(self._summary)
for xunit in new.get_xunits():
self.props.child.append_column(self.__summary_column(xunit))
class XfstestsView(Gtk.Box):
"""A widget to display the results of an Xfstests runs."""
properties = GObject.Property(type=PropertyList)
model = GObject.Property(type=TestCaseList)
summary = GObject.Property(type=SummaryList)
def __init__(self):
"""Initialize an XfstestsView."""
super().__init__(orientation=Gtk.Orientation.VERTICAL)
self._propertyview = PropertyView()
self._testcaseview = TestCaseView()
self._summaryview = SummaryView()
self.bind_property("properties", self._propertyview, "model")
self.bind_property("model", self._testcaseview, "model")
self.bind_property("summary", self._summaryview, "model")
self.append(self._propertyview)
self.append(Gtk.Separator())
self.append(self._testcaseview)
self.append(Gtk.Separator())
self.append(self._summaryview)
@GObject.Property(type=FilterButtons)
def filterbuttons(self) -> FilterButtons:
"""Get the FilterButtons attached to the child TestCaseView."""
return self._testcaseview.filterbuttons