Commit 5f12f99e authored by David Boddie's avatar David Boddie

Expanded the documentation, writing more about the main code and user interface.

parent 590a3415
.. _details:
Implementation Details
======================
.. toctree::
:hidden:
user_interface
main
......@@ -14,8 +14,7 @@ metadata files.
:includehidden:
overview
main
user_interface
details
building
packaging
......
......@@ -5,16 +5,21 @@ Most the code for the application is included in a single ``main.py`` file
which contains a single ``Application`` class to manage the running of the
application and a ``main`` function to start it.
Importing Modules
-----------------
We begin by importing two standard Python modules that our application will
need:
.. literalinclude:: ../src/main.py
:start-at: import
:end-at: sys
:end-at: from
The ``sys`` module provides access to the command line arguments used when
the application was run. We use the ``random`` module to make our game
interesting.
interesting. The ``config`` module is one that is generated by the build system
to enable us to access information about where the application and its
resources are installed.
We also import modules that allow us to create user interfaces:
......@@ -22,6 +27,59 @@ We also import modules that allow us to create user interfaces:
:start-at: import gi
:end-at: Handy.init
These are standard modules for accessing GTK+ and GNOME features, plus one
that lets us create adaptive user interfaces.
These are standard modules for accessing GTK+ and GNOME features, plus the
``Handy`` module that helps us to create adaptive user interfaces.
The Application Class
---------------------
The application is represented by the ``Application`` class which is derived
from the standard ``Gtk.Application`` class. This is defined in the normal way,
beginning with the ``__init__`` method:
.. literalinclude:: ../src/main.py
:start-at: class Application
:end-at: GLib.set_application_name
This method performs two things that are necessary for the application to run
correctly:
1. It uses the ``super`` built-function to call the ``__init__`` method of the
base class. This associates the application with the application ID given.
The application ID must have a certain format. This is described in the
`Gio.GApplication documentation`_.
2. It calls the ``GLib.set_application_name`` function to set a user-readable
application name that will be localized if translations are available.
The ``do_startup`` method is responsible for performing tasks that only need to
be done at application start-up. In this example there are plenty of things
that need to be done at this point.
.. literalinclude:: ../src/main.py
:start-at: def do_startup
:end-at: Gtk.Application.do_startup
After calling the ``do_startup`` method of the base class, we can begin to set
up the application, beginning by reading a style sheet from the application's
built-in resources:
.. literalinclude:: ../src/main.py
:start-at: Load a style
:end-at: os.path.join
We also locate and read the application's images from their installed locations
on the system, as described in :ref:`data_dir`.
The application's user interface is defined using UI files which we briefly
covered in :ref:`user_interface`. The interface is constructed at run-time
using the `Gtk.Builder` class. We set it up for use by creating an instance of
this class and set its translation domain so that the user-visible text in the
UI files can be translated using message catalogs (see :ref:`po_dir`).
.. literalinclude:: ../src/main.py
:start-at: Create a builder
:end-at: set_icon_name
.. _`Gio.GApplication documentation`: https://developer.gnome.org/gio/stable/GApplication.html#g-application-id-is-valid
......@@ -2,3 +2,57 @@
User Interface
==============
The application's user interface is defined using two UI files: ``window.ui``
describes the application's window and ``menus.ui`` describes its app menu.
The ``window.ui`` file was created using the `Glade`_ user interface design
tool and ``menus.ui`` was written using a text editor.
The Application Window
----------------------
The window is a simple collection of widgets contained within a
``GtkApplicationWindow`` widget. At the top of the window is a ``HdyTitleBar``
[#f1]_ which contains a standard ``GtkHeaderBar`` with a title string and a
``GtkMenuButton`` that is used at run-time to let the user access the app menu.
.. figure:: images/window-ui.png
:alt: The application window as shown in Glade
The application window as shown in Glade
Beneath the title bar is a ``GtkBox`` container that holds a ``GtkGrid``, where
the game is played, and two ``GtkLabel`` widgets that are used to show scores
and other messages.
The structure of the window is shown in the following figure:
.. figure:: images/window-ui-hierarchy.png
:alt: Widget hierarchy of the application window
Widget hierarchy of the application window
This hierarchy is presented to the designer in the Glade user interface, and is
convenient for selecting and navigating between widgets.
The App Menu
------------
Unlike the user interface for the window, the menu's UI file was defined in a
text editor and relates menu items to actions that the application's code can
handle:
.. literalinclude:: ../src/ui/menus.ui
The actions are defined to be application-wide -- each has the ``app.`` prefix.
Their strings are marked as translatable so that they will be included in the
message catalogs described in :ref:`po_dir`. Actions are described in more
details in the `Actions section`_ of the `Python GTK+ 3 Tutorial`_.
.. [#f1] ``HdyTitleBar`` is a widget from the `libhandy library`_ which
provides widgets for adaptive user interfaces.
.. _`Glade`: https://glade.gnome.org/
.. _`libhandy library`: https://source.puri.sm/Librem5/libhandy
.. _`Actions section`: https://python-gtk-3-tutorial.readthedocs.io/en/latest/application.html#actions
.. _`Python GTK+ 3 Tutorial`: https://python-gtk-3-tutorial.readthedocs.io/en/latest/index.html
......@@ -22,8 +22,6 @@ Handy.init()
class Application(Gtk.Application):
_images = ['dug1.svg', 'dug2.svg', 'ground.svg', 'treasure.svg']
def __init__(self):
super().__init__(application_id='sm.puri.treasure')
GLib.set_application_name(_('Treasure'))
......@@ -31,13 +29,6 @@ class Application(Gtk.Application):
def do_startup(self):
Gtk.Application.do_startup(self)
# Create a builder with the correct translation domain and load user
# interface definitions from the resources.
builder = Gtk.Builder()
builder.set_translation_domain('treasure')
builder.add_from_resource('/sm/puri/treasure/ui/menus.ui')
builder.add_from_resource('/sm/puri/treasure/ui/window.ui')
# Load a style sheet from the resources.
self.css = Gtk.CssProvider()
self.css.load_from_resource('/sm/puri/treasure/ui/style.css')
......@@ -46,10 +37,17 @@ class Application(Gtk.Application):
# as pixbufs.
self.pixbufs = {}
for image in self._images:
for image in ['dug1.svg', 'dug2.svg', 'ground.svg', 'treasure.svg']:
self.pixbufs[image] = GdkPixbuf.Pixbuf.new_from_file(
os.path.join(config.pkgdatadir, 'images', image))
# Create a builder with the correct translation domain and load user
# interface definitions from the resources.
builder = Gtk.Builder()
builder.set_translation_domain('treasure')
builder.add_from_resource('/sm/puri/treasure/ui/menus.ui')
builder.add_from_resource('/sm/puri/treasure/ui/window.ui')
# Get the window from the builder.
self.window = builder.get_object('window')
self.window.set_property('application', self)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment