aboutsummaryrefslogtreecommitdiffstats
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.cpp406
1 files changed, 406 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:
+ */