aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorMartin Mathieson <martin.r.mathieson@googlemail.com>2015-10-17 08:54:55 -0700
committerMartin Mathieson <martin.r.mathieson@googlemail.com>2015-10-17 21:27:26 +0000
commit8efd83ef82a3a6895a956ae5ceafd8f97826b001 (patch)
tree0c99b3cc017e92b0e52f41571924ab88e9457421 /ui
parent8e9fc80e29b1fa8bfa85b37900ff150855c8efd6 (diff)
LTE RLC Graph: add support for going to packet clicked
Change-Id: I7e1ada7508c33f7ccea5703a9ea9e2a76ecdb706 Reviewed-on: https://code.wireshark.org/review/11118 Petri-Dish: Martin Mathieson <martin.r.mathieson@googlemail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Martin Mathieson <martin.r.mathieson@googlemail.com>
Diffstat (limited to 'ui')
-rw-r--r--ui/qt/lte_rlc_graph_dialog.cpp128
-rw-r--r--ui/qt/lte_rlc_graph_dialog.h9
-rw-r--r--ui/qt/lte_rlc_graph_dialog.ui11
-rw-r--r--ui/qt/lte_rlc_statistics_dialog.cpp28
-rw-r--r--ui/qt/lte_rlc_statistics_dialog.h6
-rw-r--r--ui/qt/main_window.h3
-rw-r--r--ui/qt/main_window_slots.cpp23
7 files changed, 158 insertions, 50 deletions
diff --git a/ui/qt/lte_rlc_graph_dialog.cpp b/ui/qt/lte_rlc_graph_dialog.cpp
index a60a506017..af4356538c 100644
--- a/ui/qt/lte_rlc_graph_dialog.cpp
+++ b/ui/qt/lte_rlc_graph_dialog.cpp
@@ -48,9 +48,7 @@
// TODO:
// - better handling of zooming (select area like TCP and/or Jim's patch for 1 dimension at a time)
-// - get launched from RLC stats for a pre-known channel
// - how to avoid panning or zooming out to -ve (x or y axis)
-// - goto packet functionality when click on segments
const QRgb graph_color_ack = tango_sky_blue_4; // Blue for ACK lines
const QRgb graph_color_nack = tango_scarlet_red_3; // Red for NACKs
@@ -91,8 +89,8 @@ LteRlcGraphDialog::LteRlcGraphDialog(QWidget &parent, CaptureFile &cf, bool chan
ctx_menu_->addAction(ui->actionMoveLeft1);
ctx_menu_->addAction(ui->actionMoveUp1);
ctx_menu_->addAction(ui->actionMoveDown1);
-// ctx_menu_.addSeparator();
-// ctx_menu_->addAction(ui->actionGoToPacket);
+ ctx_menu_->addSeparator();
+ ctx_menu_->addAction(ui->actionGoToPacket);
ctx_menu_->addSeparator();
ctx_menu_->addAction(ui->actionDragZoom);
// ctx_menu_->addAction(ui->actionToggleTimeOrigin);
@@ -164,6 +162,12 @@ void LteRlcGraphDialog::completeGraph()
nacks_graph_ = sp->addGraph();
nacks_graph_->setPen(QPen(QBrush(graph_color_nack), 0.25));
+ // Create tracer
+ tracer_ = new QCPItemTracer(sp);
+ sp->addItem(tracer_);
+ tracer_->setVisible(false);
+ toggleTracerStyle(true);
+
connect(rp, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(graphClicked(QMouseEvent*)));
connect(rp, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoved(QMouseEvent*)));
connect(rp, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(mouseReleased(QMouseEvent*)));
@@ -185,8 +189,14 @@ bool LteRlcGraphDialog::compareHeaders(rlc_segment *seg)
// Look for channel to plot based upon currently selected frame.
void LteRlcGraphDialog::findChannel()
{
+ // Temporarily disconnect mouse move signals.
+ QCustomPlot *rp = ui->rlcPlot;
+ disconnect(rp, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoved(QMouseEvent*)));
+
char *err_string = NULL;
gboolean free_err_string = FALSE;
+
+ // Rescan for channel data.
rlc_graph_segment_list_free(&graph_);
if (!rlc_graph_segment_list_get(cap_file_.capFile(), &graph_, graph_.channelSet,
&err_string, &free_err_string)) {
@@ -196,6 +206,9 @@ void LteRlcGraphDialog::findChannel()
g_free(err_string);
}
}
+
+ // Reconnect mouse move signal.
+ connect(rp, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoved(QMouseEvent*)));
}
// Fill in graph data based upon what was read into the rlc_graph struct.
@@ -208,6 +221,8 @@ void LteRlcGraphDialog::fillGraph()
return;
}
+ tracer_->setGraph(NULL);
+
base_graph_->setLineStyle(QCPGraph::lsNone); // dot
reseg_graph_->setLineStyle(QCPGraph::lsNone); // dot
acks_graph_->setLineStyle(QCPGraph::lsStepLeft); // to get step effect...
@@ -279,6 +294,8 @@ void LteRlcGraphDialog::fillGraph()
mouseMoved(NULL);
resetAxes();
+ tracer_->setGraph(base_graph_);
+
// XXX QCustomPlot doesn't seem to draw any sort of focus indicator.
sp->setFocus();
}
@@ -342,7 +359,7 @@ void LteRlcGraphDialog::keyPressEvent(QKeyEvent *event)
break;
case Qt::Key_G:
-// on_actionGoToPacket_triggered();
+ on_actionGoToPacket_triggered();
break;
case Qt::Key_T:
// on_actionToggleTimeOrigin_triggered();
@@ -430,7 +447,7 @@ void LteRlcGraphDialog::graphClicked(QMouseEvent *event)
if (rp->axisRect()->rect().contains(event->pos())) {
rp->setCursor(QCursor(Qt::ClosedHandCursor));
}
-// on_actionGoToPacket_triggered();
+ on_actionGoToPacket_triggered();
} else {
if (!rubber_band_) {
rubber_band_ = new QRubberBand(QRubberBand::Rectangle, rp);
@@ -448,6 +465,7 @@ void LteRlcGraphDialog::mouseMoved(QMouseEvent *event)
QString hint;
Qt::CursorShape shape = Qt::ArrowCursor;
+ // Set the cursor shape.
if (event) {
if (event->buttons().testFlag(Qt::LeftButton)) {
if (mouse_drags_) {
@@ -465,41 +483,41 @@ void LteRlcGraphDialog::mouseMoved(QMouseEvent *event)
rp->setCursor(QCursor(shape));
}
+
if (mouse_drags_) {
-// double ts = 0;
-// packet_num_ = 0;
-// int interval_packet = -1;
-
-// if (event && tracer_->graph()) {
-// tracer_->setGraphKey(rp->xAxis->pixelToCoord(event->pos().x()));
-// ts = tracer_->position->key();
-
-// QTreeWidgetItem *ti = ui->graphTreeWidget->topLevelItem(0);
-// IOGraph *iog = NULL;
-// if (ti) {
-// iog = ti->data(name_col_, Qt::UserRole).value<IOGraph *>();
-// interval_packet = iog->packetFromTime(ts);
-// }
-// }
-
-// if (interval_packet < 0) {
-// hint += tr("Hover over the graph for details.");
-// } else {
-// QString msg = tr("No packets in interval");
-// QString val;
-// if (interval_packet > 0) {
-// packet_num_ = (guint32) interval_packet;
-// msg = tr("%1 %2")
-// .arg(!file_closed_ ? tr("Click to select packet") : tr("Packet"))
-// .arg(packet_num_);
-// val = " = " + QString::number(tracer_->position->value(), 'g', 4);
-// }
-// hint += tr("%1 (%2s%3).")
-// .arg(msg)
-// .arg(QString::number(ts, 'g', 4))
-// .arg(val);
-// }
+ double tr_key = tracer_->position->key();
+ struct rlc_segment *packet_seg = NULL;
+ packet_num_ = 0;
+
+ // XXX If we have multiple packets with the same timestamp tr_key
+ // may not return the packet we want. It might be possible to fudge
+ // unique keys using nextafter().
+ //printf("testing here (event=%p, tracer_->graph()=%p\n", event, tracer_->graph());
+ if (event && tracer_->graph() && tracer_->position->axisRect()->rect().contains(event->pos())) {
+ packet_seg = time_stamp_map_.value(tr_key, NULL);
+ }
+
+ if (!packet_seg) {
+ tracer_->setVisible(false);
+// hint += "Hover over the graph for details. " + stream_desc_ + "</i></small>";
+// ui->hintLabel->setText(hint);
+// ui->streamPlot->replot();
+ return;
+ }
+
+ tracer_->setVisible(true);
+ packet_num_ = packet_seg->num;
+// hint += tr("%1 %2 (%3s len %4 seq %5 ack %6 win %7)")
+// .arg(cap_file_ ? tr("Click to select packet") : tr("Packet"))
+// .arg(packet_num_)
+// .arg(QString::number(packet_seg->rel_secs + packet_seg->rel_usecs / 1000000.0, 'g', 4))
+// .arg(packet_seg->th_seglen)
+// .arg(packet_seg->th_seq)
+// .arg(packet_seg->th_ack)
+// .arg(packet_seg->th_win);
+ tracer_->setGraphKey(ui->rlcPlot->xAxis->pixelToCoord(event->pos().x()));
rp->replot();
+
} else {
if (event && rubber_band_ && rubber_band_->isVisible()) {
rubber_band_->setGeometry(QRect(rb_origin_, event->pos()).normalized());
@@ -564,6 +582,38 @@ void LteRlcGraphDialog::resetAxes()
rp->replot();
}
+void LteRlcGraphDialog::on_actionGoToPacket_triggered()
+{
+ if (tracer_->visible() && cap_file_.capFile() && (packet_num_ > 0)) {
+ // Signal to the packetlist which frame we want to show.
+ emit goToPacket(packet_num_);
+ }
+}
+
+void LteRlcGraphDialog::toggleTracerStyle(bool force_default)
+{
+ if (!tracer_->visible() && !force_default) return;
+
+ QPen sp_pen = ui->rlcPlot->graph(0)->pen();
+ QCPItemTracer::TracerStyle tstyle = QCPItemTracer::tsCrosshair;
+ QPen tr_pen = QPen(tracer_->pen());
+ QColor tr_color = sp_pen.color();
+
+ if (force_default || tracer_->style() != QCPItemTracer::tsCircle) {
+ tstyle = QCPItemTracer::tsCircle;
+ tr_color.setAlphaF(1.0);
+ tr_pen.setWidthF(1.5);
+ } else {
+ tr_color.setAlphaF(0.5);
+ tr_pen.setWidthF(1.0);
+ }
+
+ tracer_->setStyle(tstyle);
+ tr_pen.setColor(tr_color);
+ tracer_->setPen(tr_pen);
+ ui->rlcPlot->replot();
+}
+
void LteRlcGraphDialog::on_actionReset_triggered()
{
resetAxes();
diff --git a/ui/qt/lte_rlc_graph_dialog.h b/ui/qt/lte_rlc_graph_dialog.h
index ba602f2c4e..92c090e862 100644
--- a/ui/qt/lte_rlc_graph_dialog.h
+++ b/ui/qt/lte_rlc_graph_dialog.h
@@ -48,6 +48,9 @@ public:
void setChannelInfo(guint16 ueid, guint8 rlcMode,
guint16 channelType, guint16 channelId, guint8 direction);
+signals:
+ void goToPacket(int packet_num);
+
protected:
void showEvent(QShowEvent *event);
void keyPressEvent(QKeyEvent *event);
@@ -70,6 +73,8 @@ private:
QCPGraph *reseg_graph_;
QCPGraph *acks_graph_;
QCPGraph *nacks_graph_;
+ QCPItemTracer *tracer_;
+ guint32 packet_num_;
void completeGraph();
@@ -82,6 +87,8 @@ private:
void panAxes(int x_pixels, int y_pixels);
QRectF getZoomRanges(QRect zoom_rect);
+ void toggleTracerStyle(bool force_default);
+
private slots:
void graphClicked(QMouseEvent *event);
void mouseMoved(QMouseEvent *event);
@@ -102,6 +109,8 @@ private slots:
void on_actionDragZoom_triggered();
void on_actionMoveUp100_triggered();
void on_actionMoveDown100_triggered();
+
+ void on_actionGoToPacket_triggered();
};
#endif // LTE_RLC_GRAPH_DIALOG_H
diff --git a/ui/qt/lte_rlc_graph_dialog.ui b/ui/qt/lte_rlc_graph_dialog.ui
index 827a1bb62b..65946dc415 100644
--- a/ui/qt/lte_rlc_graph_dialog.ui
+++ b/ui/qt/lte_rlc_graph_dialog.ui
@@ -228,6 +228,17 @@
<string>PgDown</string>
</property>
</action>
+ <action name="actionGoToPacket">
+ <property name="text">
+ <string>Go To Packet Under Cursor</string>
+ </property>
+ <property name="toolTip">
+ <string>Go to packet currently under the cursor</string>
+ </property>
+ <property name="shortcut">
+ <string>G</string>
+ </property>
+ </action>
</widget>
<customwidgets>
<customwidget>
diff --git a/ui/qt/lte_rlc_statistics_dialog.cpp b/ui/qt/lte_rlc_statistics_dialog.cpp
index 945c32c850..1378b068a6 100644
--- a/ui/qt/lte_rlc_statistics_dialog.cpp
+++ b/ui/qt/lte_rlc_statistics_dialog.cpp
@@ -312,13 +312,11 @@ public:
return filter_expr;
}
- // Create an RLC Graph and populate it with this channel's details.
- void launchGraph(guint8 direction, CaptureFile &cf)
- {
- LteRlcGraphDialog *graph_dialog = new LteRlcGraphDialog(dialog_, cf, true);
- graph_dialog->setChannelInfo(ueid_, mode_, channelType_, channelId_, direction);
- graph_dialog->show();
- }
+ // Accessors (queried for launching graph)
+ unsigned get_ueid() { return ueid_; }
+ unsigned get_channelType() { return channelType_; }
+ unsigned get_channelId() { return channelId_; }
+ unsigned get_mode() { return mode_; }
private:
QWidget &dialog_;
@@ -879,9 +877,15 @@ void LteRlcStatisticsDialog::captureFileClosing()
void LteRlcStatisticsDialog::launchULGraphButtonClicked()
{
if (statsTreeWidget()->selectedItems().count() > 0 && statsTreeWidget()->selectedItems()[0]->type() == rlc_channel_row_type_) {
+ // Get the channel item.
QTreeWidgetItem *ti = statsTreeWidget()->selectedItems()[0];
RlcChannelTreeWidgetItem *rc_ti = static_cast<RlcChannelTreeWidgetItem*>(ti);
- rc_ti->launchGraph(DIRECTION_UPLINK, cf_);
+ emit launchRLCGraph(true,
+ rc_ti->get_ueid(),
+ rc_ti->get_mode(),
+ rc_ti->get_channelType(),
+ rc_ti->get_channelId(),
+ DIRECTION_UPLINK);
}
}
@@ -889,9 +893,15 @@ void LteRlcStatisticsDialog::launchULGraphButtonClicked()
void LteRlcStatisticsDialog::launchDLGraphButtonClicked()
{
if (statsTreeWidget()->selectedItems().count() > 0 && statsTreeWidget()->selectedItems()[0]->type() == rlc_channel_row_type_) {
+ // Get the channel item.
QTreeWidgetItem *ti = statsTreeWidget()->selectedItems()[0];
RlcChannelTreeWidgetItem *rc_ti = static_cast<RlcChannelTreeWidgetItem*>(ti);
- rc_ti->launchGraph(DIRECTION_DOWNLINK, cf_);
+ emit launchRLCGraph(true,
+ rc_ti->get_ueid(),
+ rc_ti->get_mode(),
+ rc_ti->get_channelType(),
+ rc_ti->get_channelId(),
+ DIRECTION_DOWNLINK);
}
}
diff --git a/ui/qt/lte_rlc_statistics_dialog.h b/ui/qt/lte_rlc_statistics_dialog.h
index cbfec3309b..8d83b68f02 100644
--- a/ui/qt/lte_rlc_statistics_dialog.h
+++ b/ui/qt/lte_rlc_statistics_dialog.h
@@ -39,6 +39,12 @@ public:
protected:
+signals:
+ void launchRLCGraph(bool channelKnown,
+ guint16 ueid, guint8 rlcMode,
+ guint16 channelType, guint16 channelId,
+ guint8 direction);
+
private:
// Extra controls needed for this dialog.
QCheckBox *useRLCFramesFromMacCheckBox_;
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index d83bd94777..be314ed24e 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -245,6 +245,9 @@ public slots:
void filterExpressionsChanged();
+ void launchRLCGraph(bool channelKnown, guint16 ueid, guint8 rlcMode,
+ guint16 channelType, guint16 channelId, guint8 direction);
+
private slots:
// Manually connected slots (no "on_<object>_<signal>").
diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp
index e5c366c06f..32786a08b9 100644
--- a/ui/qt/main_window_slots.cpp
+++ b/ui/qt/main_window_slots.cpp
@@ -3037,6 +3037,11 @@ void MainWindow::statCommandLteRlcStatistics(const char *arg, void *)
LteRlcStatisticsDialog *lte_rlc_stats_dlg = new LteRlcStatisticsDialog(*this, capture_file_, arg);
connect(lte_rlc_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
+ // N.B. It is necessary for the RLC Statistics window to launch the RLC graph in this way, to ensure
+ // that the goToPacket() signal/slot connection gets set up...
+ connect(lte_rlc_stats_dlg, SIGNAL(launchRLCGraph(bool, guint16, guint8, guint16, guint16, guint8)),
+ this, SLOT(launchRLCGraph(bool, guint16, guint8, guint16, guint16, guint8)));
+
lte_rlc_stats_dlg->show();
}
@@ -3045,12 +3050,26 @@ void MainWindow::on_actionTelephonyLteRlcStatistics_triggered()
statCommandLteRlcStatistics(NULL, NULL);
}
-void MainWindow::on_actionTelephonyLteRlcGraph_triggered()
+void MainWindow::launchRLCGraph(bool channelKnown,
+ guint16 ueid, guint8 rlcMode,
+ guint16 channelType, guint16 channelId, guint8 direction)
{
- LteRlcGraphDialog *lrg_dialog = new LteRlcGraphDialog(*this, capture_file_, false);
+ LteRlcGraphDialog *lrg_dialog = new LteRlcGraphDialog(*this, capture_file_, channelKnown);
+ connect(lrg_dialog, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
+ // This is a bit messy, but wanted to hide these parameters from users of
+ // on_actionTelephonyLteRlcGraph_triggered().
+ if (channelKnown) {
+ lrg_dialog->setChannelInfo(ueid, rlcMode, channelType, channelId, direction);
+ }
lrg_dialog->show();
}
+void MainWindow::on_actionTelephonyLteRlcGraph_triggered()
+{
+ // We don't yet know the channel.
+ launchRLCGraph(false, 0, 0, 0, 0, 0);
+}
+
void MainWindow::on_actionTelephonyMtp3Summary_triggered()
{
Mtp3SummaryDialog *mtp3s_dialog = new Mtp3SummaryDialog(*this, capture_file_);