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
- 1 participants
- 213385 discussions
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

[arm/master] Use resizable panes for layout, added scrolled window for connections.
by atagar@torproject.org 14 Jun '11
by atagar@torproject.org 14 Jun '11
14 Jun '11
commit 39fe520fa85256c506c7f5eeb6dfd02bed787b05
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Tue Jun 14 01:29:13 2011 +0500
Use resizable panes for layout, added scrolled window for connections.
---
src/gui/arm.xml | 550 +++++++++++++++++++++++++++++--------------------------
1 files changed, 287 insertions(+), 263 deletions(-)
diff --git a/src/gui/arm.xml b/src/gui/arm.xml
index a511583..e58279b 100644
--- a/src/gui/arm.xml
+++ b/src/gui/arm.xml
@@ -282,358 +282,403 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox_main">
+ <object class="GtkVPaned" id="vpaned_main">
<property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkNotebook" id="notebook_main">
+ <object class="GtkHPaned" id="hpaned_main">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
- <object class="GtkVBox" id="vbox_graph">
+ <object class="GtkNotebook" id="notebook_main">
<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>
+ <property name="can_focus">True</property>
<child>
- <object class="GtkHBox" id="hbox_graph">
+ <object class="GtkVBox" id="vbox_graph">
<property name="visible">True</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkVBox" id="vbox_graph_primary">
+ <object class="GtkLabel" id="label_graph_top">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <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>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <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_primary_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>
+ <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="GtkVBox" id="vbox_graph_secondary">
+ <object class="GtkHBox" id="hbox_graph">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
<child>
- <object class="GtkLabel" id="label_graph_secondary_top">
+ <object class="GtkVBox" id="vbox_graph_primary">
<property name="visible">True</property>
- <property name="label" translatable="yes">Upload (0.0 b/sec)</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <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>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="placeholder_graph_primary">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <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>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkVBox" id="placeholder_graph_secondary">
+ <object class="GtkVBox" id="vbox_graph_secondary">
<property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <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>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
<child>
- <placeholder/>
+ <object class="GtkVBox" id="placeholder_graph_secondary">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <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>
+ <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>
- <child>
- <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>
- <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">
+ <child type="tab">
+ <object class="GtkLabel" id="label_notebook_graph">
<property name="visible">True</property>
- <property name="label" translatable="yes">2 Clients, 1 Control</property>
+ <property name="label" translatable="yes">Graphs</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
+ <property name="tab_fill">False</property>
</packing>
</child>
<child>
- <object class="GtkTreeView" id="treeview_conn">
+ <object class="GtkVBox" id="vbox_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>
- <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>
+ <property name="orientation">vertical</property>
<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 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="GtkTreeViewColumn" id="treeviewcolumn_conn_type">
- <property name="title">column</property>
+ <object class="GtkScrolledWindow" id="scrolledwindow_conn">
+ <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="GtkCellRendererText" id="cellrenderertext_conn_type"/>
- <attributes>
- <attribute name="foreground">4</attribute>
- <attribute name="markup">3</attribute>
- </attributes>
+ <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>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <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_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>
</child>
</object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
</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">
+ <child type="tab">
+ <object class="GtkLabel" id="label_notebook_conn">
<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>
+ <property name="label" translatable="yes">Connections</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
</packing>
</child>
<child>
- <object class="GtkScrolledWindow" id="scrolledwindow_config">
+ <object class="GtkVBox" id="vbox_config">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</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="GtkTreeView" id="treeview_config">
+ <object class="GtkScrolledWindow" id="scrolledwindow_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>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
<child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn_key">
- <property name="title">column</property>
+ <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="headers_clickable">False</property>
+ <property name="search_column">0</property>
<child>
- <object class="GtkCellRendererText" id="cellrenderertext_config_key"/>
- <attributes>
- <attribute name="foreground">3</attribute>
- <attribute name="markup">0</attribute>
- </attributes>
+ <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>
- </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>
+ <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>
- </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>
+ <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>
</child>
</object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
</child>
</object>
<packing>
- <property name="position">1</property>
+ <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">2</property>
+ <property name="resize">False</property>
+ <property name="shrink">True</property>
</packing>
</child>
- <child type="tab">
- <object class="GtkLabel" id="label_notebook_config">
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow_sticky">
<property name="visible">True</property>
- <property name="label" translatable="yes">Configuration</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_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>
+ </child>
</object>
<packing>
- <property name="position">2</property>
- <property name="tab_fill">False</property>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
</packing>
</child>
</object>
<packing>
- <property name="position">0</property>
+ <property name="resize">False</property>
+ <property name="shrink">True</property>
</packing>
</child>
<child>
- <object class="GtkScrolledWindow" id="scrolledwindow_sticky">
+ <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="GtkTreeView" id="treeview_sticky">
+ <object class="GtkTextView" id="textview_log">
<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_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>
+ <property name="buffer">textbuffer_log</property>
</object>
</child>
</object>
<packing>
- <property name="padding">5</property>
- <property name="position">1</property>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
</packing>
</child>
</object>
@@ -641,27 +686,6 @@ each direction. (Default: 0) </span></property>
<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>
- <property name="buffer">textbuffer_log</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>
1
0

