Beispiel #1
0
    def __init__(self, executor_widgets):
        self.log_widget = ScrollingLog()

        self.latest_stats = LatestStats()
        self.cumulative_stats = CumulativeStats()

        stats_pane = Pile([(WEIGHT, 0.333, self.latest_stats),
                           (WEIGHT, 0.667, self.cumulative_stats)])

        self.graphs = ThreeGraphs()
        self.logo = TaurusLogo()

        ordered_widgets = sorted(executor_widgets, key=lambda x: x.priority)
        right_widgets = ListBox(
            SimpleListWalker([Pile([x, Divider()]) for x in ordered_widgets]))
        widget_pile = Pile([
            (7, self.logo),
            right_widgets,
        ])

        log_block = Pile([(1, Filler(Divider('─'))), self.log_widget])

        right_pane = Pile([(WEIGHT, 0.667, widget_pile),
                           (WEIGHT, 0.333, log_block)])

        columns = [(WEIGHT, 0.25, self.graphs), (WEIGHT, 0.50, stats_pane),
                   (WEIGHT, 0.25, right_pane)]
        super(TaurusConsole, self).__init__(columns)
Beispiel #2
0
    def __init__(self,
                 original_widget,
                 title="",
                 tlcorner=u'┌',
                 tline=u'─',
                 lline=u'│',
                 trcorner=u'┐',
                 blcorner=u'└',
                 rline=u'│',
                 bline=u'─',
                 brcorner=u'┘'):
        """
        Draw a line around original_widget.

        Use 'title' to set an initial title text with will be centered
        on top of the box.

        You can also override the widgets used for the lines/corners:
            tline: top line
            bline: bottom line
            lline: left line
            rline: right line
            tlcorner: top left corner
            trcorner: top right corner
            blcorner: bottom left corner
            brcorner: bottom right corner

        """

        tline, bline = Divider(tline), Divider(bline)
        lline, rline = SolidFill(lline), SolidFill(rline)
        tlcorner, trcorner = Text(tlcorner), Text(trcorner)
        blcorner, brcorner = Text(blcorner), Text(brcorner)

        self.title_widget = Text(self.format_title(title))
        self.tline_widget = Columns([
            tline,
            ('flow', self.title_widget),
            tline,
        ])

        top = Columns([('fixed', 1, tlcorner), self.tline_widget,
                       ('fixed', 1, trcorner)])

        middle = Columns([
            ('fixed', 1, lline),
            original_widget,
            ('fixed', 1, rline),
        ],
                         box_columns=[0, 2],
                         focus_column=1)

        bottom = Columns([('fixed', 1, blcorner), bline,
                          ('fixed', 1, brcorner)])

        pile = Pile([('flow', top), middle, ('flow', bottom)], focus_item=1)

        WidgetDecoration.__init__(self, original_widget)
        WidgetWrap.__init__(self, pile)
Beispiel #3
0
    def generate_display_widget(self, size):
        """
        Actually generate display widget (ignoring cache)
        """
        (maxcol,) = size
        d = Divider()
        if len(self.cells) == 0: # how dull
            return d

        if self.v_sep > 1:
            # increase size of divider
            d.top = self.v_sep-1

        # cells per row
        bpr = (maxcol+self.h_sep) // (self.cell_width+self.h_sep)

        if bpr == 0: # too narrow, pile them on top of eachother
            l = [self.cells[0]]
            f = 0
            for b in self.cells[1:]:
                if b is self.focus_cell:
                    f = len(l)
                if self.v_sep:
                    l.append(d)
                l.append(b)
            return Pile(l, f)
        
        if bpr >= len(self.cells): # all fit on one row
            k = len(self.cells)
            f = self.cells.index(self.focus_cell)
            cols = Columns(self.cells, self.h_sep, f)
            rwidth = (self.cell_width+self.h_sep)*k - self.h_sep
            row = Padding(cols, self.align, rwidth)
            return row

        
        out = []
        s = 0
        f = 0
        while s < len(self.cells):
            if out and self.v_sep:
                out.append(d)
            k = min( len(self.cells), s+bpr )
            cells = self.cells[s:k]
            if self.focus_cell in cells:
                f = len(out)
                fcol = cells.index(self.focus_cell)
                cols = Columns(cells, self.h_sep, fcol)
            else:
                cols = Columns(cells, self.h_sep)
            rwidth = (self.cell_width+self.h_sep)*(k-s)-self.h_sep
            row = Padding(cols, self.align, rwidth)
            out.append(row)
            s += bpr
        return Pile(out, f)    
