diff options
Diffstat (limited to '')
-rw-r--r-- | ui/qt/models/expert_info_proxy_model.cpp | 290 |
1 files changed, 290 insertions, 0 deletions
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 0000000..ac13eff --- /dev/null +++ b/ui/qt/models/expert_info_proxy_model.cpp @@ -0,0 +1,290 @@ +/* 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 <ui/qt/models/expert_info_model.h> +#include <ui/qt/models/expert_info_proxy_model.h> +#include <ui/qt/utils/color_utils.h> + +#include <QRegularExpression> + +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: + { + 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 foreground color for groups + switch(item->severity()) { + case(PI_COMMENT): + case(PI_CHAT): + case(PI_NOTE): + case(PI_WARN): + case(PI_ERROR): + return QBrush(ColorUtils::expert_color_foreground); + } + } + break; + 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()) { + QRegularExpression regex(textFilter_, QRegularExpression::CaseInsensitiveOption | + QRegularExpression::UseUnicodePropertiesOption); + if (! regex.isValid()) + return false; + + 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(); +} |