circuitlistwidget.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <QPoint>
00018 #include <QTimer>
00019 #include <vidalia.h>
00020
00021 #include "circuitlistwidget.h"
00022
00023 #define IMG_CLOSE ":/images/22x22/edit-delete.png"
00024 #define IMG_ZOOM ":/images/22x22/page-zoom.png"
00025
00026 #define CLOSED_CIRCUIT_REMOVE_DELAY 3000
00027 #define FAILED_CIRCUIT_REMOVE_DELAY 5000
00028 #define CLOSED_STREAM_REMOVE_DELAY 3000
00029 #define FAILED_STREAM_REMOVE_DELAY 4000
00030
00031
00032
00033 CircuitListWidget::CircuitListWidget(QWidget *parent)
00034 : QTreeWidget(parent)
00035 {
00036
00037 setHeaderLabels(QStringList() << tr("Connection") << tr("Status"));
00038
00039
00040 connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
00041 this, SLOT(onSelectionChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
00042 connect(this, SIGNAL(customContextMenuRequested(QPoint)),
00043 this, SLOT(customContextMenuRequested(QPoint)));
00044
00045
00046
00047 vApp->createShortcut(QKeySequence::Delete, this, this,
00048 SLOT(closeSelectedConnections()));
00049 }
00050
00051
00052
00053
00054 void
00055 CircuitListWidget::customContextMenuRequested(const QPoint &pos)
00056 {
00057 QMenu menu(this);
00058
00059
00060 QTreeWidgetItem *item = itemAt(pos);
00061 if (!item)
00062 return;
00063
00064 if (!item->parent()) {
00065
00066 CircuitItem *circuitItem = dynamic_cast<CircuitItem *>(item);
00067 if (!circuitItem)
00068 return;
00069
00070
00071 QAction *zoomAct = new QAction(QIcon(IMG_ZOOM),
00072 tr("Zoom to Circuit"), this);
00073 QAction *closeAct = new QAction(QIcon(IMG_CLOSE),
00074 tr("Close Circuit (Del)"), this);
00075 zoomAct->setEnabled(circuitItem->circuit().status() == Circuit::Built);
00076 menu.addAction(zoomAct);
00077 menu.addSeparator();
00078 menu.addAction(closeAct);
00079
00080
00081
00082 QAction* action = menu.exec(mapToGlobal(pos));
00083 if (action == closeAct)
00084 emit closeCircuit(circuitItem->id());
00085 else if (action == zoomAct)
00086 emit zoomToCircuit(circuitItem->id());
00087 } else {
00088
00089 StreamItem *streamItem = dynamic_cast<StreamItem *>(item);
00090 if (!streamItem)
00091 return;
00092
00093
00094 QAction *closeAct = new QAction(QIcon(IMG_CLOSE),
00095 tr("Close Stream (Del)"), this);
00096 menu.addAction(closeAct);
00097
00098
00099
00100 QAction* action = menu.exec(mapToGlobal(pos));
00101 if (action == closeAct)
00102 emit closeStream(streamItem->id());
00103 }
00104 }
00105
00106
00107 void
00108 CircuitListWidget::closeSelectedConnections()
00109 {
00110 QList<QTreeWidgetItem *> items = selectedItems();
00111 foreach (QTreeWidgetItem *item, items) {
00112 if (!item->parent()) {
00113 CircuitItem *circuitItem = dynamic_cast<CircuitItem *>(item);
00114 if (circuitItem)
00115 emit closeCircuit(circuitItem->id());
00116 } else {
00117 StreamItem *streamItem = dynamic_cast<StreamItem *>(item);
00118 if (streamItem)
00119 emit closeStream(streamItem->id());
00120 }
00121 }
00122 }
00123
00124
00125
00126 void
00127 CircuitListWidget::addCircuit(const Circuit &circuit)
00128 {
00129
00130 CircuitItem *item = findCircuitItem(circuit.id());
00131
00132 if (!item) {
00133
00134 item = new CircuitItem(circuit);
00135 addTopLevelItem(item);
00136 } else {
00137
00138 item->update(circuit);
00139 }
00140
00141
00142 Circuit::Status status = circuit.status();
00143 if (status == Circuit::Closed) {
00144 scheduleCircuitRemoval(item, CLOSED_CIRCUIT_REMOVE_DELAY);
00145 } else if (status == Circuit::Failed) {
00146 scheduleCircuitRemoval(item, FAILED_CIRCUIT_REMOVE_DELAY);
00147 }
00148 }
00149
00150
00151
00152 void
00153 CircuitListWidget::addStream(const Stream &stream)
00154 {
00155
00156 StreamItem *item = findStreamItem(stream.id());
00157
00158 if (!item) {
00159 CircuitItem *circuit = findCircuitItem(stream.circuitId());
00160
00161 if (circuit) {
00162 circuit->addStream(new StreamItem(stream));
00163 expandItem(circuit);
00164 }
00165 } else {
00166
00167 item->update(stream);
00168
00169
00170 Stream::Status status = stream.status();
00171 if (status == Stream::Closed) {
00172 scheduleStreamRemoval(item, CLOSED_STREAM_REMOVE_DELAY);
00173 } else if (status == Stream::Failed) {
00174 scheduleStreamRemoval(item, FAILED_STREAM_REMOVE_DELAY);
00175 }
00176 }
00177 }
00178
00179
00180 void
00181 CircuitListWidget::scheduleCircuitRemoval(CircuitItem *circuit, int delay)
00182 {
00183 if (!_circuitRemovalList.contains(circuit)) {
00184 _circuitRemovalList << circuit;
00185 QTimer::singleShot(delay, this, SLOT(removeCircuit()));
00186 }
00187 }
00188
00189
00190 void
00191 CircuitListWidget::scheduleStreamRemoval(StreamItem *stream, int delay)
00192 {
00193 if (!_streamRemovalList.contains(stream)) {
00194 _streamRemovalList << stream;
00195 QTimer::singleShot(delay, this, SLOT(removeStream()));
00196 }
00197 }
00198
00199
00200 void
00201 CircuitListWidget::removeCircuit()
00202 {
00203 if (!_circuitRemovalList.isEmpty()) {
00204 CircuitItem *circuitItem = _circuitRemovalList.takeFirst();
00205 Circuit circuit = circuitItem->circuit();
00206 removeCircuit(circuitItem);
00207 emit circuitRemoved(circuit.id());
00208 }
00209 }
00210
00211
00212 void
00213 CircuitListWidget::removeCircuit(CircuitItem *circuit)
00214 {
00215 if (circuit) {
00216
00217 QList<StreamItem *> streams = circuit->streams();
00218 foreach (StreamItem *stream, streams) {
00219
00220 if (_streamRemovalList.contains(stream)) {
00221
00222
00223 int index = _streamRemovalList.indexOf(stream);
00224 _streamRemovalList.replace(index, (StreamItem *)0);
00225 }
00226
00227
00228 circuit->removeStream(stream);
00229 }
00230
00231 delete takeTopLevelItem(indexOfTopLevelItem(circuit));
00232 }
00233 }
00234
00235
00236 void
00237 CircuitListWidget::removeStream()
00238 {
00239 if (!_streamRemovalList.isEmpty()) {
00240 StreamItem *stream = _streamRemovalList.takeFirst();
00241 removeStream(stream);
00242 }
00243 }
00244
00245
00246 void
00247 CircuitListWidget::removeStream(StreamItem *stream)
00248 {
00249 if (stream) {
00250
00251 CircuitItem *circuit = (CircuitItem *)stream->parent();
00252 if (circuit) {
00253
00254 circuit->removeStream(stream);
00255 } else {
00256
00257 delete stream;
00258 }
00259 }
00260 }
00261
00262
00263 void
00264 CircuitListWidget::clearCircuits()
00265 {
00266 QTreeWidget::clear();
00267 _circuitRemovalList.clear();
00268 _streamRemovalList.clear();
00269 }
00270
00271
00272
00273 CircuitItem*
00274 CircuitListWidget::findCircuitItem(const CircuitId &circid)
00275 {
00276 int numCircs = topLevelItemCount();
00277 for (int i = 0; i < numCircs; i++) {
00278 CircuitItem *circuit = (CircuitItem *)topLevelItem(i);
00279 if (circid == circuit->id()) {
00280 return circuit;
00281 }
00282 }
00283 return 0;
00284 }
00285
00286
00287
00288 StreamItem*
00289 CircuitListWidget::findStreamItem(const StreamId &streamid)
00290 {
00291 int numCircs = topLevelItemCount();
00292 int numStreams;
00293
00294 for (int i = 0; i < numCircs; i++) {
00295 CircuitItem *circuit = (CircuitItem *)topLevelItem(i);
00296 numStreams = circuit->childCount();
00297
00298 for (int j = 0; j < numStreams; j++) {
00299 StreamItem *stream = (StreamItem *)circuit->child(j);
00300 if (streamid == stream->id()) {
00301 return stream;
00302 }
00303 }
00304 }
00305 return 0;
00306 }
00307
00308
00309 void
00310 CircuitListWidget::onSelectionChanged(QTreeWidgetItem *cur,
00311 QTreeWidgetItem *prev)
00312 {
00313 Q_UNUSED(prev);
00314
00315 if (cur) {
00316 Circuit circuit;
00317
00318 if (!cur->parent()) {
00319
00320 circuit = ((CircuitItem *)cur)->circuit();
00321 } else {
00322
00323 CircuitItem *circItem = (CircuitItem *)cur->parent();
00324 circuit = circItem->circuit();
00325 }
00326
00327
00328 emit circuitSelected(circuit);
00329 }
00330 }
00331
00332
00333 CircuitList
00334 CircuitListWidget::circuits()
00335 {
00336 int numCircs = topLevelItemCount();
00337 CircuitList circs;
00338
00339 for (int i = 0; i < numCircs; i++) {
00340 CircuitItem *circ = (CircuitItem *)topLevelItem(i);
00341 circs << circ->circuit();
00342 }
00343 return circs;
00344 }
00345