[PATCH 4/5] Add a window to manage Anaconda screen transitions.

Vratislav Podzimek vpodzime at redhat.com
Wed Jun 18 13:47:19 UTC 2014


On Wed, 2014-06-18 at 09:07 -0400, David Shea wrote:
> On 06/18/2014 06:24 AM, Vratislav Podzimek wrote:
> > On Mon, 2014-06-16 at 15:09 -0400, David Shea wrote:
> >> Instead of each hub and spoke being a separate Gtk window, create a
> >> single window to contain every non-dialog screen. This changes the
> >> parent type of AnacondaBaseWindow to GtkBin instead of GtkWindow.
> >>
> >> This change is mostly helpful in live environments where we have less
> >> control over the window manager. Each spoke and hub appeared as a
> >> separate window the in the window manager and it made things look kind
> >> of weird, as well as opening up the possibility for some troublesome
> >> window interactions.
> >> ---
> >>   pyanaconda/ui/gui/__init__.py        | 100 ++++++++++++++++++++++++++++++++---
> >>   pyanaconda/ui/gui/hubs/__init__.py   |  56 +++++++-------------
> >>   pyanaconda/ui/gui/spokes/__init__.py |   7 ++-
> >>   pyanaconda/ui/gui/utils.py           |   2 +-
> >>   widgets/src/BaseWindow.c             |  14 +++--
> >>   widgets/src/BaseWindow.h             |   6 +--
> >>   widgets/src/HubWindow.c              |   9 ++--
> >>   widgets/src/SpokeWindow.c            |  29 ++--------
> >>   widgets/src/StandaloneWindow.c       |  23 +-------
> >>   9 files changed, 137 insertions(+), 109 deletions(-)
> >>
> >> diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py
> >> index 15c55aa..38576a1 100644
> >> --- a/pyanaconda/ui/gui/__init__.py
> >> +++ b/pyanaconda/ui/gui/__init__.py
> >> @@ -123,7 +123,6 @@ class GUIObject(common.UIObject):
> >>           else:
> >>               self.builder.add_from_file(self._findUIFile())
> >>   
> >> -        ANACONDA_WINDOW_GROUP.add_window(self.window)
> >>           self.builder.connect_signals(self)
> >>   
> >>           # Keybinder from GI needs to be initialized before use
> >> @@ -169,7 +168,7 @@ class GUIObject(common.UIObject):
> >>   
> >>       @property
> >>       def window(self):
> >> -        """Return the top-level object out of the GtkBuilder representation
> >> +        """Return the object out of the GtkBuilder representation
> >>              previously loaded by the load method.
> >>           """
> >>   
> >> @@ -180,6 +179,11 @@ class GUIObject(common.UIObject):
> >>   
> >>           return self._window
> >>   
> >> +    @property
> >> +    def main_window(self):
> >> +        """Return the top-level window containing this GUIObject."""
> >> +        return self.window.get_toplevel()
> >> +
> >>       def clear_info(self):
> >>           """Clear any info bar from the bottom of the screen."""
> >>           self.window.clear_info()
> >> @@ -236,6 +240,89 @@ class ErrorDialog(GUIObject):
> >>           rc = self.window.run()
> >>           return rc
> >>   
> >> +class MainWindow(Gtk.Window):
> >> +    """This is a top-level, full size window containing the Anaconda screens."""
> >> +
> >> +    def __init__(self):
> >> +        Gtk.Window.__init__(self)
> >> +
> >> +        # Create a stack and a list of what's been added to the stack
> >> +        self._stack = Gtk.Stack()
> >> +        self._stack_contents = set()
> >> +
> >> +        # Create an accel group for the F12 accelerators added after window transitions
> >> +        self._accel_group = Gtk.AccelGroup()
> >> +        self.add_accel_group(self._accel_group)
> >> +
> >> +        # Set properties on the window
> >> +        self.set_decorated(False)
> >> +        self.maximize()
> >> +        self.add(self._stack)
> >> +        self.show_all()
> >> +
> >> +        # Connect to realize to perform some actions with the GdkScreen
> >> +        self.connect("realize", self._on_realize)
> >> +
> >> +        self._current_action = None
> >> +
> >> +    def _on_realize(self, widget, user_data=None):
> >> +        # Change the default size to the full size of the GdkScreen so that when
> >> +        # we're unmaximized the size of the anaconda window isn't something dumb
> >> +        screen = self.get_screen()
> >> +        self.set_default_size(screen.get_width(), screen.get_height())
> >> +
> >> +    @property
> >> +    def current_action(self):
> >> +        return self._current_action
> >> +
> >> +    def _setVisibleChild(self, child):
> >> +        # Remove the F12 accelerator from the old window
> >> +        old_screen = self._stack.get_visible_child()
> >> +        if old_screen:
> >> +            old_screen.remove_accelerator(self._accel_group, Gdk.KEY_F12, 0)
> >> +
> >> +        # Check if the widget is already on the stack
> >> +        if child not in self._stack_contents:
> >> +            self._stack.add(child.window)
> >> +            self._stack_contents.add(child)
> >> +            child.window.show_all()
> >> +
> >> +        # It would be handy for F12 to continue to work like it did in the old
> >> +        # UI, by skipping you to the next screen or sending you back to the hub
> >> +        if isinstance(child.window, AnacondaWidgets.BaseStandalone):
> >> +            child.window.add_accelerator("continue-clicked", self._accel_group,
> >> +                    Gdk.KEY_F12, 0, 0)
> >> +        elif isinstance(child.window, AnacondaWidgets.SpokeWindow):
> >> +            child.window.add_accelerator("button-clicked", self._accel_group,
> >> +                    Gdk.KEY_F12, 0, 0)
> >> +
> >> +        self._stack.set_visible_child(child.window)
> >> +
> >> +    def setCurrentAction(self, standalone):
> >> +        """Set the current standalone widget.
> >> +
> >> +           This changes the currently displayed screen and, if the standalone
> >> +           is a hub, sets the hub as the screen to which spokes will return.
> >> +
> >> +           :param AnacondaWidgets.BaseStandalone standalone: the new standalone action
> >> +        """
> >> +        self._current_action = standalone
> >> +        self._setVisibleChild(standalone)
> >> +
> >> +    def enterSpoke(self, spoke):
> >> +        """Enter a spoke.
> >> +
> >> +           The spoke will be displayed as the current screen, but the current-action
> >> +           to which the spoke will return will not be changed.
> >> +
> >> +           :param AnacondaWidgets.SpokeWindow spoke: a spoke to enter
> >> +        """
> >> +        self._setVisibleChild(spoke)
> >> +
> >> +    def returnToHub(self):
> >> +        """Exit a spoke and return to a hub."""
> >> +        self._setVisibleChild(self._current_action)
> >> +
> >>   class GraphicalUserInterface(UserInterface):
> >>       """This is the standard GTK+ interface we try to steer everything to using.
> >>          It is suitable for use both directly and via VNC.
> >> @@ -258,6 +345,8 @@ class GraphicalUserInterface(UserInterface):
> >>           self._mehInterface = GraphicalExceptionHandlingIface(
> >>                                       self.lightbox_over_current_action)
> >>   
> >> +        self.mainWindow = MainWindow()
> > This window should be added to the ANACONDA_WINDOW_GROUP or we should
> > get rid of it (may be unnecessary now that we have just a single base
> > window).
> 
> Yes, I'll add it to the group. I kept the group around because it seemed 
> important for lightbox stuff, so the main window should be part of the 
> group at least until we figure out how to get rid of the lightbox widget.
Well, I've added it because of some bugs when python-meh's window
appeared below the spoke's window, lightbox, etc. We could try removing
it and testing if things keep working or start misbehaving again.

-- 
Vratislav Podzimek

Anaconda Rider | RHCE | Red Hat, Inc. | Brno - Czech Republic




More information about the anaconda-patches mailing list