Commit fc1ff764 authored by Matt Edman's avatar Matt Edman
Browse files

Add the ability to view active circuits and streams. This still needs a little

polish, but it's pretty much all here.


svn:r870
parent 02e3e21f
Loading
Loading
Loading
Loading
+29 −2
Changes for src/gui/network/circuititem.cpp: 29 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -24,11 +24,38 @@
 * \version $Id$
 */

#include "circuitlistwidget.h"
#include "circuititem.h"


CircuitItem::CircuitItem(CircuitListWidget *parent)
: QTreeWidgetItem(parent)
/** Constructor */
CircuitItem::CircuitItem(Circuit circuit)
{
  /* Save the circuit id */
  _id = circuit.id();
  /* Update the displayed text */
  update(circuit);
}

/** Updates the status and path of this circuit item. */
void
CircuitItem::update(Circuit circuit)
{
  /* Get the path, or put in a semi-meaningful value if the path is empty */
  QString path = circuit.path();
  if (path.isEmpty()) {
    path = tr("<Path Empty>");
  }

  /* Update the column fields */
  setText(CircuitListWidget::ConnectionColumn, path);
  setText(CircuitListWidget::StatusColumn, circuit.statusString());
}

/** Adds a stream as a child of this circuit. */
void
CircuitItem::addStream(StreamItem *stream)
{
  addChild(stream);
}
+17 −2
Changes for src/gui/network/circuititem.h: 17 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -27,16 +27,31 @@
#ifndef _CIRCUITITEM_H
#define _CIRCUITITEM_H

#include <QApplication>
#include <QTreeWidgetItem>
#include <control/circuit.h>
#include <control/stream.h>

#include "circuitlistwidget.h"
#include "streamitem.h"


class CircuitItem : public QTreeWidgetItem
{
  Q_DECLARE_TR_FUNCTIONS(CircuitItem)

public:
  /** Default constructor */
  CircuitItem(CircuitListWidget *parent);
  CircuitItem(Circuit circuit);
 
  /** Adds a stream to this circuit item */
  void addStream(StreamItem *stream);
  /** Updates the status of this circuit item using the given circuit. */
  void update(Circuit circuit);
  /** Returns the ID for this circuit. */
  quint64 id() { return _id; }
  
private:
  quint64 _id; /**< Circuit ID associated with this item. */
};

#endif
+173 −0
Changes for src/gui/network/circuitlistwidget.cpp: 173 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -24,11 +24,184 @@
 * \version $Id$
 */

#include <QTimer>

#include "circuitlistwidget.h"

#define CLOSED_CIRCUIT_REMOVE_DELAY     3000
#define FAILED_CIRCUIT_REMOVE_DELAY     5000
#define CLOSED_STREAM_REMOVE_DELAY      3000
#define FAILED_STREAM_REMOVE_DELAY      4000


/** Default constructor. */
CircuitListWidget::CircuitListWidget(QWidget *parent)
: QTreeWidget(parent)
{
}

/** Adds a circuit to the list. If the circuit already exists in the list, the
 * status and path will be updated. */
void
CircuitListWidget::addCircuit(Circuit circuit)
{
  /* Check to see if the circuit already exists in the tree */
  CircuitItem *item = findCircuitItem(circuit.id());
  
  if (!item) {
    /* Add the new circuit */
    addTopLevelItem(new CircuitItem(circuit));
  } else {
    /* Circuit already exists, so update its status and path */
    item->update(circuit);

    /* If the circuit is closed or dead, schedule it for removal */
    Circuit::Status status = circuit.status();
    if (status == Circuit::Closed) {
      scheduleCircuitRemoval(item, CLOSED_CIRCUIT_REMOVE_DELAY);
    } else if (status == Circuit::Failed) {
      scheduleCircuitRemoval(item, FAILED_CIRCUIT_REMOVE_DELAY);
    }
  }
}

/** Adds a stream to the list. If the stream already exists in the list, the
 * status and path will be updated. */
void
CircuitListWidget::addStream(Stream stream)
{
  /* Check to see if the stream already exists in the tree */
  StreamItem *item = findStreamItem(stream.id());

  if (!item) {
    CircuitItem *circuit = findCircuitItem(stream.circuitId());
    /* New stream, so try to find its circuit and add it */
    if (circuit) {
      circuit->addStream(new StreamItem(stream));
      expandItem(circuit);
    }
  } else {
    /* Stream already exists, so just update its status */
    item->update(stream);

    /* If the stream is closed or dead, schedule it for removal */
    Stream::Status status = stream.status();
    if (status == Stream::Closed || status == Stream::Detached) {
      scheduleStreamRemoval(item, CLOSED_STREAM_REMOVE_DELAY);
    } else if (status == Stream::Failed) {
      scheduleStreamRemoval(item, FAILED_STREAM_REMOVE_DELAY);
    }
  }
}

