예제 #1
0
  def _resize_graph(self):
    """
    Prompts for user input to resize the graph panel. Options include...

      * down arrow - grow graph
      * up arrow - shrink graph
      * enter / space - set size
    """

    with nyx.curses.CURSES_LOCK:
      try:
        while True:
          show_message('press the down/up to resize the graph, and enter when done', BOLD)
          key = nyx.curses.key_input()

          if key.match('down'):
            # don't grow the graph if it's already consuming the whole display
            # (plus an extra line for the graph/log gap)

            max_height = nyx.curses.screen_size().height - self.get_top()
            current_height = self.get_height()

            if current_height < max_height + 1:
              self.set_graph_height(self._graph_height + 1)
          elif key.match('up'):
            self.set_graph_height(self._graph_height - 1)
          elif key.is_selection():
            break

          nyx_interface().redraw()
      finally:
        show_message()
예제 #2
0
  def _update_accounting(self, event):
    if not CONFIG['show_accounting']:
      self._accounting_stats = None
    elif not self._accounting_stats or time.time() - self._accounting_stats.retrieved >= ACCOUNTING_RATE:
      old_accounting_stats = self._accounting_stats
      self._accounting_stats = tor_controller().get_accounting_stats(None)

      if not nyx_interface().is_paused():
        # if we either added or removed accounting info then redraw the whole
        # screen to account for resizing

        if bool(old_accounting_stats) != bool(self._accounting_stats):
          nyx_interface().redraw()
예제 #3
0
def show_menu():
    menu = _make_menu()
    cursor = MenuCursor(menu.children[0].children[0])

    with nyx.curses.CURSES_LOCK:
        show_message('Press m or esc to close the menu.', BOLD)

        while not cursor.is_done:
            selection_x = _draw_top_menubar(menu, cursor.selection)
            _draw_submenu(cursor.selection, cursor.selection.submenu, 1,
                          selection_x)
            cursor.handle_key(nyx.curses.key_input())
            nyx_interface().redraw(True)

        show_message()
