diff options
author | Gerald Combs <gerald@wireshark.org> | 2016-05-19 11:21:02 +0900 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2016-05-25 06:36:25 +0000 |
commit | 6952c1342a7c4ff1828e0bc1a36cfcfd394ee923 (patch) | |
tree | 433370041cf427f46d6a4d4c56d95726e93ec686 /ui | |
parent | bf628988b655895ef429fa835e77c5fdca9a901b (diff) |
Qt: Add Time and Comment labels to the sequence diagram.
Add "Time" and "Comment" labels to the sequence diagram similar to the
GTK+ UI. Draw a border around the diagram as well.
Widen the default spacing and set it to a simple em-width multiple.
Fix our port number alignment.
Copy over the sequence diagram colors from the GTK+ UI and add them to
ColorUtils. Color sequences according to their respective conversation
numbers.
To do:
- Add zoom.
Ping-Bug: 12419
Change-Id: I3f9b4ffbfcc34aae1c38e303cd36ff207be247b1
Reviewed-on: https://code.wireshark.org/review/15554
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'ui')
-rw-r--r-- | ui/qt/color_utils.cpp | 70 | ||||
-rw-r--r-- | ui/qt/color_utils.h | 8 | ||||
-rw-r--r-- | ui/qt/sequence_diagram.cpp | 69 | ||||
-rw-r--r-- | ui/qt/sequence_dialog.cpp | 81 | ||||
-rw-r--r-- | ui/qt/sequence_dialog.h | 4 |
5 files changed, 157 insertions, 75 deletions
diff --git a/ui/qt/color_utils.cpp b/ui/qt/color_utils.cpp index 204aa59f80..cb1bdb7ac6 100644 --- a/ui/qt/color_utils.cpp +++ b/ui/qt/color_utils.cpp @@ -31,24 +31,6 @@ const QColor ColorUtils::expert_color_error = QColor ( 0xff, 0x5c, 0x5c ); const QColor ColorUtils::expert_color_foreground = QColor ( 0x00, 0x00, 0x00 ); /* Black */ const QColor ColorUtils::hidden_proto_item = QColor ( 0x44, 0x44, 0x44 ); /* Gray */ -// Available colors -// XXX - Add custom -const QList<QRgb> ColorUtils::graph_colors_ = QList<QRgb>() - << tango_aluminium_6 // Bar outline (use black instead)? - << tango_sky_blue_5 - << tango_butter_6 - << tango_chameleon_5 - << tango_scarlet_red_5 - << tango_plum_5 - << tango_orange_6 - << tango_aluminium_3 - << tango_sky_blue_3 - << tango_butter_3 - << tango_chameleon_3 - << tango_scarlet_red_3 - << tango_plum_3 - << tango_orange_3; - ColorUtils::ColorUtils(QObject *parent) : QObject(parent) { @@ -109,6 +91,58 @@ QRgb ColorUtils::alphaBlend(const QBrush &brush1, const QBrush &brush2, qreal al return alphaBlend(brush1.color(), brush2.color(), alpha); } +QList<QRgb> ColorUtils::graph_colors_; +const QList<QRgb> ColorUtils::graphColors() +{ + if (graph_colors_.isEmpty()) { + // Available graph colors + // XXX - Add custom + graph_colors_ = QList<QRgb>() + << tango_aluminium_6 // Bar outline (use black instead)? + << tango_sky_blue_5 + << tango_butter_6 + << tango_chameleon_5 + << tango_scarlet_red_5 + << tango_plum_5 + << tango_orange_6 + << tango_aluminium_3 + << tango_sky_blue_3 + << tango_butter_3 + << tango_chameleon_3 + << tango_scarlet_red_3 + << tango_plum_3 + << tango_orange_3; + } + return graph_colors_; +} + +QRgb ColorUtils::graphColor(int item) +{ + if (graph_colors_.isEmpty()) graphColors(); // Init list. + return graph_colors_[item % graph_colors_.size()]; +} + +QList<QRgb> ColorUtils::sequence_colors_; +QRgb ColorUtils::sequenceColor(int item) +{ + if (sequence_colors_.isEmpty()) { + // Available sequence colors. Copied from gtk/graph_analysis.c. + // XXX - Add custom? + sequence_colors_ = QList<QRgb>() + << qRgb(144, 238, 144) + << qRgb(255, 160, 123) + << qRgb(255, 182, 193) + << qRgb(250, 250, 210) + << qRgb(255, 255, 52) + << qRgb(103, 205, 170) + << qRgb(224, 255, 255) + << qRgb(176, 196, 222) + << qRgb(135, 206, 254) + << qRgb(211, 211, 211); + } + return sequence_colors_[item % sequence_colors_.size()]; +} + /* * Editor modelines * diff --git a/ui/qt/color_utils.h b/ui/qt/color_utils.h index e9b1806363..3dceadf474 100644 --- a/ui/qt/color_utils.h +++ b/ui/qt/color_utils.h @@ -53,15 +53,17 @@ public: static const QColor expert_color_foreground; /* black */ static const QColor hidden_proto_item; /* gray */ - static const QList<QRgb> graphColors() { return graph_colors_; } - static QRgb graphColor(int item) { return graph_colors_[item % graph_colors_.size()]; } + static const QList<QRgb> graphColors(); + static QRgb graphColor(int item); + static QRgb sequenceColor(int item); signals: public slots: private: - static const QList<QRgb> graph_colors_; + static QList<QRgb> graph_colors_; + static QList<QRgb> sequence_colors_; }; void color_filter_qt_add_cb(color_filter_t *colorf, gpointer user_data); diff --git a/ui/qt/sequence_diagram.cpp b/ui/qt/sequence_diagram.cpp index 1beab92659..fa1ace2d54 100644 --- a/ui/qt/sequence_diagram.cpp +++ b/ui/qt/sequence_diagram.cpp @@ -25,6 +25,7 @@ #include "ui/tap-sequence-analysis.h" +#include "color_utils.h" #include "qt_ui_utils.h" #include <QFont> @@ -187,7 +188,7 @@ void SequenceDiagram::draw(QCPPainter *painter) QPen fg_pen; qreal alpha = 0.50; - // Lifelines (node lines) + // Lifelines (node lines). Will likely be overdrawn below. painter->save(); painter->setOpacity(alpha); fg_pen = mainPen(); @@ -208,35 +209,40 @@ void SequenceDiagram::draw(QCPPainter *painter) double cur_key = it.key(); seq_analysis_item_t *sai = it.value().value; QPen fg_pen(mainPen()); + QColor bg_color; if (sai->frame_number == selected_packet_) { - // Highlighted background - painter->save(); - QRect bg_rect( - QPoint(coordsToPixels(cur_key - 0.5, value_axis_->range().lower).toPoint()), - QPoint(coordsToPixels(cur_key + 0.5, value_axis_->range().upper).toPoint())); QPalette sel_pal; - painter->fillRect(bg_rect, sel_pal.brush(QPalette::Highlight)); fg_pen.setColor(sel_pal.color(QPalette::HighlightedText)); + bg_color = sel_pal.color(QPalette::Highlight); + } else { + fg_pen.setColor(Qt::black); + bg_color = ColorUtils::sequenceColor(sai->conv_num); + } - // Highlighted lifelines - painter->save(); - QPen hl_pen = fg_pen; - hl_pen.setStyle(Qt::DashLine); - painter->setPen(hl_pen); - painter->setOpacity(alpha); - for (int ll_x = value_axis_->range().lower; ll_x < value_axis_->range().upper; ll_x++) { - // Only draw where we have arrows. - if (ll_x < 0 || ll_x >= value_axis_->tickVector().size()) continue; - QPoint ll_start(coordsToPixels(cur_key - 0.5, ll_x).toPoint()); - QPoint ll_end(coordsToPixels(cur_key + 0.5, ll_x).toPoint()); - hl_pen.setDashOffset(bg_rect.top() - ll_start.x()); - painter->drawLine(ll_start, ll_end); - } - painter->restore(); - - painter->restore(); + // Highlighted background +// painter->save(); + QRect bg_rect( + QPoint(coordsToPixels(cur_key - 0.5, value_axis_->range().lower).toPoint()), + QPoint(coordsToPixels(cur_key + 0.5, value_axis_->range().upper).toPoint())); + painter->fillRect(bg_rect, bg_color); +// painter->restore(); + + // Highlighted lifelines + painter->save(); + QPen hl_pen = fg_pen; + hl_pen.setStyle(Qt::DashLine); + painter->setPen(hl_pen); + painter->setOpacity(alpha); + for (int ll_x = value_axis_->range().lower; ll_x < value_axis_->range().upper; ll_x++) { + // Only draw where we have arrows. + if (ll_x < 0 || ll_x >= value_axis_->tickVector().size()) continue; + QPoint ll_start(coordsToPixels(cur_key - 0.5, ll_x).toPoint()); + QPoint ll_end(coordsToPixels(cur_key + 0.5, ll_x).toPoint()); + hl_pen.setDashOffset(bg_rect.top() - ll_start.x()); + painter->drawLine(ll_start, ll_end); } + painter->restore(); if (cur_key < key_axis_->range().lower || cur_key > key_axis_->range().upper) { continue; @@ -283,14 +289,17 @@ void SequenceDiagram::draw(QCPPainter *painter) painter->drawText(text_pt, arrow_label); if (sai->port_src && sai->port_dst) { - QString port_num = QString::number(sai->port_src); - text_pt = QPoint(arrow_start.x() - en_w - (cfm.width(port_num) * dir_mul), + int left_x = dir_mul > 0 ? arrow_start.x() : arrow_end.x(); + int right_x = dir_mul > 0 ? arrow_end.x() : arrow_start.x(); + QString port_left = QString::number(dir_mul > 0 ? sai->port_src : sai->port_dst); + QString port_right = QString::number(dir_mul > 0 ? sai->port_dst : sai->port_src); + + text_pt = QPoint(left_x - en_w - cfm.width(port_left), arrow_start.y() + (en_w / 2)); - painter->drawText(text_pt, port_num); + painter->drawText(text_pt, port_left); - port_num = QString::number(sai->port_dst); - text_pt.setX(arrow_end.x() - en_w + (cfm.width(port_num) * dir_mul)); - painter->drawText(text_pt, port_num); + text_pt.setX(right_x + en_w); + painter->drawText(text_pt, port_right); } painter->restore(); } diff --git a/ui/qt/sequence_dialog.cpp b/ui/qt/sequence_dialog.cpp index f2776fca19..4bd5d9d548 100644 --- a/ui/qt/sequence_dialog.cpp +++ b/ui/qt/sequence_dialog.cpp @@ -27,6 +27,7 @@ #include "wsutil/nstime.h" #include "wsutil/utf8_entities.h" +#include "color_utils.h" #include "progress_frame.h" #include "sequence_diagram.h" #include "wireshark_application.h" @@ -37,6 +38,9 @@ #include <QPoint> // To do: +// - Add zoom controls. +// - Limit dragging to valid ranges. +// - Handle trackpad and mouse wheel scrolling. // - Add UTF8 to text dump // - Save to XMI? http://www.umlgraph.org/ // - Time: abs vs delta @@ -46,8 +50,6 @@ // - Change line_style to seq_type (i.e. draw ACKs dashed) // - Create WSGraph subclasses with common behavior. // - Help button and text -// - Diagram shrinks when you click on it on retina displays. -// - Add zoom controls. SequenceDialog::SequenceDialog(QWidget &parent, CaptureFile &cf, SequenceInfo *info) : WiresharkDialog(parent, cf), @@ -55,7 +57,7 @@ SequenceDialog::SequenceDialog(QWidget &parent, CaptureFile &cf, SequenceInfo *i info_(info), num_items_(0), packet_num_(0), - node_label_w_(20) + sequence_w_(1) { ui->setupUi(this); loadGeometry(parent.width(), parent.height() * 4 / 5); @@ -80,9 +82,32 @@ SequenceDialog::SequenceDialog(QWidget &parent, CaptureFile &cf, SequenceInfo *i sp->xAxis->setPadding(0); sp->xAxis->setLabelPadding(0); sp->xAxis->setTickLabelPadding(0); + + 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); + sp->xAxis2->setVisible(true); sp->yAxis2->setVisible(true); + key_text_ = new QCPItemText(sp); + key_text_->setText(tr("Time")); + sp->addItem(key_text_); + + key_text_->setPositionAlignment(Qt::AlignRight | Qt::AlignBottom); + key_text_->position->setType(QCPItemPosition::ptAbsolute); + key_text_->setClipToAxisRect(false); + + comment_text_ = new QCPItemText(sp); + comment_text_->setText(tr("Comment")); + sp->addItem(comment_text_); + + comment_text_->setPositionAlignment(Qt::AlignLeft | Qt::AlignBottom); + comment_text_->position->setType(QCPItemPosition::ptAbsolute); + comment_text_->setClipToAxisRect(false); + one_em_ = QFontMetrics(sp->yAxis->labelFont()).height(); ui->horizontalScrollBar->setSingleStep(100 / one_em_); ui->verticalScrollBar->setSingleStep(100 / one_em_); @@ -134,8 +159,6 @@ SequenceDialog::SequenceDialog(QWidget &parent, CaptureFile &cf, SequenceInfo *i connect(this, SIGNAL(goToPacket(int)), seq_diagram_, SLOT(setSelectedPacket(int))); disconnect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - - QTimer::singleShot(0, this, SLOT(fillDiagram())); } SequenceDialog::~SequenceDialog() @@ -151,7 +174,7 @@ void SequenceDialog::updateWidgets() void SequenceDialog::showEvent(QShowEvent *) { - resetAxes(); + QTimer::singleShot(0, this, SLOT(fillDiagram())); } void SequenceDialog::resizeEvent(QResizeEvent *) @@ -350,18 +373,8 @@ void SequenceDialog::fillDiagram() seq_diagram_->setData(info_->sainfo()); } - QFontMetrics vfm = QFontMetrics(sp->xAxis2->labelFont()); - char* addr_str; - node_label_w_ = 0; - for (guint i = 0; i < info_->sainfo()->num_nodes; i++) { - addr_str = address_to_display(NULL, &(info_->sainfo()->nodes[i])); - int label_w = vfm.width(addr_str); - if (node_label_w_ < label_w) { - node_label_w_ = label_w; - } - wmem_free(NULL, addr_str); - } - node_label_w_ = (node_label_w_ * 3 / 4) + one_em_; + QFontMetrics fm = QFontMetrics(sp->xAxis2->labelFont()); + sequence_w_ = fm.height() * 15 ; // Arbitrary mouseMoved(NULL); resetAxes(); @@ -394,6 +407,7 @@ void SequenceDialog::resetAxes(bool keep_lower) if (!info_->sainfo()) return; QCustomPlot *sp = ui->sequencePlot; + // Allow space for labels on the top and port numbers on the left. double top_pos = -1.0, left_pos = -0.5; if (keep_lower) { @@ -401,21 +415,42 @@ void SequenceDialog::resetAxes(bool keep_lower) left_pos = sp->xAxis2->range().lower; } - double range_ratio = sp->xAxis2->axisRect()->width() / node_label_w_; - sp->xAxis2->setRange(left_pos, range_ratio + left_pos); + double range_span = sp->viewport().width() / sequence_w_; + sp->xAxis2->setRange(left_pos, range_span + left_pos); - range_ratio = sp->yAxis->axisRect()->height() / (one_em_ * 1.5); - sp->yAxis->setRange(top_pos, range_ratio + top_pos); + range_span = sp->axisRect()->height() / (one_em_ * 1.5); + sp->yAxis->setRange(top_pos, range_span + top_pos); double rmin = sp->xAxis2->range().size() / 2; ui->horizontalScrollBar->setRange((rmin - 0.5) * 100, (info_->sainfo()->num_nodes - 0.5 - rmin) * 100); xAxisChanged(sp->xAxis2->range()); + ui->horizontalScrollBar->setValue(ui->horizontalScrollBar->minimum()); // Shouldn't be needed. rmin = (sp->yAxis->range().size() / 2); ui->verticalScrollBar->setRange((rmin - 1.0) * 100, (num_items_ - 0.5 - rmin) * 100); yAxisChanged(sp->yAxis->range()); - sp->replot(); + // 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(); + key_text_->position->setCoords(axis_rect.left() + - sp->yAxis->padding() + - sp->yAxis->tickLabelPadding() + - sp->yAxis->offset(), + axis_rect.top()); + comment_text_->position->setCoords(axis_rect.right() + + sp->yAxis2->padding() + + sp->yAxis2->tickLabelPadding() + + sp->yAxis2->offset(), + axis_rect.top()); + + sp->replot(QCustomPlot::rpHint); } void SequenceDialog::on_resetButton_clicked() diff --git a/ui/qt/sequence_dialog.h b/ui/qt/sequence_dialog.h index 59505583c6..e091b583b0 100644 --- a/ui/qt/sequence_dialog.h +++ b/ui/qt/sequence_dialog.h @@ -108,8 +108,10 @@ private: int num_items_; guint32 packet_num_; double one_em_; - int node_label_w_; + int sequence_w_; QMenu ctx_menu_; + QCPItemText *key_text_; + QCPItemText *comment_text_; void panAxes(int x_pixels, int y_pixels); void resetAxes(bool keep_lower = false); |