Commit 3246946f authored by Matt Edman's avatar Matt Edman
Browse files

Make sure we don't try to remove a circuit list item twice, and show

descriptor summaries for each router in the path when the path is selected.


svn:r879
parent 34831300
Loading
Loading
Loading
Loading
+39 −5
Changes for src/gui/network/circuitlistwidget.cpp: 39 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -38,6 +38,9 @@
CircuitListWidget::CircuitListWidget(QWidget *parent)
: QTreeWidget(parent)
{
  /* Find out when a circuit has been selected */
  connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
          this, SLOT(onSelectionChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
}

/** Adds a circuit to the list. If the circuit already exists in the list, the
@@ -86,7 +89,7 @@ CircuitListWidget::addStream(Stream stream)

    /* If the stream is closed or dead, schedule it for removal */
    Stream::Status status = stream.status();
    if (status == Stream::Closed || status == Stream::Detached) {
    if (status == Stream::Closed) {
      scheduleStreamRemoval(item, CLOSED_STREAM_REMOVE_DELAY);
    } else if (status == Stream::Failed) {
      scheduleStreamRemoval(item, FAILED_STREAM_REMOVE_DELAY);
@@ -98,17 +101,21 @@ CircuitListWidget::addStream(Stream stream)
void
CircuitListWidget::scheduleCircuitRemoval(CircuitItem *circuit, int delay)
{
  if (!_circuitRemovalList.contains(circuit)) {
    _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)
{
  if (!_streamRemovalList.contains(stream)) {
    _streamRemovalList << stream;
    QTimer::singleShot(delay, this, SLOT(removeStream()));
  } 
}

/** Removes the first circuit scheduled to be removed. */
void
@@ -126,9 +133,18 @@ 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;
    QList<StreamItem *> streams = circuit->streams();
    foreach (StreamItem *stream, streams) {
      /* Check if this stream was scheduled for removal already */
      if (_streamRemovalList.contains(stream)) {
        /* If this stream was already scheduled for removal, replace its pointer
         * with 0, so it doesn't get removed twice. */
        int index = _streamRemovalList.indexOf(stream);
        _streamRemovalList.replace(index, (StreamItem *)0);
      }
      
      /* Remove the stream item from the circuit */
      circuit->removeStream(stream);
    }
    /* Remove the circuit item itself */
    delete takeTopLevelItem(indexOfTopLevelItem(circuit));
@@ -150,10 +166,13 @@ void
CircuitListWidget::removeStream(StreamItem *stream)
{
  if (stream) {
    /* Try to get the stream's parent (a circuit item) */ 
    CircuitItem *circuit = (CircuitItem *)stream->parent();
    if (circuit) {
      delete circuit->takeChild(circuit->indexOfChild(stream));
      /* Remove the stream from the circuit and delete the item */
      circuit->removeStream(stream);
    } else {
      /* It isn't on a circuit, so just delete the stream */
      delete stream;
    }
  }
@@ -205,3 +224,18 @@ CircuitListWidget::findStreamItem(quint64 streamid)
  return 0;
}

/** Called when the current item selection has changed. */
void
CircuitListWidget::onSelectionChanged(QTreeWidgetItem *cur, 
                                      QTreeWidgetItem *prev)
{
  Q_UNUSED(prev);

  if (cur && !cur->parent()) {
    Circuit circuit = ((CircuitItem *)cur)->circuit();
    if (circuit.length() > 0) {
      emit circuitSelected(circuit);
    }
  }
}
+6 −0
Changes for src/gui/network/circuitlistwidget.h: 6 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -59,6 +59,10 @@ public:
  /** Removes the given stream item. */
  void removeStream(StreamItem *stream);

signals:
  /** Emitted when a circuit item is selected. */
  void circuitSelected(Circuit circuit);

public slots:
  /** Clears all circuits and streams from the list. */
  void clear();
@@ -68,6 +72,8 @@ private slots:
  void removeCircuit(); 
  /** Removes the stream with the given ID. */
  void removeStream();
  /** Called when the current item selectio has changed. */
  void onSelectionChanged(QTreeWidgetItem *cur, QTreeWidgetItem *prev);

private:
  /** Finds the circuit with the given ID. */
+27 −4
Changes for src/gui/network/netviewer.cpp: 27 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -36,6 +36,10 @@
#define IMG_ZOOMIN  ":/images/22x22/zoom-in.png"
#define IMG_ZOOMOUT ":/images/22x22/zoom-out.png"

/** Maximum time to proceess other events while loading the long list of
 * router descriptors. */
#define MAX_EVENTS_TIMEOUT  25


/** Constructor. Loads settings from VidaliaSettings.
 * \param parent The parent widget of this NetViewer object.\
@@ -88,8 +92,10 @@ NetViewer::NetViewer(QWidget *parent)
  connect(ui.actionHelp, SIGNAL(triggered()), this, SLOT(help()));
  connect(ui.actionNewNym, SIGNAL(triggered()), this, SLOT(newNym()));
  connect(ui.actionRefresh, SIGNAL(triggered()), this, SLOT(loadRouters()));
  connect(ui.treeRouterList, SIGNAL(routerSelected(RouterDescriptor)),
          ui.textRouterInfo, SLOT(display(RouterDescriptor)));
  connect(ui.treeRouterList, SIGNAL(routerSelected(QList<RouterDescriptor>)),
          ui.textRouterInfo, SLOT(display(QList<RouterDescriptor>)));
  connect(ui.treeCircuitList, SIGNAL(circuitSelected(Circuit)),
          this, SLOT(circuitSelected(Circuit)));

  connect(_torControl, SIGNAL(connected(bool)), ui.actionRefresh, SLOT(setEnabled(bool)));
  connect(_torControl, SIGNAL(connected(bool)), ui.actionNewNym, SLOT(setEnabled(bool)));
@@ -143,7 +149,7 @@ NetViewer::loadRouters()
  idList = _torControl->getRouterIDList();
  foreach (QString id, idList) {
    ui.treeRouterList->addRouter(_torControl->getRouterDescriptor(id));
    Vidalia::processEvents();
    Vidalia::processEvents(QEventLoop::AllEvents, MAX_EVENTS_TIMEOUT);
  }

  /* Ok, they can refresh again. */
@@ -209,7 +215,24 @@ NetViewer::loadNewDescriptors(QStringList ids)
{
  foreach (QString id, ids) {
    ui.treeRouterList->addRouter(_torControl->getRouterDescriptor(id));
    Vidalia::processEvents();
    Vidalia::processEvents(QEventLoop::AllEvents, MAX_EVENTS_TIMEOUT);
  }
}

/** Called when the user selects a circuit from the circuit and streams
 * list. */
void
NetViewer::circuitSelected(Circuit circuit)
{
  /* Clear any selected items. */
  ui.treeRouterList->deselectAll();

  foreach (QString router, circuit.hops()) {
    /* Try to find and select each router in the path */
    RouterListItem *item = ui.treeRouterList->findRouterItem(router);
    if (item) {
      ui.treeRouterList->setItemSelected(item, true);
    }
  }
}
+2 −0
Changes for src/gui/network/netviewer.h: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ private slots:
  /** Called when the user selects the "New Nym" action on the toolbar. */
  void newNym();
  /** Called when the user selects a map action on the toolbar */
  /** Called when the user selects a circuit on the circuit list */
  void circuitSelected(Circuit circuit);
  
private:
  /** Loads a list of new descriptors from the list of IDs. */
+49 −9
Changes for src/gui/network/routerlistitem.cpp: 49 added lines, 9 removed lines.
Original line number Diff line number Diff line
@@ -27,30 +27,70 @@
#include "routerlistwidget.h"
#include "routerlistitem.h"

#define STATUS_COLUMN (RouterListWidget::StatusColumn)
#define NAME_COLUMN   (RouterListWidget::NameColumn)

#define IMG_NODE_OFFLINE    ":/images/icons/node-unresponsive.png"
#define IMG_NODE_SLEEPING   ":/images/icons/node-hibernating.png"
#define IMG_NODE_NO_BW      ":/images/icons/node-bw-none.png"
#define IMG_NODE_LOW_BW     ":/images/icons/node-bw-low.png"
#define IMG_NODE_MED_BW     ":/images/icons/node-bw-med.png"
#define IMG_NODE_HIGH_BW    ":/images/icons/node-bw-high.png"


/** Default constructor. */
RouterListItem::RouterListItem(RouterListWidget *list)
RouterListItem::RouterListItem(RouterListWidget *list, RouterDescriptor rd)
: QTreeWidgetItem()
{
  _list = list;
  update(rd);
}

void
RouterListItem::update(RouterDescriptor rd)
{
  QIcon statusIcon;
  _rd = rd;
  
  /* Determine the status value (used for sorting) and icon */
  if (_rd.offline()) {
    _statusValue = -1;
    statusIcon = QIcon(IMG_NODE_OFFLINE);
  } else if (_rd.hibernating()) {
    _statusValue = 0;
    statusIcon = QIcon(IMG_NODE_SLEEPING);
  } else {
    _statusValue = (qint64)_rd.observedBandwidth();
    if (_statusValue >= 400*1024) {
      statusIcon = QIcon(IMG_NODE_HIGH_BW);
    } else if (_statusValue >= 60*1024) {
      statusIcon = QIcon(IMG_NODE_MED_BW);
    } else if (_statusValue >= 20*1024) {
      statusIcon = QIcon(IMG_NODE_LOW_BW);
    } else {
      statusIcon = QIcon(IMG_NODE_NO_BW);
    }
  }
  
  /* Make the new information visible */
  setIcon(STATUS_COLUMN, statusIcon);
  setText(NAME_COLUMN, _rd.name());
}

/** Overload the comparison operator. */
bool
RouterListItem::operator<(const QTreeWidgetItem &other) const
{
  const RouterListItem *a = this;
  const RouterListItem *b = (RouterListItem *)&other;

  if (_list) {
    if (_list->sortColumn() == RouterListWidget::StatusColumn) {
      /* Numeric comparison based on status and/or bandwidth */
      return (this->data(RouterListWidget::StatusColumn,
                         Qt::UserRole).toLongLong() >
              other.data(RouterListWidget::StatusColumn,
                         Qt::UserRole).toLongLong());
      return (a->_statusValue > b->_statusValue);
    } else if (_list->sortColumn() == RouterListWidget::NameColumn) {
      /* Perform a case-insensitive comparison based on router name */
      return (this->data(RouterListWidget::NameColumn,
                         Qt::UserRole).toString() >
              other.data(RouterListWidget::NameColumn,
                         Qt::UserRole).toString());
      return (a->name().toLower() > b->name().toLower());
    }
  }
  return QTreeWidgetItem::operator<(other);
Loading