summaryrefslogtreecommitdiffstats
path: root/ui/qt/capture_info_dialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ui/qt/capture_info_dialog.cpp205
1 files changed, 205 insertions, 0 deletions
diff --git a/ui/qt/capture_info_dialog.cpp b/ui/qt/capture_info_dialog.cpp
new file mode 100644
index 00000000..5a29652c
--- /dev/null
+++ b/ui/qt/capture_info_dialog.cpp
@@ -0,0 +1,205 @@
+/* capture_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 "config.h"
+
+#include "wireshark.h"
+
+#include "ui/capture_info.h"
+
+#include "epan/capture_dissectors.h"
+#include "epan/proto.h"
+
+#include "ui/capture.h"
+
+#include "capture_info_dialog.h"
+#include "ui_capture_info_dialog.h"
+
+#include "main_application.h"
+
+#include "ui/qt/models/sparkline_delegate.h"
+
+#include "utils/qt_ui_utils.h"
+
+#include <QMainWindow>
+#include <QPushButton>
+
+// The GTK+ version of this dialog showed a list of protocols and a simple bar graph
+// (progress bars) showing their portion of the total number of packets. We show a
+// a time series for each protocol using a sparkline. If we wanted to show bar graphs
+// instead we could do so using QProgressBars or using PercentBarDelegates.
+
+extern "C" {
+
+// Callbacks defined in ui/capture_info.h.
+
+/* create the capture info dialog */
+/* will keep pointers to the fields in the counts parameter */
+void capture_info_ui_create(
+capture_info *cinfo,
+capture_session *cap_session)
+{
+ // cinfo->ui should have three values:
+ // - The main window, set in MainWindow::startCapture.
+ // - This dialog, set below.
+ // - NULL, set in our destructor.
+
+ if (!cinfo || !cinfo->ui) return;
+ if (!cap_session) return;
+ QMainWindow *main_window = qobject_cast<QMainWindow *>((QObject *)cinfo->ui);
+ if (!main_window) return;
+
+ // ...and we take it over from here.
+ CaptureInfoDialog *ci_dlg = new CaptureInfoDialog(cinfo, cap_session, main_window);
+ cinfo->ui = ci_dlg;
+ ci_dlg->show();
+}
+
+/* update the capture info dialog */
+/* As this function is a bit time critical while capturing, */
+/* prepare everything possible in the capture_info_ui_create() function above! */
+void capture_info_ui_update(
+capture_info *cinfo)
+{
+ CaptureInfoDialog *ci_dlg = qobject_cast<CaptureInfoDialog *>((QObject *)cinfo->ui);
+ if (!ci_dlg) return;
+ ci_dlg->updateInfo();
+}
+
+/* destroy the capture info dialog again */
+void capture_info_ui_destroy(
+capture_info *cinfo)
+{
+ CaptureInfoDialog *ci_dlg = qobject_cast<CaptureInfoDialog *>((QObject *)cinfo->ui);
+ if (!ci_dlg) return;
+ cinfo->ui = NULL;
+ delete ci_dlg;
+}
+
+} // extern "C"
+
+CaptureInfoDialog::CaptureInfoDialog(struct _capture_info *cap_info, struct _capture_session *cap_session, QWidget *parent) :
+ GeometryStateDialog(parent),
+ ui(new Ui::CaptureInfoDialog),
+ cap_info_(cap_info),
+ cap_session_(cap_session)
+{
+ ui->setupUi(this);
+ loadGeometry();
+ setWindowTitle(mainApp->windowTitleString(tr("Capture Information")));
+
+ QPushButton *button = ui->buttonBox->button(QDialogButtonBox::Abort);
+ button->setText(tr("Stop Capture"));
+ connect(button, &QPushButton::clicked, this, &CaptureInfoDialog::stopCapture);
+
+ ci_model_ = new CaptureInfoModel(cap_info, this);
+ ui->treeView->setModel(ci_model_);
+
+ ui->treeView->setItemDelegateForColumn(1, new SparkLineDelegate(this));
+
+ duration_.start();
+}
+
+CaptureInfoDialog::~CaptureInfoDialog()
+{
+ delete ui;
+ cap_info_->ui = NULL;
+}
+
+void CaptureInfoDialog::updateInfo()
+{
+ int secs = int(duration_.elapsed() / 1000);
+ QString duration = tr("%1 packets, %2:%3:%4")
+ .arg(cap_info_->counts->total)
+ .arg(secs / 3600, 2, 10, QChar('0'))
+ .arg(secs % 3600 / 60, 2, 10, QChar('0'))
+ .arg(secs % 60, 2, 10, QChar('0'));
+ ui->infoLabel->setText(duration);
+
+ ci_model_->updateInfo();
+ ui->treeView->resizeColumnToContents(0);
+}
+
+void CaptureInfoDialog::stopCapture()
+{
+#ifdef HAVE_LIBPCAP
+ capture_stop(cap_session_); // ...or we could connect to MainWindow::stopCapture.
+#endif // HAVE_LIBPCAP
+}
+
+CaptureInfoModel::CaptureInfoModel(struct _capture_info *cap_info, QObject *parent) :
+ QAbstractTableModel(parent),
+ cap_info_(cap_info),
+ samples_(0),
+ last_other_(0)
+{
+}
+
+void CaptureInfoModel::updateInfo()
+{
+ if (!cap_info_) return;
+
+ GHashTableIter iter;
+ gpointer key, value;
+
+ samples_++;
+ other_points_.append(cap_info_->counts->other - last_other_);
+ last_other_ = cap_info_->counts->other;
+
+ g_hash_table_iter_init (&iter, cap_info_->counts->counts_hash);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ int proto_id = GPOINTER_TO_INT(key);
+ int cur_count = (int) capture_dissector_get_count(cap_info_->counts, proto_id);
+ if (!points_.contains(proto_id)) {
+ emit beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ QVector<int> zeroes = QVector<int>(samples_, 0);
+ points_[proto_id] = zeroes.toList();
+ last_count_[proto_id] = 0;
+ emit endInsertRows();
+ } else {
+ points_[proto_id].append(cur_count - last_count_[proto_id]);
+ last_count_[proto_id] = cur_count;
+ }
+ }
+ emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
+}
+
+int CaptureInfoModel::rowCount(const QModelIndex &) const
+{
+ if (!cap_info_) return 0;
+ return static_cast<int>(points_.keys().size()) + 1;
+}
+
+int CaptureInfoModel::columnCount(const QModelIndex &) const
+{
+ return 2;
+}
+
+QVariant CaptureInfoModel::data(const QModelIndex &index, int role) const
+{
+ QList<int> proto_ids = points_.keys();
+ int row = index.row();
+
+ if (role == Qt::DisplayRole && index.column() == 0) {
+ if (row < proto_ids.size()) {
+ int proto_id = proto_ids.at(row);
+ return QString(proto_get_protocol_short_name(find_protocol_by_id(proto_id)));
+ } else {
+ return tr("Other");
+ }
+ } else if (role == Qt::UserRole && index.column() == 1) {
+ if (row < proto_ids.size()) {
+ int proto_id = proto_ids.at(row);
+ return QVariant::fromValue(points_[proto_id]);
+ } else {
+ return QVariant::fromValue(other_points_);
+ }
+ }
+ return QVariant();
+}