gtk: Add a window to the Application

This is an empty Adw.Window with a headerbar configured to display the
application name. I also bind the Application runid property to the
Window to print out the currently displayed run.

Signed-off-by: Anna Schumaker <anna@nowheycreamery.com>
This commit is contained in:
Anna Schumaker 2023-07-28 16:59:48 -04:00
parent d5413700f0
commit c1b73748f1
4 changed files with 135 additions and 6 deletions

66
tests/gtk/test_window.py Normal file
View File

@ -0,0 +1,66 @@
# Copyright 2023 (c) Anna Schumaker.
"""Tests our Window implementation."""
import unittest
import xfstestsdb.gtk.window
from gi.repository import Gtk
from gi.repository import Adw
class TestWindow(unittest.TestCase):
"""Test case for our Window subclass."""
def setUp(self):
"""Set up common variables."""
self.window = xfstestsdb.gtk.window.Window()
def test_init(self):
"""Check that the Window is set up correctly."""
self.assertIsInstance(self.window, Adw.Window)
self.assertEqual(self.window.props.default_height, 800)
self.assertEqual(self.window.props.default_width, 1200)
self.assertTrue(self.window.has_css_class("devel"))
self.assertIsInstance(self.window.props.content, Gtk.Box)
self.assertEqual(self.window.props.content.get_orientation(),
Gtk.Orientation.VERTICAL)
def test_headerbar(self):
"""Test the headerbar property."""
self.assertIsInstance(self.window.headerbar, Adw.HeaderBar)
self.assertEqual(self.window.props.content.get_first_child(),
self.window.headerbar)
self.assertTrue(self.window.headerbar.has_css_class("flat"))
def test_title_widget(self):
"""Test the title widget property."""
self.assertIsInstance(self.window.title, Adw.WindowTitle)
self.assertEqual(self.window.title.props.title, "xfstestsdb gtk")
self.assertEqual(self.window.headerbar.props.title_widget,
self.window.title)
def test_child(self):
"""Test the window child property."""
self.assertIsInstance(self.window.headerbar.get_next_sibling(),
Adw.Bin)
self.assertIsNone(self.window.child)
self.window.child = Gtk.Label()
self.assertEqual(self.window.headerbar.get_next_sibling().props.child,
self.window.child)
label = Gtk.Label()
window2 = xfstestsdb.gtk.window.Window(child=label)
self.assertEqual(window2.child, label)
self.assertEqual(window2.headerbar.get_next_sibling().props.child,
label)
def test_runid(self):
"""Test the window runid property."""
self.assertEqual(self.window.runid, 0)
self.assertEqual(self.window.title.props.subtitle, "")
self.window.runid = 3
self.assertEqual(self.window.title.props.subtitle, "runid #3")
self.window.runid = 0
self.assertEqual(self.window.title.props.subtitle, "")

View File

@ -50,17 +50,36 @@ class TestApplication(unittest.TestCase):
mock_activate.assert_called()
self.assertEqual(self.application.runid, 42)
@unittest.mock.patch("gi.repository.Adw.Application.add_window")
@unittest.mock.patch("gi.repository.Adw.Application.do_startup")
def test_startup(self, mock_startup: unittest.mock.Mock):
def test_startup(self, mock_startup: unittest.mock.Mock,
mock_add_window: unittest.mock.Mock):
"""Check that startup sets up our application instance correctly."""
self.application.emit("startup")
mock_startup.assert_called_with(self.application)
self.assertIsNone(self.application.win)
self.application.emit("startup")
self.assertIsInstance(self.application.win,
xfstestsdb.gtk.window.Window)
mock_startup.assert_called_with(self.application)
mock_add_window.assert_called_with(self.application.win)
self.application.runid = 42
self.assertEqual(self.application.win.runid, 42)
@unittest.mock.patch("gi.repository.Adw.Application.add_window")
@unittest.mock.patch("gi.repository.Adw.Application.do_startup")
@unittest.mock.patch("gi.repository.Adw.Application.do_activate")
def test_activate(self, mock_activate: unittest.mock.Mock):
def test_activate(self, mock_activate: unittest.mock.Mock,
mock_startup: unittest.mock.Mock,
mock_add_window: unittest.mock.Mock):
"""Check that activating our application works correctly."""
self.application.emit("activate")
mock_activate.assert_called_with(self.application)
self.application.emit("startup")
with unittest.mock.patch.object(self.application.win,
"present") as mock_present:
self.application.emit("activate")
mock_activate.assert_called_with(self.application)
mock_present.assert_called()
@unittest.mock.patch("gi.repository.Adw.Application.do_shutdown")
def test_shutdown(self, mock_shutdown: unittest.mock.Mock):

View File

@ -7,6 +7,7 @@ from . import gsetup
from gi.repository import GObject
from gi.repository import Gio
from gi.repository import Adw
from . import window
from .. import commands
from .. import sqlite
@ -15,6 +16,7 @@ class Application(Adw.Application):
"""Our Adw.Application for displaying xfstests results."""
runid = GObject.Property(type=int)
win = GObject.Property(type=window.Window)
def __init__(self):
"""Initialize the application."""
@ -36,10 +38,14 @@ class Application(Adw.Application):
def do_startup(self) -> None:
"""Handle the Adw.Application::startup signal."""
Adw.Application.do_startup(self)
self.win = window.Window()
self.bind_property("runid", self.win, "runid")
self.add_window(self.win)
def do_activate(self) -> None:
"""Handle the Adw.Application::activate signal."""
Adw.Application.do_activate(self)
self.win.present()
def do_shutdown(self) -> None:
"""Handle the Adw.Application::shutdown signal."""

38
xfstestsdb/gtk/window.py Normal file
View File

@ -0,0 +1,38 @@
# Copyright 2023 (c) Anna Schumaker.
"""The main Adw.Window implementation for our application."""
import typing
from gi.repository import GObject
from gi.repository import Gtk
from gi.repository import Adw
class Window(Adw.Window):
"""Our customized Window displayed to the user."""
child = GObject.Property(type=Gtk.Widget)
headerbar = GObject.Property(type=Adw.HeaderBar)
title = GObject.Property(type=Adw.WindowTitle)
runid = GObject.Property(type=int)
def __init__(self, **kwargs):
"""Set up our Window."""
super().__init__(default_height=800, default_width=1200,
content=Gtk.Box(orientation=Gtk.Orientation.VERTICAL),
title=Adw.WindowTitle(title="xfstestsdb gtk"),
headerbar=Adw.HeaderBar(), **kwargs)
self.headerbar.props.title_widget = self.title
self.headerbar.add_css_class("flat")
self.props.content.append(self.headerbar)
self.props.content.append(Adw.Bin(child=self.child))
self.bind_property("child", self.headerbar.get_next_sibling(), "child")
self.connect("notify::runid", self.__notify_runid)
if __debug__:
self.add_css_class("devel")
def __notify_runid(self, window: typing.Self,
param: GObject.ParamSpec) -> None:
text = f"runid #{self.runid}" if self.runid > 0 else ""
self.title.props.subtitle = text