diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /ui/qt/expert_info_dialog.cpp | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ui/qt/expert_info_dialog.cpp')
-rw-r--r-- | ui/qt/expert_info_dialog.cpp | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/ui/qt/expert_info_dialog.cpp b/ui/qt/expert_info_dialog.cpp new file mode 100644 index 0000000..38fa449 --- /dev/null +++ b/ui/qt/expert_info_dialog.cpp @@ -0,0 +1,353 @@ +/* expert_info_dialog.cpp + * + * 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_dialog.h" +#include <ui_expert_info_dialog.h> + +#include "file.h" + +#include <epan/epan_dissect.h> +#include <epan/expert.h> +#include <epan/stat_tap_ui.h> +#include <epan/tap.h> + +#include "progress_frame.h" +#include "main_application.h" + +#include <QAction> +#include <QHash> +#include <QMenu> +#include <QMessageBox> +#include <QPushButton> + +// To do: +// - Test with custom expert levels (Preferences -> Expert). +// - Test with large captures. +// - 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. + +ExpertInfoDialog::ExpertInfoDialog(QWidget &parent, CaptureFile &capture_file, QString displayFilter) : + WiresharkDialog(parent, capture_file), + ui(new Ui::ExpertInfoDialog), + expert_info_model_(new ExpertInfoModel(capture_file)), + proxyModel_(new ExpertInfoProxyModel(this)), + display_filter_(displayFilter) +{ + ui->setupUi(this); + ui->hintLabel->setSmallText(); + ui->limitCheckBox->setChecked(! display_filter_.isEmpty()); + connect(ui->limitCheckBox, &QCheckBox::toggled, + this, &ExpertInfoDialog::limitCheckBoxToggled); + + proxyModel_->setSourceModel(expert_info_model_); + ui->expertInfoTreeView->setModel(proxyModel_); + + 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. + int dlg_width = parent.width() * 3 / 5; + if (dlg_width < width()) dlg_width = width(); + loadGeometry(dlg_width, parent.height()); + + int one_em = fontMetrics().height(); + ui->expertInfoTreeView->setColumnWidth(ExpertInfoProxyModel::colProxySummary, one_em * 25); // Arbitrary + + //Unfortunately this has to be done manually and not through .ui + ui->severitiesPushButton->setMenu(ui->menuShowExpert); + + ui->expertInfoTreeView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->expertInfoTreeView, SIGNAL(customContextMenuRequested(QPoint)), + SLOT(showExpertInfoMenu(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())); + } + + //Add collapse/expand all menu options + QAction *collapse = new QAction(tr("Collapse All"), this); + ctx_menu_.addAction(collapse); + connect(collapse, SIGNAL(triggered()), this, SLOT(collapseTree())); + + QAction *expand = new QAction(tr("Expand All"), this); + ctx_menu_.addAction(expand); + connect(expand, SIGNAL(triggered()), this, SLOT(expandTree())); + + connect(&cap_file_, SIGNAL(captureEvent(CaptureEvent)), + this, SLOT(captureEvent(CaptureEvent))); + + ProgressFrame::addToButtonBox(ui->buttonBox, &parent); + + updateWidgets(); + QTimer::singleShot(0, this, SLOT(retapPackets())); +} + +ExpertInfoDialog::~ExpertInfoDialog() +{ + delete ui; + delete proxyModel_; + delete expert_info_model_; +} + +void ExpertInfoDialog::clearAllData() +{ + expert_info_model_->clear(); +} + +ExpertInfoTreeView* ExpertInfoDialog::getExpertInfoView() +{ + return ui->expertInfoTreeView; +} + +void ExpertInfoDialog::retapPackets() +{ + if (file_closed_) return; + + clearAllData(); + removeTapListeners(); + + if (!registerTapListener("expert", + expert_info_model_, + ui->limitCheckBox->isChecked() ? display_filter_.toUtf8().constData(): NULL, + TL_REQUIRES_COLUMNS, + ExpertInfoModel::tapReset, + ExpertInfoModel::tapPacket, + ExpertInfoModel::tapDraw)) { + return; + } + + cap_file_.retapPackets(); +} + +void ExpertInfoDialog::captureEvent(CaptureEvent e) +{ + if (e.captureContext() == CaptureEvent::Retap) + { + switch (e.eventType()) + { + case CaptureEvent::Started: + ui->limitCheckBox->setEnabled(false); + ui->groupBySummaryCheckBox->setEnabled(false); + break; + case CaptureEvent::Finished: + updateWidgets(); + break; + default: + break; + } + } +} + +void ExpertInfoDialog::updateWidgets() +{ + ui->limitCheckBox->setEnabled(! file_closed_ && ! display_filter_.isEmpty()); + + ui->actionShowError->setEnabled(expert_info_model_->numEvents(ExpertInfoModel::severityError) > 0); + ui->actionShowWarning->setEnabled(expert_info_model_->numEvents(ExpertInfoModel::severityWarn) > 0); + ui->actionShowNote->setEnabled(expert_info_model_->numEvents(ExpertInfoModel::severityNote) > 0); + ui->actionShowChat->setEnabled(expert_info_model_->numEvents(ExpertInfoModel::severityChat) > 0); + ui->actionShowComment->setEnabled(expert_info_model_->numEvents(ExpertInfoModel::severityComment) > 0); + + 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); + ui->hintLabel->setText(hint); + + ui->groupBySummaryCheckBox->setEnabled(!file_closed_); +} + +void ExpertInfoDialog::on_actionShowError_toggled(bool checked) +{ + proxyModel_->setSeverityFilter(PI_ERROR, !checked); + updateWidgets(); +} + +void ExpertInfoDialog::on_actionShowWarning_toggled(bool checked) +{ + proxyModel_->setSeverityFilter(PI_WARN, !checked); + updateWidgets(); +} + +void ExpertInfoDialog::on_actionShowNote_toggled(bool checked) +{ + proxyModel_->setSeverityFilter(PI_NOTE, !checked); + updateWidgets(); +} + +void ExpertInfoDialog::on_actionShowChat_toggled(bool checked) +{ + proxyModel_->setSeverityFilter(PI_CHAT, !checked); + updateWidgets(); +} + +void ExpertInfoDialog::on_actionShowComment_toggled(bool checked) +{ + proxyModel_->setSeverityFilter(PI_COMMENT, !checked); + updateWidgets(); +} + + +void ExpertInfoDialog::showExpertInfoMenu(QPoint pos) +{ + bool enable = true; + QModelIndex expertIndex = ui->expertInfoTreeView->indexAt(pos); + if (!expertIndex.isValid()) { + return; + } + + if (proxyModel_->data(expertIndex.sibling(expertIndex.row(), ExpertInfoModel::colHf), Qt::DisplayRole).toInt() < 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->expertInfoTreeView->viewport()->mapToGlobal(pos)); +} + +void ExpertInfoDialog::filterActionTriggered() +{ + QModelIndex modelIndex = ui->expertInfoTreeView->currentIndex(); + FilterAction *fa = qobject_cast<FilterAction *>(QObject::sender()); + + if (!fa || !modelIndex.isValid()) { + return; + } + + int hf_index = proxyModel_->data(modelIndex.sibling(modelIndex.row(), ExpertInfoModel::colHf), Qt::DisplayRole).toInt(); + + if (hf_index > -1) { + QString filter_string; + if (fa->action() == FilterAction::ActionWebLookup) { + filter_string = QString("%1 %2") + .arg(proxyModel_->data(modelIndex.sibling(modelIndex.row(), ExpertInfoModel::colProtocol), Qt::DisplayRole).toString()) + .arg(proxyModel_->data(modelIndex.sibling(modelIndex.row(), ExpertInfoModel::colSummary), Qt::DisplayRole).toString()); + } else if (fa->action() == FilterAction::ActionCopy) { + filter_string = QString("%1 %2: %3") + .arg(proxyModel_->data(modelIndex.sibling(modelIndex.row(), ExpertInfoModel::colPacket), Qt::DisplayRole).toUInt()) + .arg(proxyModel_->data(modelIndex.sibling(modelIndex.row(), ExpertInfoModel::colProtocol), Qt::DisplayRole).toString()) + .arg(proxyModel_->data(modelIndex.sibling(modelIndex.row(), ExpertInfoModel::colSummary), Qt::DisplayRole).toString()); + } else { + filter_string = proto_registrar_get_abbrev(hf_index); + } + + if (! filter_string.isEmpty()) { + emit filterAction(filter_string, fa->action(), fa->actionType()); + } + } +} + +void ExpertInfoDialog::collapseTree() +{ + ui->expertInfoTreeView->collapseAll(); +} + +void ExpertInfoDialog::expandTree() +{ + ui->expertInfoTreeView->expandAll(); +} + +void ExpertInfoDialog::limitCheckBoxToggled(bool) +{ + retapPackets(); +} + +void ExpertInfoDialog::on_groupBySummaryCheckBox_toggled(bool) +{ + expert_info_model_->setGroupBySummary(ui->groupBySummaryCheckBox->isChecked()); +} + +// Show child (packet list) items that match the contents of searchLineEdit. +void ExpertInfoDialog::on_searchLineEdit_textChanged(const QString &search_re) +{ + proxyModel_->setSummaryFilter(search_re); +} + +void ExpertInfoDialog::on_buttonBox_helpRequested() +{ + mainApp->helpTopicAction(HELP_EXPERT_INFO_DIALOG); +} + +// Stat command + args + +static void +expert_info_init(const char *, void*) { + mainApp->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_qt_expert_info(void); + +void +register_tap_listener_qt_expert_info(void) +{ + register_stat_tap_ui(&expert_info_stat_ui, NULL); +} + +} |