1 /* capture_options_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 "capture_options_dialog.h"
15 #include <ui/qt/widgets/capture_filter_combo.h>
16 #include <ui_capture_options_dialog.h>
17 #include "compiled_filter_output.h"
18 #include "manage_interfaces_dialog.h"
20 #include "main_application.h"
26 #include <QAbstractItemModel>
27 #include <QMessageBox>
30 #include "ringbuffer.h"
31 #include "ui/capture_opts.h"
32 #include "ui/capture_ui_utils.h"
33 #include "ui/capture_globals.h"
35 #include "ui/ws_ui_util.h"
37 #include <wsutil/utf8_entities.h>
38 #include "ui/preference_utils.h"
39 #include "ui/recent.h"
42 #include <epan/prefs.h>
43 #include <epan/prefs-int.h>
44 #include <epan/addr_resolv.h>
45 #include <wsutil/filesystem.h>
47 #include <wiretap/wtap.h>
49 #include <ui/qt/utils/qt_ui_utils.h>
50 #include <ui/qt/utils/stock_icon.h>
51 #include <ui/qt/models/sparkline_delegate.h>
52 #include "ui/qt/widgets/wireshark_file_dialog.h"
55 // - Set a size hint for item delegates.
56 // - Make promiscuous and monitor mode checkboxes.
57 // - Fix InterfaceTreeDelegate method names.
58 // - You can edit filters via the main CaptureFilterCombo and via each
59 // individual interface row. We should probably do one or the other.
60 // - There might be a point in having the separate combo boxes in the
61 // individual interface row, if their CaptureFilterCombos actually
62 // called recent_get_cfilter_list with the interface name to get the
63 // separate list of recent capture filters for that interface, but
66 const int stat_update_interval_
= 1000; // ms
69 * Symbolic names for column indices.
85 static interface_t
*find_device_by_if_name(const QString
&interface_name
)
89 for (i
= 0; i
< global_capture_opts
.all_ifaces
->len
; i
++) {
90 device
= &g_array_index(global_capture_opts
.all_ifaces
, interface_t
, i
);
91 if (!interface_name
.compare(device
->display_name
) && !device
->hidden
&& device
->if_info
.type
!= IF_PIPE
) {
98 class InterfaceTreeWidgetItem
: public QTreeWidgetItem
101 InterfaceTreeWidgetItem(QTreeWidget
*tree
) : QTreeWidgetItem(tree
) {}
102 bool operator< (const QTreeWidgetItem
&other
) const;
103 QVariant
data(int column
, int role
) const;
104 void setData(int column
, int role
, const QVariant
&value
);
107 void updateInterfaceColumns(interface_t
*device
)
111 // Prevent infinite recursive signal loop
112 // itemChanged->interfaceItemChanged->updateInterfaceColumns
113 treeWidget()->blockSignals(true);
114 QString default_str
= QObject::tr("default");
116 // XXX - this is duplicated in InterfaceTreeModel::data;
117 // it should be done in common code somewhere.
119 if (device
->active_dlt
== -1)
120 linkname
= "Unknown";
122 linkname
= QObject::tr("DLT %1").arg(device
->active_dlt
);
123 for (GList
*list
= device
->links
; list
!= NULL
; list
= gxx_list_next(list
)) {
124 link_row
*linkr
= gxx_list_data(link_row
*, list
);
125 if (linkr
->dlt
== device
->active_dlt
) {
126 linkname
= linkr
->name
;
131 setText(col_link_
, linkname
);
133 if (device
->if_info
.type
== IF_EXTCAP
) {
134 /* extcap interfaces does not have this settings */
135 setApplicable(col_pmode_
, false);
137 setApplicable(col_snaplen_
, false);
138 setApplicable(col_buffer_
, false);
140 setApplicable(col_pmode_
, true);
141 setCheckState(col_pmode_
, device
->pmode
? Qt::Checked
: Qt::Unchecked
);
143 QString snaplen_string
= device
->has_snaplen
? QString::number(device
->snaplen
) : default_str
;
144 setText(col_snaplen_
, snaplen_string
);
145 setText(col_buffer_
, QString::number(device
->buffer
));
147 setText(col_filter_
, device
->cfilter
);
149 if (device
->monitor_mode_supported
) {
150 setApplicable(col_monitor_
, true);
151 setCheckState(col_monitor_
, device
->monitor_mode_enabled
? Qt::Checked
: Qt::Unchecked
);
153 setApplicable(col_monitor_
, false);
155 treeWidget()->blockSignals(false);
158 void setApplicable(int column
, bool applicable
= false) {
159 QPalette palette
= mainApp
->palette();
162 setText(column
, QString());
164 setData(column
, Qt::CheckStateRole
, QVariant());
165 palette
.setCurrentColorGroup(QPalette::Disabled
);
166 setText(column
, UTF8_EM_DASH
);
168 setForeground(column
, palette
.text().color());
173 CaptureOptionsDialog::CaptureOptionsDialog(QWidget
*parent
) :
174 GeometryStateDialog(parent
),
175 ui(new Ui::CaptureOptionsDialog
)
179 setWindowTitle(mainApp
->windowTitleString(tr("Capture Options")));
184 ui
->buttonBox
->button(QDialogButtonBox::Ok
)->setText(tr("Start"));
186 // Start out with the list *not* sorted, so they show up in the order
187 // in which they were provided
188 ui
->interfaceTree
->sortByColumn(-1, Qt::AscendingOrder
);
189 ui
->interfaceTree
->setItemDelegateForColumn(col_extcap_
, &interface_item_delegate_
);
190 ui
->interfaceTree
->setItemDelegateForColumn(col_interface_
, &interface_item_delegate_
);
191 ui
->interfaceTree
->setItemDelegateForColumn(col_traffic_
, new SparkLineDelegate(this));
192 ui
->interfaceTree
->setItemDelegateForColumn(col_link_
, &interface_item_delegate_
);
194 ui
->interfaceTree
->setItemDelegateForColumn(col_snaplen_
, &interface_item_delegate_
);
195 ui
->interfaceTree
->setItemDelegateForColumn(col_buffer_
, &interface_item_delegate_
);
196 ui
->interfaceTree
->setItemDelegateForColumn(col_filter_
, &interface_item_delegate_
);
198 interface_item_delegate_
.setTree(ui
->interfaceTree
);
200 ui
->filenameLineEdit
->setPlaceholderText(tr("Leave blank to use a temporary file"));
202 ui
->rbCompressionNone
->setChecked(true);
203 ui
->rbTimeNum
->setChecked(true);
205 ui
->tempDirLineEdit
->setPlaceholderText(g_get_tmp_dir());
206 ui
->tempDirLineEdit
->setText(global_capture_opts
.temp_dir
);
208 // Changes in interface selections or capture filters should be propagated
209 // to the main welcome screen where they will be applied to the global
211 connect(this, &CaptureOptionsDialog::interfacesChanged
, ui
->captureFilterComboBox
, &CaptureFilterCombo::interfacesChanged
);
212 connect(ui
->captureFilterComboBox
, &CaptureFilterCombo::captureFilterSyntaxChanged
, this, &CaptureOptionsDialog::updateWidgets
);
213 connect(ui
->captureFilterComboBox
->lineEdit(), &QLineEdit::textEdited
, this, &CaptureOptionsDialog::filterEdited
);
214 connect(ui
->captureFilterComboBox
->lineEdit(), &QLineEdit::textEdited
, this, &CaptureOptionsDialog::captureFilterTextEdited
);
215 connect(&interface_item_delegate_
, &InterfaceTreeDelegate::filterChanged
, ui
->captureFilterComboBox
->lineEdit(), &QLineEdit::setText
);
216 connect(&interface_item_delegate_
, &InterfaceTreeDelegate::filterChanged
, this, &CaptureOptionsDialog::captureFilterTextEdited
);
217 connect(this, &CaptureOptionsDialog::ifsChanged
, this, &CaptureOptionsDialog::refreshInterfaceList
);
218 connect(mainApp
, &MainApplication::localInterfaceListChanged
, this, &CaptureOptionsDialog::updateLocalInterfaces
);
219 connect(ui
->browseButton
, &QPushButton::clicked
, this, &CaptureOptionsDialog::browseButtonClicked
);
220 connect(ui
->interfaceTree
, &QTreeWidget::itemClicked
, this, &CaptureOptionsDialog::itemClicked
);
221 connect(ui
->interfaceTree
, &QTreeWidget::itemDoubleClicked
, this, &CaptureOptionsDialog::itemDoubleClicked
);
222 connect(ui
->tempDirBrowseButton
, &QPushButton::clicked
, this, &CaptureOptionsDialog::tempDirBrowseButtonClicked
);
224 // Ring buffer minimums (all 1 except # of files)
225 ui
->PktSpinBox
->setMinimum(1);
226 ui
->MBSpinBox
->setMinimum(1);
227 ui
->SecsSpinBox
->setMinimum(1);
228 ui
->IntervalSecsSpinBox
->setMinimum(1);
229 ui
->RbSpinBox
->setMinimum(2);
232 ui
->stopPktSpinBox
->setMinimum(1);
233 ui
->stopFilesSpinBox
->setMinimum(1);
234 ui
->stopMBSpinBox
->setMinimum(1);
235 ui
->stopSecsSpinBox
->setMinimum(1);
237 // Capture size maximum depends on units. Initial unit is kB.
238 ui
->MBSpinBox
->setMaximum(2000000000);
239 ui
->stopMBSpinBox
->setMaximum(2000000000);
241 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
242 connect(ui
->MBComboBox
, QOverload
<int>::of(&QComboBox::currentIndexChanged
), this, &CaptureOptionsDialog::MBComboBoxIndexChanged
);
243 connect(ui
->stopMBComboBox
, QOverload
<int>::of(&QComboBox::currentIndexChanged
), this, &CaptureOptionsDialog::stopMBComboBoxIndexChanged
);
245 connect(ui
->MBComboBox
, &QComboBox::currentIndexChanged
, this, &CaptureOptionsDialog::MBComboBoxIndexChanged
);
246 connect(ui
->stopMBComboBox
, &QComboBox::currentIndexChanged
, this, &CaptureOptionsDialog::stopMBComboBoxIndexChanged
);
249 ui
->tabWidget
->setCurrentIndex(0);
254 CaptureOptionsDialog::~CaptureOptionsDialog()
259 /* Update global device selections based on the TreeWidget selection. */
260 void CaptureOptionsDialog::updateGlobalDeviceSelections()
263 QTreeWidgetItemIterator
iter(ui
->interfaceTree
);
265 global_capture_opts
.num_selected
= 0;
268 QString device_name
= (*iter
)->data(col_interface_
, Qt::UserRole
).value
<QString
>();
269 for (unsigned i
= 0; i
< global_capture_opts
.all_ifaces
->len
; i
++) {
270 interface_t
*device
= &g_array_index(global_capture_opts
.all_ifaces
, interface_t
, i
);
271 if (device_name
.compare(QString().fromUtf8(device
->name
)) == 0) {
272 if ((*iter
)->isSelected()) {
273 device
->selected
= true;
274 global_capture_opts
.num_selected
++;
276 device
->selected
= false;
286 /* Update TreeWidget selection based on global device selections. */
287 void CaptureOptionsDialog::updateFromGlobalDeviceSelections()
290 QTreeWidgetItemIterator
iter(ui
->interfaceTree
);
292 // Prevent recursive interface interfaceSelected signals
293 ui
->interfaceTree
->blockSignals(true);
296 QString device_name
= (*iter
)->data(col_interface_
, Qt::UserRole
).value
<QString
>();
297 for (unsigned i
= 0; i
< global_capture_opts
.all_ifaces
->len
; i
++) {
298 interface_t
*device
= &g_array_index(global_capture_opts
.all_ifaces
, interface_t
, i
);
299 if (device_name
.compare(QString().fromUtf8(device
->name
)) == 0) {
300 if ((bool)device
->selected
!= (*iter
)->isSelected()) {
301 (*iter
)->setSelected(device
->selected
);
309 ui
->interfaceTree
->blockSignals(false);
313 void CaptureOptionsDialog::interfaceSelected()
315 if (sender() == ui
->interfaceTree
) {
316 // Local changes, propagate our changes
317 updateGlobalDeviceSelections();
318 emit
interfacesChanged();
320 // Changes from the welcome screen, adjust to its state.
321 updateFromGlobalDeviceSelections();
324 updateSelectedFilter();
329 void CaptureOptionsDialog::filterEdited()
331 QList
<QTreeWidgetItem
*> si
= ui
->interfaceTree
->selectedItems();
333 foreach (QTreeWidgetItem
*ti
, si
) {
334 ti
->setText(col_filter_
, ui
->captureFilterComboBox
->lineEdit()->text());
337 if (si
.count() > 0) {
338 QModelIndex col_filter_idx
= ui
->interfaceTree
->model()->index(ui
->interfaceTree
->indexOfTopLevelItem(si
[0]), col_filter_
);
339 ui
->interfaceTree
->scrollTo(col_filter_idx
);
343 void CaptureOptionsDialog::updateWidgets()
345 SyntaxLineEdit
*sle
= qobject_cast
<SyntaxLineEdit
*>(ui
->captureFilterComboBox
->lineEdit());
350 bool can_capture
= false;
352 if (ui
->interfaceTree
->selectedItems().count() > 0 && sle
->syntaxState() != SyntaxLineEdit::Invalid
) {
356 ui
->compileBPF
->setEnabled(can_capture
);
357 ui
->buttonBox
->button(QDialogButtonBox::Ok
)->setEnabled(can_capture
);
360 void CaptureOptionsDialog::on_capturePromModeCheckBox_toggled(bool checked
)
363 prefs
.capture_prom_mode
= checked
;
364 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
365 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(ui
->interfaceTree
->topLevelItem(row
));
368 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
369 device
= getDeviceByName(device_name
);
370 if (!device
) continue;
371 device
->pmode
= checked
;
372 ti
->updateInterfaceColumns(device
);
376 void CaptureOptionsDialog::on_captureMonitorModeCheckBox_toggled(bool checked
)
379 prefs
.capture_monitor_mode
= checked
;
380 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
381 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(ui
->interfaceTree
->topLevelItem(row
));
384 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
385 device
= getDeviceByName(device_name
);
386 if (!device
) continue;
387 if (device
->monitor_mode_supported
) {
388 device
->monitor_mode_enabled
= checked
;
389 ti
->updateInterfaceColumns(device
);
394 void CaptureOptionsDialog::browseButtonClicked()
396 QString file_name
= WiresharkFileDialog::getSaveFileName(this, tr("Specify a Capture File"), get_open_dialog_initial_dir());
397 ui
->filenameLineEdit
->setText(file_name
);
400 void CaptureOptionsDialog::tempDirBrowseButtonClicked()
402 QString specified_dir
= WiresharkFileDialog::getExistingDirectory(this, tr("Specify temporary directory"));
403 ui
->tempDirLineEdit
->setText(specified_dir
);
406 void CaptureOptionsDialog::interfaceItemChanged(QTreeWidgetItem
*item
, int column
)
408 QWidget
* editor
= ui
->interfaceTree
->indexWidget(ui
->interfaceTree
->currentIndex());
410 ui
->interfaceTree
->closePersistentEditor(item
, ui
->interfaceTree
->currentColumn());
413 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(item
);
417 QString interface_name
= ti
->text(col_interface_
);
418 device
= find_device_by_if_name(interface_name
);
424 device
->pmode
= item
->checkState(col_pmode_
) == Qt::Checked
? true : false;
425 ti
->updateInterfaceColumns(device
);
430 bool monitor_mode
= false;
431 if (ti
->checkState(col_monitor_
) == Qt::Checked
) monitor_mode
= true;
433 if_capabilities_t
*caps
;
434 char *auth_str
= NULL
;
435 QString active_dlt_name
;
437 set_active_dlt(device
, global_capture_opts
.default_options
.linktype
);
439 #ifdef HAVE_PCAP_REMOTE
440 if (device
->remote_opts
.remote_host_opts
.auth_type
== CAPTURE_AUTH_PWD
) {
441 auth_str
= ws_strdup_printf("%s:%s", device
->remote_opts
.remote_host_opts
.auth_username
,
442 device
->remote_opts
.remote_host_opts
.auth_password
);
445 caps
= capture_get_if_capabilities(device
->name
, monitor_mode
, auth_str
, NULL
, NULL
, main_window_update
);
448 if (caps
!= Q_NULLPTR
) {
450 #if GLIB_CHECK_VERSION(2, 68, 0)
451 g_list_free_full(g_steal_pointer(&device
->links
), capture_opts_free_link_row
);
453 g_list_free_full((GList
*)g_steal_pointer(&device
->links
), capture_opts_free_link_row
);
455 device
->active_dlt
= -1;
456 device
->monitor_mode_supported
= caps
->can_set_rfmon
;
457 device
->monitor_mode_enabled
= monitor_mode
&& caps
->can_set_rfmon
;
458 GList
*lt_list
= device
->monitor_mode_enabled
? caps
->data_link_types_rfmon
: caps
->data_link_types
;
460 for (GList
*lt_entry
= lt_list
; lt_entry
!= Q_NULLPTR
; lt_entry
= gxx_list_next(lt_entry
)) {
461 link_row
*linkr
= g_new(link_row
, 1);
462 data_link_info_t
*data_link_info
= gxx_list_data(data_link_info_t
*, lt_entry
);
464 * For link-layer types libpcap/Npcap doesn't know
465 * about, the name will be "DLT n", and the description will
467 * We mark those as unsupported, and don't allow them to be
468 * used - capture filters won't work on them, for example.
470 if (data_link_info
->description
!= Q_NULLPTR
) {
471 linkr
->dlt
= data_link_info
->dlt
;
472 if (active_dlt_name
.isEmpty()) {
473 device
->active_dlt
= data_link_info
->dlt
;
474 active_dlt_name
= data_link_info
->description
;
476 linkr
->name
= g_strdup(data_link_info
->description
);
479 /* XXX - should we just omit them? */
480 str
= ws_strdup_printf("%s (not supported)", data_link_info
->name
);
482 linkr
->name
= g_strdup(str
);
485 device
->links
= g_list_append(device
->links
, linkr
);
487 free_if_capabilities(caps
);
489 /* We don't know whether this supports monitor mode or not;
490 don't ask for monitor mode. */
491 device
->monitor_mode_enabled
= false;
492 device
->monitor_mode_supported
= false;
495 ti
->updateInterfaceColumns(device
);
504 void CaptureOptionsDialog::itemClicked(QTreeWidgetItem
*item
, int column
)
506 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(item
);
511 QString interface_name
= ti
->text(col_interface_
);
512 device
= find_device_by_if_name(interface_name
);
518 if (device
->if_info
.type
== IF_EXTCAP
) {
519 /* this checks if configuration is required and not yet provided or saved via prefs */
520 QString device_name
= ti
->data(col_extcap_
, Qt::UserRole
).value
<QString
>();
521 if (extcap_has_configuration((const char *)(device_name
.toStdString().c_str())))
523 emit
showExtcapOptions(device_name
, false);
532 #endif /* HAVE_LIBPCAP */
535 void CaptureOptionsDialog::itemDoubleClicked(QTreeWidgetItem
*item
, int column
)
537 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(item
);
542 // Double click starts capture just on columns which are not editable
548 QString interface_name
= ti
->text(col_interface_
);
549 device
= find_device_by_if_name(interface_name
);
552 if (device
->if_info
.type
== IF_EXTCAP
) {
553 /* this checks if configuration is required and not yet provided or saved via prefs */
554 QString device_name
= ti
->data(col_extcap_
, Qt::UserRole
).value
<QString
>();
555 if (extcap_requires_configuration((const char *)(device_name
.toStdString().c_str())))
557 emit
showExtcapOptions(device_name
, true);
561 #endif /* HAVE_LIBPCAP */
572 void CaptureOptionsDialog::MBComboBoxIndexChanged(int index
)
576 ui
->MBSpinBox
->setMaximum(2000000000);
579 ui
->MBSpinBox
->setMaximum(2000000);
582 ui
->MBSpinBox
->setMaximum(2000);
587 void CaptureOptionsDialog::stopMBComboBoxIndexChanged(int index
)
591 ui
->stopMBSpinBox
->setMaximum(2000000000);
594 ui
->stopMBSpinBox
->setMaximum(2000000);
597 ui
->stopMBSpinBox
->setMaximum(2000);
602 void CaptureOptionsDialog::on_gbStopCaptureAuto_toggled(bool checked
)
604 global_capture_opts
.has_file_interval
= checked
;
607 void CaptureOptionsDialog::on_gbNewFileAuto_toggled(bool checked
)
609 global_capture_opts
.multi_files_on
= checked
;
610 ui
->stopMBCheckBox
->setEnabled(checked
?false:true);
611 ui
->stopMBSpinBox
->setEnabled(checked
?false:true);
612 ui
->stopMBComboBox
->setEnabled(checked
?false:true);
613 ui
->gbCompression
->setEnabled(checked
);
614 ui
->rbCompressionNone
->setEnabled(checked
);
615 #if defined(HAVE_ZLIB) || defined(HAVE_ZLIBNG)
616 ui
->rbCompressionGzip
->setEnabled(checked
);
618 ui
->rbCompressionGzip
->setEnabled(false);
622 void CaptureOptionsDialog::on_cbUpdatePacketsRT_toggled(bool checked
)
624 global_capture_opts
.real_time_mode
= checked
;
627 void CaptureOptionsDialog::on_cbAutoScroll_toggled(bool checked
)
629 recent
.capture_auto_scroll
= checked
;
632 void CaptureOptionsDialog::on_cbExtraCaptureInfo_toggled(bool checked
)
634 global_capture_opts
.show_info
= checked
;
637 void CaptureOptionsDialog::on_cbResolveMacAddresses_toggled(bool checked
)
639 gbl_resolv_flags
.mac_name
= checked
;
642 void CaptureOptionsDialog::on_cbResolveNetworkNames_toggled(bool checked
)
644 gbl_resolv_flags
.network_name
= checked
;
647 void CaptureOptionsDialog::on_cbResolveTransportNames_toggled(bool checked
)
649 gbl_resolv_flags
.transport_name
= checked
;
652 void CaptureOptionsDialog::on_buttonBox_accepted()
654 if (saveOptionsToPreferences()) {
657 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(ui
->interfaceTree
->currentItem());
661 QString interface_name
= ti
->text(col_interface_
);
662 device
= find_device_by_if_name(interface_name
);
663 if (device
&& device
->if_info
.type
== IF_EXTCAP
) {
664 /* this checks if configuration is required and not yet provided or saved via prefs */
665 QString device_name
= ti
->data(col_extcap_
, Qt::UserRole
).value
<QString
>();
666 if (extcap_requires_configuration((const char *)(device_name
.toStdString().c_str())))
668 emit
showExtcapOptions(device_name
, true);
673 #endif /* HAVE_LIBPCAP */
675 emit
setFilterValid(true, ui
->captureFilterComboBox
->lineEdit()->text());
680 // Not sure why we have to do this manually.
681 void CaptureOptionsDialog::on_buttonBox_rejected()
683 if (saveOptionsToPreferences()) {
688 void CaptureOptionsDialog::on_buttonBox_helpRequested()
690 // Probably the wrong URL.
691 mainApp
->helpTopicAction(HELP_CAPTURE_OPTIONS_DIALOG
);
694 void CaptureOptionsDialog::updateInterfaces()
696 if (prefs
.capture_pcap_ng
) {
697 ui
->rbPcapng
->setChecked(true);
699 ui
->rbPcap
->setChecked(true);
701 ui
->capturePromModeCheckBox
->setChecked(prefs
.capture_prom_mode
);
702 ui
->captureMonitorModeCheckBox
->setChecked(prefs
.capture_monitor_mode
);
703 ui
->captureMonitorModeCheckBox
->setEnabled(false);
705 if (global_capture_opts
.saving_to_file
) {
706 ui
->filenameLineEdit
->setText(QString(global_capture_opts
.orig_save_file
));
709 ui
->gbNewFileAuto
->setChecked(global_capture_opts
.multi_files_on
);
710 ui
->PktCheckBox
->setChecked(global_capture_opts
.has_file_packets
);
711 if (global_capture_opts
.has_file_packets
) {
712 ui
->PktSpinBox
->setValue(global_capture_opts
.file_packets
);
714 ui
->MBCheckBox
->setChecked(global_capture_opts
.has_autostop_filesize
);
715 if (global_capture_opts
.has_autostop_filesize
) {
716 int value
= global_capture_opts
.autostop_filesize
;
717 if (value
> 1000000) {
718 if (global_capture_opts
.multi_files_on
) {
719 ui
->MBSpinBox
->setValue(value
/ 1000000);
720 ui
->MBComboBox
->setCurrentIndex(2);
722 ui
->stopMBCheckBox
->setChecked(true);
723 ui
->stopMBSpinBox
->setValue(value
/ 1000000);
724 ui
->stopMBComboBox
->setCurrentIndex(2);
726 } else if (value
> 1000 && value
% 1000 == 0) {
727 if (global_capture_opts
.multi_files_on
) {
728 ui
->MBSpinBox
->setValue(value
/ 1000);
729 ui
->MBComboBox
->setCurrentIndex(1);
731 ui
->stopMBCheckBox
->setChecked(true);
732 ui
->stopMBSpinBox
->setValue(value
/ 1000);
733 ui
->stopMBComboBox
->setCurrentIndex(1);
736 if (global_capture_opts
.multi_files_on
) {
737 ui
->MBSpinBox
->setValue(value
);
738 ui
->MBComboBox
->setCurrentIndex(0);
740 ui
->stopMBCheckBox
->setChecked(true);
741 ui
->stopMBSpinBox
->setValue(value
);
742 ui
->stopMBComboBox
->setCurrentIndex(0);
747 ui
->SecsCheckBox
->setChecked(global_capture_opts
.has_file_duration
);
748 if (global_capture_opts
.has_file_duration
) {
749 int value
= global_capture_opts
.file_duration
;
750 if (value
> 3600 && value
% 3600 == 0) {
751 ui
->SecsSpinBox
->setValue(value
/ 3600);
752 ui
->SecsComboBox
->setCurrentIndex(2);
753 } else if (value
> 60 && value
% 60 == 0) {
754 ui
->SecsSpinBox
->setValue(value
/ 60);
755 ui
->SecsComboBox
->setCurrentIndex(1);
757 ui
->SecsSpinBox
->setValue(value
);
758 ui
->SecsComboBox
->setCurrentIndex(0);
762 ui
->IntervalSecsCheckBox
->setChecked(global_capture_opts
.has_file_interval
);
763 if (global_capture_opts
.has_file_interval
) {
764 int value
= global_capture_opts
.file_interval
;
765 if (value
> 3600 && value
% 3600 == 0) {
766 ui
->IntervalSecsSpinBox
->setValue(value
/ 3600);
767 ui
->IntervalSecsComboBox
->setCurrentIndex(2);
768 } else if (value
> 60 && value
% 60 == 0) {
769 ui
->IntervalSecsSpinBox
->setValue(value
/ 60);
770 ui
->IntervalSecsComboBox
->setCurrentIndex(1);
772 ui
->IntervalSecsSpinBox
->setValue(value
);
773 ui
->IntervalSecsComboBox
->setCurrentIndex(0);
777 if (global_capture_opts
.has_ring_num_files
) {
778 ui
->RbSpinBox
->setValue(global_capture_opts
.ring_num_files
);
779 ui
->RbCheckBox
->setCheckState(Qt::Checked
);
782 if (global_capture_opts
.has_autostop_duration
) {
783 ui
->stopSecsCheckBox
->setChecked(true);
784 int value
= global_capture_opts
.autostop_duration
;
785 if (value
> 3600 && value
% 3600 == 0) {
786 ui
->stopSecsSpinBox
->setValue(value
/ 3600);
787 ui
->stopSecsComboBox
->setCurrentIndex(2);
788 } else if (value
> 60 && value
% 60 == 0) {
789 ui
->stopSecsSpinBox
->setValue(value
/ 60);
790 ui
->stopSecsComboBox
->setCurrentIndex(1);
792 ui
->stopSecsSpinBox
->setValue(value
);
793 ui
->stopSecsComboBox
->setCurrentIndex(0);
797 if (global_capture_opts
.has_autostop_packets
) {
798 ui
->stopPktCheckBox
->setChecked(true);
799 ui
->stopPktSpinBox
->setValue(global_capture_opts
.autostop_packets
);
802 if (global_capture_opts
.has_autostop_files
) {
803 ui
->stopFilesCheckBox
->setChecked(true);
804 ui
->stopFilesSpinBox
->setValue(global_capture_opts
.autostop_files
);
807 ui
->cbUpdatePacketsRT
->setChecked(global_capture_opts
.real_time_mode
);
808 ui
->cbAutoScroll
->setChecked(recent
.capture_auto_scroll
);
809 ui
->cbExtraCaptureInfo
->setChecked(global_capture_opts
.show_info
);
811 ui
->cbResolveMacAddresses
->setChecked(gbl_resolv_flags
.mac_name
);
812 ui
->cbResolveNetworkNames
->setChecked(gbl_resolv_flags
.network_name
);
813 ui
->cbResolveTransportNames
->setChecked(gbl_resolv_flags
.transport_name
);
815 // Rebuild the interface list without disturbing the main welcome screen.
816 disconnect(ui
->interfaceTree
, &QTreeWidget::itemSelectionChanged
, this, &CaptureOptionsDialog::interfaceSelected
);
817 ui
->interfaceTree
->clear();
822 QList
<QTreeWidgetItem
*> selected_interfaces
;
824 disconnect(ui
->interfaceTree
, &QTreeWidget::itemChanged
, this, &CaptureOptionsDialog::interfaceItemChanged
);
826 if (global_capture_opts
.all_ifaces
->len
> 0) {
829 for (unsigned device_idx
= 0; device_idx
< global_capture_opts
.all_ifaces
->len
; device_idx
++) {
830 device
= &g_array_index(global_capture_opts
.all_ifaces
, interface_t
, device_idx
);
832 /* Continue if capture device is hidden */
833 if (device
->hidden
) {
837 // Traffic sparklines
838 InterfaceTreeWidgetItem
*ti
= new InterfaceTreeWidgetItem(ui
->interfaceTree
);
839 ti
->setFlags(ti
->flags() | Qt::ItemIsEditable
);
841 if (device
->if_info
.type
== IF_EXTCAP
) {
842 ti
->setIcon(col_extcap_
, QIcon(StockIcon("x-capture-options")));
843 ti
->setData(col_extcap_
, Qt::UserRole
, QString(device
->if_info
.name
));
844 ti
->setToolTip(col_extcap_
, QStringLiteral("Extcap interface settings"));
847 ti
->setText(col_interface_
, device
->display_name
);
848 ti
->setData(col_interface_
, Qt::UserRole
, QString(device
->name
));
849 if (device
->if_info
.type
!= IF_EXTCAP
)
850 ti
->setData(col_traffic_
, Qt::UserRole
, QVariant::fromValue(ti
->points
));
852 if (device
->no_addresses
> 0) {
853 QString addr_str
= tr("%1: %2").arg(device
->no_addresses
> 1 ? tr("Addresses") : tr("Address")).arg(device
->addresses
);
854 QTreeWidgetItem
*addr_ti
= new QTreeWidgetItem(ti
);
856 addr_str
.replace('\n', ", ");
857 addr_ti
->setText(0, addr_str
);
858 addr_ti
->setFlags(addr_ti
->flags() ^ Qt::ItemIsSelectable
);
859 addr_ti
->setFirstColumnSpanned(true);
860 addr_ti
->setToolTip(col_interface_
, QStringLiteral("<span>%1</span>").arg(addr_str
));
861 ti
->setToolTip(col_interface_
, QStringLiteral("<span>%1</span>").arg(addr_str
));
863 ti
->setToolTip(col_interface_
, tr("no addresses"));
866 if (capture_dev_user_pmode_find(device
->name
, &pmode
)) {
867 device
->pmode
= pmode
;
869 if (capture_dev_user_snaplen_find(device
->name
, &hassnap
, &snaplen
)) {
870 /* Default snap length set in preferences */
871 device
->snaplen
= snaplen
;
872 device
->has_snaplen
= snaplen
== WTAP_MAX_PACKET_SIZE_STANDARD
? false : hassnap
;
874 /* No preferences set yet, use default values */
875 device
->snaplen
= WTAP_MAX_PACKET_SIZE_STANDARD
;
876 device
->has_snaplen
= false;
879 if (capture_dev_user_buffersize_find(device
->name
) != -1) {
880 buffer
= capture_dev_user_buffersize_find(device
->name
);
881 device
->buffer
= buffer
;
883 device
->buffer
= DEFAULT_CAPTURE_BUFFER_SIZE
;
885 if (device
->monitor_mode_supported
) {
886 ui
->captureMonitorModeCheckBox
->setEnabled(true);
888 ti
->updateInterfaceColumns(device
);
890 if (device
->selected
) {
891 selected_interfaces
<< ti
;
896 connect(ui
->interfaceTree
, &QTreeWidget::itemChanged
, this, &CaptureOptionsDialog::interfaceItemChanged
);
898 foreach (QTreeWidgetItem
*ti
, selected_interfaces
) {
899 ti
->setSelected(true);
901 connect(ui
->interfaceTree
, &QTreeWidget::itemSelectionChanged
, this, &CaptureOptionsDialog::interfaceSelected
);
902 updateSelectedFilter();
904 // Manually or automatically size some columns as needed.
905 int one_em
= fontMetrics().height();
906 for (int col
= 0; col
< ui
->interfaceTree
->topLevelItemCount(); col
++) {
909 ui
->interfaceTree
->setColumnWidth(col
, one_em
* 3.25);
912 ui
->interfaceTree
->setColumnWidth(col
, one_em
* 4.25);
915 ui
->interfaceTree
->setColumnWidth(col
, one_em
* 4.25);
918 ui
->interfaceTree
->setColumnWidth(col
, one_em
* 3.25);
921 ui
->interfaceTree
->resizeColumnToContents(col
);
930 stat_timer_
= new QTimer(this);
931 connect(stat_timer_
, &QTimer::timeout
, this, &CaptureOptionsDialog::updateStatistics
);
932 stat_timer_
->start(stat_update_interval_
);
936 void CaptureOptionsDialog::showEvent(QShowEvent
*)
941 void CaptureOptionsDialog::refreshInterfaceList()
944 emit
interfaceListChanged();
947 void CaptureOptionsDialog::updateLocalInterfaces()
952 void CaptureOptionsDialog::updateStatistics(void)
956 disconnect(ui
->interfaceTree
, &QTreeWidget::itemChanged
, this, &CaptureOptionsDialog::interfaceItemChanged
);
957 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
959 for (unsigned if_idx
= 0; if_idx
< global_capture_opts
.all_ifaces
->len
; if_idx
++) {
960 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
964 device
= &g_array_index(global_capture_opts
.all_ifaces
, interface_t
, if_idx
);
965 QString device_name
= ti
->text(col_interface_
);
966 if (device_name
.compare(device
->display_name
) || device
->hidden
|| device
->if_info
.type
== IF_PIPE
) {
969 QList
<int> points
= ti
->data(col_traffic_
, Qt::UserRole
).value
<QList
<int> >();
970 points
.append(device
->packet_diff
);
971 ti
->setData(col_traffic_
, Qt::UserRole
, QVariant::fromValue(points
));
974 connect(ui
->interfaceTree
, &QTreeWidget::itemChanged
, this, &CaptureOptionsDialog::interfaceItemChanged
);
975 ui
->interfaceTree
->viewport()->update();
978 void CaptureOptionsDialog::on_compileBPF_clicked()
980 QList
<InterfaceFilter
> interfaces
;
981 foreach (QTreeWidgetItem
*ti
, ui
->interfaceTree
->selectedItems()) {
982 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
983 interfaces
.emplaceBack(ti
->text(col_interface_
), ti
->text(col_filter_
));
985 interfaces
.append(InterfaceFilter(ti
->text(col_interface_
), ti
->text(col_filter_
)));
989 CompiledFilterOutput
*cfo
= new CompiledFilterOutput(this, interfaces
);
994 bool CaptureOptionsDialog::saveOptionsToPreferences()
996 if (ui
->rbPcapng
->isChecked()) {
997 global_capture_opts
.use_pcapng
= true;
998 prefs
.capture_pcap_ng
= true;
1000 global_capture_opts
.use_pcapng
= false;
1001 prefs
.capture_pcap_ng
= false;
1004 g_free(global_capture_opts
.save_file
);
1005 g_free(global_capture_opts
.orig_save_file
);
1007 QString filename
= ui
->filenameLineEdit
->text();
1008 if (filename
.length() > 0) {
1009 /* User specified a file to which the capture should be written. */
1010 global_capture_opts
.saving_to_file
= true;
1011 global_capture_opts
.save_file
= qstring_strdup(filename
);
1012 global_capture_opts
.orig_save_file
= qstring_strdup(filename
);
1013 /* Save the directory name for future file dialogs. */
1014 set_last_open_dir(get_dirname(filename
.toUtf8().data()));
1016 /* User didn't specify a file; save to a temporary file. */
1017 global_capture_opts
.saving_to_file
= false;
1018 global_capture_opts
.save_file
= NULL
;
1019 global_capture_opts
.orig_save_file
= NULL
;
1022 QString tempdir
= ui
->tempDirLineEdit
->text();
1023 if (tempdir
.length() > 0) {
1024 global_capture_opts
.temp_dir
= qstring_strdup(tempdir
);
1027 global_capture_opts
.temp_dir
= NULL
;
1030 global_capture_opts
.has_ring_num_files
= ui
->RbCheckBox
->isChecked();
1032 if (global_capture_opts
.has_ring_num_files
) {
1033 global_capture_opts
.ring_num_files
= ui
->RbSpinBox
->value();
1034 if (global_capture_opts
.ring_num_files
> RINGBUFFER_MAX_NUM_FILES
)
1035 global_capture_opts
.ring_num_files
= RINGBUFFER_MAX_NUM_FILES
;
1036 #if RINGBUFFER_MIN_NUM_FILES > 0
1037 else if (global_capture_opts
.ring_num_files
< RINGBUFFER_MIN_NUM_FILES
)
1038 global_capture_opts
.ring_num_files
= RINGBUFFER_MIN_NUM_FILES
;
1041 global_capture_opts
.multi_files_on
= ui
->gbNewFileAuto
->isChecked();
1042 if (global_capture_opts
.multi_files_on
) {
1043 global_capture_opts
.has_file_duration
= ui
->SecsCheckBox
->isChecked();
1044 if (global_capture_opts
.has_file_duration
) {
1045 global_capture_opts
.file_duration
= ui
->SecsSpinBox
->value();
1046 int index
= ui
->SecsComboBox
->currentIndex();
1048 case 1: global_capture_opts
.file_duration
*= 60;
1050 case 2: global_capture_opts
.file_duration
*= 3600;
1054 global_capture_opts
.has_file_interval
= ui
->IntervalSecsCheckBox
->isChecked();
1055 if (global_capture_opts
.has_file_interval
) {
1056 global_capture_opts
.file_interval
= ui
->IntervalSecsSpinBox
->value();
1057 int index
= ui
->IntervalSecsComboBox
->currentIndex();
1059 case 1: global_capture_opts
.file_interval
*= 60;
1061 case 2: global_capture_opts
.file_interval
*= 3600;
1065 global_capture_opts
.has_file_packets
= ui
->PktCheckBox
->isChecked();
1066 if (global_capture_opts
.has_file_packets
) {
1067 global_capture_opts
.file_packets
= ui
->PktSpinBox
->value();
1069 global_capture_opts
.has_autostop_filesize
= ui
->MBCheckBox
->isChecked();
1070 if (global_capture_opts
.has_autostop_filesize
) {
1071 global_capture_opts
.autostop_filesize
= ui
->MBSpinBox
->value();
1072 int index
= ui
->MBComboBox
->currentIndex();
1074 case 1: if (global_capture_opts
.autostop_filesize
> 2000000) {
1075 QMessageBox::warning(this, tr("Error"),
1076 tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB."));
1079 global_capture_opts
.autostop_filesize
*= 1000;
1082 case 2: if (global_capture_opts
.autostop_filesize
> 2000) {
1083 QMessageBox::warning(this, tr("Error"),
1084 tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB."));
1087 global_capture_opts
.autostop_filesize
*= 1000000;
1092 /* test if the settings are ok for a ringbuffer */
1093 if (global_capture_opts
.save_file
== NULL
) {
1094 QMessageBox::warning(this, tr("Error"),
1095 tr("Multiple files: No capture file name given. You must specify a filename if you want to use multiple files."));
1097 } else if (!global_capture_opts
.has_autostop_filesize
&&
1098 !global_capture_opts
.has_file_interval
&&
1099 !global_capture_opts
.has_file_duration
&&
1100 !global_capture_opts
.has_file_packets
) {
1101 QMessageBox::warning(this, tr("Error"),
1102 tr("Multiple files: No file limit given. You must specify a file size, interval, or number of packets for each file."));
1103 g_free(global_capture_opts
.save_file
);
1104 global_capture_opts
.save_file
= NULL
;
1108 global_capture_opts
.has_autostop_filesize
= ui
->stopMBCheckBox
->isChecked();
1109 if (global_capture_opts
.has_autostop_filesize
) {
1110 global_capture_opts
.autostop_filesize
= ui
->stopMBSpinBox
->value();
1111 int index
= ui
->stopMBComboBox
->currentIndex();
1113 case 1: if (global_capture_opts
.autostop_filesize
> 2000000) {
1114 QMessageBox::warning(this, tr("Error"),
1115 tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB."));
1118 global_capture_opts
.autostop_filesize
*= 1000;
1121 case 2: if (global_capture_opts
.autostop_filesize
> 2000) {
1122 QMessageBox::warning(this, tr("Error"),
1123 tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB."));
1126 global_capture_opts
.autostop_filesize
*= 1000000;
1133 global_capture_opts
.has_autostop_duration
= ui
->stopSecsCheckBox
->isChecked();
1134 if (global_capture_opts
.has_autostop_duration
) {
1135 global_capture_opts
.autostop_duration
= ui
->stopSecsSpinBox
->value();
1136 int index
= ui
->stopSecsComboBox
->currentIndex();
1138 case 1: global_capture_opts
.autostop_duration
*= 60;
1140 case 2: global_capture_opts
.autostop_duration
*= 3600;
1145 global_capture_opts
.has_autostop_packets
= ui
->stopPktCheckBox
->isChecked();
1146 if (global_capture_opts
.has_autostop_packets
) {
1147 global_capture_opts
.autostop_packets
= ui
->stopPktSpinBox
->value();
1150 global_capture_opts
.has_autostop_files
= ui
->stopFilesCheckBox
->isChecked();
1151 if (global_capture_opts
.has_autostop_files
) {
1152 global_capture_opts
.autostop_files
= ui
->stopFilesSpinBox
->value();
1155 interface_t
*device
;
1157 for (int col
= col_link_
; col
<= col_filter_
; col
++) {
1158 if (ui
->interfaceTree
->isColumnHidden(col
)) {
1161 /* All entries are separated by comma. There is also one before the first interface to be able to identify
1162 word boundaries. As 'lo' is part of 'nflog' an exact match is necessary. */
1166 QStringList link_list
;
1168 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1169 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1170 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1171 device
= getDeviceByName(device_name
);
1172 if (!device
|| device
->active_dlt
== -1) {
1175 link_list
<< QStringLiteral("%1(%2)").arg(device
->name
).arg(device
->active_dlt
);
1177 g_free(prefs
.capture_devices_linktypes
);
1178 prefs
.capture_devices_linktypes
= qstring_strdup(link_list
.join(","));
1183 QStringList buffer_size_list
;
1185 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1186 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1187 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1188 device
= getDeviceByName(device_name
);
1189 if (!device
|| device
->buffer
== -1) {
1192 buffer_size_list
<< QStringLiteral("%1(%2)").arg(device
->name
).arg(device
->buffer
);
1194 g_free(prefs
.capture_devices_buffersize
);
1195 prefs
.capture_devices_buffersize
= qstring_strdup(buffer_size_list
.join(","));
1200 QStringList snaplen_list
;
1202 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1203 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1204 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1205 device
= getDeviceByName(device_name
);
1206 if (!device
) continue;
1207 snaplen_list
<< QStringLiteral("%1:%2(%3)")
1209 .arg(device
->has_snaplen
)
1210 .arg(device
->has_snaplen
? device
->snaplen
: WTAP_MAX_PACKET_SIZE_STANDARD
);
1212 g_free(prefs
.capture_devices_snaplen
);
1213 prefs
.capture_devices_snaplen
= qstring_strdup(snaplen_list
.join(","));
1218 QStringList pmode_list
;
1220 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1221 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1222 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1223 device
= getDeviceByName(device_name
);
1224 if (!device
|| !device
->pmode
) {
1227 pmode_list
<< QStringLiteral("%1(%2)").arg(device
->name
).arg(device
->pmode
);
1229 g_free(prefs
.capture_devices_pmode
);
1230 prefs
.capture_devices_pmode
= qstring_strdup(pmode_list
.join(","));
1236 QStringList monitor_list
;
1238 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1239 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1240 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1241 device
= getDeviceByName(device_name
);
1242 if (!device
|| !device
->monitor_mode_supported
|| (device
->monitor_mode_supported
&& !device
->monitor_mode_enabled
)) {
1245 monitor_list
<< device
->name
;
1247 g_free(prefs
.capture_devices_monitor_mode
);
1248 prefs
.capture_devices_monitor_mode
= qstring_strdup(monitor_list
.join(","));
1253 // The device cfilter should have been applied at this point.
1254 // We shouldn't change it here.
1257 // XXX Update selected interfaces only?
1258 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1259 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1260 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1261 device
= getDeviceByName(device_name
);
1262 if (!device
) continue;
1263 g_free(device
->cfilter
);
1264 if (ti
->text(col_filter_
).isEmpty()) {
1265 device
->cfilter
= NULL
;
1267 device
->cfilter
= qstring_strdup(ti
->text(col_filter_
));
1275 g_free(global_capture_opts
.compress_type
);
1277 if (ui
->rbCompressionNone
->isChecked() ) {
1278 global_capture_opts
.compress_type
= NULL
;
1279 } else if (ui
->rbCompressionGzip
->isChecked() ) {
1280 global_capture_opts
.compress_type
= qstring_strdup("gzip");
1282 global_capture_opts
.compress_type
= NULL
;
1285 if (ui
->rbTimeNum
->isChecked() ) {
1286 global_capture_opts
.has_nametimenum
= true;
1287 } else if (ui
->rbNumTime
->isChecked() ) {
1288 global_capture_opts
.has_nametimenum
= false;
1290 global_capture_opts
.has_nametimenum
= false;
1297 void CaptureOptionsDialog::updateSelectedFilter()
1299 // Should match MainWelcome::interfaceSelected.
1300 QPair
<const QString
, bool> sf_pair
= CaptureFilterEdit::getSelectedFilter();
1301 const QString user_filter
= sf_pair
.first
;
1302 bool conflict
= sf_pair
.second
;
1305 ui
->captureFilterComboBox
->lineEdit()->clear();
1306 ui
->captureFilterComboBox
->setConflict(true);
1308 ui
->captureFilterComboBox
->lineEdit()->setText(user_filter
);
1312 void CaptureOptionsDialog::on_manageButton_clicked()
1314 if (saveOptionsToPreferences()) {
1315 ManageInterfacesDialog
*dlg
= new ManageInterfacesDialog(this);
1320 void CaptureOptionsDialog::changeEvent(QEvent
* event
)
1324 switch (event
->type())
1326 case QEvent::LanguageChange
:
1327 ui
->retranslateUi(this);
1333 QDialog::changeEvent(event
);
1336 interface_t
*CaptureOptionsDialog::getDeviceByName(const QString device_name
)
1338 for (unsigned i
= 0; i
< global_capture_opts
.all_ifaces
->len
; i
++) {
1339 interface_t
*device
= &g_array_index(global_capture_opts
.all_ifaces
, interface_t
, i
);
1340 if (device_name
.compare(QString().fromUtf8(device
->name
)) == 0) {
1348 // InterfaceTreeItem
1350 bool InterfaceTreeWidgetItem::operator< (const QTreeWidgetItem
&other
) const {
1351 if (treeWidget()->sortColumn() == col_traffic_
) {
1352 QList
<int> points
= data(col_traffic_
, Qt::UserRole
).value
<QList
<int> >();
1353 QList
<int> other_points
= other
.data(col_traffic_
, Qt::UserRole
).value
<QList
<int> >();
1354 double avg
= 0, other_avg
= 0;
1355 foreach (int point
, points
) {
1356 avg
+= (double) point
/ points
.length();
1358 foreach (int point
, other_points
) {
1359 other_avg
+= (double) point
/ other_points
.length();
1361 return avg
< other_avg
;
1363 return QTreeWidgetItem::operator<(other
);
1366 QVariant
InterfaceTreeWidgetItem::data(int column
, int role
) const
1368 // See setData for the special col_traffic_ treatment.
1369 if (column
== col_traffic_
&& role
== Qt::UserRole
) {
1370 return QVariant::fromValue(points
);
1373 if (column
== col_snaplen_
&& role
== Qt::DisplayRole
) {
1374 QVariant data
= QTreeWidgetItem::data(column
, role
);
1375 if (data
.toInt() == WTAP_MAX_PACKET_SIZE_STANDARD
|| data
.toInt() == 0) {
1376 return InterfaceTreeDelegate::tr("default");
1380 return QTreeWidgetItem::data(column
, role
);
1383 void InterfaceTreeWidgetItem::setData(int column
, int role
, const QVariant
&value
)
1385 // Workaround for closing editors on updates to the points list: normally
1386 // QTreeWidgetItem::setData emits dataChanged when the value (list) changes.
1387 // We could store a pointer to the list, or just have this hack that does
1388 // not emit dataChanged.
1389 if (column
== col_traffic_
&& role
== Qt::UserRole
) {
1390 points
= value
.value
<QList
<int> >();
1394 QTreeWidgetItem::setData(column
, role
, value
);
1398 // InterfaceTreeDelegate
1401 #include <QComboBox>
1403 InterfaceTreeDelegate::InterfaceTreeDelegate(QObject
*parent
)
1404 : QStyledItemDelegate(parent
), tree_(NULL
)
1409 InterfaceTreeDelegate::~InterfaceTreeDelegate()
1414 QWidget
* InterfaceTreeDelegate::createEditor(QWidget
*parent
, const QStyleOptionViewItem
&, const QModelIndex
&idx
) const
1417 int buffer
= DEFAULT_CAPTURE_BUFFER_SIZE
;
1418 unsigned snap
= WTAP_MAX_PACKET_SIZE_STANDARD
;
1419 GList
*links
= NULL
;
1421 if (idx
.column() > 1 && idx
.data().toString().compare(UTF8_EM_DASH
)) {
1422 QTreeWidgetItem
*ti
= tree_
->topLevelItem(idx
.row());
1423 QString interface_name
= ti
->text(col_interface_
);
1424 interface_t
*device
= find_device_by_if_name(interface_name
);
1427 buffer
= device
->buffer
;
1428 snap
= device
->snaplen
;
1429 links
= device
->links
;
1431 switch (idx
.column()) {
1433 case col_interface_
:
1440 QStringList valid_link_types
;
1442 // XXX The GTK+ UI fills in all link types, valid or not. We add
1443 // only the valid ones. If we *do* wish to include invalid link
1444 // types we'll have to jump through the hoops necessary to disable
1447 for (list
= links
; list
!= Q_NULLPTR
; list
= gxx_list_next(list
)) {
1448 linkr
= gxx_list_data(link_row
*, list
);
1449 if (linkr
->dlt
>= 0) {
1450 valid_link_types
<< linkr
->name
;
1454 if (valid_link_types
.size() < 2) {
1457 QComboBox
*cb
= new QComboBox(parent
);
1458 cb
->addItems(valid_link_types
);
1460 connect(cb
, &QComboBox::currentTextChanged
, this, &InterfaceTreeDelegate::linkTypeChanged
);
1466 QSpinBox
*sb
= new QSpinBox(parent
);
1467 sb
->setRange(0, WTAP_MAX_PACKET_SIZE_STANDARD
);
1469 sb
->setWrapping(true);
1470 sb
->setSpecialValueText(tr("default"));
1471 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1472 connect(sb
, &QSpinBox::valueChanged
, this, &InterfaceTreeDelegate::snapshotLengthChanged
);
1474 connect(sb
, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged
), this, &InterfaceTreeDelegate::snapshotLengthChanged
);
1481 QSpinBox
*sb
= new QSpinBox(parent
);
1482 sb
->setRange(1, WTAP_MAX_PACKET_SIZE_STANDARD
);
1483 sb
->setValue(buffer
);
1484 sb
->setWrapping(true);
1485 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1486 connect(sb
, &QSpinBox::valueChanged
, this, &InterfaceTreeDelegate::bufferSizeChanged
);
1488 connect(sb
, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged
), this, &InterfaceTreeDelegate::bufferSizeChanged
);
1495 // XXX: Should this take the interface name, so that the history
1496 // list is taken from the interface-specific recent cfilter list?
1497 CaptureFilterCombo
*cf
= new CaptureFilterCombo(parent
, true);
1498 connect(cf
->lineEdit(), &QLineEdit::textEdited
, this, &InterfaceTreeDelegate::filterChanged
);
1506 w
->setAutoFillBackground(true);
1510 bool InterfaceTreeDelegate::eventFilter(QObject
*object
, QEvent
*event
)
1512 QComboBox
* comboBox
= dynamic_cast<QComboBox
*>(object
);
1514 if (event
->type() == QEvent::MouseButtonRelease
) {
1515 comboBox
->showPopup();
1519 return QStyledItemDelegate::eventFilter(object
, event
);
1524 void InterfaceTreeDelegate::linkTypeChanged(const QString selected_link_type
)
1528 interface_t
*device
;
1530 QTreeWidgetItem
*ti
= tree_
->currentItem();
1534 QString interface_name
= ti
->text(col_interface_
);
1535 device
= find_device_by_if_name(interface_name
);
1539 for (list
= device
->links
; list
!= Q_NULLPTR
; list
= gxx_list_next(list
)) {
1540 temp
= gxx_list_data(link_row
*, list
);
1541 if (!selected_link_type
.compare(temp
->name
)) {
1542 device
->active_dlt
= temp
->dlt
;
1545 // XXX We might want to verify that active_dlt is valid at this point.
1548 void InterfaceTreeDelegate::snapshotLengthChanged(int value
)
1550 interface_t
*device
;
1551 QTreeWidgetItem
*ti
= tree_
->currentItem();
1555 QString interface_name
= ti
->text(col_interface_
);
1556 device
= find_device_by_if_name(interface_name
);
1560 if (value
!= WTAP_MAX_PACKET_SIZE_STANDARD
&& value
!= 0) {
1561 device
->has_snaplen
= true;
1562 device
->snaplen
= value
;
1564 device
->has_snaplen
= false;
1565 device
->snaplen
= WTAP_MAX_PACKET_SIZE_STANDARD
;
1569 void InterfaceTreeDelegate::bufferSizeChanged(int value
)
1571 interface_t
*device
;
1572 QTreeWidgetItem
*ti
= tree_
->currentItem();
1576 QString interface_name
= ti
->text(col_interface_
);
1577 device
= find_device_by_if_name(interface_name
);
1581 device
->buffer
= value
;
1584 #endif /* HAVE_LIBPCAP */