Beispiel #4
0
    def setup_popup(self, title):
        """
        Overlays a dialog box on top of the working view using a Frame
        """

        # Header
        if self.small_display:
            header = Padding(Text(title, align='center'))
        else:
            header = LineBox(Text(title),
                             tline=None,
                             rline=' ',
                             lline=' ',
                             trcorner=' ',
                             tlcorner=' ',
                             blcorner='',
                             brcorner='')

        header = AttrWrap(header, 'header')

        # Body
        error_text = Text("", align='center')
        # register the Text widget with the application, so we can change it
        self._error = error_text

        error_text = AttrWrap(error_text, 'error')
        body = Pile([
            Divider(), error_text,
            Divider(),
            LineBox(GridFlow([self.setup_button("Dismiss", self.close_popup)],
                             12, 2, 0, 'center'),
                    bline=None,
                    lline=None,
                    rline=None,
                    tlcorner='─',
                    trcorner='─')
        ])

        body = LineBox(body)
        body = AttrWrap(body, 'body')

        # on small displays let the popup fill the screen (horizontal)
        if self.small_display:
            body = Padding(Filler(body, 'middle'), 'center')
        else:
            body = Padding(Filler(body, 'middle'), 'center', ('relative', 50))

        body = AttrWrap(body, 'bg')

        # Main dialog widget
        dialog = Frame(body, header=header, focus_part='body')

        return dialog
Beispiel #5
0
    def __init__(self, sidebar_widgets):
        self.log_widget = ScrollingLog()

        self.latest_stats = LatestStats()
        self.cumulative_stats = CumulativeStats()

        stats_pane = Pile([(WEIGHT, 0.33, self.latest_stats),
                           (WEIGHT, 0.67, self.cumulative_stats), ])

        self.graphs = ThreeGraphs()

        right_widgets = ListBox(SimpleListWalker([Pile([x, Divider()]) for x in sidebar_widgets]))

        self.logo = TaurusLogo()
        right_pane = Pile([(10, self.logo),
                           right_widgets,
                           (1, Filler(Divider('─'))),
                           (WEIGHT, 1, self.log_widget)])

        columns = [(WEIGHT, 0.25, self.graphs),
                   (WEIGHT, 0.50, stats_pane),
                   (WEIGHT, 0.25, right_pane)]
        super(TaurusConsole, self).__init__(columns)
Beispiel #6
0
    def __init__(self, original_widget, title="",
                 title_align="center", title_attr=None,
                 tlcorner=u'┌', tline=u'─', lline=u'│',
                 trcorner=u'┐', blcorner=u'└', rline=u'│',
                 bline=u'─', brcorner=u'┘'):
        """
        Draw a line around original_widget.

        Use 'title' to set an initial title text with will be centered
        on top of the box.

        Use `title_attr` to apply a specific attribute to the title text.

        Use `title_align` to align the title to the 'left', 'right', or 'center'.
        The default is 'center'.

        You can also override the widgets used for the lines/corners:
            tline: top line
            bline: bottom line
            lline: left line
            rline: right line
            tlcorner: top left corner
            trcorner: top right corner
            blcorner: bottom left corner
            brcorner: bottom right corner

        If empty string is specified for one of the lines/corners, then no
        character will be output there.  This allows for seamless use of
        adjoining LineBoxes.
        """

        if tline:
            tline = Divider(tline)
        if bline:
            bline = Divider(bline)
        if lline:
            lline = SolidFill(lline)
        if rline:
            rline = SolidFill(rline)
        tlcorner, trcorner = Text(tlcorner), Text(trcorner)
        blcorner, brcorner = Text(blcorner), Text(brcorner)

        if not tline and title:
            raise ValueError('Cannot have a title when tline is empty string')

        if title_attr:
            self.title_widget = Text((title_attr, self.format_title(title)))
        else:
            self.title_widget = Text(self.format_title(title))

        if tline:
            if title_align not in ('left', 'center', 'right'):
                raise ValueError('title_align must be one of "left", "right", or "center"')
            if title_align == 'left':
                tline_widgets = [('flow', self.title_widget), tline]
            else:
                tline_widgets = [tline, ('flow', self.title_widget)]
                if title_align == 'center':
                    tline_widgets.append(tline)
            self.tline_widget = Columns(tline_widgets)
            top = Columns([
                ('fixed', 1, tlcorner),
                self.tline_widget,
                ('fixed', 1, trcorner)
            ])

        else:
            self.tline_widget = None
            top = None

        middle_widgets = []
        if lline:
            middle_widgets.append(('fixed', 1, lline))
        else:
            # Note: We need to define a fixed first widget (even if it's 0 width) so that the other
            # widgets have something to anchor onto
            middle_widgets.append(('fixed', 0, SolidFill(u"")))
        middle_widgets.append(original_widget)
        focus_col = len(middle_widgets) - 1
        if rline:
            middle_widgets.append(('fixed', 1, rline))

        middle = Columns(middle_widgets,
                box_columns=[0, 2], focus_column=focus_col)

        if bline:
            bottom = Columns([
                ('fixed', 1, blcorner), bline, ('fixed', 1, brcorner)
            ])
        else:
            bottom = None

        pile_widgets = []
        if top:
            pile_widgets.append(('flow', top))
        pile_widgets.append(middle)
        focus_pos = len(pile_widgets) - 1
        if bottom:
            pile_widgets.append(('flow', bottom))
        pile = Pile(pile_widgets, focus_item=focus_pos)

        WidgetDecoration.__init__(self, original_widget)
        WidgetWrap.__init__(self, pile)