/** Schedules the given circuit to be removed after the specified timeout. */
void
CircuitListWidget::scheduleCircuitRemoval(CircuitItem *circuit, int delay)
{
  _circuitRemovalList << circuit;
  QTimer::singleShot(delay, this, SLOT(removeCircuit()));
}

/** Schedules the given stream to be removed after the specified timeout. */
void
CircuitListWidget::scheduleStreamRemoval(StreamItem *stream, int delay)
{
  _streamRemovalList << stream;
  QTimer::singleShot(delay, this, SLOT(removeStream()));
}

/** Removes the first circuit scheduled to be removed. */
void
CircuitListWidget::removeCircuit()
{
  if (!_circuitRemovalList.isEmpty()) {
    CircuitItem *circuit = _circuitRemovalList.takeFirst();
    removeCircuit(circuit);
  }
}

/** Removes the given circuit item and all streams on that circuit. */
void
CircuitListWidget::removeCircuit(CircuitItem *circuit)
{
  if (circuit) {
    /* Remove all streams (if any) on this circuit. */
    QList<QTreeWidgetItem *> streams = circuit->takeChildren();
    foreach (QTreeWidgetItem *stream, streams) {
      delete stream;
    }
    /* Remove the circuit item itself */
    delete takeTopLevelItem(indexOfTopLevelItem(circuit));
  }
}

/** Removes the first stream scheduled to be removed. */
void
CircuitListWidget::removeStream()
{
  if (!_streamRemovalList.isEmpty()) {
    StreamItem *stream = _streamRemovalList.takeFirst();
    removeStream(stream);
  }
}

/** Removes the given stream item. */
void
CircuitListWidget::removeStream(StreamItem *stream)
{
  if (stream) {
    CircuitItem *circuit = (CircuitItem *)stream->parent();
    if (circuit) {
      delete circuit->takeChild(circuit->indexOfChild(stream));
    } else {
      delete stream;
    }
  }
}

/** Clears all circuits and streams from the list. */
void
CircuitListWidget::clear()
{
  QTreeWidget::clear();
  _circuitRemovalList.clear();
  _streamRemovalList.clear();
}

/** Finds the circuit with the given ID and returns a pointer to that
 * circuit's item in the list. */
CircuitItem*
CircuitListWidget::findCircuitItem(quint64 circid)
{
  int numCircs = topLevelItemCount();
  for (int i = 0; i < numCircs; i++) {
    CircuitItem *circuit = (CircuitItem *)topLevelItem(i);
    if (circid == circuit->id()) {
      return circuit;
    }
  }
  return 0;
}

/** Finds the stream with the given ID and returns a pointer to that stream's
 * item in the list. */
StreamItem*
CircuitListWidget::findStreamItem(quint64 streamid)
{
  int numCircs = topLevelItemCount();
  int numStreams;
  
  for (int i = 0; i < numCircs; i++) {
    CircuitItem *circuit = (CircuitItem *)topLevelItem(i);
    numStreams = circuit->childCount();
  
    for (int j = 0; j < numStreams; j++) {
      StreamItem *stream = (StreamItem *)circuit->child(j);
      if (streamid == stream->id()) {
        return stream;
      }
    }
  }
  return 0;
}
+48 −0
Changes for src/gui/network/circuitlistwidget.h: 48 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -28,13 +28,61 @@
#define _CIRCUITLISTWIDGET_H

#include <QTreeWidget>
#include <QList>

#include "circuititem.h"
#include "streamitem.h"


class CircuitListWidget : public QTreeWidget
{
  Q_OBJECT
  
public:
  /** Circuit list columns. */
  enum Columns {
    ConnectionColumn = 0, /**< Column for either the circuit or stream */
    StatusColumn = 1      /**< Status of the connection. */
  };
  
  /** Default constructor */
  CircuitListWidget(QWidget *parent = 0);

  /** Adds a circuit to the list. If the circuit already exists in the list,
   * the status and path will be updated. */
  void addCircuit(Circuit circuit);
  /** Adds a stream to the list. If the stream already exists in the list, the
   * status and path will be updated. */
  void addStream(Stream stream);
  /** Removes the given circuit item and all streams on that circuit. */
  void removeCircuit(CircuitItem *circuit);
  /** Removes the given stream item. */
  void removeStream(StreamItem *stream);

public slots:
  /** Clears all circuits and streams from the list. */
  void clear();

private slots:
  /** Removes the circuit with the given ID and any streams on this circuit.*/
  void removeCircuit(); 
  /** Removes the stream with the given ID. */
  void removeStream();

private:
  /** Finds the circuit with the given ID. */
  CircuitItem* findCircuitItem(quint64 circid);
  /** Finds the stream with the given ID. */
  StreamItem* findStreamItem(quint64 streamid);
  /** Schedules the given circuit item to be removed after the given timeout. */
  void scheduleCircuitRemoval(CircuitItem *circuit, int delay);
  /** Schedules a stream to be removed after the given timeout. */
  void scheduleStreamRemoval(StreamItem *stream, int delay);

