[tor-commits] [vidalia/alpha] Implement circuit clasification inside the Network Map

chiiph at torproject.org chiiph at torproject.org
Thu Mar 15 13:17:56 UTC 2012


commit df79f222a6412c9abf337ff3d946cfeed3461ad4
Author: Tomás Touceda <chiiph at torproject.org>
Date:   Thu Mar 15 10:12:03 2012 -0300

    Implement circuit clasification inside the Network Map
    
    Also, remove some whitespace
---
 src/torcontrol/Circuit.cpp              |   80 +++++++-
 src/torcontrol/Circuit.h                |   52 +++++-
 src/torcontrol/TorControl.cpp           |    6 +-
 src/vidalia/network/GeoIpResolver.cpp   |    8 +-
 src/vidalia/network/NetViewer.cpp       |   36 +++--
 src/vidalia/network/NetViewer.ui        |  326 ++++++++++++++++++-------------
 src/vidalia/network/TorMapImageView.cpp |   42 ++--
 7 files changed, 361 insertions(+), 189 deletions(-)

diff --git a/src/torcontrol/Circuit.cpp b/src/torcontrol/Circuit.cpp
index 3b6cb80..a15ddd6 100644
--- a/src/torcontrol/Circuit.cpp
+++ b/src/torcontrol/Circuit.cpp
@@ -1,36 +1,44 @@
 /*
 **  This file is part of Vidalia, and is subject to the license terms in the
-**  LICENSE file, found in the top level directory of this distribution. If 
+**  LICENSE file, found in the top level directory of this distribution. If
 **  you did not receive the LICENSE file with this file, you may obtain it
 **  from the Vidalia source package distributed by the Vidalia Project at
-**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 
-**  including this file, may be copied, modified, propagated, or distributed 
+**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
+**  including this file, may be copied, modified, propagated, or distributed
 **  except according to the terms described in the LICENSE file.
 */
 
-/* 
+/*
 ** \file Circuit.cpp
 ** \brief Object representing a Tor circuit
 */
 
 #include "tcglobal.h"
 #include "Circuit.h"
+#include "stringutil.h"
 
 #include <QStringList>
 #include <QRegExp>
+#include <QDebug>
 
 
 /** Default constructor. */
 Circuit::Circuit()
