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