def create_interface(self): self.screen = Screen() self.screen.start() self.screen.register_palette([ ("title", "white", "dark blue", "standout"), ("line", "light gray", "black"), ("help", "white", "dark blue")] ) self.body = ListBox(SimpleListWalker([])) self.lines = self.body.body self.title = Text(MAIN_TITLE) self.header = AttrWrap(self.title, "title") self.help = AttrWrap( Text(HELP_STRINGS["main"]), "help" ) self.input = Edit(caption="%s> " % self.ircchannel) self.footer = Pile([self.help, self.input]) self.top = Frame(self.body, self.header, self.footer)
def __init__(self, loop): header = [AttrWrap(Text(TITLE_TEXT), "border"), AttrWrap(Text('(Q) Quit'), "border"), AttrWrap(Text('(F5) Refresh'), "border"), AttrWrap(Text('(F6) Add units'), "border"), AttrWrap(Text('(F8) Console'), "border")] header = Columns(header) self.timer = Text("", align="left") self.status_info = Text("", align="left") self.horizon_url = Text("", align="right") self.jujugui_url = Text("", align="right") footer = Columns([('weight', 0.2, self.status_info), ('weight', 0.1, self.timer), ('weight', 0.2, self.horizon_url), ('weight', 0.2, self.jujugui_url)]) footer = AttrWrap(footer, "border") self.poll_interval = 10 self.ticks_left = 0 self.juju_state = None self.maas_state = None self.nodes = ListWithHeader(NODE_HEADER) self.loop = loop self.cr = CommandRunner() Frame.__init__(self, header=header, body=self.nodes, footer=footer) self.controller_overlay = ControllerOverlay(self, self.cr) self._target = self.controller_overlay
def __init__(self, configuration): Frame.__init__(self, WelcomeBuffer(), header=TabsWidget(), footer=StatusBar('')) self._configuration = configuration self._editor_mode = False
def __init__(self): _check_encoding() # Make sure terminal supports utf8 header = Header() body = Banner() footer = StatusBar('') self.frame = Frame(body, header=header, footer=footer) super().__init__(self.frame)
def __init__(self): header = [AttrWrap(Text(TITLE_TEXT), "border"), AttrWrap(Text('(Q) Quit'), "border"), AttrWrap(Text('(F8) Node list'), "border")] header = Columns(header) with open(path.expanduser('~/.cloud-install/commands.log')) as f: body = f.readlines() body = ListBox([Text(x) for x in body]) Frame.__init__(self, header=header, body=body)
class Sidebar(BoxWidget): signals = ['select', 'search'] def __init__(self, phones): self.phone_edit = EnterEdit('Phone:', '') self.chan_edit = EnterEdit('Chanl:', '') self.call_id_edit = EnterEdit('SipID:', '') self.text_edit = EnterEdit('Find:', '') connect_signal(self.phone_edit, 'enter', self.on_change, 'phone') connect_signal(self.chan_edit, 'enter', self.on_change, 'chan') connect_signal(self.call_id_edit, 'enter', self.on_change, 'call_id') connect_signal(self.text_edit, 'enter', self.on_change, 'text') self.phones_text = Text([('key', 'F4'), ' Phones']) self.head = Pile([ AttrWrap(Text([('key', 'F3'), ' Search']), 'bar'), AttrWrap(self.phone_edit, 'no', 'selection'), AttrWrap(self.chan_edit, 'no', 'selection'), AttrWrap(self.call_id_edit, 'no', 'selection'), Divider('-'), AttrWrap(self.text_edit, 'no', 'selection'), AttrWrap(self.phones_text, 'bar'), ]) self.items = SimpleListWalker([]) self.set_results(phones) self.listbox = ListBox(self.items) self.frame = Frame(self.listbox, header=self.head) def set_results(self, results): self.phones_text.set_text([('key', 'F4'), ' Results (%s)' % len(results)]) self.items[:] = [] group = [] for ref in results: item = RadioButton(group, ref, state=False) connect_signal(item, 'change', self.on_select_phone, ref) item = AttrWrap(item, 'no', 'selection') self.items.append(item) def render(self, size, focus=False): return self.frame.render(size, focus) def keypress(self, size, key): return self.frame.keypress(size, key) # noinspection PyUnusedLocal def on_select_phone(self, button, new_state, call_id): if new_state: self._emit('select', call_id) # noinspection PyUnusedLocal def on_change(self, widget, value, field_name): self._emit('search', field_name, value)
def __init__(self, header=None, body=None, footer=None): self.header = header if header else Header() self.body = body if body else Banner() self.footer = footer if footer else StatusBarWidget() self.frame = Frame(self.body, header=self.header, footer=self.footer) self.services_view = None self.placement_view = None self.controller = None self.machine_wait_view = None self.node_install_wait_view = None self.add_services_dialog = None super().__init__(self.frame)
def _layout(self): self._wallpaper_count = Text(str(len(self._wpctrl.wallpapers))) self._info = Text("", wrap='clip') self._head = Columns([('pack', self._wallpaper_count), (10, Text("Wallpapers")), self._info], dividechars=1) header = Pile([self._head, AttrMap(Divider("─"), 'divider')]) self._screens = [ScreenWidget(screen, self._scrctrl) for screen in self._scrctrl.screens] body = ListBoxWithTabSupport(self._screens) self._root = Frame(header=header, body=body)
def __init__(self, list_data=None): self.is_editing = False self.tasks = [] self.name = None self.group = None self.id = None if list_data: # Parse the data. self.parse_data(list_data) else: # Must be a new list self.name = 'untitled' self.group = 'none' self.id = uuid.uuid4().hex # AttrSpecs self.attr_spec = AttrSpec('', '') self.focus_nav = AttrSpec('h12', '') self.focus_ins = AttrSpec('h160', '') # Build widget stack self.title = TitleBar(self.name) self.group_foot = GroupFoot(self.group) self.body = urwid.SimpleFocusListWalker(self.tasks) self.list_box = ListBox(self.body) self.list_frame = Frame(self.list_box, header=self.title, footer=self.group_foot) self.line_box = LineBox(self.list_frame) self.line_attr = AttrMap(self.line_box, self.attr_spec, self.focus_nav) super().__init__(self.line_attr)
def __init__(self, parser, encoding): self.loop = None self.parser = parser self.panel_focus = 1 self.show_ladder = False self.search = { 'phone': '', 'chan': '', 'call_id': '', } self.sidebar = Sidebar(sorted(self.parser.get_phone_set())) connect_signal(self.sidebar, 'select', self.on_result_selected) connect_signal(self.sidebar, 'search', self.on_search) self.log_display = LogDisplay(parser, encoding) self.cols = Columns([ ('fixed', 20, self.sidebar), ('fixed', 1, Filler(Divider(), 'top')), ('weight', 1, self.log_display), ]) self.footer = Text('') self.set_footer_text() self.frame = Frame(self.cols, footer=AttrWrap(self.footer, 'bar'))
def __init__(self, header=None, body=None, footer=None): _check_encoding() # Make sure terminal supports utf8 cb = self.show_exception_message utils.register_async_exception_callback(cb) self.header = header if header else Header() self.body = body if body else Banner() self.footer = footer if footer else StatusBar('') self.frame = Frame(self.body, header=self.header, footer=self.footer) self.services_view = None self.placement_view = None self.controller = None self.machine_wait_view = None self.add_services_dialog = None super().__init__(self.frame)
def __init__(self, schema, cb): self.input_items = schema self.cb = cb self.frame = Frame(body=self._build_widget(), footer=self._build_footer()) self.buttons_selected = False super().__init__(self.frame)
def __init__(self, application, controller): """ application: a Service instance representing a juju application controller: a DeployGUIController instance """ self.controller = controller self.application = application self.header = "Architecture" # Shadow means temporary to the view, they are committed to # the controller if the user chooses OK # {machine_id : [(app, assignmenttype) ...] self.shadow_assignments = defaultdict(list) for machine_id, al in self.controller.assignments.items(): for (a, at) in al: if a == self.application: self.shadow_assignments[machine_id].append((a, at)) # {juju_machine_id : maas machine id} self.shadow_pins = copy.copy(controller.maas_machine_map) self.machine_pin_view = None self._machines = copy.deepcopy(app.metadata_controller.bundle.machines) self.alarm = None self.widgets = self.build_widgets() self.description_w = Text("") self.buttons_selected = False self.frame = Frame(body=self.build_widgets(), footer=self.build_footer()) super().__init__(self.frame) self.update()
def __init__(self, app, error=None, cb=None): self.app = app self.error = error self.cb = cb self.config = self.app.config self.field_labels = self._build_field_labels() self.fields = self._build_fields() self.buttons = self._build_buttons() self.frame = Frame(body=self._build_widget(), footer=self._build_footer()) self.tab_order = [ 'email', 'password', 'twofa', 'login', 'quit', ] self.focus_by_fields = { 'email': ('body', 0), 'password': ('body', 2), 'twofa': ('body', 4), 'login': ('footer', 3), 'quit': ('footer', 1), } super().__init__(self.frame)
def __init__(self): self.header = Header("") self.body = Body() self.footer = Footer("", 0, 1) self.frame = Frame(self.body, header=self.header, footer=self.footer) self.progress_current = 0 self.progress_completion = 0 super().__init__(Color.body(self.frame))
def __init__(self, app, clouds, cb): self.app = app self.cb = cb self.clouds = clouds self.config = self.app.config self.buttons_pile_selected = False self.frame = Frame(body=self._build_widget(), footer=self._build_footer()) super().__init__(self.frame)
def __init__(self, choice_callback=None, command_callback=None, help_callback=None): self.palette = [ ('brick', 'light red', 'black'), ('rubble', 'yellow', 'black'), ('wood', 'light green', 'black'), ('concrete', 'white', 'black'), ('stone', 'light cyan', 'black'), ('marble', 'light magenta', 'black'), ('jack', 'dark gray', 'white'), ('msg_info', 'white', 'black'), ('msg_err', 'light red', 'black'), ('msg_debug', 'light green', 'black'), ] self.choice_callback = choice_callback self.command_callback = command_callback self.help_callback = help_callback self.screen = None self.loop = None self.called_loop_stop = False self.reactor_stop_fired = False self.quit_flag = False self.edit_msg = "Make selection ('q' to quit): " self.roll_list = SimpleListWalker([]) self.game_log_list = SimpleListWalker([]) self.choices_list = SimpleListWalker([]) self.state_text = SimpleListWalker([Text('Connecting...')]) self.edit_widget = Edit(self.edit_msg) self.roll = ListBox(self.roll_list) self.game_log = ListBox(self.game_log_list) self.choices = ListBox(self.choices_list) self.state = ListBox(self.state_text) self.left_frame = Pile([ LineBox(self.state), (13, LineBox(self.choices)), ]) self.right_frame = Pile([LineBox(self.game_log), LineBox(self.roll)]) self.state.set_focus(len(self.state_text) - 1) self.columns = Columns([('weight', 0.75, self.left_frame), ('weight', 0.25, self.right_frame)]) self.frame_widget = Frame(footer=self.edit_widget, body=self.columns, focus_part='footer') self.exc_info = None
def __init__(self, start_date=None, end_date=None, period=None):#{{{ self.period = period if start_date is None: start_date = period + relativedelta(day=1) self.start_date = start_date if end_date is None: end_date = period + relativedelta(day=31) self.end_date = end_date title = "Subdiario de ventas" if period: stitle = " (periodo %s)" % period.strftime("%m/%Y") else: stitle = " (%s - %s)" % (start_date.strftime("%d/%m/%Y"), end_date.strftime("%d/%m/%Y")) list_header = Columns([ ('fixed', 2, Divider()), ('fixed', 3, Text(u"Tip", align='center')), ('fixed', 6, Text(u"Número", align='center')), Text(u"Razón Social", align='left'), ('fixed', 5, Text(u"Hora", align='left')), ('fixed', 3, Text(u"Ven", align='right')), ('fixed', 6, Text(u"Impues", align='right')), ('fixed', 6, Text(u"Descue", align='right')), ('fixed', 9, Text(u"Total".upper(), align='right')), ], dividechars=1) title_row = [('listado.title.important', title), stitle] header_row = [ AttrMap(Text(title_row, align='center', wrap='clip'), 'listado.title'), AttrMap(list_header, 'listado.list_header'), ] header = Pile(header_row) footer = Text("Calculando ...") self.short_footer = None self.large_footer = None self._current_footer = 0 query = session.query(Documento.fecha).filter(Documento.fecha.between(start_date, end_date))\ .order_by(Documento.fecha).distinct() treestore = TreeListWalker([DateNode(k[0]) for k in query]) treebox = TreeListBox(treestore) self.content = Frame( AttrMap(treebox, 'listado.body'), header=header, footer=AttrMap(footer, 'listado.footer')) self.configure_subprocess() self.__super.__init__(self.content, height=('relative', 100), width=('relative', 100), with_border=False)
def start(config): """Start the application and handle user input. Blocks until the application exits.""" def item_chosen(button, server): global choice choice = server response = Text( [u'Connecting to: ', server.connection_string(), u'\n']) done = Button(u'Ok') urwid.connect_signal(done, 'click', exit_program) main.original_widget = Filler( Pile([response, AttrMap(done, None, focus_map='reversed')])) def exit_program(button): raise urwid.ExitMainLoop() def unhandled(key): vim_map = {'h': 'left', 'j': 'down', 'k': 'up', 'l': 'right'} if key in vim_map.keys(): list_box.keypress((0, 1), vim_map[key]) elif key in ['left', 'right']: pass elif key in ['esc', 'q']: raise ExitMainLoop() body = [urwid.Text(u'\nServers'), Divider(u'-')] for server in config.get_servers(): button = Button(server.name) urwid.connect_signal(button, 'click', item_chosen, server) body.append(AttrMap(button, None, focus_map='reversed')) list_box = ListBox(urwid.SimpleFocusListWalker(body)) main = Padding(list_box, left=2, right=2) overlay = Overlay(main, SolidFill(u'\N{MEDIUM SHADE}'), align='center', width=('relative', 60), valign='middle', height=('relative', 60), min_width=20, min_height=9) header = AttrMap(Text(u' ssh-menu'), 'header') footer = AttrMap(Text(u'this is the footer'), 'footer') frame = Frame(overlay, header=header, footer=footer) urwid.MainLoop(urwid.AttrMap(frame, 'body'), palette=palette, unhandled_input=unhandled).run() return choice
def __init__(self): self._editor = None # header header = TabsWidget() # body body = Banner() # footer self._status_bar = configuration.styles.get('status_bar', False) if self._status_bar: footer = StatusBar('') else: footer = None self.frame = Frame(body, header=header, footer=footer) WidgetWrap.__init__(self, self.frame)
def keypress(self, size, key): """ Signal binding for NodeViewMode Keys: * F5 - Refreshes the node list """ if key == 'f5': self.ticks_left = 0 return Frame.keypress(self, size, key)
def __init__(self, app, models, cb): self.app = app self.cb = cb self.controllers = models.keys() self.models = models self.config = self.app.config self.buttons_pile_selected = False self.frame = Frame(body=self._build_widget(), footer=self._build_footer()) super().__init__(self.frame)
def __init__(self, body): TUI.root = Frame(body.root, Text(("header", ""), "center"), Text(TUI.main_helper_text, "center")) TUI.loop = MainLoop(TUI.root, TUI.palette, unhandled_input=TUI.unhandled_input) TUI.install_signals_handler()
def build_widgets(self): self.services_column = ServicesColumn(self.display_controller, self.placement_controller, self) self.machines_column = MachinesColumn(self.display_controller, self.placement_controller, self) self.relations_column = RelationsColumn(self.display_controller, self.placement_controller, self, self.metadata_controller) self.charmstore_column = CharmstoreColumn(self.display_controller, self.placement_controller, self, self.metadata_controller) self.options_column = OptionsColumn(self.display_controller, self.placement_controller, self, self.metadata_controller) self.machines_header = self.get_machines_header(self.machines_column) self.relations_header = self.get_relations_header() self.services_header = self.get_services_header() self.charmstore_header = self.get_charmstore_header( self.charmstore_column) self.options_header = self.get_options_header(self.options_column) cs = [self.services_header, self.charmstore_header] self.header_columns = Columns(cs, dividechars=2) self.columns = Columns([self.services_column, self.machines_column], dividechars=2) self.deploy_button = MenuSelectButton("\nCommit\n", on_press=self.do_deploy) self.deploy_button_label = Text("Some charms use default") self.placement_edit_body_pile = Pile([self.columns]) self.placement_edit_body = Filler(Padding( self.placement_edit_body_pile, align='center', width=('relative', 95)), valign='top') self.bundle_graph_text = Text("No graph to display yet.") self.bundle_graph_widget = Padding(self.bundle_graph_text, 'center', 'pack') b = AttrMap(self.deploy_button, 'frame_header', 'button_primary focus') self.footer_grid = GridFlow( [self.deploy_button_label, Padding(b, width=28, align='center')], 28, 1, 1, 'right') f = AttrMap(self.footer_grid, 'frame_footer', 'frame_footer') self.frame = Frame(header=Pile([self.header_columns, HR()]), body=self.placement_edit_body, footer=f) return self.frame
def __init__(self, parser): self.parser = parser self.find = {'ref': '', 'text': ''} self.isolate_filter = (None, None) self.line_collection = None self.jump_stack = [] self.expansions = {} self.show_sip_level = 2 self.show_ladder = False self.show_only_filtered = False self.show_verbose = True self.show_channel = True self.line_no_before_isolate = 0 self.showing_help = False self.walker = LogLineWalker([('Select call on the left side', None)], self.jump, self.expand, self.isolate) self.header = AttrWrap(Text([('key', 'F6'), ' Log']), 'bar') self.listbox = ListBox(self.walker) self.frame = Frame(self.listbox, header=self.header)
def __init__(self, nickname): self.nickname = nickname self.output = ChatMessages(self) self.message = ChatInput(self) self.window = Frame( body=self.output, footer=self.message, focus_part='footer' ) self.main_loop = None self.connection = Connection(self)
def __init__(self, app, clouds, cb=None): self.app = app self.cb = cb self.clouds = clouds self.blacklist = parse_blacklist() self.whitelist = parse_whitelist() self.config = self.app.config self.buttons_pile_selected = False self.frame = Frame(body=self._build_widget(), footer=self._build_footer()) super().__init__(self.frame)
def __init__(self, back=None): """Create a new instance of this view. :param back: Callback to invoke when the BACK button is selected. If None, the BACK button will be hidden. """ self.back = back self.frame = Frame(body=self._build_body(), footer=self._build_footer()) self.buttons_selected = False super().__init__(self.frame)
def __init__(self, app, spells, cb): self.app = app self.cb = cb self.spells = spells self.config = self.app.config self.frame = Frame(body=self._build_widget(), footer=self._build_footer()) self.buttons_pile_selected = False super().__init__(self.frame) self.handle_focus_changed()
def __init__(self, header=None, body=None, footer=None): _check_encoding() # Make sure terminal supports utf8 self.header = header if header else Header() self.body = body if body else Banner() self.footer = footer if footer else StatusBar('') self.frame = Frame(self.body, header=self.header, footer=self.footer) self.placement_view = None super().__init__(self.frame)
def __init__(self): self.header = Header("") self.footer = Footer("", 0, 1) self.frame = Frame(ListBox([Text("")]), header=self.header, footer=self.footer) self.progress_current = 0 self.progress_completion = 0 # After the install starts, we want to stop setting the footer # from the body view. self.auto_footer = True super().__init__(Color.body(self.frame))
def build(model, f, layout): footer = ['meta-', em('q'), 'uit/e', em('x'), 'it/', em('s'), 'ave'] footer += [' [shift]meta-'] for sep, c in enumerate('dwmya'): if sep: footer += ['/'] footer += [em(c)] footer += ['ctivity/', em('t'), 'oday'] active = defaultdict(list) branch = layout(model, f, active) return active, Border( Frame(Filler(branch, valign='top'), footer=Pile([Divider(), Text(footer, align='center')])))
def __init__(self, body=SolidFill(), header=None, footer=None, focus_part=None, unhandled_input=None, palette=None): self.document = Frame(body, header, footer, focus_part) self.loop = MainLoop( self.document, palette, event_loop=AsyncioEventLoop(loop=asyncio.get_event_loop()), unhandled_input=unhandled_input ) self.loop.screen.set_terminal_properties(colors=256) self.body = body self.footer = footer self.header = header
def __init__(self, configuration): self._configuration = configuration self._editor = None # header header = TabsWidget() # body body = Banner(configuration) # footer self._status_bar = configuration.styles.get('status_bar', False) if self._status_bar: footer = StatusBar('') else: footer = None Frame.__init__(self, body, header=header, footer=footer)
def __init__(self, track=None, clip=None): self.editing = clip or track self.header = Text( 'Editing clip {}'.format(clip.name) if clip else 'Adding new clip to {}'.format(track.name) if track else 'Editor') self.widgets = [EditorWidget(name, label, default) for name, label, default in self.editing.get_fields()] \ if self.editing else [] self.body = ListBox(SimpleFocusListWalker(self.widgets)) WidgetWrap.__init__(self, Frame(self.body, self.header))
def __init__(self, tui): self.tui = tui self.header_str = "Q:quit q:previous L:log" self.header = Text(self.header_str) self.body = Pile([]) self.footer = Text("No messages") self.footerpile = Pile([self.footer]) self.frame = Frame(self.body, AttrMap(self.header, 'status'), AttrMap(self.footerpile, 'status'), 'body') urwid.WidgetWrap.__init__(self, self.frame) self.hotkeys = {} ## key:func self.add_hotkey(':', self.start_prompt, 'cmd') self.add_hotkey('u', self.sync, 'sync')
def __init__(self, header=None, body=None, footer=None): _check_encoding() # Make sure terminal supports utf8 cb = self.show_exception_message utils.register_async_exception_callback(cb) self.header = header if header else Header() self.body = body if body else Banner() self.footer = footer if footer else StatusBar("") self.frame = Frame(self.body, header=self.header, footer=self.footer) self.services_view = None self.placement_view = None self.controller = None self.machine_wait_view = None self.add_services_dialog = None super().__init__(self.frame)
def __init__(self): self._editor = None # header header = TabsWidget() # body body = Banner() # footer self._status_bar = configuration.styles.get("status_bar", False) if self._status_bar: footer = StatusBar("") else: footer = None self.frame = Frame(body, header=header, footer=footer) super(CursesInterface, self).__init__(self.frame)
def __init__(self, title=None, stitle=None, list_header=None):#{{{ self._check_methods() query = self.build_query() max_rows = self.build_max_rows() self.walker = QueryWalker(query, self.formatter, max_rows, self.row_adapter, self.result_callback) querylist = ListBox(self.walker) header_row = [] title_row = [] if title: title_row.append(('listado.title.important', title)) if stitle: title_row.append(stitle) if len(title_row) > 0: header_row.append(AttrMap(Text(title_row, align='center', wrap='clip'), 'listado.title')) if list_header: header_row.append(AttrMap(list_header, 'listado.list_header')) if len(header_row) > 0: header = Pile(header_row) else: header = None footer = Text("Calculando ...") self.short_footer = None self.large_footer = None self._current_footer = 0 self.content = Frame( AttrMap(querylist, 'listado.body'), header=header, footer=AttrMap(footer, 'listado.footer')) self.__super.__init__(self.content, height=('relative', 100), width=('relative', 100), with_border=False)
def __init__(self, configuration): self._configuration = configuration self._editor = None # header header = TabsWidget() # body body = Banner(configuration) # footer self._status_bar = configuration.styles.get("status_bar", False) if self._status_bar: footer = StatusBar("") else: footer = None self.frame = Frame(body, header=header, footer=footer) WidgetWrap.__init__(self, self.frame)
def __init__(self, header_text): self._contents = SimpleListWalker([]) body = ListBox(self._contents) Frame.__init__(self, header=Columns(header_text), body=body)
class PegasusGUI(WidgetWrap): key_conversion_map = {'tab': 'down', 'shift tab': 'up'} def __init__(self, header=None, body=None, footer=None): self.header = header if header else Header() self.body = body if body else Banner() self.footer = footer if footer else StatusBarWidget() self.frame = Frame(self.body, header=self.header, footer=self.footer) self.services_view = None self.placement_view = None self.controller = None self.machine_wait_view = None self.node_install_wait_view = None self.add_services_dialog = None super().__init__(self.frame) def keypress(self, size, key): key = self.key_conversion_map.get(key, key) return super().keypress(size, key) def focus_next(self): if hasattr(self.frame.body, 'scroll_down'): self.frame.body.scroll_down() def focus_previous(self): if hasattr(self.frame.body, 'scroll_up'): self.frame.body.scroll_up() def focus_first(self): if hasattr(self.frame.body, 'scroll_top'): self.frame.body.scroll_top() def focus_last(self): if hasattr(self.frame.body, 'scroll_bottom'): self.frame.body.scroll_bottom() def show_help_info(self): self.controller = self.frame.body self.frame.body = HelpView() def show_step_info(self, msg): self.frame.body = StepInfoView(msg) def show_selector_with_desc(self, title, opts, cb): self.frame.body = SelectorWithDescriptionWidget(title, opts, cb) def show_password_input(self, title, cb): self.frame.body = PasswordInput(title, cb) def show_maas_input(self, title, cb): self.frame.body = MaasServerInput(title, cb) def show_landscape_input(self, title, cb): self.frame.body = LandscapeInput(title, cb) def set_pending_deploys(self, pending_charms): self.frame.footer.set_pending_deploys(pending_charms) def status_message(self, text): self.frame.footer.message(text) self.frame.set_footer(self.frame.footer) def status_error_message(self, message): self.frame.footer.error_message(message) def status_info_message(self, message): self.frame.footer.info_message( "{}\N{HORIZONTAL ELLIPSIS}".format(message)) def set_openstack_rel(self, release): self.frame.header.set_openstack_rel(release) def clear_status(self): self.frame.footer = None self.frame.set_footer(self.frame.footer) def render_services_view(self, nodes, juju_state, maas_state, config): self.services_view = ServicesView(nodes, juju_state, maas_state, config) self.frame.body = self.services_view self.header.set_show_add_units_hotkey(True) self.update_phase_status(config) def refresh_services_view(self, nodes, config): self.services_view.refresh_nodes(nodes) self.update_phase_status(config) def update_phase_status(self, config): dc = config.getopt('deploy_complete') dcstr = "complete" if dc else "pending" rc = config.getopt('relations_complete') rcstr = "complete" if rc else "pending" ppc = config.getopt('postproc_complete') ppcstr = "complete" if ppc else "pending" self.status_info_message("Status: Deployments {}, " "Relations {}, " "Post-processing {} ".format(dcstr, rcstr, ppcstr)) def render_node_install_wait(self, message): if self.node_install_wait_view is None: self.node_install_wait_view = NodeInstallWaitView(message) self.frame.body = self.node_install_wait_view def render_placement_view(self, loop, config, cb): """ render placement view :param cb: deploy callback trigger """ if self.placement_view is None: assert self.controller is not None pc = self.controller.placement_controller self.placement_view = PlacementView(self, pc, loop, config, cb) self.placement_view.update() self.frame.body = self.placement_view def render_machine_wait_view(self, config): if self.machine_wait_view is None: self.machine_wait_view = MachineWaitView( self, self.current_installer, config) self.machine_wait_view.update() self.frame.body = self.machine_wait_view def render_add_services_dialog(self, deploy_cb, cancel_cb): def reset(): self.add_services_dialog = None def cancel(): reset() cancel_cb() def deploy(): reset() deploy_cb() if self.add_services_dialog is None: self.add_services_dialog = AddServicesDialog(self.controller, deploy_cb=deploy, cancel_cb=cancel) self.add_services_dialog.update() self.frame.body = Filler(self.add_services_dialog) def show_exception_message(self, ex): if isinstance(ex, async.ThreadCancelledException): log.debug("Thread cancelled intentionally.") else:
class PegasusGUI(WidgetWrap): key_conversion_map = {'tab': 'down', 'shift tab': 'up'} def __init__(self, header=None, body=None, footer=None): self.header = header if header else Header() self.body = body if body else Banner() self.footer = footer if footer else StatusBarWidget() self.frame = Frame(self.body, header=self.header, footer=self.footer) self.services_view = None self.placement_view = None self.controller = None self.machine_wait_view = None self.node_install_wait_view = None self.add_services_dialog = None super().__init__(self.frame) def keypress(self, size, key): key = self.key_conversion_map.get(key, key) return super().keypress(size, key) def focus_next(self): if hasattr(self.frame.body, 'scroll_down'): self.frame.body.scroll_down() def focus_previous(self): if hasattr(self.frame.body, 'scroll_up'): self.frame.body.scroll_up() def focus_first(self): if hasattr(self.frame.body, 'scroll_top'): self.frame.body.scroll_top() def focus_last(self): if hasattr(self.frame.body, 'scroll_bottom'): self.frame.body.scroll_bottom() def show_help_info(self): self.controller = self.frame.body self.frame.body = HelpView() def show_step_info(self, msg): self.frame.body = StepInfoView(msg) def show_selector_with_desc(self, title, opts, cb): self.frame.body = SelectorWithDescriptionWidget(title, opts, cb) def show_password_input(self, title, cb): self.frame.body = PasswordInput(title, cb) def show_maas_input(self, title, cb): self.frame.body = MaasServerInput(title, cb) def show_landscape_input(self, title, cb): self.frame.body = LandscapeInput(title, cb) def set_pending_deploys(self, pending_charms): self.frame.footer.set_pending_deploys(pending_charms) def status_message(self, text): self.frame.footer.message(text) self.frame.set_footer(self.frame.footer) def status_error_message(self, message): self.frame.footer.error_message(message) def status_info_message(self, message): self.frame.footer.info_message( "{}\N{HORIZONTAL ELLIPSIS}".format(message)) def set_openstack_rel(self, release): self.frame.header.set_openstack_rel(release) def clear_status(self): self.frame.footer = None self.frame.set_footer(self.frame.footer) def render_services_view(self, nodes, juju_state, maas_state, config): self.services_view = ServicesView(nodes, juju_state, maas_state, config) self.frame.body = self.services_view self.header.set_show_add_units_hotkey(True) self.update_phase_status(config) def refresh_services_view(self, nodes, config): self.services_view.refresh_nodes(nodes) self.update_phase_status(config) def update_phase_status(self, config): dc = config.getopt('deploy_complete') dcstr = "complete" if dc else "pending" rc = config.getopt('relations_complete') rcstr = "complete" if rc else "pending" ppc = config.getopt('postproc_complete') ppcstr = "complete" if ppc else "pending" self.status_info_message("Status: Deployments {}, " "Relations {}, " "Post-processing {} ".format(dcstr, rcstr, ppcstr)) def render_node_install_wait(self, message): if self.node_install_wait_view is None: self.node_install_wait_view = NodeInstallWaitView(message) self.frame.body = self.node_install_wait_view def render_placement_view(self, loop, config, cb): """ render placement view :param cb: deploy callback trigger """ if self.placement_view is None: assert self.controller is not None pc = self.controller.placement_controller self.placement_view = PlacementView(self, pc, loop, config, cb) self.placement_view.update() self.frame.body = self.placement_view def render_machine_wait_view(self, config): if self.machine_wait_view is None: self.machine_wait_view = MachineWaitView( self, self.current_installer, config) self.machine_wait_view.update() self.frame.body = self.machine_wait_view def render_add_services_dialog(self, deploy_cb, cancel_cb): def reset(): self.add_services_dialog = None def cancel(): reset() cancel_cb() def deploy(): reset() deploy_cb() if self.add_services_dialog is None: self.add_services_dialog = AddServicesDialog(self.controller, deploy_cb=deploy, cancel_cb=cancel) self.add_services_dialog.update() self.frame.body = Filler(self.add_services_dialog) def show_exception_message(self, ex): msg = ("A fatal error has occurred: {}\n".format(ex.args[0])) log.error(msg) self.frame.body = ErrorView(ex.args[0]) AlarmMonitor.remove_all() def select_install_type(self, install_types, cb): """ Dialog for selecting installation type """ self.show_selector_with_desc( 'Select the type of installation to perform', install_types, cb) def __repr__(self): return "<Ubuntu OpenStack Installer GUI Interface>" def tasker(self, loop, config): """ Interface with Tasker class :param loop: urwid.Mainloop :param dict config: config object """ return Tasker(self, loop, config) def exit(self, loop=None): """ Provide exit loop helper :param loop: Just a placeholder, exit with urwid. """ urwid.ExitMainLoop()
class PegasusGUI(WidgetWrap): def __init__(self, header=None, body=None, footer=None): _check_encoding() # Make sure terminal supports utf8 cb = self.show_exception_message utils.register_async_exception_callback(cb) self.header = header if header else Header() self.body = body if body else Banner() self.footer = footer if footer else StatusBar('') self.frame = Frame(self.body, header=self.header, footer=self.footer) self.services_view = None self.placement_view = None self.controller = None self.machine_wait_view = None self.add_services_dialog = None super().__init__(self.frame) def _build_overlay_widget(self, top_w, align, width, valign, height, min_width, min_height): return Overlay(top_w=Filler(top_w), bottom_w=self.frame, align=align, width=width, valign=valign, height=height, min_width=width, min_height=height) def show_widget_on_top(self, widget, width, height, align='center', valign='middle', min_height=0, min_width=0): """Show `widget` on top of :attr:`frame`.""" self._w = self._build_overlay_widget(top_w=widget, align=align, width=width, valign=valign, height=height, min_width=min_width, min_height=min_height) def focus_next(self): if hasattr(self.frame.body, 'scroll_down'): self.frame.body.scroll_down() def focus_previous(self): if hasattr(self.frame.body, 'scroll_up'): self.frame.body.scroll_up() def focus_first(self): if hasattr(self.frame.body, 'scroll_top'): self.frame.body.scroll_top() def focus_last(self): if hasattr(self.frame.body, 'scroll_bottom'): self.frame.body.scroll_bottom() def hide_widget_on_top(self): """Hide the topmost widget (if any).""" self._w = self.frame def show_help_info(self): widget = HelpScreen() self.show_widget_on_top(widget, width=80, height=22, align="center", valign="middle", min_height=10) def hide_help_info(self): self.hide_widget_on_top() def show_step_info(self, msg): self.hide_step_info() widget = StepInfo(msg) self.show_widget_on_top(widget, width=60, height=14, align="center", valign="middle", min_height=10) def hide_step_info(self): self.hide_widget_on_top() def show_selector_info(self, title, opts, cb): widget = Selector(title, opts, cb) self.show_widget_on_top(widget, width=50, height=10) def hide_selector_info(self): self.hide_widget_on_top() def show_selector_with_desc(self, title, opts, cb): widget = SelectorWithDescription(title, opts, cb) self.show_widget_on_top(widget, width=80, height=14) def hide_selector_with_desc(self): self.hide_widget_on_top() def show_fatal_error_message(self, msg, cb): w = InfoDialog(msg, cb) self.show_widget_on_top(w, width=50, height=20) def show_password_input(self, title, cb): widget = PasswordInput(title, cb) self.show_widget_on_top(widget, width=50, height=7) def hide_show_password_input(self): self.hide_widget_on_top() def show_maas_input(self, title, cb): widget = MaasServerInput(title, cb) self.show_widget_on_top(widget, width=50, height=10) def hide_show_maas_input(self): self.hide_widget_on_top() def show_dhcp_range(self, range_low, range_high, title, cb): widget = DhcpRangeInput(range_low, range_high, title, cb) self.show_widget_on_top(widget, width=50, height=10) def hide_show_dhcp_range(self): self.hide_widget_on_top() def show_landscape_input(self, title, cb): widget = LandscapeInput(title, cb) self.show_widget_on_top(widget, width=50, height=9) def hide_show_landscape_input(self): self.hide_widget_on_top() def set_pending_deploys(self, pending_charms): self.frame.footer.set_pending_deploys(pending_charms) def flash(self, msg): self.frame.body.flash("{}\N{HORIZONTAL ELLIPSIS}".format(msg)) def flash_reset(self): self.frame.body.flash_reset() def status_message(self, text): self.frame.footer.message(text) self.frame.set_footer(self.frame.footer) def status_error_message(self, message): self.frame.footer.error_message(message) def status_info_message(self, message): self.frame.footer.info_message( "{}\N{HORIZONTAL ELLIPSIS}".format(message)) def set_dashboard_url(self, ip, user, password): self.frame.footer.set_dashboard_url(ip, user, password) def set_jujugui_url(self, ip): self.frame.footer.set_jujugui_url(ip) def set_openstack_rel(self, text): self.frame.footer.set_openstack_rel(text) def clear_status(self): self.frame.footer = None self.frame.set_footer(self.frame.footer) def render_services_view(self, nodes, juju_state, maas_state, config, **kwargs): if self.services_view is None: self.services_view = ServicesView(nodes, juju_state, maas_state, config) self.services_view.update(nodes) self.frame.set_body(self.services_view) self.header.set_show_add_units_hotkey(True) def render_node_install_wait(self, message=None, **kwargs): self.frame.body = NodeInstallWaitMode(message, **kwargs) self.frame.set_body(self.frame.body) def render_placement_view(self, loop, config, cb): """ render placement view :param cb: deploy callback trigger """ if self.placement_view is None: assert self.controller is not None pc = self.controller.placement_controller self.placement_view = PlacementView(self, pc, loop, config, cb) self.placement_view.update() self.frame.body = self.placement_view def render_machine_wait_view(self, config): if self.machine_wait_view is None: self.machine_wait_view = MachineWaitView( self, self.current_installer, config) self.machine_wait_view.update() self.frame.body = self.machine_wait_view def render_add_services_dialog(self, deploy_cb, cancel_cb): def reset(): self.add_services_dialog = None def cancel(): reset() cancel_cb() def deploy(): reset() deploy_cb() if self.add_services_dialog is None: self.add_services_dialog = AddServicesDialog(self.controller, deploy_cb=deploy, cancel_cb=cancel) self.add_services_dialog.update() self.frame.body = Filler(self.add_services_dialog) def show_exception_message(self, ex, logpath="~/.cloud-install/commands"): def handle_done(*args, **kwargs): raise urwid.ExitMainLoop() self.hide_widget_on_top() msg = ("A fatal error has occurred: {}\n" "See {} for further info.".format(ex.args[0], logpath)) self.show_fatal_error_message(msg, handle_done) def select_install_type(self, install_types, cb): """ Dialog for selecting installation type """ self.status_info_message("Choose your installation path") self.show_selector_with_desc('Install Type', install_types, cb) def select_maas_type(self, cb): """ Perform multi install based on existing MAAS or if a new MAAS will be installed """ self.status_info_message( "If a MAAS exists please enter the Server IP and your " "administrator's API Key. Otherwise leave blank and a new " "MAAS will be created for you") self.show_maas_input("MAAS Setup", cb) def __repr__(self): return "<Ubuntu OpenStack Installer GUI Interface>" def tasker(self, loop, config): """ Interface with Tasker class :param loop: urwid.Mainloop :param dict config: config object """ return Tasker(self, loop, config) def exit(self, loop=None): """ Provide exit loop helper :param loop: Just a placeholder, exit with urwid. """ urwid.ExitMainLoop()
class SubDiarioVentasTree(Dialog):#{{{ def __init__(self, start_date=None, end_date=None, period=None):#{{{ self.period = period if start_date is None: start_date = period + relativedelta(day=1) self.start_date = start_date if end_date is None: end_date = period + relativedelta(day=31) self.end_date = end_date title = "Subdiario de ventas" if period: stitle = " (periodo %s)" % period.strftime("%m/%Y") else: stitle = " (%s - %s)" % (start_date.strftime("%d/%m/%Y"), end_date.strftime("%d/%m/%Y")) list_header = Columns([ ('fixed', 2, Divider()), ('fixed', 3, Text(u"Tip", align='center')), ('fixed', 6, Text(u"Número", align='center')), Text(u"Razón Social", align='left'), ('fixed', 5, Text(u"Hora", align='left')), ('fixed', 3, Text(u"Ven", align='right')), ('fixed', 6, Text(u"Impues", align='right')), ('fixed', 6, Text(u"Descue", align='right')), ('fixed', 9, Text(u"Total".upper(), align='right')), ], dividechars=1) title_row = [('listado.title.important', title), stitle] header_row = [ AttrMap(Text(title_row, align='center', wrap='clip'), 'listado.title'), AttrMap(list_header, 'listado.list_header'), ] header = Pile(header_row) footer = Text("Calculando ...") self.short_footer = None self.large_footer = None self._current_footer = 0 query = session.query(Documento.fecha).filter(Documento.fecha.between(start_date, end_date))\ .order_by(Documento.fecha).distinct() treestore = TreeListWalker([DateNode(k[0]) for k in query]) treebox = TreeListBox(treestore) self.content = Frame( AttrMap(treebox, 'listado.body'), header=header, footer=AttrMap(footer, 'listado.footer')) self.configure_subprocess() self.__super.__init__(self.content, height=('relative', 100), width=('relative', 100), with_border=False) #}}} def keypress(self, key):#{{{ if key in ('enter', 'esc', ' ', 'f10'): self.quit() elif key in ('v', 'V'): self.switch_footer() return self.__super.keypress(key) #}}} def switch_footer(self):#{{{ if self.large_footer and self.short_footer: self.content.set_footer((self.short_footer, self.large_footer)[self._current_footer]) self._current_footer = 1 - (1 * self._current_footer) #}}} def run(self):#{{{ message_waiter(u" Procesando información ... ") self._subprocess.start() return self.__super.run() #}}} def configure_subprocess(self):#{{{ self._subquery = session.query(Documento)\ .filter(Documento.fecha.between(self.start_date, self.end_date))\ #.filter(Documento.tipo.in_([u'FAC', u'FAA'])).order_by(Documento.fecha) self._qout = Queue() self._subprocess = Process(target=self.execute_query, args=(self._qout,)) #}}} def configure_subloop(self, loop):#{{{ self._loop = loop self._handle = loop.event_loop.watch_file(self._qout._reader, self.result_callback) #}}} def execute_query(self, qout):#{{{ from sqlalchemy import create_engine fresh_engine = create_engine(get_current_config().database_uri) self._subquery.session.bind = fresh_engine qout.put([(d.vendedor, d.total, d.tipo) for d in self._subquery]) qout.close() #}}} def result_callback(self):#{{{ result = self._qout.get() vend = get_current_config().vendedores data = defaultdict(lambda: defaultdict(list)) k0 = itemgetter(0) k1 = itemgetter(1) k2 = itemgetter(2) cols = (u'FAC+FAA', u'REM', u'PRE') for vcode, docs in groupby(sorted(result, key=k0), key=k0): vname = vend[vcode]['nombre'] if vcode in vend else vcode for dtype, docs in groupby(sorted(docs, key=k2), key=k2): data[vname][dtype].extend(map(k1, docs)) _totals_by_type = defaultdict(int) for vname, dtype in data.iteritems(): dtype[u'FAC+FAA'] = dtype.get(u'FAC', []) + dtype.get(u'FAA', []) for c in cols: _totals_by_type[c] = _totals_by_type[c] + len(dtype.get(c, [])) _totals_by_type = [(c, _totals_by_type[c]) for c in cols] _total_docs_row = ["Total documentos: ", ('listado.footer.important', "%s" % len(result)), " ("] for k, v in _totals_by_type: _total_docs_row.extend(["%s: " % k, ('listado.footer.important', "%d" % v), " "]) del _total_docs_row[-1] _total_docs_row.append(")") _total_docs_row = Text(_total_docs_row, wrap='clip') self.short_footer = AttrMap(Columns([ _total_docs_row, ('fixed', 3, Text([('listado.footer.important', "^^^")])), ], dividechars=1), 'listado.footer') def _t(e): return sum(e[1][u'FAC+FAA']) + Decimal('0.9')*sum(e[1][u'REM']) def _nozero(docs): return sum([sum(docs[c]) for c in cols]) > 0 _totals = sorted([(vname, docs) for vname, docs in data.iteritems() if _nozero(docs)], key=_t, reverse=True) large_items = [AttrMap(Columns([Text(u'', wrap='clip')] + [ ('fixed', 11, Text(u'%s' % c, align='right')) for c in cols] + [ ('fixed', 5, Divider()), ], dividechars=1), 'listado.footer')] large_items.extend([AttrMap(Columns([Text(unicode(vname or '~')+u':', align='right')] + [ ('fixed', 11, AttrMap(Text("%11s" % moneyfmt(Decimal(sum(dtype[c]))), align='left', wrap='clip'), 'listado.footer.important')) for c in cols] + [ ('fixed', 5, Divider()), ], dividechars=1), 'listado.footer') for vname, dtype in _totals]) def _tot_col(col): return Decimal(sum([sum(dtype[col]) for _, dtype in _totals])) large_items.append(AttrMap(Columns([Text("Total:", align='right'),] + [ ('fixed', 11, AttrMap(Text("%11s" % moneyfmt(_tot_col(c)), align='left', wrap='clip'), 'listado.footer.important')) for c in cols ] + [ ('fixed', 5, Divider()), ], dividechars=1), 'listado.footer.key')) large_items.append(AttrMap(Columns([ _total_docs_row, ('fixed', 3, Text([('listado.footer.important', "vvv")])), ], dividechars=1), 'listado.footer')) self.large_footer = Pile(large_items) self.switch_footer() self._loop.event_loop.remove_watch_file(self._handle) self._loop.draw_screen()
class PegasusGUI(WidgetWrap): def __init__(self, header=None, body=None, footer=None): _check_encoding() # Make sure terminal supports utf8 self.header = header if header else Header() self.body = body if body else Banner() self.footer = footer if footer else StatusBar('') self.frame = Frame(self.body, header=self.header, footer=self.footer) self.placement_view = None super().__init__(self.frame) def _build_overlay_widget(self, top_w, align, width, valign, height, min_width, min_height): return Overlay(top_w=Filler(top_w), bottom_w=self.frame, align=align, width=width, valign=valign, height=height, min_width=width, min_height=height) def show_widget_on_top(self, widget, width, height, align='center', valign='middle', min_height=0, min_width=0): """Show `widget` on top of :attr:`frame`.""" self._w = self._build_overlay_widget(top_w=widget, align=align, width=width, valign=valign, height=height, min_width=min_width, min_height=min_height) def focus_next(self): self.frame.body.scroll_down() def focus_previous(self): self.frame.body.scroll_up() def focus_first(self): self.frame.body.scroll_top() def focus_last(self): self.frame.body.scroll_bottom() def hide_widget_on_top(self): """Hide the topmost widget (if any).""" self._w = self.frame def show_help_info(self): widget = HelpScreen() self.show_widget_on_top(widget, width=80, height=22, align="center", valign="middle", min_height=10) def hide_help_info(self): self.hide_widget_on_top() def show_step_info(self, msg, width=60, height=10): self.hide_step_info() widget = StepInfo(msg, height) self.show_widget_on_top(widget, width=width, height=height + 1, align="center", valign="middle", min_height=10) def hide_step_info(self): self.hide_widget_on_top() def show_selector_info(self, title, opts, cb): widget = Selector(title, opts, cb) self.show_widget_on_top(widget, width=50, height=10) def hide_selector_info(self): self.hide_widget_on_top() def show_fatal_error_message(self, msg, cb): w = InfoDialog(msg, cb) self.show_widget_on_top(w, width=50, height=20) def show_password_input(self, title, cb): widget = PasswordInput(title, cb) self.show_widget_on_top(widget, width=50, height=10) def hide_show_password_input(self): self.hide_widget_on_top() def show_maas_input(self, title, cb): widget = MaasServerInput(title, cb) self.show_widget_on_top(widget, width=50, height=10) def hide_show_maas_input(self): self.hide_widget_on_top() def show_dhcp_range(self, range_low, range_high, title, cb): widget = DhcpRangeInput(range_low, range_high, title, cb) self.show_widget_on_top(widget, width=50, height=10) def hide_show_dhcp_range(self): self.hide_widget_on_top() def show_landscape_input(self, title, cb): widget = LandscapeInput(title, cb) self.show_widget_on_top(widget, width=50, height=10) def hide_show_landscape_input(self): self.hide_widget_on_top() def show_add_charm_info(self, charms, cb): widget = AddCharmDialog(charms, cb) self.show_widget_on_top(widget, width=50, height=10) def hide_add_charm_info(self): self.hide_widget_on_top() def set_pending_deploys(self, pending_charms): self.frame.footer.set_pending_deploys(pending_charms) def status_message(self, text): self.frame.footer.message(text) self.frame.set_footer(self.frame.footer) def status_error_message(self, message): self.frame.footer.error_message(message) def status_info_message(self, message): self.frame.footer.info_message(message) def status_dashboard_url(self, ip): self.frame.footer.set_dashboard_url(ip) def status_jujugui_url(self, ip): self.frame.footer.set_jujugui_url(ip) def status_openstack_rel(self, text): self.frame.footer.set_openstack_rel(text) def clear_status(self): self.frame.footer = None self.frame.set_footer(self.frame.footer) def render_nodes(self, nodes, juju_state, maas_state, **kwargs): self.frame.body = NodeViewMode(nodes, juju_state, maas_state) self.frame.set_body(self.frame.body) self.header.set_show_add_units_hotkey(True) def render_node_install_wait(self, **kwargs): self.frame.body = NodeInstallWaitMode(**kwargs) self.frame.set_body(self.frame.body) def render_placement_view(self, display_controller, placement_controller): if self.placement_view is None: self.placement_view = PlacementView(display_controller, placement_controller) self.placement_view.update() self.frame.body = self.placement_view
class PegasusGUI(WidgetWrap): key_conversion_map = {"tab": "down", "shift tab": "up"} def __init__(self, header=None, body=None, footer=None): _check_encoding() # Make sure terminal supports utf8 cb = self.show_exception_message utils.register_async_exception_callback(cb) self.header = header if header else Header() self.body = body if body else Banner() self.footer = footer if footer else StatusBar("") self.frame = Frame(self.body, header=self.header, footer=self.footer) self.services_view = None self.placement_view = None self.controller = None self.machine_wait_view = None self.add_services_dialog = None super().__init__(self.frame) def keypress(self, size, key): key = self.key_conversion_map.get(key, key) return super().keypress(size, key) def _build_overlay_widget(self, top_w, align, width, valign, height, min_width, min_height): return Overlay( top_w=Filler(top_w), bottom_w=self.frame, align=align, width=width, valign=valign, height=height, min_width=width, min_height=height, ) def show_widget_on_top(self, widget, width, height, align="center", valign="middle", min_height=0, min_width=0): """Show `widget` on top of :attr:`frame`.""" self._w = self._build_overlay_widget( top_w=widget, align=align, width=width, valign=valign, height=height, min_width=min_width, min_height=min_height, ) def focus_next(self): if hasattr(self.frame.body, "scroll_down"): self.frame.body.scroll_down() def focus_previous(self): if hasattr(self.frame.body, "scroll_up"): self.frame.body.scroll_up() def focus_first(self): if hasattr(self.frame.body, "scroll_top"): self.frame.body.scroll_top() def focus_last(self): if hasattr(self.frame.body, "scroll_bottom"): self.frame.body.scroll_bottom() def hide_widget_on_top(self): """Hide the topmost widget (if any).""" self._w = self.frame def show_help_info(self): self.controller = self.frame.body self.frame.body = HelpScreen() def show_step_info(self, msg): self.frame.body = StepInfo(msg) def show_selector_with_desc(self, title, opts, cb): self.frame.body = SelectorWithDescription(title, opts, cb) def show_fatal_error_message(self, msg, cb): w = InfoDialog(msg, cb) self.show_widget_on_top(w, width=50, height=20) def show_password_input(self, title, cb): self.frame.body = PasswordInput(title, cb) def show_maas_input(self, title, cb): self.frame.body = MaasServerInput(title, cb) def show_landscape_input(self, title, cb): self.frame.body = LandscapeInput(title, cb) def set_pending_deploys(self, pending_charms): self.frame.footer.set_pending_deploys(pending_charms) def flash(self, msg): self.frame.body.flash("{}\N{HORIZONTAL ELLIPSIS}".format(msg)) def flash_reset(self): self.frame.body.flash_reset() def status_message(self, text): self.frame.footer.message(text) self.frame.set_footer(self.frame.footer) def status_error_message(self, message): self.frame.footer.error_message(message) def status_info_message(self, message): self.frame.footer.info_message("{}\N{HORIZONTAL ELLIPSIS}".format(message)) def set_dashboard_url(self, ip, user, password): self.frame.footer.set_dashboard_url(ip, user, password) def set_jujugui_url(self, ip): self.frame.footer.set_jujugui_url(ip) def set_openstack_rel(self, release): self.frame.header.set_openstack_rel(release) def clear_status(self): self.frame.footer = None self.frame.set_footer(self.frame.footer) def render_services_view(self, nodes, juju_state, maas_state, config, **kwargs): if self.services_view is None: self.services_view = ServicesView(nodes, juju_state, maas_state, config) self.services_view.update(nodes) self.frame.set_body(self.services_view) self.header.set_show_add_units_hotkey(True) dc = config.getopt("deploy_complete") dcstr = "complete" if dc else "pending" rc = config.getopt("relations_complete") rcstr = "complete" if rc else "pending" ppc = config.getopt("postproc_complete") ppcstr = "complete" if ppc else "pending" self.status_info_message( "Status: Deployments {}, " "Relations {}, " "Post-processing {} ".format(dcstr, rcstr, ppcstr) ) def render_node_install_wait(self, message=None, **kwargs): self.frame.body = NodeInstallWaitMode(message, **kwargs) def render_placement_view(self, loop, config, cb): """ render placement view :param cb: deploy callback trigger """ if self.placement_view is None: assert self.controller is not None pc = self.controller.placement_controller self.placement_view = PlacementView(self, pc, loop, config, cb) self.placement_view.update() self.frame.body = self.placement_view def render_machine_wait_view(self, config): if self.machine_wait_view is None: self.machine_wait_view = MachineWaitView(self, self.current_installer, config) self.machine_wait_view.update() self.frame.body = self.machine_wait_view def render_add_services_dialog(self, deploy_cb, cancel_cb): def reset(): self.add_services_dialog = None def cancel(): reset() cancel_cb() def deploy(): reset() deploy_cb() if self.add_services_dialog is None: self.add_services_dialog = AddServicesDialog(self.controller, deploy_cb=deploy, cancel_cb=cancel) self.add_services_dialog.update() self.frame.body = Filler(self.add_services_dialog) def show_exception_message(self, ex): msg = "A fatal error has occurred: {}\n".format(ex.args[0]) log.error(msg) self.frame.body = ErrorView(ex.args[0]) AlarmMonitor.remove_all() def select_install_type(self, install_types, cb): """ Dialog for selecting installation type """ self.show_selector_with_desc("Select the type of installation to perform", install_types, cb) def __repr__(self): return "<Ubuntu OpenStack Installer GUI Interface>" def tasker(self, loop, config): """ Interface with Tasker class :param loop: urwid.Mainloop :param dict config: config object """ return Tasker(self, loop, config) def exit(self, loop=None): """ Provide exit loop helper :param loop: Just a placeholder, exit with urwid. """ urwid.ExitMainLoop()
def exploreFieldSet(field_set, args, options={}): charset = getTerminalCharset() ui = urwid.curses_display.Screen() ui.register_palette(( ('focus', 'white', 'dark blue'), ('sep', 'white', 'dark red'), ('input', 'black', 'light gray'), )) msgs = [[],[],0] hachoir_log.use_print = False def logger(level, prefix, text, ctxt): if ctxt is not None: c = [] if hasattr(ctxt, "_logger"): c[:0] = [ ctxt._logger() ] if issubclass(ctxt.__class__, Field): ctxt = ctxt["/"] name = logger.objects.get(ctxt) if name: c[:0] = [ name ] if c: text = "[%s] %s" % ('|'.join(c), text) if not isinstance(text, unicode): text = unicode(text, charset) msgs[0].append((level, prefix, text)) logger.objects = WeakKeyDictionary() hachoir_log.on_new_message = logger preload_fields = 1 + max(0, args.preload) log_count = [ 0, 0, 0 ] sep = Separator("log: %%u/%%u/%%u | %s " % _("F1: help")) sep.set_info(*tuple(log_count)) body = Tabbed(sep) help = ('help', ListBox([ Text(getHelpMessage()) ])) logger.objects[field_set] = logger.objects[field_set.stream] = name = u'root' body.append((name, TreeBox(charset, Node(field_set, None), preload_fields, args.path, options))) log = BoxAdapter(ListBox(msgs[1]), 0) log.selectable = lambda: False wrapped_sep = AttrWrap(sep, 'sep') footer = Pile([ ('flow', wrapped_sep), log ]) # awful way to allow the user to hide the log widget log.render = lambda size, focus=False: BoxAdapter.render(log, size[:1], focus) footer.render = lambda (maxcol,), focus=False: Pile.render(footer, (maxcol, sep.rows((maxcol,))+log.height), focus) top = Frame(body, None, footer) def input_enter(w): footer.widget_list[0] = w footer.set_focus(0) top.set_focus('footer') def input_leave(): footer.widget_list[0] = wrapped_sep footer.set_focus(0) top.set_focus('body') input = Input(input_enter, input_leave) def run(): msg = _resize = retry = 0 events = ( "window resize", ) profile_display = args.profile_display while True: for e in events: try: if e == "window resize": size = ui.get_cols_rows() resize = log.height else: e = top.keypress(size, e) if e is None: pass elif e in ('f1', '?'): try: body.select(body.tabs.index(help)) except ValueError: body.append(help) resize = log.height elif e in ('esc', 'ctrl w'): body.close() if body.box_widget is None: return resize = log.height elif e == '+': if log.height: resize = log.height - 1 elif e == '-': resize = log.height + 1 elif e == 'q': return #except AssertionError: # hachoir_log.error(getBacktrace()) except NewTab_Stream, e: stream = e.field.getSubIStream() logger.objects[stream] = e = "%u/%s" % (body.active, e.field.absolute_address) parser = guessParser(stream) if not parser: hachoir_log.error(_("No parser found for %s") % stream.source) else: logger.objects[parser] = e body.append((e, TreeBox(charset, Node(parser, None), preload_fields, None, options))) resize = log.height except NeedInput, e: input.do(*e.args) if profile_display: events = events[1:] break while True: if msgs[0]: for level, prefix, text in msgs[0]: log_count[level] += 1 txt = Text("[%u]%s %s" % (msg, prefix, text)) msg += 1 msgs[1].append(txt) _resize += txt.rows(size[:1]) if log.height < _resize and (resize is None or resize < _resize): resize = _resize log.set_focus(len(msgs[1])-1) sep.set_info(*tuple(log_count)) msgs[0] = [] if resize is not None: body.height = size[1] - sep.rows(size[:1]) - resize if body.height <= 0: resize += body.height - 1 body.height = 1 log.height = resize resize = None canvas = top.render(size, focus=True) if not msgs[0]: _resize = retry = 0 break assert not retry retry += 1 ui.draw_screen(size, canvas) msgs[2] = len(msgs[1]) if profile_display and events: continue while True: events = ui.get_input() if events: break
class CursesInterface(WidgetWrap): """ Creates a curses interface for the program, providing functions to draw all the components of the UI. Provides a facade API to draw the representation of the :class:`~turses.models.TimelineList`, help :class:`HelpBuffer` and intro :class:`Banner` screens. """ def __init__(self): self._editor = None # header header = TabsWidget() # body body = Banner() # footer self._status_bar = configuration.styles.get('status_bar', False) if self._status_bar: footer = StatusBar('') else: footer = None self.frame = Frame(body, header=header, footer=footer) super(CursesInterface, self).__init__(self.frame) def _build_overlay_widget(self, top_w, align, width, valign, height, min_width, min_height): return Overlay(top_w=Filler(top_w), bottom_w=self.frame, align=align, width=width, valign=valign, height=height, min_width=width, min_height=height) # -- Modes ---------------------------------------------------------------- def draw_timelines(self, timelines): self.frame.body = TimelinesBuffer(timelines) self.frame.set_body(self.frame.body) def show_info(self): self.frame.header.clear() self.frame.body = Banner() self.frame.set_body(self.frame.body) def show_help(self): self.clear_header() self.status_info_message(_('type <esc> to leave the help page.')) self.frame.body = HelpBuffer() self.frame.set_body(self.frame.body) # -- Header --------------------------------------------------------------- def clear_header(self): self.frame.header.clear() def set_tab_names(self, names): self.frame.header.set_tabs(names) self.frame.set_header(self.frame.header) def activate_tab(self, index): self.frame.header.set_active_tab(index) self.frame.set_header(self.frame.header) def highlight_tabs(self, indexes): self.frame.header.set_visible_tabs(indexes) # -- Footer --------------------------------------------------------------- @property def can_write_status(self): if self._status_bar: if self.frame.footer is None: self.frame.footer = StatusBar('') return True return False def status_message(self, text): if self.can_write_status: self.frame.footer.message(text) self.frame.set_footer(self.frame.footer) def status_error_message(self, message): if self.can_write_status: self.frame.footer.error_message(message) def status_info_message(self, message): if self.can_write_status: self.frame.footer.info_message(message) def clear_status(self): self.frame.footer = None self.frame.set_footer(self.frame.footer) # -- Timeline mode -------------------------------------------------------- def focus_timeline(self, index): """Give focus to the `index`-th visible timeline.""" self.frame.body.focus_timeline(index) def focus_status(self, index): if callable(getattr(self.frame.body, 'set_focus', None)): self.frame.body.set_focus(index) def center_focus(self): if callable(getattr(self.frame.body, 'set_focus_valign', None)): logging.debug('centering focus') self.frame.body.set_focus_valign('middle') # -- motions -------------------------------------------------------------- def focus_next(self): self.frame.body.scroll_down() def focus_previous(self): self.frame.body.scroll_up() def focus_first(self): self.frame.body.scroll_top() def focus_last(self): self.frame.body.scroll_bottom() # -- editors -------------------------------------------------------------- def _show_editor(self, editor_cls, prompt, content, done_signal_handler, **kwargs): self._editor = editor_cls(prompt=prompt, content=content, done_signal_handler=done_signal_handler, **kwargs) styles = configuration.styles horizontal_align = styles['editor_horizontal_align'] vertical_align = styles['editor_vertical_align'] self.show_widget_on_top(widget=self._editor, width=80, height=5, align=horizontal_align, valign=vertical_align, min_height=5,) return self._editor def show_text_editor(self, prompt='', content='', done_signal_handler=None, cursor_position=None): return self._show_editor(TextEditor, prompt, content, done_signal_handler, cursor_position=cursor_position) def show_tweet_editor(self, prompt='', content='', done_signal_handler=None, cursor_position=None): return self._show_editor(TweetEditor, prompt, content, done_signal_handler, cursor_position=cursor_position) def show_dm_editor(self, prompt='', content='', recipient='', done_signal_handler=None): return self._show_editor(DmEditor, prompt, content, done_signal_handler, recipient=recipient,) def hide_editor(self, done_signal_handler): try: disconnect_signal(self._editor, 'done', done_signal_handler) except Exception, message: # `disconnect_signal` raises an exception if no signal was # connected from `self._editor`. we can safely ignore it. logging.exception(message) self._editor = None self.hide_widget_on_top()
class Listado(Dialog):#{{{ def __init__(self, title=None, stitle=None, list_header=None):#{{{ self._check_methods() query = self.build_query() max_rows = self.build_max_rows() self.walker = QueryWalker(query, self.formatter, max_rows, self.row_adapter, self.result_callback) querylist = ListBox(self.walker) header_row = [] title_row = [] if title: title_row.append(('listado.title.important', title)) if stitle: title_row.append(stitle) if len(title_row) > 0: header_row.append(AttrMap(Text(title_row, align='center', wrap='clip'), 'listado.title')) if list_header: header_row.append(AttrMap(list_header, 'listado.list_header')) if len(header_row) > 0: header = Pile(header_row) else: header = None footer = Text("Calculando ...") self.short_footer = None self.large_footer = None self._current_footer = 0 self.content = Frame( AttrMap(querylist, 'listado.body'), header=header, footer=AttrMap(footer, 'listado.footer')) self.__super.__init__(self.content, height=('relative', 100), width=('relative', 100), with_border=False) #}}} def _check_methods(self):#{{{ for meth in ('build_query', 'build_max_rows', 'formatter', 'row_adapter', 'result_callback'): method = getattr(self, meth, None) if not method: raise NotImplementedError("'%s' must be implemented in subclasses of Listado" % meth) if not callable(method): raise RuntimeError("'%s.%s' must be callable method to run properly" %\ (type(self).__name__, meth)) #}}} def keypress(self, key):#{{{ if key in ('enter', 'esc', ' ', 'f10'): self.quit() elif key in ('v', 'V'): self.switch_footer() return self.__super.keypress(key) #}}} def configure_subloop(self, subloop):#{{{ self.walker.connect_watcher(subloop) #}}} def quit(self, *args):#{{{ self.walker.stop_workers() return self.__super.quit(*args) #}}} def switch_footer(self):#{{{ if self.large_footer and self.short_footer: self.content.set_footer((self.short_footer, self.large_footer)[self._current_footer]) self._current_footer = 1 - (1 * self._current_footer) #}}} def run(self):#{{{ message_waiter(u" Procesando información ... ") return self.__super.run()
class PegasusGUI(WidgetWrap): def __init__(self): _check_encoding() # Make sure terminal supports utf8 header = Header() body = Banner() footer = StatusBar('') self.frame = Frame(body, header=header, footer=footer) super().__init__(self.frame) def _build_overlay_widget(self, top_w, align, width, valign, height, min_width, min_height): return Overlay(top_w=Filler(top_w), bottom_w=self.frame, align=align, width=width, valign=valign, height=height, min_width=width, min_height=height) def show_widget_on_top(self, widget, width, height, align='center', valign='middle', min_height=0, min_width=0): """Show `widget` on top of :attr:`frame`.""" self._w = self._build_overlay_widget(top_w=widget, align=align, width=width, valign=valign, height=height, min_width=min_width, min_height=min_height) def focus_next(self): self.frame.body.scroll_down() def focus_previous(self): self.frame.body.scroll_up() def focus_first(self): self.frame.body.scroll_top() def focus_last(self): self.frame.body.scroll_bottom() def hide_widget_on_top(self): """Hide the topmost widget (if any).""" self._w = self.frame def show_help_info(self): widget = HelpScreen() self.show_widget_on_top(widget, width=80, height=22, align="center", valign="middle", min_height=10) def hide_help_info(self): self.hide_widget_on_top() def show_step_info(self, msg=None): self.hide_step_info() widget = StepInfo(msg) self.show_widget_on_top(widget, width=50, height=3, align="center", valign="middle", min_height=10) def hide_step_info(self): self.hide_widget_on_top() def show_add_charm_info(self, charms, cb): widget = AddCharmDialog(charms, cb) self.show_widget_on_top(widget, width=50, height=10) def hide_add_charm_info(self): self.hide_widget_on_top() def set_pending_deploys(self, pending_charms): self.frame.footer.set_pending_deploys(pending_charms) def status_message(self, text): self.frame.footer.message(text) self.frame.set_footer(self.frame.footer) def status_error_message(self, message): self.frame.footer.error_message(message) def status_info_message(self, message): self.frame.footer.info_message(message) def status_dashboard_url(self, ip): self.frame.footer.set_dashboard_url(ip) def status_jujugui_url(self, ip): self.frame.footer.set_jujugui_url(ip) def clear_status(self): self.frame.footer = None self.frame.set_footer(self.frame.footer) def render_nodes(self, nodes, juju_state, maas_state, **kwargs): self.frame.body = NodeViewMode(nodes, juju_state, maas_state) self.frame.set_body(self.frame.body) def render_node_install_wait(self, **kwargs): self.frame.body = NodeInstallWaitMode() self.frame.set_body(self.frame.body)
class Client(Component): channel = "client" def init(self, host, port=6667, opts=None): self.host = host self.port = port self.opts = opts self.hostname = gethostname() self.nick = opts.nick self.ircchannel = opts.channel # Add TCPClient and IRC to the system. TCPClient(channel=self.channel).register(self) IRC(channel=self.channel).register(self) self.create_interface() def create_interface(self): self.screen = Screen() self.screen.start() self.screen.register_palette([ ("title", "white", "dark blue", "standout"), ("line", "light gray", "black"), ("help", "white", "dark blue")] ) self.body = ListBox(SimpleListWalker([])) self.lines = self.body.body self.title = Text(MAIN_TITLE) self.header = AttrWrap(self.title, "title") self.help = AttrWrap( Text(HELP_STRINGS["main"]), "help" ) self.input = Edit(caption="%s> " % self.ircchannel) self.footer = Pile([self.help, self.input]) self.top = Frame(self.body, self.header, self.footer) def ready(self, component): """Ready Event This event is triggered by the underlying ``TCPClient`` Component when it is ready to start making a new connection. """ self.fire(connect(self.host, self.port)) def connected(self, host, port): """connected Event This event is triggered by the underlying ``TCPClient`` Component when a successfully connection has been made. """ nick = self.nick hostname = self.hostname name = "%s on %s using circuits/%s" % (nick, hostname, systemVersion) self.fire(NICK(nick)) self.fire(USER(nick, hostname, host, name)) def numeric(self, source, numeric, *args): """Numeric Event This event is triggered by the ``IRC`` Protocol Component when we have received an IRC Numberic Event from server we are connected to. """ if numeric == ERR_NICKNAMEINUSE: self.fire(NICK("{0:s}_".format(args[0]))) elif numeric in (RPL_ENDOFMOTD, ERR_NOMOTD): self.fire(JOIN(self.ircchannel)) @handler("stopped", channel="*") def _on_stopped(self, component): self.screen.stop() @handler("generate_events") def _on_generate_events(self, event): event.reduce_time_left(0) size = self.screen.get_cols_rows() if not select( self.screen.get_input_descriptors(), [], [], 0.1)[0] == []: timeout, keys, raw = self.screen.get_input_nonblocking() for k in keys: if k == "window resize": size = self.screen.get_cols_rows() continue elif k == "enter": self.processCommand(self.input.get_edit_text()) self.input.set_edit_text("") continue self.top.keypress(size, k) self.input.set_edit_text(self.input.get_edit_text() + k) self.update_screen(size) def unknownCommand(self, command): self.lines.append(Text("Unknown command: %s" % command)) def syntaxError(self, command, args, expected): self.lines.append( Text("Syntax error ({0:s}): {1:s} Expected: {2:s}".format( command, args, expected) ) ) def processCommand(self, s): # noqa match = CMD_REGEX.match(s) if match is not None: command = match.groupdict()["command"] if not match.groupdict()["args"] == "": tokens = match.groupdict()["args"].split(" ") else: tokens = [] fn = "cmd" + command.upper() if hasattr(self, fn): f = getattr(self, fn) if callable(f): args, vargs, kwargs, default = getargspec(f) args.remove("self") if len(args) == len(tokens): if len(args) == 0: f() else: f(*tokens) else: if len(tokens) > len(args): if vargs is None: if len(args) > 0: factor = len(tokens) - len(args) + 1 f(*back_merge(tokens, factor)) else: self.syntaxError( command, " ".join(tokens), " ".join( x for x in args + [vargs] if x is not None ) ) else: f(*tokens) elif default is not None and \ len(args) == ( len(tokens) + len(default)): f(*(tokens + list(default))) else: self.syntaxError( command, " ".join(tokens), " ".join( x for x in args + [vargs] if x is not None ) ) else: if self.ircchannel is not None: self.lines.append(Text("<%s> %s" % (self.nick, s))) self.fire(PRIVMSG(self.ircchannel, s)) else: self.lines.append(Text( "No channel joined. Try /join #<channel>")) def cmdEXIT(self, message=""): self.fire(QUIT(message)) raise SystemExit(0) def cmdSERVER(self, host, port=6667): self.fire(connect(host, port)) def cmdSSLSERVER(self, host, port=6697): self.fire(connect(host, port, secure=True)) def cmdJOIN(self, channel): if self.ircchannel is not None: self.cmdPART(self.ircchannel, "Joining %s" % channel) self.fire(JOIN(channel)) self.ircchannel = channel def cmdPART(self, channel=None, message="Leaving"): if channel is None: channel = self.ircchannel if channel is not None: self.fire(PART(channel, message)) self.ircchannel = None def cmdQUOTE(self, message): self.fire(request(Message(message))) def cmdQUIT(self, message="Bye"): self.fire(QUIT(message)) def update_screen(self, size): canvas = self.top.render(size, focus=True) self.screen.draw_screen(size, canvas) @handler("notice", "privmsg") def _on_notice_or_privmsg(self, event, source, target, message): nick, ident, host = source if event.name == "notice": self.lines.append(Text("-%s- %s" % (nick, message))) else: self.lines.append(Text("<%s> %s" % (nick, message)))