-{
-  _status  = Unknown;
-  _isValid = false;
-}
+  : _status(Unknown),
+    _isValid(false),
+    _buildFlags(None),
+    _purpose(General)
+{}
 
 /** Parses the string given in Tor control protocol format for a circuit. The
  * format is:
- * 
- *      CircuitID SP CircStatus [SP Path]
+ *
+ *    CircuitID SP CircStatus [SP Path]
+ *    [SP "BUILD_FLAGS=" BuildFlags] [SP "PURPOSE=" Purpose]
+ *    [SP "HS_STATE=" HSState] [SP "REND_QUERY=" HSAddress]
+ *    [SP "TIME_CREATED=" TimeCreated]
+ *    [SP "REASON=" Reason [SP "REMOTE_REASON=" Reason]] CRLF
+ *
  *
  * If the status is "LAUNCHED", the Path is empty. Server names in the path
  * must follow Tor's VERBOSE_NAMES format.
@@ -59,15 +67,65 @@ Circuit::Circuit(const QString &circuit)
       }
     }
 
+    if(parts.size() > 3) {
+      parts.removeFirst(); // remove id
+      parts.removeFirst(); // remove status
+      parts.removeFirst(); // remove path
+
+      bool ok;
+      QHash<QString,QString> rest = string_parse_keyvals(parts.join(" "), &ok);
+      foreach(const QString key, rest.keys()) {
+        if(key.compare("BUILD_FLAGS", Qt::CaseInsensitive) == 0) {
+          _buildFlags = None;
+          foreach(const QString flag, rest.value(key).split(","))
+             _buildFlags |= flagValue(flag);
+        } else if(key.compare("PURPOSE", Qt::CaseInsensitive) == 0) {
+          _purpose = purposeValue(rest.value(key));
+        }
+      }
+    }
+
     _isValid = true;
   }
   return;
-  
+
 err:
   tc::warn("Improperly formatted circuit: '%1'").arg(circuit);
   _isValid = false;
 }
 
+Circuit::BuildFlag
+Circuit::flagValue(const QString &flag) const
+{
+  if (!flag.compare("ONEHOP_TUNNEL", Qt::CaseInsensitive))
+    return OneHopTunnel;
+  if (!flag.compare("IS_INTERNAL", Qt::CaseInsensitive))
+    return IsInternal;
+  if (!flag.compare("NEED_CAPACITY", Qt::CaseInsensitive))
+    return NeedCapacity;
+  if (!flag.compare("NEED_UPTIME", Qt::CaseInsensitive))
+    return NeedUptime;
+  return None;
+}
+
+Circuit::Purpose
+Circuit::purposeValue(const QString &purpose) const
+{
+  if (!purpose.compare("CONTROLLER", Qt::CaseInsensitive))
+    return Controller;
+  if (!purpose.compare("HS_CLIENT_INTRO", Qt::CaseInsensitive))
+    return HsClientIntro;
+  if (!purpose.compare("HS_CLIENT_REND", Qt::CaseInsensitive))
+    return HsClientRend;
+  if (!purpose.compare("HS_SERVICE_INTRO", Qt::CaseInsensitive))
+    return HsServiceIntro;
+  if (!purpose.compare("HS_SERVICE_REND", Qt::CaseInsensitive))
+    return HsServiceRend;
+  if (!purpose.compare("TESTING", Qt::CaseInsensitive))
+    return Testing;
+  return General;
+}
+
 /** Returns true iff <b>circId</b> consists of only between 1 and 16
  * (inclusive) ASCII-encoded letters and numbers. */
 bool
diff --git a/src/torcontrol/Circuit.h b/src/torcontrol/Circuit.h
index 33f12ef..831816a 100644
--- a/src/torcontrol/Circuit.h
+++ b/src/torcontrol/Circuit.h
@@ -1,10 +1,10 @@
 /*
 **  This file is part of Vidalia, and is subject to the license terms in the
-**  LICENSE file, found in the top level directory of this distribution. If 
+**  LICENSE file, found in the top level directory of this distribution. If
 **  you did not receive the LICENSE file with this file, you may obtain it
 **  from the Vidalia source package distributed by the Vidalia Project at
-**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 
-**  including this file, may be copied, modified, propagated, or distributed 
+**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
+**  including this file, may be copied, modified, propagated, or distributed
 **  except according to the terms described in the LICENSE file.
 */
 
@@ -39,14 +39,35 @@ public:
     Closed     /**< Circuit closed (was built) */
   };
 
+  /** Build flags for circuits */
+  enum BuildFlag {
+    None         = 0x0000,
+    OneHopTunnel = 0x0001,
+    IsInternal   = 0x0002,
+    NeedCapacity = 0x0004,
+    NeedUptime   = 0x0008,
+  };
+  Q_DECLARE_FLAGS(BuildFlags, BuildFlag)
+
+  /** Purpose for a circuit */
+  enum Purpose {
+    General = 0,
+    HsClientIntro,
+    HsClientRend,
+    HsServiceIntro,
+    HsServiceRend,
+    Testing,
+    Controller
+  };
+
   /** Default constructor. */
   Circuit();
-  /** Constructor. */  
+  /** Constructor. */
   Circuit(const CircuitId &circuit);
-  
+
   /** Returns true if this circuit is valid. */
   bool isValid() const { return _isValid; }
-  
+
   /** Returns the ID for this circuit */
   CircuitId id() const { return _circId; }
   /** Returns the status of this circuit */
@@ -60,6 +81,11 @@ public:
   /** Returns the circuit's path as an ordered list of router fingerprints. */
   QStringList routerIDs() const { return _ids; }
 
