Vidalia  0.2.15
RouterListItem.cpp
Go to the documentation of this file.
00001 /*
00002 **  This file is part of Vidalia, and is subject to the license terms in the
00003 **  LICENSE file, found in the top level directory of this distribution. If you
00004 **  did not receive the LICENSE file with this file, you may obtain it from the
00005 **  Vidalia source package distributed by the Vidalia Project at
00006 **  http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 
00007 **  including this file, may be copied, modified, propagated, or distributed 
00008 **  except according to the terms described in the LICENSE file.
00009 */
00010 
00011 /*
00012 ** \file RouterListItem.cpp
00013 ** \brief Item representing a single router and status in a RouterListWidget
00014 */
00015 
00016 #include "RouterListItem.h"
00017 #include "RouterListWidget.h"
00018 
00019 #include <QHeaderView>
00020 
00021 #define STATUS_COLUMN   (RouterListWidget::StatusColumn)
00022 #define COUNTRY_COLUMN  (RouterListWidget::CountryColumn)
00023 #define NAME_COLUMN     (RouterListWidget::NameColumn)
00024 
00025 #define IMG_NODE_OFFLINE    ":/images/icons/node-unresponsive.png"
00026 #define IMG_NODE_SLEEPING   ":/images/icons/node-hibernating.png"
00027 #define IMG_NODE_NO_BW      ":/images/icons/node-bw-none.png"
00028 #define IMG_NODE_LOW_BW     ":/images/icons/node-bw-low.png"
00029 #define IMG_NODE_MED_BW     ":/images/icons/node-bw-med.png"
00030 #define IMG_NODE_HIGH_BW    ":/images/icons/node-bw-high.png"
00031 #define IMG_FLAG_UNKNOWN    ":/images/flags/unknown.png"
00032 
00033 
00034 /** Default constructor. */
00035 RouterListItem::RouterListItem(RouterListWidget *list, RouterDescriptor rd)
00036   : QTreeWidgetItem()
00037 {
00038   _list = list;
00039   _rd   = 0;
00040   _countryCode = "~"; /* Force items with no country to the bottom */
00041   setIcon(COUNTRY_COLUMN, QIcon(IMG_FLAG_UNKNOWN));
00042   update(rd);
00043 }
00044 
00045 /** Destructor. */
00046 RouterListItem::~RouterListItem()
00047 {
00048   if (_rd)
00049     delete _rd;
00050 }
00051 
00052 /** Updates the router descriptor for this item. */
00053 void
00054 RouterListItem::update(const RouterDescriptor &rd)
00055 {
00056   QIcon statusIcon;
00057   if (_rd) {
00058     delete _rd;
00059   }
00060   _rd = new RouterDescriptor(rd);
00061   
00062   /* Determine the status value (used for sorting) and icon */
00063   if (_rd->offline()) {
00064     _statusValue = -1;
00065     statusIcon = QIcon(IMG_NODE_OFFLINE);
00066     setToolTip(STATUS_COLUMN, tr("Offline"));
00067   } else if (_rd->hibernating()) {
00068     _statusValue = 0;
00069     statusIcon = QIcon(IMG_NODE_SLEEPING);
00070     setToolTip(STATUS_COLUMN, tr("Hibernating"));
00071   } else {
00072     _statusValue = (qint64)qMin(_rd->observedBandwidth(), 
00073                                 qMin(_rd->averageBandwidth(),
00074                                      _rd->burstBandwidth()));
00075     if (_statusValue >= 400*1024) {
00076       statusIcon = QIcon(IMG_NODE_HIGH_BW);
00077     } else if (_statusValue >= 60*1024) {
00078       statusIcon = QIcon(IMG_NODE_MED_BW);
00079     } else if (_statusValue >= 20*1024) {
00080       statusIcon = QIcon(IMG_NODE_LOW_BW);
00081     } else {
00082       statusIcon = QIcon(IMG_NODE_NO_BW);
00083     }
00084     setToolTip(STATUS_COLUMN, tr("%1 KB/s").arg(_statusValue/1024));
00085   }
00086   
00087   /* Make the new information visible */
00088   setIcon(STATUS_COLUMN, statusIcon);
00089   setText(NAME_COLUMN, _rd->name());
00090   setToolTip(NAME_COLUMN, QString(_rd->name() + "\r\n" + _rd->platform()));
00091 }
00092 
00093 /** Sets the location information for this item's router descriptor. */
00094 void
00095 RouterListItem::setLocation(const GeoIpRecord &geoip)
00096 {
00097   QPixmap flag(":/images/flags/" + geoip.countryCode().toLower() + ".png");
00098   if (!flag.isNull()) {
00099     setIcon(COUNTRY_COLUMN, QIcon(flag));
00100   }
00101   setToolTip(COUNTRY_COLUMN, geoip.toString());
00102 
00103   if (_rd)
00104     _rd->setLocation(geoip.toString());
00105   _countryCode = geoip.countryCode();
00106 }
00107 
00108 /** Overload the comparison operator. */
00109 bool
00110 RouterListItem::operator<(const QTreeWidgetItem &other) const
00111 {
00112   const RouterListItem *a = this;
00113   const RouterListItem *b = (RouterListItem *)&other;
00114  
00115   if (_list) {
00116     Qt::SortOrder order = _list->header()->sortIndicatorOrder();
00117     switch (_list->sortColumn()) {
00118       case RouterListWidget::StatusColumn:
00119         /* Numeric comparison based on status and/or bandwidth */
00120         if (a->_statusValue == b->_statusValue) {
00121           if (order == Qt::AscendingOrder)
00122             return (a->name().toLower() > b->name().toLower());
00123           else
00124             return (a->name().toLower() < b->name().toLower());
00125         }
00126         return (a->_statusValue < b->_statusValue);
00127       case RouterListWidget::CountryColumn:
00128         /* Compare based on country code */
00129         if (a->_countryCode == b->_countryCode) {
00130           if (order == Qt::AscendingOrder)
00131             return (a->_statusValue > b->_statusValue);
00132           else
00133             return (a->_statusValue < b->_statusValue);
00134         }
00135         return (a->_countryCode < b->_countryCode);
00136       case RouterListWidget::NameColumn:
00137         /* Case-insensitive comparison based on router name */
00138         if (a->name().toLower() == b->name().toLower()) {
00139           if (order == Qt::AscendingOrder)
00140             return (a->_statusValue > b->_statusValue);
00141           else
00142             return (a->_statusValue < b->_statusValue);
00143         }
00144         return (a->name().toLower() < b->name().toLower());
00145       default:
00146         break;
00147     }
00148   }
00149   return QTreeWidgetItem::operator<(other);
00150 }
00151