summaryrefslogtreecommitdiffstats
path: root/ui/qt/models/expert_info_model.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/qt/models/expert_info_model.cpp')
-rw-r--r--ui/qt/models/expert_info_model.cpp424
1 files changed, 424 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 0000000..017dba3
--- /dev/null
+++ b/ui/qt/models/expert_info_model.cpp
@@ -0,0 +1,424 @@
+/* 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-or-later
+ */
+
+#include "expert_info_model.h"
+
+#include "file.h"
+#include <epan/proto.h>
+
+ExpertPacketItem::ExpertPacketItem(const 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()
+{
+ for (int row = 0; row < childItems_.count(); row++)
+ {
+ delete childItems_.value(row);
+ }
+
+ childItems_.clear();
+}
+
+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 static_cast<int>(childItems_.count());
+}
+
+int ExpertPacketItem::row() const
+{
+ if (parentItem_)
+ return static_cast<int>(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())
+{
+}
+
+ExpertInfoModel::~ExpertInfoModel()
+{
+ delete root_;
+}
+
+void ExpertInfoModel::clear()
+{
+ beginResetModel();
+
+ eventCounts_.clear();
+ delete root_;
+ root_ = createRootItem();
+
+ endResetModel();
+}
+
+ExpertPacketItem* ExpertInfoModel::createRootItem()
+{
+ static const char* rootName = "ROOT";
+DIAG_OFF_CAST_AWAY_CONST
+ static expert_info_t root_expert = { 0, -1, -1, -1, rootName, (gchar*)rootName, NULL };
+DIAG_ON_CAST_AWAY_CONST
+
+ 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 && role != Qt::ToolTipRole))
+ return QVariant();
+
+ ExpertPacketItem* item = static_cast<ExpertPacketItem*>(index.internalPointer());
+ if (item == NULL)
+ return QVariant();
+
+ if (role == Qt::ToolTipRole)
+ {
+ QString filterName = proto_registrar_get_abbrev(item->hfId());
+ return filterName;
+ }
+ else if (role == Qt::DisplayRole)
+ {
+ 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 (item->severity() == PI_COMMENT)
+ return item->summary().simplified();
+ if (group_by_summary_)
+ return item->colInfo().simplified();
+
+ return item->summary().simplified();
+ }
+ else
+ {
+ if (group_by_summary_)
+ {
+ if (item->severity() == PI_COMMENT)
+ return "Packet comments listed below.";
+ if (item->hfId() != -1) {
+ return proto_registrar_get_name(item->hfId());
+ } else {
+ 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)
+{
+ beginResetModel();
+ group_by_summary_ = group_by_summary;
+ 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(const 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();
+}
+
+tap_packet_status ExpertInfoModel::tapPacket(void *eid_ptr, struct _packet_info *pinfo, struct epan_dissect *, const void *data, tap_flags_t)
+{
+ ExpertInfoModel *model = static_cast<ExpertInfoModel*>(eid_ptr);
+ const expert_info_t *expert_info = (const expert_info_t *) data;
+ tap_packet_status status = TAP_PACKET_DONT_REDRAW;
+
+ if (!pinfo || !model || !expert_info)
+ return TAP_PACKET_DONT_REDRAW;
+
+ model->addExpertInfo(*expert_info);
+
+ status = TAP_PACKET_REDRAW;
+
+ model->eventCounts_[(enum ExpertSeverity)expert_info->severity]++;
+
+ return status;
+}
+
+void ExpertInfoModel::tapDraw(void *eid_ptr)
+{
+ ExpertInfoModel *model = static_cast<ExpertInfoModel*>(eid_ptr);
+ if (!model)
+ return;
+
+ model->beginResetModel();
+ model->endResetModel();
+}