예제 #4
0
  def _draw(self, subwindow):
    if not self._displayed_stat:
      return

    if not nyx_interface().is_paused():
      stat = self._stats[self._displayed_stat]
      accounting_stats = self._accounting_stats
    else:
      if not self._stats_paused:
        return  # when first paused concurrency could mean this isn't set yet

      stat = self._stats_paused[self._displayed_stat]
      accounting_stats = self._accounting_stats_paused

    with self._stats_lock:
      subgraph_height = self._graph_height + 2  # graph rows + header + x-axis label
      subgraph_width = min(subwindow.width // 2, CONFIG['max_graph_width'])
      interval, bounds_type = self._update_interval, self._bounds_type

      subwindow.addstr(0, 0, stat.title(subwindow.width), HIGHLIGHT)

      _draw_subgraph(subwindow, stat.primary, 0, subgraph_width, subgraph_height, bounds_type, interval, PRIMARY_COLOR)
      _draw_subgraph(subwindow, stat.secondary, subgraph_width, subgraph_width, subgraph_height, bounds_type, interval, SECONDARY_COLOR)

      if stat.stat_type() == GraphStat.BANDWIDTH and accounting_stats:
        _draw_accounting_stats(subwindow, DEFAULT_CONTENT_HEIGHT + subgraph_height - 2, accounting_stats)
예제 #5
0
파일: log.py 프로젝트: traumschule/nyx
    def _draw(self, subwindow, is_correction=False):
        scroll = self._scroller.location(self._last_content_height,
                                         subwindow.height - 1)

        event_filter = self._filter.clone()
        event_types = list(self._event_types)
        last_content_height = self._last_content_height
        show_duplicates = self._show_duplicates

        event_log = self._event_log_paused if nyx_interface().is_paused(
        ) else self._event_log
        event_log = list(
            filter(lambda entry: event_filter.match(entry.display_message),
                   event_log))
        event_log = list(
            filter(lambda entry: not entry.is_duplicate or show_duplicates,
                   event_log))

        is_scrollbar_visible = last_content_height > subwindow.height - 1

        if is_scrollbar_visible:
            subwindow.scrollbar(1, scroll, last_content_height)

        x, y = 2 if is_scrollbar_visible else 0, 1 - scroll
        y = _draw_entries(subwindow, x, y, event_log, show_duplicates)

        # drawing the title after the content, so we'll clear content from the top line

        _draw_title(subwindow, event_types, event_filter)

        # redraw the display if...
        # - last_content_height was off by too much
        # - we're off the bottom of the page

        new_content_height = y + scroll - 1
        content_height_delta = abs(last_content_height - new_content_height)
        force_redraw, force_redraw_reason = True, ''

        if content_height_delta >= CONTENT_HEIGHT_REDRAW_THRESHOLD:
            force_redraw_reason = 'estimate was off by %i' % content_height_delta
        elif new_content_height > subwindow.height and scroll + subwindow.height - 1 > new_content_height:
            force_redraw_reason = 'scrolled off the bottom of the page'
        elif not is_scrollbar_visible and new_content_height > subwindow.height - 1:
            force_redraw_reason = "scroll bar wasn't previously visible"
        elif is_scrollbar_visible and new_content_height <= subwindow.height - 1:
            force_redraw_reason = "scroll bar shouldn't be visible"
        else:
            force_redraw = False

        self._last_content_height = new_content_height
        self._has_new_event = False

        if force_redraw and not is_correction:
            log.debug(
                'redrawing the log panel with the corrected content height (%s)'
                % force_redraw_reason)
            self._draw(subwindow, True)
예제 #6
0
def show_help():
    """
  Presents a popup with the current page's hotkeys.

  :returns: :class:`~nyx.curses.KeyInput` that was pressed to close the popup
    if it's one panels should act upon, **None** otherwise
  """

    interface = nyx_interface()
    handlers = []

    for panel in reversed(interface.page_panels()[1:]):
        handlers += [
            handler for handler in panel.key_handlers() if handler.description
        ]

    def _render(subwindow):
        subwindow.box()
        subwindow.addstr(0, 0,
                         'Page %i Commands:' % (interface.get_page() + 1),
                         HIGHLIGHT)

        for i, option in enumerate(handlers):
            if i // 2 >= subwindow.height - 2:
                break

            # Entries are shown in the form '<key>: <description>[ (<selection>)]',
            # such as...
            #
            #   u: duplicate log entries (hidden)

            x = 2 if i % 2 == 0 else 41
            y = (i // 2) + 1

            x = subwindow.addstr(x, y, option.key, BOLD)
            x = subwindow.addstr(x, y, ': ' + option.description)

            if option.current:
                x = subwindow.addstr(x, y, ' (')
                x = subwindow.addstr(x, y, option.current, BOLD)
                x = subwindow.addstr(x, y, ')')

        # tells user to press a key if the lower left is unoccupied

        if len(handlers) < 13 and subwindow.height == 9:
            subwindow.addstr(2, 7, 'Press any key...')

    with nyx.curses.CURSES_LOCK:
        nyx.curses.draw(_render, top=_top(), width=80, height=9)
        keypress = nyx.curses.key_input()

    if keypress.is_selection() or keypress.is_scroll() or keypress.match(
            'left', 'right'):
        return None
    else:
        return keypress
예제 #7
0
파일: header.py 프로젝트: bounteous/nyx
def _draw_status(subwindow, x, y, is_paused, message, *attr):
    """
  Provides general usage information or a custom message.
  """

    if message:
        subwindow.addstr(x, y, message, *attr)
    elif not is_paused:
        interface = nyx_interface()
        subwindow.addstr(
            x, y, 'page %i / %i - m: menu, p: pause, h: page help, q: quit' %
            (interface.get_page() + 1, interface.page_count()))
    else:
        subwindow.addstr(x, y, 'Paused', HIGHLIGHT)
예제 #8
0
파일: starter.py 프로젝트: bounteous/nyx
def _shutdown_daemons(controller):
    """
  Stops and joins on worker threads.
  """

    halt_threads = [nyx.tracker.stop_trackers()]
    interface = nyx_interface()

    if interface:
        halt_threads.append(interface.halt())

    for thread in halt_threads:
        thread.join()

    controller.close()
예제 #9
0
  def get_height(self):
    """
    Provides the height of the content.
    """

    max_height = nyx.panel.Panel.get_height(self)

    if not self._displayed_stat:
      return 0

    height = DEFAULT_CONTENT_HEIGHT + self._graph_height
    accounting_stats = self._accounting_stats if not nyx_interface().is_paused() else self._accounting_stats_paused

    if self._displayed_stat == GraphStat.BANDWIDTH and accounting_stats:
      height += 3

    return min(max_height, height)
예제 #10
0
파일: connection.py 프로젝트: tka85/nyx
    def _draw(self, subwindow):
        controller = tor_controller()
        interface = nyx_interface()
        entries = self._entries

        lines = list(
            itertools.chain.from_iterable(
                [entry.get_lines() for entry in entries]))
        is_showing_details = self._show_details and lines
        details_offset = DETAILS_HEIGHT + 1 if is_showing_details else 0
        selected, scroll = self._scroller.selection(
            lines, subwindow.height - details_offset - 1)

        if interface.is_paused():
            current_time = self._pause_time
        elif not controller.is_alive():
            current_time = controller.connection_time()
        else:
            current_time = time.time()

        is_scrollbar_visible = len(
            lines) > subwindow.height - details_offset - 1
        scroll_offset = 2 if is_scrollbar_visible else 0

        _draw_title(subwindow, entries, self._show_details)

        if is_showing_details:
            _draw_details(subwindow, selected)

            # draw a 'T' pipe if connecting with the scrollbar

            if is_scrollbar_visible:
                subwindow._addch(1, DETAILS_HEIGHT + 1, curses.ACS_TTEE)

        if is_scrollbar_visible:
            subwindow.scrollbar(1 + details_offset, scroll, len(lines))

        for line_number in range(scroll, len(lines)):
            y = line_number + details_offset + 1 - scroll
            _draw_line(subwindow, scroll_offset, y, lines[line_number],
                       lines[line_number] == selected,
                       subwindow.width - scroll_offset, current_time)

            if y >= subwindow.height:
                break
예제 #11
0
파일: header.py 프로젝트: bounteous/nyx
    def _draw(self, subwindow):
        vals = self._vals  # local reference to avoid concurrency concerns
        self._last_width = subwindow.width
        is_wide = self.is_wide()

        # space available for content

        interface = nyx_interface()
        left_width = max(subwindow.width //
                         2, 77) if is_wide else subwindow.width
        right_width = subwindow.width - left_width

        _draw_platform_section(subwindow, 0, 0, left_width, vals)

        if vals.is_connected:
            _draw_ports_section(subwindow, 0, 1, left_width, vals)
        else:
            _draw_disconnected(subwindow, 0, 1, vals.last_heartbeat)

        if is_wide:
            _draw_resource_usage(subwindow, left_width, 0, right_width, vals,
                                 self._pause_time)

            if vals.is_relay:
                _draw_fingerprint_and_fd_usage(subwindow, left_width, 1,
                                               right_width, vals)
                _draw_flags(subwindow, 0, 2, vals.flags)
                _draw_exit_policy(subwindow, left_width, 2, vals.exit_policy)
            elif vals.is_connected:
                _draw_newnym_option(subwindow, left_width, 1, vals.newnym_wait)
        else:
            _draw_resource_usage(subwindow, 0, 2, left_width, vals,
                                 self._pause_time)

            if vals.is_relay:
                _draw_fingerprint_and_fd_usage(subwindow, 0, 3, left_width,
                                               vals)
                _draw_flags(subwindow, 0, 4, vals.flags)

        _draw_status(subwindow, 0,
                     self.get_height() - 1, interface.is_paused(),
                     self._message, *self._message_attr)
예제 #12
0
def _make_menu():
    """
  Constructs the base menu and all of its contents.
  """

    interface = nyx_interface()

    if not interface.is_paused():
        pause_item = MenuItem('Pause', interface.set_paused, True)
    else:
        pause_item = MenuItem('Unpause', interface.set_paused, False)

    root_menu = Submenu('')

    root_menu.add(
        Submenu('Actions', [
            MenuItem('Close Menu', None),
            MenuItem('New Identity',
                     interface.header_panel().send_newnym),
            MenuItem('Reset Tor',
                     tor_controller().signal, stem.Signal.RELOAD),
            pause_item,
            MenuItem('Exit', interface.quit),
        ]))

    root_menu.add(_view_menu())

    for panel in interface.page_panels():
        submenu = panel.submenu()

        if submenu:
            root_menu.add(submenu)

    root_menu.add(
        Submenu('Help', [
            MenuItem('Hotkeys', nyx.popups.show_help),
            MenuItem('About', nyx.popups.show_about),
        ]))

    return root_menu
예제 #13
0
def _view_menu():
    """
  Submenu consisting of...

    [X] <Page 1>
    [ ] <Page 2>
    [ ] etc...
        Color (Submenu)
  """

    interface = nyx_interface()

    view_menu = Submenu('View')
    page_group = RadioGroup(interface.set_page, interface.get_page())

    for i in range(interface.page_count()):
        page_panels = interface.page_panels(page_number=i)[1:]
        label = ' / '.join([
            type(panel).__name__.replace('Panel', '') for panel in page_panels
        ])
        view_menu.add(RadioMenuItem(label, page_group, i))

    if nyx.curses.is_color_supported():
        color_group = RadioGroup(nyx.curses.set_color_override,
                                 nyx.curses.get_color_override())

        view_menu.add(
            Submenu('Color', [
                RadioMenuItem('All', color_group, None),
                [
                    RadioMenuItem(str_tools._to_camel_case(opt), color_group,
                                  opt) for opt in nyx.curses.Color
                ],
            ]))

    return view_menu
예제 #14
0
def _top():
    return nyx_interface().header_panel().get_height()