Beispiel #7
0
    def __init__(self,
                 original_widget,
                 title="",
                 title_align="center",
                 tlcorner='┌',
                 tline='─',
                 lline='│',
                 trcorner='┐',
                 blcorner='└',
                 rline='│',
                 bline='─',
                 brcorner='┘'):
        """
        Draw a line around original_widget.
        Use 'title' to set an initial title text with will be centered
        on top of the box.
        Use `title_align` to align the title to the 'left', 'right', or 'center'.
        The default is 'center'.
        You can also override the widgets used for the lines/corners:
            tline: top line
            bline: bottom line
            lline: left line
            rline: right line
            tlcorner: top left corner
            trcorner: top right corner
            blcorner: bottom left corner
            brcorner: bottom right corner
        .. note:: This differs from the vanilla urwid LineBox by discarding
            the a line if the middle of the line is set to either None or the
            empty string.
        """

        if tline:
            tline = Divider(tline)
        if bline:
            bline = Divider(bline)
        if lline:
            lline = SolidFill(lline)
        if rline:
            rline = SolidFill(rline)
        tlcorner, trcorner = Text(tlcorner), Text(trcorner)
        blcorner, brcorner = Text(blcorner), Text(brcorner)

        if not tline and title:
            raise ValueError('Cannot have a title when tline is unset')

        self.title_widget = Text(self.format_title(title))

        if tline:
            if title_align not in ('left', 'center', 'right'):
                raise ValueError(
                    'title_align must be one of "left", "right", or "center"')
            if title_align == 'left':
                tline_widgets = [('flow', self.title_widget), tline]
            else:
                tline_widgets = [tline, ('flow', self.title_widget)]
                if title_align == 'center':
                    tline_widgets.append(tline)
            self.tline_widget = Columns(tline_widgets)
            top = Columns([('fixed', 1, tlcorner), self.tline_widget,
                           ('fixed', 1, trcorner)])

        else:
            self.tline_widget = None
            top = None

        middle_widgets = []
        if lline:
            middle_widgets.append(('fixed', 1, lline))
        middle_widgets.append(original_widget)
        focus_col = len(middle_widgets) - 1
        if rline:
            middle_widgets.append(('fixed', 1, rline))

        middle = Columns(middle_widgets,
                         box_columns=[0, 2],
                         focus_column=focus_col)

        if bline:
            bottom = Columns([('fixed', 1, blcorner), bline,
                              ('fixed', 1, brcorner)])
        else:
            bottom = None

        pile_widgets = []
        if top:
            pile_widgets.append(('flow', top))
        pile_widgets.append(middle)
        focus_pos = len(pile_widgets) - 1
        if bottom:
            pile_widgets.append(('flow', bottom))
        pile = Pile(pile_widgets, focus_item=focus_pos)

        WidgetDecoration.__init__(self, original_widget)
        WidgetWrap.__init__(self, pile)
