gtk: Add a CalendarView class for selecting xfstests runs by date

This combines a Calendar and RunidView to select runs on a given day.

Signed-off-by: Anna Schumaker <anna@nowheycreamery.com>
This commit is contained in:
Anna Schumaker 2023-11-03 13:28:25 -04:00
parent bac99c9c54
commit 704eb08091
2 changed files with 133 additions and 0 deletions

View File

@ -3,6 +3,7 @@
import datetime import datetime
import unittest import unittest
import xfstestsdb.gtk.sidebar import xfstestsdb.gtk.sidebar
from gi.repository import GLib
from gi.repository import Gtk from gi.repository import Gtk
@ -84,3 +85,84 @@ class TestRunidView(unittest.TestCase):
self.view._view.emit("activate", 0) self.view._view.emit("activate", 0)
self.assertTrue(self.view._selection[0].get_expanded()) self.assertTrue(self.view._selection[0].get_expanded())
self.assertEqual(self.view.runid, 2) self.assertEqual(self.view.runid, 2)
class TestCalendarView(unittest.TestCase):
"""Test the CalendarView class."""
def setUp(self):
"""Set up common variables."""
self.xfstestsdb = xfstestsdb.Command()
with unittest.mock.patch("sys.stdout"):
self.xfstestsdb.run(["new", "/dev/vda1"])
self.xfstestsdb.run(["new", "/dev/vda2"])
self.xfstestsdb.run(["new", "/dev/vda3"])
self.xfstestsdb.run(["new", "/dev/vda4"])
query = "UPDATE xfstests_runs SET timestamp=? WHERE runid=?"
dtime = datetime.datetime.now().replace(year=2023, month=1)
self.xfstestsdb.sql(query, dtime.replace(day=1), 1)
self.xfstestsdb.sql(query, dtime.replace(day=8), 2)
self.xfstestsdb.sql(query, dtime.replace(day=15), 3)
self.sidebar = xfstestsdb.gtk.sidebar.CalendarView(self.xfstestsdb.sql)
def test_init(self):
"""Test that the calendar view was set up properly."""
self.assertIsInstance(self.sidebar, Gtk.Box)
self.assertEqual(self.sidebar.props.spacing, 6)
self.assertEqual(self.sidebar.props.orientation,
Gtk.Orientation.VERTICAL)
self.assertEqual(self.sidebar.sql, self.xfstestsdb.sql)
def test_calendar(self):
"""Test the calendar widget."""
self.assertIsInstance(self.sidebar._calendar, Gtk.Calendar)
self.assertEqual(self.sidebar.get_first_child(),
self.sidebar._calendar)
today = datetime.date.today()
self.assertTrue(self.sidebar._calendar.get_day_is_marked(today.day))
def test_view(self):
"""Test the runid view widget."""
self.assertIsInstance(self.sidebar._view,
xfstestsdb.gtk.sidebar.RunidView)
self.assertIsInstance(self.sidebar._view.model,
xfstestsdb.gtk.tree.DateDeviceList)
self.assertEqual(self.sidebar._calendar.get_next_sibling(),
self.sidebar._view)
self.assertEqual(self.sidebar._view.model.date, datetime.date.today())
def test_marked_days(self):
"""Test marking days in the calendar."""
gl_date = GLib.DateTime.new_local(2023, 1, 10, 0, 0, 0)
self.sidebar._calendar.select_day(gl_date)
for signal in ["next-month", "next-year", "prev-month", "prev-year"]:
with self.subTest(signal=signal):
with unittest.mock.patch.object(self.sidebar._calendar,
"clear_marks") as mock_clear:
with unittest.mock.patch.object(self.sidebar._calendar,
"mark_day") as mock_mark:
self.sidebar._calendar.emit(signal)
mock_clear.assert_called()
mock_mark.assert_has_calls([unittest.mock.call(1),
unittest.mock.call(8),
unittest.mock.call(15)])
def test_select_day(self):
"""Test selecting a day in the calendar."""
gl_now = GLib.DateTime.new_now_local()
self.sidebar._calendar.select_day(gl_now.add_days(-1))
today = datetime.date.today()
self.assertEqual(self.sidebar._view.model.date,
today - datetime.timedelta(days=1))
def test_runid_property(self):
"""Test the runid property."""
self.assertEqual(self.sidebar.runid, 0)
self.sidebar._view.runid = 42
self.assertEqual(self.sidebar.runid, 42)

View File

@ -1,9 +1,11 @@
# Copyright 2023 (c) Anna Schumaker. # Copyright 2023 (c) Anna Schumaker.
"""Our sidebar for selecting a specific xfstests run to view.""" """Our sidebar for selecting a specific xfstests run to view."""
import datetime
import typing import typing
from gi.repository import GObject from gi.repository import GObject
from gi.repository import Gio from gi.repository import Gio
from gi.repository import Gtk from gi.repository import Gtk
from .. import sqlite
from . import row from . import row
from . import tree from . import tree
@ -44,3 +46,52 @@ class RunidView(Gtk.ScrolledWindow):
param: GObject.ParamSpec) -> None: param: GObject.ParamSpec) -> None:
model = None if self.model is None else self.model.treemodel model = None if self.model is None else self.model.treemodel
self._selection.props.model = model self._selection.props.model = model
class CalendarView(Gtk.Box):
"""Our calendar view for seleting an xfstests run by date."""
runid = GObject.Property(type=int)
sql = GObject.Property(type=GObject.TYPE_PYOBJECT)
def __init__(self, sql: sqlite.Connection) -> None:
"""Initialize a CalendarView instance."""
super().__init__(sql=sql, spacing=6,
orientation=Gtk.Orientation.VERTICAL)
today = datetime.date.today()
self._calendar = Gtk.Calendar()
self._view = RunidView(model=tree.DateDeviceList(sql, today))
self._view.bind_property("runid", self, "runid")
self._calendar.connect("day-selected", self.__day_selected)
self._calendar.connect("next-month", self.__date_changed)
self._calendar.connect("next-year", self.__date_changed)
self._calendar.connect("prev-month", self.__date_changed)
self._calendar.connect("prev-year", self.__date_changed)
self.__mark_days(today)
self.append(self._calendar)
self.append(self._view)
def __day_selected(self, calendar: Gtk.Calendar) -> None:
self.__select_day(datetime.date(*calendar.get_date().get_ymd()))
def __date_changed(self, calendar: Gtk.Calendar) -> None:
date = datetime.date(*calendar.get_date().get_ymd())
self.__mark_days(date)
self.__select_day(date)
def __select_day(self, date: datetime.date) -> None:
self._view.model = tree.DateDeviceList(self.sql, date)
def __mark_days(self, date: datetime.date) -> None:
min = datetime.datetime.combine(date.replace(day=1), datetime.time())
max = (min + datetime.timedelta(days=40)).replace(day=1)
self._calendar.clear_marks()
for stamp in self.sql("""SELECT DISTINCT timestamp FROM tagged_runs
WHERE timestamp >= ? AND timestamp < ?""",
min, max).fetchall():
ts = datetime.datetime.fromisoformat(stamp['timestamp'])
self._calendar.mark_day(ts.day)