[tor-commits] [arm/release] Moving sort selection out of the controller

atagar at torproject.org atagar at torproject.org
Sun Jul 17 06:08:18 UTC 2011


commit 77dc38f4fdd098a124b2973a86c267bdfd126f92
Author: Damian Johnson <atagar at 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
+





More information about the tor-commits mailing list