2013-10-24 22:52:30 +00:00
|
|
|
/* sequence_dialog.cpp
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "sequence_dialog.h"
|
2015-06-25 16:17:03 +00:00
|
|
|
#include <ui_sequence_dialog.h>
|
2013-10-24 22:52:30 +00:00
|
|
|
|
2013-10-25 23:16:56 +00:00
|
|
|
#include "epan/addr_resolv.h"
|
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
#include "wsutil/nstime.h"
|
2015-11-17 01:13:23 +00:00
|
|
|
#include "wsutil/utf8_entities.h"
|
2013-10-24 22:52:30 +00:00
|
|
|
|
2016-05-19 02:21:02 +00:00
|
|
|
#include "color_utils.h"
|
2015-11-17 01:13:23 +00:00
|
|
|
#include "progress_frame.h"
|
2014-11-19 00:21:42 +00:00
|
|
|
#include "sequence_diagram.h"
|
2013-11-12 01:08:08 +00:00
|
|
|
#include "wireshark_application.h"
|
|
|
|
|
|
|
|
#include <QDir>
|
|
|
|
#include <QFileDialog>
|
2013-10-24 22:52:30 +00:00
|
|
|
#include <QFontMetrics>
|
2013-10-25 23:16:56 +00:00
|
|
|
#include <QPoint>
|
2016-06-01 14:05:01 +00:00
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
|
|
|
// Qt::escape
|
|
|
|
#include <QTextDocument>
|
|
|
|
#endif
|
2013-10-24 22:52:30 +00:00
|
|
|
|
|
|
|
// To do:
|
2016-05-31 16:31:10 +00:00
|
|
|
// - Resize or show + hide the Time and Comment axes, possibly via one of
|
|
|
|
// the following:
|
|
|
|
// - Split the time, diagram, and comment sections into three separate
|
|
|
|
// widgets inside a QSplitter. This would resemble the GTK+ UI, but we'd
|
|
|
|
// have to coordinate between the three and we'd lose time and comment
|
|
|
|
// values in PDF and PNG exports.
|
|
|
|
// - Add separate controls for the width and/or visibility of the Time and
|
|
|
|
// Comment columns.
|
|
|
|
// - Fake a splitter widget by catching mouse events in the plot area.
|
|
|
|
// Drawing a QCPItemLine or QCPItemPixmap over each Y axis might make
|
|
|
|
// this easier.
|
2016-06-16 20:31:47 +00:00
|
|
|
// - For general flows, let the user show columns other than COL_INFO.
|
2013-11-12 01:08:08 +00:00
|
|
|
// - Add UTF8 to text dump
|
|
|
|
// - Save to XMI? http://www.umlgraph.org/
|
|
|
|
// - Time: abs vs delta
|
|
|
|
// - Hide nodes
|
|
|
|
// - Clickable time + comments?
|
|
|
|
// - Incorporate packet comments?
|
|
|
|
// - Change line_style to seq_type (i.e. draw ACKs dashed)
|
|
|
|
// - Create WSGraph subclasses with common behavior.
|
2013-11-13 22:18:01 +00:00
|
|
|
// - Help button and text
|
2013-10-24 22:52:30 +00:00
|
|
|
|
2016-05-25 19:02:40 +00:00
|
|
|
static const double min_top_ = -1.0;
|
|
|
|
static const double min_left_ = -0.5;
|
|
|
|
|
2015-11-15 21:57:43 +00:00
|
|
|
SequenceDialog::SequenceDialog(QWidget &parent, CaptureFile &cf, SequenceInfo *info) :
|
2014-12-29 19:42:01 +00:00
|
|
|
WiresharkDialog(parent, cf),
|
2013-10-24 22:52:30 +00:00
|
|
|
ui(new Ui::SequenceDialog),
|
2015-11-15 21:57:43 +00:00
|
|
|
info_(info),
|
2013-10-25 23:16:56 +00:00
|
|
|
num_items_(0),
|
|
|
|
packet_num_(0),
|
2016-05-19 02:21:02 +00:00
|
|
|
sequence_w_(1)
|
2013-10-24 22:52:30 +00:00
|
|
|
{
|
|
|
|
ui->setupUi(this);
|
2016-02-28 18:23:20 +00:00
|
|
|
loadGeometry(parent.width(), parent.height() * 4 / 5);
|
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
QCustomPlot *sp = ui->sequencePlot;
|
2015-11-15 21:57:43 +00:00
|
|
|
setWindowSubtitle(info_ ? tr("Call Flow") : tr("Flow"));
|
2013-10-24 22:52:30 +00:00
|
|
|
|
2015-11-15 21:57:43 +00:00
|
|
|
if (!info_) {
|
|
|
|
info_ = new SequenceInfo(sequence_analysis_info_new());
|
|
|
|
info_->sainfo()->type = SEQ_ANALYSIS_ANY;
|
|
|
|
info_->sainfo()->all_packets = TRUE;
|
2014-11-19 00:21:42 +00:00
|
|
|
} else {
|
2015-11-15 21:57:43 +00:00
|
|
|
info_->ref();
|
|
|
|
num_items_ = sequence_analysis_get_nodes(info_->sainfo());
|
2014-11-19 00:21:42 +00:00
|
|
|
}
|
|
|
|
|
2013-10-25 23:16:56 +00:00
|
|
|
seq_diagram_ = new SequenceDiagram(sp->yAxis, sp->xAxis2, sp->yAxis2);
|
2013-10-24 22:52:30 +00:00
|
|
|
sp->addPlottable(seq_diagram_);
|
2016-05-25 19:02:40 +00:00
|
|
|
|
|
|
|
// When dragging is enabled it's easy to drag past the lower and upper
|
|
|
|
// bounds of each axis. Disable it for now.
|
|
|
|
//sp->axisRect()->setRangeDragAxes(sp->xAxis2, sp->yAxis);
|
|
|
|
//sp->setInteractions(QCP::iRangeDrag);
|
2013-10-24 22:52:30 +00:00
|
|
|
|
|
|
|
sp->xAxis->setVisible(false);
|
2013-10-28 23:57:57 +00:00
|
|
|
sp->xAxis->setPadding(0);
|
|
|
|
sp->xAxis->setLabelPadding(0);
|
|
|
|
sp->xAxis->setTickLabelPadding(0);
|
2016-05-19 02:21:02 +00:00
|
|
|
|
|
|
|
QPen base_pen(ColorUtils::alphaBlend(palette().text(), palette().base(), 0.25));
|
|
|
|
base_pen.setWidthF(0.5);
|
|
|
|
sp->xAxis2->setBasePen(base_pen);
|
|
|
|
sp->yAxis->setBasePen(base_pen);
|
|
|
|
sp->yAxis2->setBasePen(base_pen);
|
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
sp->xAxis2->setVisible(true);
|
|
|
|
sp->yAxis2->setVisible(true);
|
|
|
|
|
2016-05-19 02:21:02 +00:00
|
|
|
key_text_ = new QCPItemText(sp);
|
|
|
|
key_text_->setText(tr("Time"));
|
|
|
|
sp->addItem(key_text_);
|
|
|
|
|
2016-05-25 19:02:40 +00:00
|
|
|
key_text_->setPositionAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
2016-05-19 02:21:02 +00:00
|
|
|
key_text_->position->setType(QCPItemPosition::ptAbsolute);
|
|
|
|
key_text_->setClipToAxisRect(false);
|
|
|
|
|
|
|
|
comment_text_ = new QCPItemText(sp);
|
|
|
|
comment_text_->setText(tr("Comment"));
|
|
|
|
sp->addItem(comment_text_);
|
|
|
|
|
2016-05-25 19:02:40 +00:00
|
|
|
comment_text_->setPositionAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
2016-05-19 02:21:02 +00:00
|
|
|
comment_text_->position->setType(QCPItemPosition::ptAbsolute);
|
|
|
|
comment_text_->setClipToAxisRect(false);
|
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
one_em_ = QFontMetrics(sp->yAxis->labelFont()).height();
|
2013-10-28 23:57:57 +00:00
|
|
|
ui->horizontalScrollBar->setSingleStep(100 / one_em_);
|
|
|
|
ui->verticalScrollBar->setSingleStep(100 / one_em_);
|
2013-10-24 22:52:30 +00:00
|
|
|
|
2013-10-25 23:16:56 +00:00
|
|
|
ui->gridLayout->setSpacing(0);
|
2013-10-24 22:52:30 +00:00
|
|
|
connect(sp->yAxis, SIGNAL(rangeChanged(QCPRange)), sp->yAxis2, SLOT(setRange(QCPRange)));
|
|
|
|
|
2016-06-05 21:33:06 +00:00
|
|
|
ctx_menu_.addAction(ui->actionZoomIn);
|
|
|
|
ctx_menu_.addAction(ui->actionZoomOut);
|
2013-11-12 01:08:08 +00:00
|
|
|
ctx_menu_.addAction(ui->actionReset);
|
|
|
|
ctx_menu_.addSeparator();
|
|
|
|
ctx_menu_.addAction(ui->actionMoveRight10);
|
|
|
|
ctx_menu_.addAction(ui->actionMoveLeft10);
|
|
|
|
ctx_menu_.addAction(ui->actionMoveUp10);
|
|
|
|
ctx_menu_.addAction(ui->actionMoveDown10);
|
|
|
|
ctx_menu_.addAction(ui->actionMoveRight1);
|
|
|
|
ctx_menu_.addAction(ui->actionMoveLeft1);
|
|
|
|
ctx_menu_.addAction(ui->actionMoveUp1);
|
|
|
|
ctx_menu_.addAction(ui->actionMoveDown1);
|
|
|
|
ctx_menu_.addSeparator();
|
|
|
|
ctx_menu_.addAction(ui->actionGoToPacket);
|
2016-05-25 19:02:40 +00:00
|
|
|
ctx_menu_.addAction(ui->actionGoToNextPacket);
|
|
|
|
ctx_menu_.addAction(ui->actionGoToPreviousPacket);
|
2013-11-12 01:08:08 +00:00
|
|
|
|
2013-11-11 22:00:48 +00:00
|
|
|
ui->showComboBox->setCurrentIndex(0);
|
|
|
|
ui->addressComboBox->setCurrentIndex(0);
|
|
|
|
|
|
|
|
QComboBox *fcb = ui->flowComboBox;
|
|
|
|
fcb->addItem(ui->actionFlowAny->text(), SEQ_ANALYSIS_ANY);
|
|
|
|
fcb->addItem(ui->actionFlowTcp->text(), SEQ_ANALYSIS_TCP);
|
|
|
|
|
2015-11-15 21:57:43 +00:00
|
|
|
ui->flowComboBox->setCurrentIndex(info_->sainfo()->type);
|
2014-11-19 00:21:42 +00:00
|
|
|
|
2015-11-15 21:57:43 +00:00
|
|
|
if (info_->sainfo()->type == SEQ_ANALYSIS_VOIP) {
|
2015-11-17 01:13:23 +00:00
|
|
|
ui->flowComboBox->blockSignals(true);
|
2014-11-19 00:21:42 +00:00
|
|
|
ui->controlFrame->hide();
|
2013-10-24 22:52:30 +00:00
|
|
|
}
|
|
|
|
|
2013-11-12 01:08:08 +00:00
|
|
|
QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save);
|
2015-07-31 17:34:43 +00:00
|
|
|
save_bt->setText(tr("Save As" UTF8_HORIZONTAL_ELLIPSIS));
|
2013-11-12 01:08:08 +00:00
|
|
|
|
2016-09-13 11:37:11 +00:00
|
|
|
QPushButton *close_bt = ui->buttonBox->button(QDialogButtonBox::Close);
|
|
|
|
if (close_bt) {
|
|
|
|
close_bt->setDefault(true);
|
|
|
|
}
|
|
|
|
|
2015-11-17 01:13:23 +00:00
|
|
|
ProgressFrame::addToButtonBox(ui->buttonBox, &parent);
|
|
|
|
|
2013-10-25 23:16:56 +00:00
|
|
|
connect(ui->horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(hScrollBarChanged(int)));
|
|
|
|
connect(ui->verticalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(vScrollBarChanged(int)));
|
|
|
|
connect(sp->xAxis2, SIGNAL(rangeChanged(QCPRange)), this, SLOT(xAxisChanged(QCPRange)));
|
|
|
|
connect(sp->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(yAxisChanged(QCPRange)));
|
|
|
|
connect(sp, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(diagramClicked(QMouseEvent*)));
|
|
|
|
connect(sp, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoved(QMouseEvent*)));
|
2016-05-25 19:02:40 +00:00
|
|
|
connect(sp, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(mouseWheeled(QWheelEvent*)));
|
2013-11-12 22:50:26 +00:00
|
|
|
connect(this, SIGNAL(goToPacket(int)), seq_diagram_, SLOT(setSelectedPacket(int)));
|
|
|
|
|
2013-11-12 01:08:08 +00:00
|
|
|
disconnect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
2013-10-24 22:52:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SequenceDialog::~SequenceDialog()
|
|
|
|
{
|
2015-11-15 21:57:43 +00:00
|
|
|
info_->unref();
|
2013-10-24 22:52:30 +00:00
|
|
|
delete ui;
|
|
|
|
}
|
|
|
|
|
2014-12-29 19:42:01 +00:00
|
|
|
void SequenceDialog::updateWidgets()
|
2013-10-24 22:52:30 +00:00
|
|
|
{
|
2015-09-25 09:05:45 +00:00
|
|
|
WiresharkDialog::updateWidgets();
|
2013-10-24 22:52:30 +00:00
|
|
|
}
|
|
|
|
|
2015-07-07 06:24:50 +00:00
|
|
|
void SequenceDialog::showEvent(QShowEvent *)
|
2013-10-24 22:52:30 +00:00
|
|
|
{
|
2016-05-19 02:21:02 +00:00
|
|
|
QTimer::singleShot(0, this, SLOT(fillDiagram()));
|
2013-10-24 22:52:30 +00:00
|
|
|
}
|
|
|
|
|
2015-07-07 06:24:50 +00:00
|
|
|
void SequenceDialog::resizeEvent(QResizeEvent *)
|
2013-10-24 22:52:30 +00:00
|
|
|
{
|
2016-09-13 10:49:23 +00:00
|
|
|
if (!info_) return;
|
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
resetAxes(true);
|
|
|
|
}
|
|
|
|
|
2013-11-12 01:08:08 +00:00
|
|
|
void SequenceDialog::keyPressEvent(QKeyEvent *event)
|
|
|
|
{
|
|
|
|
int pan_pixels = event->modifiers() & Qt::ShiftModifier ? 1 : 10;
|
|
|
|
|
|
|
|
// XXX - Copy some shortcuts from tcp_stream_dialog.cpp
|
|
|
|
switch(event->key()) {
|
2016-06-05 21:33:06 +00:00
|
|
|
case Qt::Key_Minus:
|
|
|
|
case Qt::Key_Underscore: // Shifted minus on U.S. keyboards
|
|
|
|
on_actionZoomOut_triggered();
|
|
|
|
break;
|
|
|
|
case Qt::Key_Plus:
|
|
|
|
case Qt::Key_Equal: // Unshifted plus on U.S. keyboards
|
|
|
|
on_actionZoomIn_triggered();
|
|
|
|
break;
|
|
|
|
|
2013-11-12 01:08:08 +00:00
|
|
|
case Qt::Key_Right:
|
|
|
|
case Qt::Key_L:
|
|
|
|
panAxes(pan_pixels, 0);
|
|
|
|
break;
|
|
|
|
case Qt::Key_Left:
|
|
|
|
case Qt::Key_H:
|
|
|
|
panAxes(-1 * pan_pixels, 0);
|
|
|
|
break;
|
|
|
|
case Qt::Key_Up:
|
|
|
|
case Qt::Key_K:
|
Add a Qt I/O Graph dialog.
For each graph you can set:
- Its visibility
- A name
- A display filter
- Color, from a fixed list
- Plot style: Line, Impulse, Bar, Stacked Bar, Dot, Square, Diamond
- Basic Y Axes (packets/s, bytes/s, bits/s)
- Computed Y Axes (SUM, MIN, AVG, MAX)
- Smoothing
You can pan and zoom using the mouse and keyboard. Clicking on a graph
selects the last packet for that interval. If all graphs have the same Y
axis a single label is shown, otherwise a legend is shown.
The time scale (X axis) can be toggled between relative seconds and the
time of day.
Graphs can be saved as PDF, PNG, BMP, and JPEG. Settings are "sticky"
via the io_graphs UAT.
To do:
- Minimize graph drawing delays.
- Figure out why smoothing differs from GTK+
- Everything else at the top of io_graph_dialog.cpp
- Fix empty resets.
A fair amount of code was copied from TCPStreamDialog. We might want to
subclass QCustomPlot and place the shared code there.
Move common syntax checking to SyntaxLineEdit.
Move some common code from ui/gtk/io_stat.c to ui/io_graph_item.[ch] and
use it in both GTK+ and Qt.
Make the io_graph_item_t array allocation in io_stat.c static. The
behavior should be identical and this gives us additional compile-time
checks.
Change-Id: I9a3d544469b7048f0761fdbf7bcf20f44ae76577
Reviewed-on: https://code.wireshark.org/review/435
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Tested-by: Gerald Combs <gerald@wireshark.org>
2014-02-12 00:07:10 +00:00
|
|
|
panAxes(0, pan_pixels);
|
2013-11-12 01:08:08 +00:00
|
|
|
break;
|
|
|
|
case Qt::Key_Down:
|
|
|
|
case Qt::Key_J:
|
Add a Qt I/O Graph dialog.
For each graph you can set:
- Its visibility
- A name
- A display filter
- Color, from a fixed list
- Plot style: Line, Impulse, Bar, Stacked Bar, Dot, Square, Diamond
- Basic Y Axes (packets/s, bytes/s, bits/s)
- Computed Y Axes (SUM, MIN, AVG, MAX)
- Smoothing
You can pan and zoom using the mouse and keyboard. Clicking on a graph
selects the last packet for that interval. If all graphs have the same Y
axis a single label is shown, otherwise a legend is shown.
The time scale (X axis) can be toggled between relative seconds and the
time of day.
Graphs can be saved as PDF, PNG, BMP, and JPEG. Settings are "sticky"
via the io_graphs UAT.
To do:
- Minimize graph drawing delays.
- Figure out why smoothing differs from GTK+
- Everything else at the top of io_graph_dialog.cpp
- Fix empty resets.
A fair amount of code was copied from TCPStreamDialog. We might want to
subclass QCustomPlot and place the shared code there.
Move common syntax checking to SyntaxLineEdit.
Move some common code from ui/gtk/io_stat.c to ui/io_graph_item.[ch] and
use it in both GTK+ and Qt.
Make the io_graph_item_t array allocation in io_stat.c static. The
behavior should be identical and this gives us additional compile-time
checks.
Change-Id: I9a3d544469b7048f0761fdbf7bcf20f44ae76577
Reviewed-on: https://code.wireshark.org/review/435
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Tested-by: Gerald Combs <gerald@wireshark.org>
2014-02-12 00:07:10 +00:00
|
|
|
panAxes(0, -1 * pan_pixels);
|
2013-11-12 01:08:08 +00:00
|
|
|
break;
|
|
|
|
|
2016-05-28 17:45:12 +00:00
|
|
|
case Qt::Key_PageDown:
|
|
|
|
case Qt::Key_Space:
|
|
|
|
ui->verticalScrollBar->setValue(ui->verticalScrollBar->value() + ui->verticalScrollBar->pageStep());
|
|
|
|
break;
|
|
|
|
case Qt::Key_PageUp:
|
|
|
|
ui->verticalScrollBar->setValue(ui->verticalScrollBar->value() - ui->verticalScrollBar->pageStep());
|
|
|
|
break;
|
|
|
|
|
2013-11-12 01:08:08 +00:00
|
|
|
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_G:
|
|
|
|
on_actionGoToPacket_triggered();
|
|
|
|
break;
|
2016-05-25 19:02:40 +00:00
|
|
|
case Qt::Key_N:
|
|
|
|
on_actionGoToNextPacket_triggered();
|
|
|
|
break;
|
|
|
|
case Qt::Key_P:
|
|
|
|
on_actionGoToPreviousPacket_triggered();
|
|
|
|
break;
|
2013-11-12 01:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QDialog::keyPressEvent(event);
|
|
|
|
}
|
|
|
|
|
2013-10-25 23:16:56 +00:00
|
|
|
void SequenceDialog::hScrollBarChanged(int value)
|
|
|
|
{
|
|
|
|
if (qAbs(ui->sequencePlot->xAxis2->range().center()-value/100.0) > 0.01) {
|
|
|
|
ui->sequencePlot->xAxis2->setRange(value/100.0, ui->sequencePlot->xAxis2->range().size(), Qt::AlignCenter);
|
|
|
|
ui->sequencePlot->replot();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::vScrollBarChanged(int value)
|
|
|
|
{
|
|
|
|
if (qAbs(ui->sequencePlot->yAxis->range().center()-value/100.0) > 0.01) {
|
|
|
|
ui->sequencePlot->yAxis->setRange(value/100.0, ui->sequencePlot->yAxis->range().size(), Qt::AlignCenter);
|
|
|
|
ui->sequencePlot->replot();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::xAxisChanged(QCPRange range)
|
|
|
|
{
|
2016-06-04 19:17:46 +00:00
|
|
|
ui->horizontalScrollBar->setValue(qRound(qreal(range.center()*100.0)));
|
|
|
|
ui->horizontalScrollBar->setPageStep(qRound(qreal(range.size()*100.0)));
|
2013-10-25 23:16:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::yAxisChanged(QCPRange range)
|
|
|
|
{
|
2016-06-04 19:17:46 +00:00
|
|
|
ui->verticalScrollBar->setValue(qRound(qreal(range.center()*100.0)));
|
|
|
|
ui->verticalScrollBar->setPageStep(qRound(qreal(range.size()*100.0)));
|
2013-10-25 23:16:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::diagramClicked(QMouseEvent *event)
|
|
|
|
{
|
2016-05-25 19:02:40 +00:00
|
|
|
switch (event->button()) {
|
|
|
|
case Qt::LeftButton:
|
|
|
|
on_actionGoToPacket_triggered();
|
|
|
|
break;
|
|
|
|
case Qt::RightButton:
|
2013-11-12 01:08:08 +00:00
|
|
|
// XXX We should find some way to get sequenceDiagram to handle a
|
|
|
|
// contextMenuEvent instead.
|
|
|
|
ctx_menu_.exec(event->globalPos());
|
2016-05-25 19:02:40 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2013-11-12 01:08:08 +00:00
|
|
|
}
|
2013-10-25 23:16:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::mouseMoved(QMouseEvent *event)
|
|
|
|
{
|
|
|
|
packet_num_ = 0;
|
|
|
|
QString hint;
|
|
|
|
if (event) {
|
|
|
|
seq_analysis_item_t *sai = seq_diagram_->itemForPosY(event->pos().y());
|
|
|
|
if (sai) {
|
2015-10-25 21:52:30 +00:00
|
|
|
packet_num_ = sai->frame_number;
|
2016-05-31 15:24:12 +00:00
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
|
|
|
QString raw_comment = Qt::escape(sai->comment);
|
|
|
|
#else
|
|
|
|
QString raw_comment = QString(sai->comment).toHtmlEscaped();
|
|
|
|
#endif
|
|
|
|
hint = QString("Packet %1: %2").arg(packet_num_).arg(raw_comment);
|
2013-10-25 23:16:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hint.isEmpty()) {
|
2015-11-15 21:57:43 +00:00
|
|
|
if (!info_->sainfo()) {
|
2014-11-19 00:21:42 +00:00
|
|
|
hint += tr("No data");
|
|
|
|
} else {
|
2015-11-15 21:57:43 +00:00
|
|
|
hint += tr("%Ln node(s)", "", info_->sainfo()->num_nodes) + QString(", ")
|
2014-11-19 00:21:42 +00:00
|
|
|
+ tr("%Ln item(s)", "", num_items_);
|
|
|
|
}
|
2013-10-25 23:16:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hint.prepend("<small><i>");
|
|
|
|
hint.append("</i></small>");
|
|
|
|
ui->hintLabel->setText(hint);
|
|
|
|
}
|
|
|
|
|
2016-05-25 19:02:40 +00:00
|
|
|
void SequenceDialog::mouseWheeled(QWheelEvent *event)
|
2013-10-25 23:16:56 +00:00
|
|
|
{
|
2016-05-25 19:02:40 +00:00
|
|
|
int scroll_delta = event->delta() * -1 / 15;
|
|
|
|
if (event->orientation() == Qt::Vertical) {
|
|
|
|
scroll_delta *= ui->verticalScrollBar->singleStep();
|
|
|
|
ui->verticalScrollBar->setValue(ui->verticalScrollBar->value() + scroll_delta);
|
|
|
|
} else {
|
|
|
|
scroll_delta *= ui->horizontalScrollBar->singleStep();
|
|
|
|
ui->horizontalScrollBar->setValue(ui->horizontalScrollBar->value() + scroll_delta);
|
2013-10-25 23:16:56 +00:00
|
|
|
}
|
2016-05-25 19:02:40 +00:00
|
|
|
event->accept();
|
2013-10-25 23:16:56 +00:00
|
|
|
}
|
|
|
|
|
2013-11-12 01:08:08 +00:00
|
|
|
void SequenceDialog::on_buttonBox_accepted()
|
|
|
|
{
|
|
|
|
QString file_name, extension;
|
|
|
|
QDir path(wsApp->lastOpenDir());
|
|
|
|
QString pdf_filter = tr("Portable Document Format (*.pdf)");
|
|
|
|
QString png_filter = tr("Portable Network Graphics (*.png)");
|
|
|
|
QString bmp_filter = tr("Windows Bitmap (*.bmp)");
|
|
|
|
// Gaze upon my beautiful graph with lossy artifacts!
|
|
|
|
QString jpeg_filter = tr("JPEG File Interchange Format (*.jpeg *.jpg)");
|
|
|
|
QString ascii_filter = tr("ASCII (*.txt)");
|
|
|
|
|
|
|
|
QString filter = QString("%1;;%2;;%3;;%4")
|
|
|
|
.arg(pdf_filter)
|
|
|
|
.arg(png_filter)
|
|
|
|
.arg(bmp_filter)
|
|
|
|
.arg(jpeg_filter);
|
2014-12-29 19:42:01 +00:00
|
|
|
if (!file_closed_) {
|
2013-11-12 01:08:08 +00:00
|
|
|
filter.append(QString(";;%5").arg(ascii_filter));
|
|
|
|
}
|
|
|
|
|
2014-12-31 22:21:50 +00:00
|
|
|
file_name = QFileDialog::getSaveFileName(this, wsApp->windowTitleString(tr("Save Graph As" UTF8_HORIZONTAL_ELLIPSIS)),
|
2013-11-12 01:08:08 +00:00
|
|
|
path.canonicalPath(), filter, &extension);
|
|
|
|
|
|
|
|
if (file_name.length() > 0) {
|
|
|
|
bool save_ok = false;
|
|
|
|
if (extension.compare(pdf_filter) == 0) {
|
|
|
|
save_ok = ui->sequencePlot->savePdf(file_name);
|
|
|
|
} else if (extension.compare(png_filter) == 0) {
|
|
|
|
save_ok = ui->sequencePlot->savePng(file_name);
|
|
|
|
} else if (extension.compare(bmp_filter) == 0) {
|
|
|
|
save_ok = ui->sequencePlot->saveBmp(file_name);
|
|
|
|
} else if (extension.compare(jpeg_filter) == 0) {
|
|
|
|
save_ok = ui->sequencePlot->saveJpg(file_name);
|
2015-11-15 21:57:43 +00:00
|
|
|
} else if (extension.compare(ascii_filter) == 0 && !file_closed_ && info_->sainfo()) {
|
|
|
|
save_ok = sequence_analysis_dump_to_file(file_name.toUtf8().constData(), info_->sainfo(), cap_file_.capFile(), 0);
|
2013-11-12 01:08:08 +00:00
|
|
|
}
|
|
|
|
// else error dialog?
|
|
|
|
if (save_ok) {
|
|
|
|
path = QDir(file_name);
|
|
|
|
wsApp->setLastOpenDir(path.canonicalPath().toUtf8().constData());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
void SequenceDialog::fillDiagram()
|
|
|
|
{
|
2015-11-15 21:57:43 +00:00
|
|
|
if (!info_->sainfo() || file_closed_) return;
|
2014-11-19 00:21:42 +00:00
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
QCustomPlot *sp = ui->sequencePlot;
|
2014-11-19 00:21:42 +00:00
|
|
|
|
2015-11-15 21:57:43 +00:00
|
|
|
if (info_->sainfo()->type == SEQ_ANALYSIS_VOIP) {
|
|
|
|
seq_diagram_->setData(info_->sainfo());
|
2014-11-19 00:21:42 +00:00
|
|
|
} else {
|
|
|
|
seq_diagram_->clearData();
|
2015-11-15 21:57:43 +00:00
|
|
|
sequence_analysis_list_free(info_->sainfo());
|
|
|
|
sequence_analysis_list_get(cap_file_.capFile(), info_->sainfo());
|
|
|
|
num_items_ = sequence_analysis_get_nodes(info_->sainfo());
|
|
|
|
seq_diagram_->setData(info_->sainfo());
|
2014-11-19 00:21:42 +00:00
|
|
|
}
|
2013-10-25 23:16:56 +00:00
|
|
|
|
2016-06-05 21:33:06 +00:00
|
|
|
sequence_w_ = one_em_ * 15; // Arbitrary
|
2013-10-25 23:16:56 +00:00
|
|
|
|
|
|
|
mouseMoved(NULL);
|
2013-10-24 22:52:30 +00:00
|
|
|
resetAxes();
|
|
|
|
|
|
|
|
// XXX QCustomPlot doesn't seem to draw any sort of focus indicator.
|
|
|
|
sp->setFocus();
|
|
|
|
}
|
|
|
|
|
2013-11-12 01:08:08 +00:00
|
|
|
void SequenceDialog::panAxes(int x_pixels, int y_pixels)
|
|
|
|
{
|
2016-05-25 19:02:40 +00:00
|
|
|
// We could simplify this quite a bit if we set the scroll bar values instead.
|
|
|
|
if (!info_->sainfo()) return;
|
|
|
|
|
2013-11-12 01:08:08 +00:00
|
|
|
QCustomPlot *sp = ui->sequencePlot;
|
|
|
|
double h_pan = 0.0;
|
|
|
|
double v_pan = 0.0;
|
|
|
|
|
|
|
|
h_pan = sp->xAxis2->range().size() * x_pixels / sp->xAxis2->axisRect()->width();
|
2016-05-25 19:02:40 +00:00
|
|
|
if (h_pan < 0) {
|
|
|
|
h_pan = qMax(h_pan, min_left_ - sp->xAxis2->range().lower);
|
|
|
|
} else {
|
|
|
|
h_pan = qMin(h_pan, info_->sainfo()->num_nodes - sp->xAxis2->range().upper);
|
|
|
|
}
|
|
|
|
|
2013-11-12 01:08:08 +00:00
|
|
|
v_pan = sp->yAxis->range().size() * y_pixels / sp->yAxis->axisRect()->height();
|
2016-05-25 19:02:40 +00:00
|
|
|
if (v_pan < 0) {
|
|
|
|
v_pan = qMax(v_pan, min_top_ - sp->yAxis->range().lower);
|
|
|
|
} else {
|
|
|
|
v_pan = qMin(v_pan, num_items_ - sp->yAxis->range().upper);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (h_pan && !(sp->xAxis2->range().contains(min_left_) && sp->xAxis2->range().contains(info_->sainfo()->num_nodes))) {
|
2013-11-12 01:08:08 +00:00
|
|
|
sp->xAxis2->moveRange(h_pan);
|
|
|
|
sp->replot();
|
|
|
|
}
|
2016-05-25 19:02:40 +00:00
|
|
|
if (v_pan && !(sp->yAxis->range().contains(min_top_) && sp->yAxis->range().contains(num_items_))) {
|
2013-11-12 01:08:08 +00:00
|
|
|
sp->yAxis->moveRange(v_pan);
|
|
|
|
sp->replot();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
void SequenceDialog::resetAxes(bool keep_lower)
|
|
|
|
{
|
2015-11-15 21:57:43 +00:00
|
|
|
if (!info_->sainfo()) return;
|
2014-11-19 00:21:42 +00:00
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
QCustomPlot *sp = ui->sequencePlot;
|
2016-05-19 02:21:02 +00:00
|
|
|
|
2013-10-28 23:57:57 +00:00
|
|
|
// Allow space for labels on the top and port numbers on the left.
|
2016-05-25 19:02:40 +00:00
|
|
|
double top_pos = min_top_, left_pos = min_left_;
|
2013-10-24 22:52:30 +00:00
|
|
|
if (keep_lower) {
|
|
|
|
top_pos = sp->yAxis->range().lower;
|
2013-10-25 23:16:56 +00:00
|
|
|
left_pos = sp->xAxis2->range().lower;
|
2013-10-24 22:52:30 +00:00
|
|
|
}
|
|
|
|
|
2016-06-05 21:33:06 +00:00
|
|
|
double range_span = sp->viewport().width() / sequence_w_ * sp->axisRect()->rangeZoomFactor(Qt::Horizontal);
|
2016-05-19 02:21:02 +00:00
|
|
|
sp->xAxis2->setRange(left_pos, range_span + left_pos);
|
2013-10-24 22:52:30 +00:00
|
|
|
|
2016-05-19 02:21:02 +00:00
|
|
|
range_span = sp->axisRect()->height() / (one_em_ * 1.5);
|
|
|
|
sp->yAxis->setRange(top_pos, range_span + top_pos);
|
2013-10-24 22:52:30 +00:00
|
|
|
|
2013-10-28 23:57:57 +00:00
|
|
|
double rmin = sp->xAxis2->range().size() / 2;
|
2015-11-15 21:57:43 +00:00
|
|
|
ui->horizontalScrollBar->setRange((rmin - 0.5) * 100, (info_->sainfo()->num_nodes - 0.5 - rmin) * 100);
|
2013-10-28 23:57:57 +00:00
|
|
|
xAxisChanged(sp->xAxis2->range());
|
2016-05-19 02:21:02 +00:00
|
|
|
ui->horizontalScrollBar->setValue(ui->horizontalScrollBar->minimum()); // Shouldn't be needed.
|
2013-10-28 23:57:57 +00:00
|
|
|
|
|
|
|
rmin = (sp->yAxis->range().size() / 2);
|
|
|
|
ui->verticalScrollBar->setRange((rmin - 1.0) * 100, (num_items_ - 0.5 - rmin) * 100);
|
|
|
|
yAxisChanged(sp->yAxis->range());
|
|
|
|
|
2016-05-19 02:21:02 +00:00
|
|
|
// It would be exceedingly handy if we could do one or both of the
|
|
|
|
// following:
|
|
|
|
// - Position an axis label above its axis inline with the tick labels.
|
|
|
|
// - Anchor a QCPItemText to one of the corners of a QCPAxis.
|
|
|
|
// Neither of those appear to be possible, so we first call replot in
|
|
|
|
// order to lay out our X axes, place our labels, the call replot again.
|
|
|
|
sp->replot(QCustomPlot::rpQueued);
|
|
|
|
|
|
|
|
QRect axis_rect = sp->axisRect()->rect();
|
2016-05-25 19:02:40 +00:00
|
|
|
|
2016-05-19 02:21:02 +00:00
|
|
|
key_text_->position->setCoords(axis_rect.left()
|
|
|
|
- sp->yAxis->padding()
|
|
|
|
- sp->yAxis->tickLabelPadding()
|
|
|
|
- sp->yAxis->offset(),
|
2016-05-25 19:02:40 +00:00
|
|
|
axis_rect.top() / 2);
|
2016-05-19 02:21:02 +00:00
|
|
|
comment_text_->position->setCoords(axis_rect.right()
|
|
|
|
+ sp->yAxis2->padding()
|
|
|
|
+ sp->yAxis2->tickLabelPadding()
|
|
|
|
+ sp->yAxis2->offset(),
|
2016-05-25 19:02:40 +00:00
|
|
|
axis_rect.top() / 2);
|
2016-05-19 02:21:02 +00:00
|
|
|
|
|
|
|
sp->replot(QCustomPlot::rpHint);
|
2013-10-24 22:52:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_resetButton_clicked()
|
|
|
|
{
|
|
|
|
resetAxes();
|
|
|
|
}
|
2013-10-25 23:16:56 +00:00
|
|
|
|
|
|
|
void SequenceDialog::on_actionGoToPacket_triggered()
|
|
|
|
{
|
2014-12-29 19:42:01 +00:00
|
|
|
if (!file_closed_ && packet_num_ > 0) {
|
2013-10-25 23:16:56 +00:00
|
|
|
emit goToPacket(packet_num_);
|
|
|
|
}
|
|
|
|
}
|
2013-11-11 22:00:48 +00:00
|
|
|
|
2016-05-25 19:02:40 +00:00
|
|
|
void SequenceDialog::goToAdjacentPacket(bool next)
|
|
|
|
{
|
|
|
|
if (file_closed_) return;
|
2016-05-27 20:00:31 +00:00
|
|
|
|
2016-05-25 19:02:40 +00:00
|
|
|
int old_key = seq_diagram_->selectedKey();
|
|
|
|
int adjacent_packet = seq_diagram_->adjacentPacket(next);
|
|
|
|
int new_key = seq_diagram_->selectedKey();
|
|
|
|
|
|
|
|
if (adjacent_packet > 0) {
|
2016-05-27 20:00:31 +00:00
|
|
|
if (new_key >= 0) {
|
|
|
|
QCustomPlot *sp = ui->sequencePlot;
|
|
|
|
double range_offset = 0.0;
|
2016-05-25 19:02:40 +00:00
|
|
|
// Scroll if we're at our scroll margin and we haven't reached
|
|
|
|
// the end of our range.
|
|
|
|
double scroll_margin = 3.0; // Lines
|
2016-05-27 20:00:31 +00:00
|
|
|
|
|
|
|
if (old_key >= 0) {
|
|
|
|
range_offset = new_key - old_key;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new_key < sp->yAxis->range().lower) {
|
|
|
|
// Out of range, top
|
|
|
|
range_offset = qRound(new_key - sp->yAxis->range().lower - scroll_margin - 0.5);
|
|
|
|
} else if (new_key > sp->yAxis->range().upper) {
|
|
|
|
// Out of range, bottom
|
|
|
|
range_offset = qRound(new_key - sp->yAxis->range().upper + scroll_margin + 0.5);
|
|
|
|
} else if (next) {
|
|
|
|
// In range, next
|
2016-05-25 19:02:40 +00:00
|
|
|
if (new_key + scroll_margin < sp->yAxis->range().upper) {
|
|
|
|
range_offset = 0.0;
|
|
|
|
}
|
|
|
|
} else {
|
2016-05-27 20:00:31 +00:00
|
|
|
// In range, previous
|
2016-05-25 19:02:40 +00:00
|
|
|
if (new_key - scroll_margin > sp->yAxis->range().lower) {
|
|
|
|
range_offset = 0.0;
|
|
|
|
}
|
2016-05-27 20:00:31 +00:00
|
|
|
}
|
2016-05-25 19:02:40 +00:00
|
|
|
|
2016-05-27 20:00:31 +00:00
|
|
|
// Clamp to our upper & lower bounds.
|
|
|
|
if (range_offset > 0) {
|
|
|
|
range_offset = qMin(range_offset, num_items_ - sp->yAxis->range().upper);
|
|
|
|
} else if (range_offset < 0) {
|
|
|
|
range_offset = qMax(range_offset, min_top_ - sp->yAxis->range().lower);
|
2016-05-25 19:02:40 +00:00
|
|
|
}
|
|
|
|
sp->yAxis->moveRange(range_offset);
|
|
|
|
}
|
|
|
|
emit goToPacket(adjacent_packet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-17 01:13:23 +00:00
|
|
|
void SequenceDialog::on_showComboBox_activated(int index)
|
2013-11-11 22:00:48 +00:00
|
|
|
{
|
2015-11-15 21:57:43 +00:00
|
|
|
if (!info_->sainfo()) return;
|
2014-11-19 00:21:42 +00:00
|
|
|
|
2013-11-11 22:00:48 +00:00
|
|
|
if (index == 0) {
|
2015-11-15 21:57:43 +00:00
|
|
|
info_->sainfo()->all_packets = TRUE;
|
2013-11-11 22:00:48 +00:00
|
|
|
} else {
|
2015-11-15 21:57:43 +00:00
|
|
|
info_->sainfo()->all_packets = FALSE;
|
2013-11-11 22:00:48 +00:00
|
|
|
}
|
2013-11-13 22:18:01 +00:00
|
|
|
fillDiagram();
|
2013-11-11 22:00:48 +00:00
|
|
|
}
|
|
|
|
|
2015-11-17 01:13:23 +00:00
|
|
|
void SequenceDialog::on_flowComboBox_activated(int index)
|
2013-11-11 22:00:48 +00:00
|
|
|
{
|
2015-11-15 21:57:43 +00:00
|
|
|
if (!info_->sainfo() || info_->sainfo()->type == SEQ_ANALYSIS_VOIP || index < 0) return;
|
2014-11-19 00:21:42 +00:00
|
|
|
|
2015-11-15 21:57:43 +00:00
|
|
|
info_->sainfo()->type = static_cast<seq_analysis_type>(ui->flowComboBox->itemData(index).toInt());
|
2013-11-13 22:18:01 +00:00
|
|
|
fillDiagram();
|
2013-11-11 22:00:48 +00:00
|
|
|
}
|
|
|
|
|
2015-11-17 01:13:23 +00:00
|
|
|
void SequenceDialog::on_addressComboBox_activated(int index)
|
2013-11-11 22:00:48 +00:00
|
|
|
{
|
2015-11-15 21:57:43 +00:00
|
|
|
if (!info_->sainfo()) return;
|
2014-11-19 00:21:42 +00:00
|
|
|
|
2013-11-11 22:00:48 +00:00
|
|
|
if (index == 0) {
|
2015-11-15 21:57:43 +00:00
|
|
|
info_->sainfo()->any_addr = TRUE;
|
2013-11-11 22:00:48 +00:00
|
|
|
} else {
|
2015-11-15 21:57:43 +00:00
|
|
|
info_->sainfo()->any_addr = FALSE;
|
2013-11-11 22:00:48 +00:00
|
|
|
}
|
2013-11-13 22:18:01 +00:00
|
|
|
fillDiagram();
|
2013-11-12 01:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_actionReset_triggered()
|
|
|
|
{
|
|
|
|
on_resetButton_clicked();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_actionMoveRight10_triggered()
|
|
|
|
{
|
|
|
|
panAxes(10, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_actionMoveLeft10_triggered()
|
|
|
|
{
|
|
|
|
panAxes(-10, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_actionMoveUp10_triggered()
|
|
|
|
{
|
Add a Qt I/O Graph dialog.
For each graph you can set:
- Its visibility
- A name
- A display filter
- Color, from a fixed list
- Plot style: Line, Impulse, Bar, Stacked Bar, Dot, Square, Diamond
- Basic Y Axes (packets/s, bytes/s, bits/s)
- Computed Y Axes (SUM, MIN, AVG, MAX)
- Smoothing
You can pan and zoom using the mouse and keyboard. Clicking on a graph
selects the last packet for that interval. If all graphs have the same Y
axis a single label is shown, otherwise a legend is shown.
The time scale (X axis) can be toggled between relative seconds and the
time of day.
Graphs can be saved as PDF, PNG, BMP, and JPEG. Settings are "sticky"
via the io_graphs UAT.
To do:
- Minimize graph drawing delays.
- Figure out why smoothing differs from GTK+
- Everything else at the top of io_graph_dialog.cpp
- Fix empty resets.
A fair amount of code was copied from TCPStreamDialog. We might want to
subclass QCustomPlot and place the shared code there.
Move common syntax checking to SyntaxLineEdit.
Move some common code from ui/gtk/io_stat.c to ui/io_graph_item.[ch] and
use it in both GTK+ and Qt.
Make the io_graph_item_t array allocation in io_stat.c static. The
behavior should be identical and this gives us additional compile-time
checks.
Change-Id: I9a3d544469b7048f0761fdbf7bcf20f44ae76577
Reviewed-on: https://code.wireshark.org/review/435
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Tested-by: Gerald Combs <gerald@wireshark.org>
2014-02-12 00:07:10 +00:00
|
|
|
panAxes(0, 10);
|
2013-11-12 01:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_actionMoveDown10_triggered()
|
|
|
|
{
|
Add a Qt I/O Graph dialog.
For each graph you can set:
- Its visibility
- A name
- A display filter
- Color, from a fixed list
- Plot style: Line, Impulse, Bar, Stacked Bar, Dot, Square, Diamond
- Basic Y Axes (packets/s, bytes/s, bits/s)
- Computed Y Axes (SUM, MIN, AVG, MAX)
- Smoothing
You can pan and zoom using the mouse and keyboard. Clicking on a graph
selects the last packet for that interval. If all graphs have the same Y
axis a single label is shown, otherwise a legend is shown.
The time scale (X axis) can be toggled between relative seconds and the
time of day.
Graphs can be saved as PDF, PNG, BMP, and JPEG. Settings are "sticky"
via the io_graphs UAT.
To do:
- Minimize graph drawing delays.
- Figure out why smoothing differs from GTK+
- Everything else at the top of io_graph_dialog.cpp
- Fix empty resets.
A fair amount of code was copied from TCPStreamDialog. We might want to
subclass QCustomPlot and place the shared code there.
Move common syntax checking to SyntaxLineEdit.
Move some common code from ui/gtk/io_stat.c to ui/io_graph_item.[ch] and
use it in both GTK+ and Qt.
Make the io_graph_item_t array allocation in io_stat.c static. The
behavior should be identical and this gives us additional compile-time
checks.
Change-Id: I9a3d544469b7048f0761fdbf7bcf20f44ae76577
Reviewed-on: https://code.wireshark.org/review/435
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Tested-by: Gerald Combs <gerald@wireshark.org>
2014-02-12 00:07:10 +00:00
|
|
|
panAxes(0, -10);
|
2013-11-12 01:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_actionMoveRight1_triggered()
|
|
|
|
{
|
|
|
|
panAxes(1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_actionMoveLeft1_triggered()
|
|
|
|
{
|
|
|
|
panAxes(-1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_actionMoveUp1_triggered()
|
|
|
|
{
|
Add a Qt I/O Graph dialog.
For each graph you can set:
- Its visibility
- A name
- A display filter
- Color, from a fixed list
- Plot style: Line, Impulse, Bar, Stacked Bar, Dot, Square, Diamond
- Basic Y Axes (packets/s, bytes/s, bits/s)
- Computed Y Axes (SUM, MIN, AVG, MAX)
- Smoothing
You can pan and zoom using the mouse and keyboard. Clicking on a graph
selects the last packet for that interval. If all graphs have the same Y
axis a single label is shown, otherwise a legend is shown.
The time scale (X axis) can be toggled between relative seconds and the
time of day.
Graphs can be saved as PDF, PNG, BMP, and JPEG. Settings are "sticky"
via the io_graphs UAT.
To do:
- Minimize graph drawing delays.
- Figure out why smoothing differs from GTK+
- Everything else at the top of io_graph_dialog.cpp
- Fix empty resets.
A fair amount of code was copied from TCPStreamDialog. We might want to
subclass QCustomPlot and place the shared code there.
Move common syntax checking to SyntaxLineEdit.
Move some common code from ui/gtk/io_stat.c to ui/io_graph_item.[ch] and
use it in both GTK+ and Qt.
Make the io_graph_item_t array allocation in io_stat.c static. The
behavior should be identical and this gives us additional compile-time
checks.
Change-Id: I9a3d544469b7048f0761fdbf7bcf20f44ae76577
Reviewed-on: https://code.wireshark.org/review/435
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Tested-by: Gerald Combs <gerald@wireshark.org>
2014-02-12 00:07:10 +00:00
|
|
|
panAxes(0, 1);
|
2013-11-12 01:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_actionMoveDown1_triggered()
|
|
|
|
{
|
Add a Qt I/O Graph dialog.
For each graph you can set:
- Its visibility
- A name
- A display filter
- Color, from a fixed list
- Plot style: Line, Impulse, Bar, Stacked Bar, Dot, Square, Diamond
- Basic Y Axes (packets/s, bytes/s, bits/s)
- Computed Y Axes (SUM, MIN, AVG, MAX)
- Smoothing
You can pan and zoom using the mouse and keyboard. Clicking on a graph
selects the last packet for that interval. If all graphs have the same Y
axis a single label is shown, otherwise a legend is shown.
The time scale (X axis) can be toggled between relative seconds and the
time of day.
Graphs can be saved as PDF, PNG, BMP, and JPEG. Settings are "sticky"
via the io_graphs UAT.
To do:
- Minimize graph drawing delays.
- Figure out why smoothing differs from GTK+
- Everything else at the top of io_graph_dialog.cpp
- Fix empty resets.
A fair amount of code was copied from TCPStreamDialog. We might want to
subclass QCustomPlot and place the shared code there.
Move common syntax checking to SyntaxLineEdit.
Move some common code from ui/gtk/io_stat.c to ui/io_graph_item.[ch] and
use it in both GTK+ and Qt.
Make the io_graph_item_t array allocation in io_stat.c static. The
behavior should be identical and this gives us additional compile-time
checks.
Change-Id: I9a3d544469b7048f0761fdbf7bcf20f44ae76577
Reviewed-on: https://code.wireshark.org/review/435
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Tested-by: Gerald Combs <gerald@wireshark.org>
2014-02-12 00:07:10 +00:00
|
|
|
panAxes(0, -1);
|
2013-11-11 22:00:48 +00:00
|
|
|
}
|
2013-11-14 17:37:40 +00:00
|
|
|
|
2016-06-05 21:33:06 +00:00
|
|
|
void SequenceDialog::on_actionZoomIn_triggered()
|
|
|
|
{
|
|
|
|
zoomXAxis(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_actionZoomOut_triggered()
|
|
|
|
{
|
|
|
|
zoomXAxis(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::zoomXAxis(bool in)
|
|
|
|
{
|
|
|
|
QCustomPlot *sp = ui->sequencePlot;
|
|
|
|
double h_factor = sp->axisRect()->rangeZoomFactor(Qt::Horizontal);
|
|
|
|
|
|
|
|
if (!in) {
|
|
|
|
h_factor = pow(h_factor, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
sp->xAxis2->scaleRange(h_factor, sp->xAxis->range().lower);
|
|
|
|
sp->replot();
|
|
|
|
}
|
|
|
|
|
2015-11-15 21:57:43 +00:00
|
|
|
SequenceInfo::SequenceInfo(seq_analysis_info_t *sainfo) :
|
|
|
|
sainfo_(sainfo),
|
|
|
|
count_(1)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SequenceInfo::~SequenceInfo()
|
|
|
|
{
|
|
|
|
sequence_analysis_info_free(sainfo_);
|
|
|
|
}
|
|
|
|
|
2013-11-14 17:37:40 +00:00
|
|
|
/*
|
|
|
|
* Editor modelines
|
|
|
|
*
|
|
|
|
* Local Variables:
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
|
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
|
|
*/
|