Source code for numericalmodel.gui

#!/usr/bin/env python3
# system modules
import os, sys
import logging
import signal
import textwrap
from pkg_resources import resource_filename

# internal modules
from .. import utils

# external modules


instructions = textwrap.dedent(""" 
To install, use your system's package manager and install ``python3-gi``.

On Debian/Ubuntu::

    sudo apt-get install python3-gi

.. note:: If you don't have system privileges, there is also the (experimental)
    :mod:`pgi` module on `PyPi <https://pypi.python.org/pypi/pgi/>`_ that you
    can install via::

        pip3 install --user pgi

    Theoretically, the :any:`NumericalModelGui` might work with this package as
    well.
""")

__doc__ = \
""" 
Graphical user interface for a NumericalModel. This module is only useful
if the system package ``python3-gi`` is installed to provide the :mod:`gi`
module.

""" + instructions

PGI = False
GTK_INSTALLED = False 
try: # try real gi module
    import gi
    gi.require_version('Gtk','3.0')
    from gi.repository import Gtk
    from gi.repository import GLib
    GTK_INSTALLED = True # importing real gi worked
except: # importing real gi didn't work
    try: # try pgi package
        import pgi
        pgi.install_as_gi()
        import gi
        gi.require_version('Gtk','3.0')
        from gi.repository import Gtk
        from gi.repository import GLib
        PGI = True
        GTK_INSTALLED = True # importing pgi worked
    except:
        pass


# only if gtk is installed
[docs]class NumericalModelGui(utils.LoggerObject): """ class for a GTK gui to run a :any:`NumericalModel` interactively Args: numericalmodel (NumericalModel): the NumericalModel to run """ def __init__(self, numericalmodel): # check for GTK if not GTK_INSTALLED: print("Gtk3.0 bindings seem not installed.\n"+instructions) sys.exit() self.setup_signals( signals = [signal.SIGINT, signal.SIGTERM, signal.SIGHUP], handler = self.quit ) ################## ### Properties ### ################## @property def builder(self): """ The gui's ``GtkBuilder``. This is a read-only property. :getter: Return the ``GtkBuilder``, load the :any:`gladefile` if necessary. :type: ``GtkBuilder`` """ try: self._builder except AttributeError: self._builder = Gtk.Builder() # new builder # load the gladefile self._builder.add_from_file( self.gladefile ) return self._builder @property def gladefile(self): """ The gui's Glade file. This is a read-only property. :type: :any:`str` """ return resource_filename(__name__, "gui.glade") ############### ### Methods ### ###############
[docs] def setup_signals(self, signals, handler): """ This is a workaround to signal.signal(signal, handler) which does not work with a ``GLib.MainLoop`` for some reason. Thanks to: http://stackoverflow.com/a/26457317/5433146 Args: signals (list): the signals (see :any:`signal` module) to connect to handler (callable): function to be executed on these signals """ def install_glib_handler(sig): # add a unix signal handler GLib.unix_signal_add( GLib.PRIORITY_HIGH, sig, # for the given signal handler, # on this signal, run this function sig # with this argument ) for sig in signals: # loop over all signals GLib.idle_add( # 'execute' install_glib_handler, sig, # add a handler for this signal priority = GLib.PRIORITY_HIGH )
[docs] def setup_gui(self): """ Set up the GTK gui elements """ # connect signals self.handlers = { "CloseApplication": self.quit, } self.builder.connect_signals(self.handlers) # show everything self["main_applicationwindow"].show_all()
[docs] def run(self): """ Run the gui """ # set up the gui self.setup_gui() # run the gui self.logger.debug("starting mainloop") Gtk.main() self.logger.debug("mainloop is over")
[docs] def quit(self, *args): """ Stop the gui """ self.logger.debug("received quitting signal") self.logger.debug("stopping mainloop...") Gtk.main_quit() self.logger.debug("mainloop stopped")
[docs] def __getitem__(self, key): """ When indexed, return the corresponding Glade gui element Args: key (str): the Glade gui element name """ return self.builder.get_object( key )