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
|
|
|
|
*
|
2018-04-30 07:47:58 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2013-10-24 22:52:30 +00:00
|
|
|
|
|
|
|
#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"
|
|
|
|
|
2016-11-23 15:28:34 +00:00
|
|
|
#include "file.h"
|
2017-12-03 18:53:58 +00:00
|
|
|
|
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"
|
2017-09-22 03:20:03 +00:00
|
|
|
#include "wsutil/file_util.h"
|
2018-03-25 21:24:59 +00:00
|
|
|
#include <wsutil/report_message.h>
|
2013-10-24 22:52:30 +00:00
|
|
|
|
2017-07-25 14:15:18 +00:00
|
|
|
#include <ui/qt/utils/color_utils.h>
|
2015-11-17 01:13:23 +00:00
|
|
|
#include "progress_frame.h"
|
2017-07-25 14:15:18 +00:00
|
|
|
#include <ui/qt/utils/qt_ui_utils.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"
|
2017-09-16 14:52:23 +00:00
|
|
|
#include <ui/qt/utils/variant_pointer.h>
|
2017-09-21 15:28:26 +00:00
|
|
|
#include <ui/alert_box.h>
|
2018-05-16 00:02:26 +00:00
|
|
|
#include "ui/qt/widgets/wireshark_file_dialog.h"
|
2013-11-12 01:08:08 +00:00
|
|
|
|
|
|
|
#include <QDir>
|
2013-10-24 22:52:30 +00:00
|
|
|
#include <QFontMetrics>
|
2013-10-25 23:16:56 +00:00
|
|
|
#include <QPoint>
|
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
|
2019-07-27 07:54:44 +00:00
|
|
|
// - Save to XMI? https://www.spinellis.gr/umlgraph/
|
2013-11-12 01:08:08 +00:00
|
|
|
// - 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;
|
|
|
|
|
2017-09-16 14:52:23 +00:00
|
|
|
typedef struct {
|
|
|
|
int curr_index;
|
|
|
|
QComboBox *flow;
|
|
|
|
SequenceInfo *info;
|
|
|
|
} sequence_items_t;
|
|
|
|
|
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
|
|
|
|
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());
|
2017-09-16 14:52:23 +00:00
|
|
|
info_->sainfo()->name = "any";
|
2014-11-19 00:21:42 +00:00
|
|
|
} else {
|
2015-11-15 21:57:43 +00:00
|
|
|
info_->ref();
|
2016-12-14 18:37:04 +00:00
|
|
|
sequence_analysis_free_nodes(info_->sainfo());
|
2015-11-15 21:57:43 +00:00
|
|
|
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);
|
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"));
|
|
|
|
|
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"));
|
|
|
|
|
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);
|
2019-08-04 08:47:01 +00:00
|
|
|
QAction * action = ctx_menu_.addAction(tr("Reset Diagram"), this, SLOT(resetView()));
|
|
|
|
action->setToolTip(tr("Reset the diagram to its initial state."));
|
2013-11-12 01:08:08 +00:00
|
|
|
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);
|
2020-01-12 19:31:47 +00:00
|
|
|
set_action_shortcuts_visible_in_context_menu(ctx_menu_.actions());
|
2013-11-12 01:08:08 +00:00
|
|
|
|
2013-11-11 22:00:48 +00:00
|
|
|
ui->addressComboBox->setCurrentIndex(0);
|
|
|
|
|
2019-08-04 08:47:01 +00:00
|
|
|
QPushButton * btn = ui->buttonBox->addButton(tr("Reset Diagram"), QDialogButtonBox::ActionRole);
|
|
|
|
btn->setToolTip(tr("Reset the diagram to its initial state."));
|
|
|
|
connect(btn, &QPushButton::clicked, this, &SequenceDialog::resetView);
|
|
|
|
|
2017-09-16 14:52:23 +00:00
|
|
|
sequence_items_t item_data;
|
|
|
|
|
|
|
|
item_data.curr_index = 0;
|
|
|
|
item_data.flow = ui->flowComboBox;
|
|
|
|
item_data.info = info_;
|
2013-11-11 22:00:48 +00:00
|
|
|
|
2017-09-16 14:52:23 +00:00
|
|
|
//Add all registered analysis to combo box
|
|
|
|
sequence_analysis_table_iterate_tables(addFlowSequenceItem, &item_data);
|
2014-11-19 00:21:42 +00:00
|
|
|
|
2017-09-16 14:52:23 +00:00
|
|
|
if (strcmp(info_->sainfo()->name, "voip") == 0) {
|
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);
|
2020-09-29 00:40:05 +00:00
|
|
|
save_bt->setText(tr("Save As…"));
|
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);
|
|
|
|
|
2017-01-19 23:23:29 +00:00
|
|
|
loadGeometry(parent.width(), parent.height() * 4 / 5);
|
|
|
|
|
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
|
|
|
|
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-09-29 18:25:52 +00:00
|
|
|
QString raw_comment = html_escape(sai->comment);
|
2016-05-31 15:24:12 +00:00
|
|
|
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
|
|
|
{
|
2020-05-28 18:40:08 +00:00
|
|
|
int scroll_x = event->angleDelta().x() * -1 / 8;
|
|
|
|
scroll_x *= ui->horizontalScrollBar->singleStep();
|
|
|
|
if (scroll_x) {
|
|
|
|
ui->horizontalScrollBar->setValue(ui->horizontalScrollBar->value() + scroll_x);
|
|
|
|
}
|
|
|
|
|
|
|
|
int scroll_y = event->angleDelta().ry() * -1 / 8;
|
|
|
|
scroll_y *= ui->verticalScrollBar->singleStep();
|
|
|
|
if (scroll_y) {
|
|
|
|
ui->verticalScrollBar->setValue(ui->verticalScrollBar->value() + scroll_y);
|
2013-10-25 23:16:56 +00:00
|
|
|
}
|
2020-05-28 18:40:08 +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));
|
|
|
|
}
|
|
|
|
|
2020-09-29 00:40:05 +00:00
|
|
|
file_name = WiresharkFileDialog::getSaveFileName(this, wsApp->windowTitleString(tr("Save Graph As…")),
|
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()) {
|
2017-09-22 03:20:03 +00:00
|
|
|
FILE *outfile = ws_fopen(file_name.toUtf8().constData(), "w");
|
|
|
|
if (outfile != NULL) {
|
|
|
|
sequence_analysis_dump_to_file(outfile, info_->sainfo(), 0);
|
|
|
|
save_ok = true;
|
2017-12-26 19:41:29 +00:00
|
|
|
fclose(outfile);
|
2017-09-22 03:20:03 +00:00
|
|
|
} else {
|
|
|
|
save_ok = false;
|
|
|
|
}
|
2013-11-12 01:08:08 +00:00
|
|
|
}
|
|
|
|
// else error dialog?
|
|
|
|
if (save_ok) {
|
|
|
|
path = QDir(file_name);
|
|
|
|
wsApp->setLastOpenDir(path.canonicalPath().toUtf8().constData());
|
2017-09-21 15:28:26 +00:00
|
|
|
} else {
|
|
|
|
open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
|
2013-11-12 01:08:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2017-09-16 14:52:23 +00:00
|
|
|
if (strcmp(info_->sainfo()->name, "voip") == 0) {
|
2015-11-15 21:57:43 +00:00
|
|
|
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());
|
2017-09-21 15:28:26 +00:00
|
|
|
|
|
|
|
register_analysis_t* analysis = sequence_analysis_find_by_name(info_->sainfo()->name);
|
|
|
|
if (analysis != NULL)
|
|
|
|
{
|
2018-03-25 21:24:59 +00:00
|
|
|
GString *error_string;
|
2017-09-23 01:57:50 +00:00
|
|
|
const char *filter = NULL;
|
|
|
|
if (ui->displayFilterCheckBox->checkState() == Qt::Checked)
|
|
|
|
filter = cap_file_.capFile()->dfilter;
|
|
|
|
|
2018-03-25 21:24:59 +00:00
|
|
|
error_string = register_tap_listener(sequence_analysis_get_tap_listener_name(analysis), info_->sainfo(), filter, sequence_analysis_get_tap_flags(analysis),
|
2018-07-21 00:07:19 +00:00
|
|
|
NULL, sequence_analysis_get_packet_func(analysis), NULL, NULL);
|
2018-03-25 21:24:59 +00:00
|
|
|
if (error_string) {
|
|
|
|
report_failure("Sequence dialog - tap registration failed: %s", error_string->str);
|
|
|
|
g_string_free(error_string, TRUE);
|
|
|
|
}
|
2017-09-21 15:28:26 +00:00
|
|
|
|
|
|
|
cf_retap_packets(cap_file_.capFile());
|
|
|
|
remove_tap_listener(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.
|
2016-09-25 09:57:55 +00:00
|
|
|
sp->replot(QCustomPlot::rpQueuedReplot);
|
2016-05-19 02:21:02 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
2016-09-25 09:57:55 +00:00
|
|
|
sp->replot(QCustomPlot::rpRefreshHint);
|
2013-10-24 22:52:30 +00:00
|
|
|
}
|
|
|
|
|
2019-08-04 08:47:01 +00:00
|
|
|
void SequenceDialog::resetView()
|
2013-10-24 22:52:30 +00:00
|
|
|
{
|
|
|
|
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) {
|
2016-11-23 15:28:34 +00:00
|
|
|
cf_goto_frame(cap_file_.capFile(), packet_num_);
|
|
|
|
seq_diagram_->setSelectedPacket(packet_num_);
|
2013-10-25 23:16:56 +00:00
|
|
|
}
|
|
|
|
}
|
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);
|
|
|
|
}
|
2016-11-23 15:28:34 +00:00
|
|
|
cf_goto_frame(cap_file_.capFile(), adjacent_packet);
|
|
|
|
seq_diagram_->setSelectedPacket(adjacent_packet);
|
2016-05-25 19:02:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-23 01:57:50 +00:00
|
|
|
void SequenceDialog::on_displayFilterCheckBox_toggled(bool)
|
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
|
|
|
{
|
2017-09-16 14:52:23 +00:00
|
|
|
if (!info_->sainfo() || (strcmp(info_->sainfo()->name, "voip") == 0) || index < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
register_analysis_t* analysis = VariantPointer<register_analysis_t>::asPtr(ui->flowComboBox->itemData(index));
|
|
|
|
info_->sainfo()->name = sequence_analysis_get_name(analysis);
|
2014-11-19 00:21:42 +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_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_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();
|
|
|
|
}
|
|
|
|
|
2017-09-16 14:52:23 +00:00
|
|
|
gboolean SequenceDialog::addFlowSequenceItem(const void* key, void *value, void *userdata)
|
|
|
|
{
|
|
|
|
const char* name = (const char*)key;
|
|
|
|
register_analysis_t* analysis = (register_analysis_t*)value;
|
|
|
|
sequence_items_t* item_data = (sequence_items_t*)userdata;
|
|
|
|
|
|
|
|
/* XXX - Although "voip" isn't a registered name yet, it appears to have special
|
|
|
|
handling that will be done outside of registered data */
|
|
|
|
if (strcmp(name, "voip") == 0)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
item_data->flow->addItem(sequence_analysis_get_ui_name(analysis), VariantPointer<register_analysis_t>::asQVariant(analysis));
|
|
|
|
|
|
|
|
if (item_data->flow->itemData(item_data->curr_index).toString().compare(item_data->info->sainfo()->name) == 0)
|
|
|
|
item_data->flow->setCurrentIndex(item_data->curr_index);
|
|
|
|
|
|
|
|
item_data->curr_index++;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
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:
|
|
|
|
*/
|