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"
23 #include "capture_opts.h"
27 #include <QAbstractItemModel>
28 #include <QMessageBox>
31 #include "ringbuffer.h"
32 #include "ui/capture_ui_utils.h"
33 #include "ui/capture_globals.h"
34 #include "ui/iface_lists.h"
35 #include "ui/file_dialog.h"
37 #include "ui/ws_ui_util.h"
39 #include <wsutil/utf8_entities.h>
40 #include "ui/preference_utils.h"
41 #include "ui/recent.h"
44 #include <epan/prefs.h>
45 #include <epan/prefs-int.h>
46 #include <epan/addr_resolv.h>
47 #include <wsutil/filesystem.h>
49 #include <wiretap/wtap.h>
51 #include <ui/qt/utils/qt_ui_utils.h>
52 #include <ui/qt/utils/stock_icon.h>
53 #include <ui/qt/models/sparkline_delegate.h>
54 #include "ui/qt/widgets/wireshark_file_dialog.h"
57 // - Set a size hint for item delegates.
58 // - Make promiscuous and monitor mode checkboxes.
59 // - Fix InterfaceTreeDelegate method names.
60 // - You can edit filters via the main CaptureFilterCombo and via each
61 // individual interface row. We should probably do one or the other.
62 // - There might be a point in having the separate combo boxes in the
63 // individual interface row, if their CaptureFilterCombos actually
64 // called recent_get_cfilter_list with the interface name to get the
65 // separate list of recent capture filters for that interface, but
68 const int stat_update_interval_
= 1000; // ms
70 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
71 #define SHOW_BUFFER_COLUMN 1
74 #if defined(HAVE_PCAP_CREATE)
75 #define SHOW_MONITOR_COLUMN 1
79 * Symbolic names for column indices.
95 static interface_t
*find_device_by_if_name(const QString
&interface_name
)
99 for (i
= 0; i
< global_capture_opts
.all_ifaces
->len
; i
++) {
100 device
= &g_array_index(global_capture_opts
.all_ifaces
, interface_t
, i
);
101 if (!interface_name
.compare(device
->display_name
) && !device
->hidden
&& device
->if_info
.type
!= IF_PIPE
) {
108 class InterfaceTreeWidgetItem
: public QTreeWidgetItem
111 InterfaceTreeWidgetItem(QTreeWidget
*tree
) : QTreeWidgetItem(tree
) {}
112 bool operator< (const QTreeWidgetItem
&other
) const;
113 QVariant
data(int column
, int role
) const;
114 void setData(int column
, int role
, const QVariant
&value
);
117 void updateInterfaceColumns(interface_t
*device
)
121 // Prevent infinite recursive signal loop
122 // itemChanged->interfaceItemChanged->updateInterfaceColumns
123 treeWidget()->blockSignals(true);
124 QString default_str
= QObject::tr("default");
126 // XXX - this is duplicated in InterfaceTreeModel::data;
127 // it should be done in common code somewhere.
129 if (device
->active_dlt
== -1)
130 linkname
= "Unknown";
132 linkname
= QObject::tr("DLT %1").arg(device
->active_dlt
);
133 for (GList
*list
= device
->links
; list
!= NULL
; list
= gxx_list_next(list
)) {
134 link_row
*linkr
= gxx_list_data(link_row
*, list
);
135 if (linkr
->dlt
== device
->active_dlt
) {
136 linkname
= linkr
->name
;
141 setText(col_link_
, linkname
);
143 if (device
->if_info
.type
== IF_EXTCAP
) {
144 /* extcap interfaces does not have this settings */
145 setApplicable(col_pmode_
, false);
147 setApplicable(col_snaplen_
, false);
148 #ifdef SHOW_BUFFER_COLUMN
149 setApplicable(col_buffer_
, false);
152 setApplicable(col_pmode_
, true);
153 setCheckState(col_pmode_
, device
->pmode
? Qt::Checked
: Qt::Unchecked
);
155 QString snaplen_string
= device
->has_snaplen
? QString::number(device
->snaplen
) : default_str
;
156 setText(col_snaplen_
, snaplen_string
);
157 #ifdef SHOW_BUFFER_COLUMN
158 setText(col_buffer_
, QString::number(device
->buffer
));
161 setText(col_filter_
, device
->cfilter
);
163 #ifdef SHOW_MONITOR_COLUMN
164 if (device
->monitor_mode_supported
) {
165 setApplicable(col_monitor_
, true);
166 setCheckState(col_monitor_
, device
->monitor_mode_enabled
? Qt::Checked
: Qt::Unchecked
);
168 setApplicable(col_monitor_
, false);
171 treeWidget()->blockSignals(false);
174 void setApplicable(int column
, bool applicable
= false) {
175 QPalette palette
= mainApp
->palette();
178 setText(column
, QString());
180 setData(column
, Qt::CheckStateRole
, QVariant());
181 palette
.setCurrentColorGroup(QPalette::Disabled
);
182 setText(column
, UTF8_EM_DASH
);
184 setForeground(column
, palette
.text().color());
189 CaptureOptionsDialog::CaptureOptionsDialog(QWidget
*parent
) :
190 GeometryStateDialog(parent
),
191 ui(new Ui::CaptureOptionsDialog
)
195 setWindowTitle(mainApp
->windowTitleString(tr("Capture Options")));
200 ui
->buttonBox
->button(QDialogButtonBox::Ok
)->setText(tr("Start"));
202 // Start out with the list *not* sorted, so they show up in the order
203 // in which they were provided
204 ui
->interfaceTree
->sortByColumn(-1, Qt::AscendingOrder
);
205 ui
->interfaceTree
->setItemDelegateForColumn(col_extcap_
, &interface_item_delegate_
);
206 ui
->interfaceTree
->setItemDelegateForColumn(col_interface_
, &interface_item_delegate_
);
207 ui
->interfaceTree
->setItemDelegateForColumn(col_traffic_
, new SparkLineDelegate(this));
208 ui
->interfaceTree
->setItemDelegateForColumn(col_link_
, &interface_item_delegate_
);
210 ui
->interfaceTree
->setItemDelegateForColumn(col_snaplen_
, &interface_item_delegate_
);
211 #ifdef SHOW_BUFFER_COLUMN
212 ui
->interfaceTree
->setItemDelegateForColumn(col_buffer_
, &interface_item_delegate_
);
214 ui
->interfaceTree
->setColumnHidden(col_buffer_
, true);
216 #ifndef SHOW_MONITOR_COLUMN
217 ui
->interfaceTree
->setColumnHidden(col_monitor_
, true);
218 ui
->captureMonitorModeCheckBox
->setVisible(false);
220 ui
->interfaceTree
->setItemDelegateForColumn(col_filter_
, &interface_item_delegate_
);
222 interface_item_delegate_
.setTree(ui
->interfaceTree
);
224 ui
->filenameLineEdit
->setPlaceholderText(tr("Leave blank to use a temporary file"));
226 ui
->rbCompressionNone
->setChecked(true);
227 ui
->rbTimeNum
->setChecked(true);
229 ui
->tempDirLineEdit
->setPlaceholderText(g_get_tmp_dir());
230 ui
->tempDirLineEdit
->setText(global_capture_opts
.temp_dir
);
232 // Changes in interface selections or capture filters should be propagated
233 // to the main welcome screen where they will be applied to the global
235 connect(this, SIGNAL(interfacesChanged()), ui
->captureFilterComboBox
, SIGNAL(interfacesChanged()));
236 connect(ui
->captureFilterComboBox
, SIGNAL(captureFilterSyntaxChanged(bool)), this, SLOT(updateWidgets()));
237 connect(ui
->captureFilterComboBox
->lineEdit(), SIGNAL(textEdited(QString
)),
238 this, SLOT(filterEdited()));
239 connect(ui
->captureFilterComboBox
->lineEdit(), SIGNAL(textEdited(QString
)),
240 this, SIGNAL(captureFilterTextEdited(QString
)));
241 connect(&interface_item_delegate_
, SIGNAL(filterChanged(QString
)),
242 ui
->captureFilterComboBox
->lineEdit(), SLOT(setText(QString
)));
243 connect(&interface_item_delegate_
, SIGNAL(filterChanged(QString
)),
244 this, SIGNAL(captureFilterTextEdited(QString
)));
245 connect(this, SIGNAL(ifsChanged()), this, SLOT(refreshInterfaceList()));
246 connect(mainApp
, SIGNAL(localInterfaceListChanged()), this, SLOT(updateLocalInterfaces()));
247 connect(ui
->browseButton
, SIGNAL(clicked()), this, SLOT(browseButtonClicked()));
248 connect(ui
->interfaceTree
, SIGNAL(itemClicked(QTreeWidgetItem
*,int)), this, SLOT(itemClicked(QTreeWidgetItem
*,int)));
249 connect(ui
->interfaceTree
, SIGNAL(itemDoubleClicked(QTreeWidgetItem
*,int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem
*,int)));
250 connect(ui
->tempDirBrowseButton
, SIGNAL(clicked()), this, SLOT(tempDirBrowseButtonClicked()));
252 // Ring buffer minimums (all 1 except # of files)
253 ui
->PktSpinBox
->setMinimum(1);
254 ui
->MBSpinBox
->setMinimum(1);
255 ui
->SecsSpinBox
->setMinimum(1);
256 ui
->IntervalSecsSpinBox
->setMinimum(1);
257 ui
->RbSpinBox
->setMinimum(2);
260 ui
->stopPktSpinBox
->setMinimum(1);
261 ui
->stopFilesSpinBox
->setMinimum(1);
262 ui
->stopMBSpinBox
->setMinimum(1);
263 ui
->stopSecsSpinBox
->setMinimum(1);
265 // Capture size maximum depends on units. Initial unit is kB.
266 ui
->MBSpinBox
->setMaximum(2000000000);
267 ui
->stopMBSpinBox
->setMaximum(2000000000);
269 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
270 connect(ui
->MBComboBox
, QOverload
<int>::of(&QComboBox::currentIndexChanged
), this, &CaptureOptionsDialog::MBComboBoxIndexChanged
);
271 connect(ui
->stopMBComboBox
, QOverload
<int>::of(&QComboBox::currentIndexChanged
), this, &CaptureOptionsDialog::stopMBComboBoxIndexChanged
);
273 connect(ui
->MBComboBox
, &QComboBox::currentIndexChanged
, this, &CaptureOptionsDialog::MBComboBoxIndexChanged
);
274 connect(ui
->stopMBComboBox
, &QComboBox::currentIndexChanged
, this, &CaptureOptionsDialog::stopMBComboBoxIndexChanged
);
277 ui
->tabWidget
->setCurrentIndex(0);
282 CaptureOptionsDialog::~CaptureOptionsDialog()
287 /* Update global device selections based on the TreeWidget selection. */
288 void CaptureOptionsDialog::updateGlobalDeviceSelections()
291 QTreeWidgetItemIterator
iter(ui
->interfaceTree
);
293 global_capture_opts
.num_selected
= 0;
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 ((*iter
)->isSelected()) {
301 device
->selected
= true;
302 global_capture_opts
.num_selected
++;
304 device
->selected
= false;
314 /* Update TreeWidget selection based on global device selections. */
315 void CaptureOptionsDialog::updateFromGlobalDeviceSelections()
318 QTreeWidgetItemIterator
iter(ui
->interfaceTree
);
320 // Prevent recursive interface interfaceSelected signals
321 ui
->interfaceTree
->blockSignals(true);
324 QString device_name
= (*iter
)->data(col_interface_
, Qt::UserRole
).value
<QString
>();
325 for (unsigned i
= 0; i
< global_capture_opts
.all_ifaces
->len
; i
++) {
326 interface_t
*device
= &g_array_index(global_capture_opts
.all_ifaces
, interface_t
, i
);
327 if (device_name
.compare(QString().fromUtf8(device
->name
)) == 0) {
328 if ((bool)device
->selected
!= (*iter
)->isSelected()) {
329 (*iter
)->setSelected(device
->selected
);
337 ui
->interfaceTree
->blockSignals(false);
341 void CaptureOptionsDialog::interfaceSelected()
343 if (sender() == ui
->interfaceTree
) {
344 // Local changes, propagate our changes
345 updateGlobalDeviceSelections();
346 emit
interfacesChanged();
348 // Changes from the welcome screen, adjust to its state.
349 updateFromGlobalDeviceSelections();
352 updateSelectedFilter();
357 void CaptureOptionsDialog::filterEdited()
359 QList
<QTreeWidgetItem
*> si
= ui
->interfaceTree
->selectedItems();
361 foreach (QTreeWidgetItem
*ti
, si
) {
362 ti
->setText(col_filter_
, ui
->captureFilterComboBox
->lineEdit()->text());
365 if (si
.count() > 0) {
366 QModelIndex col_filter_idx
= ui
->interfaceTree
->model()->index(ui
->interfaceTree
->indexOfTopLevelItem(si
[0]), col_filter_
);
367 ui
->interfaceTree
->scrollTo(col_filter_idx
);
371 void CaptureOptionsDialog::updateWidgets()
373 SyntaxLineEdit
*sle
= qobject_cast
<SyntaxLineEdit
*>(ui
->captureFilterComboBox
->lineEdit());
378 bool can_capture
= false;
380 if (ui
->interfaceTree
->selectedItems().count() > 0 && sle
->syntaxState() != SyntaxLineEdit::Invalid
) {
384 ui
->compileBPF
->setEnabled(can_capture
);
385 ui
->buttonBox
->button(QDialogButtonBox::Ok
)->setEnabled(can_capture
);
388 void CaptureOptionsDialog::on_capturePromModeCheckBox_toggled(bool checked
)
391 prefs
.capture_prom_mode
= checked
;
392 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
393 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(ui
->interfaceTree
->topLevelItem(row
));
396 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
397 device
= getDeviceByName(device_name
);
398 if (!device
) continue;
399 device
->pmode
= checked
;
400 ti
->updateInterfaceColumns(device
);
404 void CaptureOptionsDialog::on_captureMonitorModeCheckBox_toggled(bool checked
)
407 prefs
.capture_monitor_mode
= checked
;
408 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
409 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(ui
->interfaceTree
->topLevelItem(row
));
412 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
413 device
= getDeviceByName(device_name
);
414 if (!device
) continue;
415 if (device
->monitor_mode_supported
) {
416 device
->monitor_mode_enabled
= checked
;
417 ti
->updateInterfaceColumns(device
);
422 void CaptureOptionsDialog::browseButtonClicked()
424 QString file_name
= WiresharkFileDialog::getSaveFileName(this, tr("Specify a Capture File"), get_open_dialog_initial_dir());
425 ui
->filenameLineEdit
->setText(file_name
);
428 void CaptureOptionsDialog::tempDirBrowseButtonClicked()
430 QString specified_dir
= WiresharkFileDialog::getExistingDirectory(this, tr("Specify temporary directory"));
431 ui
->tempDirLineEdit
->setText(specified_dir
);
434 void CaptureOptionsDialog::interfaceItemChanged(QTreeWidgetItem
*item
, int column
)
436 QWidget
* editor
= ui
->interfaceTree
->indexWidget(ui
->interfaceTree
->currentIndex());
438 ui
->interfaceTree
->closePersistentEditor(item
, ui
->interfaceTree
->currentColumn());
441 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(item
);
445 QString interface_name
= ti
->text(col_interface_
);
446 device
= find_device_by_if_name(interface_name
);
452 device
->pmode
= item
->checkState(col_pmode_
) == Qt::Checked
? true : false;
453 ti
->updateInterfaceColumns(device
);
456 #ifdef SHOW_MONITOR_COLUMN
459 bool monitor_mode
= false;
460 if (ti
->checkState(col_monitor_
) == Qt::Checked
) monitor_mode
= true;
462 if_capabilities_t
*caps
;
463 char *auth_str
= NULL
;
464 QString active_dlt_name
;
466 set_active_dlt(device
, global_capture_opts
.default_options
.linktype
);
468 #ifdef HAVE_PCAP_REMOTE
469 if (device
->remote_opts
.remote_host_opts
.auth_type
== CAPTURE_AUTH_PWD
) {
470 auth_str
= ws_strdup_printf("%s:%s", device
->remote_opts
.remote_host_opts
.auth_username
,
471 device
->remote_opts
.remote_host_opts
.auth_password
);
474 caps
= capture_get_if_capabilities(device
->name
, monitor_mode
, auth_str
, NULL
, NULL
, main_window_update
);
477 if (caps
!= Q_NULLPTR
) {
479 #if GLIB_CHECK_VERSION(2, 68, 0)
480 g_list_free_full(g_steal_pointer(&device
->links
), capture_opts_free_link_row
);
482 g_list_free_full((GList
*)g_steal_pointer(&device
->links
), capture_opts_free_link_row
);
484 device
->active_dlt
= -1;
485 device
->monitor_mode_supported
= caps
->can_set_rfmon
;
486 device
->monitor_mode_enabled
= monitor_mode
&& caps
->can_set_rfmon
;
487 GList
*lt_list
= device
->monitor_mode_enabled
? caps
->data_link_types_rfmon
: caps
->data_link_types
;
489 for (GList
*lt_entry
= lt_list
; lt_entry
!= Q_NULLPTR
; lt_entry
= gxx_list_next(lt_entry
)) {
490 link_row
*linkr
= g_new(link_row
, 1);
491 data_link_info_t
*data_link_info
= gxx_list_data(data_link_info_t
*, lt_entry
);
493 * For link-layer types libpcap/WinPcap/Npcap doesn't know
494 * about, the name will be "DLT n", and the description will
496 * We mark those as unsupported, and don't allow them to be
497 * used - capture filters won't work on them, for example.
499 if (data_link_info
->description
!= Q_NULLPTR
) {
500 linkr
->dlt
= data_link_info
->dlt
;
501 if (active_dlt_name
.isEmpty()) {
502 device
->active_dlt
= data_link_info
->dlt
;
503 active_dlt_name
= data_link_info
->description
;
505 linkr
->name
= g_strdup(data_link_info
->description
);
508 /* XXX - should we just omit them? */
509 str
= ws_strdup_printf("%s (not supported)", data_link_info
->name
);
511 linkr
->name
= g_strdup(str
);
514 device
->links
= g_list_append(device
->links
, linkr
);
516 free_if_capabilities(caps
);
518 /* We don't know whether this supports monitor mode or not;
519 don't ask for monitor mode. */
520 device
->monitor_mode_enabled
= false;
521 device
->monitor_mode_supported
= false;
524 ti
->updateInterfaceColumns(device
);
528 #endif // SHOW_MONITOR_COLUMN
534 void CaptureOptionsDialog::itemClicked(QTreeWidgetItem
*item
, int column
)
536 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(item
);
541 QString interface_name
= ti
->text(col_interface_
);
542 device
= find_device_by_if_name(interface_name
);
548 if (device
->if_info
.type
== IF_EXTCAP
) {
549 /* this checks if configuration is required and not yet provided or saved via prefs */
550 QString device_name
= ti
->data(col_extcap_
, Qt::UserRole
).value
<QString
>();
551 if (extcap_has_configuration((const char *)(device_name
.toStdString().c_str())))
553 emit
showExtcapOptions(device_name
, false);
562 #endif /* HAVE_LIBPCAP */
565 void CaptureOptionsDialog::itemDoubleClicked(QTreeWidgetItem
*item
, int column
)
567 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(item
);
572 // Double click starts capture just on columns which are not editable
578 QString interface_name
= ti
->text(col_interface_
);
579 device
= find_device_by_if_name(interface_name
);
582 if (device
->if_info
.type
== IF_EXTCAP
) {
583 /* this checks if configuration is required and not yet provided or saved via prefs */
584 QString device_name
= ti
->data(col_extcap_
, Qt::UserRole
).value
<QString
>();
585 if (extcap_requires_configuration((const char *)(device_name
.toStdString().c_str())))
587 emit
showExtcapOptions(device_name
, true);
591 #endif /* HAVE_LIBPCAP */
602 void CaptureOptionsDialog::MBComboBoxIndexChanged(int index
)
606 ui
->MBSpinBox
->setMaximum(2000000000);
609 ui
->MBSpinBox
->setMaximum(2000000);
612 ui
->MBSpinBox
->setMaximum(2000);
617 void CaptureOptionsDialog::stopMBComboBoxIndexChanged(int index
)
621 ui
->stopMBSpinBox
->setMaximum(2000000000);
624 ui
->stopMBSpinBox
->setMaximum(2000000);
627 ui
->stopMBSpinBox
->setMaximum(2000);
632 void CaptureOptionsDialog::on_gbStopCaptureAuto_toggled(bool checked
)
634 global_capture_opts
.has_file_interval
= checked
;
637 void CaptureOptionsDialog::on_gbNewFileAuto_toggled(bool checked
)
639 global_capture_opts
.multi_files_on
= checked
;
640 ui
->stopMBCheckBox
->setEnabled(checked
?false:true);
641 ui
->stopMBSpinBox
->setEnabled(checked
?false:true);
642 ui
->stopMBComboBox
->setEnabled(checked
?false:true);
643 ui
->gbCompression
->setEnabled(checked
);
644 ui
->rbCompressionNone
->setEnabled(checked
);
645 #if defined(HAVE_ZLIB) || defined(HAVE_ZLIBNG)
646 ui
->rbCompressionGzip
->setEnabled(checked
);
648 ui
->rbCompressionGzip
->setEnabled(false);
652 void CaptureOptionsDialog::on_cbUpdatePacketsRT_toggled(bool checked
)
654 global_capture_opts
.real_time_mode
= checked
;
657 void CaptureOptionsDialog::on_cbAutoScroll_toggled(bool checked
)
659 recent
.capture_auto_scroll
= checked
;
662 void CaptureOptionsDialog::on_cbExtraCaptureInfo_toggled(bool checked
)
664 global_capture_opts
.show_info
= checked
;
667 void CaptureOptionsDialog::on_cbResolveMacAddresses_toggled(bool checked
)
669 gbl_resolv_flags
.mac_name
= checked
;
672 void CaptureOptionsDialog::on_cbResolveNetworkNames_toggled(bool checked
)
674 gbl_resolv_flags
.network_name
= checked
;
677 void CaptureOptionsDialog::on_cbResolveTransportNames_toggled(bool checked
)
679 gbl_resolv_flags
.transport_name
= checked
;
682 void CaptureOptionsDialog::on_buttonBox_accepted()
684 if (saveOptionsToPreferences()) {
687 InterfaceTreeWidgetItem
*ti
= dynamic_cast<InterfaceTreeWidgetItem
*>(ui
->interfaceTree
->currentItem());
691 QString interface_name
= ti
->text(col_interface_
);
692 device
= find_device_by_if_name(interface_name
);
693 if (device
&& device
->if_info
.type
== IF_EXTCAP
) {
694 /* this checks if configuration is required and not yet provided or saved via prefs */
695 QString device_name
= ti
->data(col_extcap_
, Qt::UserRole
).value
<QString
>();
696 if (extcap_requires_configuration((const char *)(device_name
.toStdString().c_str())))
698 emit
showExtcapOptions(device_name
, true);
703 #endif /* HAVE_LIBPCAP */
705 emit
setFilterValid(true, ui
->captureFilterComboBox
->lineEdit()->text());
710 // Not sure why we have to do this manually.
711 void CaptureOptionsDialog::on_buttonBox_rejected()
713 if (saveOptionsToPreferences()) {
718 void CaptureOptionsDialog::on_buttonBox_helpRequested()
720 // Probably the wrong URL.
721 mainApp
->helpTopicAction(HELP_CAPTURE_OPTIONS_DIALOG
);
724 void CaptureOptionsDialog::updateInterfaces()
726 if (prefs
.capture_pcap_ng
) {
727 ui
->rbPcapng
->setChecked(true);
729 ui
->rbPcap
->setChecked(true);
731 ui
->capturePromModeCheckBox
->setChecked(prefs
.capture_prom_mode
);
732 ui
->captureMonitorModeCheckBox
->setChecked(prefs
.capture_monitor_mode
);
733 ui
->captureMonitorModeCheckBox
->setEnabled(false);
735 if (global_capture_opts
.saving_to_file
) {
736 ui
->filenameLineEdit
->setText(QString(global_capture_opts
.orig_save_file
));
739 ui
->gbNewFileAuto
->setChecked(global_capture_opts
.multi_files_on
);
740 ui
->PktCheckBox
->setChecked(global_capture_opts
.has_file_packets
);
741 if (global_capture_opts
.has_file_packets
) {
742 ui
->PktSpinBox
->setValue(global_capture_opts
.file_packets
);
744 ui
->MBCheckBox
->setChecked(global_capture_opts
.has_autostop_filesize
);
745 if (global_capture_opts
.has_autostop_filesize
) {
746 int value
= global_capture_opts
.autostop_filesize
;
747 if (value
> 1000000) {
748 if (global_capture_opts
.multi_files_on
) {
749 ui
->MBSpinBox
->setValue(value
/ 1000000);
750 ui
->MBComboBox
->setCurrentIndex(2);
752 ui
->stopMBCheckBox
->setChecked(true);
753 ui
->stopMBSpinBox
->setValue(value
/ 1000000);
754 ui
->stopMBComboBox
->setCurrentIndex(2);
756 } else if (value
> 1000 && value
% 1000 == 0) {
757 if (global_capture_opts
.multi_files_on
) {
758 ui
->MBSpinBox
->setValue(value
/ 1000);
759 ui
->MBComboBox
->setCurrentIndex(1);
761 ui
->stopMBCheckBox
->setChecked(true);
762 ui
->stopMBSpinBox
->setValue(value
/ 1000);
763 ui
->stopMBComboBox
->setCurrentIndex(1);
766 if (global_capture_opts
.multi_files_on
) {
767 ui
->MBSpinBox
->setValue(value
);
768 ui
->MBComboBox
->setCurrentIndex(0);
770 ui
->stopMBCheckBox
->setChecked(true);
771 ui
->stopMBSpinBox
->setValue(value
);
772 ui
->stopMBComboBox
->setCurrentIndex(0);
777 ui
->SecsCheckBox
->setChecked(global_capture_opts
.has_file_duration
);
778 if (global_capture_opts
.has_file_duration
) {
779 int value
= global_capture_opts
.file_duration
;
780 if (value
> 3600 && value
% 3600 == 0) {
781 ui
->SecsSpinBox
->setValue(value
/ 3600);
782 ui
->SecsComboBox
->setCurrentIndex(2);
783 } else if (value
> 60 && value
% 60 == 0) {
784 ui
->SecsSpinBox
->setValue(value
/ 60);
785 ui
->SecsComboBox
->setCurrentIndex(1);
787 ui
->SecsSpinBox
->setValue(value
);
788 ui
->SecsComboBox
->setCurrentIndex(0);
792 ui
->IntervalSecsCheckBox
->setChecked(global_capture_opts
.has_file_interval
);
793 if (global_capture_opts
.has_file_interval
) {
794 int value
= global_capture_opts
.file_interval
;
795 if (value
> 3600 && value
% 3600 == 0) {
796 ui
->IntervalSecsSpinBox
->setValue(value
/ 3600);
797 ui
->IntervalSecsComboBox
->setCurrentIndex(2);
798 } else if (value
> 60 && value
% 60 == 0) {
799 ui
->IntervalSecsSpinBox
->setValue(value
/ 60);
800 ui
->IntervalSecsComboBox
->setCurrentIndex(1);
802 ui
->IntervalSecsSpinBox
->setValue(value
);
803 ui
->IntervalSecsComboBox
->setCurrentIndex(0);
807 if (global_capture_opts
.has_ring_num_files
) {
808 ui
->RbSpinBox
->setValue(global_capture_opts
.ring_num_files
);
809 ui
->RbCheckBox
->setCheckState(Qt::Checked
);
812 if (global_capture_opts
.has_autostop_duration
) {
813 ui
->stopSecsCheckBox
->setChecked(true);
814 int value
= global_capture_opts
.autostop_duration
;
815 if (value
> 3600 && value
% 3600 == 0) {
816 ui
->stopSecsSpinBox
->setValue(value
/ 3600);
817 ui
->stopSecsComboBox
->setCurrentIndex(2);
818 } else if (value
> 60 && value
% 60 == 0) {
819 ui
->stopSecsSpinBox
->setValue(value
/ 60);
820 ui
->stopSecsComboBox
->setCurrentIndex(1);
822 ui
->stopSecsSpinBox
->setValue(value
);
823 ui
->stopSecsComboBox
->setCurrentIndex(0);
827 if (global_capture_opts
.has_autostop_packets
) {
828 ui
->stopPktCheckBox
->setChecked(true);
829 ui
->stopPktSpinBox
->setValue(global_capture_opts
.autostop_packets
);
832 if (global_capture_opts
.has_autostop_files
) {
833 ui
->stopFilesCheckBox
->setChecked(true);
834 ui
->stopFilesSpinBox
->setValue(global_capture_opts
.autostop_files
);
837 ui
->cbUpdatePacketsRT
->setChecked(global_capture_opts
.real_time_mode
);
838 ui
->cbAutoScroll
->setChecked(recent
.capture_auto_scroll
);
839 ui
->cbExtraCaptureInfo
->setChecked(global_capture_opts
.show_info
);
841 ui
->cbResolveMacAddresses
->setChecked(gbl_resolv_flags
.mac_name
);
842 ui
->cbResolveNetworkNames
->setChecked(gbl_resolv_flags
.network_name
);
843 ui
->cbResolveTransportNames
->setChecked(gbl_resolv_flags
.transport_name
);
845 // Rebuild the interface list without disturbing the main welcome screen.
846 disconnect(ui
->interfaceTree
, SIGNAL(itemSelectionChanged()), this, SLOT(interfaceSelected()));
847 ui
->interfaceTree
->clear();
849 #ifdef SHOW_BUFFER_COLUMN
854 QList
<QTreeWidgetItem
*> selected_interfaces
;
856 disconnect(ui
->interfaceTree
, SIGNAL(itemChanged(QTreeWidgetItem
*,int)), this, SLOT(interfaceItemChanged(QTreeWidgetItem
*,int)));
858 if (global_capture_opts
.all_ifaces
->len
> 0) {
861 for (unsigned device_idx
= 0; device_idx
< global_capture_opts
.all_ifaces
->len
; device_idx
++) {
862 device
= &g_array_index(global_capture_opts
.all_ifaces
, interface_t
, device_idx
);
864 /* Continue if capture device is hidden */
865 if (device
->hidden
) {
869 // Traffic sparklines
870 InterfaceTreeWidgetItem
*ti
= new InterfaceTreeWidgetItem(ui
->interfaceTree
);
871 ti
->setFlags(ti
->flags() | Qt::ItemIsEditable
);
873 if (device
->if_info
.type
== IF_EXTCAP
) {
874 ti
->setIcon(col_extcap_
, QIcon(StockIcon("x-capture-options")));
875 ti
->setData(col_extcap_
, Qt::UserRole
, QString(device
->if_info
.name
));
876 ti
->setToolTip(col_extcap_
, QStringLiteral("Extcap interface settings"));
879 ti
->setText(col_interface_
, device
->display_name
);
880 ti
->setData(col_interface_
, Qt::UserRole
, QString(device
->name
));
881 if (device
->if_info
.type
!= IF_EXTCAP
)
882 ti
->setData(col_traffic_
, Qt::UserRole
, QVariant::fromValue(ti
->points
));
884 if (device
->no_addresses
> 0) {
885 QString addr_str
= tr("%1: %2").arg(device
->no_addresses
> 1 ? tr("Addresses") : tr("Address")).arg(device
->addresses
);
886 QTreeWidgetItem
*addr_ti
= new QTreeWidgetItem(ti
);
888 addr_str
.replace('\n', ", ");
889 addr_ti
->setText(0, addr_str
);
890 addr_ti
->setFlags(addr_ti
->flags() ^ Qt::ItemIsSelectable
);
891 addr_ti
->setFirstColumnSpanned(true);
892 addr_ti
->setToolTip(col_interface_
, QStringLiteral("<span>%1</span>").arg(addr_str
));
893 ti
->setToolTip(col_interface_
, QStringLiteral("<span>%1</span>").arg(addr_str
));
895 ti
->setToolTip(col_interface_
, tr("no addresses"));
898 if (capture_dev_user_pmode_find(device
->name
, &pmode
)) {
899 device
->pmode
= pmode
;
901 if (capture_dev_user_snaplen_find(device
->name
, &hassnap
, &snaplen
)) {
902 /* Default snap length set in preferences */
903 device
->snaplen
= snaplen
;
904 device
->has_snaplen
= snaplen
== WTAP_MAX_PACKET_SIZE_STANDARD
? false : hassnap
;
906 /* No preferences set yet, use default values */
907 device
->snaplen
= WTAP_MAX_PACKET_SIZE_STANDARD
;
908 device
->has_snaplen
= false;
911 #ifdef SHOW_BUFFER_COLUMN
912 if (capture_dev_user_buffersize_find(device
->name
) != -1) {
913 buffer
= capture_dev_user_buffersize_find(device
->name
);
914 device
->buffer
= buffer
;
916 device
->buffer
= DEFAULT_CAPTURE_BUFFER_SIZE
;
919 #ifdef SHOW_MONITOR_COLUMN
920 if (device
->monitor_mode_supported
) {
921 ui
->captureMonitorModeCheckBox
->setEnabled(true);
924 ti
->updateInterfaceColumns(device
);
926 if (device
->selected
) {
927 selected_interfaces
<< ti
;
932 connect(ui
->interfaceTree
, SIGNAL(itemChanged(QTreeWidgetItem
*,int)), this, SLOT(interfaceItemChanged(QTreeWidgetItem
*,int)));
934 foreach (QTreeWidgetItem
*ti
, selected_interfaces
) {
935 ti
->setSelected(true);
937 connect(ui
->interfaceTree
, SIGNAL(itemSelectionChanged()), this, SLOT(interfaceSelected()));
938 updateSelectedFilter();
940 // Manually or automatically size some columns as needed.
941 int one_em
= fontMetrics().height();
942 for (int col
= 0; col
< ui
->interfaceTree
->topLevelItemCount(); col
++) {
945 ui
->interfaceTree
->setColumnWidth(col
, one_em
* 3.25);
948 ui
->interfaceTree
->setColumnWidth(col
, one_em
* 4.25);
951 ui
->interfaceTree
->setColumnWidth(col
, one_em
* 4.25);
954 ui
->interfaceTree
->setColumnWidth(col
, one_em
* 3.25);
957 ui
->interfaceTree
->resizeColumnToContents(col
);
966 stat_timer_
= new QTimer(this);
967 connect(stat_timer_
, SIGNAL(timeout()), this, SLOT(updateStatistics()));
968 stat_timer_
->start(stat_update_interval_
);
972 void CaptureOptionsDialog::showEvent(QShowEvent
*)
977 void CaptureOptionsDialog::refreshInterfaceList()
980 emit
interfaceListChanged();
983 void CaptureOptionsDialog::updateLocalInterfaces()
988 void CaptureOptionsDialog::updateStatistics(void)
992 disconnect(ui
->interfaceTree
, SIGNAL(itemChanged(QTreeWidgetItem
*,int)), this, SLOT(interfaceItemChanged(QTreeWidgetItem
*,int)));
993 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
995 for (unsigned if_idx
= 0; if_idx
< global_capture_opts
.all_ifaces
->len
; if_idx
++) {
996 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1000 device
= &g_array_index(global_capture_opts
.all_ifaces
, interface_t
, if_idx
);
1001 QString device_name
= ti
->text(col_interface_
);
1002 if (device_name
.compare(device
->display_name
) || device
->hidden
|| device
->if_info
.type
== IF_PIPE
) {
1005 QList
<int> points
= ti
->data(col_traffic_
, Qt::UserRole
).value
<QList
<int> >();
1006 points
.append(device
->packet_diff
);
1007 ti
->setData(col_traffic_
, Qt::UserRole
, QVariant::fromValue(points
));
1010 connect(ui
->interfaceTree
, SIGNAL(itemChanged(QTreeWidgetItem
*,int)), this, SLOT(interfaceItemChanged(QTreeWidgetItem
*,int)));
1011 ui
->interfaceTree
->viewport()->update();
1014 void CaptureOptionsDialog::on_compileBPF_clicked()
1016 QList
<InterfaceFilter
> interfaces
;
1017 foreach (QTreeWidgetItem
*ti
, ui
->interfaceTree
->selectedItems()) {
1018 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1019 interfaces
.emplaceBack(ti
->text(col_interface_
), ti
->text(col_filter_
));
1021 interfaces
.append(InterfaceFilter(ti
->text(col_interface_
), ti
->text(col_filter_
)));
1025 QString filter
= ui
->captureFilterComboBox
->currentText();
1026 CompiledFilterOutput
*cfo
= new CompiledFilterOutput(this, interfaces
);
1031 bool CaptureOptionsDialog::saveOptionsToPreferences()
1033 if (ui
->rbPcapng
->isChecked()) {
1034 global_capture_opts
.use_pcapng
= true;
1035 prefs
.capture_pcap_ng
= true;
1037 global_capture_opts
.use_pcapng
= false;
1038 prefs
.capture_pcap_ng
= false;
1041 g_free(global_capture_opts
.save_file
);
1042 g_free(global_capture_opts
.orig_save_file
);
1044 QString filename
= ui
->filenameLineEdit
->text();
1045 if (filename
.length() > 0) {
1046 /* User specified a file to which the capture should be written. */
1047 global_capture_opts
.saving_to_file
= true;
1048 global_capture_opts
.save_file
= qstring_strdup(filename
);
1049 global_capture_opts
.orig_save_file
= qstring_strdup(filename
);
1050 /* Save the directory name for future file dialogs. */
1051 set_last_open_dir(get_dirname(filename
.toUtf8().data()));
1053 /* User didn't specify a file; save to a temporary file. */
1054 global_capture_opts
.saving_to_file
= false;
1055 global_capture_opts
.save_file
= NULL
;
1056 global_capture_opts
.orig_save_file
= NULL
;
1059 QString tempdir
= ui
->tempDirLineEdit
->text();
1060 if (tempdir
.length() > 0) {
1061 global_capture_opts
.temp_dir
= qstring_strdup(tempdir
);
1064 global_capture_opts
.temp_dir
= NULL
;
1067 global_capture_opts
.has_ring_num_files
= ui
->RbCheckBox
->isChecked();
1069 if (global_capture_opts
.has_ring_num_files
) {
1070 global_capture_opts
.ring_num_files
= ui
->RbSpinBox
->value();
1071 if (global_capture_opts
.ring_num_files
> RINGBUFFER_MAX_NUM_FILES
)
1072 global_capture_opts
.ring_num_files
= RINGBUFFER_MAX_NUM_FILES
;
1073 #if RINGBUFFER_MIN_NUM_FILES > 0
1074 else if (global_capture_opts
.ring_num_files
< RINGBUFFER_MIN_NUM_FILES
)
1075 global_capture_opts
.ring_num_files
= RINGBUFFER_MIN_NUM_FILES
;
1078 global_capture_opts
.multi_files_on
= ui
->gbNewFileAuto
->isChecked();
1079 if (global_capture_opts
.multi_files_on
) {
1080 global_capture_opts
.has_file_duration
= ui
->SecsCheckBox
->isChecked();
1081 if (global_capture_opts
.has_file_duration
) {
1082 global_capture_opts
.file_duration
= ui
->SecsSpinBox
->value();
1083 int index
= ui
->SecsComboBox
->currentIndex();
1085 case 1: global_capture_opts
.file_duration
*= 60;
1087 case 2: global_capture_opts
.file_duration
*= 3600;
1091 global_capture_opts
.has_file_interval
= ui
->IntervalSecsCheckBox
->isChecked();
1092 if (global_capture_opts
.has_file_interval
) {
1093 global_capture_opts
.file_interval
= ui
->IntervalSecsSpinBox
->value();
1094 int index
= ui
->IntervalSecsComboBox
->currentIndex();
1096 case 1: global_capture_opts
.file_interval
*= 60;
1098 case 2: global_capture_opts
.file_interval
*= 3600;
1102 global_capture_opts
.has_file_packets
= ui
->PktCheckBox
->isChecked();
1103 if (global_capture_opts
.has_file_packets
) {
1104 global_capture_opts
.file_packets
= ui
->PktSpinBox
->value();
1106 global_capture_opts
.has_autostop_filesize
= ui
->MBCheckBox
->isChecked();
1107 if (global_capture_opts
.has_autostop_filesize
) {
1108 global_capture_opts
.autostop_filesize
= ui
->MBSpinBox
->value();
1109 int index
= ui
->MBComboBox
->currentIndex();
1111 case 1: if (global_capture_opts
.autostop_filesize
> 2000000) {
1112 QMessageBox::warning(this, tr("Error"),
1113 tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB."));
1116 global_capture_opts
.autostop_filesize
*= 1000;
1119 case 2: if (global_capture_opts
.autostop_filesize
> 2000) {
1120 QMessageBox::warning(this, tr("Error"),
1121 tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB."));
1124 global_capture_opts
.autostop_filesize
*= 1000000;
1129 /* test if the settings are ok for a ringbuffer */
1130 if (global_capture_opts
.save_file
== NULL
) {
1131 QMessageBox::warning(this, tr("Error"),
1132 tr("Multiple files: No capture file name given. You must specify a filename if you want to use multiple files."));
1134 } else if (!global_capture_opts
.has_autostop_filesize
&&
1135 !global_capture_opts
.has_file_interval
&&
1136 !global_capture_opts
.has_file_duration
&&
1137 !global_capture_opts
.has_file_packets
) {
1138 QMessageBox::warning(this, tr("Error"),
1139 tr("Multiple files: No file limit given. You must specify a file size, interval, or number of packets for each file."));
1140 g_free(global_capture_opts
.save_file
);
1141 global_capture_opts
.save_file
= NULL
;
1145 global_capture_opts
.has_autostop_filesize
= ui
->stopMBCheckBox
->isChecked();
1146 if (global_capture_opts
.has_autostop_filesize
) {
1147 global_capture_opts
.autostop_filesize
= ui
->stopMBSpinBox
->value();
1148 int index
= ui
->stopMBComboBox
->currentIndex();
1150 case 1: if (global_capture_opts
.autostop_filesize
> 2000000) {
1151 QMessageBox::warning(this, tr("Error"),
1152 tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB."));
1155 global_capture_opts
.autostop_filesize
*= 1000;
1158 case 2: if (global_capture_opts
.autostop_filesize
> 2000) {
1159 QMessageBox::warning(this, tr("Error"),
1160 tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB."));
1163 global_capture_opts
.autostop_filesize
*= 1000000;
1170 global_capture_opts
.has_autostop_duration
= ui
->stopSecsCheckBox
->isChecked();
1171 if (global_capture_opts
.has_autostop_duration
) {
1172 global_capture_opts
.autostop_duration
= ui
->stopSecsSpinBox
->value();
1173 int index
= ui
->stopSecsComboBox
->currentIndex();
1175 case 1: global_capture_opts
.autostop_duration
*= 60;
1177 case 2: global_capture_opts
.autostop_duration
*= 3600;
1182 global_capture_opts
.has_autostop_packets
= ui
->stopPktCheckBox
->isChecked();
1183 if (global_capture_opts
.has_autostop_packets
) {
1184 global_capture_opts
.autostop_packets
= ui
->stopPktSpinBox
->value();
1187 global_capture_opts
.has_autostop_files
= ui
->stopFilesCheckBox
->isChecked();
1188 if (global_capture_opts
.has_autostop_files
) {
1189 global_capture_opts
.autostop_files
= ui
->stopFilesSpinBox
->value();
1192 interface_t
*device
;
1194 for (int col
= col_link_
; col
<= col_filter_
; col
++) {
1195 if (ui
->interfaceTree
->isColumnHidden(col
)) {
1198 /* All entries are separated by comma. There is also one before the first interface to be able to identify
1199 word boundaries. As 'lo' is part of 'nflog' an exact match is necessary. */
1203 QStringList link_list
;
1205 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1206 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1207 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1208 device
= getDeviceByName(device_name
);
1209 if (!device
|| device
->active_dlt
== -1) {
1212 link_list
<< QStringLiteral("%1(%2)").arg(device
->name
).arg(device
->active_dlt
);
1214 g_free(prefs
.capture_devices_linktypes
);
1215 prefs
.capture_devices_linktypes
= qstring_strdup(link_list
.join(","));
1218 #ifdef SHOW_BUFFER_COLUMN
1221 QStringList buffer_size_list
;
1223 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1224 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1225 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1226 device
= getDeviceByName(device_name
);
1227 if (!device
|| device
->buffer
== -1) {
1230 buffer_size_list
<< QStringLiteral("%1(%2)").arg(device
->name
).arg(device
->buffer
);
1232 g_free(prefs
.capture_devices_buffersize
);
1233 prefs
.capture_devices_buffersize
= qstring_strdup(buffer_size_list
.join(","));
1236 #endif // HAVE_BUFFER_SETTING
1239 QStringList snaplen_list
;
1241 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1242 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1243 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1244 device
= getDeviceByName(device_name
);
1245 if (!device
) continue;
1246 snaplen_list
<< QStringLiteral("%1:%2(%3)")
1248 .arg(device
->has_snaplen
)
1249 .arg(device
->has_snaplen
? device
->snaplen
: WTAP_MAX_PACKET_SIZE_STANDARD
);
1251 g_free(prefs
.capture_devices_snaplen
);
1252 prefs
.capture_devices_snaplen
= qstring_strdup(snaplen_list
.join(","));
1257 QStringList pmode_list
;
1259 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1260 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1261 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1262 device
= getDeviceByName(device_name
);
1263 if (!device
|| !device
->pmode
) {
1266 pmode_list
<< QStringLiteral("%1(%2)").arg(device
->name
).arg(device
->pmode
);
1268 g_free(prefs
.capture_devices_pmode
);
1269 prefs
.capture_devices_pmode
= qstring_strdup(pmode_list
.join(","));
1273 #ifdef SHOW_MONITOR_COLUMN
1276 QStringList monitor_list
;
1278 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1279 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1280 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1281 device
= getDeviceByName(device_name
);
1282 if (!device
|| !device
->monitor_mode_supported
|| (device
->monitor_mode_supported
&& !device
->monitor_mode_enabled
)) {
1285 monitor_list
<< device
->name
;
1287 g_free(prefs
.capture_devices_monitor_mode
);
1288 prefs
.capture_devices_monitor_mode
= qstring_strdup(monitor_list
.join(","));
1291 #endif // HAVE_MONITOR_SETTING
1294 // The device cfilter should have been applied at this point.
1295 // We shouldn't change it here.
1298 // XXX Update selected interfaces only?
1299 for (int row
= 0; row
< ui
->interfaceTree
->topLevelItemCount(); row
++) {
1300 QTreeWidgetItem
*ti
= ui
->interfaceTree
->topLevelItem(row
);
1301 QString device_name
= ti
->data(col_interface_
, Qt::UserRole
).toString();
1302 device
= getDeviceByName(device_name
);
1303 if (!device
) continue;
1304 g_free(device
->cfilter
);
1305 if (ti
->text(col_filter_
).isEmpty()) {
1306 device
->cfilter
= NULL
;
1308 device
->cfilter
= qstring_strdup(ti
->text(col_filter_
));
1316 g_free(global_capture_opts
.compress_type
);
1318 if (ui
->rbCompressionNone
->isChecked() ) {
1319 global_capture_opts
.compress_type
= NULL
;
1320 } else if (ui
->rbCompressionGzip
->isChecked() ) {
1321 global_capture_opts
.compress_type
= qstring_strdup("gzip");
1323 global_capture_opts
.compress_type
= NULL
;
1326 if (ui
->rbTimeNum
->isChecked() ) {
1327 global_capture_opts
.has_nametimenum
= true;
1328 } else if (ui
->rbNumTime
->isChecked() ) {
1329 global_capture_opts
.has_nametimenum
= false;
1331 global_capture_opts
.has_nametimenum
= false;
1338 void CaptureOptionsDialog::updateSelectedFilter()
1340 // Should match MainWelcome::interfaceSelected.
1341 QPair
<const QString
, bool> sf_pair
= CaptureFilterEdit::getSelectedFilter();
1342 const QString user_filter
= sf_pair
.first
;
1343 bool conflict
= sf_pair
.second
;
1346 ui
->captureFilterComboBox
->lineEdit()->clear();
1347 ui
->captureFilterComboBox
->setConflict(true);
1349 ui
->captureFilterComboBox
->lineEdit()->setText(user_filter
);
1353 void CaptureOptionsDialog::on_manageButton_clicked()
1355 if (saveOptionsToPreferences()) {
1356 ManageInterfacesDialog
*dlg
= new ManageInterfacesDialog(this);
1361 void CaptureOptionsDialog::changeEvent(QEvent
* event
)
1365 switch (event
->type())
1367 case QEvent::LanguageChange
:
1368 ui
->retranslateUi(this);
1374 QDialog::changeEvent(event
);
1377 interface_t
*CaptureOptionsDialog::getDeviceByName(const QString device_name
)
1379 for (unsigned i
= 0; i
< global_capture_opts
.all_ifaces
->len
; i
++) {
1380 interface_t
*device
= &g_array_index(global_capture_opts
.all_ifaces
, interface_t
, i
);
1381 if (device_name
.compare(QString().fromUtf8(device
->name
)) == 0) {
1389 // InterfaceTreeItem
1391 bool InterfaceTreeWidgetItem::operator< (const QTreeWidgetItem
&other
) const {
1392 if (treeWidget()->sortColumn() == col_traffic_
) {
1393 QList
<int> points
= data(col_traffic_
, Qt::UserRole
).value
<QList
<int> >();
1394 QList
<int> other_points
= other
.data(col_traffic_
, Qt::UserRole
).value
<QList
<int> >();
1395 double avg
= 0, other_avg
= 0;
1396 foreach (int point
, points
) {
1397 avg
+= (double) point
/ points
.length();
1399 foreach (int point
, other_points
) {
1400 other_avg
+= (double) point
/ other_points
.length();
1402 return avg
< other_avg
;
1404 return QTreeWidgetItem::operator<(other
);
1407 QVariant
InterfaceTreeWidgetItem::data(int column
, int role
) const
1409 // See setData for the special col_traffic_ treatment.
1410 if (column
== col_traffic_
&& role
== Qt::UserRole
) {
1411 return QVariant::fromValue(points
);
1414 if (column
== col_snaplen_
&& role
== Qt::DisplayRole
) {
1415 QVariant data
= QTreeWidgetItem::data(column
, role
);
1416 if (data
.toInt() == WTAP_MAX_PACKET_SIZE_STANDARD
|| data
.toInt() == 0) {
1417 return InterfaceTreeDelegate::tr("default");
1421 return QTreeWidgetItem::data(column
, role
);
1424 void InterfaceTreeWidgetItem::setData(int column
, int role
, const QVariant
&value
)
1426 // Workaround for closing editors on updates to the points list: normally
1427 // QTreeWidgetItem::setData emits dataChanged when the value (list) changes.
1428 // We could store a pointer to the list, or just have this hack that does
1429 // not emit dataChanged.
1430 if (column
== col_traffic_
&& role
== Qt::UserRole
) {
1431 points
= value
.value
<QList
<int> >();
1435 QTreeWidgetItem::setData(column
, role
, value
);
1439 // InterfaceTreeDelegate
1442 #include <QComboBox>
1444 InterfaceTreeDelegate::InterfaceTreeDelegate(QObject
*parent
)
1445 : QStyledItemDelegate(parent
), tree_(NULL
)
1450 InterfaceTreeDelegate::~InterfaceTreeDelegate()
1455 QWidget
* InterfaceTreeDelegate::createEditor(QWidget
*parent
, const QStyleOptionViewItem
&, const QModelIndex
&idx
) const
1458 #ifdef SHOW_BUFFER_COLUMN
1459 int buffer
= DEFAULT_CAPTURE_BUFFER_SIZE
;
1461 unsigned snap
= WTAP_MAX_PACKET_SIZE_STANDARD
;
1462 GList
*links
= NULL
;
1464 if (idx
.column() > 1 && idx
.data().toString().compare(UTF8_EM_DASH
)) {
1465 QTreeWidgetItem
*ti
= tree_
->topLevelItem(idx
.row());
1466 QString interface_name
= ti
->text(col_interface_
);
1467 interface_t
*device
= find_device_by_if_name(interface_name
);
1470 #ifdef SHOW_BUFFER_COLUMN
1471 buffer
= device
->buffer
;
1473 snap
= device
->snaplen
;
1474 links
= device
->links
;
1476 switch (idx
.column()) {
1478 case col_interface_
:
1485 QStringList valid_link_types
;
1487 // XXX The GTK+ UI fills in all link types, valid or not. We add
1488 // only the valid ones. If we *do* wish to include invalid link
1489 // types we'll have to jump through the hoops necessary to disable
1492 for (list
= links
; list
!= Q_NULLPTR
; list
= gxx_list_next(list
)) {
1493 linkr
= gxx_list_data(link_row
*, list
);
1494 if (linkr
->dlt
>= 0) {
1495 valid_link_types
<< linkr
->name
;
1499 if (valid_link_types
.size() < 2) {
1502 QComboBox
*cb
= new QComboBox(parent
);
1503 cb
->addItems(valid_link_types
);
1505 connect(cb
, &QComboBox::currentTextChanged
, this, &InterfaceTreeDelegate::linkTypeChanged
);
1511 QSpinBox
*sb
= new QSpinBox(parent
);
1512 sb
->setRange(0, WTAP_MAX_PACKET_SIZE_STANDARD
);
1514 sb
->setWrapping(true);
1515 sb
->setSpecialValueText(tr("default"));
1516 connect(sb
, SIGNAL(valueChanged(int)), this, SLOT(snapshotLengthChanged(int)));
1520 #ifdef SHOW_BUFFER_COLUMN
1523 QSpinBox
*sb
= new QSpinBox(parent
);
1524 sb
->setRange(1, WTAP_MAX_PACKET_SIZE_STANDARD
);
1525 sb
->setValue(buffer
);
1526 sb
->setWrapping(true);
1527 connect(sb
, SIGNAL(valueChanged(int)), this, SLOT(bufferSizeChanged(int)));
1534 // XXX: Should this take the interface name, so that the history
1535 // list is taken from the interface-specific recent cfilter list?
1536 CaptureFilterCombo
*cf
= new CaptureFilterCombo(parent
, true);
1537 connect(cf
->lineEdit(), SIGNAL(textEdited(QString
)), this, SIGNAL(filterChanged(QString
)));
1545 w
->setAutoFillBackground(true);
1549 bool InterfaceTreeDelegate::eventFilter(QObject
*object
, QEvent
*event
)
1551 QComboBox
* comboBox
= dynamic_cast<QComboBox
*>(object
);
1553 if (event
->type() == QEvent::MouseButtonRelease
) {
1554 comboBox
->showPopup();
1558 return QStyledItemDelegate::eventFilter(object
, event
);
1563 void InterfaceTreeDelegate::linkTypeChanged(const QString selected_link_type
)
1567 interface_t
*device
;
1569 QTreeWidgetItem
*ti
= tree_
->currentItem();
1573 QString interface_name
= ti
->text(col_interface_
);
1574 device
= find_device_by_if_name(interface_name
);
1578 for (list
= device
->links
; list
!= Q_NULLPTR
; list
= gxx_list_next(list
)) {
1579 temp
= gxx_list_data(link_row
*, list
);
1580 if (!selected_link_type
.compare(temp
->name
)) {
1581 device
->active_dlt
= temp
->dlt
;
1584 // XXX We might want to verify that active_dlt is valid at this point.
1587 void InterfaceTreeDelegate::snapshotLengthChanged(int value
)
1589 interface_t
*device
;
1590 QTreeWidgetItem
*ti
= tree_
->currentItem();
1594 QString interface_name
= ti
->text(col_interface_
);
1595 device
= find_device_by_if_name(interface_name
);
1599 if (value
!= WTAP_MAX_PACKET_SIZE_STANDARD
&& value
!= 0) {
1600 device
->has_snaplen
= true;
1601 device
->snaplen
= value
;
1603 device
->has_snaplen
= false;
1604 device
->snaplen
= WTAP_MAX_PACKET_SIZE_STANDARD
;
1608 #ifdef SHOW_BUFFER_COLUMN
1609 void InterfaceTreeDelegate::bufferSizeChanged(int value
)
1611 interface_t
*device
;
1612 QTreeWidgetItem
*ti
= tree_
->currentItem();
1616 QString interface_name
= ti
->text(col_interface_
);
1617 device
= find_device_by_if_name(interface_name
);
1621 device
->buffer
= value
;
1625 #endif /* HAVE_LIBPCAP */