Beispiel #8
0
    def process_message(self, message):
        if message[
                'message_type'] == 'heartbeat' and not self._heartbeat_is_animating:
            self._heartbeat_is_animating = True
            self._animate_heartbeat()

        if not self.seen_message and message[
                'message_type'] == 'certificate_update':
            self.right_text = urwid.Text('')
            self.frame.set_body(
                urwid.Columns(widget_list=[
                    urwid.Pile([
                        SidelessLineBox(
                            self.list_box,
                            title="CertStream Messages",
                            bline="",
                        ),
                        ('flow',
                         urwid.Columns([
                             ('fixed', 6, urwid.Text(u'└─────')),
                             ('flow', self.counter_text),
                             Divider('─'),
                             ('fixed', 1, urwid.Text(u'┘')),
                         ]))
                    ]),
                    SidelessLineBox(urwid.Filler(self.right_text,
                                                 valign=urwid.TOP),
                                    title="Parsed JSON")
                ], ))
            self.seen_message = True

        if message['message_type'] == 'certificate_update':
            _, original_offset = self.list_box.get_focus()
            self.list_walker.insert(
                0,
                urwid.AttrMap(FauxButton("[{}] {} - {}".format(
                    message['data']['cert_index'],
                    message['data']['source']['url'],
                    message['data']['leaf_cert']['subject']['CN'],
                ),
                                         user_data=message,
                                         on_press=self.focus_right_panel),
                              '',
                              focus_map='buttons'))

            self.counter_text.set_text(
                self.COUNTER_FORMAT.format(original_offset,
                                           len(self.list_box.body) - 1))

            offset = (len(self.list_box.body) - 1)

            logging.info("Disconnecting")
            urwid.disconnect_signal(self.list_walker, "modified",
                                    self.item_focused)
            logging.info("Setting focus")
            self.list_walker.set_focus(offset)
            logging.info("Reconnecting")
            urwid.connect_signal(self.list_walker, "modified",
                                 self.item_focused)
            logging.info("Done")

            self.right_text.set_text(
                json.dumps(self.list_walker[
                    offset - self.list_box.get_focus()[1] -
                    1].original_widget.user_data['data']['leaf_cert'],
                           indent=4))

        self.loop.draw_screen()
Beispiel #9
0
    def setup_frame(self, title, input_title):
        """
        Creates the main view, with a 3 horizontal pane container (Frame)
        """
        self.keys = []  # List of keys added to the OSK
        self._shift = False  # OSK Shift key state

        # title frame (header) uses a LineBox with just the bottom line enabled
        # if we're on a small display, use a simple Text with Padding
        if self.small_display:
            header = Padding(Text(title, align='center'))

        else:
            header = LineBox(Text(title),
                             tline=None,
                             rline=' ',
                             lline=' ',
                             trcorner=' ',
                             tlcorner=' ',
                             blcorner='',
                             brcorner='')

        header = AttrWrap(header, 'header')

        # Body frame, containing the input and the OSK widget
        input = Text([('input text', ''), ('prompt', ASCII_BLOCK)])
        self.input = input

        Key = self.add_osk_key  # alias the key creation function
        osk = Pile([
            # 1st keyboard row
            WrappableColumns([
                (1, Text(" ")),
                (3, Key('`', shifted='~')),
                (3, Key('1', shifted='!')),
                (3, Key('2', shifted='@')),
                (3, Key('3', shifted='#')),
                (3, Key('4', shifted='$')),
                (3, Key('5', shifted='%')),
                (3, Key('6', shifted='^')),
                (3, Key('7', shifted='&')),
                (3, Key('8', shifted='*')),
                (3, Key('9', shifted='(')),
                (3, Key('0', shifted=')')),
                (3, Key('-', shifted='_')),
                (3, Key('=', shifted='+')),
                (1, Text(" ")),
            ], 0),
            Divider(),
            # 2nd keyboard row
            WrappableColumns([
                (2, Text(" ")),
                (3, Key('q')),
                (3, Key('w')),
                (3, Key('e')),
                (3, Key('r')),
                (3, Key('t')),
                (3, Key('y')),
                (3, Key('u')),
                (3, Key('i')),
                (3, Key('o')),
                (3, Key('p')),
                (3, Key('[', shifted='{')),
                (3, Key(']', shifted='}')),
                (3, Key('\\', shifted='|')),
            ], 0),
            Divider(),
            # 3rd keyboard row
            WrappableColumns([
                (3, Text(" ")),
                (3, Key('a')),
                (3, Key('s')),
                (3, Key('d')),
                (3, Key('f')),
                (3, Key('g')),
                (3, Key('h')),
                (3, Key('j')),
                (3, Key('k')),
                (3, Key('l')),
                (3, Key(';', shifted=':')),
                (3, Key('\'', shifted='"')),
            ], 0),
            Divider(),
            # 4th keyboard row
            WrappableColumns([(4, Text(" ")), (3, Key('z')), (3, Key('x')),
                              (3, Key('c')), (3, Key('v')), (3, Key('b')),
                              (3, Key('n')), (3, Key('m')),
                              (3, Key(',', shifted='<')),
                              (3, Key('.', shifted='>')),
                              (3, Key('/', shifted='?'))], 0),
            Divider(),
            # 5th (last) keyboard row
            WrappableColumns([
                (1, Text(" ")),
                (9,
                 Key('↑ Shift',
                     shifted='↑ SHIFT',
                     callback=self.shift_key_press)),
                (2, Text(" ")),
                (15, Key('Space', value=' ', shifted=' ')),
                (2, Text(" ")),
                (10, Key('Delete ←', callback=self.bksp_key_press)),
            ], 0),
            Divider()
        ])

        if self.small_display:
            # small displays: remove last divider line
            osk.contents.pop(len(osk.contents) - 1)

        osk = Padding(osk, 'center', 40)

        # setup the text input and the buttons
        input = AttrWrap(LineBox(input), 'input')
        input = Padding(AttrWrap(input, 'input text'),
                        'center', ('relative', 80),
                        min_width=30)
        ok_btn = self.setup_button("OK", self.button_press, exitcode=0)
        cancel_btn = self.setup_button("Cancel", self.button_press, exitcode=1)

        # setup the main OSK area, depending on the screen size
        if self.small_display:
            body = Pile([
                Text(f'Enter the {input_title}', align='center'), input,
                Divider(), osk,
                Divider(),
                GridFlow([ok_btn, cancel_btn], 10, 2, 0, 'center'),
                Divider()
            ])
        else:
            body = Pile([
                Divider(), input,
                Divider(), osk,
                LineBox(GridFlow([ok_btn, cancel_btn], 10, 2, 0, 'center'),
                        bline=None,
                        lline=None,
                        rline=None,
                        tlcorner='─',
                        trcorner='─')
            ])
            body = LineBox(body, f'Enter the {input_title}')

        body = AttrWrap(body, 'body')  # Style the main OSK area

        # wrap and align the main OSK in the frame
        body = Padding(body, 'center', 55, min_width=42)
        body = Filler(body, 'middle')

        body = AttrWrap(body, 'bg')  # Style the body containing the OSK

        frame = Frame(body, header=header, focus_part='body')

        return frame