+  /** Returns the circuit's build flags */
+  BuildFlags buildFlags() const { return _buildFlags; }
+  /** Returns the circuit's purpose */
+  Purpose purpose() const { return _purpose; }
+
   /** Converts a string description of a circuit's status to an enum value */
   static Status toStatus(const QString &strStatus);
 
@@ -73,6 +99,18 @@ private:
   QStringList _names;  /**< Nicknames of the routers in the circuit. */
   QStringList _ids;    /**< IDs of the routers in the circuit. */
   bool _isValid;
+
+  BuildFlags _buildFlags;
+  Purpose _purpose;
+
+  /** Returns a BuildFlag enum value for the given router status
+   * <b>flag</b>. If <b>flag</b> is not recognized, then <i>None</i>
+   * is returned. */
+  BuildFlag flagValue(const QString &flag) const;
+  /** Returns a Purpose enum value for the given router status
+   * <b>purpose</b>. If <b>purpose</b> is not recognized, then
+   * <i>General</i> is returned. */
+  Purpose purposeValue(const QString &purpose) const;
 };
 
 Q_DECLARE_METATYPE(Circuit);
@@ -80,5 +118,7 @@ Q_DECLARE_METATYPE(Circuit);
 /** A collection of circuits. */
 typedef QList<Circuit> CircuitList;
 
+Q_DECLARE_OPERATORS_FOR_FLAGS(Circuit::BuildFlags)
+
 #endif
 
diff --git a/src/torcontrol/TorControl.cpp b/src/torcontrol/TorControl.cpp
index 9cdf6ad..29d544f 100644
--- a/src/torcontrol/TorControl.cpp
+++ b/src/torcontrol/TorControl.cpp
@@ -3,8 +3,8 @@
 **  LICENSE file, found in the top level directory of this distribution. If
 **  you did not receive the LICENSE file with this file, you may obtain it
 **  from the Vidalia source package distributed by the Vidalia Project at
-**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 
-**  including this file, may be copied, modified, propagated, or distributed 
+**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
+**  including this file, may be copied, modified, propagated, or distributed
 **  except according to the terms described in the LICENSE file.
 */
 
@@ -906,7 +906,7 @@ TorControl::loadConf(const QString &contents, QString *errmsg)
 {
   ControlCommand cmd("+LOADCONF");
   ControlReply reply;
-  
+
   cmd.addArgument(contents + ".");
   return send(cmd, reply, errmsg);
 }
diff --git a/src/vidalia/network/GeoIpResolver.cpp b/src/vidalia/network/GeoIpResolver.cpp
index f2c5100..9752dd9 100644
--- a/src/vidalia/network/GeoIpResolver.cpp
+++ b/src/vidalia/network/GeoIpResolver.cpp
@@ -3,8 +3,8 @@
 **  LICENSE file, found in the top level directory of this distribution. If you
 **  did not receive the LICENSE file with this file, you may obtain it from the
 **  Vidalia source package distributed by the Vidalia Project at
-**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 
-**  including this file, may be copied, modified, propagated, or distributed 
+**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
+**  including this file, may be copied, modified, propagated, or distributed
 **  except according to the terms described in the LICENSE file.
 */
 
@@ -64,7 +64,7 @@ GeoIpResolver::resolveUsingLocalDatabase(const QHostAddress &ip)
     QString countryCode = _database.countryCodeByAddr(ip);
     if (! countryCode.isEmpty()) {
       QPair<float,float> coords = CountryInfo::countryLocation(countryCode);
-      return GeoIpRecord(ip, coords.first, coords.second, 
+      return GeoIpRecord(ip, coords.first, coords.second,
                          CountryInfo::countryName(countryCode),
                          countryCode);
     }
@@ -81,6 +81,6 @@ GeoIpResolver::resolve(const QHostAddress &ip)
   if (_useLocalDatabase)
     return resolveUsingLocalDatabase(ip);
 #endif
-  return resolveUsingTor(ip); 
+  return resolveUsingTor(ip);
 }
 
