summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docbook/wsug_graphics/ws-stats-conversations.pngbin104894 -> 250943 bytes
-rw-r--r--docbook/wsug_graphics/ws-stats-hierarchy.pngbin21480 -> 181226 bytes
-rw-r--r--docbook/wsug_src/WSUG_chapter_statistics.asciidoc24
-rw-r--r--ui/qt/CMakeLists.txt2
-rw-r--r--ui/qt/Makefile.am2
-rw-r--r--ui/qt/conversation_dialog.cpp70
-rw-r--r--ui/qt/conversation_dialog.h4
-rw-r--r--ui/qt/percent_bar_delegate.cpp26
-rw-r--r--ui/qt/timeline_delegate.cpp103
-rw-r--r--ui/qt/timeline_delegate.h80
10 files changed, 286 insertions, 25 deletions
diff --git a/docbook/wsug_graphics/ws-stats-conversations.png b/docbook/wsug_graphics/ws-stats-conversations.png
index 3655e50657..763188a368 100644
--- a/docbook/wsug_graphics/ws-stats-conversations.png
+++ b/docbook/wsug_graphics/ws-stats-conversations.png
Binary files differ
diff --git a/docbook/wsug_graphics/ws-stats-hierarchy.png b/docbook/wsug_graphics/ws-stats-hierarchy.png
index 3dbb93f8e7..1fb0860ed9 100644
--- a/docbook/wsug_graphics/ws-stats-hierarchy.png
+++ b/docbook/wsug_graphics/ws-stats-hierarchy.png
Binary files differ
diff --git a/docbook/wsug_src/WSUG_chapter_statistics.asciidoc b/docbook/wsug_src/WSUG_chapter_statistics.asciidoc
index 3755159d90..5255ef7ad0 100644
--- a/docbook/wsug_src/WSUG_chapter_statistics.asciidoc
+++ b/docbook/wsug_src/WSUG_chapter_statistics.asciidoc
@@ -35,7 +35,6 @@ These statistics range from general information about the loaded capture file
- Various other protocol specific statistics.
-
[NOTE]
====
The protocol specific statistics require detailed knowledge about the specific
@@ -45,11 +44,11 @@ be pretty hard to understand.
[[ChStatSummary]]
-=== The _Summary_ window
+=== The ``Summary'' window
General statistics about the current capture file.
-.The "Summary" window
+.The ``Summary'' window
image::wsug_graphics/ws-stats-summary.png[]
* __File__: general information about the capture file.
@@ -73,12 +72,12 @@ image::wsug_graphics/ws-stats-summary.png[]
[[ChStatHierarchy]]
-=== The "Protocol Hierarchy" window
+=== The ``Protocol Hierarchy'' window
The protocol hierarchy of the captured packets.
-.The "Protocol Hierarchy" window
-image::wsug_graphics/ws-stats-hierarchy.png[]
+.The ``Protocol Hierarchy'' window
+image::wsug_graphics/ws-stats-hierarchy.png[scaledwidth="100%"]
This is a tree of all the protocols in the capture. Each row contains the
statistical values of one protocol. Two of the columns (_Percent Packets_ and
@@ -143,10 +142,11 @@ 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.
+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.
-.The "Conversations" window
+.The ``Conversations'' window
image::wsug_graphics/ws-stats-conversations.png[scaledwidth="100%"]
Each row in the list shows the statistical values for exactly one conversation.
@@ -241,7 +241,7 @@ will be received by some or all of the listed unicast endpoints.
[[ChStatEndpointsWindow]]
-==== The "Endpoints" window
+==== The ``Endpoints'' window
This window shows statistics about the endpoints captured.
@@ -281,13 +281,13 @@ it before (or while) you are doing a live capture.
[[ChStatIOGraphs]]
-=== The "IO Graphs" window
+=== The ``IO Graphs'' window
User configurable graph of the captured network packets.
You can define up to five differently colored graphs.
-.The "IO Graphs" window
+.The ``IO Graphs'' window
image::wsug_graphics/ws-stats-iographs.png[]
The user can configure the following things:
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index 6b2d9f1fbf..5d7d06a223 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -146,6 +146,7 @@ set(WIRESHARK_QT_HEADERS
tap_parameter_dialog.h
tcp_stream_dialog.h
time_shift_dialog.h
+ timeline_delegate.h
traffic_table_dialog.h
uat_dialog.h
voip_calls_dialog.h
@@ -301,6 +302,7 @@ set(WIRESHARK_QT_SRC
tap_parameter_dialog.cpp
tcp_stream_dialog.cpp
time_shift_dialog.cpp
+ timeline_delegate.cpp
traffic_table_dialog.cpp
uat_dialog.cpp
voip_calls_dialog.cpp
diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am
index 8385f35c6e..f8971397d9 100644
--- a/ui/qt/Makefile.am
+++ b/ui/qt/Makefile.am
@@ -278,6 +278,7 @@ MOC_HDRS = \
tap_parameter_dialog.h \
tcp_stream_dialog.h \
time_shift_dialog.h \
+ timeline_delegate.h \
traffic_table_dialog.h \
uat_dialog.h \
voip_calls_dialog.h \
@@ -545,6 +546,7 @@ WIRESHARK_QT_SRC = \
tap_parameter_dialog.cpp \
tcp_stream_dialog.cpp \
time_shift_dialog.cpp \
+ timeline_delegate.cpp \
traffic_table_dialog.cpp \
uat_dialog.cpp \
voip_calls_dialog.cpp \
diff --git a/ui/qt/conversation_dialog.cpp b/ui/qt/conversation_dialog.cpp
index bf6dce50eb..4ace205e19 100644
--- a/ui/qt/conversation_dialog.cpp
+++ b/ui/qt/conversation_dialog.cpp
@@ -31,6 +31,7 @@
#include "wsutil/str_util.h"
#include "qt_ui_utils.h"
+#include "timeline_delegate.h"
#include "wireshark_application.h"
#include <QCheckBox>
@@ -153,6 +154,9 @@ bool ConversationDialog::addTrafficTable(register_ct_t* table)
trafficTableTabWidget()->addTab(conv_tree, table_name);
+ conv_tree->setItemDelegateForColumn(CONV_COLUMN_START, new TimelineDelegate(conv_tree));
+ conv_tree->setItemDelegateForColumn(CONV_COLUMN_DURATION, new TimelineDelegate(conv_tree));
+
connect(conv_tree, SIGNAL(titleChanged(QWidget*,QString)),
this, SLOT(setTabText(QWidget*,QString)));
connect(conv_tree, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
@@ -325,14 +329,20 @@ public:
conv_array_(conv_array),
conv_idx_(conv_idx),
resolve_names_ptr_(resolve_names_ptr)
- {}
+ {
+ QString timeline_tt = QObject::tr("Bars show the relative timeline for each conversation.");
+ setToolTip(CONV_COLUMN_START, timeline_tt);
+ setToolTip(CONV_COLUMN_DURATION, timeline_tt);
+ }
conv_item_t *convItem() {
return &g_array_index(conv_array_, conv_item_t, conv_idx_);
}
virtual QVariant data(int column, int role) const {
- if (role == Qt::DisplayRole) {
+ switch (role) {
+ case Qt::DisplayRole:
+ {
// Column text cooked representation.
conv_item_t *conv_item = &g_array_index(conv_array_, conv_item_t, conv_idx_);
@@ -371,6 +381,37 @@ public:
default:
return colData(column, resolve_names).toString();
}
+ break;
+ }
+ case Qt::UserRole:
+ {
+ if (column != CONV_COLUMN_START && column != CONV_COLUMN_DURATION) break;
+
+ ConversationTreeWidget *ctw = qobject_cast<ConversationTreeWidget *>(treeWidget());
+ if (!ctw) break;
+
+ conv_item_t *conv_item = &g_array_index(conv_array_, conv_item_t, conv_idx_);
+ double start_time = nstime_to_sec(&conv_item->start_time);
+ double stop_time = nstime_to_sec(&conv_item->stop_time);
+
+ double span_s = ctw->maxRelStopTime() - ctw->minRelStartTime();
+ if (span_s <= 0) break;
+ int start_px = ctw->columnWidth(CONV_COLUMN_START);
+ int column_px = start_px + ctw->columnWidth(CONV_COLUMN_DURATION);
+
+ struct timeline_span span_px;
+ span_px.start = ((start_time - ctw->minRelStartTime()) * column_px) / span_s;
+ span_px.width = ((stop_time - start_time) * column_px) / span_s;
+
+ if (column == CONV_COLUMN_DURATION) {
+ span_px.start -= start_px;
+ }
+ return qVariantFromValue(span_px);
+
+ break;
+ }
+ default:
+ break;
}
return QTreeWidgetItem::data(column, role);
}
@@ -498,7 +539,9 @@ private:
// TrafficTableTreeWidget / QTreeWidget subclass that allows tapping
ConversationTreeWidget::ConversationTreeWidget(QWidget *parent, register_ct_t* table) :
- TrafficTableTreeWidget(parent, table)
+ TrafficTableTreeWidget(parent, table),
+ min_rel_start_time_(0),
+ max_rel_stop_time_(0)
{
setColumnCount(CONV_NUM_COLUMNS);
setUniformRowHeights(true);
@@ -609,6 +652,8 @@ void ConversationTreeWidget::tapReset(void *conv_hash_ptr)
conv_tree->clear();
reset_conversation_table_data(&conv_tree->hash_);
+ conv_tree->min_rel_start_time_ = 0;
+ conv_tree->max_rel_stop_time_ = 0;
}
void ConversationTreeWidget::tapDraw(void *conv_hash_ptr)
@@ -659,6 +704,11 @@ void ConversationTreeWidget::updateItems() {
ConversationTreeWidgetItem *ctwi = new ConversationTreeWidgetItem(hash_.conv_array, i, &resolve_names_);
new_items << ctwi;
+ if (i == 0) {
+ min_rel_start_time_ = nstime_to_sec(&(ctwi->convItem()->start_time));
+ max_rel_stop_time_ = nstime_to_sec(&(ctwi->convItem()->stop_time));
+ }
+
for (int col = 0; col < columnCount(); col++) {
switch (col) {
case CONV_COLUMN_SRC_ADDR:
@@ -672,6 +722,20 @@ void ConversationTreeWidget::updateItems() {
}
addTopLevelItems(new_items);
+ for (int i = 0; i < topLevelItemCount(); i++) {
+ ConversationTreeWidgetItem *ctwi = dynamic_cast<ConversationTreeWidgetItem *>(topLevelItem(i));
+
+ double item_rel_start = nstime_to_sec(&(ctwi->convItem()->start_time));
+ if (item_rel_start < min_rel_start_time_) {
+ min_rel_start_time_ = item_rel_start;
+ }
+
+ double item_rel_stop = nstime_to_sec(&(ctwi->convItem()->stop_time));
+ if (item_rel_stop > max_rel_stop_time_) {
+ max_rel_stop_time_ = item_rel_stop;
+ }
+ }
+
setSortingEnabled(true);
if (resize) {
diff --git a/ui/qt/conversation_dialog.h b/ui/qt/conversation_dialog.h
index 6e7abf5ca6..d962684ac3 100644
--- a/ui/qt/conversation_dialog.h
+++ b/ui/qt/conversation_dialog.h
@@ -35,10 +35,14 @@ public:
static void tapReset(void *conv_hash_ptr);
static void tapDraw(void *conv_hash_ptr);
+ double minRelStartTime() { return min_rel_start_time_; }
+ double maxRelStopTime() { return max_rel_stop_time_; }
private:
void initDirectionMap();
void updateItems();
+ double min_rel_start_time_; // seconds
+ double max_rel_stop_time_; // seconds
private slots:
void filterActionTriggered();
diff --git a/ui/qt/percent_bar_delegate.cpp b/ui/qt/percent_bar_delegate.cpp
index 76517de85e..31555aec38 100644
--- a/ui/qt/percent_bar_delegate.cpp
+++ b/ui/qt/percent_bar_delegate.cpp
@@ -35,7 +35,9 @@ void PercentBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
QStyleOptionViewItem option_vi = option;
QStyledItemDelegate::initStyleOption(&option_vi, index);
- QStyledItemDelegate::paint(painter, option, index);
+ // Paint our rect with no text using the current style, then draw our
+ // bar and text over it.
+ QStyledItemDelegate::paint(painter, option, QModelIndex());
bool ok = false;
double value = index.data(Qt::UserRole).toDouble(&ok);
@@ -45,8 +47,6 @@ void PercentBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
return;
}
- painter->save();
-
if (QApplication::style()->objectName().contains("vista")) {
// QWindowsVistaStyle::drawControl does this internally. Unfortunately there
// doesn't appear to be a more general way to do this.
@@ -54,29 +54,35 @@ void PercentBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
option_vi.palette.color(QPalette::Active, QPalette::Text));
}
- QColor bar_color = ColorUtils::alphaBlend(option_vi.palette.windowText(),
- option_vi.palette.window(), bar_blend_);
QPalette::ColorGroup cg = option_vi.state & QStyle::State_Enabled
? QPalette::Normal : QPalette::Disabled;
+ QColor text_color = option_vi.palette.color(cg, QPalette::Text);
+ QColor bar_color = ColorUtils::alphaBlend(option_vi.palette.windowText(),
+ option_vi.palette.window(), bar_blend_);
+
if (cg == QPalette::Normal && !(option_vi.state & QStyle::State_Active))
cg = QPalette::Inactive;
if (option_vi.state & QStyle::State_Selected) {
- painter->setPen(option_vi.palette.color(cg, QPalette::HighlightedText));
+ text_color = option_vi.palette.color(cg, QPalette::HighlightedText);
bar_color = ColorUtils::alphaBlend(option_vi.palette.color(cg, QPalette::Window),
option_vi.palette.color(cg, QPalette::Highlight),
bar_blend_);
- } else {
- painter->setPen(option_vi.palette.color(cg, QPalette::Text));
}
+ painter->save();
+ int border_radius = 3; // We use 3 px elsewhere, e.g. filter combos.
QRect pct_rect = option.rect;
pct_rect.adjust(1, 1, -1, -1);
pct_rect.setWidth(((pct_rect.width() * value) / 100.0) + 0.5);
- painter->fillRect(pct_rect, bar_color);
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(bar_color);
+ painter->drawRoundedRect(pct_rect, border_radius, border_radius);
+ painter->restore();
+ painter->save();
QString pct_str = QString::number(value, 'f', 1);
+ painter->setPen(text_color);
painter->drawText(option.rect, Qt::AlignCenter, pct_str);
-
painter->restore();
}
diff --git a/ui/qt/timeline_delegate.cpp b/ui/qt/timeline_delegate.cpp
new file mode 100644
index 0000000000..0cfdd73147
--- /dev/null
+++ b/ui/qt/timeline_delegate.cpp
@@ -0,0 +1,103 @@
+/* timeline_delegate.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 "timeline_delegate.h"
+
+#include "color_utils.h"
+
+#include <QApplication>
+#include <QPainter>
+
+// XXX We might want to move this to conversation_dialog.cpp.
+
+// PercentBarDelegate uses a stronger blend value, but its bars are also
+// more of a prominent feature. Make the blend weaker here so that we don't
+// obscure our text.
+static const double bar_blend_ = 0.08;
+
+TimelineDelegate::TimelineDelegate(QWidget *parent) :
+ QStyledItemDelegate(parent)
+{}
+
+void TimelineDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ QStyleOptionViewItem option_vi = option;
+ QStyledItemDelegate::initStyleOption(&option_vi, index);
+
+
+ struct timeline_span span_px = index.data(Qt::UserRole).value<struct timeline_span>();
+
+ // Paint our rect with no text using the current style, then draw our
+ // bar and text over it.
+ QStyledItemDelegate::paint(painter, option, QModelIndex());
+
+ if (QApplication::style()->objectName().contains("vista")) {
+ // QWindowsVistaStyle::drawControl does this internally. Unfortunately there
+ // doesn't appear to be a more general way to do this.
+ option_vi.palette.setColor(QPalette::All, QPalette::HighlightedText,
+ option_vi.palette.color(QPalette::Active, QPalette::Text));
+ }
+
+ QPalette::ColorGroup cg = option_vi.state & QStyle::State_Enabled
+ ? QPalette::Normal : QPalette::Disabled;
+ QColor text_color = option_vi.palette.color(cg, QPalette::Text);
+ QColor bar_color = ColorUtils::alphaBlend(option_vi.palette.windowText(),
+ option_vi.palette.window(), bar_blend_);
+
+ if (cg == QPalette::Normal && !(option_vi.state & QStyle::State_Active))
+ cg = QPalette::Inactive;
+ if (option_vi.state & QStyle::State_Selected) {
+ text_color = option_vi.palette.color(cg, QPalette::HighlightedText);
+ bar_color = ColorUtils::alphaBlend(option_vi.palette.color(cg, QPalette::Window),
+ option_vi.palette.color(cg, QPalette::Highlight),
+ bar_blend_);
+ }
+
+ painter->save();
+ int border_radius = 3; // We use 3 px elsewhere, e.g. filter combos.
+ QRect timeline_rect = option.rect;
+ timeline_rect.adjust(span_px.start, 1, 0, -1);
+ timeline_rect.setWidth(span_px.width);
+ painter->setClipRect(option.rect);
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(bar_color);
+ painter->drawRoundedRect(timeline_rect, border_radius, border_radius);
+ painter->restore();
+
+ painter->save();
+ painter->setPen(text_color);
+ painter->drawText(option.rect, Qt::AlignCenter, index.data(Qt::DisplayRole).toString());
+ painter->restore();
+}
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/timeline_delegate.h b/ui/qt/timeline_delegate.h
new file mode 100644
index 0000000000..face6da320
--- /dev/null
+++ b/ui/qt/timeline_delegate.h
@@ -0,0 +1,80 @@
+/* timeline_delegate.h
+ *
+ * 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.
+ */
+
+#ifndef TIMELINE_DELEGATE_H
+#define TIMELINE_DELEGATE_H
+
+/*
+ * @file Timeline delegate.
+ *
+ * QStyledItemDelegate subclass that will draw a timeline indicator for
+ * the specified value.
+ *
+ * This is intended to be used in QTreeWidgets to show timelines, e.g. for
+ * conversations.
+ * To use it, first call setItemDelegate:
+ *
+ * myTreeWidget()->setItemDelegateForColumn(col_time_start_, new TimelineDelegate());
+ *
+ * Then, for each QTreeWidgetItem, set or return a timeline_span for the start and end
+ * of the timeline in pixels relative to the column width.
+ *
+ * setData(col_start_, Qt::UserRole, start_span);
+ * setData(col_end_, Qt::UserRole, end_span);
+ *
+ */
+
+#include <QStyledItemDelegate>
+
+// Pixels are relative to item rect and will be clipped.
+struct timeline_span {
+ int start;
+ int width;
+};
+
+Q_DECLARE_METATYPE(timeline_span)
+
+class TimelineDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
+
+public:
+ TimelineDelegate(QWidget *parent = 0);
+protected:
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+private:
+};
+
+#endif // TIMELINE_DELEGATE_H
+
+/*
+ * 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:
+ */