158 lines
6.1 KiB
Python
158 lines
6.1 KiB
Python
# The base classes for Anaconda TUI Hubs
|
|
#
|
|
# Copyright (C) (2012) 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.
|
|
#
|
|
from pyanaconda import lifecycle
|
|
from pyanaconda.ui.tui.tuiobject import TUIObject
|
|
from pyanaconda.ui import common
|
|
|
|
from simpleline.render.containers import ListRowContainer
|
|
from simpleline.render.prompt import Prompt
|
|
from simpleline.render.screen import InputState
|
|
from simpleline.render.screen_handler import ScreenHandler
|
|
|
|
from pyanaconda.core.i18n import _, N_
|
|
from pyanaconda.anaconda_loggers import get_module_logger
|
|
log = get_module_logger(__name__)
|
|
|
|
|
|
class TUIHub(TUIObject, common.Hub):
|
|
"""Base Hub class implementing the pyanaconda.ui.common.Hub interface.
|
|
It uses text based categories to look for relevant Spokes and manages
|
|
all the spokes it finds to have the proper category.
|
|
|
|
:param categories: list all the spoke categories to be displayed in this Hub
|
|
:type categories: list of strings
|
|
|
|
|
|
|
|
.. inheritance-diagram:: TUIHub
|
|
:parts: 3
|
|
"""
|
|
|
|
categories = []
|
|
|
|
def __init__(self, data, storage, payload):
|
|
TUIObject.__init__(self, data)
|
|
common.Hub.__init__(self, storage, payload)
|
|
self.title = N_("Default HUB title")
|
|
self._container = None
|
|
|
|
self._spokes_map = [] # hold all the spokes in the right ordering
|
|
self._spokes = {} # holds spokes referenced by their class name
|
|
self._spoke_count = 0
|
|
|
|
# we want user input
|
|
self.input_required = True
|
|
|
|
def setup(self, args="anaconda"):
|
|
TUIObject.setup(self, args)
|
|
environment = args
|
|
cats_and_spokes = self._collectCategoriesAndSpokes()
|
|
categories = cats_and_spokes.keys()
|
|
|
|
# display categories by sort order or class name if their
|
|
# sort order is the same
|
|
for c in common.sort_categories(categories):
|
|
|
|
hub_spokes = []
|
|
for spoke_class in cats_and_spokes[c]:
|
|
# Do the checks for the spoke and create the spoke
|
|
if spoke_class.should_run(environment, self.data):
|
|
spoke = spoke_class(self.data, self.storage, self.payload)
|
|
|
|
if spoke.showable:
|
|
spoke.initialize()
|
|
else:
|
|
log.warning("Spoke %s initialization failure!", spoke.__class__.__name__)
|
|
del spoke
|
|
continue
|
|
|
|
if spoke.indirect:
|
|
continue
|
|
|
|
hub_spokes.append(spoke)
|
|
|
|
# sort created spokes and add them to result structures
|
|
for spoke in sorted(hub_spokes, key=lambda s: s.title):
|
|
|
|
self._spoke_count += 1
|
|
self._spokes_map.append(spoke)
|
|
self._spokes[spoke.__class__.__name__] = spoke
|
|
|
|
if self._spoke_count:
|
|
# initialization of all expected spokes has been started, so notify the controller
|
|
hub_controller = lifecycle.get_controller_by_name(self.__class__.__name__)
|
|
if hub_controller:
|
|
hub_controller.all_modules_added()
|
|
else:
|
|
log.error("Initialization controller for hub %s expected but missing.", self.__class__.__name__)
|
|
|
|
# only schedule the hub if it has some spokes
|
|
return self._spoke_count != 0
|
|
|
|
def refresh(self, args=None):
|
|
"""This methods fills the self.window list by all the objects
|
|
we want shown on this screen. Title and Spokes mostly."""
|
|
TUIObject.refresh(self, args)
|
|
|
|
self._container = ListRowContainer(2, columns_width=39, spacing=2)
|
|
|
|
for w in self._spokes_map:
|
|
self._container.add(w, callback=self._item_called, data=w)
|
|
|
|
self.window.add_with_separator(self._container)
|
|
|
|
def _item_called(self, data):
|
|
item = data
|
|
ScreenHandler.push_screen(item)
|
|
|
|
def input(self, args, key):
|
|
"""Handle user input. Numbers are used to show a spoke, the rest is passed
|
|
to the higher level for processing."""
|
|
|
|
if self._container.process_user_input(key):
|
|
return InputState.PROCESSED
|
|
else:
|
|
# If we get a continue, check for unfinished spokes. If unfinished
|
|
# don't continue
|
|
if key == Prompt.CONTINUE:
|
|
for spoke in self._spokes.values():
|
|
if not spoke.completed and spoke.mandatory:
|
|
print(_("Please complete all spokes before continuing"))
|
|
return InputState.DISCARDED
|
|
|
|
return key
|
|
|
|
def prompt(self, args=None):
|
|
"""Show an alternative prompt if the hub contains only one spoke.
|
|
Otherwise it is not readily apparent that the user needs to press
|
|
1 to enter the single visible spoke.
|
|
|
|
:param args: optional argument passed from switch_screen calls
|
|
:type args: anything
|
|
|
|
:return: returns text to be shown next to the prompt for input or None
|
|
to skip further input processing
|
|
:rtype: str|None
|
|
"""
|
|
prompt = super().prompt(args)
|
|
|
|
if self._spoke_count == 1:
|
|
prompt.add_option("1", _("to enter the %(spoke_title)s spoke") % {"spoke_title": list(self._spokes.values())[0].title})
|
|
|
|
return prompt
|