class ProgressView(BaseView): def __init__(self, controller): self.controller = controller self.listwalker = SimpleFocusListWalker([]) self.listbox = ListBox(self.listwalker) self.linebox = MyLineBox(self.listbox) body = [ ('pack', Text("")), ('weight', 1, Padding.center_79(self.linebox)), ('pack', Text("")), ] self.pile = Pile(body) super().__init__(self.pile) def add_log_tail(self, text): at_end = len( self.listwalker) == 0 or self.listbox.focus_position == len( self.listwalker) - 1 for line in text.splitlines(): self.listwalker.append(Text(line)) if at_end: self.listbox.set_focus(len(self.listwalker) - 1) self.listbox.set_focus_valign('bottom') def clear_log_tail(self): self.listwalker[:] = [] def set_status(self, text): self.linebox.set_title(text) def show_complete(self, include_exit=False): buttons = [ ok_btn(_("Reboot Now"), on_press=self.reboot), ] if include_exit: buttons.append(cancel_btn(_("Exit To Shell"), on_press=self.quit)) buttons = button_pile(buttons) new_pile = Pile([ ('pack', Text("")), buttons, ('pack', Text("")), ]) self.pile.contents[-1] = (new_pile, self.pile.options('pack')) self.pile.focus_position = len(self.pile.contents) - 1 def reboot(self, btn): self.controller.reboot() def quit(self, btn): self.controller.quit()
class ProgressView(BaseView): def __init__(self, controller): self.controller = controller self.spinner = Spinner(controller.loop) self.event_listwalker = SimpleFocusListWalker([]) self.event_listbox = ListBox(self.event_listwalker) self.event_linebox = MyLineBox(self.event_listbox) self.event_buttons = button_pile([other_btn("View full log", on_press=self.view_log)]) event_body = [ ('pack', Text("")), ('weight', 1, Padding.center_79(self.event_linebox)), ('pack', Text("")), ('pack', self.event_buttons), ('pack', Text("")), ] self.event_pile = Pile(event_body) self.log_listwalker = SimpleFocusListWalker([]) self.log_listbox = ListBox(self.log_listwalker) log_linebox = MyLineBox(self.log_listbox, _("Full installer output")) log_body = [ ('weight', 1, log_linebox), ('pack', button_pile([other_btn(_("Close"), on_press=self.close_log)])), ] self.log_pile = Pile(log_body) super().__init__(self.event_pile) def add_event(self, text): at_end = len(self.event_listwalker) == 0 or self.event_listbox.focus_position == len(self.event_listwalker) - 1 if len(self.event_listwalker) > 0: self.event_listwalker[-1] = self.event_listwalker[-1][0] self.event_listwalker.append(Columns([('pack', Text(text)), ('pack', self.spinner)], dividechars=1)) if at_end: self.event_listbox.set_focus(len(self.event_listwalker) - 1) self.event_listbox.set_focus_valign('bottom') def add_log_line(self, text): at_end = len(self.log_listwalker) == 0 or self.log_listbox.focus_position == len(self.log_listwalker) - 1 self.log_listwalker.append(Text(text)) if at_end: self.log_listbox.set_focus(len(self.log_listwalker) - 1) self.log_listbox.set_focus_valign('bottom') def set_status(self, text): self.event_linebox.set_title(text) def show_complete(self, include_exit=False): p = self.event_buttons.original_widget p.contents.append( (ok_btn(_("Reboot Now"), on_press=self.reboot), p.options('pack'))) if include_exit: p.contents.append( (cancel_btn(_("Exit To Shell"), on_press=self.quit), p.options('pack'))) w = 0 for b, o in p.contents: w = max(len(b.base_widget.label), w) self.event_buttons.width = self.event_buttons.min_width = w + 4 self.event_pile.focus_position = 3 p.focus_position = 1 def reboot(self, btn): self.controller.reboot() def quit(self, btn): self.controller.quit() def view_log(self, btn): self._w = self.log_pile def close_log(self, btn): self._w = self.event_pile
class NetworkView(BaseView): def __init__(self, model, controller): self.model = model self.controller = controller self.items = [] self.error = Text("", align='center') self.model_inputs = Pile(self._build_model_inputs()) self.additional_options = Pile(self._build_additional_options()) self.body = [ Padding.center_79(self.model_inputs), Padding.line_break(""), Padding.center_79(self.additional_options), Padding.line_break(""), Padding.center_79(Color.info_error(self.error)), Padding.line_break(""), Padding.fixed_10(self._build_buttons()), ] # FIXME determine which UX widget should have focus self.lb = ListBox(self.body) self.lb.set_focus(4) # _build_buttons super().__init__(self.lb) def _build_buttons(self): cancel = Color.button(cancel_btn(on_press=self.cancel)) done = Color.button(done_btn(on_press=self.done)) self.default_focus = done buttons = [done, cancel] return Pile(buttons, focus_item=done) def _build_model_inputs(self): netdevs = self.model.get_all_netdevs() ifname_width = 8 # default padding if netdevs: ifname_width += max(map(lambda dev: len(dev.name), netdevs)) if ifname_width > 20: ifname_width = 20 iface_menus = [] # Display each interface -- name in first column, then configured IPs # in the second. log.debug('interfaces: {}'.format(netdevs)) for dev in netdevs: col_1 = [] col_2 = [] col_1.append( Color.menu_button( menu_btn(label=dev.name, on_press=self.on_net_dev_press))) if dev.type == 'wlan': col_2.extend(_build_wifi_info(dev)) if len(dev.actual_ip_addresses) == 0 and dev.type == 'eth' and not dev.is_connected: col_2.append(Color.info_primary(Text("Not connected"))) col_2.extend(_build_gateway_ip_info_for_version(dev, 4)) col_2.extend(_build_gateway_ip_info_for_version(dev, 6)) # Other device info (MAC, vendor/model, speed) template = '' if dev.hwaddr: template += '{} '.format(dev.hwaddr) if dev.is_bond_slave: template += '(Bonded) ' if not dev.vendor.lower().startswith('unknown'): vendor = textwrap.wrap(dev.vendor, 15)[0] template += '{} '.format(vendor) if not dev.model.lower().startswith('unknown'): model = textwrap.wrap(dev.model, 20)[0] template += '{} '.format(model) if dev.speed: template += '({})'.format(dev.speed) col_2.append(Color.info_minor(Text(template))) iface_menus.append(Columns([(ifname_width, Pile(col_1)), Pile(col_2)], 2)) return iface_menus def refresh_model_inputs(self): self.model_inputs.contents = [ (obj, ('pack', None)) for obj in self._build_model_inputs() ] self.additional_options.contents = [ (obj, ('pack', None)) for obj in self._build_additional_options() ] def _build_additional_options(self): labels = [] netdevs = self.model.get_all_netdevs() # Display default route status if self.model.default_v4_gateway is not None: v4_route_source = "via " + self.model.default_v4_gateway default_v4_route_w = Color.info_minor( Text(" IPv4 default route " + v4_route_source + ".")) labels.append(default_v4_route_w) if self.model.default_v6_gateway is not None: v6_route_source = "via " + self.model.default_v6_gateway default_v6_route_w = Color.info_minor( Text(" IPv6 default route " + v6_route_source + ".")) labels.append(default_v6_route_w) max_btn_len = 0 buttons = [] for opt, sig in self.model.get_menu(): if ':set-default-route' in sig: if len(netdevs) < 2: log.debug('Skipping default route menu option' ' (only one nic)') continue if ':bond-interfaces' in sig: not_bonded = [dev for dev in netdevs if not dev.is_bonded] if len(not_bonded) < 2: log.debug('Skipping bonding menu option' ' (not enough available nics)') continue if len(opt) > max_btn_len: max_btn_len = len(opt) buttons.append( Color.menu_button( menu_btn(label=opt, on_press=self.additional_menu_select, user_data=sig))) from urwid import Padding buttons = [ Padding(button, align='left', width=max_btn_len + 6) for button in buttons ] return labels + buttons def additional_menu_select(self, result, sig): self.controller.signal.emit_signal(sig) def on_net_dev_press(self, result): log.debug("Selected network dev: {}".format(result.label)) self.controller.network_configure_interface(result.label) def show_network_error(self, action, info=None): if action == 'generate': self.error.set_text("Network configuration failed: %r" % (info,)) elif action == 'apply': self.error.set_text("Network configuration could not be applied; " + \ "please verify your settings.") elif action == 'timeout': self.error.set_text("Network configuration timed out; " + \ "please verify your settings.") elif action == 'canceled': self.error.set_text("Network configuration canceled.") else: self.error.set_text("An unexpected error has occurred; " + \ "please verify your settings.") def done(self, result): self.controller.network_finish(self.model.render()) def cancel(self, button): self.controller.cancel()