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