aboutsummaryrefslogtreecommitdiffstats
path: root/ui/qt
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2015-03-11 15:22:20 -0700
committerAnders Broman <a.broman58@gmail.com>2015-05-08 04:29:59 +0000
commitf77e02ccc62c9283eefba416efbb2f94e460066e (patch)
tree40aa62ed6f8c03e22cdc636e2335f3b810810b65 /ui/qt
parent3d7ff97e4fa9211a064acbac0ec0c025a164d69e (diff)
Expert Info dialog.
Show all expert messages in a combined view. Group top-level items by a (severity, group, protocol) tuple. Let the user enable and disable messages via a check menu. Add ProtoTree::goToField and expert_info_t.hf_index. Use them to jump to what we hope is the afflicted item. Enable the context menu only if the user has selected a packet item. Add a free-form search field that matches expert summaries. This differs from the GTK+ version but hopefully provides a smoother workflow. Bug: 10931 Change-Id: Ia12cb7c27cdea1634fa2798fb7e4c1b23bd16ad2 Reviewed-on: https://code.wireshark.org/review/8294 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/qt')
-rw-r--r--ui/qt/CMakeLists.txt3
-rw-r--r--ui/qt/Makefile.am2
-rw-r--r--ui/qt/Makefile.common4
-rw-r--r--ui/qt/Wireshark.pro3
-rw-r--r--ui/qt/color_utils.cpp8
-rw-r--r--ui/qt/color_utils.h9
-rw-r--r--ui/qt/display_filter_edit.h1
-rw-r--r--ui/qt/expert_info_dialog.cpp581
-rw-r--r--ui/qt/expert_info_dialog.h116
-rw-r--r--ui/qt/expert_info_dialog.ui221
-rw-r--r--ui/qt/main_status_bar.cpp5
-rw-r--r--ui/qt/main_status_bar.h1
-rw-r--r--ui/qt/main_window.cpp3
-rw-r--r--ui/qt/main_window.h2
-rw-r--r--ui/qt/main_window.ui10
-rw-r--r--ui/qt/main_window_slots.cpp28
-rw-r--r--ui/qt/packet_list.cpp6
-rw-r--r--ui/qt/packet_list.h1
-rw-r--r--ui/qt/proto_tree.cpp41
-rw-r--r--ui/qt/proto_tree.h1
20 files changed, 1029 insertions, 17 deletions
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index e52e803185..821aaf1837 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -47,6 +47,7 @@ set(WIRESHARK_QT_HEADERS
display_filter_edit.h
elided_label.h
endpoint_dialog.h
+ expert_info_dialog.h
export_dissection_dialog.h
export_object_dialog.h
export_pdu_dialog.h
@@ -157,6 +158,7 @@ set(WIRESHARK_QT_SRC
display_filter_combo.cpp
display_filter_edit.cpp
elided_label.cpp
+ expert_info_dialog.cpp
export_dissection_dialog.cpp
export_object_dialog.cpp
export_pdu_dialog.cpp
@@ -262,6 +264,7 @@ set(WIRESHARK_QT_UI
column_editor_frame.ui
compiled_filter_output.ui
decode_as_dialog.ui
+ expert_info_dialog.ui
export_object_dialog.ui
export_pdu_dialog.ui
file_set_dialog.ui
diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am
index 372ed6f675..d29a8235c3 100644
--- a/ui/qt/Makefile.am
+++ b/ui/qt/Makefile.am
@@ -140,6 +140,8 @@ compiled_filter_output.cpp compiled_filter_output.h: ui_compiled_filter_output.h
decode_as_dialog.cpp decode_as_dialog.h: ui_decode_as_dialog.h
+expert_info_dialog.cpp expert_info_dialog.h: ui_expert_info_dialog.h
+
export_object_dialog.cpp export_object_dialog.h: ui_export_object_dialog.h
export_pdu_dialog.cpp export_pdu_dialog.h: ui_export_pdu_dialog.h
diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common
index bd5da843d9..b9a2705c73 100644
--- a/ui/qt/Makefile.common
+++ b/ui/qt/Makefile.common
@@ -39,6 +39,7 @@ NODIST_GENERATED_HEADER_FILES = \
ui_column_editor_frame.h \
ui_compiled_filter_output.h \
ui_decode_as_dialog.h \
+ ui_expert_info_dialog.h \
ui_export_object_dialog.h \
ui_export_pdu_dialog.h \
ui_extcap_options_dialog.h \
@@ -144,6 +145,7 @@ MOC_HDRS = \
display_filter_edit.h \
elided_label.h \
endpoint_dialog.h \
+ expert_info_dialog.h \
export_dissection_dialog.h \
export_object_dialog.h \
export_pdu_dialog.h \
@@ -226,6 +228,7 @@ UI_FILES = \
column_editor_frame.ui \
compiled_filter_output.ui \
decode_as_dialog.ui \
+ expert_info_dialog.ui \
export_object_dialog.ui \
export_pdu_dialog.ui \
extcap_options_dialog.ui \
@@ -347,6 +350,7 @@ WIRESHARK_QT_SRC = \
display_filter_edit.cpp \
elided_label.cpp \
endpoint_dialog.cpp \
+ expert_info_dialog.cpp \
export_dissection_dialog.cpp \
export_object_dialog.cpp \
export_pdu_dialog.cpp \
diff --git a/ui/qt/Wireshark.pro b/ui/qt/Wireshark.pro
index ec80b40281..6cfe6088db 100644
--- a/ui/qt/Wireshark.pro
+++ b/ui/qt/Wireshark.pro
@@ -215,6 +215,7 @@ FORMS += \
column_editor_frame.ui \
compiled_filter_output.ui \
decode_as_dialog.ui \
+ expert_info_dialog.ui \
export_object_dialog.ui \
export_pdu_dialog.ui \
extcap_options_dialog.ui \
@@ -277,6 +278,7 @@ HEADERS += $$HEADERS_WS_C \
decode_as_dialog.h \
elided_label.h \
endpoint_dialog.h \
+ expert_info_dialog.h \
export_dissection_dialog.h \
export_object_dialog.h \
export_pdu_dialog.h \
@@ -628,6 +630,7 @@ SOURCES += \
display_filter_edit.cpp \
elided_label.cpp \
endpoint_dialog.cpp \
+ expert_info_dialog.cpp \
export_dissection_dialog.cpp \
export_object_dialog.cpp \
export_pdu_dialog.cpp \
diff --git a/ui/qt/color_utils.cpp b/ui/qt/color_utils.cpp
index e6d7f31082..70babce6e8 100644
--- a/ui/qt/color_utils.cpp
+++ b/ui/qt/color_utils.cpp
@@ -45,6 +45,14 @@ initialize_color(color_t *color, guint16 red, guint16 green, guint16 blue)
return TRUE;
}
+const QColor ColorUtils::expert_color_comment = QColor ( 0xb7, 0xf7, 0x74 ); /* Green */
+const QColor ColorUtils::expert_color_chat = QColor ( 0x80, 0xb7, 0xf7 ); /* Light blue */
+const QColor ColorUtils::expert_color_note = QColor ( 0xa0, 0xff, 0xff ); /* Bright turquoise */
+const QColor ColorUtils::expert_color_warn = QColor ( 0xf7, 0xf2, 0x53 ); /* Yellow */
+const QColor ColorUtils::expert_color_error = QColor ( 0xff, 0x5c, 0x5c ); /* Pale red */
+const QColor ColorUtils::expert_color_foreground = QColor ( 0x00, 0x00, 0x00 ); /* Black */
+const QColor ColorUtils::hidden_proto_item = QColor ( 0x44, 0x44, 0x44 ); /* Gray */
+
ColorUtils::ColorUtils(QObject *parent) :
QObject(parent)
{
diff --git a/ui/qt/color_utils.h b/ui/qt/color_utils.h
index aa74adcfaf..6d5a872106 100644
--- a/ui/qt/color_utils.h
+++ b/ui/qt/color_utils.h
@@ -44,6 +44,15 @@ public:
static QRgb alphaBlend(const QColor &color1, const QColor &color2, qreal alpha);
static QRgb alphaBlend(const QBrush &brush1, const QBrush &brush2, qreal alpha);
+ // ...because they don't really fit anywhere else?
+ static const QColor expert_color_comment; /* green */
+ static const QColor expert_color_chat; /* light blue */
+ static const QColor expert_color_note; /* bright turquoise */
+ static const QColor expert_color_warn; /* yellow */
+ static const QColor expert_color_error; /* pale red */
+ static const QColor expert_color_foreground; /* black */
+ static const QColor hidden_proto_item; /* gray */
+
signals:
public slots:
diff --git a/ui/qt/display_filter_edit.h b/ui/qt/display_filter_edit.h
index 74f373a09f..1648b78bb0 100644
--- a/ui/qt/display_filter_edit.h
+++ b/ui/qt/display_filter_edit.h
@@ -61,7 +61,6 @@ signals:
void pushFilterSyntaxWarning(const QString&);
void filterPackets(QString& new_filter, bool force);
void addBookmark(QString filter);
-
};
#endif // DISPLAYFILTEREDIT_H
diff --git a/ui/qt/expert_info_dialog.cpp b/ui/qt/expert_info_dialog.cpp
new file mode 100644
index 0000000000..98df85251f
--- /dev/null
+++ b/ui/qt/expert_info_dialog.cpp
@@ -0,0 +1,581 @@
+/* expert_info_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 "expert_info_dialog.h"
+#include "ui_expert_info_dialog.h"
+
+#include "file.h"
+
+#include <epan/expert.h>
+#include <epan/stat_tap_ui.h>
+#include <epan/tap.h>
+
+#include "color_utils.h"
+#include "wireshark_application.h"
+
+#include <QAction>
+#include <QHash>
+#include <QMenu>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QTreeWidgetItemIterator>
+
+// To do:
+// - Test with custom expert levels (Preferences -> Protocols -> Expert).
+// - Figure out why the expert level prefs are buried under "Protocols".
+// - Test with large captures. Add a custom model if needed.
+// - Promote to a fourth pane in the main window?
+// - Make colors configurable? In theory we could condense image/expert_indicators.svg,
+// down to one item, make sure it uses a single (or a few) base color(s), and generate
+// icons on the fly.
+
+const int severity_col_ = 0;
+const int group_col_ = 1;
+const int protocol_col_ = 2;
+const int count_col_ = 3;
+
+const int packet_col_ = 0;
+
+const int group_type_ = 1000;
+const int packet_type_ = 1001;
+
+const int auto_expand_threshold_ = 20; // Arbitrary
+
+class ExpertGroupTreeWidgetItem : public QTreeWidgetItem
+{
+public:
+ ExpertGroupTreeWidgetItem(QTreeWidget *parent, int severity, int group, const QString &protocol) : QTreeWidgetItem (parent, group_type_) {
+ // XXX We set text and data here, colors in addExpertInfo, and counts
+ // in updateCounts.
+ setData(severity_col_, Qt::UserRole, QVariant(severity));
+ setData(group_col_, Qt::UserRole, QVariant(group));
+
+ setText(severity_col_, val_to_str_const(severity, expert_severity_vals, "Unknown"));
+ setText(group_col_, val_to_str_const(group, expert_group_vals, "Unknown"));
+ setText(protocol_col_, protocol);
+ setText(count_col_, "0");
+ }
+ bool operator< (const QTreeWidgetItem &other) const
+ {
+ int sort_col = treeWidget()->sortColumn();
+ switch(sort_col) {
+ case severity_col_:
+ return data(severity_col_, Qt::UserRole).value<int>() < other.data(severity_col_, Qt::UserRole).value<int>();
+ case count_col_:
+ return text(count_col_).toInt() < other.text(count_col_).toInt();
+ default:
+ return QTreeWidgetItem::operator<(other);
+ }
+ }
+};
+
+class ExpertPacketTreeWidgetItem : public QTreeWidgetItem
+{
+public:
+ ExpertPacketTreeWidgetItem(QTreeWidgetItem *parent, expert_info_t *expert_info = NULL) :
+ QTreeWidgetItem (parent, packet_type_),
+ packet_num_(0),
+ hf_id_(-1)
+ {
+ if (expert_info) {
+ packet_num_ = expert_info->packet_num;
+ hf_id_ = expert_info->hf_index;
+ protocol_ = expert_info->protocol;
+ summary_ = expert_info->summary;
+ }
+ setFirstColumnSpanned(true);
+ setText(packet_col_, QString("%1: %2")
+ .arg(packet_num_)
+ .arg(summary_));
+ }
+ guint32 packetNum() const { return packet_num_; }
+ int hfId() const { return hf_id_; }
+ QString protocol() const { return protocol_; }
+ QString summary() const { return summary_; }
+ bool operator< (const QTreeWidgetItem &other) const
+ {
+ // Probably not needed.
+ if (other.type() != packet_type_) return QTreeWidgetItem::operator< (other);
+ const ExpertPacketTreeWidgetItem *other_expert = static_cast<const ExpertPacketTreeWidgetItem *>(&other);
+ // Force ascending.
+ if (treeWidget()->header()->sortIndicatorOrder() == Qt::DescendingOrder) {
+ return packet_num_ > other_expert->packetNum();
+ } else {
+ return packet_num_ < other_expert->packetNum();
+ }
+ }
+private:
+ guint32 packet_num_;
+ int hf_id_;
+ QString protocol_;
+ QString summary_;
+};
+
+ExpertInfoDialog::ExpertInfoDialog(QWidget &parent, CaptureFile &capture_file) :
+ WiresharkDialog(parent, capture_file),
+ ui(new Ui::ExpertInfoDialog),
+ need_show_hide_(false),
+ display_filter_(QString())
+{
+ ui->setupUi(this);
+
+ setWindowSubtitle(tr("Expert Information"));
+
+ // Clicking on an item jumps to its associated packet. Make the dialog
+ // narrow so that we avoid obscuring the packet list.
+ // XXX Use recent settings instead
+ int dlg_width = parent.width() / 2;
+ if (dlg_width < width()) dlg_width = width();
+ resize(dlg_width, parent.height());
+
+ severity_actions_ = QList<QAction *>() << ui->actionShowError << ui->actionShowWarning
+ << ui->actionShowNote << ui->actionShowChat
+ << ui->actionShowComment;
+ QList<int> severities = QList<int>() << PI_ERROR << PI_WARN << PI_NOTE << PI_CHAT << PI_COMMENT;
+ QMenu *severity_menu = new QMenu();
+
+ // It might be nice to color each menu item to match each severity. It
+ // might also be nice if Qt supported that...
+ foreach (QAction *sa, severity_actions_) {
+ severity_menu->addAction(sa);
+ sa->setData(QVariant(severities.takeFirst()));
+ sa->setChecked(true);
+ connect(sa, SIGNAL(toggled(bool)), this, SLOT(actionShowToggled()));
+ }
+ ui->severitiesPushButton->setMenu(severity_menu);
+
+ ui->expertInfoTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(ui->expertInfoTreeWidget, SIGNAL(customContextMenuRequested(QPoint)),
+ SLOT(showProtoHierMenu(QPoint)));
+
+ QMenu *submenu;
+
+ FilterAction::Action cur_action = FilterAction::ActionApply;
+ submenu = ctx_menu_.addMenu(FilterAction::actionName(cur_action));
+ foreach (FilterAction::ActionType at, FilterAction::actionTypes()) {
+ FilterAction *fa = new FilterAction(submenu, cur_action, at);
+ submenu->addAction(fa);
+ connect(fa, SIGNAL(triggered()), this, SLOT(filterActionTriggered()));
+ }
+
+ cur_action = FilterAction::ActionPrepare;
+ submenu = ctx_menu_.addMenu(FilterAction::actionName(cur_action));
+ foreach (FilterAction::ActionType at, FilterAction::actionTypes()) {
+ FilterAction *fa = new FilterAction(submenu, cur_action, at);
+ submenu->addAction(fa);
+ connect(fa, SIGNAL(triggered()), this, SLOT(filterActionTriggered()));
+ }
+
+ FilterAction *fa;
+ QList<FilterAction::Action> extra_actions =
+ QList<FilterAction::Action>() << FilterAction::ActionFind
+ << FilterAction::ActionColorize
+ << FilterAction::ActionWebLookup
+ << FilterAction::ActionCopy;
+
+ foreach (FilterAction::Action extra_action, extra_actions) {
+ fa = new FilterAction(&ctx_menu_, extra_action);
+ ctx_menu_.addAction(fa);
+ connect(fa, SIGNAL(triggered()), this, SLOT(filterActionTriggered()));
+ }
+
+ setDisplayFilter();
+ retapPackets();
+
+}
+
+ExpertInfoDialog::~ExpertInfoDialog()
+{
+ delete ui;
+}
+
+void ExpertInfoDialog::clearAllData()
+{
+ ui->expertInfoTreeWidget->clear();
+ error_events_ = 0;
+ warn_events_ = 0;
+ note_events_ = 0;
+ chat_events_ = 0;
+ comment_events_ = 0;
+
+ need_show_hide_ = false;
+ ei_to_ti_.clear();
+}
+
+void ExpertInfoDialog::setDisplayFilter(const QString &display_filter)
+{
+ display_filter_ = display_filter;
+ updateWidgets();
+}
+
+void ExpertInfoDialog::retapPackets()
+{
+ if (file_closed_) return;
+
+ clearAllData();
+ remove_tap_listener(this);
+
+ GString *error_string = register_tap_listener("expert",
+ this,
+ NULL,
+ TL_REQUIRES_NOTHING,
+ tapReset,
+ tapPacket,
+ tapDraw);
+ if (error_string) {
+ QMessageBox::warning(this, tr("Endpoint expert failed to register tap listener"),
+ error_string->str);
+ g_string_free(error_string, TRUE);
+ return;
+ }
+
+ if (ui->limitCheckBox->isChecked()) {
+ error_string = set_tap_dfilter(this, display_filter_.toUtf8().constData());
+ if (error_string) {
+ QMessageBox::warning(this, tr("Endpoint expert failed to set filter"),
+ error_string->str);
+ g_string_free(error_string, TRUE);
+ return;
+ }
+ }
+
+ cap_file_.retapPackets();
+
+ updateWidgets();
+
+ for (int i = 0; i < ui->expertInfoTreeWidget->topLevelItemCount(); i++) {
+ QTreeWidgetItem *group_ti = ui->expertInfoTreeWidget->topLevelItem(i);
+ if (group_ti->childCount() <= auto_expand_threshold_) {
+ group_ti->setExpanded(true);
+ }
+ }
+}
+
+void ExpertInfoDialog::addExpertInfo(struct expert_info_s *expert_info)
+{
+ if (!expert_info) return;
+ QTreeWidgetItem *group_ti;
+
+ QString key = QString("%1|%2|%3")
+ .arg(expert_info->severity)
+ .arg(expert_info->group)
+ .arg(expert_info->protocol);
+
+ QColor background;
+ switch(expert_info->severity) {
+ case(PI_COMMENT):
+ background = ColorUtils::expert_color_comment;
+ break;
+ case(PI_CHAT):
+ background = ColorUtils::expert_color_chat;
+ break;
+ case(PI_NOTE):
+ background = ColorUtils::expert_color_note;
+ break;
+ case(PI_WARN):
+ background = ColorUtils::expert_color_warn;
+ break;
+ case(PI_ERROR):
+ background = ColorUtils::expert_color_error;
+ break;
+ default:
+ break;
+ }
+
+ if (ei_to_ti_.contains(key)) {
+ group_ti = ei_to_ti_[key];
+ } else {
+ group_ti = new ExpertGroupTreeWidgetItem(ui->expertInfoTreeWidget, expert_info->severity, expert_info->group, expert_info->protocol);
+ if (background.isValid()) {
+ for (int i = 0; i < ui->expertInfoTreeWidget->columnCount(); i++) {
+ group_ti->setBackground(i, background);
+ group_ti->setForeground(i, ColorUtils::expert_color_foreground);
+ }
+ }
+ ei_to_ti_[key] = group_ti;
+ }
+
+ new ExpertPacketTreeWidgetItem(group_ti, expert_info);
+
+ // XXX Use plain colors until our users demand to be blinded.
+// if (background.isValid()) {
+// packet_ti->setBackground(0, background);
+// packet_ti->setForeground(0, ColorUtils::expert_color_foreground);
+ // }
+}
+
+void ExpertInfoDialog::updateCounts()
+{
+ for (int i = 0; i < ui->expertInfoTreeWidget->topLevelItemCount(); i++) {
+ QTreeWidgetItem *group_ti = ui->expertInfoTreeWidget->topLevelItem(i);
+ group_ti->setText(count_col_, QString::number(group_ti->childCount()));
+ }
+}
+
+void ExpertInfoDialog::tapReset(void *eid_ptr)
+{
+ ExpertInfoDialog *eid = static_cast<ExpertInfoDialog *>(eid_ptr);
+ if (!eid) return;
+
+ eid->clearAllData();
+}
+
+gboolean ExpertInfoDialog::tapPacket(void *eid_ptr, packet_info *pinfo, epan_dissect_t *, const void *data)
+{
+ ExpertInfoDialog *eid = static_cast<ExpertInfoDialog *>(eid_ptr);
+ expert_info_t *expert_info = (expert_info_t *) data;
+ gboolean draw_required = FALSE;
+
+ if (!pinfo || !eid || !expert_info) return 0;
+
+ eid->addExpertInfo(expert_info);
+
+ switch(expert_info->severity) {
+ case(PI_COMMENT):
+ if (eid->comment_events_ < 1) draw_required = TRUE;
+ eid->comment_events_++;
+ break;
+ case(PI_CHAT):
+ if (eid->chat_events_ < 1) draw_required = TRUE;
+ eid->chat_events_++;
+ break;
+ case(PI_NOTE):
+ if (eid->note_events_ < 1) draw_required = TRUE;
+ eid->note_events_++;
+ break;
+ case(PI_WARN):
+ if (eid->warn_events_ < 1) draw_required = TRUE;
+ eid->warn_events_++;
+ break;
+ case(PI_ERROR):
+ if (eid->error_events_ < 1) draw_required = TRUE;
+ eid->error_events_++;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ return draw_required;
+}
+
+void ExpertInfoDialog::tapDraw(void *eid_ptr)
+{
+ ExpertInfoDialog *eid = static_cast<ExpertInfoDialog *>(eid_ptr);
+ if (!eid) return;
+
+ eid->updateWidgets();
+}
+
+void ExpertInfoDialog::updateWidgets()
+{
+ ui->limitCheckBox->setEnabled(! file_closed_ && ! display_filter_.isEmpty());
+
+ ui->actionShowError->setEnabled(error_events_ > 0);
+ ui->actionShowWarning->setEnabled(warn_events_ > 0);
+ ui->actionShowNote->setEnabled(note_events_ > 0);
+ ui->actionShowChat->setEnabled(chat_events_ > 0);
+ ui->actionShowComment->setEnabled(comment_events_ > 0);
+
+ if (need_show_hide_) {
+ for (int i = 0; i < ui->expertInfoTreeWidget->topLevelItemCount(); i++) {
+ QTreeWidgetItem *group_ti = ui->expertInfoTreeWidget->topLevelItem(i);
+ switch (group_ti->data(severity_col_, Qt::UserRole).value<int>()) {
+ case PI_ERROR:
+ group_ti->setHidden(! ui->actionShowError->isChecked());
+ break;
+ case PI_WARN:
+ group_ti->setHidden(! ui->actionShowWarning->isChecked());
+ break;
+ case PI_NOTE:
+ group_ti->setHidden(! ui->actionShowNote->isChecked());
+ break;
+ case PI_CHAT:
+ group_ti->setHidden(! ui->actionShowChat->isChecked());
+ break;
+ case PI_COMMENT:
+ group_ti->setHidden(! ui->actionShowComment->isChecked());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ updateCounts();
+
+ QString tooltip;
+ QString hint;
+
+ if (file_closed_) {
+ tooltip = tr("Capture file closed.");
+ hint = tr("Capture file closed.");
+ } else if (display_filter_.isEmpty()) {
+ tooltip = tr("No display filter");
+ hint = tr("No display filter set.");
+ } else {
+ tooltip = tr("Limit information to \"%1\".").arg(display_filter_);
+ hint = tr("Display filter: \"%1\"").arg(display_filter_);
+ }
+
+ ui->limitCheckBox->setToolTip(tooltip);
+ hint.prepend("<small><i>");
+ hint.append("</i></small>");
+ ui->hintLabel->setText(hint);
+
+}
+
+void ExpertInfoDialog::actionShowToggled()
+{
+ need_show_hide_ = true;
+ updateWidgets();
+}
+
+void ExpertInfoDialog::showProtoHierMenu(QPoint pos)
+{
+ bool enable = true;
+ ExpertPacketTreeWidgetItem *packet_ti = dynamic_cast<ExpertPacketTreeWidgetItem *>(ui->expertInfoTreeWidget->currentItem());
+ if (!packet_ti || packet_ti->hfId() < 0) {
+ enable = false;
+ }
+
+ foreach (QMenu *submenu, ctx_menu_.findChildren<QMenu*>()) {
+ submenu->setEnabled(enable && !file_closed_);
+ }
+ foreach (QAction *action, ctx_menu_.actions()) {
+ FilterAction *fa = qobject_cast<FilterAction *>(action);
+ bool action_enable = enable && !file_closed_;
+ if (fa && (fa->action() == FilterAction::ActionWebLookup || fa->action() == FilterAction::ActionCopy)) {
+ action_enable = enable;
+ }
+ action->setEnabled(action_enable);
+ }
+
+ ctx_menu_.popup(ui->expertInfoTreeWidget->viewport()->mapToGlobal(pos));
+}
+
+void ExpertInfoDialog::filterActionTriggered()
+{
+ ExpertPacketTreeWidgetItem *packet_ti = dynamic_cast<ExpertPacketTreeWidgetItem *>(ui->expertInfoTreeWidget->currentItem());
+ FilterAction *fa = qobject_cast<FilterAction *>(QObject::sender());
+
+ if (!fa || !packet_ti) {
+ return;
+ }
+
+ int hf_index = packet_ti->hfId();
+ if (hf_index > -1) {
+ QString filter_string;
+ if (fa->action() == FilterAction::ActionWebLookup) {
+ filter_string = QString("%1 %2")
+ .arg(packet_ti->protocol())
+ .arg(packet_ti->summary());
+ } else if (fa->action() == FilterAction::ActionCopy) {
+ filter_string = QString("%1 %2: %3")
+ .arg(packet_ti->packetNum())
+ .arg(packet_ti->protocol())
+ .arg(packet_ti->summary());
+ } else {
+ filter_string = proto_registrar_get_abbrev(hf_index);
+ }
+
+ if (! filter_string.isEmpty()) {
+ emit filterAction(filter_string, fa->action(), fa->actionType());
+ }
+ }
+}
+
+void ExpertInfoDialog::captureFileClosing()
+{
+ remove_tap_listener(this);
+ WiresharkDialog::captureFileClosing();
+}
+
+void ExpertInfoDialog::on_expertInfoTreeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *)
+{
+ // Ignore top-level items.
+ if (!current || !current->parent() || file_closed_) return;
+
+ ExpertPacketTreeWidgetItem *packet_ti = dynamic_cast<ExpertPacketTreeWidgetItem *>(current);
+ if (!packet_ti) return;
+
+ emit goToPacket(packet_ti->packetNum(), packet_ti->hfId());
+}
+
+void ExpertInfoDialog::on_limitCheckBox_toggled(bool)
+{
+ retapPackets();
+}
+
+// Show child (packet list) items that match the contents of searchLineEdit.
+void ExpertInfoDialog::on_searchLineEdit_textChanged(const QString &search_re)
+{
+ QTreeWidgetItemIterator it(ui->expertInfoTreeWidget, QTreeWidgetItemIterator::NoChildren);
+ QRegExp regex(search_re, Qt::CaseInsensitive);
+ while (*it) {
+ bool hidden = true;
+ if (search_re.isEmpty() || (*it)->text(packet_col_).contains(regex)) {
+ hidden = false;
+ }
+ (*it)->setHidden(hidden);
+ ++it;
+ }
+}
+
+void ExpertInfoDialog::on_buttonBox_helpRequested()
+{
+ wsApp->helpTopicAction(HELP_EXPERT_INFO_DIALOG);
+}
+
+// Stat command + args
+
+static void
+expert_info_init(const char *, void*) {
+ wsApp->emitStatCommandSignal("ExpertInfo", NULL, NULL);
+}
+
+static stat_tap_ui expert_info_stat_ui = {
+ REGISTER_STAT_GROUP_GENERIC,
+ NULL,
+ "expert",
+ expert_info_init,
+ 0,
+ NULL
+};
+
+extern "C" {
+void
+register_tap_listener_expert_info(void)
+{
+ register_stat_tap_ui(&expert_info_stat_ui, NULL);
+}
+}
+
+/*
+ * 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/expert_info_dialog.h b/ui/qt/expert_info_dialog.h
new file mode 100644
index 0000000000..04fb211159
--- /dev/null
+++ b/ui/qt/expert_info_dialog.h
@@ -0,0 +1,116 @@
+/* expert_info_dialog.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 EXPERT_INFO_DIALOG_H
+#define EXPERT_INFO_DIALOG_H
+
+#include "config.h"
+
+#include <glib.h>
+
+#include "epan/epan_dissect.h"
+
+#include "filter_action.h"
+#include "wireshark_dialog.h"
+
+#include <QMenu>
+#include <QTreeWidgetItem>
+
+struct expert_info_s;
+
+namespace Ui {
+class ExpertInfoDialog;
+}
+
+class ExpertInfoDialog : public WiresharkDialog
+{
+ Q_OBJECT
+
+public:
+ explicit ExpertInfoDialog(QWidget &parent, CaptureFile& capture_file);
+ ~ExpertInfoDialog();
+
+ void clearAllData();
+ void setDisplayFilter(const QString &display_filter = QString());
+
+signals:
+ void goToPacket(int packet_num, int hf_id);
+ void filterAction(QString& filter, FilterAction::Action action, FilterAction::ActionType type);
+
+private:
+ Ui::ExpertInfoDialog *ui;
+
+ int comment_events_;
+// int disp_events;
+ int chat_events_;
+ int note_events_;
+ int warn_events_;
+ int error_events_;
+
+ bool need_show_hide_;
+
+ QMenu ctx_menu_;
+
+ QHash<QString, QTreeWidgetItem*> ei_to_ti_;
+ QList<QAction *> severity_actions_;
+
+ QString display_filter_;
+
+ void retapPackets();
+
+ // Called from tapPacket
+ void addExpertInfo(struct expert_info_s *expert_info);
+ // Called from tapDraw
+ void updateCounts();
+
+ // Callbacks for register_tap_listener
+ static void tapReset(void *eid_ptr);
+ static gboolean tapPacket(void *eid_ptr, packet_info *pinfo, epan_dissect_t *, const void *data);
+ static void tapDraw(void *eid_ptr);
+
+private slots:
+ void updateWidgets();
+
+ void actionShowToggled();
+ void showProtoHierMenu(QPoint pos);
+ void filterActionTriggered();
+ void captureFileClosing();
+
+ void on_expertInfoTreeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *);
+ void on_limitCheckBox_toggled(bool);
+ void on_searchLineEdit_textChanged(const QString &search_re);
+ void on_buttonBox_helpRequested();
+};
+
+#endif // EXPERT_INFO_DIALOG_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:
+ */
diff --git a/ui/qt/expert_info_dialog.ui b/ui/qt/expert_info_dialog.ui
new file mode 100644
index 0000000000..7b36744f9a
--- /dev/null
+++ b/ui/qt/expert_info_dialog.ui
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ExpertInfoDialog</class>
+ <widget class="QDialog" name="ExpertInfoDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>620</width>
+ <height>450</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTreeWidget" name="expertInfoTreeWidget">
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <column>
+ <property name="text">
+ <string notr="true">Severity</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Group</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Protocol</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Count</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <widget class="ElidedLabel" name="hintLabel">
+ <property name="text">
+ <string>&lt;small&gt;&lt;i&gt;A hint.&lt;/i&gt;&lt;/small&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0,1,0,0">
+ <item>
+ <widget class="QCheckBox" name="limitCheckBox">
+ <property name="text">
+ <string>Limit to Display Filter</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="toolTip">
+ <string>Search expert summaries.</string>
+ </property>
+ <property name="text">
+ <string>Search:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="searchLineEdit">
+ <property name="toolTip">
+ <string>Search expert summaries.</string>
+ </property>
+ </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>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="severitiesPushButton">
+ <property name="text">
+ <string>Show...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Close|QDialogButtonBox::Help</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ <action name="actionShowError">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Error</string>
+ </property>
+ <property name="toolTip">
+ <string>Show error packets.</string>
+ </property>
+ </action>
+ <action name="actionShowWarning">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Warning</string>
+ </property>
+ <property name="toolTip">
+ <string>Show warning packets.</string>
+ </property>
+ </action>
+ <action name="actionShowNote">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Note</string>
+ </property>
+ <property name="toolTip">
+ <string>Show note packets.</string>
+ </property>
+ </action>
+ <action name="actionShowChat">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Chat</string>
+ </property>
+ <property name="toolTip">
+ <string>Show chat packets.</string>
+ </property>
+ </action>
+ <action name="actionShowComment">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Comment</string>
+ </property>
+ <property name="toolTip">
+ <string>Show comment packets.</string>
+ </property>
+ </action>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>ElidedLabel</class>
+ <extends>QLabel</extends>
+ <header>elided_label.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ExpertInfoDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ExpertInfoDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/ui/qt/main_status_bar.cpp b/ui/qt/main_status_bar.cpp
index e834f178b0..756bc63af8 100644
--- a/ui/qt/main_status_bar.cpp
+++ b/ui/qt/main_status_bar.cpp
@@ -125,6 +125,7 @@ MainStatusBar::MainStatusBar(QWidget *parent) :
comment_label_.setText("<a href><img src=\":/comment/capture_comment_update.png\"></img></a>");
comment_label_.setToolTip(tr("Open the Capture File Properties dialog"));
comment_label_.setEnabled(false);
+ connect(&expert_status_, SIGNAL(linkActivated(QString)), this, SIGNAL(showExpertInfo()));
connect(&comment_label_, SIGNAL(linkActivated(QString)), this, SIGNAL(editCaptureComment()));
info_progress_hb->setContentsMargins(0, 0, 0, 0);
@@ -192,7 +193,7 @@ void MainStatusBar::hideExpert() {
void MainStatusBar::expertUpdate() {
// <img> won't load @2x versions in Qt versions earlier than 5.4.
// We might have to switch to a QPushButton.
- QString img_text = "<img src=\":/expert/expert_";
+ QString img_text = "<a href><img src=\":/expert/expert_";
QString tt_text = tr(" is the highest expert info level");
switch(expert_get_highest_severity()) {
@@ -221,7 +222,7 @@ void MainStatusBar::expertUpdate() {
break;
}
- img_text.append(".png\"></img>");
+ img_text.append(".png\"></img></a>");
expert_status_.setText(img_text);
expert_status_.setToolTip(tt_text);
expert_status_.show();
diff --git a/ui/qt/main_status_bar.h b/ui/qt/main_status_bar.h
index 9d8cdefa90..1cb024a4d2 100644
--- a/ui/qt/main_status_bar.h
+++ b/ui/qt/main_status_bar.h
@@ -57,6 +57,7 @@ private:
QAction *delete_action_;
signals:
+ void showExpertInfo();
void editCaptureComment();
public slots:
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index 8948ec432d..8c1dc798fd 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -406,6 +406,9 @@ MainWindow::MainWindow(QWidget *parent) :
connect(byte_view_tab_, SIGNAL(byteFieldHovered(const QString&)),
main_ui_->statusBar, SLOT(pushByteStatus(const QString&)));
+ connect(main_ui_->statusBar, SIGNAL(showExpertInfo()),
+ this, SLOT(on_actionAnalyzeExpertInfo_triggered()));
+
connect(main_ui_->statusBar, SIGNAL(editCaptureComment()),
this, SLOT(on_actionStatisticsCaptureFileProperties_triggered()));
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index 408a5ab0ab..e4becaf39e 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -375,6 +375,8 @@ private slots:
void on_actionAnalyzeFollowTCPStream_triggered();
void on_actionAnalyzeFollowUDPStream_triggered();
void on_actionAnalyzeFollowSSLStream_triggered();
+ void statCommandExpertInfo(const char *, void *);
+ void on_actionAnalyzeExpertInfo_triggered();
void on_actionHelpContents_triggered();
void on_actionHelpMPWireshark_triggered();
diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui
index c232c03316..deb03fd4bd 100644
--- a/ui/qt/main_window.ui
+++ b/ui/qt/main_window.ui
@@ -351,6 +351,8 @@
<addaction name="separator"/>
<addaction name="menuSCTP"/>
<addaction name="menuFollow"/>
+ <addaction name="separator"/>
+ <addaction name="actionAnalyzeExpertInfo"/>
</widget>
<widget class="QMenu" name="menuStatistics">
<property name="enabled">
@@ -2319,6 +2321,14 @@
<string>Automatically scroll to the last packet during a live capture.</string>
</property>
</action>
+ <action name="actionAnalyzeExpertInfo">
+ <property name="text">
+ <string>Expert Info</string>
+ </property>
+ <property name="toolTip">
+ <string>Show expert notifications</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp
index feb11fe7b2..4027880b15 100644
--- a/ui/qt/main_window_slots.cpp
+++ b/ui/qt/main_window_slots.cpp
@@ -79,7 +79,9 @@
#include "coloring_rules_dialog.h"
#include "conversation_dialog.h"
#include "decode_as_dialog.h"
+#include "display_filter_edit.h"
#include "endpoint_dialog.h"
+#include "expert_info_dialog.h"
#include "export_object_dialog.h"
#include "export_pdu_dialog.h"
#if HAVE_EXTCAP
@@ -488,6 +490,12 @@ void MainWindow::filterAction(QString &action_filter, FilterAction::Action actio
df_combo_box_->lineEdit()->setText(new_filter);
df_combo_box_->lineEdit()->setFocus();
break;
+ case FilterAction::ActionWebLookup:
+ {
+ QString url = QString("https://www.google.com/search?q=") + new_filter;
+ QDesktopServices::openUrl(QUrl(url));
+ break;
+ }
case FilterAction::ActionCopy:
wsApp->clipboard()->setText(new_filter);
break;
@@ -2315,6 +2323,26 @@ void MainWindow::on_actionSCTPFilterThisAssociation_triggered()
}
}
+void MainWindow::statCommandExpertInfo(const char *, void *)
+{
+ ExpertInfoDialog *expert_dialog = new ExpertInfoDialog(*this, capture_file_);
+ const DisplayFilterEdit *df_edit = dynamic_cast<DisplayFilterEdit *>(df_combo_box_->lineEdit());
+
+ expert_dialog->setDisplayFilter(df_edit->text());
+
+ connect(expert_dialog, SIGNAL(goToPacket(int, int)),
+ packet_list_, SLOT(goToPacket(int, int)));
+ connect(expert_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
+ this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
+
+ expert_dialog->show();
+}
+
+void MainWindow::on_actionAnalyzeExpertInfo_triggered()
+{
+ statCommandExpertInfo(NULL, NULL);
+}
+
// Next / previous / first / last slots in packet_list
diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp
index 7255cc506a..ec6c77779d 100644
--- a/ui/qt/packet_list.cpp
+++ b/ui/qt/packet_list.cpp
@@ -961,6 +961,12 @@ void PacketList::goToPacket(int packet) {
}
}
+void PacketList::goToPacket(int packet, int hf_id)
+{
+ goToPacket(packet);
+ proto_tree_->goToField(hf_id);
+}
+
void PacketList::markFrame()
{
int row = currentIndex().row();
diff --git a/ui/qt/packet_list.h b/ui/qt/packet_list.h
index 0e9194cd6c..0c29db71d8 100644
--- a/ui/qt/packet_list.h
+++ b/ui/qt/packet_list.h
@@ -121,6 +121,7 @@ public slots:
void goFirstPacket();
void goLastPacket();
void goToPacket(int packet);
+ void goToPacket(int packet, int hf_id);
void markFrame();
void markAllDisplayedFrames(bool set);
void ignoreFrame();
diff --git a/ui/qt/proto_tree.cpp b/ui/qt/proto_tree.cpp
index ed07e0e36b..7af1956dbc 100644
--- a/ui/qt/proto_tree.cpp
+++ b/ui/qt/proto_tree.cpp
@@ -26,6 +26,8 @@
#include <epan/ftypes/ftypes.h>
#include <epan/prefs.h>
+#include "color_utils.h"
+
#include <QApplication>
#include <QContextMenuEvent>
#include <QDesktopServices>
@@ -33,14 +35,6 @@
#include <QTreeWidgetItemIterator>
#include <QUrl>
-QColor expert_color_comment ( 0xb7, 0xf7, 0x74 ); /* Green */
-QColor expert_color_chat ( 0x80, 0xb7, 0xf7 ); /* light blue */
-QColor expert_color_note ( 0xa0, 0xff, 0xff ); /* bright turquoise */
-QColor expert_color_warn ( 0xf7, 0xf2, 0x53 ); /* yellow */
-QColor expert_color_error ( 0xff, 0x5c, 0x5c ); /* pale red */
-QColor expert_color_foreground ( 0x00, 0x00, 0x00 ); /* black */
-QColor hidden_proto_item ( 0x44, 0x44, 0x44 ); /* gray */
-
/* Fill a single protocol tree item with its string value and set its color. */
static void
proto_tree_draw_node(proto_node *node, gpointer data)
@@ -117,24 +111,24 @@ proto_tree_draw_node(proto_node *node, gpointer data)
if(FI_GET_FLAG(fi, PI_SEVERITY_MASK)) {
switch(FI_GET_FLAG(fi, PI_SEVERITY_MASK)) {
case(PI_COMMENT):
- item->setData(0, Qt::BackgroundRole, expert_color_comment);
+ item->setData(0, Qt::BackgroundRole, ColorUtils::expert_color_comment);
break;
case(PI_CHAT):
- item->setData(0, Qt::BackgroundRole, expert_color_chat);
+ item->setData(0, Qt::BackgroundRole, ColorUtils::expert_color_chat);
break;
case(PI_NOTE):
- item->setData(0, Qt::BackgroundRole, expert_color_note);
+ item->setData(0, Qt::BackgroundRole, ColorUtils::expert_color_note);
break;
case(PI_WARN):
- item->setData(0, Qt::BackgroundRole, expert_color_warn);
+ item->setData(0, Qt::BackgroundRole, ColorUtils::expert_color_warn);
break;
case(PI_ERROR):
- item->setData(0, Qt::BackgroundRole, expert_color_error);
+ item->setData(0, Qt::BackgroundRole, ColorUtils::expert_color_error);
break;
default:
g_assert_not_reached();
}
- item->setData(0, Qt::ForegroundRole, expert_color_foreground);
+ item->setData(0, Qt::ForegroundRole, ColorUtils::expert_color_foreground);
}
item->setText(0, label_ptr);
@@ -302,6 +296,25 @@ void ProtoTree::emitRelatedFrame(int related_frame, ft_framenum_type_t framenum_
emit relatedFrame(related_frame, framenum_type);
}
+// XXX We select the first match, which might not be the desired item.
+void ProtoTree::goToField(int hf_id)
+{
+ if (hf_id < 0) return;
+
+ QTreeWidgetItemIterator iter(this);
+ while (*iter) {
+ field_info *fi = (*iter)->data(0, Qt::UserRole).value<field_info *>();
+
+ if (fi && fi->hfinfo) {
+ if (fi->hfinfo->id == hf_id) {
+ setCurrentItem(*iter);
+ break;
+ }
+ }
+ iter++;
+ }
+}
+
void ProtoTree::updateSelectionStatus(QTreeWidgetItem* item) {
if (item) {
diff --git a/ui/qt/proto_tree.h b/ui/qt/proto_tree.h
index b883308b1b..92cd3e1291 100644
--- a/ui/qt/proto_tree.h
+++ b/ui/qt/proto_tree.h
@@ -38,6 +38,7 @@ public:
explicit ProtoTree(QWidget *parent = 0);
void fillProtocolTree(proto_tree *protocol_tree);
void emitRelatedFrame(int related_frame, ft_framenum_type_t framenum_type = FT_FRAMENUM_NONE);
+ void goToField(int hf_id);
void clear();
protected: