aboutsummaryrefslogtreecommitdiffstats
path: root/ui/qt/models
diff options
context:
space:
mode:
Diffstat (limited to 'ui/qt/models')
-rw-r--r--ui/qt/models/expert_info_model.cpp406
-rw-r--r--ui/qt/models/expert_info_model.h140
-rw-r--r--ui/qt/models/expert_info_proxy_model.cpp278
-rw-r--r--ui/qt/models/expert_info_proxy_model.h73
4 files changed, 897 insertions, 0 deletions
diff --git a/ui/qt/models/expert_info_model.cpp b/ui/qt/models/expert_info_model.cpp
new file mode 100644
index 0000000000..326a369290
--- /dev/null
+++ b/ui/qt/models/expert_info_model.cpp
@@ -0,0 +1,406 @@
+/* expert_info_model.cpp
+ * Data model for Expert Info tap data.
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "expert_info_model.h"
+#include <ui/qt/utils/color_utils.h>
+
+#include "file.h"
+
+ExpertPacketItem::ExpertPacketItem(expert_info_t& expert_info, column_info *cinfo, ExpertPacketItem* parent) :
+ packet_num_(expert_info.packet_num),
+ group_(expert_info.group),
+ severity_(expert_info.severity),
+ hf_id_(expert_info.hf_index),
+ protocol_(expert_info.protocol),
+ summary_(expert_info.summary),
+ parentItem_(parent)
+{
+ if (cinfo) {
+ info_ = col_get_text(cinfo, COL_INFO);
+ }
+}
+
+ExpertPacketItem::~ExpertPacketItem()
+{
+}
+
+QString ExpertPacketItem::groupKey(bool group_by_summary, int severity, int group, QString protocol, int expert_hf)
+{
+ QString key = QString("%1|%2|%3")
+ .arg(severity)
+ .arg(group)
+ .arg(protocol);
+ if (group_by_summary) {
+ key += QString("|%1").arg(expert_hf);
+ }
+ return key;
+}
+
+QString ExpertPacketItem::groupKey(bool group_by_summary) {
+ return groupKey(group_by_summary, severity_, group_, protocol_, hf_id_);
+}
+
+void ExpertPacketItem::appendChild(ExpertPacketItem* child, QString hash)
+{
+ childItems_.append(child);
+ hashChild_[hash] = child;
+}
+
+ExpertPacketItem* ExpertPacketItem::child(int row)
+{
+ return childItems_.value(row);
+}
+
+ExpertPacketItem* ExpertPacketItem::child(QString hash)
+{
+ return hashChild_[hash];
+}
+
+int ExpertPacketItem::childCount() const
+{
+ return childItems_.count();
+}
+
+int ExpertPacketItem::row() const
+{
+ if (parentItem_)
+ return parentItem_->childItems_.indexOf(const_cast<ExpertPacketItem*>(this));
+
+ return 0;
+}
+
+ExpertPacketItem* ExpertPacketItem::parentItem()
+{
+ return parentItem_;
+}
+
+
+
+
+ExpertInfoModel::ExpertInfoModel(CaptureFile& capture_file, QObject *parent) :
+ QAbstractItemModel(parent),
+ capture_file_(capture_file),
+ group_by_summary_(true),
+ root_(createRootItem())
+{
+}
+
+void ExpertInfoModel::clear()
+{
+ emit beginResetModel();
+
+ eventCounts_.clear();
+ delete root_;
+ root_ = createRootItem();
+
+ emit endResetModel();
+}
+
+ExpertPacketItem* ExpertInfoModel::createRootItem()
+{
+ static const char* rootName = "ROOT";
+ static expert_info_t root_expert = { 0, -1, -1, -1, rootName, (gchar*)rootName, NULL };
+
+ return new ExpertPacketItem(root_expert, NULL, NULL);
+}
+
+
+
+int ExpertInfoModel::numEvents(enum ExpertSeverity severity)
+{
+ return eventCounts_[severity];
+}
+
+QModelIndex ExpertInfoModel::index(int row, int column, const QModelIndex& parent) const
+{
+ if (!hasIndex(row, column, parent))
+ return QModelIndex();
+
+ ExpertPacketItem *parent_item, *child_item;
+
+ if (!parent.isValid())
+ parent_item = root_;
+ else
+ parent_item = static_cast<ExpertPacketItem*>(parent.internalPointer());
+
+ Q_ASSERT(parent_item);
+ if (group_by_summary_) {
+ //don't allow group layer
+ if (parent_item == root_) {
+ int row_count = 0;
+ ExpertPacketItem *grandchild_item;
+
+ for (int subrow = 0; subrow < parent_item->childCount(); subrow++) {
+ child_item = parent_item->child(subrow);
+ //summary children are always stored in first child of group
+ grandchild_item = child_item->child(0);
+
+ if (row_count+grandchild_item->childCount() > row) {
+ return createIndex(row, column, grandchild_item->child(row-row_count));
+ }
+ row_count += grandchild_item->childCount();
+ }
+
+ //shouldn't happen
+ return QModelIndex();
+ }
+
+ int root_level = 0;
+ ExpertPacketItem *item = parent_item;
+ while (item != root_)
+ {
+ root_level++;
+ item = item->parentItem();
+ }
+
+ if (root_level == 3) {
+ child_item = parent_item->child(row);
+ if (child_item) {
+ return createIndex(row, column, child_item);
+ }
+ }
+
+ } else {
+ child_item = parent_item->child(row);
+ if (child_item) {
+ //only allow 2 levels deep
+ if (((parent_item == root_) || (parent_item->parentItem() == root_)))
+ return createIndex(row, column, child_item);
+ }
+ }
+ return QModelIndex();
+}
+
+QModelIndex ExpertInfoModel::parent(const QModelIndex& index) const
+{
+ if (!index.isValid())
+ return QModelIndex();
+
+ ExpertPacketItem *item = static_cast<ExpertPacketItem*>(index.internalPointer());
+ ExpertPacketItem *parent_item = item->parentItem();
+
+ if (group_by_summary_)
+ {
+ //don't allow group layer
+ int root_level = 0;
+ item = parent_item;
+ while ((item != root_) && (item != NULL))
+ {
+ root_level++;
+ item = item->parentItem();
+ }
+
+ if (root_level == 3)
+ return createIndex(parent_item->row(), 0, parent_item);
+
+ } else {
+ if (parent_item == root_)
+ return QModelIndex();
+
+ return createIndex(parent_item->row(), 0, parent_item);
+ }
+
+ return QModelIndex();
+}
+
+#if 0
+Qt::ItemFlags ExpertInfoModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return 0;
+
+ ExpertPacketItem* item = static_cast<ExpertPacketItem*>(index.internalPointer());
+ Qt::ItemFlags flags = QAbstractTableModel::flags(index);
+
+ //collapse???
+ return flags;
+}
+#endif
+
+QVariant ExpertInfoModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || role != Qt::DisplayRole)
+ return QVariant();
+
+ ExpertPacketItem* item = static_cast<ExpertPacketItem*>(index.internalPointer());
+ if (item == NULL)
+ return QVariant();
+
+ switch ((enum ExpertColumn)index.column()) {
+ case colSeverity:
+ return QString(val_to_str_const(item->severity(), expert_severity_vals, "Unknown"));
+ case colSummary:
+ if (index.parent().isValid())
+ {
+ if (group_by_summary_)
+ return item->colInfo().simplified();
+
+ return item->summary().simplified();
+ }
+ else
+ {
+ if (group_by_summary_)
+ return item->summary().simplified();
+ }
+ return QVariant();
+ case colGroup:
+ return QString(val_to_str_const(item->group(), expert_group_vals, "Unknown"));
+ case colProtocol:
+ return item->protocol();
+ case colCount:
+ if (!index.parent().isValid())
+ {
+ return item->childCount();
+ }
+ break;
+ case colPacket:
+ return item->packetNum();
+ case colHf:
+ return item->hfId();
+ default:
+ break;
+ }
+
+ return QVariant();
+}
+
+//GUI helpers
+void ExpertInfoModel::setGroupBySummary(bool group_by_summary)
+{
+ emit beginResetModel();
+ group_by_summary_ = group_by_summary;
+ emit endResetModel();
+}
+
+int ExpertInfoModel::rowCount(const QModelIndex &parent) const
+{
+ ExpertPacketItem *parent_item;
+ if (parent.column() > 0)
+ return 0;
+
+ if (!parent.isValid())
+ parent_item = root_;
+ else
+ parent_item = static_cast<ExpertPacketItem*>(parent.internalPointer());
+
+ if (group_by_summary_) {
+ int row_count = 0;
+
+ //don't allow group layer
+ if (parent_item == root_) {
+ ExpertPacketItem *child_item, *grandchild_item;
+
+ for (int row = 0; row < parent_item->childCount(); row++) {
+ child_item = parent_item->child(row);
+ grandchild_item = child_item->child(0);
+ row_count += grandchild_item->childCount();
+ }
+
+ return row_count;
+ }
+
+ return parent_item->childCount();
+
+ } else {
+ //only allow 2 levels deep
+ if ((parent_item == root_) || (parent_item->parentItem() == root_))
+ return parent_item->childCount();
+ }
+
+ return 0;
+}
+
+int ExpertInfoModel::columnCount(const QModelIndex& ) const
+{
+ return colLast;
+}
+
+void ExpertInfoModel::addExpertInfo(struct expert_info_s& expert_info)
+{
+ QString groupKey = ExpertPacketItem::groupKey(FALSE, expert_info.severity, expert_info.group, QString(expert_info.protocol), expert_info.hf_index);
+ QString summaryKey = ExpertPacketItem::groupKey(TRUE, expert_info.severity, expert_info.group, QString(expert_info.protocol), expert_info.hf_index);
+
+ ExpertPacketItem* expert_root = root_->child(groupKey);
+ if (expert_root == NULL) {
+ ExpertPacketItem *new_item = new ExpertPacketItem(expert_info, &(capture_file_.capFile()->cinfo), root_);
+
+ root_->appendChild(new_item, groupKey);
+
+ expert_root = new_item;
+ }
+
+ ExpertPacketItem *expert = new ExpertPacketItem(expert_info, &(capture_file_.capFile()->cinfo), expert_root);
+ expert_root->appendChild(expert, groupKey);
+
+ //add the summary children off of the first child of the root children
+ ExpertPacketItem* summary_root = expert_root->child(0);
+
+ //make a summary child
+ ExpertPacketItem* expert_summary_root = summary_root->child(summaryKey);
+ if (expert_summary_root == NULL) {
+ ExpertPacketItem *new_summary = new ExpertPacketItem(expert_info, &(capture_file_.capFile()->cinfo), summary_root);
+
+ summary_root->appendChild(new_summary, summaryKey);
+ expert_summary_root = new_summary;
+ }
+
+ ExpertPacketItem *expert_summary = new ExpertPacketItem(expert_info, &(capture_file_.capFile()->cinfo), expert_summary_root);
+ expert_summary_root->appendChild(expert_summary, summaryKey);
+}
+
+void ExpertInfoModel::tapReset(void *eid_ptr)
+{
+ ExpertInfoModel *model = static_cast<ExpertInfoModel*>(eid_ptr);
+ if (!model)
+ return;
+
+ model->clear();
+}
+
+gboolean ExpertInfoModel::tapPacket(void *eid_ptr, struct _packet_info *pinfo, struct epan_dissect *, const void *data)
+{
+ ExpertInfoModel *model = static_cast<ExpertInfoModel*>(eid_ptr);
+ expert_info_t *expert_info = (expert_info_t *) data;
+ gboolean draw_required = FALSE;
+
+ if (!pinfo || !model || !expert_info)
+ return FALSE;
+
+ model->addExpertInfo(*expert_info);
+
+ if (model->numEvents((enum ExpertSeverity)expert_info->severity) < 1)
+ draw_required = TRUE;
+
+ model->eventCounts_[(enum ExpertSeverity)expert_info->severity]++;
+
+ return draw_required;
+}
+
+void ExpertInfoModel::tapDraw(void *eid_ptr)
+{
+ ExpertInfoModel *model = static_cast<ExpertInfoModel*>(eid_ptr);
+ if (!model)
+ return;
+
+ emit model->beginResetModel();
+ emit model->endResetModel();
+}
+
+/* * 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/models/expert_info_model.h b/ui/qt/models/expert_info_model.h
new file mode 100644
index 0000000000..471cd6700a
--- /dev/null
+++ b/ui/qt/models/expert_info_model.h
@@ -0,0 +1,140 @@
+/* expert_info_model.h
+ * Data model for Expert Info tap data.
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef EXPERT_INFO_MODEL_H
+#define EXPERT_INFO_MODEL_H
+
+#include <config.h>
+
+#include <QAbstractItemModel>
+#include <QList>
+#include <QMap>
+
+#include <ui/qt/capture_file.h>
+
+#include <epan/expert.h>
+#include <epan/column-utils.h>
+
+class ExpertPacketItem
+{
+public:
+ ExpertPacketItem(expert_info_t& expert_info, column_info *cinfo, ExpertPacketItem* parent);
+ virtual ~ExpertPacketItem();
+
+ unsigned int packetNum() const { return packet_num_; }
+ int group() const { return group_; }
+ int severity() const { return severity_; }
+ int hfId() const { return hf_id_; }
+ QString protocol() const { return protocol_; }
+ QString summary() const { return summary_; }
+ QString colInfo() const { return info_; }
+
+ static QString groupKey(bool group_by_summary, int severity, int group, QString protocol, int expert_hf);
+ QString groupKey(bool group_by_summary);
+
+ void appendChild(ExpertPacketItem* child, QString hash);
+ ExpertPacketItem* child(int row);
+ ExpertPacketItem* child(QString hash);
+ int childCount() const;
+ int row() const;
+ ExpertPacketItem* parentItem();
+
+private:
+ unsigned int packet_num_;
+ int group_;
+ int severity_;
+ int hf_id_;
+ // Half-hearted attempt at conserving memory. If this isn't sufficient,
+ // PacketListRecord interns column strings in a GStringChunk.
+ QByteArray protocol_;
+ QByteArray summary_;
+ QByteArray info_;
+
+ QList<ExpertPacketItem*> childItems_;
+ ExpertPacketItem* parentItem_;
+ QHash<QString, ExpertPacketItem*> hashChild_; //optimization for insertion
+};
+
+class ExpertInfoModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ ExpertInfoModel(CaptureFile& capture_file, QObject *parent = 0);
+
+ enum ExpertColumn {
+ colSeverity = 0,
+ colSummary,
+ colGroup,
+ colProtocol,
+ colCount,
+ colPacket,
+ colHf,
+ colLast
+ };
+
+ enum ExpertSeverity {
+ severityError = PI_ERROR,
+ severityWarn = PI_WARN,
+ severityNote = PI_NOTE,
+ severityChat = PI_CHAT,
+ severityComment = PI_COMMENT
+ };
+
+ QModelIndex index(int row, int column,
+ const QModelIndex & = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &) const;
+#if 0
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+#endif
+ QVariant data(const QModelIndex &index, int role) const;
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+ int numEvents(enum ExpertSeverity severity);
+
+ void clear();
+
+ //GUI helpers
+ void setGroupBySummary(bool group_by_summary);
+
+ // Called from tapPacket
+ void addExpertInfo(struct expert_info_s& expert_info);
+
+ // Callbacks for register_tap_listener
+ static void tapReset(void *eid_ptr);
+ static gboolean tapPacket(void *eid_ptr, struct _packet_info *pinfo, struct epan_dissect *, const void *data);
+ static void tapDraw(void *eid_ptr);
+
+private:
+ CaptureFile& capture_file_;
+
+ ExpertPacketItem* createRootItem();
+
+ bool group_by_summary_;
+ ExpertPacketItem* root_;
+
+ QHash<enum ExpertSeverity, int> eventCounts_;
+};
+#endif // EXPERT_INFO_MODEL_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/models/expert_info_proxy_model.cpp b/ui/qt/models/expert_info_proxy_model.cpp
new file mode 100644
index 0000000000..68a1faf11f
--- /dev/null
+++ b/ui/qt/models/expert_info_proxy_model.cpp
@@ -0,0 +1,278 @@
+/* expert_info_model.cpp
+ * Data model for Expert Info tap data.
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <ui/qt/models/expert_info_model.h>
+#include <ui/qt/models/expert_info_proxy_model.h>
+#include <ui/qt/utils/color_utils.h>
+
+ExpertInfoProxyModel::ExpertInfoProxyModel(QObject *parent) : QSortFilterProxyModel(parent),
+ severityMode_(Group)
+{
+}
+
+bool ExpertInfoProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
+{
+ ExpertPacketItem *left_item,
+ *right_item;
+ QString leftStr, rightStr;
+ bool checkPacketNumber = false;
+ int compare_ret;
+
+ if (source_left.parent().isValid() && source_right.parent().isValid()) {
+ left_item = static_cast<ExpertPacketItem*>(source_left.parent().internalPointer());
+ right_item = static_cast<ExpertPacketItem*>(source_right.parent().internalPointer());
+ } else {
+ left_item = static_cast<ExpertPacketItem*>(source_left.internalPointer()),
+ right_item = static_cast<ExpertPacketItem*>(source_right.internalPointer());
+ }
+
+ if ((left_item != NULL) && (right_item != NULL)) {
+ switch (source_left.column())
+ {
+ case colProxySeverity:
+ if (left_item->severity() != right_item->severity()) {
+ return (left_item->severity() < right_item->severity());
+ }
+
+ checkPacketNumber = true;
+ break;
+ case colProxySummary:
+ compare_ret = left_item->summary().compare(right_item->summary());
+ if (compare_ret < 0)
+ return true;
+ if (compare_ret > 0)
+ return false;
+
+ checkPacketNumber = true;
+ break;
+ case colProxyGroup:
+ if (left_item->group() != right_item->group()) {
+ return (left_item->group() < right_item->group());
+ }
+
+ checkPacketNumber = true;
+ break;
+ case colProxyProtocol:
+ compare_ret = left_item->protocol().compare(right_item->protocol());
+ if (compare_ret < 0)
+ return true;
+ if (compare_ret > 0)
+ return false;
+
+ checkPacketNumber = true;
+ break;
+ case colProxyCount:
+ break;
+ default:
+ break;
+ }
+
+ if (checkPacketNumber) {
+ return (left_item->packetNum() < right_item->packetNum());
+ }
+ }
+
+ // fallback to string cmp on other fields
+ return QSortFilterProxyModel::lessThan(source_left, source_right);
+}
+
+QVariant ExpertInfoProxyModel::data(const QModelIndex &proxy_index, int role) const
+{
+ QModelIndex source_index;
+
+ switch (role)
+ {
+ case Qt::BackgroundRole:
+ {
+ source_index = mapToSource(proxy_index);
+
+ //only color base row
+ if (!source_index.isValid() || source_index.parent().isValid())
+ return QVariant();
+
+ ExpertPacketItem* item = static_cast<ExpertPacketItem*>(source_index.internalPointer());
+ if (item == NULL)
+ return QVariant();
+
+ // provide background color for groups
+ switch(item->severity()) {
+ case(PI_COMMENT):
+ return QBrush(ColorUtils::expert_color_comment);
+ case(PI_CHAT):
+ return QBrush(ColorUtils::expert_color_chat);
+ case(PI_NOTE):
+ return QBrush(ColorUtils::expert_color_note);
+ case(PI_WARN):
+ return QBrush(ColorUtils::expert_color_warn);
+ case(PI_ERROR):
+ return QBrush(ColorUtils::expert_color_error);
+ }
+ }
+ break;
+ case Qt::ForegroundRole:
+ // XXX Use plain colors until our users demand to be blinded.
+ return QBrush(ColorUtils::expert_color_foreground);
+ case Qt::TextAlignmentRole:
+ switch (proxy_index.column())
+ {
+ case colProxySeverity:
+ //packet number should be right aligned
+ if (source_index.parent().isValid())
+ return Qt::AlignRight;
+ break;
+ case colProxyCount:
+ return Qt::AlignRight;
+ default:
+ break;
+ }
+ return Qt::AlignLeft;
+
+ case Qt::DisplayRole:
+ source_index = mapToSource(proxy_index);
+
+ switch (proxy_index.column())
+ {
+ case colProxySeverity:
+ if (source_index.parent().isValid())
+ return sourceModel()->data(source_index.sibling(source_index.row(), ExpertInfoModel::colPacket), role);
+
+ return sourceModel()->data(source_index.sibling(source_index.row(), ExpertInfoModel::colSeverity), role);
+ case colProxySummary:
+ return sourceModel()->data(source_index.sibling(source_index.row(), ExpertInfoModel::colSummary), role);
+ case colProxyGroup:
+ return sourceModel()->data(source_index.sibling(source_index.row(), ExpertInfoModel::colGroup), role);
+ case colProxyProtocol:
+ return sourceModel()->data(source_index.sibling(source_index.row(), ExpertInfoModel::colProtocol), role);
+ case colProxyCount:
+ //only show counts for parent
+ if (!source_index.parent().isValid()) {
+ //because of potential filtering, count is computed manually
+ unsigned int count = 0;
+ ExpertPacketItem *child_item,
+ *item = static_cast<ExpertPacketItem*>(source_index.internalPointer());
+ for (int row = 0; row < item->childCount(); row++) {
+ child_item = item->child(row);
+ if (child_item == NULL)
+ continue;
+ if (filterAcceptItem(*child_item))
+ count++;
+ }
+
+ return count;
+ }
+ }
+ break;
+ }
+
+ return QSortFilterProxyModel::data(proxy_index, role);
+}
+
+QVariant ExpertInfoProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+
+ switch ((enum ExpertProxyColumn)section) {
+ case colProxySeverity:
+ if (severityMode_ == Packet)
+ return tr("Packet");
+ else
+ return tr("Severity");
+ case colProxySummary:
+ return tr("Summary");
+ case colProxyGroup:
+ return tr("Group");
+ case colProxyProtocol:
+ return tr("Protocol");
+ case colProxyCount:
+ return tr("Count");
+ default:
+ break;
+ }
+ }
+ return QVariant();
+}
+
+int ExpertInfoProxyModel::columnCount(const QModelIndex& ) const
+{
+ return colProxyLast;
+}
+
+bool ExpertInfoProxyModel::filterAcceptItem(ExpertPacketItem& item) const
+{
+ if (hidden_severities_.contains(item.severity()))
+ return false;
+
+ if (!textFilter_.isEmpty()) {
+ QRegExp regex(textFilter_, Qt::CaseInsensitive);
+
+ if (item.protocol().contains(regex))
+ return true;
+
+ if (item.summary().contains(regex))
+ return true;
+
+ if (item.colInfo().contains(regex))
+ return true;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool ExpertInfoProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+{
+ QModelIndex severityIdx = sourceModel()->index(sourceRow, ExpertInfoModel::colSeverity, sourceParent);
+ ExpertPacketItem* item = static_cast<ExpertPacketItem*>(severityIdx.internalPointer());
+ if (item == NULL)
+ return true;
+
+ return filterAcceptItem(*item);
+}
+
+//GUI helpers
+void ExpertInfoProxyModel::setSeverityMode(enum SeverityMode mode)
+{
+ severityMode_ = mode;
+ emit headerDataChanged(Qt::Vertical, 0, 1);
+}
+
+void ExpertInfoProxyModel::setSeverityFilter(int severity, bool hide)
+{
+ if (hide)
+ {
+ hidden_severities_ << severity;
+ }
+ else
+ {
+ hidden_severities_.removeOne(severity);
+ }
+
+ invalidateFilter();
+}
+
+void ExpertInfoProxyModel::setSummaryFilter(const QString &filter)
+{
+ textFilter_ = filter;
+ invalidateFilter();
+}
+
+
+/* * 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/models/expert_info_proxy_model.h b/ui/qt/models/expert_info_proxy_model.h
new file mode 100644
index 0000000000..3926e0e9e5
--- /dev/null
+++ b/ui/qt/models/expert_info_proxy_model.h
@@ -0,0 +1,73 @@
+/* expert_info_model.h
+ * Data model for Expert Info tap data.
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef EXPERT_INFO_PROXY_MODEL_H
+#define EXPERT_INFO_PROXY_MODEL_H
+
+#include <config.h>
+
+#include <QSortFilterProxyModel>
+
+class ExpertPacketItem;
+
+class ExpertInfoProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ ExpertInfoProxyModel(QObject *parent = 0);
+
+ enum SeverityMode { Group, Packet };
+ enum ExpertProxyColumn {
+ colProxySeverity = 0,
+ colProxySummary,
+ colProxyGroup,
+ colProxyProtocol,
+ colProxyCount,
+ colProxyLast
+ };
+
+ QVariant data(const QModelIndex &index, int role) const;
+ QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+ virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
+
+ //GUI helpers
+ void setSeverityMode(enum SeverityMode);
+ void setSeverityFilter(int severity, bool hide);
+ void setSummaryFilter(const QString &filter);
+
+protected:
+ bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
+ bool filterAcceptItem(ExpertPacketItem& item) const;
+
+ enum SeverityMode severityMode_;
+ QList<int> hidden_severities_;
+
+ QString textFilter_;
+
+};
+
+#endif // EXPERT_INFO_PROXY_MODEL_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:
+ */