Beispiel #10
0
    def __init__(self,
                 original_widget,
                 title="",
                 tlcorner=None,
                 tline=None,
                 lline=None,
                 trcorner=None,
                 blcorner=None,
                 rline=None,
                 bline=None,
                 brcorner=None):
        """
        Draw a line around original_widget.

        Use 'title' to set an initial title text with will be centered
        on top of the box.

        You can also override the widgets used for the lines/corners:
            tline: top line
            bline: bottom line
            lline: left line
            rline: right line
            tlcorner: top left corner
            trcorner: top right corner
            blcorner: bottom left corner
            brcorner: bottom right corner
        """
        self.title_widget = Text(self.format_title(title))

        def use_attr(a, t):
            if a is not None:
                t = AttrWrap(t, a)
                return t
            else:
                return t

        self.tline_widget = Columns([
            Divider(self.ACS_HLINE),
            ('flow', self.title_widget),
            Divider(self.ACS_HLINE),
        ])

        tline = use_attr(tline, self.tline_widget)
        bline = use_attr(bline, Divider(self.ACS_HLINE))
        lline = use_attr(lline, SolidFill(self.ACS_VLINE))
        rline = use_attr(rline, SolidFill(self.ACS_VLINE))
        tlcorner = use_attr(tlcorner, Text(self.ACS_ULCORNER))
        trcorner = use_attr(trcorner, Text(self.ACS_URCORNER))
        blcorner = use_attr(blcorner, Text(self.ACS_LLCORNER))
        brcorner = use_attr(brcorner, Text(self.ACS_LRCORNER))
        top = Columns([('fixed', 1, tlcorner), tline, ('fixed', 1, trcorner)])
        middle = Columns([('fixed', 1, lline), original_widget,
                          ('fixed', 1, rline)],
                         box_columns=[0, 2],
                         focus_column=1)
        bottom = Columns([('fixed', 1, blcorner), bline,
                          ('fixed', 1, brcorner)])
        pile = Pile([('flow', top), middle, ('flow', bottom)], focus_item=1)

        WidgetDecoration.__init__(self, original_widget)
        WidgetWrap.__init__(self, pile)