routerlistwidget.cpp

Go to the documentation of this file.
00001 /****************************************************************
00002  *  Vidalia is distributed under the following license:
00003  *
00004  *  Copyright (C) 2006,  Matt Edman, Justin Hipple
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00019  *  Boston, MA  02110-1301, USA.
00020  ****************************************************************/
00021 
00022 /** 
00023  * \file routerlistwidget.cpp
00024  * \version $Id: routerlistwidget.cpp 1241 2006-09-26 00:42:21Z edmanm $
00025  * \brief Displays a list of Tor servers and their status
00026  */
00027 
00028 #include <QHeaderView>
00029 #include <vidalia.h>
00030 
00031 #include "routerlistwidget.h"
00032 
00033 
00034 RouterListWidget::RouterListWidget(QWidget *parent)
00035 : QTreeWidget(parent)
00036 {
00037   /* Create and initialize columns */
00038   setHeaderLabels(QStringList() << tr("Status") << tr("Server"));
00039 
00040   /* Set the column size and sort order for the router list. We call
00041    * sortByColumn() twice so that the highest bandwidth servers are at the top
00042    * instead of the bottom. */
00043   sortByColumn(StatusColumn);
00044   sortByColumn(StatusColumn);
00045 
00046   /* Find out when the selected item has changed. */
00047   connect(this, SIGNAL(itemSelectionChanged()), 
00048           this, SLOT(onSelectionChanged()));
00049 }
00050 
00051 /** Deselects all currently selected routers. */
00052 void
00053 RouterListWidget::deselectAll()
00054 {
00055   QList<QTreeWidgetItem *> selected = selectedItems();
00056   foreach (QTreeWidgetItem *item, selected) {
00057     setItemSelected(item, false);
00058   }
00059 }
00060 
00061 /** Clear the list of router items. */
00062 void
00063 RouterListWidget::clearRouters()
00064 {
00065   _idmap.clear();
00066   QTreeWidget::clear();
00067 }
00068 
00069 /** Inserts a new router list item into the list, in its proper sorted place
00070  * according to the current sort column. */
00071 void
00072 RouterListWidget::insertSorted(RouterListItem *item)
00073 {
00074   Qt::SortOrder order = header()->sortIndicatorOrder();
00075   int left  = 0;
00076   int right = topLevelItemCount();
00077   int mid;
00078 
00079   while (left < right) {
00080     mid = (left + right)/2;
00081     if (order == Qt::AscendingOrder) {
00082       if (*((RouterListItem *)topLevelItem(mid)) < *item) {
00083         left = mid + 1;
00084       } else {
00085         right = mid;
00086       }
00087     } else {
00088       if (*item < *((RouterListItem *)topLevelItem(mid))) {
00089         left = mid+1;
00090       } else {
00091         right = mid;
00092       }
00093     }
00094   }
00095  
00096   if (left == topLevelItemCount()) {
00097     addTopLevelItem(item);
00098   } else {
00099     insertTopLevelItem(left, item);
00100   }
00101 }
00102 
00103 /** Called when the user selects a router from the list. This will search the
00104  * list for a router whose names starts with the key pressed. */
00105 void
00106 RouterListWidget::keyPressEvent(QKeyEvent *event)
00107 {
00108   int index;
00109   
00110   QString key = event->text();
00111   if (!key.isEmpty() && key.at(0).isLetterOrNumber()) {
00112     /* A text key was pressed, so search for routers that begin with that key. */
00113     QList<QTreeWidgetItem *> list = findItems(QString("^[%1%2].*$")
00114                                                   .arg(key.toUpper())
00115                                                   .arg(key.toLower()),
00116                                                Qt::MatchRegExp|Qt::MatchWrap,
00117                                                NameColumn);
00118     if (list.size() > 0) {
00119       QList<QTreeWidgetItem *> s = selectedItems();
00120       
00121       /* A match was found, so deselect any previously selected routers,
00122        * select the new match, and make sure it's visible. If there was
00123        * already a router selected that started with the search key, go to the
00124        * next match in the list. */
00125       deselectAll();
00126       index = (!s.size() ? 0 : (list.indexOf(s.at(0)) + 1) % list.size());
00127 
00128       /* Select the item and scroll to it */
00129       setItemSelected(list.at(index), true);
00130       scrollToItem(list.at(index));
00131     }
00132     event->accept();
00133   } else {
00134     /* It was something we don't understand, so hand it to the parent class */
00135     QTreeWidget::keyPressEvent(event);
00136   }
00137 }
00138 
00139 /** Finds the list item whose key ID matches <b>id</b>. Returns 0 if not 
00140  * found. */
00141 RouterListItem*
00142 RouterListWidget::findRouterById(QString id)
00143 {
00144   if (_idmap.contains(id)) {
00145     return _idmap.value(id);
00146   }
00147   return 0;
00148 }
00149 
00150 /** Finds the list item whose router nickname matches <b>name</b>. If more 
00151  * than one router exists with given name, the first match will be returned. 
00152  * Returns 0 if not found. */
00153 RouterListItem*
00154 RouterListWidget::findRouterByName(QString name)
00155 {
00156   QList<QTreeWidgetItem *> list = findItems(name,
00157                                             Qt::MatchExactly,
00158                                             NameColumn);
00159   /* It's possible that more than one router could have the same name, but
00160    * without a fingerprint on which to match, we just have to pick one. We'll
00161    * return the first match. */
00162   if (list.size() > 0) {
00163     return (RouterListItem *)list.at(0);
00164   }
00165   return 0;
00166 }
00167 
00168 /** Adds a router descriptor to the list. */
00169 void
00170 RouterListWidget::addRouter(RouterDescriptor rd)
00171 {
00172   QString id = rd.id();
00173   if (!id.isEmpty()) {
00174     RouterListItem *item = findRouterById(id);
00175     if (item) {
00176       /* This is an updated descriptor, so remove the old item and we'll 
00177        * add a new, updated item. */
00178       delete takeTopLevelItem(indexOfTopLevelItem(item));
00179       _idmap.remove(id);
00180     }
00181 
00182     /* Add the router item to the list and store its descriptor. */
00183     item = new RouterListItem(this, rd);
00184     insertSorted(item);
00185     _idmap.insert(id, item);
00186 
00187     /* Set our status tip to the number of servers in the list */
00188     setStatusTip(tr("%1 servers total").arg(topLevelItemCount()));
00189   }
00190 }
00191 
00192 /** Called when the selected items have changed. This emits the 
00193  * routerSelected() signal with the descriptor for the selected router.
00194  */
00195 void
00196 RouterListWidget::onSelectionChanged()
00197 {
00198   RouterDescriptor rd;
00199   QList<QTreeWidgetItem *> items = selectedItems();
00200 
00201   if (items.count() > 0) {
00202       rd = ((RouterListItem *)items[0])->descriptor();
00203   }
00204     emit routerSelected(rd);
00205 }
00206 

Generated on Mon Oct 23 20:08:16 2006 for Vidalia by  doxygen 1.5.0