def showDetailedError(self, message, details, buttons=None): from pyanaconda.ui.gui.spokes.lib.detailederror import DetailedErrorDialog buttons = buttons or [C_("GUI|Detailed Error Dialog", "_Quit")] dlg = DetailedErrorDialog(None, buttons=buttons, label=message) with self.mainWindow.enlightbox(dlg.window): dlg.refresh(details) rc = dlg.run() dlg.window.destroy() return rc
def _storageResetHandler(self, exn): message = ( _("There is a problem with your existing storage " "configuration: %(errortxt)s\n\n" "You must resolve this matter before the installation can " "proceed. There is a shell available for use which you " "can access by pressing ctrl-alt-f1 and then ctrl-b 2." "\n\nOnce you have resolved the issue you can retry the " "storage scan. If you do not fix it you will have to exit " "the installer.") % { "errortxt": exn }) details = _(exn.suggestion) buttons = (C_("GUI|Storage Detailed Error Dialog", "_Exit Installer"), C_("GUI|Storage Detailed Error Dialog", "_Retry")) if self.ui.showDetailedError(message, details, buttons=buttons): return ERROR_RETRY else: return ERROR_RAISE
def prompt(self, args=None): """ Customize default prompt. """ prompt = NormalTUISpoke.prompt(self, args) prompt.set_message( _("Please select the timezone. Use numbers or type names directly") ) # TRANSLATORS: 'b' to go back prompt.add_option(C_('TUI|Spoke Navigation|Time Settings', 'b'), _("back to region list")) return prompt
def prompt(self, args=None): """Return the text to be shown as prompt or handle the prompt and return None. :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 """ return _(u" Please make your choice from above ['%(quit)s' to quit | '%(continue)s' to continue |\n '%(refresh)s' to refresh]: ") % { # TRANSLATORS: 'q' to quit 'quit': C_('TUI|Spoke Navigation', 'q'), # TRANSLATORS:'c' to continue 'continue': C_('TUI|Spoke Navigation', 'c'), # TRANSLATORS:'r' to refresh 'refresh': C_('TUI|Spoke Navigation', 'r') }
def prompt(self, args=None): incompleteSpokes = [ spoke for spoke in self._keys.values() if spoke.mandatory and not spoke.completed ] # do a bit of final sanity checking, make sure pkg selection # size < available fs space if flags.automatedInstall: if self._checker and not self._checker.check(): print(self._checker.error_message) if not incompleteSpokes: self.close() return None if flags.ksprompt: for spoke in incompleteSpokes: log.info("kickstart installation stopped for info: %s", spoke.title) else: errtxt = _("The following mandatory spokes are not completed:") + \ "\n" + "\n".join(spoke.title for spoke in incompleteSpokes) log.error("CmdlineError: %s", errtxt) raise CmdlineError(errtxt) # if we ever need to halt the flow of a ks install to prompt users for # input, flip off the automatedInstall flag -- this way installation # does not automatically proceed once all spokes are complete, and a # user must confirm they want to begin installation flags.automatedInstall = False # override the default prompt since we want to offer the 'b' to begin # installation option here return _( " Please make your choice from above ['%(quit)s' to quit | '%(begin)s' to begin installation |\n '%(refresh)s' to refresh]: " ) % { # TRANSLATORS: 'q' to quit 'quit': C_('TUI|Spoke Navigation', 'q'), # TRANSLATORS: 'b' to begin installation 'begin': C_('TUI|Spoke Navigation', 'b'), # TRANSLATORS: 'r' to refresh 'refresh': C_('TUI|Spoke Navigation', 'r') }
def on_delete_all_clicked(self, button, *args): if button.get_label() == C_("GUI|Reclaim Dialog", "Delete _all"): action = DELETE button.set_label(C_("GUI|Reclaim Dialog", "Preserve _all")) else: action = PRESERVE button.set_label(C_("GUI|Reclaim Dialog", "Delete _all")) itr = self._diskStore.get_iter_first() while itr: obj = PartStoreRow(*self._diskStore[itr]) if not obj.editable: itr = self._diskStore.iter_next(itr) continue device = self.storage.devicetree.getDeviceByID(obj.id) if device.isDisk: self._actionChanged(itr, action) itr = self._diskStore.iter_next(itr)
def input(self, args, key): if self._container is not None and self._container.process_user_input( key): return InputState.PROCESSED # TRANSLATORS: 'c' to continue elif key.lower() == C_('TUI|Spoke Navigation', 'c'): self.apply() self.close() return InputState.PROCESSED else: return super(SelectISOSpoke, self).input(args, key)
def input(self, args, key): """ Handle user input. """ if self._container.process_user_input(key): return InputState.PROCESSED else: # TRANSLATORS: 'b' to go back if key.lower() == C_("TUI|Spoke Navigation|Language Support", "b"): ScreenHandler.replace_screen(self) return InputState.PROCESSED else: return super(LangSpoke, self).input(args, key)
def on_info_bar_clicked(self, *args): if self.errors: label = _( "The following errors were encountered when checking your storage " "configuration. You can modify your storage layout or quit the " "installer.") dialog = DetailedErrorDialog(self.data, buttons=[ C_("GUI|Storage|Error Dialog", "_Quit"), C_("GUI|Storage|Error Dialog", "_Modify Storage Layout") ], label=label) with self.main_window.enlightbox(dialog.window): errors = "\n".join(self.errors) dialog.refresh(errors) rc = dialog.run() dialog.window.destroy() if rc == 0: # Quit. sys.exit(0) iutil.ipmi_report(constants.IPMI_ABORTED) elif self.warnings: label = _( "The following warnings were encountered when checking your storage " "configuration. These are not fatal, but you may wish to make " "changes to your storage layout.") dialog = DetailedErrorDialog(self.data, buttons=[_("_OK")], label=label) with self.main_window.enlightbox(dialog.window): warnings = "\n".join(self.warnings) dialog.refresh(warnings) rc = dialog.run() dialog.window.destroy()
def input(self, args, key): """Grab the disk choice and update things""" self.errors = [] if self._container.process_user_input(key): self.redraw() return InputState.PROCESSED else: # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): if self.selected_disks: # Is DASD formatting supported? if DasdFormatting.is_supported(): # Wait for storage. threadMgr.wait(THREAD_STORAGE) # Get selected disks. disks = getDisksByNames(self.disks, self.selected_disks) # Check if some of the disks should be formatted. dasd_formatting = DasdFormatting() dasd_formatting.search_disks(disks) if dasd_formatting.should_run(): # We want to apply current selection before running dasdfmt to # prevent this information from being lost afterward applyDiskSelection(self.storage, self.data, self.selected_disks) # Run the dialog. self.run_dasdfmt_dialog(dasd_formatting) self.redraw() return InputState.PROCESSED # make sure no containers were split up by the user's disk # selection self.errors.extend(checkDiskSelection(self.storage, self.selected_disks)) if self.errors: # The disk selection has to make sense before we can # proceed. self.redraw() return InputState.PROCESSED self.apply() new_spoke = PartTypeSpoke(self.data, self.storage, self.payload, self.instclass) ScreenHandler.push_screen_modal(new_spoke) self.apply() self.execute() self.close() return InputState.PROCESSED else: return super(StorageSpoke, self).input(args, key)
def _retranslate_one(self, widgetName, context=None): widget = self.builder.get_object(widgetName) if not widget: return if not widget in self._origStrings: self._origStrings[widget] = widget.get_label() before = self._origStrings[widget] if context is not None: widget.set_label(C_(context, before)) else: widget.set_label(_(before))
def input(self, args, key): """ Grab the choice and update things. """ if not self._container.process_user_input(key): # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): self.apply() self.close() return InputState.PROCESSED else: return super(PartitionSchemeSpoke, self).input(args, key) self.redraw() return InputState.PROCESSED
def input(self, args, key): """Grab the disk choice and update things""" self.errors = [] try: keyid = int(key) - 1 if keyid < 0: return key self.selection = keyid if len(self.disks) > 1 and keyid == len(self.disks): self._select_all_disks() else: self._update_disk_list(self.disks[keyid]) return INPUT_PROCESSED except (ValueError, IndexError): # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): if self.selected_disks: # check selected disks to see if we have any unformatted DASDs # if we're on s390x, since they need to be formatted before we # can use them. if arch.is_s390(): _disks = [ d for d in self.disks if d.name in self.selected_disks ] to_format = [ d for d in _disks if d.type == "dasd" and blockdev.s390.dasd_needs_format(d.busid) ] if to_format: self.run_dasdfmt(to_format) return None # make sure no containers were split up by the user's disk # selection self.errors.extend( checkDiskSelection(self.storage, self.selected_disks)) if self.errors: # The disk selection has to make sense before we can # proceed. return None newspoke = AutoPartSpoke(self.app, self.data, self.storage, self.payload, self.instclass) self.app.switch_screen_modal(newspoke) self.apply() self.execute() self.close() return INPUT_PROCESSED else: return super(StorageSpoke, self).input(args, key)
def on_info_bar_clicked(self, *args): if not self._errorMsgs: return label = _( "The software marked for installation has the following errors. " "This is likely caused by an error with your installation source. " "You can quit the installer, change your software source, or change " "your software selections.") dialog = DetailedErrorDialog( self.data, buttons=[ C_("GUI|Software Selection|Error Dialog", "_Quit"), C_("GUI|Software Selection|Error Dialog", "_Modify Software Source"), C_("GUI|Software Selection|Error Dialog", "Modify _Selections") ], label=label) with self.main_window.enlightbox(dialog.window): dialog.refresh(self._errorMsgs) rc = dialog.run() dialog.window.destroy() if rc == 0: # Quit. iutil.ipmi_abort(scripts=self.data.scripts) sys.exit(0) elif rc == 1: # Send the user to the installation source spoke. self.skipTo = "SourceSpoke" self.window.emit("button-clicked") elif rc == 2: # Close the dialog so the user can change selections. pass else: pass
def initialize(self): Hub.initialize(self) if flags.livecdInstall: continueText = self.builder.get_object("rebootLabel") continueText.set_text( _("%s is now successfully installed on your system and ready " "for you to use! When you are ready, reboot your system to start using it!" )) continueText.set_line_wrap(True) self.window.get_continue_button().set_label( C_("GUI|Progress", "_Quit")) self._progressBar = self.builder.get_object("progressBar") self._progressLabel = self.builder.get_object("progressLabel") self._progressNotebook = self.builder.get_object("progressNotebook") self._spinner = self.builder.get_object("progressSpinner") lbl = self.builder.get_object("configurationLabel") lbl.set_text( _("%s is now successfully installed, but some configuration still needs to be done.\n" "Finish it and then click the Finish configuration button please." ) % productName) lbl = self.builder.get_object("rebootLabel") lbl.set_text( _("%s is now successfully installed and ready for you to use!\n" "Go ahead and reboot to start using it!") % productName) rnotes = self._get_rnotes() # Get the start of the pages we're about to add to the notebook rnotes_start = self._progressNotebook.get_n_pages() if rnotes: # Add a new page in the notebook for each ransom note image. for f in rnotes: img = Gtk.Image.new_from_file(f) img.show() self._progressNotebook.append_page(img, None) # An infinite list of the page numbers containing ransom notes images. self._rnotesPages = itertools.cycle( range(rnotes_start, self._progressNotebook.get_n_pages())) else: # Add a blank page to the notebook and we'll just cycle to that # over and over again. blank = Gtk.Box() blank.show() self._progressNotebook.append_page(blank, None) self._rnotesPages = itertools.cycle([rnotes_start])
def input(self, args, key): # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): self.apply() self.close() return key try: num = int(key) # get the ISO path self._current_iso_path = self._isos[num - 1] self.apply() self.close() return True except (IndexError, ValueError): return key
def input(self, args, key): try: keyid = int(key) - 1 except ValueError: if key.lower().replace("_", " ") in self._lower_zones: index = self._lower_zones.index(key.lower().replace("_", " ")) self._selection = self._zones[index] self.apply() self.close() return INPUT_PROCESSED elif key.lower() in self._lower_regions: index = self._lower_regions.index(key.lower()) if len(self._timezones[self._regions[index]]) == 1: self._selection = "%s/%s" % ( self._regions[index], self._timezones[self._regions[index]][0]) self.apply() self.close() else: self.app.switch_screen(self, self._regions[index]) return INPUT_PROCESSED # TRANSLATORS: 'b' to go back elif key.lower() == C_('TUI|Spoke Navigation|Time Settings', 'b'): self.app.switch_screen(self, None) return INPUT_PROCESSED else: return key if keyid < 0: return key if args: if keyid >= len(self._timezones[args]): return key self._selection = "%s/%s" % (args, self._timezones[args][keyid]) self.apply() self.close() else: if keyid >= len(self._regions): return key region = self._regions[keyid] selected_timezones = self._timezones[region] if len(selected_timezones) == 1: self._selection = "%s/%s" % (region, selected_timezones[0]) self.apply() self.close() else: self.app.switch_screen(self, region) return INPUT_PROCESSED
def input(self, args, key): """Grab the disk choice and update things""" self.errors = [] try: keyid = int(key) - 1 self.selection = keyid if len(self.disks) > 1 and keyid == len(self.disks): self._select_all_disks() else: self._update_disk_list(self.disks[keyid]) return INPUT_PROCESSED except (ValueError, IndexError): # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): if self.selected_disks: # check selected disks to see if we have any unformatted or # LDL DASDs if we're on s390x, since they need to be # formatted before we can use them. if arch.isS390(): unformatted = make_unformatted_dasd_list( self.selected_disks) ldl = [ d for d in self.selected_disks if is_ldl_dasd(d) ] # combine into one nice list dasds = list(set(unformatted + ldl)) if dasds: self.run_dasdfmt(dasds) return None # make sure no containers were split up by the user's disk # selection self.errors.extend( checkDiskSelection(self.storage, self.selected_disks)) if self.errors: # The disk selection has to make sense before we can # proceed. return None newspoke = AutoPartSpoke(self.app, self.data, self.storage, self.payload, self.instclass) self.app.switch_screen_modal(newspoke) self.apply() self.execute() self.close() return INPUT_PROCESSED else: return key
def input(self, args, key): """Grab the disk choice and update things""" self.errors = [] if self._container.process_user_input(key): self.redraw() return InputState.PROCESSED else: # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): if self.selected_disks: # check selected disks to see if we have any unformatted DASDs # if we're on s390x, since they need to be formatted before we # can use them. if arch.is_s390(): _disks = [ d for d in self.disks if d.name in self.selected_disks ] to_format = [ d for d in _disks if d.type == "dasd" and blockdev.s390.dasd_needs_format(d.busid) ] if to_format: self.run_dasdfmt(to_format) self.redraw() return InputState.PROCESSED # make sure no containers were split up by the user's disk # selection self.errors.extend( checkDiskSelection(self.storage, self.selected_disks)) if self.errors: # The disk selection has to make sense before we can # proceed. self.redraw() return InputState.PROCESSED self.apply() new_spoke = PartTypeSpoke(self.data, self.storage, self.payload, self.instclass) ScreenHandler.push_screen_modal(new_spoke) self.apply() self.execute() self.close() return InputState.PROCESSED else: return super(StorageSpoke, self).input(args, key)
def input(self, args, key): """Move along home.""" try: keyid = int(key) - 1 except ValueError: # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): self.apply() self.close() return INPUT_PROCESSED else: return key if 0 <= keyid < len(self._roots): self._selection = keyid return INPUT_PROCESSED
def input(self, args, key): """Grab the choice and update things""" if not self._container.process_user_input(key): # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): new_spoke = PartitionSchemeSpoke(self.data, self.storage, self.payload, self.instclass) ScreenHandler.push_screen_modal(new_spoke) self.apply() self.close() return InputState.PROCESSED else: return super(AutoPartSpoke, self).input(args, key) self.redraw() return InputState.PROCESSED
def input(self, args, key): """ Handle the input; this chooses the desktop environment. """ try: keyid = int(key) - 1 except ValueError: # TRANSLATORS: 'c' to continue if key.lower() == C_("TUI|Spoke Navigation", "c") and \ 0 <= self._selection < len(self.payload.environments): self.apply() self.close() return INPUT_PROCESSED else: return key if 0 <= keyid < len(self.payload.environments): self._selection = keyid return INPUT_PROCESSED
def input(self, args, key): """ Grab the choice and update things. """ try: keyid = int(key) - 1 except ValueError: # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): self.apply() self.close() return INPUT_PROCESSED else: return super(PartitionSchemeSpoke, self).input(args, key) if 0 <= keyid < len(self.partschemes): self._selection = keyid return INPUT_PROCESSED
def input(self, args, key): """ Handle the input; this chooses the desktop environment. """ try: keyid = int(key) - 1 except ValueError: # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): # No environment was selected, close if self._selection is None: self.close() # The environment was selected, switch screen elif args is None: # Get addons for the selected environment environment = self._get_environment(self._selection) environment_id = self._get_environment_id(environment) addons = self._get_available_addons(environment_id) # Switch the screen self.app.switch_screen(self, addons) # The addons were selected, apply and close else: self.apply() self.close() return INPUT_PROCESSED else: return super(SoftwareSpoke, self).input(args, key) # Process the environment selection if args is None: if 0 <= keyid < len(self.payload.environments): self._selection = keyid # Process the addons selection else: if 0 <= keyid < len(args): addon = args[keyid] if addon not in self._addons_selection: self._addons_selection.add(addon) else: self._addons_selection.remove(addon) return INPUT_PROCESSED
def input(self, args, key): """Override input so that we can launch the VNC password spoke""" if self._container.process_user_input(key): self.apply() self.close() return InputState.PROCESSED else: # TRANSLATORS: 'q' to quit if key.lower() == C_('TUI|Spoke Navigation', 'q'): d = YesNoDialog(_(u"Do you really want to quit?")) ScreenHandler.push_screen_modal(d) if d.answer: ipmi_abort(scripts=self.data.scripts) if can_touch_runtime_system("Quit and Reboot"): execWithRedirect("systemctl", ["--no-wall", "reboot"]) else: sys.exit(1) else: return super(AskVNCSpoke, self).input(args, key)
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.""" try: number = int(key) self.app.switch_screen_with_return(self._keys[number]) return None except (ValueError, KeyError): # If we get a continue, check for unfinished spokes. If unfinished # don't continue # TRANSLATORS: 'c' to continue if key == C_('TUI|Spoke Navigation', 'c'): for spoke in self._spokes.values(): if not spoke.completed and spoke.mandatory: print(_("Please complete all spokes before continuing")) return False return key
def input(self, args, key): """ Handle user input. """ try: keyid = int(key) - 1 if args: self._selected = args[keyid] self.apply() self.close() else: self.app.switch_screen(self, self._locales[self._langs_and_locales[self._langs[keyid]]]) return True except (ValueError, IndexError): pass # TRANSLATORS: 'b' to go back if key.lower() == C_('TUI|Spoke Navigation|Language Support', 'b'): self.app.switch_screen(self, None) return True else: return key
def input(self, args, key): """Grab the choice and update things""" try: keyid = int(key) - 1 except ValueError: # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): newspoke = PartitionSchemeSpoke(self.app, self.data, self.storage, self.payload, self.instclass) self.app.switch_screen_modal(newspoke) self.apply() self.close() return INPUT_PROCESSED else: return super(AutoPartSpoke, self).input(args, key) if 0 <= keyid < len(self.parttypelist): self.clearPartType = PARTTYPES[self.parttypelist[keyid]] self.apply() return INPUT_PROCESSED
def _createBox(self): gi.require_version("Gtk", "3.0") gi.require_version("AnacondaWidgets", "3.3") from gi.repository import Gtk, AnacondaWidgets cats_and_spokes = self._collectCategoriesAndSpokes() categories = cats_and_spokes.keys() grid = Gtk.Grid(row_spacing=6, column_spacing=6, column_homogeneous=True, margin_bottom=12) row = 0 for c in sorted(categories, key=lambda c: c.title): obj = c() selectors = [] for spokeClass in sorted(cats_and_spokes[c], key=lambda s: s.title): # Check if this spoke is to be shown in the supported environments if not any( spokeClass.should_run(environ, self.data) for environ in flags.environs): continue # Create the new spoke and populate its UI with whatever data. # From here on, this Spoke will always exist. spoke = spokeClass(self.data, self.storage, self.payload, self.instclass) spoke.window.set_beta(self.window.get_beta()) spoke.window.set_property("distribution", distributionText().upper()) # If a spoke is not showable, it is unreachable in the UI. We # might as well get rid of it. # # NOTE: Any kind of spoke can be unshowable. if not spoke.showable: del (spoke) continue # This allows being able to jump between two spokes without # having to directly involve the hub. self._spokes[spokeClass.__name__] = spoke # If a spoke is indirect, it is reachable but not directly from # a hub. This is for things like the custom partitioning spoke, # which you can only get to after going through the initial # storage configuration spoke. # # NOTE: This only makes sense for NormalSpokes. Other kinds # of spokes do not involve a hub. if spoke.indirect: spoke.initialize() continue spoke.selector = AnacondaWidgets.SpokeSelector( C_("GUI|Spoke", spoke.title), spoke.icon) # Set all selectors to insensitive before initialize runs. The call to # _updateCompleteness later will take care of setting it straight. spoke.selector.set_sensitive(False) spoke.initialize() if not spoke.ready: self._notReadySpokes.append(spoke) # Set some default values on the associated selector that # affect its display on the hub. self._updateCompleteness(spoke, update_continue=False) spoke.selector.connect("button-press-event", self._on_spoke_clicked, spoke) spoke.selector.connect("key-release-event", self._on_spoke_clicked, spoke) # If this is a kickstart install, attempt to execute any provided ksdata now. if flags.automatedInstall and spoke.ready and spoke.changed and \ spoke.visitedSinceApplied: spoke.execute() spoke.visitedSinceApplied = False selectors.append(spoke.selector) if not selectors: continue label = Gtk.Label(label="<span font-desc=\"Sans 14\">%s</span>" % escape_markup(_(obj.title)), use_markup=True, halign=Gtk.Align.START, margin_top=12, margin_bottom=12) grid.attach(label, 0, row, 2, 1) row += 1 col = 0 for selector in selectors: selector.set_margin_start(12) grid.attach(selector, col, row, 1, 1) col = int(not col) if col == 0: row += 1 # If this category contains an odd number of selectors, the above # row += 1 will not have run for the last row, which puts the next # category's title in the wrong place. if len(selectors) % 2: row += 1 # 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__) spokeArea = self.window.get_spoke_area() viewport = Gtk.Viewport() viewport.add(grid) spokeArea.add(viewport) self._updateContinue()
def prompt(self, args=None): prompt = super(MountPointAssignSpoke, self).prompt(args) # TRANSLATORS: 's' to rescan devices prompt.add_option(C_('TUI|Spoke Navigation|Partitioning', 's'), _("rescan devices")) return prompt