aboutsummaryrefslogtreecommitdiffstats
path: root/ui/qt/tcp_stream_dialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/qt/tcp_stream_dialog.cpp')
-rw-r--r--ui/qt/tcp_stream_dialog.cpp387
1 files changed, 316 insertions, 71 deletions
diff --git a/ui/qt/tcp_stream_dialog.cpp b/ui/qt/tcp_stream_dialog.cpp
index dbee330d05..8a6000ea7f 100644
--- a/ui/qt/tcp_stream_dialog.cpp
+++ b/ui/qt/tcp_stream_dialog.cpp
@@ -31,8 +31,10 @@
#include "wireshark_application.h"
#include "tango_colors.h"
+#include <QCursor>
#include <QDir>
#include <QFileDialog>
+#include <QIcon>
#include <QPushButton>
#include <QDebug>
@@ -47,11 +49,16 @@ const int moving_avg_period_ = 20;
const QRgb graph_color_1 = tango_sky_blue_5;
const QRgb graph_color_2 = tango_butter_6;
+// Don't accidentally zoom into a 1x1 rect if you happen to click on the graph
+// in zoom mode.
+const int min_zoom_pixels_ = 20;
+
const QString average_throughput_label_ = QObject::tr("Avgerage Througput (bits/s)");
const QString round_trip_time_ms_label_ = QObject::tr("Round Trip Time (ms)");
const QString segment_length_label_ = QObject::tr("Segment Length (B)");
-const QString sequence_number_label_ = QObject::tr("Relative Sequence Number (B)");
+const QString sequence_number_label_ = QObject::tr("Sequence Number (B)");
const QString time_s_label_ = QObject::tr("Time (s)");
+const QString window_size_label_ = QObject::tr("Window Size (B)");
Q_DECLARE_METATYPE(tcp_graph_type)
@@ -59,7 +66,11 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty
QDialog(parent),
ui(new Ui::TCPStreamDialog),
cap_file_(cf),
+ ts_origin_conn_(true),
+ seq_origin_zero_(true),
tracer_(NULL),
+ mouse_drags_(true),
+ rubber_band_(NULL),
num_dsegs_(-1),
num_acks_(-1),
num_sack_ranges_(-1)
@@ -68,7 +79,8 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty
ui->setupUi(this);
- if (!select_tcpip_session(cap_file_, &current)) {
+ struct tcpheader *header = select_tcpip_session(cap_file_, &current);
+ if (!header) {
done(QDialog::Rejected);
}
@@ -80,15 +92,20 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty
ui->graphTypeComboBox->addItem(tr("Time / Sequence (Stevens)"), qVariantFromValue(GRAPH_TSEQ_STEVENS));
ui->graphTypeComboBox->addItem(tr("Throughput"), qVariantFromValue(GRAPH_THROUGHPUT));
ui->graphTypeComboBox->addItem(tr("Round Trip Time"), qVariantFromValue(GRAPH_RTT));
+ ui->graphTypeComboBox->addItem(tr("Window Scaling"), qVariantFromValue(GRAPH_WSCALE));
ui->graphTypeComboBox->setCurrentIndex(-1);
ui->graphTypeComboBox->setUpdatesEnabled(true);
+ ui->mouseHorizontalLayout->setContentsMargins(0, 0, 0, 0);
+ ui->dragToolButton->setChecked(mouse_drags_);
+
memset (&graph_, 0, sizeof(graph_));
graph_.type = graph_type;
COPY_ADDRESS(&graph_.src_address, &current.ip_src);
graph_.src_port = current.th_sport;
COPY_ADDRESS(&graph_.dst_address, &current.ip_dst);
graph_.dst_port = current.th_dport;
+ graph_.stream = header->th_stream;
QCustomPlot *sp = ui->streamPlot;
QCPPlotTitle *file_title = new QCPPlotTitle(sp, cf_get_display_name(cap_file_));
@@ -106,10 +123,6 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty
// Fills the graph
ui->graphTypeComboBox->setCurrentIndex(ui->graphTypeComboBox->findData(qVariantFromValue(graph_type)));
- sp->setInteractions(
- QCP::iRangeDrag |
- QCP::iRangeZoom
- );
sp->setMouseTracking(true);
sp->graph(0)->setPen(QPen(QBrush(graph_color_1), 0.25));
sp->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 5));
@@ -128,6 +141,9 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty
connect(sp, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(graphClicked(QMouseEvent*)));
connect(sp, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoved(QMouseEvent*)));
+ connect(sp, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(mouseReleased(QMouseEvent*)));
+ connect(sp, SIGNAL(axisClick(QCPAxis*,QCPAxis::SelectablePart,QMouseEvent*)),
+ this, SLOT(axisClicked(QCPAxis*,QCPAxis::SelectablePart,QMouseEvent*)));
connect(sp->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(transformYRange(QCPRange)));
disconnect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
@@ -192,17 +208,38 @@ void TCPStreamDialog::keyPressEvent(QKeyEvent *event)
toggleTracerStyle();
break;
- // Reset
case Qt::Key_0:
case Qt::Key_ParenRight: // Shifted 0 on U.S. keyboards
case Qt::Key_R:
case Qt::Key_Home:
resetAxes();
break;
- case Qt::Key_S:
+
+ case Qt::Key_D:
on_otherDirectionButton_clicked();
break;
- // Alas, there is no Blade Runner-style Qt::Key_Ehance
+ case Qt::Key_G:
+ if (tracer_->visible() && cap_file_ && packet_num_ > 0) {
+ emit goToPacket(packet_num_);
+ }
+ break;
+ case Qt::Key_S:
+ seq_origin_zero_ = seq_origin_zero_ ? false : true;
+ fillGraph();
+ break;
+ case Qt::Key_T:
+ ts_origin_conn_ = ts_origin_conn_ ? false : true;
+ fillGraph();
+ break;
+ case Qt::Key_Z:
+ if (mouse_drags_) {
+ ui->selectToolButton->toggle();
+ } else {
+ ui->dragToolButton->toggle();
+ }
+ break;
+
+ // Alas, there is no Blade Runner-style Qt::Key_Enhance
}
if (scale_range) {
@@ -223,6 +260,51 @@ void TCPStreamDialog::keyPressEvent(QKeyEvent *event)
sp->replot();
}
QDialog::keyPressEvent(event);
+
+ // GTK+ Shortcuts:
+ // Left Mouse Button selects segment under cursor in Wiresharks packet list
+ // can also drag to zoom in on a rectangular region
+ // Middle Mouse Button zooms in (towards area under cursor)
+ // <Shift>-Middle Mouse Button zooms out
+
+ // Right Mouse Button moves the graph (if zoomed in)
+ // <Ctrl>-Right Mouse Button displays a portion of graph under cursor magnified
+
+ // 1 display Round Trip Time Graph
+ // 2 display Throughput Graph
+ // 3 display Time/Sequence Graph (Stevens)
+ // 4 display Time/Sequence Graph (tcptrace)
+ // 5 display Window Scaling Graph
+
+ // <Space bar> toggles crosshairs on/off
+
+ // i or + zoom in (towards area under mouse pointer)
+ // o or - zoom out
+ // r or <Home> restore graph to initial state (zoom out max)
+ // s toggles relative/absolute sequence numbers
+ // t toggles time origin
+ // g go to frame under cursor in Wiresharks packet list (if possible)
+
+ // <Left> move view left by 100 pixels (if zoomed in)
+ // <Right> move view right 100 pixels (if zoomed in)
+ // <Up> move view up by 100 pixels (if zoomed in)
+ // <Down> move view down by 100 pixels (if zoomed in)
+
+ // <Shift><Left> move view left by 10 pixels (if zoomed in)
+ // <Shift><Right> move view right 10 pixels (if zoomed in)
+ // <Shift><Up> move view up by 10 pixels (if zoomed in)
+ // <Shift><Down> move view down by 10 pixels (if zoomed in)
+
+ // <Ctrl><Left> move view left by 1 pixel (if zoomed in)
+ // <Ctrl><Right> move view right 1 pixel (if zoomed in)
+ // <Ctrl><Up> move view up by 1 pixel (if zoomed in)
+ // <Ctrl><Down> move view down by 1 pixel (if zoomed in)
+
+}
+
+void TCPStreamDialog::mouseReleaseEvent(QMouseEvent *event)
+{
+ mouseReleased(event);
}
void TCPStreamDialog::fillGraph()
@@ -231,7 +313,7 @@ void TCPStreamDialog::fillGraph()
if (sp->graphCount() < 1) return;
- rel_time_map_.clear();
+ time_stamp_map_.clear();
sequence_num_map_.clear();
graph_segment_list_free(&graph_);
tracer_->setGraph(NULL);
@@ -244,6 +326,8 @@ void TCPStreamDialog::fillGraph()
sp->xAxis->setLabel(time_s_label_);
sp->xAxis->setNumberFormat("gb");
sp->xAxis->setNumberPrecision(6);
+ sp->yAxis->setNumberFormat("f");
+ sp->yAxis->setNumberPrecision(0);
sp->yAxis2->setVisible(false);
sp->yAxis2->setLabel(QString());
@@ -261,24 +345,35 @@ void TCPStreamDialog::fillGraph()
// graphs. If the throughput list used the same list we could call this
// above in our ctor.
graph_segment_list_get(cap_file_, &graph_, TRUE);
+ ts_offset_ = 0;
+ seq_offset_ = 0;
+ bool first = true;
for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) {
if (!compareHeaders(seg)) {
continue;
}
- double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0;
- rel_time_map_.insertMulti(rt_val, seg);
+ double ts = seg->rel_secs + seg->rel_usecs / 1000000.0;
+ if (first) {
+ if (ts_origin_conn_) ts_offset_ = ts;
+ if (seq_origin_zero_) seq_offset_ = seg->th_seq;
+ first = false;
+ }
+ time_stamp_map_.insertMulti(ts - ts_offset_, seg);
}
switch (graph_.type) {
case GRAPH_TSEQ_STEVENS:
- initializeStevens();
+ fillStevens();
break;
case GRAPH_THROUGHPUT:
- initializeThroughput();
+ fillThroughput();
break;
case GRAPH_RTT:
- initializeRoundTripTime();
+ fillRoundTripTime();
+ break;
+ case GRAPH_WSCALE:
+ fillWindowScale();
break;
default:
break;
@@ -319,13 +414,15 @@ void TCPStreamDialog::resetAxes()
sp->replot();
}
-void TCPStreamDialog::initializeStevens()
+void TCPStreamDialog::fillStevens()
{
QString dlg_title = QString(tr("Sequence Numbers")) + streamDescription();
setWindowTitle(dlg_title);
title_->setText(dlg_title);
QCustomPlot *sp = ui->streamPlot;
+ sp->yAxis->setLabel(sequence_number_label_);
+
// True Stevens-style graphs don't have lines but I like them - gcc
sp->graph(0)->setLineStyle(QCPGraph::lsStepLeft);
@@ -335,15 +432,14 @@ void TCPStreamDialog::initializeStevens()
continue;
}
- double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0;
- rel_time.append(rt_val);
- seq.append(seg->th_seq);
+ double ts = seg->rel_secs + seg->rel_usecs / 1000000.0;
+ rel_time.append(ts - ts_offset_);
+ seq.append(seg->th_seq - seq_offset_);
}
sp->graph(0)->setData(rel_time, seq);
- sp->yAxis->setLabel(sequence_number_label_);
}
-void TCPStreamDialog::initializeThroughput()
+void TCPStreamDialog::fillThroughput()
{
QString dlg_title = QString(tr("Throughput")) + streamDescription();
#ifdef MA_1_SECOND
@@ -355,6 +451,12 @@ void TCPStreamDialog::initializeThroughput()
title_->setText(dlg_title);
QCustomPlot *sp = ui->streamPlot;
+ sp->yAxis->setLabel(segment_length_label_);
+ sp->yAxis2->setLabel(average_throughput_label_);
+ sp->yAxis2->setLabelColor(QColor(graph_color_2));
+ sp->yAxis2->setTickLabelColor(QColor(graph_color_2));
+ sp->yAxis2->setVisible(true);
+
sp->graph(0)->setLineStyle(QCPGraph::lsNone);
sp->graph(1)->setVisible(true);
sp->graph(1)->setPen(QPen(QBrush(graph_color_2), 0.5));
@@ -376,10 +478,10 @@ void TCPStreamDialog::initializeThroughput()
// For now use not-really-correct initial values just to keep our vector
// lengths the same.
for (struct segment *seg = graph_.segments->next; seg != NULL; seg = seg->next) {
- double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0;
+ double ts = seg->rel_secs + seg->rel_usecs / 1000000.0;
#ifdef MA_1_SECOND
- while (rt_val - (oldest_seg->rel_secs + oldest_seg->rel_usecs / 1000000.0) > 1.0) {
+ while (ts - (oldest_seg->rel_secs + oldest_seg->rel_usecs / 1000000.0) > 1.0) {
oldest_seg = oldest_seg->next;
sum -= oldest_seg->th_seglen;
}
@@ -391,7 +493,7 @@ void TCPStreamDialog::initializeThroughput()
i++;
#endif
- double dtime = rt_val - (oldest_seg->rel_secs + oldest_seg->rel_usecs / 1000000.0);
+ double dtime = ts - (oldest_seg->rel_secs + oldest_seg->rel_usecs / 1000000.0);
double av_tput;
sum += seg->th_seglen;
if (dtime > 0.0) {
@@ -400,37 +502,35 @@ void TCPStreamDialog::initializeThroughput()
av_tput = 0.0;
}
- rel_time.append(rt_val);
+ rel_time.append(ts - ts_offset_);
seg_len.append(seg->th_seglen);
// Add a data point only if our time window has advanced. Otherwise
// update the most recent point. (We might want to show a warning
// for out-of-order packets.)
- if (tput_time.size() > 0 && rt_val <= tput_time.last()) {
+ if (tput_time.size() > 0 && ts <= tput_time.last()) {
tput[tput.size() - 1] = av_tput;
} else {
tput.append(av_tput);
- tput_time.append(rt_val);
+ tput_time.append(ts);
}
}
sp->graph(0)->setData(rel_time, seg_len);
sp->graph(1)->setData(tput_time, tput);
-
- sp->yAxis->setLabel(segment_length_label_);
-
- sp->yAxis2->setLabel(average_throughput_label_);
- sp->yAxis2->setLabelColor(QColor(graph_color_2));
- sp->yAxis2->setTickLabelColor(QColor(graph_color_2));
- sp->yAxis2->setVisible(true);
}
-void TCPStreamDialog::initializeRoundTripTime()
+void TCPStreamDialog::fillRoundTripTime()
{
QString dlg_title = QString(tr("Round Trip Time")) + streamDescription();
setWindowTitle(dlg_title);
title_->setText(dlg_title);
QCustomPlot *sp = ui->streamPlot;
+ sp->xAxis->setLabel(sequence_number_label_);
+ sp->xAxis->setNumberFormat("f");
+ sp->xAxis->setNumberPrecision(0);
+ sp->yAxis->setLabel(round_trip_time_ms_label_);
+
sp->graph(0)->setLineStyle(QCPGraph::lsLine);
QVector<double> seq_no, rtt;
@@ -452,7 +552,7 @@ void TCPStreamDialog::initializeRoundTripTime()
for (u = unack; u; u = v) {
if (ack_no > u->seqno) {
- seq_no.append(u->seqno);
+ seq_no.append(u->seqno - seq_offset_);
rtt.append((rt_val - u->time) * 1000.0);
sequence_num_map_.insert(u->seqno, seg);
rtt_delete_unack_from_list(&unack, u);
@@ -462,10 +562,33 @@ void TCPStreamDialog::initializeRoundTripTime()
}
}
sp->graph(0)->setData(seq_no, rtt);
- sp->xAxis->setLabel(sequence_number_label_);
- sp->xAxis->setNumberFormat("f");
- sp->xAxis->setNumberPrecision(0);
- sp->yAxis->setLabel(round_trip_time_ms_label_);
+}
+
+void TCPStreamDialog::fillWindowScale()
+{
+ QString dlg_title = QString(tr("Window Scaling")) + streamDescription();
+ setWindowTitle(dlg_title);
+ title_->setText(dlg_title);
+
+ QCustomPlot *sp = ui->streamPlot;
+ sp->graph(0)->setLineStyle(QCPGraph::lsLine);
+
+ QVector<double> rel_time, win_size;
+ for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) {
+ if (!compareHeaders(seg)) {
+ continue;
+ }
+
+ double ts = seg->rel_secs + seg->rel_usecs / 1000000.0;
+ guint16 flags = seg->th_flags;
+
+ if ( (flags & (TH_SYN|TH_RST)) == 0 ) {
+ rel_time.append(ts - ts_offset_);
+ win_size.append(seg->th_win);
+ }
+ }
+ sp->graph(0)->setData(rel_time, win_size);
+ sp->yAxis->setLabel(window_size_label_);
}
QString TCPStreamDialog::streamDescription()
@@ -511,58 +634,163 @@ void TCPStreamDialog::toggleTracerStyle(bool force_default)
ui->streamPlot->replot();
}
+QRectF TCPStreamDialog::getZoomRanges(QRect zoom_rect)
+{
+ QRectF zoom_ranges = QRectF();
+
+ if (zoom_rect.width() < min_zoom_pixels_ && zoom_rect.height() < min_zoom_pixels_) {
+ return zoom_ranges;
+ }
+
+ QCustomPlot *sp = ui->streamPlot;
+ QRect zr = zoom_rect.normalized();
+ QRect ar = sp->axisRect()->rect();
+ if (ar.intersects(zr)) {
+ QRect zsr = ar.intersected(zr);
+ zoom_ranges.setX(sp->xAxis->range().lower
+ + sp->xAxis->range().size() * (zsr.left() - ar.left()) / ar.width());
+ zoom_ranges.setWidth(sp->xAxis->range().size() * zsr.width() / ar.width());
+
+ // QRects grow down
+ zoom_ranges.setY(sp->yAxis->range().lower
+ + sp->yAxis->range().size() * (ar.bottom() - zsr.bottom()) / ar.height());
+ zoom_ranges.setHeight(sp->yAxis->range().size() * zsr.height() / ar.height());
+ }
+ return zoom_ranges;
+}
+
void TCPStreamDialog::graphClicked(QMouseEvent *event)
{
Q_UNUSED(event)
-// QRect spr = ui->streamPlot->axisRect()->rect();
- if (tracer_->visible() && cap_file_ && packet_num_ > 0) {
- emit goToPacket(packet_num_);
+ if (mouse_drags_) {
+ if (tracer_->visible() && cap_file_ && packet_num_ > 0) {
+ emit goToPacket(packet_num_);
+ }
+ } else {
+ if (!rubber_band_) {
+ rubber_band_ = new QRubberBand(QRubberBand::Rectangle, ui->streamPlot);
+ }
+ rb_origin_ = event->pos();
+ rubber_band_->setGeometry(QRect(rb_origin_, QSize()));
+ rubber_band_->show();
}
}
-// Setting mouseTracking on our streamPlot may not be as reliable
-// as we need. If it's not we might want to poll the mouse position
-// using a QTimer instead.
-void TCPStreamDialog::mouseMoved(QMouseEvent *event)
+void TCPStreamDialog::axisClicked(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event)
{
- double tr_key = tracer_->position->key();
- struct segment *packet_seg = NULL;
- packet_num_ = 0;
+ Q_UNUSED(part)
+ Q_UNUSED(event)
+ QCustomPlot *sp = ui->streamPlot;
- if (event && tracer_->graph() && tracer_->position->axisRect()->rect().contains(event->pos())) {
+ if (axis == sp->xAxis) {
switch (graph_.type) {
- case GRAPH_TSEQ_STEVENS:
case GRAPH_THROUGHPUT:
- packet_seg = rel_time_map_.value(tr_key, NULL);
+ case GRAPH_TSEQ_STEVENS:
+ case GRAPH_TSEQ_TCPTRACE:
+ case GRAPH_WSCALE:
+ ts_origin_conn_ = ts_origin_conn_ ? false : true;
+ fillGraph();
break;
case GRAPH_RTT:
- packet_seg = sequence_num_map_.value(tr_key, NULL);
+ seq_origin_zero_ = seq_origin_zero_ ? false : true;
+ fillGraph();
+ break;
+ default:
+ break;
+ }
+ } else if (axis == sp->yAxis) {
+ switch (graph_.type) {
+ case GRAPH_TSEQ_STEVENS:
+ case GRAPH_TSEQ_TCPTRACE:
+ seq_origin_zero_ = seq_origin_zero_ ? false : true;
+ fillGraph();
+ break;
default:
break;
}
}
+}
- if (!packet_seg) {
- tracer_->setVisible(false);
- ui->hintLabel->setText(tr("<small><i>Hover over the graph for details.</i></small>"));
+// Setting mouseTracking on our streamPlot may not be as reliable
+// as we need. If it's not we might want to poll the mouse position
+// using a QTimer instead.
+void TCPStreamDialog::mouseMoved(QMouseEvent *event)
+{
+ if (mouse_drags_) {
+ double tr_key = tracer_->position->key();
+ struct segment *packet_seg = NULL;
+ packet_num_ = 0;
+
+ if (event && tracer_->graph() && tracer_->position->axisRect()->rect().contains(event->pos())) {
+ switch (graph_.type) {
+ case GRAPH_TSEQ_STEVENS:
+ case GRAPH_THROUGHPUT:
+ case GRAPH_WSCALE:
+ packet_seg = time_stamp_map_.value(tr_key, NULL);
+ break;
+ case GRAPH_RTT:
+ packet_seg = sequence_num_map_.value(tr_key, NULL);
+ default:
+ break;
+ }
+ }
+
+ if (!packet_seg) {
+ tracer_->setVisible(false);
+ ui->hintLabel->setText(tr("<small><i>Hover over the graph for details.</i></small>"));
+ ui->streamPlot->replot();
+ return;
+ }
+
+ tracer_->setVisible(true);
+ packet_num_ = packet_seg->num;
+ QString hint = QString(tr("<small><i>%1 %2 (%3s len %4 seq %5 ack %6 win %7)</i></small>"))
+ .arg(cap_file_ ? tr("Click to select packet") : tr("Packet"))
+ .arg(packet_num_)
+ .arg(QString::number(packet_seg->rel_secs + packet_seg->rel_usecs / 1000000.0, 'g', 4))
+ .arg(packet_seg->th_seglen)
+ .arg(packet_seg->th_seq)
+ .arg(packet_seg->th_ack)
+ .arg(packet_seg->th_win);
+ ui->hintLabel->setText(hint);
+ tracer_->setGraphKey(ui->streamPlot->xAxis->pixelToCoord(event->pos().x()));
ui->streamPlot->replot();
- return;
+ } else {
+ QString hint = QString(tr("<small>Click to select a portion of the graph</small>"));
+ if (rubber_band_) {
+ rubber_band_->setGeometry(QRect(rb_origin_, event->pos()).normalized());
+ QRectF zoom_ranges = getZoomRanges(QRect(rb_origin_, event->pos()));
+ if (zoom_ranges.width() > 0.0 && zoom_ranges.height() > 0.0) {
+ hint = QString(tr("<small>Release to zoom, x = %1 to %2, y = %3 to %4</small>"))
+ .arg(zoom_ranges.x())
+ .arg(zoom_ranges.x() + zoom_ranges.width())
+ .arg(zoom_ranges.y())
+ .arg(zoom_ranges.y() + zoom_ranges.height());
+ } else {
+ hint = QString(tr("<small>Unable to select range</small>"));
+ }
+ }
+ ui->hintLabel->setText(hint);
}
+}
- tracer_->setVisible(true);
- packet_num_ = packet_seg->num;
- QString hint = QString(tr("<small><i>%1 %2 (%3s len %4 seq %5 ack %6 win %7)</i></small>"))
- .arg(cap_file_ ? tr("Click to select packet") : tr("Packet"))
- .arg(packet_num_)
- .arg(QString::number(packet_seg->rel_secs + packet_seg->rel_usecs / 1000000.0, 'g', 4))
- .arg(packet_seg->th_seglen)
- .arg(packet_seg->th_seq)
- .arg(packet_seg->th_ack)
- .arg(packet_seg->th_win);
- ui->hintLabel->setText(hint);
- tracer_->setGraphKey(ui->streamPlot->xAxis->pixelToCoord(event->pos().x()));
- ui->streamPlot->replot();
+void TCPStreamDialog::mouseReleased(QMouseEvent *event)
+{
+ if (rubber_band_) {
+ rubber_band_->hide();
+ if (!mouse_drags_) {
+ QRectF zoom_ranges = getZoomRanges(QRect(rb_origin_, event->pos()));
+ if (zoom_ranges.width() > 0.0 && zoom_ranges.height() > 0.0) {
+ QCustomPlot *sp = ui->streamPlot;
+ sp->xAxis->setRangeLower(zoom_ranges.x());
+ sp->xAxis->setRangeUpper(zoom_ranges.x() + zoom_ranges.width());
+ sp->yAxis->setRangeLower(zoom_ranges.y());
+ sp->yAxis->setRangeUpper(zoom_ranges.y() + zoom_ranges.height());
+ sp->replot();
+ }
+ }
+ }
}
void TCPStreamDialog::transformYRange(const QCPRange &y_range1)
@@ -648,6 +876,23 @@ void TCPStreamDialog::on_otherDirectionButton_clicked()
fillGraph();
}
+void TCPStreamDialog::on_dragToolButton_toggled(bool checked)
+{
+ if (checked) mouse_drags_ = true;
+ ui->streamPlot->setInteractions(
+ QCP::iRangeDrag |
+ QCP::iRangeZoom
+ );
+ ui->streamPlot->setCursor(QCursor(Qt::OpenHandCursor));
+}
+
+void TCPStreamDialog::on_selectToolButton_toggled(bool checked)
+{
+ if (checked) mouse_drags_ = false;
+ ui->streamPlot->setInteractions(0);
+ ui->streamPlot->setCursor(QCursor(Qt::CrossCursor));
+}
+
/*
* Editor modelines
*