  /** List of circuit items to be removed. */
  QList<CircuitItem *> _circuitRemovalList;
  /** List of stream items to be removed. */
  QList<StreamItem *> _streamRemovalList;
};

#endif
+36 −7
Changes for src/gui/network/netviewer.cpp: 36 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#define IMG_ZOOMIN  ":/images/22x22/zoom-in.png"
#define IMG_ZOOMOUT ":/images/22x22/zoom-out.png"


/** Constructor. Loads settings from VidaliaSettings.
 * \param parent The parent widget of this NetViewer object.\
 */
@@ -47,6 +48,8 @@ NetViewer::NetViewer(QWidget *parent)
  /* Get the TorControl object */
  _torControl = Vidalia::torControl();
  _torControl->setEvent(TorEvents::NewDescriptor, this, true);
  _torControl->setEvent(TorEvents::CircuitStatus, this, true);
  _torControl->setEvent(TorEvents::StreamStatus,  this, true);
  
  /* Create the MapFrame and add it to the dialog */
  _map = new MapFrame;
@@ -81,15 +84,15 @@ NetViewer::NetViewer(QWidget *parent)
  /* Connect the necessary slots and signals */
  connect(ui.actionHelp, SIGNAL(triggered()), this, SLOT(help()));
  connect(ui.actionNewNym, SIGNAL(triggered()), this, SLOT(newNym()));
  connect(_torControl, SIGNAL(connected(bool)), 
          ui.actionNewNym, SLOT(setEnabled(bool)));
  connect(ui.actionRefresh, SIGNAL(triggered()), 
          this, SLOT(loadRouters()));
  connect(_torControl, SIGNAL(connected(bool)),
          ui.actionRefresh, SLOT(setEnabled(bool)));
  connect(ui.actionRefresh, SIGNAL(triggered()), this, SLOT(loadRouters()));
  connect(ui.treeRouterList, SIGNAL(routerSelected(RouterDescriptor)),
          ui.textRouterInfo, SLOT(display(RouterDescriptor)));
  
  connect(_torControl, SIGNAL(connected(bool)), ui.actionRefresh, SLOT(setEnabled(bool)));
  connect(_torControl, SIGNAL(connected(bool)), ui.actionNewNym, SLOT(setEnabled(bool)));
  connect(_torControl, SIGNAL(connected()), this, SLOT(loadRouters()));
  connect(_torControl, SIGNAL(connected()), this, SLOT(loadConnections())); 
  connect(_torControl, SIGNAL(disconnected()), ui.treeCircuitList, SLOT(clear()));
}

/** Creates and adds an action to the specified action group */
@@ -114,9 +117,19 @@ NetViewer::setMapAction(QAction *action)
void
NetViewer::customEvent(QEvent *event)
{
  if (event->type() == CustomEventType::NewDescriptorEvent) {
  int type = event->type();
  if (type == CustomEventType::NewDescriptorEvent) {
    /* New router descriptor, so load it and add it to the list */
    NewDescriptorEvent *nde = (NewDescriptorEvent *)event;
    loadNewDescriptors(nde->descriptorIDs());
  } else if (type == CustomEventType::CircuitEvent) {
    /* New or updated circuit information */
    CircuitEvent *ce = (CircuitEvent *)event;
    ui.treeCircuitList->addCircuit(ce->circuit());
  } else if (type == CustomEventType::StreamEvent) {
    /* New or updated stream information */
    StreamEvent *se = (StreamEvent *)event;
    ui.treeCircuitList->addStream(se->stream());
  }
}

@@ -143,6 +156,22 @@ NetViewer::loadRouters()
  ui.actionRefresh->setEnabled(true);
}

/** Loads a list of all current circuits and streams. */
void
NetViewer::loadConnections()
{
  /* Load all circuits */
  QList<Circuit> circuits = _torControl->getCircuits();
  foreach (Circuit circuit, circuits) {
    ui.treeCircuitList->addCircuit(circuit);
  }
  /* Now load all streams */
  QList<Stream> streams = _torControl->getStreams();
  foreach (Stream stream, streams) {
    ui.treeCircuitList->addStream(stream);
  }
}

/** Overloads the default show() slot. */
void
NetViewer::show()
Loading