[PATCH 1/2] Add a help button to every Anaconda screen

Martin Kolman mkolman at redhat.com
Thu Sep 18 10:32:46 UTC 2014


On Wed, 2014-09-17 at 12:15 -0400, Anne Mulhern wrote:
> 
> 
> 
> ----- Original Message -----
> > From: "Martin Kolman" <mkolman at redhat.com>
> > To: anaconda-patches at lists.fedorahosted.org
> > Sent: Tuesday, September 16, 2014 11:09:50 AM
> > Subject: [PATCH 1/2] Add a help button to every Anaconda screen
> > 
> > This makes context aware help possible for every Anaconda screen by
> > providing a help button in the upper right corner of the screen.
> > Clicking the button opens the yelp help viewer with either a help page
> > tailored for the given screen, the main page of the installation guide
> > (if no help is available for the screen) or a "no help found" placeholder
> > page.
> > The new helpFile GUIObject attribute is used to specify which help
> > file to show for the given screen. If no help file is specified
> > either the main page of the Installation Guide will be shown (if
> > available) or the placeholder page will be shown.
> > 
> > Signed-off-by: Martin Kolman <mkolman at redhat.com>
> > ---
> >  anaconda.spec.in                                |   1 +
> >  data/help/Makefile.am                           |  20 ++++
> >  data/help/en-US/FedoraPlaceholder.html          |   5 +
> >  data/help/en-US/FedoraPlaceholderWithLinks.html |  13 +++
> >  data/help/en-US/Makefile.am                     |  23 ++++
> >  data/help/en-US/RHEL7Placeholder.html           |   5 +
> >  data/help/en-US/RHEL7PlaceholderWithLinks.html  |  11 ++
> >  pyanaconda/ihelp.py                             | 143
> >  ++++++++++++++++++++++++
> >  pyanaconda/installclass.py                      |   6 +
> >  pyanaconda/installclasses/fedora.py             |   3 +
> >  pyanaconda/installclasses/rhel.py               |   3 +
> >  pyanaconda/ui/gui/__init__.py                   |  12 ++
> >  pyanaconda/ui/gui/spokes/__init__.py            |   9 ++
> >  widgets/configure.ac                            |   2 +-
> >  widgets/glade/AnacondaWidgets.xml               |   9 +-
> >  widgets/src/BaseWindow.c                        |  48 ++++++++
> >  widgets/src/BaseWindow.h                        |   3 +
> >  widgets/src/Makefile.am                         |   2 +-
> >  18 files changed, 314 insertions(+), 4 deletions(-)
> >  create mode 100644 data/help/Makefile.am
> >  create mode 100644 data/help/en-US/FedoraPlaceholder.html
> >  create mode 100644 data/help/en-US/FedoraPlaceholderWithLinks.html
> >  create mode 100644 data/help/en-US/Makefile.am
> >  create mode 100644 data/help/en-US/RHEL7Placeholder.html
> >  create mode 100644 data/help/en-US/RHEL7PlaceholderWithLinks.html
> >  create mode 100644 pyanaconda/ihelp.py
> > 
> > diff --git a/anaconda.spec.in b/anaconda.spec.in
> > index 7f45479..0a47426 100644
> > --- a/anaconda.spec.in
> > +++ b/anaconda.spec.in
> > @@ -176,6 +176,7 @@ Requires: zenity
> >  %endif
> >  Requires: keybinder3
> >  Requires: NetworkManager-wifi
> > +Requires: yelp
> >  
> >  %description gui
> >  This package contains graphical user interface for the Anaconda installer.
> > diff --git a/data/help/Makefile.am b/data/help/Makefile.am
> > new file mode 100644
> > index 0000000..3d869fb
> > --- /dev/null
> > +++ b/data/help/Makefile.am
> > @@ -0,0 +1,20 @@
> > +# data/Makefile.am for anaconda
> > +#
> > +# Copyright (C) 2014  Red Hat, Inc.
> > +#
> > +# This program is free software; you can redistribute it and/or modify
> > +# it under the terms of the GNU Lesser General Public License as published
> > +# by the Free Software Foundation; either version 2.1 of the License, or
> > +# (at your option) any later version.
> > +#
> > +# This program is distributed in the hope that it will be useful,
> > +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > +# GNU Lesser General Public License for more details.
> > +#
> > +# You should have received a copy of the GNU Lesser General Public License
> > +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> > +#
> > +# Author: Martin Kolman <mkolman at redhat.com>
> > +
> > +MAINTAINERCLEANFILES = Makefile.in
> > diff --git a/data/help/en-US/FedoraPlaceholder.html
> > b/data/help/en-US/FedoraPlaceholder.html
> > new file mode 100644
> > index 0000000..4d1781a
> > --- /dev/null
> > +++ b/data/help/en-US/FedoraPlaceholder.html
> > @@ -0,0 +1,5 @@
> > +<body>
> > +<h1>The Anaconda built-in help</h1>
> > +<p>...is not yet available for this screen.</p>
> > +<p>You can check the Anaconda wiki page, the Fedora Installation Guide or
> > other online help resources instead.</p>
> > +</body>
> > diff --git a/data/help/en-US/FedoraPlaceholderWithLinks.html
> > b/data/help/en-US/FedoraPlaceholderWithLinks.html
> > new file mode 100644
> > index 0000000..5fe0485
> > --- /dev/null
> > +++ b/data/help/en-US/FedoraPlaceholderWithLinks.html
> > @@ -0,0 +1,13 @@
> > +<body>
> > +<h1>The Anaconda built-in help</h1>
> > +<p>...is not yet available for this screen.</p>
> > +<p>You can check the Anaconda wiki page, the Fedora Installation Guide or
> > other online help resources instead:</p>
> > +<p>
> > +<ul>
> > +    <li><a
> > href="http://docs.fedoraproject.org/en-US/Fedora/20/html/Installation_Guide/">Fedora
> > Installation Guide</a></li>
> > +    <li><a href="https://fedoraproject.org/wiki/Anaconda">Anaconda
> > Wiki</a></li>
> > +    <li><a
> > href="http://fedoraproject.org/wiki/Anaconda_Boot_Options">Anaconda Boot
> > Options</a></li>
> > +    <li><a href="http://fedoraproject.org/wiki/Anaconda/Kickstart">Anaconda
> > Kickstart</a></li>
> > +</ul>
> > +</p>
> > +</body>
> > diff --git a/data/help/en-US/Makefile.am b/data/help/en-US/Makefile.am
> > new file mode 100644
> > index 0000000..0cd10bc
> > --- /dev/null
> > +++ b/data/help/en-US/Makefile.am
> > @@ -0,0 +1,23 @@
> > +# data/Makefile.am for anaconda
> > +#
> > +# Copyright (C) 2014  Red Hat, Inc.
> > +#
> > +# This program is free software; you can redistribute it and/or modify
> > +# it under the terms of the GNU Lesser General Public License as published
> > +# by the Free Software Foundation; either version 2.1 of the License, or
> > +# (at your option) any later version.
> > +#
> > +# This program is distributed in the hope that it will be useful,
> > +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > +# GNU Lesser General Public License for more details.
> > +#
> > +# You should have received a copy of the GNU Lesser General Public License
> > +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> > +#
> > +# Author: Martin Kolman <mkolman at redhat.com>
> > +
> > +enplacholderdir               = $(docdir)/en-US
> > +dist_enplaceholder_DATA       = FedoraPlaceholder.html
> > FedoraPlaceholderWithLinks.html RHEL7Placeholder.html
> > RHEL7PlaceholderWithLinks.html
> > +
> > +MAINTAINERCLEANFILES = Makefile.in
> > diff --git a/data/help/en-US/RHEL7Placeholder.html
> > b/data/help/en-US/RHEL7Placeholder.html
> > new file mode 100644
> > index 0000000..9f3c446
> > --- /dev/null
> > +++ b/data/help/en-US/RHEL7Placeholder.html
> > @@ -0,0 +1,5 @@
> > +<body>
> > +<h1>The Anaconda built-in help</h1>
> > +<p>...is not yet available for this screen.</p>
> > +<p>You can check out the Red Hat Enterprise Linux 7 Installation Guide or
> > other online help resources instead.</p>
> > +</body>
> > diff --git a/data/help/en-US/RHEL7PlaceholderWithLinks.html
> > b/data/help/en-US/RHEL7PlaceholderWithLinks.html
> > new file mode 100644
> > index 0000000..c2da61b
> > --- /dev/null
> > +++ b/data/help/en-US/RHEL7PlaceholderWithLinks.html
> > @@ -0,0 +1,11 @@
> > +<body>
> > +<h1>The Anaconda built-in help</h1>
> > +<p>...is not yet available for this screen.</p>
> > +<p>You can check the Red Hat Enterprise Linux 7 Installation Guide or Red
> > Hat Customer Portal resources instead:</p>
> > +<p>
> > +<ul>
> > +    <li><a
> > href="https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Installation_Guide/index.html">Red
> > Hat Enterprise Linux 7 Installation Guide</a></li>
> > +    <li><a href="https://access.redhat.com">Red Hat Customer Portal</a></li>
> > +</ul>
> > +</p>
> > +</body>
> > diff --git a/pyanaconda/ihelp.py b/pyanaconda/ihelp.py
> > new file mode 100644
> > index 0000000..a8e8378
> > --- /dev/null
> > +++ b/pyanaconda/ihelp.py
> > @@ -0,0 +1,143 @@
> > +#
> > +# Copyright (C) 2014  Red Hat, Inc.
> > +#
> > +# This copyrighted material is made available to anyone wishing to use,
> > +# modify, copy, or redistribute it subject to the terms and conditions of
> > +# the GNU General Public License v.2, or (at your option) any later version.
> > +# This program is distributed in the hope that it will be useful, but
> > WITHOUT
> > +# ANY WARRANTY expressed or implied, including the implied warranties of
> > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
> > +# Public License for more details.  You should have received a copy of the
> > +# GNU General Public License along with this program; if not, write to the
> > +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> > MA
> > +# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
> > +# source code or documentation are not subject to the GNU General Public
> > +# License and may only be used or replicated with the express permission of
> > +# Red Hat, Inc.
> > +#
> > +# Red Hat Author(s): Martin Kolman <mkolman at redhat.com>
> > +#
> > +"""
> > +Anaconda built-in help module
> > +"""
> > +import os
> > +import subprocess
> > +
> > +from pyanaconda.flags import flags
> > +from pyanaconda.localization import find_best_locale_match
> > +from pyanaconda.constants import DEFAULT_LANG
> > +
> > +import logging
> > +log = logging.getLogger("anaconda")
> > +
> > +yelp_process = None
> > +
> > +def _get_best_help_file(help_folder, help_file):
> > +    """Return the path to the best help file for the current language and
> > available
> > +    help content
> > +
> > +    :param str help_folder: a path to folder where we should look for the
> > help files
> > +    :param str help_file: name of the requested help file
> > +    :return: path to the best help file or None is no match is found
> > +    :rtype: str or NoneType
> > +
> > +    """
> > +    help_langs = []
> 
> Better to remove line above and...
> 
> > +    current_lang = os.environ["LANG"]
> > +    # list all available languages for the Anaconda help
> > +    # * content is stored in folders named after the given language code
> > +    #   (en-US, cs-CZ, jp-JP, etc.)
> > +    # * we check if the given folder contains the currently needed help file
> > +    #   and only consider it fit to use if it does have the file
> > +    if not os.path.exists(help_folder):
> > +        log.warning("help folder %s for help file %s does not exist",
> > help_folder, help_file)
> > +        return None
> > +
> > +    for item in os.listdir(help_folder):
> > +        if os.path.isfile(os.path.join(help_folder, item, help_file)):
> > +            help_langs.append(item)
> 
> use list comprehension for block above:
> 
> help_langs = [l for l in os.listdir(help_folder) if os.path.isfile(os.path.join(help_folder, l, help_file)]
> 
> > +    best_lang = find_best_locale_match(current_lang, help_langs)
> > +    if not best_lang and current_lang != DEFAULT_LANG:
> > +        # nothing found for current language, fallback to the default
> > language,
> > +        # if available & different from current language
> > +        log.warning("help file %s not found in lang %s, falling back to
> > default lang (%s)",
> > +                    help_file, current_lang, DEFAULT_LANG)
> > +        best_lang = find_best_locale_match(DEFAULT_LANG, help_langs)
> > +
> > +    # did we get something usable ?
> > +    if best_lang:
> > +        # we already checked that the full path exists when enumerating
> > suitable
> > +        # help content above, so we can just return the part here without
> > +        # checking it again
> > +        return os.path.join(help_folder, best_lang, help_file)
> > +    else:
> > +        log.warning("no help content found for file %s", help_file)
> > +        return None
> > +
> > +def get_help_path(help_file, instclass):
> > +    """Return the full path for the given help file name,
> > +    if the help file path does not exist a fallback path is returned.
> > +    There are actually two possible fallback paths that might be returned:
> > +    * first we try to return path to the main page of the installation guide
> > +      (if it exists)
> > +    * if we can't find the main page of the installation page, path to a
> > +      "no help found" placeholder bundled with Anaconda is returned
> > +
> > +    Regarding help l10n, we try to respect the current locale as defined by
> > the
> > +    "LANG" environmental variable, but fallback to English if localized
> > content
> > +    is not available.
> > +
> > +    :param help_file: help file name
> > +    :type help_file: str or NoneType
> > +    :param instclass: current install class instance
> > +    :return str: full path to the help file requested or to a placeholder
> > +    """
> > +    # help l10n handling
> > +
> > +    if help_file:
> > +        help_path = _get_best_help_file(instclass.help_folder, help_file)
> > +        if help_path is not None:
> > +            return help_path
> > +
> > +    # the screen did not have a helpFile defined or the defined help file
> > +    # does not exist, so next try to check if we can find the main page
> > +    # of the installation guide and use it instead
> > +    help_path = _get_best_help_file(instclass.help_folder,
> > instclass.help_main_page)
> > +    if help_path is not None:
> > +        return help_path
> > +
> > +    # looks like the installation guide is not available, so just return
> > +    # a placeholder page that should be available available
> 
> "available" occurs twice in line above.
> 
> > +    if flags.livecdInstall:
> > +        return _get_best_help_file(instclass.help_folder,
> > instclass.help_placeholder_with_links)
> > +    else:
> > +        return _get_best_help_file(instclass.help_folder,
> > instclass.help_placeholder)
> > +
> > +def start_yelp(help_path):
> > +    """Start a new yelp process and make sure to kill any existing ones
> > +
> > +    :param str help_path: path to the help file yelp should load
> 
> Type here should be str or None, since method handles both.
> 
> > +    """
> > +
> > +    kill_yelp()
> > +    log.debug("starting yelp")
> > +    global yelp_process
> > +    # under some extreme circumstances (placeholders missing)
> > +    # the help path can be None and we need to prevent Popen
> > +    # receiving None as an argument instead of a string
> > +    if help_path is None:
> > +        help_path = ""
> > +    yelp_process = subprocess.Popen(["yelp", help_path])
> 
> Probably above 3 lines are better as:
> 
> yelp_process = subprocess.Popen(["yelp", help_path or ""])
> 
> I don't know anything about yelp, but I noticed that yelp
> with no arguments pops up a window about Gnome on my desktop,
> while 'yelp ""' pops up an empty help window and also a file
> browser window. We don't expect this situation to happen too often
> anyway, so it's probably a distinction that makes no difference.
> But maybe comment should include what is expected from yelp call here.
> 
> You might actually prefer calling yelp with no arguments than with
> "" in None case, yelp is more prone to segfaulting when invoked on empty string.
> 
> > +
> > +def kill_yelp():
> > +    """Try to kill any existing yelp processes"""
> > +
> > +    global yelp_process
> > +    if not yelp_process:
> > +        return False
> > +
> > +    log.debug("killing yelp")
> > +    yelp_process.kill()
> > +    yelp_process = None
> > +    return True
> > +
> > diff --git a/pyanaconda/installclass.py b/pyanaconda/installclass.py
> > index cba3c6a..2058876 100644
> > --- a/pyanaconda/installclass.py
> > +++ b/pyanaconda/installclass.py
> > @@ -58,6 +58,12 @@ class BaseInstallClass(object):
> >      # Blivet uses by default.
> >      defaultFS = None
> >  
> > +    # help
> > +    help_folder = "/usr/share/doc/anaconda"
> > +    help_main_page = "Installation_Guide.xml"
> > +    help_placeholder = None
> > +    help_placeholder_with_links = None
> > +
> >      @property
> >      def l10n_domain(self):
> >          if self._l10n_domain is None:
> > diff --git a/pyanaconda/installclasses/fedora.py
> > b/pyanaconda/installclasses/fedora.py
> > index 84acfb7..d176582 100644
> > --- a/pyanaconda/installclasses/fedora.py
> > +++ b/pyanaconda/installclasses/fedora.py
> > @@ -34,6 +34,9 @@ class FedoraBaseInstallClass(BaseInstallClass):
> >  
> >      efi_dir = "fedora"
> >  
> > +    help_placeholder = "FedoraPlaceholder.html"
> > +    help_placeholder_with_links = "FedoraPlaceholderWithLinks.html"
> > +
> >      def configure(self, anaconda):
> >          BaseInstallClass.configure(self, anaconda)
> >          BaseInstallClass.setDefaultPartitioning(self, anaconda.storage)
> > diff --git a/pyanaconda/installclasses/rhel.py
> > b/pyanaconda/installclasses/rhel.py
> > index 5dc39f2..f490a08 100644
> > --- a/pyanaconda/installclasses/rhel.py
> > +++ b/pyanaconda/installclasses/rhel.py
> > @@ -40,6 +40,9 @@ class RHELBaseInstallClass(BaseInstallClass):
> >  
> >      efi_dir = "redhat"
> >  
> > +    help_placeholder = "RHEL7Placeholder.html"
> > +    help_placeholder_with_links = "RHEL7PlaceholderWithLinks.html"
> > +
> >      def configure(self, anaconda):
> >          BaseInstallClass.configure(self, anaconda)
> >          BaseInstallClass.setDefaultPartitioning(self, anaconda.storage)
> > diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py
> > index e88dfad..a062aa2 100644
> > --- a/pyanaconda/ui/gui/__init__.py
> > +++ b/pyanaconda/ui/gui/__init__.py
> > @@ -31,6 +31,7 @@ from pyanaconda import product, iutil
> >  
> >  from pyanaconda.ui import UserInterface, common
> >  from pyanaconda.ui.gui.utils import gtk_action_wait, busyCursor,
> >  unbusyCursor
> > +from pyanaconda import ihelp
> >  import os.path
> >  
> >  import logging
> > @@ -81,6 +82,10 @@ class GUIObject(common.UIObject):
> >                             that use GUI elements (Hubs & Spokes) from
> >                             Anaconda
> >                             can override the translation domain with their
> >                             own,
> >                             so that their subclasses are properly translated.
> > +       helpFile         -- The location of the yelp-compatible help file for
> > the
> > +                           given GUI object. The default value of ""
> > indicates
> > +                           that the object has not specific help file
> > assigned
> > +                           and the default help file should be used.
> >      """
> >      builderObjects = []
> >      mainWidgetName = None
> > @@ -91,6 +96,7 @@ class GUIObject(common.UIObject):
> >      focusWidgetName = None
> >  
> >      uiFile = ""
> > +    helpFile = ""
> 
> To be consistent w/ specification of ihelp.get_help_path(),
> helpFile should be None here.
> 
> >      translationDomain = "anaconda"
> >  
> >      screenshots_directory = "/tmp/anaconda-screenshots"
> > @@ -536,6 +542,7 @@ class GraphicalUserInterface(UserInterface):
> >  
> >          # Use connect_after so classes can add actions before we change
> >          screens
> >          obj.window.connect_after("continue-clicked",
> >          self._on_continue_clicked)
> > +        obj.window.connect_after("help-button-clicked",
> > self._on_help_clicked, obj)
> >          obj.window.connect_after("quit-clicked", self._on_quit_clicked)
> >  
> >          return obj
> > @@ -697,6 +704,11 @@ class GraphicalUserInterface(UserInterface):
> >          self._currentAction = nextAction
> >          self._actions.pop(0)
> >  
> > +    def _on_help_clicked(self, window, obj):
> > +        # the help button has been clicked, start the yelp viewer with
> > +        # content for the current screen
> > +        ihelp.start_yelp(ihelp.get_help_path(obj.helpFile, self.instclass))
> > +
> >      def _on_quit_clicked(self, win, userData=None):
> >          if not win.get_quit_button():
> >              return
> > diff --git a/pyanaconda/ui/gui/spokes/__init__.py
> > b/pyanaconda/ui/gui/spokes/__init__.py
> > index 183dc6f..1227d44 100644
> > --- a/pyanaconda/ui/gui/spokes/__init__.py
> > +++ b/pyanaconda/ui/gui/spokes/__init__.py
> > @@ -21,6 +21,7 @@
> >  
> >  from pyanaconda.ui import common
> >  from pyanaconda.ui.gui import GUIObject
> > +from pyanaconda import ihelp
> >  
> >  __all__ = ["StandaloneSpoke", "NormalSpoke"]
> >  
> > @@ -44,6 +45,14 @@ class NormalSpoke(GUIObject, common.NormalSpoke):
> >          GUIObject.__init__(self, data)
> >          common.NormalSpoke.__init__(self, storage, payload, instclass)
> >  
> > +        # Add a help handler
> > +        self.window.connect_after("help-button-clicked",
> > self._on_help_clicked)
> > +
> > +    def _on_help_clicked(self, window):
> > +        # the help button has been clicked, start the yelp viewer with
> > +        # content for the current spoke
> > +        ihelp.start_yelp(ihelp.get_help_path(self.helpFile, self.instclass))
> > +
> >      def on_back_clicked(self, window):
> >          # Notify the hub that we're finished.
> >          # The hub will be the current-action of the main window.
> > diff --git a/widgets/configure.ac b/widgets/configure.ac
> > index 1035c6c..6456db9 100644
> > --- a/widgets/configure.ac
> > +++ b/widgets/configure.ac
> > @@ -20,7 +20,7 @@
> >  #
> >  
> >  AC_PREREQ([2.63])
> > -AC_INIT([AnacondaWidgets], [3.0], [clumens at redhat.com])
> > +AC_INIT([AnacondaWidgets], [3.1], [clumens at redhat.com])
> >  AM_INIT_AUTOMAKE([foreign])
> >  AM_SILENT_RULES([yes])
> >  
> > diff --git a/widgets/glade/AnacondaWidgets.xml
> > b/widgets/glade/AnacondaWidgets.xml
> > index 42c4194..044ceb2 100644
> > --- a/widgets/glade/AnacondaWidgets.xml
> > +++ b/widgets/glade/AnacondaWidgets.xml
> > @@ -1,6 +1,6 @@
> >  <glade-catalog name="AnacondaWidgets"
> > -               version="3.0"
> > -               targetable="2.0,1.0"
> > +               version="3.1"
> > +               targetable="3.0,2.0,1.0"
> >                 library="AnacondaWidgets"
> >                 domain="glade-3"
> >                 depends="gtk+">
> > @@ -25,6 +25,11 @@
> >                  <property id="distribution" translatable="True" />
> >                  <property id="window-name" translatable="True" />
> >              </properties>
> > +
> > +            <signals>
> > +              <signal since="3.1" id="help-button-clicked" />
> > +            </signals>
> > +
> >          </glade-widget-class>
> >  
> >          <glade-widget-class title="Standalone Spoke Window"
> > diff --git a/widgets/src/BaseWindow.c b/widgets/src/BaseWindow.c
> > index 5b7f337..94dee1f 100644
> > --- a/widgets/src/BaseWindow.c
> > +++ b/widgets/src/BaseWindow.c
> > @@ -28,6 +28,8 @@
> >  #include "BaseWindow.h"
> >  #include "intl.h"
> >  
> > + #include <atk/atk.h>
> > +
> >  /**
> >   * SECTION: BaseWindow
> >   * @title: AnacondaBaseWindow
> > @@ -95,6 +97,7 @@
> >  
> >  enum {
> >      SIGNAL_INFO_BAR_CLICKED,
> > +    SIGNAL_HELP_BUTTON_CLICKED,
> >      LAST_SIGNAL
> >  };
> >  
> > @@ -109,6 +112,7 @@ enum {
> >  #define DEFAULT_WINDOW_NAME   N_("SPOKE NAME")
> >  #define DEFAULT_BETA          N_("PRE-RELEASE / TESTING")
> >  #define LAYOUT_INDICATOR_LABEL_WIDTH 10
> > +#define HELP_BUTTON_LABEL _("_Help!")
> >  
> >  struct _AnacondaBaseWindowPrivate {
> >      gboolean    is_beta, info_shown;
> > @@ -117,6 +121,7 @@ struct _AnacondaBaseWindowPrivate {
> >      GtkWidget  *nav_box, *nav_area, *action_area;
> >      GtkWidget  *name_label, *distro_label, *beta_label;
> >      GtkWidget  *layout_indicator;
> > +    GtkWidget  *help_button;
> >  
> >      /* Untranslated versions of various things. */
> >      gchar *orig_name, *orig_distro, *orig_beta;
> > @@ -128,6 +133,7 @@ static void
> > anaconda_base_window_buildable_init(GtkBuildableIface *iface);
> >  static void format_beta_label(AnacondaBaseWindow *window, const char
> >  *markup);
> >  
> >  static gboolean anaconda_base_window_info_bar_clicked(GtkWidget *widget,
> >  GdkEvent *event, AnacondaBaseWindow *win);
> > +static void anaconda_base_window_help_button_clicked(GtkButton *button,
> > AnacondaBaseWindow *win);
> >  
> >  G_DEFINE_TYPE_WITH_CODE(AnacondaBaseWindow, anaconda_base_window,
> >  GTK_TYPE_BIN,
> >                          G_IMPLEMENT_INTERFACE(GTK_TYPE_BUILDABLE,
> >                          anaconda_base_window_buildable_init))
> > @@ -173,6 +179,7 @@ static void
> > anaconda_base_window_class_init(AnacondaBaseWindowClass *klass) {
> >                                                          G_PARAM_READWRITE));
> >  
> >      klass->info_bar_clicked = NULL;
> > +    klass->help_button_clicked = NULL;
> >  
> >      /**
> >       * AnacondaBaseWindow::info-bar-clicked:
> > @@ -192,6 +199,24 @@ static void
> > anaconda_base_window_class_init(AnacondaBaseWindowClass *klass) {
> >                                                             g_cclosure_marshal_VOID__VOID,
> >                                                             G_TYPE_NONE, 0);
> >  
> > +    /**
> > +     * AnacondaBaseWindow::help-button-clicked:
> > +     * @window: the window that received the signal
> > +     *
> > +     * Emitted when the help button in the right corner has been activated
> > +     * (pressed and released). This is commonly used to open the help view
> > with
> > +     * help content for the given spoke or hub
> > +     *
> > +     * Since: 4.0
> > +     */
> > +    window_signals[SIGNAL_HELP_BUTTON_CLICKED] =
> > g_signal_new("help-button-clicked",
> > +
> > G_TYPE_FROM_CLASS(object_class),
> > +
> > G_SIGNAL_RUN_FIRST
> > | G_SIGNAL_ACTION,
> > +
> > G_STRUCT_OFFSET(AnacondaBaseWindowClass,
> > help_button_clicked),
> > +                                                              NULL, NULL,
> > +
> > g_cclosure_marshal_VOID__VOID,
> > +                                                              G_TYPE_NONE,
> > 0);
> > +
> >      g_type_class_add_private(object_class,
> >      sizeof(AnacondaBaseWindowPrivate));
> >  }
> >  
> > @@ -210,6 +235,7 @@ GtkWidget *anaconda_base_window_new() {
> >  
> >  static void anaconda_base_window_init(AnacondaBaseWindow *win) {
> >      char *markup;
> > +    AtkObject *atk;
> >  
> >      win->priv = G_TYPE_INSTANCE_GET_PRIVATE(win,
> >                                              ANACONDA_TYPE_BASE_WINDOW,
> > @@ -325,11 +351,28 @@ G_GNUC_END_IGNORE_DEPRECATIONS
> >      gtk_widget_set_margin_top(win->priv->layout_indicator, 6);
> >      gtk_widget_set_margin_bottom(win->priv->layout_indicator, 6);
> >  
> > +    /* Create the help button. */
> > +    win->priv->help_button =
> > gtk_button_new_with_mnemonic(HELP_BUTTON_LABEL);
> > +    gtk_widget_set_halign(win->priv->help_button, GTK_ALIGN_START);
> > +    gtk_widget_set_vexpand(win->priv->help_button, FALSE);
> > +    gtk_widget_set_valign(win->priv->help_button, GTK_ALIGN_END);
> > +    gtk_widget_set_margin_bottom(win->priv->help_button, 6);
> > +
> > +    atk = gtk_widget_get_accessible(win->priv->help_button);
> > +    atk_object_set_name(atk, HELP_BUTTON_LABEL);
> > +
> > +    /* Hook up some signals for that button.  The signal handlers here will
> > +     * just raise our own custom signals for the whole window.
> > +     */
> > +    g_signal_connect(win->priv->help_button, "clicked",
> > +                     G_CALLBACK(anaconda_base_window_help_button_clicked),
> > win);
> > +
> >      /* Add everything to the nav area. */
> >      gtk_grid_attach(GTK_GRID(win->priv->nav_area), win->priv->name_label, 0,
> >      0, 1, 1);
> >      gtk_grid_attach(GTK_GRID(win->priv->nav_area), win->priv->distro_label,
> >      1, 0, 1, 1);
> >      gtk_grid_attach(GTK_GRID(win->priv->nav_area), win->priv->beta_label, 1,
> >      1, 1, 1);
> >      gtk_grid_attach(GTK_GRID(win->priv->nav_area),
> >      win->priv->layout_indicator, 1, 2, 1, 1);
> > +    gtk_grid_attach(GTK_GRID(win->priv->nav_area), win->priv->help_button,
> > 2, 1, 1, 2);
> >  }
> >  
> >  static void anaconda_base_window_get_property(GObject *object, guint
> >  prop_id, GValue *value, GParamSpec *pspec) {
> > @@ -587,6 +630,11 @@ static gboolean
> > anaconda_base_window_info_bar_clicked(GtkWidget *wiget, GdkEvent
> >      return FALSE;
> >  }
> >  
> > +static void anaconda_base_window_help_button_clicked(GtkButton *button,
> > +                                                     AnacondaBaseWindow
> > *win) {
> > +        g_signal_emit(win, window_signals[SIGNAL_HELP_BUTTON_CLICKED], 0);
> > +}
> > +
> >  /**
> >   * anaconda_base_window_clear_info:
> >   * @win: a #AnacondaBaseWindow
> > diff --git a/widgets/src/BaseWindow.h b/widgets/src/BaseWindow.h
> > index eb6191d..19891c1 100644
> > --- a/widgets/src/BaseWindow.h
> > +++ b/widgets/src/BaseWindow.h
> > @@ -56,11 +56,14 @@ struct _AnacondaBaseWindow {
> >   *                pointer to be cast to a #GtkBin pointer.
> >   * @info_bar_clicked : Function pointer called when the
> >   #AnacondaBaseWindow::info-bar-clicked
> >   *                     signal is emitted.
> > + * @help_button_clicked: Function pointer called when the
> > #AnacondaSpokeWindow::help-button-clicked
> > + *                       signal is emitted.
> >   */
> >  struct _AnacondaBaseWindowClass {
> >      GtkBinClass parent_class;
> >  
> >      void (* info_bar_clicked) (AnacondaBaseWindow *window);
> > +    void (* help_button_clicked) (AnacondaBaseWindow *window);
> >  };
> >  
> >  GType       anaconda_base_window_get_type (void);
> > diff --git a/widgets/src/Makefile.am b/widgets/src/Makefile.am
> > index dfed620..42615c2 100644
> > --- a/widgets/src/Makefile.am
> > +++ b/widgets/src/Makefile.am
> > @@ -65,7 +65,7 @@ libAnacondaWidgets_la_CFLAGS = $(GTK_CFLAGS)
> > $(GLADEUI_CFLAGS) $(LIBXKLAVIER_CFL
> >  			       -DWIDGETS_DATADIR=$(WIDGETSDATA)\
> >  			       -DTZMAP_DATADIR=$(TZMAPDATA)
> >  libAnacondaWidgets_la_LIBADD = $(GTK_LIBS) $(GLADEUI_LIBS)
> >  $(LIBXKLAVIER_LIBS)
> > -libAnacondaWidgets_la_LDFLAGS = $(LTLIBINTL) -version-info 2:0:0
> > +libAnacondaWidgets_la_LDFLAGS = $(LTLIBINTL) -version-info 3:0:1
> >  libAnacondaWidgets_la_SOURCES = $(SOURCES) $(HDRS) \
> >  	  glade-adaptor.c
> >  
> > --
> > 1.9.3
> > 
> > _______________________________________________
> > anaconda-patches mailing list
> > anaconda-patches at lists.fedorahosted.org
> > https://lists.fedorahosted.org/mailman/listinfo/anaconda-patches
> > 
> 
> A few inline comments. Otherwise, looks good.
Thanks, fixing locally!
> 
> - mulhern
> _______________________________________________
> anaconda-patches mailing list
> anaconda-patches at lists.fedorahosted.org
> https://lists.fedorahosted.org/mailman/listinfo/anaconda-patches




More information about the anaconda-patches mailing list