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 # TRANSLATORS: 'b' to begin installation if key == C_('TUI|Spoke Navigation', 'b'): for spoke in self._spokes.values(): if not spoke.completed and spoke.mandatory: print( _("Please complete all spokes before continuing")) return InputState.DISCARDED # do a bit of final sanity checking, making sure pkg selection # size < available fs space if self._checker and not self._checker.check(): print(self._checker.error_message) return InputState.DISCARDED return InputState.PROCESSED_AND_CLOSE # TRANSLATORS: 'c' to continue elif key == C_('TUI|Spoke Navigation', 'c'): # Kind of a hack, but we want to ignore if anyone presses 'c' # which is the global TUI key to close the current screen return InputState.DISCARDED else: return super().input(args, key)
def _show_error_dialog(self): 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." ) 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") ] dialog = DetailedErrorDialog(self.data, buttons=buttons, 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 the installation. 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")
def on_reset_button_clicked(self, *args): msg = _( "Continuing with this action will reset all your partitioning selections " "to their current on-disk state.") dlg = Gtk.MessageDialog(flags=Gtk.DialogFlags.MODAL, message_type=Gtk.MessageType.WARNING, buttons=Gtk.ButtonsType.NONE, message_format=msg) dlg.set_decorated(False) dlg.add_buttons( C_("GUI|Custom Partitioning|Reset Dialog", "_Reset selections"), 0, C_("GUI|Custom Partitioning|Reset Dialog", "_Preserve current selections"), 1) dlg.set_default_response(1) with self.main_window.enlightbox(dlg): rc = dlg.run() dlg.destroy() if rc == 0: self.refresh() self.blivetgui.reload() # XXX: Reset currently preserves actions set in previous runs # of the spoke, so we need to 're-add' these to the ui current_actions = self._storage_playground.devicetree.actions.find( ) if current_actions: self.blivetgui.set_actions(current_actions)
def __init__(self, *args, **kwargs): buttons = kwargs.pop("buttons", []) label = kwargs.pop("label", None) super().__init__(*args, **kwargs) if not buttons: widget = self.window.add_button( C_("GUI|Detailed Error Dialog", "_Cancel"), 0) else: buttonbox = self.builder.get_object("detailedButtonBox") i = 0 for button in buttons: widget = self.window.add_button(button, i) # Quit buttons should always appear left-most, unless it's the # only button. Then it should appear on the right. if button == C_("GUI|Detailed Error Dialog", "_Quit") and len(buttons) > 1: buttonbox.set_child_secondary(widget, True) i += 1 widget.set_can_default(True) widget.grab_default() if label: self.builder.get_object("detailedLabel").set_text(label)
def input(self, args, key): """ Grab the choice and update things. """ if not self._container.process_user_input(key): # TRANSLATORS: 's' to rescan devices if key.lower() == C_('TUI|Spoke Navigation|Partitioning', 's'): text = _("Warning: This will revert all changes done so far.\n" "Do you want to proceed?\n") question_window = YesNoDialog(text) ScreenHandler.push_screen_modal(question_window) if question_window.answer: # unset selected disks temporarily so that # storage_initialize() processes all devices disk_select_proxy = STORAGE.get_proxy(DISK_SELECTION) selected_disks = disk_select_proxy.SelectedDisks disk_select_proxy.SetSelectedDisks([]) print(_("Scanning disks. This may take a moment...")) storage_initialize(self.storage, self.data, self.storage.protected_dev_names) disk_select_proxy.SetSelectedDisks(selected_disks) self.data.mount.clear_mount_data() self._gather_mount_data_info() return InputState.PROCESSED_AND_REDRAW # TRANSLATORS: 'c' to continue elif key.lower() == C_('TUI|Spoke Navigation', 'c'): self.apply() return super().input(args, key) return InputState.PROCESSED
def on_info_bar_clicked(self, *args): if not self._error_msgs: 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._error_msgs) rc = dialog.run() dialog.window.destroy() if rc == 0: # Quit. util.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 _toggle_button_text(self, row): if row[IS_BOOT_COL]: self._set_button.set_label( C_("GUI|Selected Disks Dialog", "_Do not install boot loader")) else: self._set_button.set_label( C_("GUI|Selected Disks Dialog", "_Set as Boot Device"))
def initialize(self): super().initialize() # Disable the continue button. self.window.set_may_continue(False) # Set the label of the continue button. if conf.target.is_hardware and conf.system.can_reboot: continue_label = C_("GUI|Progress", "_Reboot System") else: continue_label = C_("GUI|Progress", "_Finish Installation") continue_button = self.window.get_continue_button() continue_button.set_label(continue_label) # Set the reboot label. if conf.target.is_hardware: continue_text = _( "%s is now successfully installed and ready for you to use!\n" "Go ahead and reboot your system to start using it!" ) % productName else: continue_text = _( "%s is now successfully installed and ready for you to use!\n" "Go ahead and quit the application to start using it!" ) % productName label = self.builder.get_object("rebootLabel") label.set_text(continue_text) # Don't show the reboot message. self._progressNotebook.set_current_page(0)
def prompt(self, args=None): incomplete_spokes = [ spoke for spoke in self._spokes.values() if spoke.mandatory and not spoke.completed ] # Kickstart space check failure either stops the automated install or # raises an error when using cmdline mode. # # For non-cmdline, prompt for input but continue to treat it as an # automated install. The spokes (in particular software selection, # which expects an environment for interactive install) will continue # to behave the same, so the user can hit 'b' at the prompt and ignore # the warning. if flags.automatedInstall and not incomplete_spokes: # Check the available space. if flags.ksprompt and self._checker and not self._checker.check(): # Space is not ok. print(self._checker.error_message) log.error(self._checker.error_message) # Unset the checker so everything passes next time. self._checker = None # TRANSLATORS: 'b' to begin installation print( _("Enter '%s' to ignore the warning and attempt to install anyway." ) % # TRANSLATORS: 'b' to begin installation C_("TUI|Spoke Navigation", "b")) else: # Space is ok and spokes are complete, continue. self.close() return None # cmdline mode and incomplete spokes raises and error if not flags.ksprompt and incomplete_spokes: errtxt = _("The following mandatory spokes are not completed:") + \ "\n" + "\n".join(spoke.title for spoke in incomplete_spokes) 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 if incomplete_spokes: flags.automatedInstall = False # override the default prompt since we want to offer the 'b' to begin # installation option here prompt = super().prompt(args) # this screen cannot be closed prompt.remove_option(Prompt.CONTINUE) # TRANSLATORS: 'b' to begin installation prompt.add_option(C_("TUI|Spoke Navigation", "b"), _("to begin installation")) return prompt
def input(self, args, key): """ Grab the choice and update things. """ if not self._container.process_user_input(key): # TRANSLATORS: 's' to rescan devices if key.lower() == C_('TUI|Spoke Navigation|Partitioning', 's'): text = _( "Warning: This will revert all changes done so far.\nDo you want to proceed?\n" ) question_window = YesNoDialog(text) ScreenHandler.push_screen_modal(question_window) if question_window.answer: # unset self.data.ignoredisk.onlyuse temporarily so that # storage_initialize() processes all devices ignoredisk = self.data.ignoredisk.onlyuse self.data.ignoredisk.onlyuse = [] print(_("Scanning disks. This may take a moment...")) storage_initialize(self.storage, self.data, self.storage.protected_dev_names) self.data.ignoredisk.onlyuse = ignoredisk self.data.mount.clear_mount_data() self._gather_mount_data_info() self.redraw() return InputState.PROCESSED # TRANSLATORS: 'c' to continue elif key.lower() == C_('TUI|Spoke Navigation', 'c'): self.apply() return super(MountPointAssignSpoke, self).input(args, key) return InputState.PROCESSED
def _get_wireless_secrets(self, setting_name, connection_hash): key_mgmt = connection_hash['802-11-wireless-security']['key-mgmt'] original_secrets = connection_hash[setting_name] secrets = [] if key_mgmt in ['wpa-none', 'wpa-psk']: secrets.append({ 'label': C_('GUI|Network|Secrets Dialog', '_Password:'******'key': 'psk', 'value': original_secrets.get('psk', ''), 'validate': self._validate_wpapsk, 'password': True }) # static WEP elif key_mgmt == 'none': key_idx = str(original_secrets.get('wep_tx_keyidx', '0')) secrets.append({ 'label': C_('GUI|Network|Secrets Dialog', '_Key:'), 'key': 'wep-key%s' % key_idx, 'value': original_secrets.get('wep-key%s' % key_idx, ''), 'wep_key_type': original_secrets.get('wep-key-type', ''), 'validate': self._validate_staticwep, 'password': True }) # WPA-Enterprise elif key_mgmt == 'wpa-eap': eap = original_secrets['eap'][0] if eap in ('md5', 'leap', 'ttls', 'peap'): secrets.append({ 'label': _('User name: '), 'key': None, 'value': original_secrets.get('identity', ''), 'validate': None, 'password': False }) secrets.append({ 'label': _('Password: '******'key': 'password', 'value': original_secrets.get('password', ''), 'validate': None, 'password': True }) elif eap == 'tls': secrets.append({ 'label': _('Identity: '), 'key': None, 'value': original_secrets.get('identity', ''), 'validate': None, 'password': False }) secrets.append({ 'label': _('Private key password: '******'key': 'private-key-password', 'value': original_secrets.get('private-key-password', ''), 'validate': None, 'password': True }) else: log.info("Unsupported wireless key management: %s", key_mgmt) return secrets
def on_info_bar_clicked(self, *args): if self._disks_errors: label = _("The following errors were encountered when checking your disk " "selection. You can modify your selection or quit the " "installer.") dialog = DetailedErrorDialog(self.data, buttons=[ C_("GUI|Storage|Error Dialog", "_Quit"), C_("GUI|Storage|Error Dialog", "_Modify Disk Selection")], label=label) with self.main_window.enlightbox(dialog.window): errors = "\n".join(self._disks_errors) dialog.refresh(errors) rc = dialog.run() dialog.window.destroy() if rc == 0: # Quit. util.ipmi_abort(scripts=self.data.scripts) sys.exit(0) elif 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. util.ipmi_abort(scripts=self.data.scripts) sys.exit(0) 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=[C_("GUI|Storage|Warning Dialog", "_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 choice and update things. """ if self._container.process_user_input(key): return InputState.PROCESSED # TRANSLATORS: 's' to rescan devices if key.lower() == C_('TUI|Spoke Navigation|Partitioning', 's'): self._rescan_devices() return InputState.PROCESSED_AND_REDRAW # TRANSLATORS: 'c' to continue elif key.lower() == C_('TUI|Spoke Navigation', 'c'): self.apply() return super().input(args, key)
def showYesNoQuestion(self, message): dlg = Gtk.MessageDialog(flags=Gtk.DialogFlags.MODAL, message_type=Gtk.MessageType.QUESTION, buttons=Gtk.ButtonsType.NONE, message_format=message) dlg.set_decorated(False) dlg.add_buttons(C_("GUI|Yes No Dialog", "_No"), 0, C_("GUI|Yes No Dialog", "_Yes"), 1) dlg.set_default_response(1) with self.mainWindow.enlightbox(dlg): rc = dlg.run() dlg.destroy() return bool(rc)
def prompt(self, args=None): prompt = super().prompt(args) # TRANSLATORS: 's' to rescan devices prompt.add_option(C_('TUI|Spoke Navigation|Partitioning', 's'), _("rescan devices")) return prompt
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 input(self, args, key): """ Handle the input; this chooses the desktop environment. """ if self._container is not None and self._container.process_user_input(key): self.redraw() else: # TRANSLATORS: 'c' to continue if key.lower() == C_('TUI|Spoke Navigation', 'c'): # No environment was selected, close if self._selected_environment is None: self.close() # The environment was selected, switch screen elif args is None: # Get addons for the selected environment environment = self._selected_environment environment_id = self._translate_env_name_to_id(environment) addons = self._get_available_addons(environment_id) # Switch the screen ScreenHandler.replace_screen(self, addons) # The addons were selected, apply and close else: self.apply() self.close() else: return super().input(args, key) return InputState.PROCESSED
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 language support to install")) # TRANSLATORS: 'b' to go back prompt.add_option(C_("TUI|Spoke Navigation|Language Support", "b"), _("to return to language list")) return prompt
def input(self, args, key): if self._container.process_user_input(key): return InputState.PROCESSED else: 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 InputState.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: ScreenHandler.replace_screen(self, self._regions[index]) return InputState.PROCESSED # TRANSLATORS: 'b' to go back elif key.lower() == C_('TUI|Spoke Navigation|Time Settings', 'b'): ScreenHandler.replace_screen(self) return InputState.PROCESSED else: return key
def prompt(self, args=None): """ Override the default TUI prompt.""" return Prompt( _("Please make your selection from the above list.\n" "Press '%(continue)s' to continue after you have made your selection") % { # TRANSLATORS:'c' to continue 'continue': C_('TUI|Root Selection', 'c'), })
def _get_checkbox_text(self): root_name = self._root_name if root_name and "_" in root_name: root_name = root_name.replace("_", "__") if self._is_multiselection: return C_( "GUI|Custom Partitioning|Confirm Delete Dialog", "Do _not show this dialog for other selected file systems.") if root_name: return C_( "GUI|Custom Partitioning|Confirm Delete Dialog", "Delete _all file systems which are only used by {}.").format( root_name) return None
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() return InputState.PROCESSED_AND_CLOSE else: return super().input(args, key)
def input(self, args, key): """Grab the disk choice and update things""" self.errors = [] if self._container.process_user_input(key): return InputState.PROCESSED_AND_REDRAW 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) # Allow to format DASDs. self._disk_init_module.SetFormatUnrecognizedEnabled(True) self._disk_init_module.SetFormatLDLEnabled(True) # Get selected disks. disks = filter_disks_by_names(self._available_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 apply_disk_selection(self._selected_disks) # Run the dialog. self.run_dasdfmt_dialog(dasd_formatting) return InputState.PROCESSED_AND_REDRAW # make sure no containers were split up by the user's disk # selection report = ValidationReport.from_structure( self._disk_select_module.ValidateSelectedDisks(self._selected_disks) ) self.errors.extend(report.get_messages()) if self.errors: # The disk selection has to make sense before we can # proceed. return InputState.PROCESSED_AND_REDRAW self.apply() new_spoke = PartTypeSpoke(self.data, self.storage, self.payload, self._storage_module, self._partitioning) ScreenHandler.push_screen_modal(new_spoke) self._partitioning = new_spoke.partitioning self.apply() self.execute() return InputState.PROCESSED_AND_CLOSE else: return super().input(args, key)
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 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().input(args, key)
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() return InputState.PROCESSED_AND_CLOSE else: return super().input(args, key) return InputState.PROCESSED_AND_REDRAW
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().input(args, key)
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.get_device_by_id(obj.id) if device.is_disk: self._actionChanged(itr, action) itr = self._diskStore.iter_next(itr)
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))