[nyx/master] Move submenus to panels

commit c9467743eb00f282c36677ef37d6dda5e23856be Author: Damian Johnson <atagar@torproject.org> Date: Thu Aug 25 09:55:55 2016 -0700 Move submenus to panels Now that constructing submenus is so much simpler this fits a lot better in the Panel subclasses. This is a great simplification for the panels as well as the menu module sincel it lets us make numerous attributes and functions private. --- nyx/controller.py | 7 +-- nyx/menu.py | 141 ++---------------------------------------------- nyx/panel/__init__.py | 11 ++++ nyx/panel/config.py | 24 +++++++-- nyx/panel/connection.py | 24 ++++++++- nyx/panel/graph.py | 97 ++++++++++++++++----------------- nyx/panel/log.py | 75 +++++++++++++------------- nyx/panel/torrc.py | 43 ++++++++------- 8 files changed, 163 insertions(+), 259 deletions(-) diff --git a/nyx/controller.py b/nyx/controller.py index 8040e7e..bf7a22d 100644 --- a/nyx/controller.py +++ b/nyx/controller.py @@ -372,9 +372,7 @@ def start_nyx(): for panel_impl in control.get_all_panels(): panel_impl.set_visible(panel_impl in display_panels) - # redraws the interface if it's needed - - control.redraw(False) + control.redraw() with nyx.curses.raw_screen() as stdscr: stdscr.refresh() @@ -419,9 +417,6 @@ def start_nyx(): log.error('Error detected when reloading tor: %s' % exc.strerror) elif key.match('h'): override_key = nyx.popups.show_help() - elif key == ord('l') - 96: - # force redraw when ctrl+l is pressed - control.redraw(True) else: for panel_impl in display_panels: for keybinding in panel_impl.key_handlers(): diff --git a/nyx/menu.py b/nyx/menu.py index b0fb646..ed58613 100644 --- a/nyx/menu.py +++ b/nyx/menu.py @@ -10,16 +10,8 @@ import functools import nyx.controller import nyx.curses import nyx.popups -import nyx.panel.config -import nyx.panel.connection -import nyx.panel.graph -import nyx.panel.log -import nyx.panel.torrc -import nyx.controller -import nyx.tracker import stem -import stem.util.connection from nyx import tor_controller from nyx.curses import RED, WHITE, NORMAL, BOLD, UNDERLINE @@ -182,17 +174,11 @@ def make_menu(): root_menu.add(_view_menu()) - for page_panel in nyx_controller.get_display_panels(): - if isinstance(page_panel, nyx.panel.graph.GraphPanel): - root_menu.add(_graph_menu(page_panel)) - elif isinstance(page_panel, nyx.panel.log.LogPanel): - root_menu.add(_log_menu(page_panel)) - elif isinstance(page_panel, nyx.panel.connection.ConnectionPanel): - root_menu.add(_connections_menu(page_panel)) - elif isinstance(page_panel, nyx.panel.config.ConfigPanel): - root_menu.add(_configuration_menu(page_panel)) - elif isinstance(page_panel, nyx.panel.torrc.TorrcPanel): - root_menu.add(_torrc_menu(page_panel)) + for panel in nyx_controller.get_display_panels(): + submenu = panel.submenu() + + if submenu: + root_menu.add(submenu) root_menu.add(Submenu('Help', [ MenuItem('Hotkeys', nyx.popups.show_help), @@ -233,123 +219,6 @@ def _view_menu(): return view_menu -def _graph_menu(graph_panel): - """ - Graph panel submenu consisting of... - - [X] <Stat 1> - [ ] <Stat 2> - [ ] <Stat 2> - Resize... - Interval (Submenu) - Bounds (Submenu) - """ - - stat_group = RadioGroup(functools.partial(setattr, graph_panel, 'displayed_stat'), graph_panel.displayed_stat) - interval_group = RadioGroup(functools.partial(setattr, graph_panel, 'update_interval'), graph_panel.update_interval) - bounds_group = RadioGroup(functools.partial(setattr, graph_panel, 'bounds_type'), graph_panel.bounds_type) - - return Submenu('Graph', [ - RadioMenuItem('None', stat_group, None), - [RadioMenuItem(str_tools._to_camel_case(opt, divider = ' '), stat_group, opt) for opt in sorted(graph_panel.stat_options())], - MenuItem('Resize...', graph_panel.resize_graph), - Submenu('Interval', [RadioMenuItem(opt, interval_group, opt) for opt in nyx.panel.graph.Interval]), - Submenu('Bounds', [RadioMenuItem(opt, bounds_group, opt) for opt in nyx.panel.graph.Bounds]), - ]) - - -def _log_menu(log_panel): - """ - Log panel submenu consisting of... - - Events... - Snapshot... - Clear - Show / Hide Duplicates - Filter (Submenu) - """ - - log_filter = log_panel.get_filter() - filter_group = RadioGroup(log_filter.select, log_filter.selection()) - - if not log_panel.is_duplicates_visible(): - duplicate_item = MenuItem('Show Duplicates', log_panel.set_duplicate_visability, True) - else: - duplicate_item = MenuItem('Hide Duplicates', log_panel.set_duplicate_visability, False) - - return Submenu('Log', [ - MenuItem('Events...', log_panel.show_event_selection_prompt), - MenuItem('Snapshot...', log_panel.show_snapshot_prompt), - MenuItem('Clear', log_panel.clear), - duplicate_item, - Submenu('Filter', [ - RadioMenuItem('None', filter_group, None), - [RadioMenuItem(opt, filter_group, opt) for opt in log_filter.latest_selections()], - MenuItem('New...', log_panel.show_filter_prompt), - ]), - ]) - - -def _connections_menu(conn_panel): - """ - Connection panel submenu consisting of... - - Sorting... - Resolver (Submenu) - """ - - tracker = nyx.tracker.get_connection_tracker() - resolver_group = RadioGroup(tracker.set_custom_resolver, tracker.get_custom_resolver()) - - return Submenu('Connections', [ - MenuItem('Sorting...', conn_panel.show_sort_dialog), - Submenu('Resolver', [ - RadioMenuItem('auto', resolver_group, None), - [RadioMenuItem(opt, resolver_group, opt) for opt in stem.util.connection.Resolver], - ]), - ]) - - -def _configuration_menu(config_panel): - """ - Configuration panel submenu consisting of... - - Save Config... - Sorting... - Filter / Unfilter Options - """ - - return Submenu('Configuration', [ - MenuItem('Save Config...', config_panel.show_write_dialog), - MenuItem('Sorting...', config_panel.show_sort_dialog), - ]) - - -def _torrc_menu(torrc_panel): - """ - Torrc panel submenu consisting of... - - Reload - Show / Hide Comments - Show / Hide Line Numbers - """ - - if not torrc_panel._show_comments: - comments_item = MenuItem('Show Comments', torrc_panel.set_comments_visible, True) - else: - comments_item = MenuItem('Hide Comments', torrc_panel.set_comments_visible, False) - - if not torrc_panel._show_line_numbers: - line_number_item = MenuItem('Show Line Numbers', torrc_panel.set_line_number_visible, True) - else: - line_number_item = MenuItem('Hide Line Numbers', torrc_panel.set_line_number_visible, False) - - return Submenu('Torrc', [ - comments_item, - line_number_item, - ]) - - class MenuCursor: """ Tracks selection and key handling in the menu. diff --git a/nyx/panel/__init__.py b/nyx/panel/__init__.py index decb276..18a66ce 100644 --- a/nyx/panel/__init__.py +++ b/nyx/panel/__init__.py @@ -22,6 +22,7 @@ Panels consisting the nyx interface. | |- set_visible - toggles panel visiblity |- key_handlers - keyboard input accepted by the panel + |- submenu - submenu for the panel +- redraw - renders the panel content """ @@ -139,6 +140,16 @@ class Panel(object): return () + def submenu(self): + """ + Provides submenu to include when the panel is shown. + + :returns: :class:`~nyx.menu.Submenu` with the panel's options or **None** + if no submenu should be shown + """ + + return None + def redraw(self, force = True): """ Renders our panel's content to the screen. diff --git a/nyx/panel/config.py b/nyx/panel/config.py index 7640b99..424586c 100644 --- a/nyx/panel/config.py +++ b/nyx/panel/config.py @@ -16,8 +16,10 @@ import nyx.popups import stem.control import stem.manual +import stem.util.connection from nyx.curses import WHITE, NORMAL, BOLD, HIGHLIGHT +from nyx.menu import MenuItem, Submenu from nyx import DATA_DIR, tor_controller from stem.util import conf, enum, log, str_tools @@ -169,7 +171,7 @@ class ConfigPanel(nyx.panel.Panel): except stem.ControllerError as exc: log.warn('Unable to determine the configuration options tor supports: %s' % exc) - def show_sort_dialog(self): + def _show_sort_dialog(self): """ Provides the dialog for sorting our configuration options. """ @@ -181,7 +183,7 @@ class ConfigPanel(nyx.panel.Panel): self._sort_order = results self._contents = sorted(self._contents, key = lambda entry: [entry.sort_value(field) for field in self._sort_order]) - def show_write_dialog(self): + def _show_write_dialog(self): """ Confirmation dialog for saving tor's configuration. """ @@ -235,11 +237,25 @@ class ConfigPanel(nyx.panel.Panel): return ( nyx.panel.KeyHandler('arrows', 'scroll up and down', _scroll, key_func = lambda key: key.is_scroll()), nyx.panel.KeyHandler('enter', 'edit configuration option', _edit_selected_value, key_func = lambda key: key.is_selection()), - nyx.panel.KeyHandler('w', 'write torrc', self.show_write_dialog), + nyx.panel.KeyHandler('w', 'write torrc', self._show_write_dialog), nyx.panel.KeyHandler('a', 'toggle filtering', _toggle_show_all), - nyx.panel.KeyHandler('s', 'sort ordering', self.show_sort_dialog), + nyx.panel.KeyHandler('s', 'sort ordering', self._show_sort_dialog), ) + def submenu(self): + """ + Submenu consisting of... + + Save Config... + Sorting... + Filter / Unfilter Options + """ + + return Submenu('Configuration', [ + MenuItem('Save Config...', self._show_write_dialog), + MenuItem('Sorting...', self._show_sort_dialog), + ]) + def _draw(self, subwindow): contents = self._get_config_options() selected, scroll = self._scroller.selection(contents, subwindow.height - DETAILS_HEIGHT) diff --git a/nyx/panel/connection.py b/nyx/panel/connection.py index afcf457..d30742f 100644 --- a/nyx/panel/connection.py +++ b/nyx/panel/connection.py @@ -18,6 +18,7 @@ import nyx.popups import nyx.tracker from nyx.curses import WHITE, NORMAL, BOLD, HIGHLIGHT +from nyx.menu import MenuItem, Submenu, RadioMenuItem, RadioGroup from nyx import tor_controller from stem.control import Listener @@ -296,7 +297,7 @@ class ConnectionPanel(nyx.panel.DaemonPanel): locale, count = entry.split('=', 1) self._client_locale_usage[locale] = int(count) - def show_sort_dialog(self): + def _show_sort_dialog(self): """ Provides a dialog for sorting our connections. """ @@ -384,7 +385,7 @@ class ConnectionPanel(nyx.panel.DaemonPanel): nyx.panel.KeyHandler('arrows', 'scroll up and down', _scroll, key_func = lambda key: key.is_scroll()), nyx.panel.KeyHandler('enter', 'show connection details', _show_details, key_func = lambda key: key.is_selection()), nyx.panel.KeyHandler('d', 'raw consensus descriptor', _show_descriptor), - nyx.panel.KeyHandler('s', 'sort ordering', self.show_sort_dialog), + nyx.panel.KeyHandler('s', 'sort ordering', self._show_sort_dialog), nyx.panel.KeyHandler('r', 'connection resolver', _pick_connection_resolver, 'auto' if resolver is None else resolver), ] @@ -396,6 +397,25 @@ class ConnectionPanel(nyx.panel.DaemonPanel): return tuple(options) + def submenu(self): + """ + Submenu consisting of... + + Sorting... + Resolver (Submenu) + """ + + tracker = nyx.tracker.get_connection_tracker() + resolver_group = RadioGroup(tracker.set_custom_resolver, tracker.get_custom_resolver()) + + return Submenu('Connections', [ + MenuItem('Sorting...', self._show_sort_dialog), + Submenu('Resolver', [ + RadioMenuItem('auto', resolver_group, None), + [RadioMenuItem(opt, resolver_group, opt) for opt in connection.Resolver], + ]), + ]) + def _draw(self, subwindow): controller = tor_controller() nyx_controller = nyx.controller.get_controller() diff --git a/nyx/panel/graph.py b/nyx/panel/graph.py index 9dd3244..492037e 100644 --- a/nyx/panel/graph.py +++ b/nyx/panel/graph.py @@ -15,6 +15,7 @@ Downloaded (0.0 B/sec): Uploaded (0.0 B/sec): """ import copy +import functools import time import nyx.controller @@ -25,6 +26,7 @@ import nyx.tracker from nyx import join, msg, tor_controller from nyx.curses import RED, GREEN, CYAN, BOLD, HIGHLIGHT +from nyx.menu import MenuItem, Submenu, RadioMenuItem, RadioGroup from stem.control import EventType, Listener from stem.util import conf, enum, log, str_tools, system @@ -413,7 +415,7 @@ class GraphPanel(nyx.panel.Panel): self._displayed_stat = None if CONFIG['features.graph.type'] == 'none' else CONFIG['features.graph.type'] self._update_interval = CONFIG['features.graph.interval'] - self._bounds = CONFIG['features.graph.bound'] + self._bounds_type = CONFIG['features.graph.bound'] self._graph_height = CONFIG['features.graph.height'] self._accounting_stats = None @@ -437,42 +439,9 @@ class GraphPanel(nyx.panel.Panel): controller.add_event_listener(self._update_stats, EventType.BW) controller.add_status_listener(lambda *args: self.redraw()) - @property - def displayed_stat(self): - return self._displayed_stat - - @displayed_stat.setter - def displayed_stat(self, value): - if value is not None and value not in self._stats.keys(): - raise ValueError("%s isn't a graphed statistic" % value) - - self._displayed_stat = value - def stat_options(self): return self._stats.keys() - @property - def update_interval(self): - return self._update_interval - - @update_interval.setter - def update_interval(self, value): - if value not in Interval: - raise ValueError("%s isn't a valid graphing update interval" % value) - - self._update_interval = value - - @property - def bounds_type(self): - return self._bounds - - @bounds_type.setter - def bounds_type(self, value): - if value not in Bounds: - raise ValueError("%s isn't a valid type of bounds" % value) - - self._bounds = value - def get_height(self): """ Provides the height of the content. @@ -480,14 +449,14 @@ class GraphPanel(nyx.panel.Panel): max_height = nyx.panel.Panel.get_height(self) - if not self.displayed_stat: + if not self._displayed_stat: return 0 nyx_controller = nyx.controller.get_controller() height = DEFAULT_CONTENT_HEIGHT + self._graph_height accounting_stats = self._accounting_stats if nyx_controller.is_paused() else self._accounting_stats_paused - if self.displayed_stat == GraphStat.BANDWIDTH and accounting_stats: + if self._displayed_stat == GraphStat.BANDWIDTH and accounting_stats: height += 3 return min(max_height, height) @@ -495,7 +464,7 @@ class GraphPanel(nyx.panel.Panel): def set_graph_height(self, new_graph_height): self._graph_height = max(1, new_graph_height) - def resize_graph(self): + def _resize_graph(self): """ Prompts for user input to resize the graph panel. Options include... @@ -534,48 +503,72 @@ class GraphPanel(nyx.panel.Panel): def _pick_stats(): available_stats = sorted(self.stat_options()) options = ['None'] + [stat.capitalize() for stat in available_stats] - previous_selection = options[available_stats.index(self.displayed_stat) + 1] if self.displayed_stat else 'None' + previous_selection = options[available_stats.index(self._displayed_stat) + 1] if self._displayed_stat else 'None' selection = nyx.popups.select_from_list('Graphed Stats:', options, previous_selection) - self.displayed_stat = None if selection == 'None' else available_stats[options.index(selection) - 1] + self._displayed_stat = None if selection == 'None' else available_stats[options.index(selection) - 1] def _next_bounds(): - self.bounds_type = Bounds.next(self.bounds_type) + self._bounds_type = Bounds.next(self._bounds_type) self.redraw() def _pick_interval(): - self.update_interval = nyx.popups.select_from_list('Update Interval:', list(Interval), self.update_interval) + self._update_interval = nyx.popups.select_from_list('Update Interval:', list(Interval), self._update_interval) self.redraw() return ( - nyx.panel.KeyHandler('g', 'resize graph', self.resize_graph), - nyx.panel.KeyHandler('s', 'graphed stats', _pick_stats, self.displayed_stat if self.displayed_stat else 'none'), - nyx.panel.KeyHandler('b', 'graph bounds', _next_bounds, self.bounds_type.replace('_', ' ')), - nyx.panel.KeyHandler('i', 'graph update interval', _pick_interval, self.update_interval), + nyx.panel.KeyHandler('g', 'resize graph', self._resize_graph), + nyx.panel.KeyHandler('s', 'graphed stats', _pick_stats, self._displayed_stat if self._displayed_stat else 'none'), + nyx.panel.KeyHandler('b', 'graph bounds', _next_bounds, self._bounds_type.replace('_', ' ')), + nyx.panel.KeyHandler('i', 'graph update interval', _pick_interval, self._update_interval), ) + def submenu(self): + """ + Submenu consisting of... + + [X] <Stat 1> + [ ] <Stat 2> + [ ] <Stat 2> + Resize... + Interval (Submenu) + Bounds (Submenu) + """ + + stat_group = RadioGroup(functools.partial(setattr, self, '_displayed_stat'), self._displayed_stat) + interval_group = RadioGroup(functools.partial(setattr, self, '_update_interval'), self._update_interval) + bounds_group = RadioGroup(functools.partial(setattr, self, '_bounds_type'), self._bounds_type) + + return Submenu('Graph', [ + RadioMenuItem('None', stat_group, None), + [RadioMenuItem(str_tools._to_camel_case(opt, divider = ' '), stat_group, opt) for opt in sorted(self.stat_options())], + MenuItem('Resize...', self._resize_graph), + Submenu('Interval', [RadioMenuItem(opt, interval_group, opt) for opt in Interval]), + Submenu('Bounds', [RadioMenuItem(opt, bounds_group, opt) for opt in Bounds]), + ]) + def set_paused(self, is_pause): if is_pause: self._accounting_stats_paused = copy.copy(self._accounting_stats) self._stats_paused = dict([(key, type(self._stats[key])(self._stats[key])) for key in self._stats]) def _draw(self, subwindow): - if not self.displayed_stat: + if not self._displayed_stat: return nyx_controller = nyx.controller.get_controller() if not nyx_controller.is_paused(): - stat = self._stats[self.displayed_stat] + stat = self._stats[self._displayed_stat] accounting_stats = self._accounting_stats else: - stat = self._stats_paused[self.displayed_stat] + stat = self._stats_paused[self._displayed_stat] accounting_stats = self._accounting_stats_paused stat = type(stat)(stat) # clone the GraphCategory subgraph_height = self._graph_height + 2 # graph rows + header + x-axis label subgraph_width = min(subwindow.width / 2, CONFIG['features.graph.max_width']) - interval, bounds_type = self.update_interval, self.bounds_type + interval, bounds_type = self._update_interval, self._bounds_type subwindow.addstr(0, 0, stat.title(subwindow.width), HIGHLIGHT) @@ -604,9 +597,9 @@ class GraphPanel(nyx.panel.Panel): for stat in self._stats.values(): stat.bandwidth_event(event) - if self.displayed_stat: - param = self._stats[self.displayed_stat] - update_rate = INTERVAL_SECONDS[self.update_interval] + if self._displayed_stat: + param = self._stats[self._displayed_stat] + update_rate = INTERVAL_SECONDS[self._update_interval] if param.primary.tick % update_rate == 0: self.redraw() diff --git a/nyx/panel/log.py b/nyx/panel/log.py index 502e383..ec9e238 100644 --- a/nyx/panel/log.py +++ b/nyx/panel/log.py @@ -7,6 +7,7 @@ for. This provides prepopulation from the log file and supports filtering by regular expressions. """ +import functools import os import time @@ -21,6 +22,7 @@ import nyx.log from nyx import join, tor_controller from nyx.curses import GREEN, YELLOW, WHITE, NORMAL, BOLD, HIGHLIGHT +from nyx.menu import MenuItem, Submenu, RadioMenuItem, RadioGroup from stem.util import conf, log @@ -111,33 +113,7 @@ class LogPanel(nyx.panel.DaemonPanel): NYX_LOGGER.emit = self._register_nyx_event - def is_duplicates_visible(self): - """ - Checks if duplicate log entries are collapsed or not. - - :returns: **True** if duplicates are shown and **False** otherwise - """ - - return self._show_duplicates - - def set_duplicate_visability(self, is_visible): - """ - Sets if duplicate log entries are collaped or expanded. - - :param bool is_visible: if **True** all log entries are shown, otherwise - they're deduplicated - """ - - self._show_duplicates = is_visible - - def get_filter(self): - """ - Provides our currently selected regex filter. - """ - - return self._filter - - def show_filter_prompt(self): + def _show_filter_prompt(self): """ Prompts the user to add a new regex filter. """ @@ -147,10 +123,9 @@ class LogPanel(nyx.panel.DaemonPanel): if regex_input: self._filter.select(regex_input) - def show_event_selection_prompt(self): + def _show_event_selection_prompt(self): """ Prompts the user to select the events being listened for. - TODO: Replace show_event_selection_prompt() with this method. """ event_types = nyx.popups.select_event_types(self._event_types) @@ -159,7 +134,7 @@ class LogPanel(nyx.panel.DaemonPanel): self._event_types = nyx.log.listen_for_events(self._register_tor_event, event_types) self.redraw() - def show_snapshot_prompt(self): + def _show_snapshot_prompt(self): """ Lets user enter a path to take a snapshot, canceling if left blank. """ @@ -173,7 +148,7 @@ class LogPanel(nyx.panel.DaemonPanel): except IOError as exc: nyx.controller.show_message('Unable to save snapshot: %s' % exc, HIGHLIGHT, max_wait = 2) - def clear(self): + def _clear(self): """ Clears the contents of the event log. """ @@ -231,12 +206,12 @@ class LogPanel(nyx.panel.DaemonPanel): if selection == 'None': self._filter.select(None) elif selection == 'New...': - self.show_filter_prompt() # prompt user to input regular expression + self._show_filter_prompt() # prompt user to input regular expression else: self._filter.select(selection) def _toggle_deduplication(): - self.set_duplicate_visability(not self.is_duplicates_visible()) + self._show_duplicates = not self._show_duplicates self.redraw() def _clear_log(): @@ -244,17 +219,43 @@ class LogPanel(nyx.panel.DaemonPanel): key_press = nyx.controller.show_message(msg, BOLD, max_wait = 30) if key_press.match('c'): - self.clear() + self._clear() return ( nyx.panel.KeyHandler('arrows', 'scroll up and down', _scroll, key_func = lambda key: key.is_scroll()), - nyx.panel.KeyHandler('a', 'save snapshot of the log', self.show_snapshot_prompt), - nyx.panel.KeyHandler('e', 'change logged events', self.show_event_selection_prompt), + nyx.panel.KeyHandler('a', 'save snapshot of the log', self._show_snapshot_prompt), + nyx.panel.KeyHandler('e', 'change logged events', self._show_event_selection_prompt), nyx.panel.KeyHandler('f', 'log regex filter', _pick_filter, 'enabled' if self._filter.selection() else 'disabled'), - nyx.panel.KeyHandler('u', 'duplicate log entries', _toggle_deduplication, 'visible' if self.is_duplicates_visible() else 'hidden'), + nyx.panel.KeyHandler('u', 'duplicate log entries', _toggle_deduplication, 'visible' if self._show_duplicates else 'hidden'), nyx.panel.KeyHandler('c', 'clear event log', _clear_log), ) + def submenu(self): + """ + Submenu consisting of... + + Events... + Snapshot... + Clear + Show / Hide Duplicates + Filter (Submenu) + """ + + filter_group = RadioGroup(self._filter.select, self._filter.selection()) + duplicates_label, duplicates_arg = ('Hide Duplicates', False) if self._show_duplicates else ('Show Duplicates', True) + + return Submenu('Log', [ + MenuItem('Events...', self._show_event_selection_prompt), + MenuItem('Snapshot...', self._show_snapshot_prompt), + MenuItem('Clear', self._clear), + MenuItem(duplicates_label, functools.partial(setattr, self, '_show_duplicates'), duplicates_arg), + Submenu('Filter', [ + RadioMenuItem('None', filter_group, None), + [RadioMenuItem(opt, filter_group, opt) for opt in self._filter.latest_selections()], + MenuItem('New...', self._show_filter_prompt), + ]), + ]) + def set_paused(self, is_pause): if is_pause: self._event_log_paused = self._event_log.clone() diff --git a/nyx/panel/torrc.py b/nyx/panel/torrc.py index 0bdaf2c..d5e890e 100644 --- a/nyx/panel/torrc.py +++ b/nyx/panel/torrc.py @@ -5,12 +5,14 @@ Panel displaying the torrc or nyxrc with the validation done against it. """ +import functools import math import string import nyx.curses from nyx.curses import RED, GREEN, YELLOW, CYAN, WHITE, BOLD, HIGHLIGHT +from nyx.menu import MenuItem, Submenu from nyx import expand_path, msg, panel, tor_controller from stem import ControllerError @@ -68,26 +70,6 @@ class TorrcPanel(panel.Panel): self._torrc_load_error = msg('panel.torrc.unable_to_load_torrc', error = exc_msg) self._torrc_content = None - def set_comments_visible(self, is_visible): - """ - Sets if comments and blank lines are shown or stripped. - - :var bool is_visible: shows comments if true, strips otherwise - """ - - self._show_comments = is_visible - self.redraw() - - def set_line_number_visible(self, is_visible): - """ - Sets if line numbers are shown or hidden. - - :var bool is_visible: displays line numbers if true, hides otherwise - """ - - self._show_line_numbers = is_visible - self.redraw() - def key_handlers(self): def _scroll(key): page_height = self.get_height() - 1 @@ -97,10 +79,10 @@ class TorrcPanel(panel.Panel): self.redraw() def _toggle_comment_stripping(): - self.set_comments_visible(not self._show_comments) + self._show_comments = not self._show_comments def _toggle_line_numbers(): - self.set_line_number_visible(not self._show_line_numbers) + self._show_line_numbers = not self._show_line_numbers return ( nyx.panel.KeyHandler('arrows', 'scroll up and down', _scroll, key_func = lambda key: key.is_scroll()), @@ -108,6 +90,23 @@ class TorrcPanel(panel.Panel): nyx.panel.KeyHandler('l', 'line numbering', _toggle_line_numbers, 'on' if self._show_line_numbers else 'off'), ) + def submenu(self): + """ + Submenu consisting of... + + Reload + Show / Hide Comments + Show / Hide Line Numbers + """ + + comments_label, comments_arg = ('Hide Comments', False) if self._show_comments else ('Show Comments', True) + line_number_label, line_number_arg = ('Hide Line Numbers', False) if self._show_line_numbers else ('Show Line Numbers', True) + + return Submenu('Torrc', [ + MenuItem(comments_label, functools.partial(setattr, self, '_show_comments'), comments_arg), + MenuItem(line_number_label, functools.partial(setattr, self, '_show_line_numbers'), line_number_arg), + ]) + def _draw(self, subwindow): scroll = self._scroller.location(self._last_content_height, subwindow.height - 1)
participants (1)
-
atagar@torproject.org