[arm/master] Added minimum width/height requirements for paned childs.
by atagar@torproject.org 14 Jun '11
by atagar@torproject.org 14 Jun '11
14 Jun '11
commit a3c427e1203d056f7c647ed679bbc54ced47aba8
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Tue Jun 14 02:48:30 2011 +0500
Added minimum width/height requirements for paned childs.
---
src/gui/arm.xml | 15 +++++++++------
1 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/src/gui/arm.xml b/src/gui/arm.xml
index e58279b..23230b6 100644
--- a/src/gui/arm.xml
+++ b/src/gui/arm.xml
@@ -288,10 +288,12 @@
<property name="orientation">vertical</property>
<child>
<object class="GtkHPaned" id="hpaned_main">
+ <property name="height_request">300</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkNotebook" id="notebook_main">
+ <property name="width_request">300</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
@@ -607,8 +609,8 @@ each direction. (Default: 0) </span></property>
</child>
</object>
<packing>
- <property name="resize">False</property>
- <property name="shrink">True</property>
+ <property name="resize">True</property>
+ <property name="shrink">False</property>
</packing>
</child>
<child>
@@ -653,17 +655,18 @@ each direction. (Default: 0) </span></property>
</object>
<packing>
<property name="resize">True</property>
- <property name="shrink">True</property>
+ <property name="shrink">False</property>
</packing>
</child>
</object>
<packing>
- <property name="resize">False</property>
- <property name="shrink">True</property>
+ <property name="resize">True</property>
+ <property name="shrink">False</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow_log">
+ <property name="height_request">100</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
@@ -678,7 +681,7 @@ each direction. (Default: 0) </span></property>
</object>
<packing>
<property name="resize">True</property>
- <property name="shrink">True</property>
+ <property name="shrink">False</property>
</packing>
</child>
</object>
1
0
commit f874c839fdf7bee393492bd6b38a5e468b1b1a06
Author: Kamran Riaz Khan <krkhan(a)inspirated.com>
Date: Tue Jun 14 02:41:29 2011 +0500
Initial commit for bandwidth graphs.
---
src/gui/controller.py | 51 +++++++++++++++++++++++++++++-
src/gui/graphing/__init__.py | 6 +++
src/gui/graphing/bandwidthStats.py | 26 +++++++++++++++
src/gui/graphing/graphStats.py | 61 ++++++++++++++++++++++++++++++++++++
4 files changed, 143 insertions(+), 1 deletions(-)
diff --git a/src/gui/controller.py b/src/gui/controller.py
index 0e444d3..91b9a03 100644
--- a/src/gui/controller.py
+++ b/src/gui/controller.py
@@ -1,14 +1,36 @@
+import gobject
+import gtk
+
from util import torTools
+from gui.graphing import graphStats, bandwidthStats
-import gtk
+from cagraph.ca_graph import CaGraph
+from cagraph.axis.xaxis import CaGraphXAxis
+from cagraph.axis.yaxis import CaGraphYAxis
+from cagraph.ca_graph_grid import CaGraphGrid
+from cagraph.series.area import CaGraphSeriesArea
+
+gobject.threads_init()
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)
+ # for custom widgets not present in builder xml
+ self.widgets = {}
+
+ self._pack_graph_widget('primary')
+ self._pack_graph_widget('secondary')
+
+ self.bwStats = bandwidthStats.BandwidthStats(self.widgets)
+
+ gobject.timeout_add(1000, self.bwStats.draw_graph, 'primary')
+ gobject.timeout_add(1000, self.bwStats.draw_graph, 'secondary')
+
def run(self):
window = self.builder.get_object('window_main')
@@ -23,6 +45,33 @@ class GuiController:
def on_window_main_delete_event(self, widget, data=None):
gtk.main_quit()
+ def _pack_graph_widget(self, name):
+ graph = CaGraph()
+ placeholder = self.builder.get_object('placeholder_graph_%s' % name)
+ placeholder.pack_start(graph)
+
+ xaxis = CaGraphXAxis(graph)
+ yaxis = CaGraphYAxis(graph)
+
+ xaxis.min = 0
+ xaxis.max = graphStats.GRAPH_INTERVAL - 1
+ xaxis.axis_style.draw_labels = False
+
+ graph.axiss.append(xaxis)
+ graph.axiss.append(yaxis)
+
+ series = CaGraphSeriesArea(graph, 0, 1)
+
+ line_colors = {'primary' : (1.0, 0.0, 1.0, 1.0), 'secondary' : (0.0, 1.0, 0.0, 1.0)}
+ fill_colors = {'primary' : (1.0, 0.0, 1.0, 0.3), 'secondary' : (0.0, 1.0, 0.0, 0.3)}
+ series.style.line_color = line_colors[name]
+ series.style.fill_color = fill_colors[name]
+
+ graph.seriess.append(series)
+ graph.grid = CaGraphGrid(graph, 0, 1)
+
+ self.widgets['graph_%s' % name] = graph
+
def startGui():
controller = GuiController()
controller.run()
diff --git a/src/gui/graphing/__init__.py b/src/gui/graphing/__init__.py
new file mode 100644
index 0000000..acc8645
--- /dev/null
+++ b/src/gui/graphing/__init__.py
@@ -0,0 +1,6 @@
+"""
+Graphs.
+"""
+
+__all__ = ["graphStats", "bandwidthStats"]
+
diff --git a/src/gui/graphing/bandwidthStats.py b/src/gui/graphing/bandwidthStats.py
new file mode 100644
index 0000000..304574e
--- /dev/null
+++ b/src/gui/graphing/bandwidthStats.py
@@ -0,0 +1,26 @@
+"""
+Bandwidth monitors.
+"""
+
+import sys
+
+import gobject
+import gtk
+
+from TorCtl import TorCtl
+from gui.graphing import graphStats
+from util import torTools
+
+class BandwidthStats(graphStats.GraphStats):
+ def __init__(self, widgets):
+ graphStats.GraphStats.__init__(self, widgets)
+
+ conn = torTools.getConn()
+ if not conn.isAlive():
+ conn.init()
+ conn.setControllerEvents(["BW"])
+ conn.addEventListener(self)
+
+ def bandwidth_event(self, event):
+ self._processEvent(event.read / 1024.0, event.written / 1024.0)
+
diff --git a/src/gui/graphing/graphStats.py b/src/gui/graphing/graphStats.py
new file mode 100644
index 0000000..5037c39
--- /dev/null
+++ b/src/gui/graphing/graphStats.py
@@ -0,0 +1,61 @@
+"""
+Base class for implementing graphing functionality.
+"""
+
+import random
+import sys
+
+from collections import deque
+
+import gobject
+import gtk
+
+from TorCtl import TorCtl
+from util import torTools
+
+GRAPH_INTERVAL = 30
+
+class GraphStats(TorCtl.PostEventListener):
+ def __init__(self, widgets):
+ TorCtl.PostEventListener.__init__(self)
+
+ self.widgets = widgets
+
+ self.data = {
+ 'primary' : deque([0] * GRAPH_INTERVAL),
+ 'secondary' : deque([0] * GRAPH_INTERVAL)}
+
+ def get_graph_data(self, name):
+ packed_data = []
+
+ for (index, value) in enumerate(self.data[name]):
+ packed_data.append((index, value))
+
+ return packed_data
+
+ def is_graph_data_zero(self, name):
+ data = self.data[name]
+ return len(data) == map(int, data).count(0)
+
+ def draw_graph(self, name):
+ graph = self.widgets['graph_%s' % name]
+ data = self.get_graph_data(name)
+
+ if self.is_graph_data_zero(name):
+ graph.seriess[0].data = []
+ else:
+ graph.seriess[0].data = data
+
+ for (index, axis) in enumerate(graph.axiss):
+ if axis.type != 'xaxis':
+ graph.auto_set_yrange(index)
+
+ graph.queue_draw()
+ return True
+
+ def _processEvent(self, primary, secondary):
+ self.data['primary'].rotate(1)
+ self.data['primary'][0] = primary
+ self.data['secondary'].rotate(1)
+ self.data['secondary'][0] = secondary
+
1
0

