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"
|
|
|
|
#include "ui_sequence_dialog.h"
|
|
|
|
|
2013-10-25 23:16:56 +00:00
|
|
|
#include "epan/addr_resolv.h"
|
|
|
|
|
2014-12-31 22:21:50 +00:00
|
|
|
#include "ui/utf8_entities.h"
|
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
#include "wsutil/nstime.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>
|
2013-10-24 22:52:30 +00:00
|
|
|
|
|
|
|
// To do:
|
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
|
|
|
|
2014-12-29 19:42:01 +00:00
|
|
|
SequenceDialog::SequenceDialog(QWidget &parent, CaptureFile &cf, seq_analysis_info_t *sainfo) :
|
|
|
|
WiresharkDialog(parent, cf),
|
2013-10-24 22:52:30 +00:00
|
|
|
ui(new Ui::SequenceDialog),
|
2014-11-19 00:21:42 +00:00
|
|
|
sainfo_(sainfo),
|
2013-10-25 23:16:56 +00:00
|
|
|
num_items_(0),
|
|
|
|
packet_num_(0),
|
|
|
|
node_label_w_(20)
|
2013-10-24 22:52:30 +00:00
|
|
|
{
|
|
|
|
ui->setupUi(this);
|
|
|
|
QCustomPlot *sp = ui->sequencePlot;
|
2014-12-29 19:42:01 +00:00
|
|
|
setWindowSubtitle(sainfo ? tr("Call Flow") : tr("Flow"));
|
2013-10-24 22:52:30 +00:00
|
|
|
|
2014-11-19 00:21:42 +00:00
|
|
|
if (!sainfo_) {
|
|
|
|
sainfo_ = sequence_analysis_info_new();
|
|
|
|
sainfo_->type = SEQ_ANALYSIS_ANY;
|
|
|
|
sainfo_->all_packets = TRUE;
|
|
|
|
} else {
|
|
|
|
num_items_ = sequence_analysis_get_nodes(sainfo_);
|
|
|
|
}
|
|
|
|
|
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_);
|
2013-10-25 23:16:56 +00:00
|
|
|
sp->axisRect()->setRangeDragAxes(sp->xAxis2, sp->yAxis);
|
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);
|
2013-10-24 22:52:30 +00:00
|
|
|
sp->xAxis2->setVisible(true);
|
|
|
|
sp->yAxis2->setVisible(true);
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
sp->setInteractions(QCP::iRangeDrag);
|
|
|
|
|
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)));
|
|
|
|
|
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);
|
|
|
|
|
2013-11-13 22:18:01 +00:00
|
|
|
ui->showComboBox->blockSignals(true);
|
2013-11-11 22:00:48 +00:00
|
|
|
ui->showComboBox->setCurrentIndex(0);
|
2013-11-13 22:18:01 +00:00
|
|
|
ui->showComboBox->blockSignals(false);
|
|
|
|
ui->addressComboBox->blockSignals(true);
|
2013-11-11 22:00:48 +00:00
|
|
|
ui->addressComboBox->setCurrentIndex(0);
|
2013-11-13 22:18:01 +00:00
|
|
|
ui->addressComboBox->blockSignals(false);
|
2013-11-11 22:00:48 +00:00
|
|
|
|
|
|
|
QComboBox *fcb = ui->flowComboBox;
|
|
|
|
fcb->addItem(ui->actionFlowAny->text(), SEQ_ANALYSIS_ANY);
|
|
|
|
fcb->addItem(ui->actionFlowTcp->text(), SEQ_ANALYSIS_TCP);
|
|
|
|
|
2013-11-13 22:18:01 +00:00
|
|
|
ui->flowComboBox->blockSignals(true);
|
2014-11-19 00:21:42 +00:00
|
|
|
ui->flowComboBox->setCurrentIndex(sainfo_->type);
|
|
|
|
|
|
|
|
if (sainfo_->type == SEQ_ANALYSIS_VOIP) {
|
|
|
|
ui->controlFrame->hide();
|
|
|
|
} else {
|
|
|
|
ui->flowComboBox->blockSignals(false);
|
2013-10-24 22:52:30 +00:00
|
|
|
}
|
|
|
|
|
2013-11-12 01:08:08 +00:00
|
|
|
QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save);
|
|
|
|
save_bt->setText(tr("Save As..."));
|
|
|
|
|
2013-11-14 17:37:40 +00:00
|
|
|
// XXX Use recent settings instead
|
2014-12-29 19:42:01 +00:00
|
|
|
resize(parent.width(), parent.height() * 4 / 5);
|
2013-10-24 22:52:30 +00:00
|
|
|
|
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*)));
|
|
|
|
connect(sp, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(mouseReleased(QMouseEvent*)));
|
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-25 23:16:56 +00:00
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
fillDiagram();
|
|
|
|
}
|
|
|
|
|
|
|
|
SequenceDialog::~SequenceDialog()
|
|
|
|
{
|
2014-11-19 00:21:42 +00:00
|
|
|
if (sainfo_->type != SEQ_ANALYSIS_VOIP) {
|
|
|
|
sequence_analysis_info_free(sainfo_);
|
|
|
|
}
|
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
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::showEvent(QShowEvent *event)
|
|
|
|
{
|
|
|
|
Q_UNUSED(event);
|
|
|
|
resetAxes();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::resizeEvent(QResizeEvent *event)
|
|
|
|
{
|
|
|
|
Q_UNUSED(event);
|
|
|
|
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()) {
|
|
|
|
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;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
QDialog::keyPressEvent(event);
|
|
|
|
}
|
|
|
|
|
2013-10-25 23:16:56 +00:00
|
|
|
void SequenceDialog::mouseReleaseEvent(QMouseEvent *event)
|
|
|
|
{
|
|
|
|
mouseReleased(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
ui->horizontalScrollBar->setValue(qRound(range.center()*100.0));
|
|
|
|
ui->horizontalScrollBar->setPageStep(qRound(range.size()*100.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::yAxisChanged(QCPRange range)
|
|
|
|
{
|
|
|
|
ui->verticalScrollBar->setValue(qRound(range.center()*100.0));
|
|
|
|
ui->verticalScrollBar->setPageStep(qRound(range.size()*100.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::diagramClicked(QMouseEvent *event)
|
|
|
|
{
|
|
|
|
QCustomPlot *sp = ui->sequencePlot;
|
|
|
|
|
2013-11-12 01:08:08 +00:00
|
|
|
if (event->button() == Qt::RightButton) {
|
|
|
|
// XXX We should find some way to get sequenceDiagram to handle a
|
|
|
|
// contextMenuEvent instead.
|
|
|
|
ctx_menu_.exec(event->globalPos());
|
|
|
|
} else if (sp->axisRect()->rect().contains(event->pos())) {
|
|
|
|
sp->setCursor(QCursor(Qt::ClosedHandCursor));
|
|
|
|
}
|
|
|
|
on_actionGoToPacket_triggered();
|
2013-10-25 23:16:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::mouseMoved(QMouseEvent *event)
|
|
|
|
{
|
|
|
|
QCustomPlot *sp = ui->sequencePlot;
|
|
|
|
Qt::CursorShape shape = Qt::ArrowCursor;
|
|
|
|
if (event) {
|
|
|
|
if (event->buttons().testFlag(Qt::LeftButton)) {
|
|
|
|
shape = Qt::ClosedHandCursor;
|
|
|
|
} else {
|
|
|
|
if (sp->axisRect()->rect().contains(event->pos())) {
|
|
|
|
shape = Qt::OpenHandCursor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sp->setCursor(QCursor(shape));
|
|
|
|
|
|
|
|
packet_num_ = 0;
|
|
|
|
QString hint;
|
|
|
|
if (event) {
|
|
|
|
seq_analysis_item_t *sai = seq_diagram_->itemForPosY(event->pos().y());
|
|
|
|
if (sai) {
|
|
|
|
packet_num_ = sai->fd->num;
|
|
|
|
hint = QString("Packet %1: %2").arg(packet_num_).arg(sai->comment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hint.isEmpty()) {
|
2014-11-19 00:21:42 +00:00
|
|
|
if (!sainfo_) {
|
|
|
|
hint += tr("No data");
|
|
|
|
} else {
|
|
|
|
hint += tr("%Ln node(s)", "", sainfo_->num_nodes) + QString(", ")
|
|
|
|
+ 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::mouseReleased(QMouseEvent *event)
|
|
|
|
{
|
|
|
|
Q_UNUSED(event);
|
|
|
|
if (ui->sequencePlot->cursor().shape() == Qt::ClosedHandCursor) {
|
|
|
|
ui->sequencePlot->setCursor(QCursor(Qt::OpenHandCursor));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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);
|
2014-12-29 19:42:01 +00:00
|
|
|
} else if (extension.compare(ascii_filter) == 0 && !file_closed_ && sainfo_) {
|
|
|
|
save_ok = sequence_analysis_dump_to_file(file_name.toUtf8().constData(), 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()
|
|
|
|
{
|
2014-12-29 19:42:01 +00:00
|
|
|
if (!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
|
|
|
|
|
|
|
if (sainfo_->type == SEQ_ANALYSIS_VOIP) {
|
|
|
|
seq_diagram_->setData(sainfo_);
|
|
|
|
} else {
|
|
|
|
seq_diagram_->clearData();
|
|
|
|
sequence_analysis_list_free(sainfo_);
|
2014-12-29 19:42:01 +00:00
|
|
|
sequence_analysis_list_get(cap_file_.capFile(), sainfo_);
|
2014-11-19 00:21:42 +00:00
|
|
|
num_items_ = sequence_analysis_get_nodes(sainfo_);
|
|
|
|
seq_diagram_->setData(sainfo_);
|
|
|
|
}
|
2013-10-25 23:16:56 +00:00
|
|
|
|
|
|
|
QFontMetrics vfm = QFontMetrics(sp->xAxis2->labelFont());
|
|
|
|
node_label_w_ = 0;
|
2014-11-19 00:21:42 +00:00
|
|
|
for (guint i = 0; i < sainfo_->num_nodes; i++) {
|
|
|
|
int label_w = vfm.width(ep_address_to_display(&(sainfo_->nodes[i])));
|
2013-10-25 23:16:56 +00:00
|
|
|
if (node_label_w_ < label_w) {
|
|
|
|
node_label_w_ = label_w;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
node_label_w_ = (node_label_w_ * 3 / 4) + one_em_;
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
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();
|
|
|
|
v_pan = sp->yAxis->range().size() * y_pixels / sp->yAxis->axisRect()->height();
|
|
|
|
// The GTK+ version won't pan unless we're zoomed. Should we do the same here?
|
|
|
|
if (h_pan) {
|
|
|
|
sp->xAxis2->moveRange(h_pan);
|
|
|
|
sp->replot();
|
|
|
|
}
|
|
|
|
if (v_pan) {
|
|
|
|
sp->yAxis->moveRange(v_pan);
|
|
|
|
sp->replot();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
void SequenceDialog::resetAxes(bool keep_lower)
|
|
|
|
{
|
2014-11-19 00:21:42 +00:00
|
|
|
if (!sainfo_) return;
|
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
QCustomPlot *sp = ui->sequencePlot;
|
2013-10-28 23:57:57 +00:00
|
|
|
// Allow space for labels on the top and port numbers on the left.
|
|
|
|
double top_pos = -1.0, left_pos = -0.5;
|
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
|
|
|
}
|
|
|
|
|
2013-10-25 23:16:56 +00:00
|
|
|
double range_ratio = sp->xAxis2->axisRect()->width() / node_label_w_;
|
|
|
|
sp->xAxis2->setRange(left_pos, range_ratio + left_pos);
|
2013-10-24 22:52:30 +00:00
|
|
|
|
2013-10-25 23:16:56 +00:00
|
|
|
range_ratio = sp->yAxis->axisRect()->height() / (one_em_ * 1.5);
|
2013-10-24 22:52:30 +00:00
|
|
|
sp->yAxis->setRange(top_pos, range_ratio + top_pos);
|
|
|
|
|
2013-10-28 23:57:57 +00:00
|
|
|
double rmin = sp->xAxis2->range().size() / 2;
|
2014-11-19 00:21:42 +00:00
|
|
|
ui->horizontalScrollBar->setRange((rmin - 0.5) * 100, (sainfo_->num_nodes - 0.5 - rmin) * 100);
|
2013-10-28 23:57:57 +00:00
|
|
|
xAxisChanged(sp->xAxis2->range());
|
|
|
|
|
|
|
|
rmin = (sp->yAxis->range().size() / 2);
|
|
|
|
ui->verticalScrollBar->setRange((rmin - 1.0) * 100, (num_items_ - 0.5 - rmin) * 100);
|
|
|
|
yAxisChanged(sp->yAxis->range());
|
|
|
|
|
2013-10-24 22:52:30 +00:00
|
|
|
sp->replot();
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
void SequenceDialog::on_showComboBox_currentIndexChanged(int index)
|
|
|
|
{
|
2014-11-19 00:21:42 +00:00
|
|
|
if (!sainfo_) return;
|
|
|
|
|
2013-11-11 22:00:48 +00:00
|
|
|
if (index == 0) {
|
2014-11-19 00:21:42 +00:00
|
|
|
sainfo_->all_packets = TRUE;
|
2013-11-11 22:00:48 +00:00
|
|
|
} else {
|
2014-11-19 00:21:42 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_flowComboBox_currentIndexChanged(int index)
|
|
|
|
{
|
2014-11-19 00:21:42 +00:00
|
|
|
if (!sainfo_ || sainfo_->type == SEQ_ANALYSIS_VOIP || index < 0) return;
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
void SequenceDialog::on_addressComboBox_currentIndexChanged(int index)
|
|
|
|
{
|
2014-11-19 00:21:42 +00:00
|
|
|
if (!sainfo_) return;
|
|
|
|
|
2013-11-11 22:00:48 +00:00
|
|
|
if (index == 0) {
|
2014-11-19 00:21:42 +00:00
|
|
|
sainfo_->any_addr = TRUE;
|
2013-11-11 22:00:48 +00:00
|
|
|
} else {
|
2014-11-19 00:21:42 +00:00
|
|
|
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
|
|
|
|
|
|
|
/*
|
|
|
|
* 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:
|
|
|
|
*/
|