aboutsummaryrefslogtreecommitdiffstats
path: root/ui/qt/tcp_stream_dialog.cpp
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2013-09-09 01:40:06 +0000
committerGerald Combs <gerald@wireshark.org>2013-09-09 01:40:06 +0000
commit829c1ed25ec2734d9c6fec6d8cbcc2b6e69ff6f1 (patch)
treea33d1faa4ba754b7a9c831c61fd8dff5bd8b1130 /ui/qt/tcp_stream_dialog.cpp
parent077d252fd92c4a41e3d5396e2f869c6804ce86ef (diff)
Add the TCP window scaling graph. Add zoom selections.
Rename some methods. Add the ability to toggle time and sequence number origins. Add more keyboard shortcuts. Comment out abs_secs abs_usecs in the segment struct since it looks like we aren't using them. Make sure we stay in the same TCP stream. svn path=/trunk/; revision=51856
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
*