def guided_partitions(self, device_index): menu_height = 9 menu_width = 40 menu_starty = (self.maxy - menu_height) / 2 + 5 confrim_window = ConfirmWindow( menu_height, menu_width, self.maxy, self.maxx, menu_starty, 'This will erase the disk.\nAre you sure?') confirmed = confrim_window.do_action().result['yes'] if not confirmed: return ActionResult(confirmed, None) #self.install_config['disk'] = self.devices[device_index].path #return ActionResult(True, None) # Do the partitioning self.window.clearerror() json_ret = subprocess.check_output([ 'gpartedbin', 'defaultpartitions', self.devices[device_index].path ], stderr=open(os.devnull, 'w')) json_dct = json.loads(json_ret) if json_dct['success']: self.install_config['disk'] = json_dct['data'] else: self.window.adderror('Partitioning failed, you may try again') return ActionResult(json_dct['success'], None)
def guided_partitions(self, device_index): menu_height = 9 menu_width = 40 menu_starty = (self.maxy - menu_height) / 2 + 5 confrim_window = ConfirmWindow( menu_height, menu_width, self.maxy, self.maxx, menu_starty, 'This will erase the disk.\nAre you sure?') confirmed = confrim_window.do_action().result['yes'] if not confirmed: return ActionResult(confirmed, None) self.progress_bar.initialize('Partitioning...') self.progress_bar.show() self.progress_bar.show_loading('Partitioning') # Do the partitioning self.window.clearerror() partitions_data = modules.commons.partition_disk( self.devices[device_index].path) if partitions_data == None: self.window.adderror('Partitioning failed, you may try again') else: self.install_config['disk'] = partitions_data self.progress_bar.hide() return ActionResult(partitions_data != None, None)
def do_action(self): self.init_text() curses.curs_set(1) if self.default_string != None: self.textwin.addstr(self.y, 0, self.default_string) self.str = self.default_string while True: if len(self.str) > self.visible_text_width: curs_loc = self.visible_text_width else: curs_loc = len(self.str) ch = self.textwin.getch(self.y, curs_loc) update_text = False if ch in [curses.KEY_ENTER, ord('\n')]: if self.confirmation_error_msg: if self.str != self.install_config[self.field]: curses.curs_set(0) conf_message_height = 8 conf_message_width = 48 conf_message_button_y = (self.maxy - conf_message_height) / 2 + 5 confrim_window = ConfirmWindow( conf_message_height, conf_message_width, self.maxy, self.maxx, conf_message_button_y, self.confirmation_error_msg, True) confrim_window.do_action() return ActionResult(False, {'goBack': True}) self.set_field() else: if not self.validate_input(): continue self.set_field() curses.curs_set(0) return ActionResult(True, None) elif ch in [ord('\t')]: curses.curs_set(0) return ActionResult(False, None) elif ch == 127: # Handle the backspace case self.str = self.str[:len(self.str) - 1] update_text = True elif len(self.str) < self.maxlength and ch in self.accepted_chars: self.str += chr(ch) update_text = True if update_text: if len(self.str) > self.visible_text_width: text = self.str[-self.visible_text_width:] else: text = self.str if self.echo_char: text = self.echo_char * len(text) # Add the dashes text = text + '_' * (self.visible_text_width - len(self.str)) self.textwin.addstr(self.y, 0, text)
def guided_partitions(self, params): if not 'diskindex' in self.install_config: return ActionResult(False, None) device_index = self.install_config['diskindex'] menu_height = 9 menu_width = 40 menu_starty = (self.maxy - menu_height) // 2 + 5 self.install_config['delete_partition'] = True confrim_window = ConfirmWindow(menu_height, menu_width, self.maxy, self.maxx, menu_starty, 'This will erase the disk.\nAre you sure?') confirmed = confrim_window.do_action().result['yes'] if confirmed == False: self.install_config['skipPrevs'] = True return ActionResult(False, {'goBack':True}) self.install_config['skipPrevs'] = False self.progress_bar.initialize('Partitioning...') self.progress_bar.show() self.progress_bar.show_loading('Partitioning') # Do the partitioning if 'partitionsnumber' in self.install_config: if int(self.install_config['partitionsnumber']) == 0: partitions_data = modules.commons.partition_disk( self.devices[device_index].path, modules.commons.default_partitions) else: partitions = [] for i in range(int(self.install_config['partitionsnumber'])): if len(self.install_config[str(i)+'partition_info'+str(0)]) == 0: sizedata = 0 else: sizedata = int(self.install_config[str(i) + 'partition_info' + str(0)]) mtdata = self.install_config[str(i) + 'partition_info' + str(2)] typedata = self.install_config[str(i) + 'partition_info'+str(1)] partitions = partitions + [{"mountpoint": mtdata, "size": sizedata, "filesystem": typedata},] partitions_data = modules.commons.partition_disk( self.devices[device_index].path, partitions) else: partitions_data = modules.commons.partition_disk( self.devices[device_index].path, modules.commons.default_partitions) if partitions_data == None: self.partition_window.adderror('Partitioning failed, you may try again') else: self.install_config['disk'] = partitions_data arch = subprocess.check_output(['uname', '-m'], universal_newlines=True) if "x86" in arch: self.install_config['boot'] = 'dualboot' else: self.install_config['boot'] = 'efi' self.progress_bar.hide() return ActionResult(partitions_data != None, None)
def do_action(self): self.init_text() curses.curs_set(1) while True: if len(self.str) > self.visible_text_width: curs_loc = self.visible_text_width else: curs_loc = len(self.str) ch = self.textwin.getch(self.y, curs_loc) if ch in [curses.KEY_ENTER, ord('\n')]: if self.confirm_pass: if self.str != self.install_config['password']: curses.curs_set(0) conf_message_height = 8 conf_message_width = 40 conf_message_button_y = (self.maxy - conf_message_height) / 2 + 5 confrim_window = ConfirmWindow(conf_message_height, conf_message_width, self.maxy, self.maxx, conf_message_button_y, "passwords don't match, please try again.", True) confrim_window.do_action() return ActionResult(False, {'goBack': True}) self.install_config['password'] = self.generate_password_hash(self.str) elif self.ispassword: err = self.validate_password(self.str) if err != self.str: self.init_text() self.textwin.addstr(self.y + 2, 0, "Error: " + err, curses.color_pair(4)) continue self.install_config['password'] = self.str; else: if not self.validate_hostname(self.str): self.textwin.addstr(self.y + 2, 0, "It should start with alpha char and ends with alpha-numeric char", curses.color_pair(4)) continue self.install_config['hostname'] = self.str curses.curs_set(0) return ActionResult(True, None) elif ch in [ord('\t')]: curses.curs_set(0) return ActionResult(False, None) elif ch == 127: # Handle the backspace case self.str = self.str[:len(self.str) - 1] update_text = True elif len(self.str) < self.maxlength and ch in self.accepted_chars: self.str += chr(ch) update_text = True if update_text: if len(self.str) > self.visible_text_width: text = self.str[-self.visible_text_width:] else: text = self.str if self.ispassword: text = '*' * len(text) # Add the dashes text = text + '_' * (self.visible_text_width - len(self.str)) self.textwin.addstr(self.y, 0, text)
def do_action(self): self.init_text() curses.curs_set(1) if self.default_string != None: self.textwin.addstr(self.y, 0, self.default_string) self.str = self.default_string while True: if len(self.str) > self.visible_text_width: curs_loc = self.visible_text_width else: curs_loc = len(self.str) ch = self.textwin.getch(self.y, curs_loc) update_text = False if ch in [curses.KEY_ENTER, ord('\n')]: if self.confirmation_error_msg: if self.str != self.install_config[self.field]: curses.curs_set(0) conf_message_height = 8 conf_message_width = 48 conf_message_button_y = (self.maxy - conf_message_height) / 2 + 5 confrim_window = ConfirmWindow(conf_message_height, conf_message_width, self.maxy, self.maxx, conf_message_button_y, self.confirmation_error_msg, True) confrim_window.do_action() return ActionResult(False, {'goBack': True}) self.set_field() else: if not self.validate_input(): continue self.set_field() curses.curs_set(0) return ActionResult(True, None) elif ch in [ord('\t')]: curses.curs_set(0) return ActionResult(False, None) elif ch == 127: # Handle the backspace case self.str = self.str[:len(self.str) - 1] update_text = True elif len(self.str) < self.maxlength and ch in self.accepted_chars: self.str += chr(ch) update_text = True if update_text: if len(self.str) > self.visible_text_width: text = self.str[-self.visible_text_width:] else: text = self.str if self.echo_char: text = self.echo_char * len(text) # Add the dashes text = text + '_' * (self.visible_text_width - len(self.str)) self.textwin.addstr(self.y, 0, text)
def guided_partitions(self, params): if not 'diskindex' in self.install_config: return ActionResult(False, None) device_index = self.install_config['diskindex'] menu_height = 9 menu_width = 40 menu_starty = (self.maxy - menu_height) // 2 + 5 self.install_config['delete_partition'] = True confrim_window = ConfirmWindow(menu_height, menu_width, self.maxy, self.maxx, menu_starty, 'This will erase the disk.\nAre you sure?') confirmed = confrim_window.do_action().result['yes'] if confirmed == False: self.install_config['skipPrevs'] = True return ActionResult(False, {'goBack':True}) self.install_config['skipPrevs'] = False self.progress_bar.initialize('Partitioning...') self.progress_bar.show() self.progress_bar.show_loading('Partitioning') # Do the partitioning if 'partitionsnumber' in self.install_config: if int(self.install_config['partitionsnumber']) == 0: partitions_data = modules.commons.partition_disk( self.devices[device_index].path, modules.commons.default_partitions) else: partitions = [] for i in range(int(self.install_config['partitionsnumber'])): if len(self.install_config[str(i)+'partition_info'+str(0)]) == 0: sizedata = 0 else: sizedata = int(self.install_config[str(i) + 'partition_info' + str(0)]) mtdata = self.install_config[str(i) + 'partition_info' + str(2)] typedata = self.install_config[str(i) + 'partition_info'+str(1)] partitions = partitions + [{"mountpoint": mtdata, "size": sizedata, "filesystem": typedata},] partitions_data = modules.commons.partition_disk( self.devices[device_index].path, partitions) else: partitions_data = modules.commons.partition_disk( self.devices[device_index].path, modules.commons.default_partitions) if partitions_data == None: self.partition_window.adderror('Partitioning failed, you may try again') else: self.install_config['disk'] = partitions_data self.progress_bar.hide() return ActionResult(partitions_data != None, None)
def next(self): if self.install_config['partitionsnumber'] == 0: window_height = 9 window_width = 40 window_starty = (self.maxy - window_height) / 2 + 5 confirm_window = ConfirmWindow( window_height, window_width, self.maxy, self.maxx, window_starty, 'Partition information cannot be empty', info=True) confirm_window.do_action() return self.display(False) #must have / if not self.has_slash: window_height = 9 window_width = 40 window_starty = (self.maxy - window_height) / 2 + 5 confirm_window = ConfirmWindow(window_height, window_width, self.maxy, self.maxx, window_starty, 'Missing /', info=True) confirm_window.do_action() return self.display(False) self.window.hide_window() self.text_pane.hide() return ActionResult(True, {'goNext': True})
def next(self): if self.cp_config['partitionsnumber'] == 0: window_height = 9 window_width = 40 window_starty = (self.maxy - window_height) // 2 + 5 confirm_window = ConfirmWindow( window_height, window_width, self.maxy, self.maxx, window_starty, 'Partition information cannot be empty', info=True) confirm_window.do_action() return self.display() #must have / if not self.has_slash: window_height = 9 window_width = 40 window_starty = (self.maxy - window_height) // 2 + 5 confirm_window = ConfirmWindow(window_height, window_width, self.maxy, self.maxx, window_starty, 'Missing /', info=True) confirm_window.do_action() return self.display() self.window.hide_window() self.partition_pane.hide() partitions = [] for i in range(int(self.cp_config['partitionsnumber'])): if len(self.cp_config[str(i) + 'partition_info' + str(0)]) == 0: sizedata = 0 else: sizedata = int(self.cp_config[str(i) + 'partition_info' + str(0)]) mtdata = self.cp_config[str(i) + 'partition_info' + str(2)] typedata = self.cp_config[str(i) + 'partition_info' + str(1)] partitions = partitions + [ { "mountpoint": mtdata, "size": sizedata, "filesystem": typedata }, ] self.install_config['partitions'] = partitions return ActionResult(True, {'goNext': True})
def do_setup_network(self): if not self.netmgr.setup_network(): msg = 'Failed to setup network configuration!' conf_message_height = 12 conf_message_width = 80 conf_message_button_y = (self.maxy - conf_message_height) // 2 + 8 ConfirmWindow(conf_message_height, conf_message_width, self.maxy, self.maxx, conf_message_button_y, msg, True).do_action() return False self.netmgr.restart_networkd() return True
def ask_proceed_unsafe_download(self, fingerprint): msg = ('This server could not prove its authenticity. Its ' 'fingerprint is:\n\n' + fingerprint + '\n\nDo you wish to proceed?\n') conf_message_height = 12 conf_message_width = 80 conf_message_button_y = (self.maxy - conf_message_height) // 2 + 8 r = ConfirmWindow(conf_message_height, conf_message_width, self.maxy, self.maxx, conf_message_button_y, msg).do_action() if not r.success or not r.result.get('yes', False): return False return True
def next(self): if self.install_config['partitionsnumber'] == 0: window_height = 9 window_width = 40 window_starty = (self.maxy-window_height) // 2 + 5 confirm_window = ConfirmWindow(window_height, window_width, self.maxy, self.maxx, window_starty, 'Partition information cannot be empty', info=True) confirm_window.do_action() return self.display(False) #must have / if not self.has_slash: window_height = 9 window_width = 40 window_starty = (self.maxy - window_height) // 2 + 5 confirm_window = ConfirmWindow(window_height, window_width, self.maxy, self.maxx, window_starty, 'Missing /', info=True) confirm_window.do_action() return self.display(False) self.window.hide_window() self.text_pane.hide() return ActionResult(True, {'goNext':True})
def guided_partitions(self, device_index): menu_height = 9 menu_width = 40 menu_starty = (self.maxy - menu_height) / 2 + 5 confrim_window = ConfirmWindow(menu_height, menu_width, self.maxy, self.maxx, menu_starty, 'This will erase the disk.\nAre you sure?') confirmed = confrim_window.do_action().result['yes'] if not confirmed: return ActionResult(confirmed, None) #self.install_config['disk'] = self.devices[device_index].path #return ActionResult(True, None) # Do the partitioning self.window.clearerror() json_ret = subprocess.check_output(['gpartedbin', 'defaultpartitions', self.devices[device_index].path], stderr=open(os.devnull, 'w')) json_dct = json.loads(json_ret) if json_dct['success']: self.install_config['disk'] = json_dct['data'] else: self.window.adderror('Partitioning failed, you may try again') return ActionResult(json_dct['success'], None)
def guided_partitions(self, device_index): menu_height = 9 menu_width = 40 menu_starty = (self.maxy - menu_height) / 2 + 5 confrim_window = ConfirmWindow(menu_height, menu_width, self.maxy, self.maxx, menu_starty, 'This will erase the disk.\nAre you sure?') confirmed = confrim_window.do_action().result['yes'] if not confirmed: return ActionResult(confirmed, None) self.progress_bar.initialize('Partitioning...') self.progress_bar.show() self.progress_bar.show_loading('Partitioning') # Do the partitioning self.window.clearerror() partitions_data = modules.commons.partition_disk(self.devices[device_index].path, modules.commons.default_partitions) if partitions_data == None: self.window.adderror('Partitioning failed, you may try again') else: self.install_config['disk'] = partitions_data self.progress_bar.hide() return ActionResult(partitions_data != None, None)
def add_ui_pages(self, options_file, maxy, maxx, install_config): items = [] license_agreement = License(maxy, maxx) select_disk = SelectDisk(maxy, maxx, install_config) select_partition = PartitionISO(maxy, maxx, install_config) package_selector = PackageSelector(maxy, maxx, install_config, options_file) hostname_reader = WindowStringReader( maxy, maxx, 10, 70, 'hostname', None, # confirmation error msg if it's a confirmation text None, # echo char self.hostname_accepted_chars, # set of accepted chars IsoConfig.validate_hostname, # validation function of the input None, # post processing of the input field 'Choose the hostname for your system', 'Hostname:', 2, install_config, self.random_hostname, True) root_password_reader = WindowStringReader( maxy, maxx, 10, 70, 'password', None, # confirmation error msg if it's a confirmation text '*', # echo char None, # set of accepted chars IsoConfig.validate_password, # validation function of the input None, # post processing of the input field 'Set up root password', 'Root password:'******'password', # confirmation error msg if it's a confirmation text "Passwords don't match, please try again.", '*', # echo char None, # set of accepted chars None, # validation function of the input IsoConfig. generate_password_hash, # post processing of the input field 'Confirm root password', 'Confirm Root password:'******'ostree_repo_url', None, # confirmation error msg if it's a confirmation text None, # echo char None, # set of accepted chars IsoConfig. validate_ostree_url_input, # validation function of the input None, # post processing of the input field 'Please provide the URL of OSTree repo', 'OSTree Repo URL:', 2, install_config, "http://") ostree_ref_reader = OSTreeWindowStringReader( maxy, maxx, 10, 70, 'ostree_repo_ref', None, # confirmation error msg if it's a confirmation text None, # echo char None, # set of accepted chars IsoConfig. validate_ostree_refs_input, # validation function of the input None, # post processing of the input field 'Please provide the Refspec in OSTree repo', 'OSTree Repo Refspec:', 2, install_config, "photon/3.0/x86_64/minimal") confirm_window = ConfirmWindow( 11, 60, maxy, maxx, (maxy - 11) // 2 + 7, 'Start installation? All data on the selected disk will be lost.\n\n' 'Press <Yes> to confirm, or <No> to quit') items.append((license_agreement.display, False)) items.append((select_disk.display, True)) items.append((select_partition.display, False)) items.append((package_selector.display, True)) if self.is_vmware_virtualization(): linux_selector = LinuxSelector(maxy, maxx, install_config) items.append((linux_selector.display, True)) items.append((hostname_reader.get_user_string, True)) items.append((root_password_reader.get_user_string, True)) items.append((confirm_password_reader.get_user_string, False)) items.append((ostree_server_selector.display, True)) items.append((ostree_url_reader.get_user_string, True)) items.append((ostree_ref_reader.get_user_string, True)) items.append((confirm_window.do_action, True)) return items
def add_ui_pages(self, install_config, ui_config, maxy, maxx): items = [] license_agreement = License(maxy, maxx) select_disk = SelectDisk(maxy, maxx, install_config) custom_partition = CustomPartition(maxy, maxx, install_config) package_selector = PackageSelector(maxy, maxx, install_config, ui_config['options_file']) hostname_reader = WindowStringReader( maxy, maxx, 10, 70, 'hostname', None, # confirmation error msg if it's a confirmation text None, # echo char self.hostname_accepted_chars, # set of accepted chars IsoConfig.validate_hostname, # validation function of the input None, # post processing of the input field 'Choose the hostname for your system', 'Hostname:', 2, install_config, self.random_hostname, True) root_password_reader = WindowStringReader( maxy, maxx, 10, 70, 'shadow_password', None, # confirmation error msg if it's a confirmation text '*', # echo char None, # set of accepted chars IsoConfig.validate_password, # validation function of the input None, # post processing of the input field 'Set up root password', 'Root password:'******'shadow_password', # confirmation error msg if it's a confirmation text "Passwords don't match, please try again.", '*', # echo char None, # set of accepted chars None, # validation function of the input CommandUtils.generate_password_hash, # post processing of the input field 'Confirm root password', 'Confirm Root password:'******'repo_url', None, # confirmation error msg if it's a confirmation text None, # echo char None, # set of accepted chars IsoConfig.validate_ostree_url_input, # validation function of the input None, # post processing of the input field 'Please provide the URL of OSTree repo', 'OSTree Repo URL:', 2, install_config, "http://") ostree_ref_reader = OSTreeWindowStringReader( maxy, maxx, 10, 70, 'repo_ref', None, # confirmation error msg if it's a confirmation text None, # echo char None, # set of accepted chars IsoConfig.validate_ostree_refs_input, # validation function of the input None, # post processing of the input field 'Please provide the Refspec in OSTree repo', 'OSTree Repo Refspec:', 2, install_config, "photon/3.0/x86_64/minimal") confirm_window = ConfirmWindow(11, 60, maxy, maxx, (maxy - 11) // 2 + 7, 'Start installation? All data on the selected disk will be lost.\n\n' 'Press <Yes> to confirm, or <No> to quit') # This represents the installer screens, the bool indicated if # I can go back to this window or not items.append((license_agreement.display, False)) items.append((select_disk.display, True)) items.append((custom_partition.display, False)) items.append((package_selector.display, True)) if 'network_screen' in ui_config: allow_vlan = ui_config['network_screen'].get('allow_vlan', False) net_cfg = NetworkConfigure(maxy, maxx, install_config, allow_vlan) items.append((net_cfg.display, True)) if 'download_screen' in ui_config: title = ui_config['download_screen'].get('title', None) intro = ui_config['download_screen'].get('intro', None) dest = ui_config['download_screen'].get('destination', None) fd = FileDownloader(maxy, maxx, install_config, title, intro, dest, True) items.append((fd.display, True)) if CommandUtils.is_vmware_virtualization(): linux_selector = LinuxSelector(maxy, maxx, install_config) items.append((linux_selector.display, True)) items.append((hostname_reader.get_user_string, True)) items.append((root_password_reader.get_user_string, True)) items.append((confirm_password_reader.get_user_string, False)) items.append((ostree_server_selector.display, True)) items.append((ostree_url_reader.get_user_string, True)) items.append((ostree_ref_reader.get_user_string, True)) items.append((confirm_window.do_action, True)) return items
def do_action(self): self.init_text() curses.curs_set(1) if self.default_string != None: self.textwin.addstr(self.y, 0, self.default_string) self.str = self.default_string while True: if len(self.str[self.position]) > self.visible_text_width: curs_loc = self.visible_text_width + 1 else: curs_loc = len(self.str[self.position]) +1 ch = self.textwin.getch(self.y + 2 + self.position * 4, curs_loc) update_text = False if ch in [curses.KEY_ENTER, ord('\n')]: if self.menu_pos == 1: curses.curs_set(0) self.shadowpanel.hide() return ActionResult(False, None) if self.confirmation_error_msg: if self.str != self.install_config[self.field]: curses.curs_set(0) conf_message_height = 8 conf_message_width = 48 conf_message_button_y = (self.maxy - conf_message_height) // 2 + 5 confrim_window = ConfirmWindow(conf_message_height, conf_message_width, self.maxy, self.maxx, conf_message_button_y, self.confirmation_error_msg, True) confrim_window.do_action() return ActionResult(False, {'goBack': True}) self.set_field() else: if not self.validate_input(): continue self.set_field() curses.curs_set(0) self.shadowpanel.hide() return ActionResult(True, None) elif ch == curses.KEY_UP: self.refresh(-1) elif ch == curses.KEY_DOWN: self.refresh(1) elif ch in [ord('\t')]: self.refresh(1, reset=True) elif ch == curses.KEY_LEFT: self.menu_refresh(1) elif ch == curses.KEY_RIGHT: self.menu_refresh(-1) elif ch == curses.KEY_BACKSPACE: # Handle the backspace case self.str[self.position] = self.str[self.position][:len(self.str[self.position]) - 1] update_text = True elif len(self.str[self.position]) < self.maxlength and ch in self.accepted_chars: self.str[self.position] += chr(ch) update_text = True if update_text: self.update_text()
def do_action(self): self.init_text() curses.curs_set(1) if self.default_string != None: self.textwin.addstr(self.y, 0, self.default_string) self.str = self.default_string while True: if len(self.str[self.position]) > self.visible_text_width: curs_loc = self.visible_text_width + 1 else: curs_loc = len(self.str[self.position]) +1 ch = self.textwin.getch(self.y+2+self.position*4, curs_loc) update_text = False if ch in [curses.KEY_ENTER, ord('\n')]: if self.menu_pos==1: curses.curs_set(0) self.shadowpanel.hide() return ActionResult(False, None) if self.confirmation_error_msg: if self.str != self.install_config[self.field]: curses.curs_set(0) conf_message_height = 8 conf_message_width = 48 conf_message_button_y = (self.maxy - conf_message_height) / 2 + 5 confrim_window = ConfirmWindow(conf_message_height, conf_message_width, self.maxy, self.maxx, conf_message_button_y, self.confirmation_error_msg, True) confrim_window.do_action() return ActionResult(False, {'goBack': True}) self.set_field() else: if not self.validate_input(): continue self.set_field() curses.curs_set(0) self.shadowpanel.hide() return ActionResult(True, None) elif ch == curses.KEY_UP: self.refresh(-1) elif ch == curses.KEY_DOWN: self.refresh(1) elif ch in [ord('\t')]: self.refresh(1, reset=True) elif ch ==curses.KEY_LEFT: self.menu_refresh(1) elif ch == curses.KEY_RIGHT: self.menu_refresh(-1) elif ch == curses.KEY_BACKSPACE: # Handle the backspace case self.str[self.position] = self.str[self.position][:len(self.str[self.position]) - 1] update_text = True elif len(self.str[self.position]) < self.maxlength and ch in self.accepted_chars: self.str[self.position] += chr(ch) update_text = True if update_text: self.update_text()