tor-commits
Threads by month
- ----- 2025 -----
- 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
July 2011
- 16 participants
- 868 discussions
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
commit 83512a5501cd3c76935287e7140ef6a3b5fa7f01
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Wed Jun 8 20:42:40 2011 +0500
Use --gui as the long argument.
---
src/starter.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/starter.py b/src/starter.py
index 9d7f17c..a94020f 100644
--- a/src/starter.py
+++ b/src/starter.py
@@ -55,7 +55,7 @@ OPT_EXPANDED = ["gtk", "interface=", "config=", "debug", "blind", "event=", "ver
HELP_MSG = """Usage arm [OPTION]
Terminal status monitor for Tor relays.
- -g, --gtk launch the Gtk+ interface
+ -g, --gui launch the Gtk+ interface
-i, --interface [ADDRESS:]PORT change control interface from %s:%i
-c, --config CONFIG_PATH loaded configuration options, CONFIG_PATH
defaults to: %s
@@ -239,7 +239,7 @@ if __name__ == '__main__':
param["startup.interface.ipAddress"] = controlAddr
param["startup.interface.port"] = controlPort
- elif opt in ("-g", "--gtk"): launchGui = True
+ elif opt in ("-g", "--gui"): launchGui = True
elif opt in ("-c", "--config"): configPath = arg # sets path of user's config
elif opt in ("-d", "--debug"): isDebugMode = True # dumps all logs
elif opt in ("-b", "--blind"):
1
0
commit bffe945d864799ef8f83f60911740958aa0c7572
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Tue Jun 7 15:31:36 2011 +0500
Add cagraph as a prereq.
---
src/prereq.py | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/src/prereq.py b/src/prereq.py
index 4bda913..2e26161 100644
--- a/src/prereq.py
+++ b/src/prereq.py
@@ -8,6 +8,9 @@ import shutil
import tempfile
TORCTL_REPO = "git://git.torproject.org/pytorctl.git"
+CAGRAPH_TARBALL_URL = "http://cagraph.googlecode.com/files/cagraph-1.2.tar.gz"
+CAGRAPH_TARBALL_NAME = "cagraph-1.2.tar.gz"
+CAGRAPH_TARBALL_ROOT = "cagraph-1.2"
def isTorCtlAvailable():
"""
@@ -20,6 +23,16 @@ def isTorCtlAvailable():
except ImportError:
return False
+def isCagraphAvailable():
+ """
+ True if cagraph is already available on the platform, false otherwise.
+ """
+ try:
+ import cagraph
+ return True
+ except ImportError:
+ return False
+
def promptTorCtlInstall():
"""
Asks the user to install TorCtl. This returns True if it was installed and
@@ -44,6 +57,30 @@ def promptTorCtlInstall():
print exc
return False
+def promptCagraphInstall():
+ """
+ Asks the user to install cagraph. This returns True if it was installed and
+ False otherwise (if it was either declined or failed to be fetched).
+ """
+
+ userInput = raw_input("Arm requires cagraph to run, but it's unavailable. Would you like to install it? (y/n): ")
+
+ # if user says no then terminate
+ if not userInput.lower() in ("y", "yes"): return False
+
+ # attempt to install TorCtl, printing the issue if unsuccessful
+ try:
+ installCagraph()
+
+ if not isCagraphAvailable():
+ raise IOError("Unable to install cagraph, sorry")
+
+ print "cagraph successfully installed"
+ return True
+ except IOError, exc:
+ print exc
+ return False
+
def installTorCtl():
"""
Checks out the current git head release for TorCtl and bundles it with arm.
@@ -71,6 +108,31 @@ def installTorCtl():
# of errors.
shutil.rmtree(tmpFilename, ignore_errors=True)
+def installCagraph():
+ """
+ Downloads and extracts the cagraph tarball.
+ This raises an IOError if unsuccessful.
+ """
+
+ if isCagraphAvailable(): return
+
+ tmpDir = tempfile.mkdtemp()
+ tmpFilename = os.path.join(tmpDir, CAGRAPH_TARBALL_NAME)
+
+ exitStatus = os.system("wget -P %s %s" % (tmpDir, CAGRAPH_TARBALL_URL))
+ if exitStatus: raise IOError("Unable to fetch cagraph from %s. Is wget installed?" % CAGRAPH_TARBALL_URL)
+
+ # the destination for TorCtl will be our directory
+ ourDir = os.path.dirname(os.path.realpath(__file__))
+
+ # exports TorCtl to our location
+ exitStatus = os.system("(cd %s && tar --strip-components=1 -xzf %s %s/cagraph)" % (ourDir, tmpFilename, CAGRAPH_TARBALL_ROOT))
+ if exitStatus: raise IOError("Unable to extract cagraph to %s" % ourDir)
+
+ # Clean up the temporary contents. This isn't vital so quietly fails in case
+ # of errors.
+ shutil.rmtree(tmpDir, ignore_errors=True)
+
if __name__ == '__main__':
majorVersion = sys.version_info[0]
minorVersion = sys.version_info[1]
@@ -92,3 +154,7 @@ if __name__ == '__main__':
isInstalled = promptTorCtlInstall()
if not isInstalled: sys.exit(1)
+ if not isCagraphAvailable():
+ isInstalled = promptCagraphInstall()
+ if not isInstalled: sys.exit(1)
+
1
0
commit 5ed6caafc77f43a389c7fcafa829803983c490a5
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Sun Jun 5 21:10:48 2011 +0500
Skeletal Gtk+ UI.
Launched via -g or --gtk command-line flag. Rudimentary usage of
torTools to display Tor pid.
---
src/gui/__init__.py | 6 +
src/gui/arm.xml | 628 +++++++++++++++++++++++++++++++++++++++++++++++++
src/gui/controller.py | 85 +++++++
src/starter.py | 13 +-
4 files changed, 729 insertions(+), 3 deletions(-)
diff --git a/src/gui/__init__.py b/src/gui/__init__.py
new file mode 100644
index 0000000..f461b3e
--- /dev/null
+++ b/src/gui/__init__.py
@@ -0,0 +1,6 @@
+"""
+Panels, popups, and handlers comprising the arm user interface.
+"""
+
+__all__ = ["controller"]
+
diff --git a/src/gui/arm.xml b/src/gui/arm.xml
new file mode 100644
index 0000000..49ffc89
--- /dev/null
+++ b/src/gui/arm.xml
@@ -0,0 +1,628 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkListStore" id="liststore_sticky">
+ <columns>
+ <!-- column-name gchararray1 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray2 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray3 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray4 -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <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 type="gchararray"/>
+ <!-- column-name gchararray3 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray4 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray5 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray6 -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">115.167.31.237:56835</col>
+ <col id="1" translatable="yes">188.120.245.249:9001 (ru)</col>
+ <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>
+ <col id="1" translatable="yes">206.217.215.183:53 (us)</col>
+ <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>
+ <col id="1" translatable="yes">127.0.0.1:51665</col>
+ <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 type="gchararray"/>
+ <!-- column-name gchararray2 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray3 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray4 -->
+ <column type="gchararray"/>
+ <!-- column-name gchararray5 -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">BandwidthRate</col>
+ <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>
+ <object class="GtkWindow" id="window_main">
+ <property name="title" translatable="yes">arm</property>
+ <property name="default_width">640</property>
+ <property name="default_height">480</property>
+ <signal name="delete_event" handler="on_window_main_delete_event"/>
+ <child>
+ <object class="GtkVBox" id="vbox_main">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">5</property>
+ <child>
+ <object class="GtkMenuBar" id="menubar_main">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkMenuItem" id="menuitem_file">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu_file">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_new">
+ <property name="label">gtk-new</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_open">
+ <property name="label">gtk-open</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_save">
+ <property name="label">gtk-save</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_saveas">
+ <property name="label">gtk-save-as</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem" id="separatormenuitem_file">
+ <property name="visible">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_exit">
+ <property name="label">gtk-quit</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="menuitem_edit">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu_edit">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_cut">
+ <property name="label">gtk-cut</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_copy">
+ <property name="label">gtk-copy</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_paste">
+ <property name="label">gtk-paste</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_delete">
+ <property name="label">gtk-delete</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="menuitem_view">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_View</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="menuitem_help">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu_help">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem_about">
+ <property name="label">gtk-about</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_main">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkNotebook" id="notebook_main">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkVBox" id="vbox_graph">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label_graph_top">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Limit: 40 Mb/s, Burst: 80 Mb/s</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox_graph">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkVBox" id="vbox_graph_a">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label_graph_a_top">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Download (0.0 b/sec)</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCurve" id="curve_graph_a">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_graph_a_bottom">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">avg: 3.5 Kb/sec, total: 2.0 MB</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_graph_b">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label_graph_b_top">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Upload (0.0 b/sec)</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCurve" id="curve_graph_b">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_graph_b_bottom">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">avg: 3.5 Kb/sec, total: 2.0 MB</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label_notebook_graph">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Graphs</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_conn">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label_conn_top">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">2 Clients, 1 Control</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTreeView" id="treeview_conn">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">liststore_conn</property>
+ <property name="headers_visible">False</property>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_origin">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_dest">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_time">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_conn_alive">
+ <property name="title">column</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label_notebook_conn">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Connections</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox_config">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label_config_top">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><span foreground="#368918"><u>RelayBandwidthBurst</u> (General Option)
+<b>Value</b>: 0 B (default, DataSize, usage: N bytes|KB|MB|GB|TB)
+<b>Description</b>: Limit the maximum token bucket size (also known as
+the burst) for <i>relayed traffic</i> to the given number of bytes in
+each direction. (Default: 0) </span></property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_config">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_config">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">liststore_config</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">0</property>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_name">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_value">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_desc">
+ <property name="title">column</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label_notebook_config">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Configuration</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_sticky">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTreeView" id="treeview_sticky">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">liststore_sticky</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_sticky_name">
+ <property name="title">column</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn_sticky_value">
+ <property name="title">column</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_log">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkTextView" id="textview_log">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">5</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkTextBuffer" id="textbuffer_log">
+ <property name="text" translatable="yes">16:09:20 [NOTICE] Bootstrapped 90%: Establishing a Tor circuit.
+16:09:23 [NOTICE] Tor has successfully opened a circuit. Looks like client functionality is working.
+16:09:23 [NOTICE] Tor has successfully opened a circuit. Looks like client functionality is working.
+16:09:24 [NOTICE] Bootstrapped 100%: Done.
+</property>
+ </object>
+</interface>
diff --git a/src/gui/controller.py b/src/gui/controller.py
new file mode 100755
index 0000000..2f54933
--- /dev/null
+++ b/src/gui/controller.py
@@ -0,0 +1,85 @@
+from util import torTools
+
+import gtk
+
+class GuiController:
+ def __init__(self):
+ filename = 'src/gui/arm.xml'
+ self.builder = gtk.Builder()
+ self.builder.add_from_file(filename)
+ self.builder.connect_signals(self)
+
+ def run(self):
+ window = self.builder.get_object('window_main')
+
+ col = self.builder.get_object('treeview_sticky').get_column(0)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'text', 0)
+
+ col = self.builder.get_object('treeview_sticky').get_column(1)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 1)
+ col.add_attribute(cell, 'foreground', 2)
+
+ col = self.builder.get_object('treeview_conn').get_column(0)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 0)
+ col.add_attribute(cell, 'foreground', 4)
+
+ col = self.builder.get_object('treeview_conn').get_column(1)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 1)
+ col.add_attribute(cell, 'foreground', 4)
+
+ col = self.builder.get_object('treeview_conn').get_column(2)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 2)
+ col.add_attribute(cell, 'foreground', 4)
+
+ col = self.builder.get_object('treeview_conn').get_column(3)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 3)
+ col.add_attribute(cell, 'foreground', 4)
+
+ col = self.builder.get_object('treeview_config').get_column(0)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 0)
+ col.add_attribute(cell, 'foreground', 3)
+
+ col = self.builder.get_object('treeview_config').get_column(1)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 1)
+ col.add_attribute(cell, 'foreground', 3)
+
+ col = self.builder.get_object('treeview_config').get_column(2)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell)
+ col.add_attribute(cell, 'markup', 2)
+ col.add_attribute(cell, 'foreground', 3)
+
+ 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)
+
+ window.show_all()
+ gtk.main()
+
+ def on_window_main_delete_event(self, widget, data=None):
+ gtk.main_quit()
+
+def startGui():
+ controller = GuiController()
+ controller.run()
+
diff --git a/src/starter.py b/src/starter.py
index b41b18b..9d7f17c 100644
--- a/src/starter.py
+++ b/src/starter.py
@@ -16,6 +16,7 @@ import platform
import version
import cli.controller
import cli.logPanel
+import gui.controller
import util.conf
import util.connections
import util.hostnames
@@ -49,11 +50,12 @@ CONFIG = {"startup.controlPassword": None,
"log.configDescriptions.persistance.saveFailed": util.log.NOTICE,
"log.savingDebugLog": util.log.NOTICE}
-OPT = "i:c:dbe:vh"
-OPT_EXPANDED = ["interface=", "config=", "debug", "blind", "event=", "version", "help"]
+OPT = "gi:c:dbe:vh"
+OPT_EXPANDED = ["gtk", "interface=", "config=", "debug", "blind", "event=", "version", "help"]
HELP_MSG = """Usage arm [OPTION]
Terminal status monitor for Tor relays.
+ -g, --gtk launch the Gtk+ interface
-i, --interface [ADDRESS:]PORT change control interface from %s:%i
-c, --config CONFIG_PATH loaded configuration options, CONFIG_PATH
defaults to: %s
@@ -208,6 +210,7 @@ def _dumpConfig():
if __name__ == '__main__':
startTime = time.time()
param = dict([(key, None) for key in CONFIG.keys()])
+ launchGui = False
isDebugMode = False
configPath = DEFAULT_CONFIG # path used for customized configuration
@@ -236,6 +239,7 @@ if __name__ == '__main__':
param["startup.interface.ipAddress"] = controlAddr
param["startup.interface.port"] = controlPort
+ elif opt in ("-g", "--gtk"): launchGui = True
elif opt in ("-c", "--config"): configPath = arg # sets path of user's config
elif opt in ("-d", "--debug"): isDebugMode = True # dumps all logs
elif opt in ("-b", "--blind"):
@@ -401,5 +405,8 @@ if __name__ == '__main__':
if util.uiTools.isUnicodeAvailable():
locale.setlocale(locale.LC_ALL, "")
- cli.controller.startTorMonitor(time.time() - initTime)
+ if launchGui == True:
+ gui.controller.startGui()
+ else:
+ cli.controller.startTorMonitor(time.time() - initTime)
1
0