13 Jun '11
commit 910dadd6eab5b2b3af3b655f52b861085f379b84
Author: Sebastian Hahn <sebastian(a)torproject.org>
Date: Sun Jun 12 13:55:32 2011 +0200
Ensure the release tarball contains all manpages
Thanks to Nick for the idea for the fix.
---
changes/bug3389 | 4 ++++
doc/Makefile.am | 18 ++++++++++--------
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/changes/bug3389 b/changes/bug3389
new file mode 100644
index 0000000..2442f4f
--- /dev/null
+++ b/changes/bug3389
@@ -0,0 +1,4 @@
+ o Major bugfixes:
+ - Always ship the tor-fw-helper manpage in our release tarballs. Bugfix
+ on 0.2.3.1-alpha; fixes bug 3389. Reported by Stephen Walker.
+
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 6cc0ea9..d8d9fbe 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -12,19 +12,21 @@
# part of the source distribution, so that people without asciidoc can
# just use the .1 and .html files.
+regular_mans = tor tor-gencert tor-resolve torify
+all_mans = $(regular_mans) tor-fw-helper
+
if USE_ASCIIDOC
if USE_FW_HELPER
-asciidoc_files = tor tor-gencert tor-resolve torify tor-fw-helper
+nodist_man_MANS = $(all_mans:=.1)
+doc_DATA = $(all_mans:=.html)
else
-asciidoc_files = tor tor-gencert tor-resolve torify
+nodist_man_MANS = $(regular_mans:=.1)
+doc_DATA = $(regular_mans:=.html)
endif
-html_in = $(asciidoc_files:=.html.in)
-man_in = $(asciidoc_files:=.1.in)
-txt_in = $(asciidoc_files:=.1.txt)
-nodist_man_MANS = $(asciidoc_files:=.1)
-doc_DATA = $(asciidoc_files:=.html)
+html_in = $(all_mans:=.html.in)
+man_in = $(all_mans:=.1.in)
+txt_in = $(all_mans:=.1.txt)
else
-asciidoc_files =
html_in =
man_in =
txt_in =
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
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

