diff options
-rw-r--r-- | docbook/wsug_graphics/ws-stats-conversations.png | bin | 250943 -> 240607 bytes | |||
-rw-r--r-- | docbook/wsug_src/WSUG_chapter_statistics.asciidoc | 13 | ||||
-rw-r--r-- | epan/column.c | 2 | ||||
-rw-r--r-- | ui/qt/capture_file.cpp | 8 | ||||
-rw-r--r-- | ui/qt/capture_file.h | 6 | ||||
-rw-r--r-- | ui/qt/conversation_dialog.cpp | 48 | ||||
-rw-r--r-- | ui/qt/conversation_dialog.h | 3 | ||||
-rw-r--r-- | ui/qt/traffic_table_dialog.cpp | 18 | ||||
-rw-r--r-- | ui/qt/traffic_table_dialog.h | 14 | ||||
-rw-r--r-- | ui/qt/traffic_table_dialog.ui | 26 | ||||
-rw-r--r-- | ui/traffic_table_ui.c | 1 | ||||
-rw-r--r-- | ui/traffic_table_ui.h | 1 |
12 files changed, 130 insertions, 10 deletions
diff --git a/docbook/wsug_graphics/ws-stats-conversations.png b/docbook/wsug_graphics/ws-stats-conversations.png Binary files differindex 763188a368..b37936b035 100644 --- a/docbook/wsug_graphics/ws-stats-conversations.png +++ b/docbook/wsug_graphics/ws-stats-conversations.png diff --git a/docbook/wsug_src/WSUG_chapter_statistics.asciidoc b/docbook/wsug_src/WSUG_chapter_statistics.asciidoc index 5255ef7ad0..d88a54b84e 100644 --- a/docbook/wsug_src/WSUG_chapter_statistics.asciidoc +++ b/docbook/wsug_src/WSUG_chapter_statistics.asciidoc @@ -141,10 +141,10 @@ description of the known endpoint types can be found in The conversations window is similar to the endpoint Window. See <<ChStatEndpointsWindow>> for a description of their common features. Along with addresses, packet counters, and byte counters the conversation window adds four -columns: the time in seconds between the start of the capture and the start of -the conversation (``Rel Start''), the duration of the conversation in seconds, and -the average bits (not bytes) per second in each direction. A timeline graph is -also drawn across the ``Rel Start'' and ``Duration'' columns. +columns: the start time of the conversation (``Rel Start'') or (``Abs Start''), +the duration of the conversation in seconds, and the average bits (not bytes) +per second in each direction. A timeline graph is also drawn across the +``Rel Start'' / ``Abs Start'' and ``Duration'' columns. .The ``Conversations'' window image::wsug_graphics/ws-stats-conversations.png[scaledwidth="100%"] @@ -154,7 +154,10 @@ Each row in the list shows the statistical values for exactly one conversation. _Name resolution_ will be done if selected in the window and if it is active for the specific protocol layer (MAC layer for the selected Ethernet endpoints page). _Limit to display filter_ will only show conversations matching the -current display filter. +current display filter. _Absolute start time_ switches the start time column +between relative (``Rel Start'') and absolute (``Abs Start'') times. Relative start +times match the ``Seconds Since Beginning of Capture'' time display format in the +packet list and absolute start times match the ``Time of Day'' display format. The button:[Copy] button will copy the list values to the clipboard in CSV (Comma Separated Values) or YAML format. The button:[Follow Stream...] button diff --git a/epan/column.c b/epan/column.c index 1f7b2fa518..2a67019591 100644 --- a/epan/column.c +++ b/epan/column.c @@ -48,7 +48,7 @@ col_format_to_string(const gint fmt) { "%At", /* 3) COL_ABS_TIME */ "%V", /* 4) COL_VSAN - !! DEPRECATED !!*/ "%B", /* 5) COL_CUMULATIVE_BYTES */ - "%Cus", /* 6 COL_CUSTOM */ + "%Cus", /* 6) COL_CUSTOM */ "%y", /* 7) COL_DCE_CALL */ "%Tt", /* 8) COL_DELTA_TIME */ "%Gt", /* 9) COL_DELTA_TIME_DIS */ diff --git a/ui/qt/capture_file.cpp b/ui/qt/capture_file.cpp index 2df533ea75..2c04a35261 100644 --- a/ui/qt/capture_file.cpp +++ b/ui/qt/capture_file.cpp @@ -99,6 +99,14 @@ struct _packet_info *CaptureFile::packetInfo() return NULL; } +int CaptureFile::timestampPrecision() +{ + if (capFile() && capFile()->wth) { + return wtap_file_tsprec(capFile()->wth); + } + return WTAP_TSPREC_UNKNOWN; +} + void CaptureFile::retapPackets() { if (cap_file_) { diff --git a/ui/qt/capture_file.h b/ui/qt/capture_file.h index 033fa06efa..61487032c0 100644 --- a/ui/qt/capture_file.h +++ b/ui/qt/capture_file.h @@ -76,6 +76,12 @@ public: */ struct _packet_info *packetInfo(); + /** Timestamp precision for the current file. + * @return One of the WTAP_TSPREC_x values defined in wiretap/wtap.h, + * or WTAP_TSPREC_UNKNOWN if no file is open. + */ + int timestampPrecision(); + /** Reload the capture file */ void reload(); diff --git a/ui/qt/conversation_dialog.cpp b/ui/qt/conversation_dialog.cpp index 4ace205e19..8810223790 100644 --- a/ui/qt/conversation_dialog.cpp +++ b/ui/qt/conversation_dialog.cpp @@ -35,6 +35,7 @@ #include "wireshark_application.h" #include <QCheckBox> +#include <QDateTime> #include <QDialogButtonBox> #include <QPushButton> @@ -58,6 +59,9 @@ // Fixed bugs: // - Friendly unit displays https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9231 // - Misleading bps calculation https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8703 +// - Show Absolute time in conversation tables https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=11618 +// - The value of 'Rel start' and 'Duration' in "Conversations" no need too precise https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=12803 + static const QString table_name_ = QObject::tr("Conversation"); ConversationDialog::ConversationDialog(QWidget &parent, CaptureFile &cf, int cli_proto_id, const char *filter) : @@ -71,6 +75,8 @@ ConversationDialog::ConversationDialog(QWidget &parent, CaptureFile &cf, int cli graph_bt_->setToolTip(tr("Graph a TCP conversation.")); connect(graph_bt_, SIGNAL(clicked()), this, SLOT(graphTcp())); + absoluteTimeCheckBox()->show(); + addProgressFrame(&parent); QList<int> conv_protos; @@ -163,6 +169,9 @@ bool ConversationDialog::addTrafficTable(register_ct_t* table) this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType))); connect(nameResolutionCheckBox(), SIGNAL(toggled(bool)), conv_tree, SLOT(setNameResolutionEnabled(bool))); + connect(absoluteTimeCheckBox(), SIGNAL(toggled(bool)), + conv_tree, SLOT(updateStartTime(bool))); + // XXX Move to ConversationTreeWidget ctor? QByteArray filter_utf8; @@ -365,9 +374,31 @@ public: case CONV_COLUMN_BYTES_BA: return gchar_free_to_qstring(format_size(conv_item->rx_bytes, format_size_unit_none|format_size_prefix_si)); case CONV_COLUMN_START: - return QString::number(nstime_to_sec(&conv_item->start_time), 'f', 9); + { + bool use_ns = treeWidget()->window()->property("nanosecond_precision").toBool(); + int width = use_ns ? 9 : 6; + + if (treeWidget()->window()->property("absolute_start_time").toBool()) { + nstime_t *abs_time = &conv_item->start_abs_time; + QDateTime abs_dt = QDateTime::fromMSecsSinceEpoch(nstime_to_msec(abs_time)); + return QString("%1.%2") + // Mimic column-utils:set_abs_time as best we can + .arg(abs_dt.toString("hh:mm:ss")) + .arg(use_ns ? abs_time->nsecs : abs_time->nsecs / 1000, width, 10, QChar('0')); + } + + return QString::number(nstime_to_sec(&conv_item->start_time), 'f', width); + } case CONV_COLUMN_DURATION: - return QString::number(duration, 'f', 6); + { + // The GTK+ UI uses 9 digit precision for the start time and 4 for the duration. + // Do the same here and above for non-nanosecond precision and add a couple + // of digits for nanosecond precision. + bool use_ns = treeWidget()->window()->property("nanosecond_precision").toBool(); + int width = use_ns ? 6 : 4; + + return QString::number(duration, 'f', width); + } case CONV_COLUMN_BPS_AB: if (duration > min_bw_calc_duration_) { bps_ab = gchar_free_to_qstring(format_size((gint64) conv_item->tx_bytes * 8 / duration, format_size_unit_none|format_size_prefix_si)); @@ -665,6 +696,19 @@ void ConversationTreeWidget::tapDraw(void *conv_hash_ptr) conv_tree->updateItems(); } +void ConversationTreeWidget::updateStartTime(bool absolute) +{ + headerItem()->setText(CONV_COLUMN_START, absolute + ? conv_abs_start_title + : conv_column_titles[CONV_COLUMN_START]); + + dataChanged(QModelIndex(), QModelIndex()); + + if (topLevelItemCount() > 0) { + resizeColumnToContents(CONV_COLUMN_START); + } +} + QMap<FilterAction::ActionDirection, conv_direction_e> fad_to_cd_; void ConversationTreeWidget::initDirectionMap() diff --git a/ui/qt/conversation_dialog.h b/ui/qt/conversation_dialog.h index d962684ac3..1aeaf39a7a 100644 --- a/ui/qt/conversation_dialog.h +++ b/ui/qt/conversation_dialog.h @@ -38,6 +38,9 @@ public: double minRelStartTime() { return min_rel_start_time_; } double maxRelStopTime() { return max_rel_stop_time_; } +public slots: + void updateStartTime(bool absolute); + private: void initDirectionMap(); void updateItems(); diff --git a/ui/qt/traffic_table_dialog.cpp b/ui/qt/traffic_table_dialog.cpp index ba43afd52f..c81fc1bf2f 100644 --- a/ui/qt/traffic_table_dialog.cpp +++ b/ui/qt/traffic_table_dialog.cpp @@ -56,12 +56,14 @@ TrafficTableDialog::TrafficTableDialog(QWidget &parent, CaptureFile &cf, const c ui(new Ui::TrafficTableDialog), cap_file_(cf), file_closed_(false), - filter_(filter) + filter_(filter), + nanosecond_timestamps_(false) { ui->setupUi(this); loadGeometry(parent.width(), parent.height() * 3 / 4); ui->enabledTypesPushButton->setText(tr("%1 Types").arg(table_name)); + ui->absoluteTimeCheckBox->hide(); setWindowSubtitle(QString("%1s").arg(table_name)); QMenu *copy_menu = new QMenu(); @@ -78,6 +80,10 @@ TrafficTableDialog::TrafficTableDialog(QWidget &parent, CaptureFile &cf, const c ui->enabledTypesPushButton->setMenu(&traffic_type_menu_); ui->trafficTableTabWidget->setFocus(); + if (cf.timestampPrecision() == WTAP_TSPREC_NSEC) { + nanosecond_timestamps_ = true; + } + connect(wsApp, SIGNAL(addressResolutionChanged()), this, SLOT(currentTabChanged())); connect(wsApp, SIGNAL(addressResolutionChanged()), this, SLOT(updateWidgets())); connect(ui->trafficTableTabWidget, SIGNAL(currentChanged(int)), @@ -93,6 +99,11 @@ TrafficTableDialog::~TrafficTableDialog() delete ui; } +bool TrafficTableDialog::absoluteStartTime() +{ + return absoluteTimeCheckBox()->isChecked(); +} + const QList<int> TrafficTableDialog::defaultProtos() const { // Reasonable defaults? @@ -144,6 +155,11 @@ QCheckBox *TrafficTableDialog::nameResolutionCheckBox() const return ui->nameResolutionCheckBox; } +QCheckBox *TrafficTableDialog::absoluteTimeCheckBox() const +{ + return ui->absoluteTimeCheckBox; +} + QPushButton *TrafficTableDialog::enabledTypesPushButton() const { return ui->enabledTypesPushButton; diff --git a/ui/qt/traffic_table_dialog.h b/ui/qt/traffic_table_dialog.h index 5abe5b2a24..9d46c77906 100644 --- a/ui/qt/traffic_table_dialog.h +++ b/ui/qt/traffic_table_dialog.h @@ -103,6 +103,8 @@ signals: class TrafficTableDialog : public WiresharkDialog { Q_OBJECT + Q_PROPERTY(bool absolute_start_time READ absoluteStartTime) + Q_PROPERTY(bool nanosecond_timestamps READ nanosecondTimestamps) public: /** Create a new conversation window. @@ -115,6 +117,16 @@ public: explicit TrafficTableDialog(QWidget &parent, CaptureFile &cf, const char *filter = NULL, const QString &table_name = tr("Unknown")); ~TrafficTableDialog(); + /** Use absolute start times. + * @return true if the "Absolute start time" checkbox is checked, false otherwise. + */ + bool absoluteStartTime(); + + /** Use nanosecond timestamps. + * @return true if the current capture file uses nanosecond timestamps, false otherwise. + */ + bool nanosecondTimestamps() { return nanosecond_timestamps_; } + public slots: signals: @@ -143,6 +155,7 @@ protected: QTabWidget *trafficTableTabWidget() const; QCheckBox *displayFilterCheckBox() const; QCheckBox *nameResolutionCheckBox() const; + QCheckBox *absoluteTimeCheckBox() const; QPushButton *enabledTypesPushButton() const; protected slots: @@ -151,6 +164,7 @@ protected slots: private: QString window_name_; + bool nanosecond_timestamps_; QList<QVariant> curTreeRowData(int row) const; diff --git a/ui/qt/traffic_table_dialog.ui b/ui/qt/traffic_table_dialog.ui index b10dd41bac..11fe478282 100644 --- a/ui/qt/traffic_table_dialog.ui +++ b/ui/qt/traffic_table_dialog.ui @@ -15,7 +15,7 @@ <widget class="QTabWidget" name="trafficTableTabWidget"/> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,1,0"> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0,1,0"> <item> <widget class="QCheckBox" name="nameResolutionCheckBox"> <property name="toolTip"> @@ -50,6 +50,29 @@ </widget> </item> <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QCheckBox" name="absoluteTimeCheckBox"> + <property name="toolTip"> + <string><html><head/><body><p>Show absolute times in the start time column.</p></body></html></string> + </property> + <property name="text"> + <string>Absolute start time</string> + </property> + </widget> + </item> + <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -83,6 +106,7 @@ </item> </layout> </widget> + <resources/> <connections> <connection> <sender>buttonBox</sender> diff --git a/ui/traffic_table_ui.c b/ui/traffic_table_ui.c index fb37ab74c6..69771b0c10 100644 --- a/ui/traffic_table_ui.c +++ b/ui/traffic_table_ui.c @@ -65,6 +65,7 @@ const char *conv_column_titles[CONV_NUM_COLUMNS] = { const char *conv_conn_a_title = "Connection A"; const char *conv_conn_b_title = "Connection B"; +const char *conv_abs_start_title = "Abs Start"; const char *endp_column_titles[ENDP_NUM_COLUMNS] = { "Address", diff --git a/ui/traffic_table_ui.h b/ui/traffic_table_ui.h index 3edf13b0fd..66e711a53a 100644 --- a/ui/traffic_table_ui.h +++ b/ui/traffic_table_ui.h @@ -54,6 +54,7 @@ typedef enum { extern const char *conv_column_titles[CONV_NUM_COLUMNS]; extern const char *conv_conn_a_title; extern const char *conv_conn_b_title; +extern const char *conv_abs_start_title; typedef enum { |