[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [nyx/master] Move submenus to panels
commit c9467743eb00f282c36677ef37d6dda5e23856be
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
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)
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits