commit 77dc38f4fdd098a124b2973a86c267bdfd126f92 Author: Damian Johnson atagar@torproject.org Date: Sat May 7 12:29:59 2011 -0700
Moving sort selection out of the controller
Sort dialogs are now provided by the popups toolkit, and triggered by the panels that want to sort themselves. --- src/cli/configPanel.py | 25 ++++++++ src/cli/connections/connPanel.py | 10 +++ src/cli/controller.py | 125 -------------------------------------- src/cli/popups.py | 106 ++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 125 deletions(-)
diff --git a/src/cli/configPanel.py b/src/cli/configPanel.py index 90c6191..6aaafc2 100644 --- a/src/cli/configPanel.py +++ b/src/cli/configPanel.py @@ -6,6 +6,8 @@ and the resulting configuration files saved. import curses import threading
+import popups + from util import conf, enum, panel, torTools, torConfig, uiTools
DEFAULT_CONFIG = {"features.config.selectionDetails.height": 6, @@ -43,6 +45,16 @@ FIELD_ATTR = {Field.CATEGORY: ("Category", "red"), Field.MAN_ENTRY: ("Man Page Entry", "blue"), Field.IS_DEFAULT: ("Is Default", "magenta")}
+def getFieldFromLabel(fieldLabel): + """ + Converts field labels back to their enumeration, raising a ValueError if it + doesn't exist. + """ + + for entryEnum in FIELD_ATTR: + if fieldLabel == FIELD_ATTR[entryEnum][0]: + return entryEnum + class ConfigEntry(): """ Configuration option in the panel. @@ -246,6 +258,19 @@ class ConfigPanel(panel.Panel): elif key == ord('a') or key == ord('A'): self.showAll = not self.showAll self.redraw(True) + elif key == ord('s') or key == ord('S'): + # set ordering for config options + titleLabel = "Config Option Ordering:" + options = [FIELD_ATTR[field][0] for field in Field.values()] + oldSelection = [FIELD_ATTR[field][0] for field in self.sortOrdering] + optionColors = dict([FIELD_ATTR[field] for field in Field.values()]) + results = popups.showSortDialog(titleLabel, options, oldSelection, optionColors) + + if results: + # converts labels back to enums + resultEnums = [getFieldFromLabel(label) for label in results] + self.setSortOrder(resultEnums) + self.valsLock.release()
def getHelp(self): diff --git a/src/cli/connections/connPanel.py b/src/cli/connections/connPanel.py index 40c479e..8ad41d5 100644 --- a/src/cli/connections/connPanel.py +++ b/src/cli/connections/connPanel.py @@ -6,6 +6,8 @@ import time import curses import threading
+import cli.popups + from cli.connections import entries, connEntry, circEntry from util import connections, enum, panel, torTools, uiTools
@@ -149,6 +151,14 @@ class ConnectionPanel(panel.Panel, threading.Thread): elif uiTools.isSelectionKey(key): self._showDetails = not self._showDetails self.redraw(True) + elif key == ord('s') or key == ord('S'): + # set ordering for connection options + titleLabel = "Connection Ordering:" + options = entries.SortAttr.values() + oldSelection = self._sortOrdering + optionColors = dict([(attr, entries.SORT_COLORS[attr]) for attr in options]) + results = cli.popups.showSortDialog(titleLabel, options, oldSelection, optionColors) + if results: self.setSortOrder(results)
self.valsLock.release()
diff --git a/src/cli/controller.py b/src/cli/controller.py index 1501419..09e3575 100644 --- a/src/cli/controller.py +++ b/src/cli/controller.py @@ -326,98 +326,6 @@ def showMenu(stdscr, popup, title, options, initialSelection):
return selection
-def showSortDialog(stdscr, panels, isPaused, page, titleLabel, options, oldSelection, optionColors): - """ - Displays a sorting dialog of the form: - - Current Order: <previous selection> - New Order: <selections made> - - <option 1> <option 2> <option 3> Cancel - - Options are colored when among the "Current Order" or "New Order", but not - when an option below them. If cancel is selected or the user presses escape - then this returns None. Otherwise, the new ordering is provided. - - Arguments: - stdscr, panels, isPaused, page - boiler plate arguments of the controller - (should be refactored away when rewriting) - - titleLabel - title displayed for the popup window - options - ordered listing of option labels - oldSelection - current ordering - optionColors - mappings of options to their color - - """ - - panel.CURSES_LOCK.acquire() - newSelections = [] # new ordering - - try: - setPauseState(panels, isPaused, page, True) - curses.cbreak() # wait indefinitely for key presses (no timeout) - - popup = panels["popup"] - cursorLoc = 0 # index of highlighted option - - # label for the inital ordering - formattedPrevListing = [] - for sortType in oldSelection: - colorStr = optionColors.get(sortType, "white") - formattedPrevListing.append("<%s>%s</%s>" % (colorStr, sortType, colorStr)) - prevOrderingLabel = "<b>Current Order: %s</b>" % ", ".join(formattedPrevListing) - - selectionOptions = list(options) - selectionOptions.append("Cancel") - - while len(newSelections) < len(oldSelection): - popup.clear() - popup.win.box() - popup.addstr(0, 0, titleLabel, curses.A_STANDOUT) - popup.addfstr(1, 2, prevOrderingLabel) - - # provides new ordering - formattedNewListing = [] - for sortType in newSelections: - colorStr = optionColors.get(sortType, "white") - formattedNewListing.append("<%s>%s</%s>" % (colorStr, sortType, colorStr)) - newOrderingLabel = "<b>New Order: %s</b>" % ", ".join(formattedNewListing) - popup.addfstr(2, 2, newOrderingLabel) - - # presents remaining options, each row having up to four options with - # spacing of nineteen cells - row, col = 4, 0 - for i in range(len(selectionOptions)): - popup.addstr(row, col * 19 + 2, selectionOptions[i], curses.A_STANDOUT if cursorLoc == i else curses.A_NORMAL) - col += 1 - if col == 4: row, col = row + 1, 0 - - popup.refresh() - - key = stdscr.getch() - if key == curses.KEY_LEFT: cursorLoc = max(0, cursorLoc - 1) - elif key == curses.KEY_RIGHT: cursorLoc = min(len(selectionOptions) - 1, cursorLoc + 1) - elif key == curses.KEY_UP: cursorLoc = max(0, cursorLoc - 4) - elif key == curses.KEY_DOWN: cursorLoc = min(len(selectionOptions) - 1, cursorLoc + 4) - elif uiTools.isSelectionKey(key): - # selected entry (the ord of '10' seems needed to pick up enter) - selection = selectionOptions[cursorLoc] - if selection == "Cancel": break - else: - newSelections.append(selection) - selectionOptions.remove(selection) - cursorLoc = min(cursorLoc, len(selectionOptions) - 1) - elif key == 27: break # esc - cancel - - setPauseState(panels, isPaused, page) - curses.halfdelay(REFRESH_RATE * 10) # reset normal pausing behavior - finally: - panel.CURSES_LOCK.release() - - if len(newSelections) == len(oldSelection): - return newSelections - else: return None - def setEventListening(selectedEvents, isBlindMode): # creates a local copy, note that a suspected python bug causes *very* # puzzling results otherwise when trying to discard entries (silently @@ -1282,18 +1190,6 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode): if selection != -1 and options[selection] != panels["conn"]._listingType: panels["conn"].setListingType(options[selection]) panels["conn"].redraw(True) - elif page == 1 and (key == ord('s') or key == ord('S')): - # set ordering for connection options - titleLabel = "Connection Ordering:" - options = cli.connections.entries.SortAttr.values() - oldSelection = panels["conn"]._sortOrdering - optionColors = dict([(attr, cli.connections.entries.SORT_COLORS[attr]) for attr in options]) - results = showSortDialog(stdscr, panels, isPaused, page, titleLabel, options, oldSelection, optionColors) - - if results: - panels["conn"].setSortOrder(results) - - panels["conn"].redraw(True) elif page == 2 and (key == ord('c') or key == ord('C')) and False: # TODO: disabled for now (probably gonna be going with separate pages # rather than popup menu) @@ -1446,27 +1342,6 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode): panel.CURSES_LOCK.release()
panels["config"].redraw(True) - elif page == 2 and (key == ord('s') or key == ord('S')): - # set ordering for config options - titleLabel = "Config Option Ordering:" - options = [configPanel.FIELD_ATTR[field][0] for field in configPanel.Field.values()] - oldSelection = [configPanel.FIELD_ATTR[field][0] for field in panels["config"].sortOrdering] - optionColors = dict([configPanel.FIELD_ATTR[field] for field in configPanel.Field.values()]) - results = showSortDialog(stdscr, panels, isPaused, page, titleLabel, options, oldSelection, optionColors) - - if results: - # converts labels back to enums - resultEnums = [] - - for label in results: - for entryEnum in configPanel.FIELD_ATTR: - if label == configPanel.FIELD_ATTR[entryEnum][0]: - resultEnums.append(entryEnum) - break - - panels["config"].setSortOrder(resultEnums) - - panels["config"].redraw(True) elif page == 2 and uiTools.isSelectionKey(key): # let the user edit the configuration value, unchanged if left blank panel.CURSES_LOCK.acquire() diff --git a/src/cli/popups.py b/src/cli/popups.py index ce51ee8..d5cf76c 100644 --- a/src/cli/popups.py +++ b/src/cli/popups.py @@ -108,3 +108,109 @@ def showHelpPopup(): return exitKey else: return None
+def showSortDialog(titleLabel, options, oldSelection, optionColors): + """ + Displays a sorting dialog of the form: + + Current Order: <previous selection> + New Order: <selections made> + + <option 1> <option 2> <option 3> Cancel + + Options are colored when among the "Current Order" or "New Order", but not + when an option below them. If cancel is selected or the user presses escape + then this returns None. Otherwise, the new ordering is provided. + + Arguments: + titleLabel - title displayed for the popup window + options - ordered listing of option labels + oldSelection - current ordering + optionColors - mappings of options to their color + """ + + popup, width, height = init(9, 80) + if not popup: return + newSelections = [] # new ordering + + try: + cursorLoc = 0 # index of highlighted option + curses.cbreak() # wait indefinitely for key presses (no timeout) + + selectionOptions = list(options) + selectionOptions.append("Cancel") + + while len(newSelections) < len(oldSelection): + popup.win.erase() + popup.win.box() + popup.addstr(0, 0, titleLabel, curses.A_STANDOUT) + + _drawSortSelection(popup, 1, 2, "Current Order: ", oldSelection, optionColors) + _drawSortSelection(popup, 2, 2, "New Order: ", newSelections, optionColors) + + # presents remaining options, each row having up to four options with + # spacing of nineteen cells + row, col = 4, 0 + for i in range(len(selectionOptions)): + optionFormat = curses.A_STANDOUT if cursorLoc == i else curses.A_NORMAL + popup.addstr(row, col * 19 + 2, selectionOptions[i], optionFormat) + col += 1 + if col == 4: row, col = row + 1, 0 + + popup.win.refresh() + + key = controller.getScreen().getch() + if key == curses.KEY_LEFT: + cursorLoc = max(0, cursorLoc - 1) + elif key == curses.KEY_RIGHT: + cursorLoc = min(len(selectionOptions) - 1, cursorLoc + 1) + elif key == curses.KEY_UP: + cursorLoc = max(0, cursorLoc - 4) + elif key == curses.KEY_DOWN: + cursorLoc = min(len(selectionOptions) - 1, cursorLoc + 4) + elif uiTools.isSelectionKey(key): + selection = selectionOptions[cursorLoc] + + if selection == "Cancel": break + else: + newSelections.append(selection) + selectionOptions.remove(selection) + cursorLoc = min(cursorLoc, len(selectionOptions) - 1) + elif key == 27: break # esc - cancel + + curses.halfdelay(controller.REFRESH_RATE * 10) # reset normal pausing behavior + finally: finalize() + + if len(newSelections) == len(oldSelection): + return newSelections + else: return None + +def _drawSortSelection(popup, y, x, prefix, options, optionColors): + """ + Draws a series of comma separated sort selections. The whole line is bold + and sort options also have their specified color. Example: + + Current Order: Man Page Entry, Option Name, Is Default + + Arguments: + popup - panel in which to draw sort selection + y - vertical location + x - horizontal location + prefix - initial string description + options - sort options to be shown + optionColors - mappings of options to their color + """ + + popup.addstr(y, x, prefix, curses.A_BOLD) + x += len(prefix) + + for i in range(len(options)): + sortType = options[i] + sortColor = uiTools.getColor(optionColors.get(sortType, "white")) + popup.addstr(y, x, sortType, sortColor | curses.A_BOLD) + x += len(sortType) + + # comma divider between options, if this isn't the last + if i < len(options) - 1: + popup.addstr(y, x, ", ", curses.A_BOLD) + x += 2 +
tor-commits@lists.torproject.org