13 Jun '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

r24820: {website} add stories from the BBC and CNN. (website/trunk/press/en)
by Andrew Lewman 13 Jun '11
by Andrew Lewman 13 Jun '11
13 Jun '11
Author: phobos
Date: 2011-06-13 00:53:40 +0000 (Mon, 13 Jun 2011)
New Revision: 24820
Modified:
website/trunk/press/en/inthemedia.wml
Log:
add stories from the BBC and CNN.
Modified: website/trunk/press/en/inthemedia.wml
===================================================================
--- website/trunk/press/en/inthemedia.wml 2011-06-11 18:55:49 UTC (rev 24819)
+++ website/trunk/press/en/inthemedia.wml 2011-06-13 00:53:40 UTC (rev 24820)
@@ -32,6 +32,20 @@
<th>Topic</th>
</tr>
</thead>
+<tr>
+<td>2011 June 12</td>
+<td>CNN: Tech</td>
+<td><a href="http://www.cnn.com/2011/TECH/web/06/11/hiding.online.identity/index.html">Wiping
+away whistle-blowers' online fingerprints</a></td>
+</tr>
+<tr style="background-color: #e5e5e5;">
+<td>2011 May 14</td>
+<td>BBC: Click</td>
+<td><a href="http://news.bbc.co.uk/2/hi/programmes/click_online/default.stm">Andrew
+and Dr. Angela Sasse from UCL were interviewed by the BBC Click program
+about why Internet Anonymity is important and valuable in a modern,
+networked society.</a></td>
+</tr>
<tr>
<td>2011 March 29</td>
<td>CNN: Situation Room</td>
1
0
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