1 /* capture_info_dialog.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "wireshark.h"
14 #include "ui/capture_info.h"
16 #include "epan/capture_dissectors.h"
17 #include "epan/proto.h"
19 #include "ui/capture.h"
21 #include "capture_info_dialog.h"
22 #include <ui_capture_info_dialog.h>
24 #include "main_application.h"
26 #include "ui/qt/models/sparkline_delegate.h"
28 #include "utils/qt_ui_utils.h"
30 #include <QMainWindow>
31 #include <QPushButton>
33 // The GTK+ version of this dialog showed a list of protocols and a simple bar graph
34 // (progress bars) showing their portion of the total number of packets. We show a
35 // a time series for each protocol using a sparkline. If we wanted to show bar graphs
36 // instead we could do so using QProgressBars or using PercentBarDelegates.
40 // Callbacks defined in ui/capture_info.h.
42 /* create the capture info dialog */
43 /* will keep pointers to the fields in the counts parameter */
44 void capture_info_ui_create(
46 capture_session
*cap_session
)
48 // cinfo->ui should have three values:
49 // - The main window, set in MainWindow::startCapture.
50 // - This dialog, set below.
51 // - NULL, set in our destructor.
53 if (!cinfo
|| !cinfo
->ui
) return;
54 if (!cap_session
) return;
55 QMainWindow
*main_window
= qobject_cast
<QMainWindow
*>((QObject
*)cinfo
->ui
);
56 if (!main_window
) return;
58 // ...and we take it over from here.
59 CaptureInfoDialog
*ci_dlg
= new CaptureInfoDialog(cinfo
, cap_session
, main_window
);
64 /* update the capture info dialog */
65 /* As this function is a bit time critical while capturing, */
66 /* prepare everything possible in the capture_info_ui_create() function above! */
67 void capture_info_ui_update(
70 CaptureInfoDialog
*ci_dlg
= qobject_cast
<CaptureInfoDialog
*>((QObject
*)cinfo
->ui
);
75 /* destroy the capture info dialog again */
76 void capture_info_ui_destroy(
79 CaptureInfoDialog
*ci_dlg
= qobject_cast
<CaptureInfoDialog
*>((QObject
*)cinfo
->ui
);
87 CaptureInfoDialog::CaptureInfoDialog(struct _capture_info
*cap_info
, struct _capture_session
*cap_session
, QWidget
*parent
) :
88 GeometryStateDialog(parent
),
89 ui(new Ui::CaptureInfoDialog
),
91 cap_session_(cap_session
)
95 setWindowTitle(mainApp
->windowTitleString(tr("Capture Information")));
97 QPushButton
*button
= ui
->buttonBox
->button(QDialogButtonBox::Abort
);
98 button
->setText(tr("Stop Capture"));
99 connect(button
, &QPushButton::clicked
, this, &CaptureInfoDialog::stopCapture
);
101 ci_model_
= new CaptureInfoModel(cap_info
, this);
102 ui
->treeView
->setModel(ci_model_
);
104 ui
->treeView
->setItemDelegateForColumn(1, new SparkLineDelegate(this));
109 CaptureInfoDialog::~CaptureInfoDialog()
112 cap_info_
->ui
= NULL
;
115 void CaptureInfoDialog::updateInfo()
117 int secs
= int(duration_
.elapsed() / 1000);
118 QString duration
= tr("%1 packets, %2:%3:%4")
119 .arg(cap_info_
->counts
->total
)
120 .arg(secs
/ 3600, 2, 10, QChar('0'))
121 .arg(secs
% 3600 / 60, 2, 10, QChar('0'))
122 .arg(secs
% 60, 2, 10, QChar('0'));
123 ui
->infoLabel
->setText(duration
);
125 ci_model_
->updateInfo();
126 ui
->treeView
->resizeColumnToContents(0);
129 void CaptureInfoDialog::stopCapture()
132 capture_stop(cap_session_
); // ...or we could connect to MainWindow::stopCapture.
133 #endif // HAVE_LIBPCAP
136 CaptureInfoModel::CaptureInfoModel(struct _capture_info
*cap_info
, QObject
*parent
) :
137 QAbstractTableModel(parent
),
144 void CaptureInfoModel::updateInfo()
146 if (!cap_info_
) return;
152 other_points_
.append(cap_info_
->counts
->other
- last_other_
);
153 last_other_
= cap_info_
->counts
->other
;
155 g_hash_table_iter_init (&iter
, cap_info_
->counts
->counts_hash
);
156 while (g_hash_table_iter_next (&iter
, &key
, &value
)) {
157 int proto_id
= GPOINTER_TO_INT(key
);
158 int cur_count
= (int) capture_dissector_get_count(cap_info_
->counts
, proto_id
);
159 if (!points_
.contains(proto_id
)) {
160 emit
beginInsertRows(QModelIndex(), rowCount(), rowCount());
161 QVector
<int> zeroes
= QVector
<int>(samples_
, 0);
162 points_
[proto_id
] = zeroes
.toList();
163 last_count_
[proto_id
] = 0;
164 emit
endInsertRows();
166 points_
[proto_id
].append(cur_count
- last_count_
[proto_id
]);
167 last_count_
[proto_id
] = cur_count
;
170 emit
dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
173 int CaptureInfoModel::rowCount(const QModelIndex
&) const
175 if (!cap_info_
) return 0;
176 return static_cast<int>(points_
.keys().size()) + 1;
179 int CaptureInfoModel::columnCount(const QModelIndex
&) const
184 QVariant
CaptureInfoModel::data(const QModelIndex
&index
, int role
) const
186 QList
<int> proto_ids
= points_
.keys();
187 int row
= index
.row();
189 if (role
== Qt::DisplayRole
&& index
.column() == 0) {
190 if (row
< proto_ids
.size()) {
191 int proto_id
= proto_ids
.at(row
);
192 return QString(proto_get_protocol_short_name(find_protocol_by_id(proto_id
)));
196 } else if (role
== Qt::UserRole
&& index
.column() == 1) {
197 if (row
< proto_ids
.size()) {
198 int proto_id
= proto_ids
.at(row
);
199 return QVariant::fromValue(points_
[proto_id
]);
201 return QVariant::fromValue(other_points_
);