tor-commits
Threads by month
- ----- 2026 -----
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 1 participants
- 214634 discussions
commit ea0b39251a9371cd81262bc360c644ab18acf1c8
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun Jun 12 12:11:23 2011 -0700
Binding handlers for the graph submenu
---
src/cli/graphing/graphPanel.py | 121 ++++++++++++++++++++++++++++------------
src/cli/menu/actions.py | 75 +++++++++++++++++++------
src/util/uiTools.py | 10 ++-
3 files changed, 150 insertions(+), 56 deletions(-)
diff --git a/src/cli/graphing/graphPanel.py b/src/cli/graphing/graphPanel.py
index 0207604..69b9121 100644
--- a/src/cli/graphing/graphPanel.py
+++ b/src/cli/graphing/graphPanel.py
@@ -239,6 +239,40 @@ class GraphPanel(panel.Panel):
self.stats = {} # available stats (mappings of label -> instance)
self.setPauseAttr("stats")
+ def getUpdateInterval(self):
+ """
+ Provides the rate that we update the graph at.
+ """
+
+ return self.updateInterval
+
+ def setUpdateInterval(self, updateInterval):
+ """
+ Sets the rate that we update the graph at.
+
+ Arguments:
+ updateInterval - update time enum
+ """
+
+ self.updateInterval = updateInterval
+
+ def getBoundsType(self):
+ """
+ Provides the type of graph bounds used.
+ """
+
+ return self.bounds
+
+ def setBoundsType(self, boundsType):
+ """
+ Sets the type of graph boundaries we use.
+
+ Arguments:
+ boundsType - graph bounds enum
+ """
+
+ self.bounds = boundsType
+
def getHeight(self):
"""
Provides the height requested by the currently displayed GraphStats (zero
@@ -260,44 +294,54 @@ class GraphPanel(panel.Panel):
self.graphHeight = max(MIN_GRAPH_HEIGHT, newGraphHeight)
+ def resizeGraph(self):
+ """
+ Prompts for user input to resize the graph panel. Options include...
+ down arrow - grow graph
+ up arrow - shrink graph
+ enter / space - set size
+ """
+
+ control = cli.controller.getController()
+
+ panel.CURSES_LOCK.acquire()
+ try:
+ while True:
+ # redraws the resized panels
+ displayPanels = control.getDisplayPanels()
+
+ occupiedContent = 0
+ for panelImpl in displayPanels:
+ panelImpl.setTop(occupiedContent)
+ occupiedContent += panelImpl.getHeight()
+
+ for panelImpl in displayPanels:
+ panelImpl.redraw(True)
+
+ msg = "press the down/up to resize the graph, and enter when done"
+ control.setMsg(msg, curses.A_BOLD, True)
+ curses.cbreak()
+ key = control.getScreen().getch()
+
+ if key == curses.KEY_DOWN:
+ # don't grow the graph if it's already consuming the whole display
+ # (plus an extra line for the graph/log gap)
+ maxHeight = self.parent.getmaxyx()[0] - self.top
+ currentHeight = self.getHeight()
+
+ if currentHeight < maxHeight + 1:
+ self.setGraphHeight(self.graphHeight + 1)
+ elif key == curses.KEY_UP:
+ self.setGraphHeight(self.graphHeight - 1)
+ elif uiTools.isSelectionKey(key): break
+ finally:
+ control.setMsg()
+ panel.CURSES_LOCK.release()
+
def handleKey(self, key):
isKeystrokeConsumed = True
if key == ord('r') or key == ord('R'):
- control = cli.controller.getController()
-
- panel.CURSES_LOCK.acquire()
- try:
- while True:
- msg = "press the down/up to resize the graph, and enter when done"
- control.setMsg(msg, curses.A_BOLD, True)
- curses.cbreak()
- key = control.getScreen().getch()
-
- if key == curses.KEY_DOWN:
- # don't grow the graph if it's already consuming the whole display
- # (plus an extra line for the graph/log gap)
- maxHeight = self.parent.getmaxyx()[0] - self.top
- currentHeight = self.getHeight()
-
- if currentHeight < maxHeight + 1:
- self.setGraphHeight(self.graphHeight + 1)
- elif key == curses.KEY_UP:
- self.setGraphHeight(self.graphHeight - 1)
- elif uiTools.isSelectionKey(key): break
-
- # redraws the resized panels
- displayPanels = control.getDisplayPanels()
-
- occupiedContent = 0
- for panelImpl in displayPanels:
- panelImpl.setTop(occupiedContent)
- occupiedContent += panelImpl.getHeight()
-
- for panelImpl in displayPanels:
- panelImpl.redraw(True)
- finally:
- control.setMsg()
- panel.CURSES_LOCK.release()
+ self.resizeGraph()
elif key == ord('b') or key == ord('B'):
# uses the next boundary type
self.bounds = Bounds.next(self.bounds)
@@ -447,6 +491,13 @@ class GraphPanel(panel.Panel):
stats._graphPanel = self
self.stats[label] = stats
+ def getStats(self):
+ """
+ Provides the currently selected stats label.
+ """
+
+ return self.currentDisplay
+
def setStats(self, label):
"""
Sets the currently displayed stats instance, hiding panel if None.
diff --git a/src/cli/menu/actions.py b/src/cli/menu/actions.py
index f81a162..9d69cb4 100644
--- a/src/cli/menu/actions.py
+++ b/src/cli/menu/actions.py
@@ -6,6 +6,7 @@ import functools
import cli.controller
import cli.menu.item
+import cli.graphing.graphPanel
from util import torTools, uiTools
@@ -18,6 +19,12 @@ def makeMenu():
baseMenu.add(makeActionsMenu())
baseMenu.add(makeViewMenu())
+ control = cli.controller.getController()
+
+ for pagePanel in control.getDisplayPanels(includeSticky = False):
+ if pagePanel.getName() == "graph":
+ baseMenu.add(makeGraphMenu(pagePanel))
+
logsMenu = cli.menu.item.Submenu("Logs")
logsMenu.add(cli.menu.item.MenuItem("Events", None))
logsMenu.add(cli.menu.item.MenuItem("Clear", None))
@@ -30,23 +37,6 @@ def makeMenu():
logsMenu.add(duplicatesSubmenu)
baseMenu.add(logsMenu)
- graphMenu = cli.menu.item.Submenu("Graph")
- graphMenu.add(cli.menu.item.MenuItem("Stats", None))
-
- sizeSubmenu = cli.menu.item.Submenu("Size")
- sizeSubmenu.add(cli.menu.item.MenuItem("Increase", None))
- sizeSubmenu.add(cli.menu.item.MenuItem("Decrease", None))
- graphMenu.add(sizeSubmenu)
-
- graphMenu.add(cli.menu.item.MenuItem("Update Interval", None))
-
- boundsSubmenu = cli.menu.item.Submenu("Bounds")
- boundsSubmenu.add(cli.menu.item.MenuItem("Local Max", None))
- boundsSubmenu.add(cli.menu.item.MenuItem("Global Max", None))
- boundsSubmenu.add(cli.menu.item.MenuItem("Tight", None))
- graphMenu.add(boundsSubmenu)
- baseMenu.add(graphMenu)
-
connectionsMenu = cli.menu.item.Submenu("Connections")
connectionsMenu.add(cli.menu.item.MenuItem("Identity", None))
connectionsMenu.add(cli.menu.item.MenuItem("Resolver", None))
@@ -121,3 +111,54 @@ def makeViewMenu():
return viewMenu
+def makeGraphMenu(graphPanel):
+ """
+ Submenu for the graph panel, consisting of...
+ [X] <Stat 1>
+ [ ] <Stat 2>
+ [ ] <Stat 2>
+ Resize
+ Interval (Submenu)
+ Bounds (Submenu)
+
+ Arguments:
+ graphPanel - instance of the graph panel
+ """
+
+ graphMenu = cli.menu.item.Submenu("Graph")
+
+ # stats options
+ statGroup = cli.menu.item.SelectionGroup(graphPanel.setStats, graphPanel.getStats())
+ availableStats = graphPanel.stats.keys()
+ availableStats.sort()
+
+ for statKey in ["None"] + availableStats:
+ label = uiTools.camelCase(statKey, divider = " ")
+ statKey = None if statKey == "None" else statKey
+ graphMenu.add(cli.menu.item.SelectionMenuItem(label, statGroup, statKey))
+
+ # resizing option
+ graphMenu.add(cli.menu.item.MenuItem("Resize", graphPanel.resizeGraph))
+
+ # interval submenu
+ intervalMenu = cli.menu.item.Submenu("Interval")
+ intervalGroup = cli.menu.item.SelectionGroup(graphPanel.setUpdateInterval, graphPanel.getUpdateInterval())
+
+ for i in range(len(cli.graphing.graphPanel.UPDATE_INTERVALS)):
+ label = cli.graphing.graphPanel.UPDATE_INTERVALS[i][0]
+ label = uiTools.camelCase(label, divider = " ")
+ intervalMenu.add(cli.menu.item.SelectionMenuItem(label, intervalGroup, i))
+
+ graphMenu.add(intervalMenu)
+
+ # bounds submenu
+ boundsMenu = cli.menu.item.Submenu("Bounds")
+ boundsGroup = cli.menu.item.SelectionGroup(graphPanel.setBoundsType, graphPanel.getBoundsType())
+
+ for boundsType in cli.graphing.graphPanel.Bounds.values():
+ boundsMenu.add(cli.menu.item.SelectionMenuItem(boundsType, boundsGroup, boundsType))
+
+ graphMenu.add(boundsMenu)
+
+ return graphMenu
+
diff --git a/src/util/uiTools.py b/src/util/uiTools.py
index 34d9210..5204960 100644
--- a/src/util/uiTools.py
+++ b/src/util/uiTools.py
@@ -272,23 +272,25 @@ def cropStr(msg, size, minWordLen = 4, minCrop = 0, endType = Ending.ELLIPSE, ge
if getRemainder: return (returnMsg, remainder)
else: return returnMsg
-def camelCase(label):
+def camelCase(label, divider = "_", joiner = " "):
"""
Converts the given string to camel case, ie:
>>> camelCase("I_LIKE_PEPPERJACK!")
'I Like Pepperjack!'
Arguments:
- label - input string to be converted
+ label - input string to be converted
+ divider - character to be used for word breaks
+ joiner - character used to fill between word breaks
"""
words = []
- for entry in label.split("_"):
+ for entry in label.split(divider):
if len(entry) == 0: words.append("")
elif len(entry) == 1: words.append(entry.upper())
else: words.append(entry[0].upper() + entry[1:].lower())
- return " ".join(words)
+ return joiner.join(words)
def drawBox(panel, top, left, width, height, attr=curses.A_NORMAL):
"""
1
0
17 Jul '11
commit 6ae0b6e6aa1481718443f3e367a91d15a5bdaa6f
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun Jun 12 13:48:13 2011 -0700
Binding handlers for the connections submenu
---
src/cli/connections/connPanel.py | 30 +++++++++++++++++-----
src/cli/menu/actions.py | 50 ++++++++++++++++++++++++++++++++-----
src/util/connections.py | 19 ++++++++++++++
3 files changed, 85 insertions(+), 14 deletions(-)
diff --git a/src/cli/connections/connPanel.py b/src/cli/connections/connPanel.py
index 8b86c65..9490ddc 100644
--- a/src/cli/connections/connPanel.py
+++ b/src/cli/connections/connPanel.py
@@ -6,6 +6,7 @@ import time
import curses
import threading
+import cli.controller
import cli.descriptorPopup
import cli.popups
@@ -124,6 +125,13 @@ class ConnectionPanel(panel.Panel, threading.Thread):
self._entryLines += entry.getLines()
self.valsLock.release()
+ def getListingType(self):
+ """
+ Provides the priority content we list connections by.
+ """
+
+ return self._listingType
+
def setListingType(self, listingType):
"""
Sets the priority information presented by the panel.
@@ -143,6 +151,20 @@ class ConnectionPanel(panel.Panel, threading.Thread):
self.valsLock.release()
+ def showSortDialog(self):
+ """
+ Provides the sort dialog for our connections.
+ """
+
+ # set ordering for connection options
+ cli.controller.getController().requestRedraw(True)
+ 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)
+
def handleKey(self, key):
self.valsLock.acquire()
@@ -156,13 +178,7 @@ class ConnectionPanel(panel.Panel, threading.Thread):
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.showSortDialog()
elif key == ord('u') or key == ord('U'):
# provides a menu to pick the connection resolver
title = "Resolver Util:"
diff --git a/src/cli/menu/actions.py b/src/cli/menu/actions.py
index c8b8da3..2827742 100644
--- a/src/cli/menu/actions.py
+++ b/src/cli/menu/actions.py
@@ -8,7 +8,7 @@ import cli.controller
import cli.menu.item
import cli.graphing.graphPanel
-from util import torTools, uiTools
+from util import connections, torTools, uiTools
def makeMenu():
"""
@@ -26,12 +26,8 @@ def makeMenu():
baseMenu.add(makeGraphMenu(pagePanel))
elif pagePanel.getName() == "log":
baseMenu.add(makeLogMenu(pagePanel))
-
- connectionsMenu = cli.menu.item.Submenu("Connections")
- connectionsMenu.add(cli.menu.item.MenuItem("Identity", None))
- connectionsMenu.add(cli.menu.item.MenuItem("Resolver", None))
- connectionsMenu.add(cli.menu.item.MenuItem("Sort Order", None))
- baseMenu.add(connectionsMenu)
+ elif pagePanel.getName() == "connections":
+ baseMenu.add(makeConnectionsMenu(pagePanel))
configurationMenu = cli.menu.item.Submenu("Configuration")
@@ -188,5 +184,45 @@ def makeLogMenu(logPanel):
logMenu.add(filterMenu)
return logMenu
+
+def makeConnectionsMenu(connPanel):
+ """
+ Submenu for the connections panel, consisting of...
+ [X] IP Address
+ [ ] Fingerprint
+ [ ] Nickname
+ Sorting...
+ Resolver (Submenu)
+
+ Arguments:
+ connPanel - instance of the connections panel
+ """
+
+ connectionsMenu = cli.menu.item.Submenu("Connections")
+
+ # listing options
+ listingGroup = cli.menu.item.SelectionGroup(connPanel.setListingType, connPanel.getListingType())
+
+ listingOptions = cli.connections.entries.ListingType.values()
+ listingOptions.remove(cli.connections.entries.ListingType.HOSTNAME)
+
+ for option in listingOptions:
+ connectionsMenu.add(cli.menu.item.SelectionMenuItem(option, listingGroup, option))
+
+ # sorting option
+ connectionsMenu.add(cli.menu.item.MenuItem("Sorting...", connPanel.showSortDialog))
+
+ # resolver submenu
+ connResolver = connections.getResolver("tor")
+ resolverMenu = cli.menu.item.Submenu("Resolver")
+ resolverGroup = cli.menu.item.SelectionGroup(connResolver.setOverwriteResolver, connResolver.getOverwriteResolver())
+
+ resolverMenu.add(cli.menu.item.SelectionMenuItem("auto", resolverGroup, None))
+
+ for option in connections.Resolver.values():
+ resolverMenu.add(cli.menu.item.SelectionMenuItem(option, resolverGroup, option))
+
+ connectionsMenu.add(resolverMenu)
+ return connectionsMenu
diff --git a/src/util/connections.py b/src/util/connections.py
index 47aa8af..97de3ea 100644
--- a/src/util/connections.py
+++ b/src/util/connections.py
@@ -444,6 +444,25 @@ class ConnectionResolver(threading.Thread):
# avoid having stray spikes up the rate.
self._rateThresholdBroken = 0
+ def getOverwriteResolver(self):
+ """
+ Provides the resolver connection resolution is forced to use. This returns
+ None if it's dynamically determined.
+ """
+
+ return self.overwriteResolver
+
+ def setOverwriteResolver(self, overwriteResolver):
+ """
+ Sets the resolver used for connection resolution, if None then this is
+ automatically determined based on what is available.
+
+ Arguments:
+ overwriteResolver - connection resolver to be used
+ """
+
+ self.overwriteResolver = overwriteResolver
+
def run(self):
while not self._halt:
minWait = self.resolveRate if self.resolveRate else self.defaultRate
1
0
17 Jul '11
commit 93875272baf20437578a4b3e18e4b39a8a9efb9e
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun Jun 12 14:08:31 2011 -0700
Binding handlers for the configuration submenu
---
src/cli/configPanel.py | 232 ++++++++++++++++++++++++++---------------------
src/cli/menu/actions.py | 34 +++++--
2 files changed, 153 insertions(+), 113 deletions(-)
diff --git a/src/cli/configPanel.py b/src/cli/configPanel.py
index c2e290d..4647286 100644
--- a/src/cli/configPanel.py
+++ b/src/cli/configPanel.py
@@ -6,7 +6,7 @@ and the resulting configuration files saved.
import curses
import threading
-import controller
+import cli.controller
import popups
from util import conf, enum, panel, sysTools, torConfig, torTools, uiTools
@@ -242,6 +242,17 @@ class ConfigPanel(panel.Panel):
return self.scroller.getCursorSelection(self._getConfigOptions())
+ def setFiltering(self, isFiltered):
+ """
+ Sets if configuration options are filtered or not.
+
+ Arguments:
+ isFiltered - if true then only relatively important options will be
+ shown, otherwise everything is shown
+ """
+
+ self.showAll = not isFiltered
+
def setSortOrder(self, ordering = None):
"""
Sets the configuration attributes we're sorting by and resorts the
@@ -258,6 +269,24 @@ class ConfigPanel(panel.Panel):
self.confImportantContents.sort(key=lambda i: (i.getAll(self.sortOrdering)))
self.valsLock.release()
+ def showSortDialog(self):
+ """
+ Provides the sort dialog for our configuration options.
+ """
+
+ # set ordering for config options
+ cli.controller.getController().requestRedraw(True)
+ 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)
+
def handleKey(self, key):
self.valsLock.acquire()
isKeystrokeConsumed = True
@@ -313,118 +342,117 @@ class ConfigPanel(panel.Panel):
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.showSortDialog()
elif key == ord('w') or key == ord('W'):
- # display a popup for saving the current configuration
- configLines = torConfig.getCustomOptions(True)
- popup, width, height = popups.init(len(configLines) + 2)
- if not popup: return
+ self.showWriteDialog()
+ else: isKeystrokeConsumed = False
+
+ self.valsLock.release()
+ return isKeystrokeConsumed
+
+ def showWriteDialog(self):
+ """
+ Provies an interface to confirm if the configuration is saved and, if so,
+ where.
+ """
+
+ # display a popup for saving the current configuration
+ cli.controller.getController().requestRedraw(True)
+ configLines = torConfig.getCustomOptions(True)
+ popup, width, height = popups.init(len(configLines) + 2)
+ if not popup: return
+
+ try:
+ # displayed options (truncating the labels if there's limited room)
+ if width >= 30: selectionOptions = ("Save", "Save As...", "Cancel")
+ else: selectionOptions = ("Save", "Save As", "X")
- try:
- # displayed options (truncating the labels if there's limited room)
- if width >= 30: selectionOptions = ("Save", "Save As...", "Cancel")
- else: selectionOptions = ("Save", "Save As", "X")
+ # checks if we can show options beside the last line of visible content
+ isOptionLineSeparate = False
+ lastIndex = min(height - 2, len(configLines) - 1)
+
+ # if we don't have room to display the selection options and room to
+ # grow then display the selection options on its own line
+ if width < (30 + len(configLines[lastIndex])):
+ popup.setHeight(height + 1)
+ popup.redraw(True) # recreates the window instance
+ newHeight, _ = popup.getPreferredSize()
- # checks if we can show options beside the last line of visible content
- isOptionLineSeparate = False
- lastIndex = min(height - 2, len(configLines) - 1)
+ if newHeight > height:
+ height = newHeight
+ isOptionLineSeparate = True
+
+ key, selection = 0, 2
+ while not uiTools.isSelectionKey(key):
+ # if the popup has been resized then recreate it (needed for the
+ # proper border height)
+ newHeight, newWidth = popup.getPreferredSize()
+ if (height, width) != (newHeight, newWidth):
+ height, width = newHeight, newWidth
+ popup.redraw(True)
- # if we don't have room to display the selection options and room to
- # grow then display the selection options on its own line
- if width < (30 + len(configLines[lastIndex])):
- popup.setHeight(height + 1)
- popup.redraw(True) # recreates the window instance
- newHeight, _ = popup.getPreferredSize()
-
- if newHeight > height:
- height = newHeight
- isOptionLineSeparate = True
+ # if there isn't room to display the popup then cancel it
+ if height <= 2:
+ selection = 2
+ break
- key, selection = 0, 2
- while not uiTools.isSelectionKey(key):
- # if the popup has been resized then recreate it (needed for the
- # proper border height)
- newHeight, newWidth = popup.getPreferredSize()
- if (height, width) != (newHeight, newWidth):
- height, width = newHeight, newWidth
- popup.redraw(True)
-
- # if there isn't room to display the popup then cancel it
- if height <= 2:
- selection = 2
- break
-
- popup.win.erase()
- popup.win.box()
- popup.addstr(0, 0, "Configuration being saved:", curses.A_STANDOUT)
+ popup.win.erase()
+ popup.win.box()
+ popup.addstr(0, 0, "Configuration being saved:", curses.A_STANDOUT)
+
+ visibleConfigLines = height - 3 if isOptionLineSeparate else height - 2
+ for i in range(visibleConfigLines):
+ line = uiTools.cropStr(configLines[i], width - 2)
- visibleConfigLines = height - 3 if isOptionLineSeparate else height - 2
- for i in range(visibleConfigLines):
- line = uiTools.cropStr(configLines[i], width - 2)
-
- if " " in line:
- option, arg = line.split(" ", 1)
- popup.addstr(i + 1, 1, option, curses.A_BOLD | uiTools.getColor("green"))
- popup.addstr(i + 1, len(option) + 2, arg, curses.A_BOLD | uiTools.getColor("cyan"))
- else:
- popup.addstr(i + 1, 1, line, curses.A_BOLD | uiTools.getColor("green"))
+ if " " in line:
+ option, arg = line.split(" ", 1)
+ popup.addstr(i + 1, 1, option, curses.A_BOLD | uiTools.getColor("green"))
+ popup.addstr(i + 1, len(option) + 2, arg, curses.A_BOLD | uiTools.getColor("cyan"))
+ else:
+ popup.addstr(i + 1, 1, line, curses.A_BOLD | uiTools.getColor("green"))
+
+ # draws selection options (drawn right to left)
+ drawX = width - 1
+ for i in range(len(selectionOptions) - 1, -1, -1):
+ optionLabel = selectionOptions[i]
+ drawX -= (len(optionLabel) + 2)
- # draws selection options (drawn right to left)
- drawX = width - 1
- for i in range(len(selectionOptions) - 1, -1, -1):
- optionLabel = selectionOptions[i]
- drawX -= (len(optionLabel) + 2)
-
- # if we've run out of room then drop the option (this will only
- # occure on tiny displays)
- if drawX < 1: break
-
- selectionFormat = curses.A_STANDOUT if i == selection else curses.A_NORMAL
- popup.addstr(height - 2, drawX, "[")
- popup.addstr(height - 2, drawX + 1, optionLabel, selectionFormat | curses.A_BOLD)
- popup.addstr(height - 2, drawX + len(optionLabel) + 1, "]")
-
- drawX -= 1 # space gap between the options
+ # if we've run out of room then drop the option (this will only
+ # occure on tiny displays)
+ if drawX < 1: break
- popup.win.refresh()
+ selectionFormat = curses.A_STANDOUT if i == selection else curses.A_NORMAL
+ popup.addstr(height - 2, drawX, "[")
+ popup.addstr(height - 2, drawX + 1, optionLabel, selectionFormat | curses.A_BOLD)
+ popup.addstr(height - 2, drawX + len(optionLabel) + 1, "]")
- key = controller.getController().getScreen().getch()
- if key == curses.KEY_LEFT: selection = max(0, selection - 1)
- elif key == curses.KEY_RIGHT: selection = min(len(selectionOptions) - 1, selection + 1)
+ drawX -= 1 # space gap between the options
- if selection in (0, 1):
- loadedTorrc, promptCanceled = torConfig.getTorrc(), False
- try: configLocation = loadedTorrc.getConfigLocation()
- except IOError: configLocation = ""
-
- if selection == 1:
- # prompts user for a configuration location
- configLocation = popups.inputPrompt("Save to (esc to cancel): ", configLocation)
- if not configLocation: promptCanceled = True
+ popup.win.refresh()
+
+ key = cli.controller.getController().getScreen().getch()
+ if key == curses.KEY_LEFT: selection = max(0, selection - 1)
+ elif key == curses.KEY_RIGHT: selection = min(len(selectionOptions) - 1, selection + 1)
+
+ if selection in (0, 1):
+ loadedTorrc, promptCanceled = torConfig.getTorrc(), False
+ try: configLocation = loadedTorrc.getConfigLocation()
+ except IOError: configLocation = ""
+
+ if selection == 1:
+ # prompts user for a configuration location
+ configLocation = popups.inputPrompt("Save to (esc to cancel): ", configLocation)
+ if not configLocation: promptCanceled = True
+
+ if not promptCanceled:
+ try:
+ torConfig.saveConf(configLocation, configLines)
+ msg = "Saved configuration to %s" % configLocation
+ except IOError, exc:
+ msg = "Unable to save configuration (%s)" % sysTools.getFileErrorMsg(exc)
- if not promptCanceled:
- try:
- torConfig.saveConf(configLocation, configLines)
- msg = "Saved configuration to %s" % configLocation
- except IOError, exc:
- msg = "Unable to save configuration (%s)" % sysTools.getFileErrorMsg(exc)
-
- popups.showMsg(msg, 2)
- finally: popups.finalize()
- else: isKeystrokeConsumed = False
-
- self.valsLock.release()
- return isKeystrokeConsumed
+ popups.showMsg(msg, 2)
+ finally: popups.finalize()
def getHelp(self):
options = []
diff --git a/src/cli/menu/actions.py b/src/cli/menu/actions.py
index 2827742..2072ead 100644
--- a/src/cli/menu/actions.py
+++ b/src/cli/menu/actions.py
@@ -28,17 +28,8 @@ def makeMenu():
baseMenu.add(makeLogMenu(pagePanel))
elif pagePanel.getName() == "connections":
baseMenu.add(makeConnectionsMenu(pagePanel))
-
- configurationMenu = cli.menu.item.Submenu("Configuration")
-
- commentsSubmenu = cli.menu.item.Submenu("Comments")
- commentsSubmenu.add(cli.menu.item.MenuItem("Hidden", None))
- commentsSubmenu.add(cli.menu.item.MenuItem("Visible", None))
- configurationMenu.add(commentsSubmenu)
-
- configurationMenu.add(cli.menu.item.MenuItem("Reload", None))
- configurationMenu.add(cli.menu.item.MenuItem("Reset Tor", None))
- baseMenu.add(configurationMenu)
+ elif pagePanel.getName() == "configuration":
+ baseMenu.add(makeConfigurationMenu(pagePanel))
return baseMenu
@@ -226,3 +217,24 @@ def makeConnectionsMenu(connPanel):
return connectionsMenu
+def makeConfigurationMenu(configPanel):
+ """
+ Submenu for the configuration panel, consisting of...
+ Save Config...
+ Sorting...
+ Filter / Unfilter Options
+
+ Arguments:
+ configPanel - instance of the configuration panel
+ """
+
+ configMenu = cli.menu.item.Submenu("Configuration")
+ configMenu.add(cli.menu.item.MenuItem("Save Config...", configPanel.showWriteDialog))
+ configMenu.add(cli.menu.item.MenuItem("Sorting...", configPanel.showSortDialog))
+
+ if configPanel.showAll: label, arg = "Filter", True
+ else: label, arg = "Unfilter", False
+ configMenu.add(cli.menu.item.MenuItem("%s Options" % label, functools.partial(configPanel.setFiltering, arg)))
+
+ return configMenu
+
1
0
commit bf373956a64afa6126b0836329042775119a6114
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun Jun 12 17:39:19 2011 -0700
Binding handlers for the torrc submenu
---
README | 1 +
src/cli/menu/actions.py | 26 ++++++++++++++++++
src/cli/torrcPanel.py | 65 ++++++++++++++++++++++++++++++++++-------------
3 files changed, 74 insertions(+), 18 deletions(-)
diff --git a/README b/README
index 0f26163..44fabf1 100644
--- a/README
+++ b/README
@@ -180,6 +180,7 @@ Layout:
__init__.py
menu.py - provides an interactive menu
item.py - individual items within the menu
+ actions.py - handlers for menu selections
__init__.py
controller.py - main display loop, handling input and layout
diff --git a/src/cli/menu/actions.py b/src/cli/menu/actions.py
index 2072ead..53e5d1c 100644
--- a/src/cli/menu/actions.py
+++ b/src/cli/menu/actions.py
@@ -30,6 +30,8 @@ def makeMenu():
baseMenu.add(makeConnectionsMenu(pagePanel))
elif pagePanel.getName() == "configuration":
baseMenu.add(makeConfigurationMenu(pagePanel))
+ elif pagePanel.getName() == "torrc":
+ baseMenu.add(makeTorrcMenu(pagePanel))
return baseMenu
@@ -238,3 +240,27 @@ def makeConfigurationMenu(configPanel):
return configMenu
+def makeTorrcMenu(torrcPanel):
+ """
+ Submenu for the torrc panel, consisting of...
+ Reload
+ Show / Hide Comments
+ Show / Hide Line Numbers
+
+ Arguments:
+ torrcPanel - instance of the torrc panel
+ """
+
+ torrcMenu = cli.menu.item.Submenu("Torrc")
+ torrcMenu.add(cli.menu.item.MenuItem("Reload", torrcPanel.reloadTorrc))
+
+ if torrcPanel.stripComments: label, arg = "Show", True
+ else: label, arg = "Hide", False
+ torrcMenu.add(cli.menu.item.MenuItem("%s Comments" % label, functools.partial(torrcPanel.setCommentsVisible, arg)))
+
+ if torrcPanel.showLineNum: label, arg = "Hide", False
+ else: label, arg = "Show", True
+ torrcMenu.add(cli.menu.item.MenuItem("%s Line Numbers" % label, functools.partial(torrcPanel.setLineNumberVisible, arg)))
+
+ return torrcMenu
+
diff --git a/src/cli/torrcPanel.py b/src/cli/torrcPanel.py
index a12cc87..c273bf0 100644
--- a/src/cli/torrcPanel.py
+++ b/src/cli/torrcPanel.py
@@ -6,6 +6,7 @@ import math
import curses
import threading
+import cli.controller
import popups
from util import conf, enum, panel, torConfig, torTools, uiTools
@@ -59,6 +60,49 @@ class TorrcPanel(panel.Panel):
self.redraw(True)
except: pass
+ def setCommentsVisible(self, isVisible):
+ """
+ Sets if comments and blank lines are shown or stripped.
+
+ Arguments:
+ isVisible - displayed comments and blank lines if true, strips otherwise
+ """
+
+ self.stripComments = not isVisible
+ self._lastContentHeightArgs = None
+ self.redraw(True)
+
+ def setLineNumberVisible(self, isVisible):
+ """
+ Sets if line numbers are shown or hidden.
+
+ Arguments:
+ isVisible - displays line numbers if true, hides otherwise
+ """
+
+ self.showLineNum = isVisible
+ self._lastContentHeightArgs = None
+ self.redraw(True)
+
+ def reloadTorrc(self):
+ """
+ Reloads the torrc, displaying an indicator of success or failure.
+ """
+
+ cli.controller.getController().requestRedraw(True)
+
+ try:
+ torConfig.getTorrc().load()
+ self._lastContentHeightArgs = None
+ self.redraw(True)
+ resultMsg = "torrc reloaded"
+ except IOError:
+ resultMsg = "failed to reload torrc"
+
+ self._lastContentHeightArgs = None
+ self.redraw(True)
+ popups.showMsg(resultMsg, 1)
+
def handleKey(self, key):
self.valsLock.acquire()
isKeystrokeConsumed = True
@@ -70,26 +114,11 @@ class TorrcPanel(panel.Panel):
self.scroll = newScroll
self.redraw(True)
elif key == ord('n') or key == ord('N'):
- self.showLineNum = not self.showLineNum
- self._lastContentHeightArgs = None
- self.redraw(True)
+ self.setLineNumberVisible(not self.showLineNum)
elif key == ord('s') or key == ord('S'):
- self.stripComments = not self.stripComments
- self._lastContentHeightArgs = None
- self.redraw(True)
+ self.setCommentsVisible(self.stripComments)
elif key == ord('r') or key == ord('R'):
- # reloads torrc, providing a notice if successful or not
- try:
- torConfig.getTorrc().load()
- self._lastContentHeightArgs = None
- self.redraw(True)
- resultMsg = "torrc reloaded"
- except IOError:
- resultMsg = "failed to reload torrc"
-
- self._lastContentHeightArgs = None
- self.redraw(True)
- popups.showMsg(resultMsg, 1)
+ self.reloadTorrc()
else: isKeystrokeConsumed = False
self.valsLock.release()
1
0
17 Jul '11
commit ee2589f311dee651c0c8d47705ebb5cb07c95a23
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun Jun 12 18:30:25 2011 -0700
Dropping alternative menu implementation
The other menus are complete now to dropping Kamran's implementation.
---
src/cli/controller.py | 11 -
src/cli/menu/menu.py | 3 +
src/cli/menu_alt/__init__.py | 6 -
src/cli/menu_alt/menu.py | 439 ------------------------------------------
src/cli/menu_alt/menuItem.py | 41 ----
5 files changed, 3 insertions(+), 497 deletions(-)
diff --git a/src/cli/controller.py b/src/cli/controller.py
index 6158ade..b019f8e 100644
--- a/src/cli/controller.py
+++ b/src/cli/controller.py
@@ -8,7 +8,6 @@ import curses
import threading
import cli.menu.menu
-import cli.menu_alt.menu
import cli.popups
import cli.headerPanel
import cli.logPanel
@@ -527,8 +526,6 @@ def drawTorMonitor(stdscr, startTime):
overrideKey = None # uses this rather than waiting on user input
isUnresponsive = False # flag for heartbeat responsiveness check
- menuKeys = []
-
while not control.isDone():
displayPanels = control.getDisplayPanels()
isUnresponsive = heartbeatCheck(isUnresponsive)
@@ -563,14 +560,6 @@ def drawTorMonitor(stdscr, startTime):
control.prevPage()
elif key == ord('p') or key == ord('P'):
control.setPaused(not control.isPaused())
- elif key == ord('n') or key == ord('N'):
- menu = cli.menu_alt.menu.Menu()
- menuKeys = menu.showMenu(keys=menuKeys)
- if menuKeys != []:
- for key in (ord('n'), ord('q'), ord('x')):
- if key in menuKeys:
- menuKeys.remove(key)
- overrideKey = key
elif key == ord('m') or key == ord('M'):
cli.menu.menu.showMenu()
elif key == ord('q') or key == ord('Q'):
diff --git a/src/cli/menu/menu.py b/src/cli/menu/menu.py
index b411a9c..1dbbbd0 100644
--- a/src/cli/menu/menu.py
+++ b/src/cli/menu/menu.py
@@ -1,3 +1,6 @@
+"""
+Display logic for presenting the menu.
+"""
import curses
diff --git a/src/cli/menu_alt/__init__.py b/src/cli/menu_alt/__init__.py
deleted file mode 100644
index 6d7b6b7..0000000
--- a/src/cli/menu_alt/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-"""
-Resources for displaying the menu.
-"""
-
-__all__ = ["menuItem", "menu"]
-
diff --git a/src/cli/menu_alt/menu.py b/src/cli/menu_alt/menu.py
deleted file mode 100644
index 7e10366..0000000
--- a/src/cli/menu_alt/menu.py
+++ /dev/null
@@ -1,439 +0,0 @@
-"""
-A drop-down menu for sending actions to panels.
-"""
-
-import curses
-
-import cli.controller
-import cli.menu_alt.menuItem as menuItem
-import cli.popups
-
-from cli.graphing.graphPanel import Bounds as GraphBounds
-from util import log, panel, uiTools
-
-PARENTLEVEL, TOPLEVEL = (-1, 0)
-
-class Menu():
- """Displays a popup menu and sends keys to appropriate panels"""
-
- def __init__(self, item=None):
- DEFAULT_ROOT = menuItem.MenuItem(label="Root", children=(
- menuItem.MenuItem(label="File", children=(
- menuItem.MenuItem(label="Exit",
- callback=lambda item: self._callbackReturnKey(ord('q'))),)),
- menuItem.MenuItem(label="Logs", children=(
- menuItem.MenuItem(label="Events",
- callback=lambda item: self._callbackPressKey('log', ord('e'))),
- menuItem.MenuItem(label="Clear",
- callback=lambda item: self._callbackPressKey('log', ord('c'))),
- menuItem.MenuItem(label="Save",
- callback=lambda item: self._callbackPressKey('log', ord('a'))),
- menuItem.MenuItem(label="Filter",
- callback=lambda item: self._callbackPressKey('log', ord('f'))),
- menuItem.MenuItem(label="Duplicates", children=(
- menuItem.MenuItem(label="Hidden",
- callback=lambda item: self._callbackSet('log', 'showDuplicates', False, ord('u')),
- enabled=lambda: self._getItemEnabled('log', 'showDuplicates', False)),
- menuItem.MenuItem(label="Visible",
- callback=lambda item: self._callbackSet('log', 'showDuplicates', True, ord('u')),
- enabled=lambda: self._getItemEnabled('log', 'showDuplicates', True)),
- )))),
- menuItem.MenuItem(label="View", children=(
- menuItem.MenuItem(label="Graph",
- callback=lambda item: self._callbackView('graph')),
- menuItem.MenuItem(label="Connections",
- callback=lambda item: self._callbackView('conn')),
- menuItem.MenuItem(label="Configuration",
- callback=lambda item: self._callbackView('configState')),
- menuItem.MenuItem(label="Configuration File",
- callback=lambda item: self._callbackView('configFile')),)),
- menuItem.MenuItem(label="Graph", children=(
- menuItem.MenuItem(label="Stats",
- callback=lambda item: self._callbackPressKey('graph', ord('s'))),
- menuItem.MenuItem(label="Size", children=(
- menuItem.MenuItem(label="Increase",
- callback=lambda item: self._callbackPressKey('graph', ord('m'))),
- menuItem.MenuItem(label="Decrease",
- callback=lambda item: self._callbackPressKey('graph', ord('n'))),
- )),
- menuItem.MenuItem(label="Update Interval",
- callback=lambda item: self._callbackPressKey('graph', ord('i'))),
- menuItem.MenuItem(label="Bounds", children=(
- menuItem.MenuItem(label="Local Max",
- callback=lambda item: self._callbackSet('graph', 'bounds', GraphBounds.LOCAL_MAX, ord('b')),
- enabled=lambda: self._getItemEnabled('graph', 'bounds', GraphBounds.LOCAL_MAX)),
- menuItem.MenuItem(label="Global Max",
- callback=lambda item: self._callbackSet('graph', 'bounds', GraphBounds.GLOBAL_MAX, ord('b')),
- enabled=lambda: self._getItemEnabled('graph', 'bounds', GraphBounds.GLOBAL_MAX)),
- menuItem.MenuItem(label="Tight",
- callback=lambda item: self._callbackSet('graph', 'bounds', GraphBounds.TIGHT, ord('b')),
- enabled=lambda: self._getItemEnabled('graph', 'bounds', GraphBounds.TIGHT)),
- )),)),
- menuItem.MenuItem(label="Connections", children=(
- menuItem.MenuItem(label="Identity",
- callback=lambda item: self._callbackPressKey('conn', ord('l'))),
- menuItem.MenuItem(label="Resolver",
- callback=lambda item: self._callbackPressKey('conn', ord('u'))),
- menuItem.MenuItem(label="Sort Order",
- callback=lambda item: self._callbackPressKey('conn', ord('s'))),
- )),
- menuItem.MenuItem(label="Configuration" , children=(
- menuItem.MenuItem(label="Comments", children=(
- menuItem.MenuItem(label="Hidden",
- callback=lambda item: self._callbackSet('configFile', 'stripComments', True, ord('s')),
- enabled=lambda: self._getItemEnabled('configFile', 'stripComments', True)),
- menuItem.MenuItem(label="Visible",
- callback=lambda item: self._callbackSet('configFile', 'stripComments', False, ord('s')),
- enabled=lambda: self._getItemEnabled('configFile', 'stripComments', False)),
- )),
- menuItem.MenuItem(label="Reload",
- callback=lambda item: self._callbackPressKey('configFile', ord('r'))),
- menuItem.MenuItem(label="Reset Tor",
- callback=lambda item: self._callbackReturnKey(ord('x'))),))
- ))
-
- self._first = [0]
- self._selection = [0]
-
- if item and item.isParent():
- self._rootItem = item
- else:
- self._rootItem = DEFAULT_ROOT
-
- def showMenu(self, keys=[]):
- keys.reverse()
- returnkeys = []
-
- popup, width, height = cli.popups.init(height=3)
- if popup:
- try:
- while True:
- popup.win.erase()
- popup.win.box()
-
- self._drawTopLevel(popup, width, height)
-
- popup.win.refresh()
-
- control = cli.controller.getController()
-
- if keys == []:
- key = control.getScreen().getch()
- else:
- key = keys.pop()
-
- if key == curses.KEY_RIGHT:
- self._moveTopLevelRight(width)
- elif key == curses.KEY_LEFT:
- self._moveTopLevelLeft(width)
- elif key == curses.KEY_DOWN:
- cascaded, returnkeys = self._cascadeNLevel()
- break
- elif key == 27:
- break
- elif uiTools.isSelectionKey(key):
- self._handleEvent()
- break
-
- finally:
- cli.popups.finalize()
-
- return returnkeys
-
- def _appendLevel(self):
- self._first.append(0)
- self._selection.append(0)
-
- def _removeLevel(self):
- self._first.pop()
- self._selection.pop()
-
- def _getCurrentTopLevelItem(self):
- index = self._first[TOPLEVEL] + self._selection[TOPLEVEL]
- return self._rootItem.getChildren()[index]
-
- def _getCurrentItem(self, level=0):
- item = self._rootItem
- if level == 0:
- sums = [sum(values) for values in zip(self._first, self._selection)]
- else:
- sums = [sum(values) for values in zip(self._first[:level], self._selection[:level])]
-
- for index in sums:
- if item.isParent():
- item = item.getChildren()[index]
- else:
- break
-
- return item
-
- def _calculateTopLevelWidths(self, width=0):
- labels = [menuItem.getLabel() for menuItem in self._rootItem.getChildren()]
-
- # width per label is set according to the longest label
- labelwidth = max(map(len, labels)) + 2
-
- # total number of labels that can be printed in supplied width
- printable = min(width / labelwidth - 1, self._rootItem.getChildrenCount())
-
- return (labelwidth, printable)
-
- def _calculateNLevelWidths(self, level=0):
- parent = self._getCurrentItem(level)
-
- if parent.isLeaf():
- return 0
-
- labels = [menuItem.getLabel() for menuItem in parent.getChildren()]
-
- labelwidth = max(map(len, labels))
-
- return labelwidth
-
- def _calculateNLevelHeights(self, height=0, level=0):
- control = cli.controller.getController()
- height, _ = control.getScreen().getmaxyx()
- topSize = sum(stickyPanel.getHeight() for stickyPanel in control.getStickyPanels())
- height = height - topSize
-
- parent = self._getCurrentItem(level)
-
- if parent.isLeaf():
- return 0
-
- printable = min(height - 4, parent.getChildrenCount())
-
- return printable if printable else parent.getChildrenCount()
-
- def _moveTopLevelRight(self, width):
- _, printable = self._calculateTopLevelWidths(width)
-
- if self._selection[TOPLEVEL] < printable - 1:
- self._selection[TOPLEVEL] = self._selection[TOPLEVEL] + 1
- else:
- self._selection[TOPLEVEL] = 0
- if printable < self._rootItem.getChildrenCount():
- self._first[TOPLEVEL] = (self._first[TOPLEVEL] + printable) % self._rootItem.getChildrenCount()
-
- if self._first[TOPLEVEL] + self._selection[TOPLEVEL] == self._rootItem.getChildrenCount():
- self._first[TOPLEVEL] = 0
- self._selection[TOPLEVEL] = 0
-
- def _moveTopLevelLeft(self, width):
- _, printable = self._calculateTopLevelWidths(width)
-
- if self._selection[TOPLEVEL] > 0:
- self._selection[TOPLEVEL] = self._selection[TOPLEVEL] - 1
- else:
- if self._first[TOPLEVEL] == 0:
- self._first[TOPLEVEL] = ((self._rootItem.getChildrenCount() / printable) * printable) % self._rootItem.getChildrenCount()
- else:
- self._first[TOPLEVEL] = abs(self._first[TOPLEVEL] - printable) % self._rootItem.getChildrenCount()
- self._selection[TOPLEVEL] = self._rootItem.getChildrenCount() - self._first[TOPLEVEL] - 1
-
- if self._selection[TOPLEVEL] > printable:
- self._selection[TOPLEVEL] = printable - 1
-
- def _drawTopLevel(self, popup, width, height):
- labelwidth, printable = self._calculateTopLevelWidths(width)
- children = self._rootItem.getChildren()[self._first[TOPLEVEL]:self._first[TOPLEVEL] + printable]
-
- top = 1
- left = 1
- for (index, item) in enumerate(children):
- labelformat = curses.A_STANDOUT if index == self._selection[TOPLEVEL] else curses.A_NORMAL
-
- popup.addch(top, left, curses.ACS_VLINE)
- left = left + 1
- popup.addstr(top, left, item.getLabel().center(labelwidth), labelformat)
- left = left + labelwidth
-
- popup.addch(top, left, curses.ACS_VLINE)
- left = left + 1
-
- def _cascadeNLevel(self):
- parent = self._getCurrentItem()
-
- if parent.isLeaf():
- return (False, [])
-
- self._appendLevel()
-
- labelwidth = self._calculateNLevelWidths(level=PARENTLEVEL)
- printable = self._calculateNLevelHeights(level=PARENTLEVEL)
-
- toplabelwidth, _ = self._calculateTopLevelWidths()
- left = (toplabelwidth + 2) * self._selection[TOPLEVEL]
-
- popup, width, height = cli.popups.init(height=printable+2, width=labelwidth+2, top=2, left=left)
-
- while self._getCurrentItem().isEnabled() == False:
- self._moveNLevelDown(height)
-
- if popup.win:
- returnkeys = []
- try:
- while True:
- popup.win.erase()
- popup.win.box()
-
- self._drawNLevel(popup, width, height)
-
- popup.win.refresh()
-
- control = cli.controller.getController()
- key = control.getScreen().getch()
-
- if key == curses.KEY_DOWN:
- self._moveNLevelDown(height)
- elif key == curses.KEY_UP:
- self._moveNLevelUp(height)
- elif key == curses.KEY_RIGHT:
- cascaded, returnkeys = self._cascadeNLevel()
- if cascaded == False:
- index = self._first[TOPLEVEL] + self._selection[TOPLEVEL] + 1
- returnkeys.append(ord('n'))
- for i in range(index):
- returnkeys.append(curses.KEY_RIGHT)
- returnkeys.append(curses.KEY_DOWN)
- break
- elif key == curses.KEY_LEFT:
- index = self._first[TOPLEVEL] + self._selection[TOPLEVEL] - 1
- index = index % self._rootItem.getChildrenCount()
- returnkeys.append(ord('n'))
- for i in range(index):
- returnkeys.append(curses.KEY_RIGHT)
- returnkeys.append(curses.KEY_DOWN)
- break
- elif key == 27:
- self._removeLevel()
- break
- elif uiTools.isSelectionKey(key):
- returnkey = self._handleEvent()
- if returnkey:
- returnkeys.append(returnkey)
- self._removeLevel()
- break
-
- finally:
- cli.popups.finalize()
-
- return (True, returnkeys)
-
- return (False, [])
-
- def _drawNLevel(self, popup, width, height):
- printable = self._calculateNLevelHeights(level=PARENTLEVEL)
- parent = self._getCurrentItem(level=PARENTLEVEL)
- children = parent.getChildren()[self._first[PARENTLEVEL]:self._first[PARENTLEVEL] + printable]
-
- top = 1
- left = 1
- for (index, item) in enumerate(children):
- labelformat = curses.A_STANDOUT if index == self._selection[PARENTLEVEL] else curses.A_NORMAL
-
- if not item.isEnabled():
- labelformat = labelformat | uiTools.getColor('yellow')
-
- popup.addstr(top, left, item.getLabel(), labelformat)
- top = top + 1
-
- def _moveNLevelDown(self, height):
- printable = self._calculateNLevelHeights(level=PARENTLEVEL)
- parent = self._getCurrentItem(level=PARENTLEVEL)
-
- if self._selection[PARENTLEVEL] < printable - 1:
- self._selection[PARENTLEVEL] = self._selection[PARENTLEVEL] + 1
- else:
- self._selection[PARENTLEVEL] = 0
- if printable < parent.getChildrenCount():
- self._first[PARENTLEVEL] = (self._first[PARENTLEVEL] + printable) % parent.getChildrenCount()
-
- if self._first[PARENTLEVEL] + self._selection[PARENTLEVEL] == parent.getChildrenCount():
- self._first[PARENTLEVEL] = 0
- self._selection[PARENTLEVEL] = 0
-
- while self._getCurrentItem().isEnabled() == False:
- self._moveNLevelDown(height)
-
- def _moveNLevelUp(self, height):
- printable = self._calculateNLevelHeights(level=PARENTLEVEL)
- parent = self._getCurrentItem(level=PARENTLEVEL)
-
- if self._selection[PARENTLEVEL] > 0:
- self._selection[PARENTLEVEL] = self._selection[PARENTLEVEL] - 1
- else:
- if self._first[PARENTLEVEL] == 0:
- self._first[PARENTLEVEL] = ((parent.getChildrenCount() / printable) * printable) % parent.getChildrenCount()
- else:
- self._first[PARENTLEVEL] = abs(self._first[PARENTLEVEL] - printable) % parent.getChildrenCount()
- self._selection[PARENTLEVEL] = parent.getChildrenCount() - self._first[PARENTLEVEL] - 1
-
- if self._selection[PARENTLEVEL] > printable:
- self._selection[PARENTLEVEL] = printable - 1
-
- while self._getCurrentItem().isEnabled() == False:
- self._moveNLevelUp(height)
-
- def _handleEvent(self):
- item = self._getCurrentItem()
-
- if item.isLeaf():
- return item.select()
- else:
- self._cascadeNLevel()
-
- def _callbackDefault(self, item):
- log.log(log.NOTICE, "%s selected" % item.getLabel())
-
- def _callbackView(self, panelname):
- control = cli.controller.getController()
-
- start = control.getPage()
- panels = control.getDisplayPanels(includeSticky=False)
- panelnames = [panel.getName() for panel in panels]
- while not panelname in panelnames:
- control.nextPage()
- panels = control.getDisplayPanels(includeSticky=False)
- panelnames = [panel.getName() for panel in panels]
-
- if control.getPage() == start:
- log.log(log.ERR, "Panel %s not found" % panelname)
- break
-
- def _getItemEnabled(self, panel, attr, value):
- control = cli.controller.getController()
- if control:
- panel = control.getPanel(panel)
-
- if panel:
- return getattr(panel, attr, None) != value
-
- return False
-
- def _callbackSet(self, panel, attr, value, key=None):
- control = cli.controller.getController()
- panel = control.getPanel(panel)
-
- panelattr = getattr(panel, attr, None)
-
- if panelattr != None:
- if hasattr(panelattr, '__call__'):
- panelattr(value)
- elif panelattr != value and key != None:
- start = panelattr
- while panelattr != value:
- panel.handleKey(key)
- panelattr = getattr(panel, attr, None)
- if panelattr == start:
- log.log(log.ERR, "Could not set %s.%s" % (panel, attr))
- break
-
- def _callbackPressKey(self, panel, key):
- control = cli.controller.getController()
- panel = control.getPanel(panel)
- panel.handleKey(key)
-
- def _callbackReturnKey(self, key):
- return key
-
diff --git a/src/cli/menu_alt/menuItem.py b/src/cli/menu_alt/menuItem.py
deleted file mode 100644
index 277c78a..0000000
--- a/src/cli/menu_alt/menuItem.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"""
-Menu Item class, used by the drop-down menus.
-"""
-
-class MenuItem():
- """
- Contains title, callback handler and possible children.
- """
-
- def __init__(self, label=None, callback=None, children=[], enabled=None):
- self._label = label
- self._callback = callback
- self._children = children
- self._enabled = enabled
-
- def getLabel(self):
- return self._label
-
- def isLeaf(self):
- return self._children == []
-
- def isParent(self):
- return self._children != []
-
- def isEnabled(self):
- if self._enabled == None:
- return True
- elif hasattr(self._enabled, '__call__'):
- return self._enabled()
- else:
- return self._enabled
-
- def getChildren(self):
- return self._children
-
- def getChildrenCount(self):
- return len(self._children)
-
- def select(self):
- return self._callback(self)
-
1
0
commit 2e7531e2ac0c36516f4a0b7a7169a988710e041d
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Tue Jun 14 01:17:07 2011 +0500
Updated graph widgets' names.
---
src/gui/arm.xml | 22 ++++++++++++++--------
src/starter.py | 2 +-
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/src/gui/arm.xml b/src/gui/arm.xml
index 85f60d3..a511583 100644
--- a/src/gui/arm.xml
+++ b/src/gui/arm.xml
@@ -307,11 +307,11 @@
<object class="GtkHBox" id="hbox_graph">
<property name="visible">True</property>
<child>
- <object class="GtkVBox" id="vbox_graph_a">
+ <object class="GtkVBox" id="vbox_graph_primary">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
- <object class="GtkLabel" id="label_graph_a_top">
+ <object class="GtkLabel" id="label_graph_primary_top">
<property name="visible">True</property>
<property name="label" translatable="yes">Download (0.0 b/sec)</property>
</object>
@@ -322,15 +322,18 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="placeholder_graph_a">
+ <object class="GtkVBox" id="placeholder_graph_primary">
<property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="label_graph_a_bottom">
+ <object class="GtkLabel" id="label_graph_primary_bottom">
<property name="visible">True</property>
<property name="label" translatable="yes">avg: 3.5 Kb/sec, total: 2.0 MB</property>
</object>
@@ -346,11 +349,11 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox_graph_b">
+ <object class="GtkVBox" id="vbox_graph_secondary">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
- <object class="GtkLabel" id="label_graph_b_top">
+ <object class="GtkLabel" id="label_graph_secondary_top">
<property name="visible">True</property>
<property name="label" translatable="yes">Upload (0.0 b/sec)</property>
</object>
@@ -361,15 +364,18 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="placeholder_graph_b">
+ <object class="GtkVBox" id="placeholder_graph_secondary">
<property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="label_graph_b_bottom">
+ <object class="GtkLabel" id="label_graph_secondary_bottom">
<property name="visible">True</property>
<property name="label" translatable="yes">avg: 3.5 Kb/sec, total: 2.0 MB</property>
</object>
diff --git a/src/starter.py b/src/starter.py
index d2ac910..50feceb 100644
--- a/src/starter.py
+++ b/src/starter.py
@@ -30,7 +30,7 @@ import util.uiTools
import TorCtl.TorCtl
import TorCtl.TorUtil
-INCLUDE_GUI = False
+INCLUDE_GUI = True
LOG_DUMP_PATH = os.path.expanduser("~/.arm/log")
DEFAULT_CONFIG = os.path.expanduser("~/.arm/armrc")
CONFIG = {"startup.controlPassword": None,
1
0
commit 697468f2df30460fb381fac35a650cb4f7c412ae
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun Jun 12 18:28:53 2011 -0700
Binding handlers for the help submenu
---
src/cli/configPanel.py | 2 --
src/cli/connections/connPanel.py | 2 --
src/cli/graphing/graphPanel.py | 4 ++--
src/cli/logPanel.py | 4 ----
src/cli/menu/actions.py | 15 +++++++++++++++
src/cli/menu/item.py | 8 +++++++-
src/cli/popups.py | 25 +++++++++++++++++++++++++
src/cli/torrcPanel.py | 3 ---
8 files changed, 49 insertions(+), 14 deletions(-)
diff --git a/src/cli/configPanel.py b/src/cli/configPanel.py
index 4647286..fedf1f7 100644
--- a/src/cli/configPanel.py
+++ b/src/cli/configPanel.py
@@ -275,7 +275,6 @@ class ConfigPanel(panel.Panel):
"""
# set ordering for config options
- cli.controller.getController().requestRedraw(True)
titleLabel = "Config Option Ordering:"
options = [FIELD_ATTR[field][0] for field in Field.values()]
oldSelection = [FIELD_ATTR[field][0] for field in self.sortOrdering]
@@ -357,7 +356,6 @@ class ConfigPanel(panel.Panel):
"""
# display a popup for saving the current configuration
- cli.controller.getController().requestRedraw(True)
configLines = torConfig.getCustomOptions(True)
popup, width, height = popups.init(len(configLines) + 2)
if not popup: return
diff --git a/src/cli/connections/connPanel.py b/src/cli/connections/connPanel.py
index 9490ddc..edf5a14 100644
--- a/src/cli/connections/connPanel.py
+++ b/src/cli/connections/connPanel.py
@@ -6,7 +6,6 @@ import time
import curses
import threading
-import cli.controller
import cli.descriptorPopup
import cli.popups
@@ -157,7 +156,6 @@ class ConnectionPanel(panel.Panel, threading.Thread):
"""
# set ordering for connection options
- cli.controller.getController().requestRedraw(True)
titleLabel = "Connection Ordering:"
options = entries.SortAttr.values()
oldSelection = self._sortOrdering
diff --git a/src/cli/graphing/graphPanel.py b/src/cli/graphing/graphPanel.py
index 8c3adf7..b080871 100644
--- a/src/cli/graphing/graphPanel.py
+++ b/src/cli/graphing/graphPanel.py
@@ -307,8 +307,6 @@ class GraphPanel(panel.Panel):
panel.CURSES_LOCK.acquire()
try:
while True:
- control.requestRedraw(True)
-
msg = "press the down/up to resize the graph, and enter when done"
control.setMsg(msg, curses.A_BOLD, True)
curses.cbreak()
@@ -325,6 +323,8 @@ class GraphPanel(panel.Panel):
elif key == curses.KEY_UP:
self.setGraphHeight(self.graphHeight - 1)
elif uiTools.isSelectionKey(key): break
+
+ control.requestRedraw(True)
finally:
control.setMsg()
panel.CURSES_LOCK.release()
diff --git a/src/cli/logPanel.py b/src/cli/logPanel.py
index ef372ab..fc3bfc3 100644
--- a/src/cli/logPanel.py
+++ b/src/cli/logPanel.py
@@ -13,7 +13,6 @@ import threading
from TorCtl import TorCtl
import popups
-import cli.controller
from version import VERSION
from util import conf, log, panel, sysTools, torTools, uiTools
@@ -792,7 +791,6 @@ class LogPanel(panel.Panel, threading.Thread):
Prompts the user to add a new regex filter.
"""
- cli.controller.getController().requestRedraw(True)
regexInput = popups.inputPrompt("Regular expression: ")
if regexInput:
@@ -809,7 +807,6 @@ class LogPanel(panel.Panel, threading.Thread):
"""
# allow user to enter new types of events to log - unchanged if left blank
- cli.controller.getController().requestRedraw(True)
popup, width, height = popups.init(11, 80)
if popup:
@@ -837,7 +834,6 @@ class LogPanel(panel.Panel, threading.Thread):
Lets user enter a path to take a snapshot, canceling if left blank.
"""
- cli.controller.getController().requestRedraw(True)
pathInput = popups.inputPrompt("Path to save log snapshot: ")
if pathInput:
diff --git a/src/cli/menu/actions.py b/src/cli/menu/actions.py
index 53e5d1c..b8b59e1 100644
--- a/src/cli/menu/actions.py
+++ b/src/cli/menu/actions.py
@@ -4,6 +4,7 @@ Generates the menu for arm, binding options with their related actions.
import functools
+import cli.popups
import cli.controller
import cli.menu.item
import cli.graphing.graphPanel
@@ -33,6 +34,8 @@ def makeMenu():
elif pagePanel.getName() == "torrc":
baseMenu.add(makeTorrcMenu(pagePanel))
+ baseMenu.add(makeHelpMenu())
+
return baseMenu
def makeActionsMenu():
@@ -90,6 +93,18 @@ def makeViewMenu():
return viewMenu
+def makeHelpMenu():
+ """
+ Submenu consisting of...
+ Hotkeys
+ About
+ """
+
+ helpMenu = cli.menu.item.Submenu("Help")
+ helpMenu.add(cli.menu.item.MenuItem("Hotkeys", cli.popups.showHelpPopup))
+ helpMenu.add(cli.menu.item.MenuItem("About", cli.popups.showAboutPopup))
+ return helpMenu
+
def makeGraphMenu(graphPanel):
"""
Submenu for the graph panel, consisting of...
diff --git a/src/cli/menu/item.py b/src/cli/menu/item.py
index beaac9c..f46cdbb 100644
--- a/src/cli/menu/item.py
+++ b/src/cli/menu/item.py
@@ -2,6 +2,8 @@
Menu item, representing an option in the drop-down menu.
"""
+import cli.controller
+
class MenuItem():
"""
Option in a drop-down menu.
@@ -53,7 +55,11 @@ class MenuItem():
the menu and false otherwise.
"""
- if self._callback: self._callback()
+ if self._callback:
+ control = cli.controller.getController()
+ control.setMsg()
+ control.requestRedraw(True)
+ self._callback()
return True
def next(self):
diff --git a/src/cli/popups.py b/src/cli/popups.py
index 5f1eac2..7254f4a 100644
--- a/src/cli/popups.py
+++ b/src/cli/popups.py
@@ -4,6 +4,7 @@ Functions for displaying popups in the interface.
import curses
+import version
import cli.controller
from util import panel, uiTools
@@ -155,6 +156,30 @@ def showHelpPopup():
return exitKey
else: return None
+def showAboutPopup():
+ """
+ Presents a popup with author and version information.
+ """
+
+ popup, _, height = init(9, 80)
+ if not popup: return
+
+ try:
+ control = cli.controller.getController()
+
+ popup.win.box()
+ popup.addstr(0, 0, "About:", curses.A_STANDOUT)
+ popup.addstr(1, 2, "arm, version %s (released %s)" % (version.VERSION, version.LAST_MODIFIED), curses.A_BOLD)
+ popup.addstr(2, 4, "Written by Damian Johnson (atagar1(a)gmail.com)")
+ popup.addstr(3, 4, "Project page: www.atagar.com/arm")
+ popup.addstr(5, 2, "Released under the GPL v3 (http://www.gnu.org/licenses/gpl.html)")
+ popup.addstr(7, 2, "Press any key...")
+ popup.win.refresh()
+
+ curses.cbreak()
+ control.getScreen().getch()
+ finally: finalize()
+
def showSortDialog(title, options, oldSelection, optionColors):
"""
Displays a sorting dialog of the form:
diff --git a/src/cli/torrcPanel.py b/src/cli/torrcPanel.py
index c273bf0..f651785 100644
--- a/src/cli/torrcPanel.py
+++ b/src/cli/torrcPanel.py
@@ -6,7 +6,6 @@ import math
import curses
import threading
-import cli.controller
import popups
from util import conf, enum, panel, torConfig, torTools, uiTools
@@ -89,8 +88,6 @@ class TorrcPanel(panel.Panel):
Reloads the torrc, displaying an indicator of success or failure.
"""
- cli.controller.getController().requestRedraw(True)
-
try:
torConfig.getTorrc().load()
self._lastContentHeightArgs = None
1
0
17 Jul '11
commit d7f1af69b70732ef9f046411b7cf12814a8a62f9
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Jun 4 21:22:35 2011 -0700
fix: Submenus were crashing when outside window
The menus (and any window with a non-zero left position) would crash when it
attempted to be created outside the screen. Caught by krkhan
---
src/cli/popups.py | 2 +-
src/util/panel.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/cli/popups.py b/src/cli/popups.py
index 52e5376..4bb519d 100644
--- a/src/cli/popups.py
+++ b/src/cli/popups.py
@@ -38,7 +38,7 @@ def init(height = -1, width = -1, top = 0, left = 0, belowStatic = True):
if popup.win != None:
panel.CURSES_LOCK.acquire()
return (popup, popup.maxX - 1, popup.maxY)
- else: return None
+ else: return (None, 0, 0)
def finalize():
"""
diff --git a/src/util/panel.py b/src/util/panel.py
index 6fae341..70f72a3 100644
--- a/src/util/panel.py
+++ b/src/util/panel.py
@@ -381,7 +381,7 @@ class Panel():
# if the panel's completely outside its parent then this is a no-op
newHeight, newWidth = self.getPreferredSize()
- if newHeight == 0:
+ if newHeight == 0 or newWidth == 0:
self.win = None
return
1
0
commit f08c8d406a08ef8b842db467237dfac6daacb4df
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Jun 4 21:47:57 2011 -0700
Message for how to close the menu
When presenting the menu showing the hotkeys for closeing in the label panel.
---
src/cli/menu/menu.py | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/src/cli/menu/menu.py b/src/cli/menu/menu.py
index 02f87ee..f83b76d 100644
--- a/src/cli/menu/menu.py
+++ b/src/cli/menu/menu.py
@@ -148,6 +148,9 @@ def showMenu():
popup.win.bkgd(' ', curses.A_STANDOUT | uiTools.getColor("red"))
selectionHierarchy = cursor.getSelection().getHierarchy()
+ # provide a message saying how to close the menu
+ control.setMsg("Press m or esc to close the menu.", curses.A_BOLD, True)
+
# renders the menu bar, noting where the open submenu is positioned
drawLeft, selectionLeft = 0, 0
@@ -175,7 +178,9 @@ def showMenu():
if not cursor.isDone():
for panelImpl in control.getDisplayPanels():
panelImpl.redraw(True)
- finally: cli.popups.finalize()
+ finally:
+ control.setMsg()
+ cli.popups.finalize()
def _drawSubmenu(cursor, level, top, left):
selectionHierarchy = cursor.getSelection().getHierarchy()
1
0
17 Jul '11
commit eedc9eeb8941d189ed9f684400cac1630bcc5c0e
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Wed Jun 8 20:41:27 2011 +0500
Remove cell renderer packing from the controller.
GtkBuilder's internal support for connecting tree models and views
is used to clean up the program.
---
src/gui/arm.xml | 119 +++++++++++++++++++++++++++++++++----------------
src/gui/controller.py | 25 ----------
2 files changed, 80 insertions(+), 64 deletions(-)
diff --git a/src/gui/arm.xml b/src/gui/arm.xml
index 49ffc89..85f60d3 100644
--- a/src/gui/arm.xml
+++ b/src/gui/arm.xml
@@ -4,13 +4,11 @@
<!-- interface-naming-policy project-wide -->
<object class="GtkListStore" id="liststore_sticky">
<columns>
- <!-- column-name gchararray1 -->
+ <!-- column-name key -->
<column type="gchararray"/>
- <!-- column-name gchararray2 -->
+ <!-- column-name value -->
<column type="gchararray"/>
- <!-- column-name gchararray3 -->
- <column type="gchararray"/>
- <!-- column-name gchararray4 -->
+ <!-- column-name foreground -->
<column type="gchararray"/>
</columns>
<data>
@@ -18,71 +16,60 @@
<col id="0" translatable="yes">arm</col>
<col id="1" translatable="yes">orthanc (Linux 2.6.35.11-83.fc14)</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">Tor</col>
<col id="1" translatable="yes">0.2.1.28 (obsolete)</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">black</col>
</row>
<row>
<col id="0" translatable="yes">Relaying</col>
<col id="1" translatable="yes">Disabled</col>
<col id="2" translatable="yes">red</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">Control Port</col>
<col id="1" translatable="yes">9051 (open)</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">CPU Tor</col>
<col id="1" translatable="yes">0.0%</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">CPU arm</col>
<col id="1" translatable="yes">0.0%</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">Memory</col>
<col id="1" translatable="yes">20 MB (1.0%)</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">PID</col>
<col id="1" translatable="yes">3980</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">Uptime</col>
<col id="1" translatable="yes">01:01:34</col>
<col id="2" translatable="yes">black</col>
- <col id="3" translatable="yes">white</col>
</row>
</data>
</object>
<object class="GtkListStore" id="liststore_conn">
<columns>
- <!-- column-name gchararray1 -->
- <column type="gchararray"/>
- <!-- column-name gchararray2 -->
+ <!-- column-name origin -->
<column type="gchararray"/>
- <!-- column-name gchararray3 -->
+ <!-- column-name dest -->
<column type="gchararray"/>
- <!-- column-name gchararray4 -->
+ <!-- column-name time -->
<column type="gchararray"/>
- <!-- column-name gchararray5 -->
+ <!-- column-name type -->
<column type="gchararray"/>
- <!-- column-name gchararray6 -->
+ <!-- column-name foreground -->
<column type="gchararray"/>
</columns>
<data>
@@ -92,7 +79,6 @@
<col id="2" translatable="yes">10.7m</col>
<col id="3" translatable="yes">CLIENT</col>
<col id="4" translatable="yes">blue</col>
- <col id="5" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">115.167.31.237:44940</col>
@@ -100,7 +86,6 @@
<col id="2" translatable="yes">28.3m</col>
<col id="3" translatable="yes">CLIENT</col>
<col id="4" translatable="yes">blue</col>
- <col id="5" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">127.0.0.1:9051</col>
@@ -108,21 +93,18 @@
<col id="2" translatable="yes">30.0m</col>
<col id="3" translatable="yes">CONTROL</col>
<col id="4" translatable="yes">red</col>
- <col id="5" translatable="yes">white</col>
</row>
</data>
</object>
<object class="GtkListStore" id="liststore_config">
<columns>
- <!-- column-name gchararray1 -->
+ <!-- column-name key -->
<column type="gchararray"/>
- <!-- column-name gchararray2 -->
+ <!-- column-name value -->
<column type="gchararray"/>
- <!-- column-name gchararray3 -->
+ <!-- column-name desc -->
<column type="gchararray"/>
- <!-- column-name gchararray4 -->
- <column type="gchararray"/>
- <!-- column-name gchararray5 -->
+ <!-- column-name foreground -->
<column type="gchararray"/>
</columns>
<data>
@@ -131,28 +113,24 @@
<col id="1" translatable="yes">5242880</col>
<col id="2" translatable="yes">Average bandwidth usage limit</col>
<col id="3" translatable="yes">#368918</col>
- <col id="4" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">BandwidthBurst</col>
<col id="1" translatable="yes">10485760</col>
<col id="2" translatable="yes">Maximum bandwidth usage limit</col>
<col id="3" translatable="yes">#368918</col>
- <col id="4" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">RelayBandwidthBurst</col>
<col id="1" translatable="yes">0 B</col>
<col id="2" translatable="yes">Maximum bandwidth usage limit for relaying</col>
<col id="3" translatable="yes">#368918</col>
- <col id="4" translatable="yes">white</col>
</row>
<row>
<col id="0" translatable="yes">ControlPort</col>
<col id="1" translatable="yes">9051</col>
<col id="2" translatable="yes">Port providing access to tor controllers (arm, vidalia, etc)</col>
<col id="3" translatable="yes">#368918</col>
- <col id="4" translatable="yes">white</col>
</row>
</data>
</object>
@@ -344,7 +322,7 @@
</packing>
</child>
<child>
- <object class="GtkCurve" id="curve_graph_a">
+ <object class="GtkVBox" id="placeholder_graph_a">
<property name="visible">True</property>
</object>
<packing>
@@ -383,7 +361,7 @@
</packing>
</child>
<child>
- <object class="GtkCurve" id="curve_graph_b">
+ <object class="GtkVBox" id="placeholder_graph_b">
<property name="visible">True</property>
</object>
<packing>
@@ -446,21 +424,49 @@
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_conn_origin">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_conn_origin"/>
+ <attributes>
+ <attribute name="foreground">4</attribute>
+ <attribute name="markup">0</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_conn_dest">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_conn_dest"/>
+ <attributes>
+ <attribute name="foreground">4</attribute>
+ <attribute name="markup">1</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_conn_time">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_conn_time"/>
+ <attributes>
+ <attribute name="foreground">4</attribute>
+ <attribute name="markup">2</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_alive">
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_type">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_conn_type"/>
+ <attributes>
+ <attribute name="foreground">4</attribute>
+ <attribute name="markup">3</attribute>
+ </attributes>
+ </child>
</object>
</child>
</object>
@@ -517,18 +523,39 @@ each direction. (Default: 0) </span></property>
<property name="headers_visible">False</property>
<property name="search_column">0</property>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn_name">
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_key">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_config_key"/>
+ <attributes>
+ <attribute name="foreground">3</attribute>
+ <attribute name="markup">0</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_value">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_config_value"/>
+ <attributes>
+ <attribute name="foreground">3</attribute>
+ <attribute name="markup">1</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_desc">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_config_desc"/>
+ <attributes>
+ <attribute name="foreground">3</attribute>
+ <attribute name="markup">2</attribute>
+ </attributes>
+ </child>
</object>
</child>
</object>
@@ -573,13 +600,26 @@ each direction. (Default: 0) </span></property>
<property name="headers_clickable">False</property>
<property name="search_column">0</property>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn_sticky_name">
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_sticky_key">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_sticky_key"/>
+ <attributes>
+ <attribute name="markup">0</attribute>
+ </attributes>
+ </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn_sticky_value">
<property name="title">column</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext_sticky_value"/>
+ <attributes>
+ <attribute name="foreground">2</attribute>
+ <attribute name="markup">1</attribute>
+ </attributes>
+ </child>
</object>
</child>
</object>
@@ -605,6 +645,7 @@ each direction. (Default: 0) </span></property>
<object class="GtkTextView" id="textview_log">
<property name="visible">True</property>
<property name="can_focus">True</property>
+ <property name="buffer">textbuffer_log</property>
</object>
</child>
</object>
diff --git a/src/gui/controller.py b/src/gui/controller.py
index a4f34a0..0e444d3 100644
--- a/src/gui/controller.py
+++ b/src/gui/controller.py
@@ -8,15 +8,11 @@ class GuiController:
self.builder = gtk.Builder()
self.builder.add_from_file(filename)
self.builder.connect_signals(self)
- self._pack_formatted_cells_into_cols()
def run(self):
window = self.builder.get_object('window_main')
- textview = self.builder.get_object('textview_log')
textbuffer = self.builder.get_object('textbuffer_log')
- textview.set_buffer(textbuffer)
-
conn = torTools.getConn()
torPid = conn.getMyPid()
textbuffer.set_text("Tor pid: %s" % torPid)
@@ -27,27 +23,6 @@ class GuiController:
def on_window_main_delete_event(self, widget, data=None):
gtk.main_quit()
- def _pack_formatted_cells_into_cols(self):
- self._pack_formatted_cell_into_col(treeview='treeview_sticky', col=0, markup=0)
- self._pack_formatted_cell_into_col(treeview='treeview_sticky', col=1, markup=1, foreground=2)
- self._pack_formatted_cell_into_col(treeview='treeview_conn', col=0, markup=0, foreground=4)
- self._pack_formatted_cell_into_col(treeview='treeview_conn', col=1, markup=1, foreground=4)
- self._pack_formatted_cell_into_col(treeview='treeview_conn', col=2, markup=2, foreground=4)
- self._pack_formatted_cell_into_col(treeview='treeview_conn', col=3, markup=3, foreground=4)
- self._pack_formatted_cell_into_col(treeview='treeview_config', col=0, markup=0, foreground=3)
- self._pack_formatted_cell_into_col(treeview='treeview_config', col=1, markup=1, foreground=3)
- self._pack_formatted_cell_into_col(treeview='treeview_config', col=2, markup=2, foreground=3)
-
- def _pack_formatted_cell_into_col(self, treeview, col, markup, foreground=-1, background=-1):
- col = self.builder.get_object(treeview).get_column(col)
- cell = gtk.CellRendererText()
- col.pack_start(cell)
- col.add_attribute(cell, 'markup', markup)
- if foreground != -1:
- col.add_attribute(cell, 'foreground', foreground)
- if background != -1:
- col.add_attribute(cell, 'background', background)
-
def startGui():
controller = GuiController()
controller.run()
1
0