def about(self, *args):
     """
     Handler for the signal from the About menu item.
     """
     try:
         self.about_dialog
     except AttributeError:
         self.about_dialog = AboutDialog(self.window)
     self.about_dialog.show()
     self.about_dialog.present()
class GFontBrowser(Gtk.Application):
    """
    A class to represent the application.  It comprises a collection of callbacks
    for the various events. On activation the application window is created  and
    all events and signals are connected to callbacks .

    The initializer uses a Gtk.Builder to read in the Glade specification, create
    the widget hierarchy, and then connect all the signals defined in the Glade
    file to the handlers (aka callbacks or slots) which are in this class.

    The list of typefaces to be dealt with is then constructed and displayed.
    """

    def __init__(self, args, **kwargs):
        super().__init__(application_id='uk.org.winder.gfontbrowser')
        self.args = args
        self.kwargs = kwargs

    def do_activate(self):
        """
        Initialize the  system.
        """
        builder = Gtk.Builder()
        builder.add_from_file(os.path.join(os.path.dirname(__file__), 'gfontbrowser.glade'))
        builder.connect_signals(self)
        for name in (
                'window',
                'family_list',
                'presentation_list',
                'sample_text',
                'font_size',
        ):
            setattr(self, name, builder.get_object(name))
        self.window.set_application(_application)  # See main below for the definition of  _application.
        font_catalogue.initialize(self.window.get_pango_context(), self.args)
        family_list_store = Gtk.ListStore(str)
        family_list_width = 0
        for family_name in font_catalogue.family_index:
            if len(family_name) > family_list_width:
                family_list_width = len(family_name)
            family_list_store.append((family_name,))
        self.family_list_tree_view_column = Gtk.TreeViewColumn('Font Family', Gtk.CellRendererText(), text=0)
        self.family_list.append_column(self.family_list_tree_view_column)
        self.family_list.set_model(family_list_store)
        presentation.initialize(self.presentation_list)
        self.window.show_all()

    def do_startup(self):
        """
        Start the system up.
        """
        Gtk.Application.do_startup(self)
        menu = Gio.Menu()
        about_action = Gio.SimpleAction.new('about', None)
        about_action.connect('activate', self.about)
        self.add_action(about_action)
        menu.append('About', 'app.about')
        quit_action = Gio.SimpleAction.new('quit', None)
        quit_action.connect('activate', self.quit)
        self.add_action(quit_action)
        menu.append('Quit', 'app.quit')
        self.set_app_menu(menu)

    def quit(self, widget, *args):
        """
        Handler for signals from the Quit menu item and the x on the window frame.
        """
        Gtk.Application.quit(self)

    def about(self, *args):
        """
        Handler for the signal from the About menu item.
        """
        try:
            self.about_dialog
        except AttributeError:
            self.about_dialog = AboutDialog(self.window)
        self.about_dialog.show()
        self.about_dialog.present()

    def family_list_single_clicked(self, tree_view):
        """
        Handler for the signal resulting from a single click on the family list.
        """
        assert tree_view is self.family_list
        cursor_path, focus_column = tree_view.get_cursor()
        # It appears that this handler gets called during initialization as well as for subsequent
        # click events. During initialization there is no cursor set, so we must expect None
        # to be returned.
        if cursor_path is None:
            assert focus_column is None
        else:
            assert focus_column == self.family_list_tree_view_column
            index = int(str(cursor_path))
            assert index < len(font_catalogue.family_index), 'index has value {}, len(family_index) is {}'.format(index, len(font_catalogue.family_index))
            assert font_catalogue.catalogue[font_catalogue.family_index[index]] is not None
            self.presentation_list.set_model(presentation.ListStore(self, font_catalogue.catalogue[font_catalogue.family_index[index]]))

    def family_list_double_clicked(self, tree_view, it, tvc):
        """
        Handler for the signal generated by a double click on the family list.
        """
        assert tree_view == self.family_list
        index_tuple, tree_view_column = tree_view.get_cursor()
        assert tree_view_column == self.family_list_tree_view_column
        assert tvc == tree_view_column
        i = index_tuple[0]
        assert i == it[0]
        presentation.Dialog(self, font_catalogue.catalogue[font_catalogue.family_index[i]])

    def refresh_sample_text(self, user_data):
        """
        Handler for the signal generated by an update to the sample text.

        This signal must be propagated to all the views on the text.
        This is an observer pattern situation.
        """
        presentation.refresh_sample_text(self.sample_text.get_text())

    def refresh_font_size(self, user_data):
        """
        Handler for the signal generated by an update to the font size.

        This signal must be propagated to all the views on the text.
        This is an observer pattern situation.
        """
        presentation.refresh_font_size(self.font_size.get_value_as_int())