Source Files¶
Three of the files in the src
directory contain Python source code:
app-resources.in
, __init__.py
and main.py
.
The first of these is a template that the build system will use to create the
application’s app-resources
executable.
The other two files are Python modules that will be copied by the build system into a Python package directory when the application is installed, resulting in a directory structure like this:
- app_resources/
- __init__.py
- main.py
The main.py
file contains the Python source code for the application, and
the __init__.py
file is just an empty package file to allow the main
module to be imported from the app_resources
package.
The Program¶
Because the application is very simple, we show the whole main program here to provide an overview before looking at the details:
# -*- coding: utf-8 -*-
# Copyright (C) 2019 Purism SPC
# SPDX-License-Identifier: GPL-3.0+
# Author: David Boddie <david.boddie@puri.sm>
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk
class Application(Gtk.Application):
def __init__(self):
super().__init__(application_id='com.example.app_resources')
GLib.set_application_name('App Resources')
GLib.set_prgname('com.example.app_resources')
def do_activate(self):
window = Gtk.ApplicationWindow(application=self)
window.set_icon_name('com.example.app_resources')
image = Gtk.Image.new_from_resource(
'/com/example/app_resources/images/picture.svg'
)
window.add(image)
window.show_all()
def main(version):
app = Application()
return app.run(sys.argv)
After the opening comments, there are three parts to the program: the module
imports, the application class, and the main
function at the end. We will
examine these parts of this program individually.
Importing Modules¶
The program begins by importing the modules it needs to create a user
interface. These are the sys
module, which is needed to access the
command line arguments passed to the program when it is run, and the gi
module, which provides a Python interface to the GNOME libraries:
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk
When importing the Gtk
module, it is important to specify the version of
the API that will be used.
Application Class¶
The application is represented by the Application
class which is derived
from the standard Gtk.Application
class. This class provides methods to set
up the application and perform tasks when it is run. It is defined in the
normal way, beginning with the __init__
method:
class Application(Gtk.Application):
def __init__(self):
super().__init__(application_id='com.example.app_resources')
GLib.set_application_name('App Resources')
GLib.set_prgname('com.example.app_resources')
This method performs three tasks that are necessary for the application to run correctly:
- It uses the
super
built-function to call the__init__
method of the base class. This associates the application with the application ID given. This ID must have a certain format which is described in the Gio.GApplication documentation. - It calls the
GLib.set_application_name
function to set a user-readable application name that will be localized if translations are available. - It calls the
GLib.set_prgname
function to set the program name, using the application ID for this value. This ensures that the application icon will be used to represent the application in the phone environment.
When the application is run, the do_activate
method of the Application
class is called. This is something that we need to implement if we want the
application to do something. In this case, we create a window and give it an
icon. Then we add an image to the window and show it:
def do_activate(self):
window = Gtk.ApplicationWindow(application=self)
window.set_icon_name('com.example.app_resources')
image = Gtk.Image.new_from_resource(
'/com/example/app_resources/images/picture.svg'
)
window.add(image)
window.show_all()
Going into detail, we create an instance of the Gtk.ApplicationWindow
class, passing the application instance to it so that the application runs
until the window is closed – see the application property documentation for
more information.
An image is displayed in the window using an instance of the Gtk.Image
class which we create by calling the static new_from_resource
method to
obtain the image data from the application’s resources. The image data is
referred to using a resource path which specifies where in the resources the
data is found. This is like referring to a file in a filing system.
We described how this is defined in the previous part
of this tutorial.
Because the window is a container, the label is added to it using the add
method, and the window is shown using the show_all
method so that both the
window and its contents are displayed.
Creating and Running an Application Instance¶
The last part of the program contains a main
function that is called by
the application’s executable script which we describe in the next section:
def main(version):
app = Application()
return app.run(sys.argv)
Here, we create the Application
instance and call its run
method with
any arguments that were passed to the application from its environment. When it
has finished running, its exit code is returned via the normal sys.exit
call.
The Template Executable¶
The app-resources.in
file is a template for the app-resources
file that
is run when the application is launched. We show the file here to provide an
overview, but break it into two parts:
#!@PYTHON@
# -*- coding: utf-8 -*-
# Copyright (C) 2019 Purism SPC
# SPDX-License-Identifier: GPL-3.0+
# Author: David Boddie <david.boddie@puri.sm>
import os
import signal
import sys
VERSION = '@VERSION@'
pkgdatadir = '@pkgdatadir@'
sys.path.insert(1, pkgdatadir)
signal.signal(signal.SIGINT, signal.SIG_DFL)
We create the app-resources
file from this template because the
installation directory and application version are provided by the build
system. These constants are inserted into the template to replace the
@VERSION@
and @pkgdatadir@
placeholders. The package directory is
appended to the list of directories that Python uses to find modules.
The second part of the file contains code to load the resources from the
app_resources.gresource
resource bundle file, using a function from the
Gio
module. It then registers the resources so that they can be used
throughout the application:
if __name__ == '__main__':
import gi
from gi.repository import Gio
res = Gio.Resource.load(os.path.join(pkgdatadir, 'app_resources.gresource'))
# Register the resource globally within the application.
res._register()
from app_resources import main
sys.exit(main.main(VERSION))
Finally, the main module for the application is imported and the main
function is run. When this function returns, the application will exit.
Summary¶
This part of the tutorial showed the simple Python program that forms the core of the application and the template for the executable script that is responsible for loading the application’s resources and calling the main program.
However, if we want to install it, we need to build it in a particular way, and we need to provide files that will allow the user to launch it from a GUI. The next part of this tutorial describes how we provide the data files to do that.