diff --git a/src/vidalia/network/NetViewer.cpp b/src/vidalia/network/NetViewer.cpp
index 8ff6b32..052bc90 100644
--- a/src/vidalia/network/NetViewer.cpp
+++ b/src/vidalia/network/NetViewer.cpp
@@ -3,8 +3,8 @@
 **  LICENSE file, found in the top level directory of this distribution. If you
 **  did not receive the LICENSE file with this file, you may obtain it from the
 **  Vidalia source package distributed by the Vidalia Project at
-**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 
-**  including this file, may be copied, modified, propagated, or distributed 
+**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
+**  including this file, may be copied, modified, propagated, or distributed
 **  except according to the terms described in the LICENSE file.
 */
 
@@ -110,7 +110,7 @@ NetViewer::NetViewer(QWidget *parent)
    * needs to be called to get rid of any descriptors that were removed. */
   _refreshTimer.setInterval(60*60*1000);
   connect(&_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
- 
+
   /* Connect the necessary slots and signals */
   connect(ui.actionHelp, SIGNAL(triggered()), this, SLOT(help()));
   connect(ui.actionRefresh, SIGNAL(triggered()), this, SLOT(refresh()));
@@ -229,7 +229,7 @@ NetViewer::refresh()
 
   /* Ok, they can refresh again. */
   ui.actionRefresh->setEnabled(true);
-} 
+}
 
 /** Clears the lists and the map */
 void
@@ -246,7 +246,7 @@ NetViewer::clear()
   ui.textRouterInfo->clear();
 }
 
-/** Called when the search of a router is triggered by the signal 
+/** Called when the search of a router is triggered by the signal
  * returnPressed from the search field. */
 void
 NetViewer::onRouterSearch()
@@ -287,7 +287,19 @@ void
 NetViewer::addCircuit(const Circuit &circuit)
 {
   /* Add the circuit to the list of all current circuits */
-  ui.treeCircuitList->addCircuit(circuit);
+  if(circuit.purpose() == Circuit::General or
+     circuit.purpose() == Circuit::Controller or
+     circuit.purpose() == Circuit::Testing) {
+    if((circuit.buildFlags() & Circuit::OneHopTunnel) or
+       (circuit.buildFlags() & Circuit::IsInternal)) {
+      ui.treeInternalCircuitList->addCircuit(circuit);
+    } else {
+      ui.treeCircuitList->addCircuit(circuit);
+    }
+  } else {
+    ui.treeHSCircuitList->addCircuit(circuit);
+  }
+
   /* Plot the circuit on the map */
   _map->addCircuit(circuit.id(), circuit.routerIDs());
 }
@@ -301,7 +313,7 @@ NetViewer::addStream(const Stream &stream)
   if (stream.status() == Stream::New) {
     QString target = stream.targetAddress();
     if (! QHostAddress(target).isNull() && _addressMap.isMapped(target)) {
-      /* Replace the IP address in the stream event with the original 
+      /* Replace the IP address in the stream event with the original
        * hostname */
       ui.treeCircuitList->addStream(
         Stream(stream.id(), stream.status(), stream.circuitId(),
@@ -332,11 +344,11 @@ void
 NetViewer::preLoadNetworkStatus()
 {
   NetworkStatus networkStatus = _torControl->getNetworkStatus();
-  
+
   foreach(RouterStatus rs, networkStatus) {
     if (!rs.isRunning())
       continue;
-    
+
     RouterDescriptor rd = _torControl->getRouterDescriptor(rs.id());
     if(_torControl->useMicrodescriptors()) {
       rd.appendRouterStatusInfo(rs);
@@ -346,7 +358,7 @@ NetViewer::preLoadNetworkStatus()
 
     QCoreApplication::processEvents();
   }
-  
+
   _it = _routers.constBegin();
   QTimer::singleShot(200, this, SLOT(loadNetworkStatus()));
 }
@@ -448,13 +460,13 @@ NetViewer::routerSelected(const QList<RouterDescriptor> &routers)
   //   _map->selectRouter(routers[0].id());
 }
 
-/** Called when the user selects a router on the network map. Displays a 
+/** Called when the user selects a router on the network map. Displays a
  * dialog with detailed information for the router specified by
  * <b>id</b>.*/
 void
 NetViewer::displayRouterInfo(const QString &id)
 {
-  RouterInfoDialog dlg(_map->isFullScreen() ? static_cast<QWidget*>(_map) 
+  RouterInfoDialog dlg(_map->isFullScreen() ? static_cast<QWidget*>(_map)
                                             : static_cast<QWidget*>(this));
 
   /* Fetch the specified router's descriptor */
diff --git a/src/vidalia/network/NetViewer.ui b/src/vidalia/network/NetViewer.ui
index 11fd0a2..b7bc0e9 100644
--- a/src/vidalia/network/NetViewer.ui
+++ b/src/vidalia/network/NetViewer.ui
@@ -6,50 +6,20 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>694</width>
-    <height>552</height>
+    <width>736</width>
+    <height>630</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Network Map</string>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
+  <layout class="QVBoxLayout" name="verticalLayout_7">
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout"/>
    </item>
    <item>
-    <widget class="QSplitter" name="splitter">
-     <property name="contextMenuPolicy">
-      <enum>Qt::NoContextMenu</enum>
-     </property>
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-     <property name="childrenCollapsible">
-      <bool>false</bool>
-     </property>
-     <widget class="QSplitter" name="splitter4">
-      <property name="sizePolicy">
-       <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-        <horstretch>1</horstretch>
-        <verstretch>0</verstretch>
-       </sizepolicy>
-      </property>
-      <property name="minimumSize">
-       <size>
-        <width>175</width>
-        <height>0</height>
-       </size>
-      </property>
-      <property name="contextMenuPolicy">
-       <enum>Qt::NoContextMenu</enum>
-      </property>
-      <property name="orientation">
-       <enum>Qt::Vertical</enum>
-      </property>
-      <property name="childrenCollapsible">
-       <bool>false</bool>
-      </property>
+    <layout class="QGridLayout" name="gridLayout_6">
+     <item row="0" column="1">
       <widget class="QLineEdit" name="lineRouterSearch">
        <property name="minimumSize">
         <size>
@@ -64,6 +34,8 @@
         </size>
        </property>
       </widget>
+     </item>
+     <item row="1" column="1">
       <widget class="RouterListWidget" name="treeRouterList">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
@@ -111,23 +83,8 @@
         </property>
        </column>
       </widget>
-     </widget>
-     <widget class="QSplitter" name="splitter3">
-      <property name="sizePolicy">
-       <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-        <horstretch>100</horstretch>
-        <verstretch>0</verstretch>
-       </sizepolicy>
-      </property>
-      <property name="contextMenuPolicy">
-       <enum>Qt::NoContextMenu</enum>
-      </property>
-      <property name="orientation">
-       <enum>Qt::Vertical</enum>
-      </property>
-      <property name="childrenCollapsible">
-       <bool>false</bool>
-      </property>
+     </item>
+     <item row="0" column="0" rowspan="2">
       <widget class="QFrame" name="frmMap">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
@@ -150,93 +107,198 @@
        <property name="frameShadow">
         <enum>QFrame::Raised</enum>
        </property>
-       <layout class="QHBoxLayout">
-        <property name="spacing">
-         <number>6</number>
-        </property>
-        <property name="margin">
-         <number>9</number>
-        </property>
+       <layout class="QGridLayout" name="gridLayout_5">
+        <item row="0" column="0">
+         <layout class="QGridLayout" name="gridLayout"/>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QSplitter" name="splitter">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <widget class="QTabWidget" name="tabWidget">
+      <property name="currentIndex">
+       <number>2</number>
+      </property>
+      <widget class="QWidget" name="tab">
+       <attribute name="title">
+        <string>Exit circuits</string>
+       </attribute>
+       <layout class="QVBoxLayout" name="verticalLayout_2">
         <item>
-         <layout class="QGridLayout" name="gridLayout">
-          <property name="margin">
-           <number>0</number>
-          </property>
-          <property name="spacing">
-           <number>6</number>
-          </property>
+         <layout class="QVBoxLayout" name="verticalLayout">
+          <item>
+           <widget class="CircuitListWidget" name="treeCircuitList">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+              <horstretch>100</horstretch>
+              <verstretch>100</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="minimumSize">
+             <size>
+              <width>300</width>
+              <height>0</height>
+             </size>
+            </property>
+            <property name="contextMenuPolicy">
+             <enum>Qt::CustomContextMenu</enum>
+            </property>
+            <property name="statusTip">
+             <string/>
+            </property>
+            <property name="sortingEnabled">
+             <bool>false</bool>
+            </property>
+            <property name="columnCount">
+             <number>2</number>
+            </property>
+            <column>
+             <property name="text">
+              <string>Connection</string>
+             </property>
+            </column>
+            <column>
+             <property name="text">
+              <string>Status</string>
+             </property>
+            </column>
+           </widget>
+          </item>
          </layout>
         </item>
        </layout>
       </widget>
-      <widget class="QSplitter" name="splitter2">
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
-         <horstretch>100</horstretch>
-         <verstretch>1</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="contextMenuPolicy">
-        <enum>Qt::NoContextMenu</enum>
-       </property>
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="childrenCollapsible">
-        <bool>false</bool>
-       </property>
-       <widget class="CircuitListWidget" name="treeCircuitList">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-          <horstretch>100</horstretch>
-          <verstretch>100</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="minimumSize">
-         <size>
-          <width>300</width>
-          <height>0</height>
-         </size>
-        </property>
-        <property name="contextMenuPolicy">
-         <enum>Qt::CustomContextMenu</enum>
-        </property>
-        <property name="statusTip">
-         <string/>
-        </property>
-        <property name="sortingEnabled">
-         <bool>false</bool>
-        </property>
-        <property name="columnCount">
-         <number>2</number>
-        </property>
-        <column>
-         <property name="text">
-          <string>Connection</string>
-         </property>
-        </column>
-        <column>
-         <property name="text">
-          <string>Status</string>
-         </property>
-        </column>
-       </widget>
-       <widget class="RouterDescriptorView" name="textRouterInfo">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-          <horstretch>100</horstretch>
-          <verstretch>100</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="contextMenuPolicy">
-         <enum>Qt::DefaultContextMenu</enum>
-        </property>
-        <property name="readOnly">
-         <bool>true</bool>
-        </property>
-       </widget>
+      <widget class="QWidget" name="tab_2">
+       <attribute name="title">
+        <string>Internal circuits</string>
+       </attribute>
+       <layout class="QVBoxLayout" name="verticalLayout_4">
+        <item>
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <item>
+           <widget class="CircuitListWidget" name="treeInternalCircuitList">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+              <horstretch>100</horstretch>
+              <verstretch>100</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="minimumSize">
+             <size>
+              <width>300</width>
+              <height>0</height>
+             </size>
+            </property>
+            <property name="contextMenuPolicy">
+             <enum>Qt::CustomContextMenu</enum>
+            </property>
+            <property name="statusTip">
+             <string/>
+            </property>
+            <property name="frameShape">
+             <enum>QFrame::StyledPanel</enum>
+            </property>
+            <property name="frameShadow">
+             <enum>QFrame::Sunken</enum>
+            </property>
+            <property name="sortingEnabled">
+             <bool>false</bool>
+            </property>
+            <property name="columnCount">
+             <number>2</number>
+            </property>
+            <column>
+             <property name="text">
+              <string>Connection</string>
+             </property>
+            </column>
+            <column>
+             <property name="text">
+              <string>Status</string>
+             </property>
+            </column>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+      <widget class="QWidget" name="tab_3">
+       <attribute name="title">
+        <string>Hidden Service circuits</string>
+       </attribute>
+       <layout class="QVBoxLayout" name="verticalLayout_6">
+        <item>
+         <layout class="QVBoxLayout" name="verticalLayout_5">
+          <item>
+           <widget class="CircuitListWidget" name="treeHSCircuitList">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+              <horstretch>100</horstretch>
+              <verstretch>100</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="minimumSize">
+             <size>
+              <width>300</width>
+              <height>0</height>
+             </size>
+            </property>
+            <property name="contextMenuPolicy">
+             <enum>Qt::CustomContextMenu</enum>
+            </property>
+            <property name="statusTip">
+             <string/>
+            </property>
+            <property name="frameShape">
+             <enum>QFrame::StyledPanel</enum>
+            </property>
+            <property name="frameShadow">
+             <enum>QFrame::Sunken</enum>
+            </property>
+            <property name="sortingEnabled">
+             <bool>false</bool>
+            </property>
+            <property name="columnCount">
+             <number>2</number>
+            </property>
+            <column>
+             <property name="text">
+              <string>Connection</string>
+             </property>
+            </column>
+            <column>
+             <property name="text">
+              <string>Status</string>
+             </property>
+            </column>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
       </widget>
      </widget>
+     <widget class="RouterDescriptorView" name="textRouterInfo">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+        <horstretch>100</horstretch>
+        <verstretch>100</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="contextMenuPolicy">
+       <enum>Qt::DefaultContextMenu</enum>
+      </property>
+      <property name="readOnly">
+       <bool>true</bool>
+      </property>
+     </widget>
     </widget>
    </item>
   </layout>
diff --git a/src/vidalia/network/TorMapImageView.cpp b/src/vidalia/network/TorMapImageView.cpp
index 6c04d89..aac70d0 100644
--- a/src/vidalia/network/TorMapImageView.cpp
+++ b/src/vidalia/network/TorMapImageView.cpp
@@ -3,8 +3,8 @@
 **  LICENSE file, found in the top level directory of this distribution. If you
 **  did not receive the LICENSE file with this file, you may obtain it from the
 **  Vidalia source package distributed by the Vidalia Project at
-**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 
-**  including this file, may be copied, modified, propagated, or distributed 
+**  http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
+**  including this file, may be copied, modified, propagated, or distributed
 **  except according to the terms described in the LICENSE file.
 */
 
@@ -59,7 +59,7 @@ static float  plen[] = {
     0.6213, 0.5722, 0.5322
   };
 
-/** Distance of corresponding parallel from equator */ 
+/** Distance of corresponding parallel from equator */
 static float  pdfe[] = {
     0.0000, 0.0620, 0.1240, 0.1860,
     0.2480, 0.3100, 0.3720, 0.4340,
@@ -88,7 +88,7 @@ TorMapImageView::addRouter(const RouterDescriptor &desc, const GeoIpRecord &geoi
 {
   QString id = desc.id();
   QPointF routerCoord = toMapSpace(geoip.latitude(), geoip.longitude());
-  
+
   /* Add data the hash of known routers, and plot the point on the map */
   if (_routers.contains(id))
     _routers.value(id)->first = routerCoord;
@@ -101,25 +101,25 @@ void
 TorMapImageView::addCircuit(const CircuitId &circid, const QStringList &path)
 {
   QPainterPath *circPainterPath = new QPainterPath;
-  
+
   /* Build the new circuit */
   for (int i = 0; i < path.size()-1; i++) {
     QString fromNode = path.at(i);
     QString toNode = path.at(i+1);
-   
+
     /* Add the coordinates of the hops to the circuit */
     if (_routers.contains(fromNode) && _routers.contains(toNode)) {
       /* Find the two endpoints for this path segment */
       QPointF fromPos = _routers.value(fromNode)->first;
       QPointF endPos = _routers.value(toNode)->first;
-      
-      /* Draw the path segment */ 
+
+      /* Draw the path segment */
       circPainterPath->moveTo(fromPos);
       circPainterPath->lineTo(endPos);
       circPainterPath->moveTo(endPos);
     }
   }
-  
+
   /** Add the data to the hash of known circuits and plot the circuit on the map */
   if (_circuits.contains(circid)) {
     /* This circuit is being updated, so just update the path, making sure we
@@ -156,7 +156,7 @@ TorMapImageView::selectRouter(const QString &id)
   repaint();
 }
 
-/** Selects and highlights the circuit with the id <b>circid</b> 
+/** Selects and highlights the circuit with the id <b>circid</b>
  * on the map. */
 void
 TorMapImageView::selectCircuit(const CircuitId &circid)
@@ -199,17 +199,17 @@ TorMapImageView::clear()
     delete circuitPair;
   }
 }
-  
+
 /** Draws the routers and paths onto the map image. */
 void
 TorMapImageView::paintImage(QPainter *painter)
 {
   painter->setRenderHint(QPainter::Antialiasing);
-  
+
   /* Draw the router points */
   foreach(QString router, _routers.keys()) {
     QPair<QPointF,bool> *routerPair = _routers.value(router);
-    painter->setPen((routerPair->second ? PEN_SELECTED : PEN_ROUTER)); 
+    painter->setPen((routerPair->second ? PEN_SELECTED : PEN_ROUTER));
     painter->drawPoint(routerPair->first);
   }
   /* Draw the circuit paths */
@@ -231,10 +231,10 @@ TorMapImageView::toMapSpace(float latitude, float longitude)
 
   float lat;
   float lon;
-  
+
   lat = floor(longitude * (deg * lerp(abs(int(latitude)), plen))
 	      + width/2 + MAP_LEFT);
-  
+
   if (latitude < 0) {
     lon = floor((height/2) + (lerp(abs(int(latitude)), pdfe) * (height/2))
 		+ MAP_TOP);
@@ -245,14 +245,14 @@ TorMapImageView::toMapSpace(float latitude, float longitude)
 
   return QPointF(lat, lon);
 }
-  
+
 /** Linearly interpolates using the values in the Robinson projection table */
 float
 TorMapImageView::lerp(float input, float *table)
 {
   int x = int(floor(input / 5));
 
-  return ((table[x+1] - table[x]) / 
+  return ((table[x+1] - table[x]) /
 	  (((x+1)*5) - (x*5))) * (input - x*5) + table[x];
 }
 
@@ -270,7 +270,7 @@ void
 TorMapImageView::zoomToFit()
 {
   QRectF rect = circuitBoundingBox();
-  
+
   if (rect.isNull()) {
     /* If there are no circuits, zoom all the way out */
     resetZoomPoint();
@@ -279,7 +279,7 @@ TorMapImageView::zoomToFit()
     /* Zoom in on the displayed circuits */
     float zoomLevel = 1.0 - qMax(rect.height()/float(MAP_HEIGHT),
                                  rect.width()/float(MAP_WIDTH));
-    
+
     zoom(rect.center().toPoint(), zoomLevel+0.2);
   }
 }
@@ -305,12 +305,12 @@ void
 TorMapImageView::zoomToRouter(const QString &id)
 {
   QPair<QPointF,bool> *routerPair;
-  
+
   if (_routers.contains(id)) {
     deselectAll();
     routerPair = _routers.value(id);
     routerPair->second = true;  /* Set the router point to "selected" */
-    zoom(routerPair->first.toPoint(), 1.0); 
+    zoom(routerPair->first.toPoint(), 1.0);
   }
 }
 





More information about the tor-commits mailing list