b4fb9e17131334de05b7230c921a9f83de6976fc
[metze/wireshark/wip.git] / ui / qt / capture_interfaces_dialog.cpp
1 /* capture_interfaces_dialog.cpp
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "config.h"
23
24 #include <glib.h>
25
26 #include "capture_interfaces_dialog.h"
27 #include "capture_filter_combo.h"
28 #include <ui_capture_interfaces_dialog.h>
29 #include "compiled_filter_output.h"
30 #include "manage_interfaces_dialog.h"
31
32 #include "wireshark_application.h"
33
34 #ifdef HAVE_LIBPCAP
35
36 #include <QAbstractItemModel>
37 #include <QFileDialog>
38 #include <QMessageBox>
39 #include <QTimer>
40
41 #include "ringbuffer.h"
42 #include "ui/capture_ui_utils.h"
43 #include "ui/capture_globals.h"
44 #include "ui/iface_lists.h"
45 #include "ui/last_open_dir.h"
46
47 #include "ui/ui_util.h"
48 #include "ui/util.h"
49 #include <wsutil/utf8_entities.h>
50 #include "ui/preference_utils.h"
51
52 #include <cstdio>
53 #include <epan/prefs.h>
54 #include <epan/prefs-int.h>
55 #include <epan/addr_resolv.h>
56 #include <wsutil/filesystem.h>
57
58 #include "qt_ui_utils.h"
59 #include "sparkline_delegate.h"
60
61 // To do:
62 // - Set a size hint for item delegates.
63 // - Make promiscuous and monitor mode checkboxes.
64 // - Fix InterfaceTreeDelegate method names.
65 // - You can edit filters via the main CaptureFilterCombo and via each
66 //   individual interface row. We should probably do one or the other.
67
68 const int stat_update_interval_ = 1000; // ms
69
70 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
71 #define SHOW_BUFFER_COLUMN 1
72 #endif
73
74 #if defined(HAVE_PCAP_CREATE)
75 #define SHOW_MONITOR_COLUMN 1
76 #endif
77
78 /*
79  * Symbolic names for column indices.
80  */
81 enum
82 {
83     col_interface_ = 0,
84     col_traffic_,
85     col_link_,
86     col_pmode_,
87     col_snaplen_,
88     col_buffer_,
89     col_monitor_,
90     col_filter_,
91     col_num_columns_
92 };
93
94 static interface_t *find_device_by_if_name(const QString &interface_name)
95 {
96     interface_t *device;
97     guint i;
98     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
99         device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
100         if (!interface_name.compare(device->display_name) && !device->hidden && device->type != IF_PIPE) {
101             return device;
102         }
103     }
104     return NULL;
105 }
106
107 class InterfaceTreeWidgetItem : public QTreeWidgetItem
108 {
109 public:
110     InterfaceTreeWidgetItem(QTreeWidget *tree) : QTreeWidgetItem(tree) {}
111     bool operator< (const QTreeWidgetItem &other) const;
112     QList<int> points;
113
114     void updateInterfaceColumns(interface_t *device)
115     {
116         if (!device) return;
117
118         QString default_str = QObject::tr("default");
119
120         QString linkname = QObject::tr("DLT %1").arg(device->active_dlt);
121         for (GList *list = device->links; list != NULL; list = g_list_next(list)) {
122             link_row *linkr = (link_row*)(list->data);
123             // XXX ...and if they're both -1?
124             if (linkr->dlt == device->active_dlt) {
125                 linkname = linkr->name;
126                 break;
127             }
128         }
129         setText(col_link_, linkname);
130
131 #ifdef HAVE_EXTCAP
132         if (device->if_info.type == IF_EXTCAP) {
133             /* extcap interfaces does not have this settings */
134             setApplicable(col_pmode_, false);
135
136             setApplicable(col_snaplen_, false);
137 #ifdef SHOW_BUFFER_COLUMN
138             setApplicable(col_buffer_, false);
139 #endif
140         } else {
141 #endif
142             setApplicable(col_pmode_, true);
143             setCheckState(col_pmode_, device->pmode ? Qt::Checked : Qt::Unchecked);
144
145             QString snaplen_string = device->has_snaplen ? QString::number(device->snaplen) : default_str;
146             setText(col_snaplen_, snaplen_string);
147 #ifdef SHOW_BUFFER_COLUMN
148             setText(col_buffer_, QString::number(device->buffer));
149 #endif
150 #ifdef HAVE_EXTCAP
151         }
152 #endif
153         setText(col_filter_, device->cfilter);
154
155 #ifdef SHOW_MONITOR_COLUMN
156         if (device->monitor_mode_supported) {
157             setApplicable(col_monitor_, true);
158             setCheckState(col_monitor_, device->monitor_mode_enabled ? Qt::Checked : Qt::Unchecked);
159         } else {
160             setApplicable(col_monitor_, false);
161         }
162 #endif
163     }
164
165     void setApplicable(int column, bool applicable = false) {
166         QPalette palette = wsApp->palette();
167
168         if (applicable) {
169             setText(column, QString());
170         } else {
171             setData(column, Qt::CheckStateRole, QVariant());
172             palette.setCurrentColorGroup(QPalette::Disabled);
173             setText(column, UTF8_EM_DASH);
174         }
175         setTextColor(column, palette.text().color());
176     }
177
178 };
179
180 CaptureInterfacesDialog::CaptureInterfacesDialog(QWidget *parent) :
181     GeometryStateDialog(parent),
182     ui(new Ui::CaptureInterfacesDialog)
183 {
184     ui->setupUi(this);
185     loadGeometry();
186     setWindowTitle(wsApp->windowTitleString(tr("Capture Interfaces")));
187
188     stat_timer_ = NULL;
189     stat_cache_ = NULL;
190
191     // XXX - Enable / disable as needed
192     ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Start"));
193
194     ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled((global_capture_opts.num_selected > 0)? true: false);
195
196     // Start out with the list *not* sorted, so they show up in the order
197     // in which they were provided
198     ui->interfaceTree->sortByColumn(-1, Qt::AscendingOrder);
199     ui->interfaceTree->setItemDelegateForColumn(col_interface_, &interface_item_delegate_);
200     ui->interfaceTree->setItemDelegateForColumn(col_traffic_, new SparkLineDelegate());
201     ui->interfaceTree->setItemDelegateForColumn(col_link_, &interface_item_delegate_);
202
203     ui->interfaceTree->setItemDelegateForColumn(col_snaplen_, &interface_item_delegate_);
204 #ifdef SHOW_BUFFER_COLUMN
205     ui->interfaceTree->setItemDelegateForColumn(col_buffer_, &interface_item_delegate_);
206 #else
207     ui->interfaceTree->setColumnHidden(col_buffer_, true);
208 #endif
209 #ifndef SHOW_MONITOR_COLUMN
210     ui->interfaceTree->setColumnHidden(col_monitor_, true);
211 #endif
212     ui->interfaceTree->setItemDelegateForColumn(col_filter_, &interface_item_delegate_);
213
214     interface_item_delegate_.setTree(ui->interfaceTree);
215
216     ui->filenameLineEdit->setPlaceholderText(tr("Leave blank to use a temporary file"));
217
218     // Changes in interface selections or capture filters should be propagated
219     // to the main welcome screen where they will be applied to the global
220     // capture options.
221     connect(this, SIGNAL(interfacesChanged()), ui->captureFilterComboBox, SIGNAL(interfacesChanged()));
222     connect(ui->captureFilterComboBox, SIGNAL(captureFilterSyntaxChanged(bool)), this, SLOT(updateWidgets()));
223     connect(ui->captureFilterComboBox->lineEdit(), SIGNAL(textEdited(QString)),
224             this, SLOT(filterEdited()));
225     connect(ui->captureFilterComboBox->lineEdit(), SIGNAL(textEdited(QString)),
226             this, SIGNAL(captureFilterTextEdited(QString)));
227     connect(&interface_item_delegate_, SIGNAL(filterChanged(QString)),
228             ui->captureFilterComboBox->lineEdit(), SLOT(setText(QString)));
229     connect(&interface_item_delegate_, SIGNAL(filterChanged(QString)),
230             this, SIGNAL(captureFilterTextEdited(QString)));
231     connect(this, SIGNAL(ifsChanged()), this, SLOT(refreshInterfaceList()));
232     connect(wsApp, SIGNAL(localInterfaceListChanged()), this, SLOT(updateLocalInterfaces()));
233     connect(ui->browseButton, SIGNAL(clicked()), this, SLOT(browseButtonClicked()));
234 }
235
236 /* Update global device selections based on the TreeWidget selection. */
237 void CaptureInterfacesDialog::updateGlobalDeviceSelections()
238 {
239 #ifdef HAVE_LIBPCAP
240     QTreeWidgetItemIterator iter(ui->interfaceTree);
241
242     global_capture_opts.num_selected = 0;
243
244     while (*iter) {
245         QString device_name = (*iter)->data(col_interface_, Qt::UserRole).value<QString>();
246         for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
247             interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
248             if (device_name.compare(QString().fromUtf8(device.name)) == 0) {
249                 if (!device.locked) {
250                     if ((*iter)->isSelected()) {
251                         device.selected = TRUE;
252                         global_capture_opts.num_selected++;
253                     } else {
254                         device.selected = FALSE;
255                     }
256                     device.locked = TRUE;
257                     global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
258                     g_array_insert_val(global_capture_opts.all_ifaces, i, device);
259
260                     device.locked = FALSE;
261                     global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
262                     g_array_insert_val(global_capture_opts.all_ifaces, i, device);
263                 }
264                 break;
265             }
266         }
267         ++iter;
268     }
269 #endif
270 }
271
272 void CaptureInterfacesDialog::interfaceSelected()
273 {
274     updateGlobalDeviceSelections();
275
276     ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled((global_capture_opts.num_selected > 0) ? true: false);
277
278     emit interfacesChanged();
279
280     updateSelectedFilter();
281
282     updateWidgets();
283 }
284
285 void CaptureInterfacesDialog::filterEdited()
286 {
287     QList<QTreeWidgetItem*> si = ui->interfaceTree->selectedItems();
288
289     foreach (QTreeWidgetItem *ti, si) {
290         ti->setText(col_filter_, ui->captureFilterComboBox->lineEdit()->text());
291     }
292
293     if (si.count() > 0) {
294         QModelIndex col_filter_idx = ui->interfaceTree->model()->index(ui->interfaceTree->indexOfTopLevelItem(si[0]), col_filter_);
295         ui->interfaceTree->scrollTo(col_filter_idx);
296     }
297 }
298
299 void CaptureInterfacesDialog::updateWidgets()
300 {
301     SyntaxLineEdit *sle = qobject_cast<SyntaxLineEdit *>(ui->captureFilterComboBox->lineEdit());
302     if (!sle) {
303         return;
304     }
305
306     bool can_capture = false;
307
308     if (ui->interfaceTree->selectedItems().count() > 0 && sle->syntaxState() != SyntaxLineEdit::Invalid) {
309         can_capture = true;
310     }
311
312     ui->compileBPF->setEnabled(can_capture);
313     ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(can_capture);
314 }
315
316 CaptureInterfacesDialog::~CaptureInterfacesDialog()
317 {
318     delete ui;
319 }
320
321 void CaptureInterfacesDialog::setTab(int idx)
322 {
323     ui->tabWidget->setCurrentIndex(idx);
324 }
325
326 void CaptureInterfacesDialog::on_capturePromModeCheckBox_toggled(bool checked)
327 {
328     interface_t *device;
329     prefs.capture_prom_mode = checked;
330     for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) {
331         InterfaceTreeWidgetItem *ti = dynamic_cast<InterfaceTreeWidgetItem *>(ui->interfaceTree->topLevelItem(row));
332         if (!ti) continue;
333
334         QString device_name = ti->data(col_interface_, Qt::UserRole).toString();
335         device = getDeviceByName(device_name);
336         if (!device) continue;
337         device->pmode = checked;
338         ti->updateInterfaceColumns(device);
339     }
340 }
341
342 void CaptureInterfacesDialog::browseButtonClicked()
343 {
344     char *open_dir = NULL;
345
346     switch (prefs.gui_fileopen_style) {
347
348     case FO_STYLE_LAST_OPENED:
349         open_dir = get_last_open_dir();
350         break;
351
352     case FO_STYLE_SPECIFIED:
353         if (prefs.gui_fileopen_dir[0] != '\0')
354             open_dir = prefs.gui_fileopen_dir;
355         break;
356     }
357     QString file_name = QFileDialog::getSaveFileName(this, tr("Specify a Capture File"), open_dir);
358     ui->filenameLineEdit->setText(file_name);
359 }
360
361 void CaptureInterfacesDialog::interfaceItemChanged(QTreeWidgetItem *item, int column)
362 {
363     QWidget* editor = ui->interfaceTree->indexWidget(ui->interfaceTree->currentIndex());
364     if (editor) {
365         ui->interfaceTree->closePersistentEditor(item, ui->interfaceTree->currentColumn());
366     }
367
368     InterfaceTreeWidgetItem *ti = dynamic_cast<InterfaceTreeWidgetItem *>(item);
369     if (!ti) return;
370
371     interface_t *device;
372     QString interface_name = ti->text(col_interface_);
373     device = find_device_by_if_name(interface_name);
374     if (!device) return;
375
376     switch(column) {
377
378     case col_pmode_:
379         device->pmode = item->checkState(col_pmode_) == Qt::Checked ? TRUE : FALSE;
380         ti->updateInterfaceColumns(device);
381         break;
382
383 #ifdef SHOW_MONITOR_COLUMN
384     case col_monitor_:
385     {
386         gboolean monitor_mode = FALSE;
387         if (ti->checkState(col_monitor_) == Qt::Checked) monitor_mode = TRUE;
388
389         if_capabilities_t *caps;
390         char *auth_str = NULL;
391         QString active_dlt_name;
392
393         set_active_dlt(device, global_capture_opts.default_options.linktype);
394
395     #ifdef HAVE_PCAP_REMOTE
396         if (device->remote_opts.remote_host_opts.auth_type == CAPTURE_AUTH_PWD) {
397             auth_str = g_strdup_printf("%s:%s", device->remote_opts.remote_host_opts.auth_username,
398                                        device->remote_opts.remote_host_opts.auth_password);
399         }
400     #endif
401         caps = capture_get_if_capabilities(device->name, monitor_mode, auth_str, NULL, main_window_update);
402         g_free(auth_str);
403
404         if (caps != NULL) {
405
406             for (int i = (gint)g_list_length(device->links)-1; i >= 0; i--) {
407                 GList* rem = g_list_nth(device->links, i);
408                 device->links = g_list_remove_link(device->links, rem);
409                 g_list_free_1(rem);
410             }
411             device->active_dlt = -1;
412             device->monitor_mode_supported = caps->can_set_rfmon;
413             device->monitor_mode_enabled = monitor_mode;
414
415             for (GList *lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
416                 link_row *linkr = (link_row *)g_malloc(sizeof(link_row));
417                 data_link_info_t *data_link_info = (data_link_info_t *)lt_entry->data;
418                 /*
419                  * For link-layer types libpcap/WinPcap doesn't know about, the
420                  * name will be "DLT n", and the description will be null.
421                  * We mark those as unsupported, and don't allow them to be
422                  * used - capture filters won't work on them, for example.
423                  */
424                 if (data_link_info->description != NULL) {
425                     linkr->dlt = data_link_info->dlt;
426                     if (active_dlt_name.isEmpty()) {
427                         device->active_dlt = data_link_info->dlt;
428                         active_dlt_name = data_link_info->description;
429                     }
430                     linkr->name = g_strdup(data_link_info->description);
431                 } else {
432                     gchar *str;
433                     /* XXX - should we just omit them? */
434                     str = g_strdup_printf("%s (not supported)", data_link_info->name);
435                     linkr->dlt = -1;
436                     linkr->name = g_strdup(str);
437                     g_free(str);
438                 }
439                 device->links = g_list_append(device->links, linkr);
440             }
441             free_if_capabilities(caps);
442         } else {
443             /* We don't know whether this supports monitor mode or not;
444                don't ask for monitor mode. */
445             device->monitor_mode_enabled = FALSE;
446             device->monitor_mode_supported = FALSE;
447         }
448
449         ti->updateInterfaceColumns(device);
450
451         break;
452     }
453 #endif // SHOW_MONITOR_COLUMN
454     default:
455         break;
456     }
457 }
458
459 void CaptureInterfacesDialog::on_gbStopCaptureAuto_toggled(bool checked)
460 {
461     global_capture_opts.has_file_duration = checked;
462 }
463
464 void CaptureInterfacesDialog::on_gbNewFileAuto_toggled(bool checked)
465 {
466     global_capture_opts.multi_files_on = checked;
467     ui->stopMBCheckBox->setEnabled(checked?false:true);
468     ui->stopMBSpinBox->setEnabled(checked?false:true);
469     ui->stopMBComboBox->setEnabled(checked?false:true);
470 }
471
472 void CaptureInterfacesDialog::on_cbUpdatePacketsRT_toggled(bool checked)
473 {
474     global_capture_opts.real_time_mode = checked;
475 }
476
477 void CaptureInterfacesDialog::on_cbAutoScroll_toggled(bool checked)
478 {
479     auto_scroll_live = checked;
480 }
481
482 void CaptureInterfacesDialog::on_cbExtraCaptureInfo_toggled(bool checked)
483 {
484     global_capture_opts.show_info = checked;
485 }
486
487 void CaptureInterfacesDialog::on_cbResolveMacAddresses_toggled(bool checked)
488 {
489     gbl_resolv_flags.mac_name = checked;
490 }
491
492 void CaptureInterfacesDialog::on_cbResolveNetworkNames_toggled(bool checked)
493 {
494     gbl_resolv_flags.network_name = checked;
495 }
496
497 void CaptureInterfacesDialog::on_cbResolveTransportNames_toggled(bool checked)
498 {
499     gbl_resolv_flags.transport_name = checked;
500 }
501
502 void CaptureInterfacesDialog::on_buttonBox_accepted()
503 {
504     if (saveOptionsToPreferences()) {
505         emit setFilterValid(true, ui->captureFilterComboBox->lineEdit()->text());
506         accept();
507     }
508 }
509
510 // Not sure why we have to do this manually.
511 void CaptureInterfacesDialog::on_buttonBox_rejected()
512 {
513     if (saveOptionsToPreferences()) {
514         reject();
515     }
516 }
517
518 void CaptureInterfacesDialog::on_buttonBox_helpRequested()
519 {
520     // Probably the wrong URL.
521     wsApp->helpTopicAction(HELP_CAPTURE_INTERFACES_DIALOG);
522 }
523
524 void CaptureInterfacesDialog::updateInterfaces()
525 {
526     if(prefs.capture_pcap_ng) {
527         ui->rbPcapng->setChecked(true);
528     } else {
529         ui->rbPcap->setChecked(true);
530     }
531     ui->capturePromModeCheckBox->setChecked(prefs.capture_prom_mode);
532
533     if (global_capture_opts.saving_to_file) {
534         ui->filenameLineEdit->setText(QString(global_capture_opts.orig_save_file));
535     }
536
537     ui->gbNewFileAuto->setChecked(global_capture_opts.multi_files_on);
538     ui->MBCheckBox->setChecked(global_capture_opts.has_autostop_filesize);
539     ui->SecsCheckBox->setChecked(global_capture_opts.has_file_duration);
540     if (global_capture_opts.has_autostop_filesize) {
541         int value = global_capture_opts.autostop_filesize;
542         if (value > 1000000) {
543             if (global_capture_opts.multi_files_on) {
544                 ui->MBSpinBox->setValue(value / 1000000);
545                 ui->MBComboBox->setCurrentIndex(2);
546             } else {
547                 ui->stopMBCheckBox->setChecked(true);
548                 ui->stopMBSpinBox->setValue(value / 1000000);
549                 ui->stopMBComboBox->setCurrentIndex(2);
550             }
551         } else if (value > 1000 && value % 1000 == 0) {
552             if (global_capture_opts.multi_files_on) {
553                 ui->MBSpinBox->setValue(value / 1000);
554                 ui->MBComboBox->setCurrentIndex(1);
555             } else {
556                 ui->stopMBCheckBox->setChecked(true);
557                 ui->stopMBSpinBox->setValue(value / 1000);
558                 ui->stopMBComboBox->setCurrentIndex(1);
559             }
560         } else {
561             if (global_capture_opts.multi_files_on) {
562                 ui->MBSpinBox->setValue(value);
563                 ui->MBComboBox->setCurrentIndex(0);
564             } else {
565                 ui->stopMBCheckBox->setChecked(true);
566                 ui->stopMBSpinBox->setValue(value);
567                 ui->stopMBComboBox->setCurrentIndex(0);
568             }
569         }
570     }
571     if (global_capture_opts.has_file_duration) {
572         int value = global_capture_opts.file_duration;
573         if (value > 3600 && value % 3600 == 0) {
574             ui->SecsSpinBox->setValue(value / 3600);
575             ui->SecsComboBox->setCurrentIndex(2);
576         } else if (value > 60 && value % 60 == 0) {
577             ui->SecsSpinBox->setValue(value / 60);
578             ui->SecsComboBox->setCurrentIndex(1);
579         } else {
580             ui->SecsSpinBox->setValue(value);
581             ui->SecsComboBox->setCurrentIndex(0);
582         }
583     }
584
585     if (global_capture_opts.has_ring_num_files) {
586         ui->RbSpinBox->setValue(global_capture_opts.ring_num_files);
587         ui->RbCheckBox->setCheckState(Qt::Checked);
588     }
589
590     if (global_capture_opts.has_autostop_duration) {
591         ui->stopSecsCheckBox->setChecked(true);
592         int value = global_capture_opts.file_duration;
593         if (value > 3600 && value % 3600 == 0) {
594             ui->stopSecsSpinBox->setValue(value / 3600);
595             ui->stopSecsComboBox->setCurrentIndex(2);
596         } else if (value > 60 && value % 60 == 0) {
597             ui->stopSecsSpinBox->setValue(value / 60);
598             ui->stopSecsComboBox->setCurrentIndex(1);
599         } else {
600             ui->stopSecsSpinBox->setValue(value);
601             ui->stopSecsComboBox->setCurrentIndex(0);
602         }
603     }
604
605     if (global_capture_opts.has_autostop_packets) {
606         ui->stopPktCheckBox->setChecked(true);
607         ui->stopPktSpinBox->setValue(global_capture_opts.autostop_packets);
608     }
609
610     if (global_capture_opts.has_autostop_files) {
611         ui->stopFilesCheckBox->setChecked(true);
612         ui->stopFilesSpinBox->setValue(global_capture_opts.autostop_files);
613     }
614
615     ui->cbUpdatePacketsRT->setChecked(global_capture_opts.real_time_mode);
616     ui->cbAutoScroll->setChecked(true);
617     ui->cbExtraCaptureInfo->setChecked(global_capture_opts.show_info);
618
619     ui->cbResolveMacAddresses->setChecked(gbl_resolv_flags.mac_name);
620     ui->cbResolveNetworkNames->setChecked(gbl_resolv_flags.network_name);
621     ui->cbResolveTransportNames->setChecked(gbl_resolv_flags.transport_name);
622
623     // Rebuild the interface list without disturbing the main welcome screen.
624     disconnect(ui->interfaceTree, SIGNAL(itemSelectionChanged()), this, SLOT(interfaceSelected()));
625     ui->interfaceTree->clear();
626
627 #ifdef SHOW_BUFFER_COLUMN
628     gint          buffer;
629 #endif
630     gint          snaplen;
631     gboolean      hassnap, pmode;
632     QList<QTreeWidgetItem *> selected_interfaces;
633
634     disconnect(ui->interfaceTree, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(interfaceItemChanged(QTreeWidgetItem*,int)));
635
636     if (global_capture_opts.all_ifaces->len > 0) {
637         interface_t *device;
638
639         for (guint device_idx = 0; device_idx < global_capture_opts.all_ifaces->len; device_idx++) {
640             device = &g_array_index(global_capture_opts.all_ifaces, interface_t, device_idx);
641
642             /* Continue if capture device is hidden */
643             if (device->hidden) {
644                 continue;
645             }
646
647             // Traffic sparklines
648             InterfaceTreeWidgetItem *ti = new InterfaceTreeWidgetItem(ui->interfaceTree);
649             ti->setFlags(ti->flags() | Qt::ItemIsEditable);
650             ti->setData(col_interface_, Qt::UserRole, QString(device->name));
651             ti->setData(col_traffic_, Qt::UserRole, qVariantFromValue(ti->points));
652
653             ti->setText(col_interface_, device->display_name);
654             if (device->no_addresses > 0) {
655                 QString addr_str = tr("%1: %2").arg(device->no_addresses > 1 ? tr("Addresses") : tr("Address")).arg(device->addresses);
656                 QTreeWidgetItem *addr_ti = new QTreeWidgetItem(ti);
657
658                 addr_str.replace('\n', ", ");
659                 addr_ti->setText(0, addr_str);
660                 addr_ti->setFlags(addr_ti->flags() ^ Qt::ItemIsSelectable);
661                 addr_ti->setFirstColumnSpanned(true);
662                 addr_ti->setToolTip(col_interface_, QString("<span>%1</span>").arg(addr_str));
663                 ti->setToolTip(col_interface_, QString("<span>%1</span>").arg(addr_str));
664             } else {
665                 ti->setToolTip(col_interface_, tr("no addresses"));
666             }
667
668             if (capture_dev_user_pmode_find(device->name, &pmode)) {
669                 device->pmode = pmode;
670             }
671             if (capture_dev_user_snaplen_find(device->name, &hassnap, &snaplen)) {
672                 /* Default snap length set in preferences */
673                 device->snaplen = snaplen;
674                 device->has_snaplen = hassnap;
675             } else {
676                 /* No preferences set yet, use default values */
677                 device->snaplen = WTAP_MAX_PACKET_SIZE;
678                 device->has_snaplen = FALSE;
679             }
680
681 #ifdef SHOW_BUFFER_COLUMN
682             if (capture_dev_user_buffersize_find(device->name) != -1) {
683                 buffer = capture_dev_user_buffersize_find(device->name);
684                 device->buffer = buffer;
685             } else {
686                 device->buffer = DEFAULT_CAPTURE_BUFFER_SIZE;
687             }
688 #endif
689             ti->updateInterfaceColumns(device);
690
691             if (device->selected) {
692                 selected_interfaces << ti;
693             }
694         }
695     }
696
697     connect(ui->interfaceTree, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(interfaceItemChanged(QTreeWidgetItem*,int)));
698
699     foreach (QTreeWidgetItem *ti, selected_interfaces) {
700         ti->setSelected(true);
701     }
702     connect(ui->interfaceTree, SIGNAL(itemSelectionChanged()), this, SLOT(interfaceSelected()));
703     updateSelectedFilter();
704
705     // Manually or automatically size some columns as needed.
706     int one_em = fontMetrics().height();
707     for (int col = 0; col < ui->interfaceTree->topLevelItemCount(); col++) {
708         switch (col) {
709         case col_pmode_:
710             ui->interfaceTree->setColumnWidth(col, one_em * 3.25);
711             break;
712         case col_snaplen_:
713             ui->interfaceTree->setColumnWidth(col, one_em * 4.25);
714             break;
715         case col_buffer_:
716             ui->interfaceTree->setColumnWidth(col, one_em * 4.25);
717             break;
718         case col_monitor_:
719             ui->interfaceTree->setColumnWidth(col, one_em * 3.25);
720             break;
721         default:
722             ui->interfaceTree->resizeColumnToContents(col);
723         }
724
725     }
726
727     ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled((global_capture_opts.num_selected > 0)? true: false);
728
729     if (!stat_timer_) {
730         updateStatistics();
731         stat_timer_ = new QTimer(this);
732         connect(stat_timer_, SIGNAL(timeout()), this, SLOT(updateStatistics()));
733         stat_timer_->start(stat_update_interval_);
734     }
735 }
736
737 void CaptureInterfacesDialog::showEvent(QShowEvent *)
738 {
739     updateInterfaces();
740 }
741
742 void CaptureInterfacesDialog::refreshInterfaceList()
743 {
744     updateInterfaces();
745     emit interfaceListChanged();
746 }
747
748 void CaptureInterfacesDialog::updateLocalInterfaces()
749 {
750     updateInterfaces();
751 }
752
753 void CaptureInterfacesDialog::updateStatistics(void)
754 {
755     interface_t *device;
756
757     for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) {
758
759         for (guint if_idx = 0; if_idx < global_capture_opts.all_ifaces->len; if_idx++) {
760             QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row);
761             if (!ti) {
762                 continue;
763             }
764             device = &g_array_index(global_capture_opts.all_ifaces, interface_t, if_idx);
765             QString device_name = ti->text(col_interface_);
766             if (device_name.compare(device->display_name) || device->hidden || device->type == IF_PIPE) {
767                 continue;
768             }
769             QList<int> points = ti->data(col_traffic_, Qt::UserRole).value<QList<int> >();
770             points.append(device->packet_diff);
771             ti->setData(col_traffic_, Qt::UserRole, qVariantFromValue(points));
772         }
773     }
774     ui->interfaceTree->viewport()->update();
775 }
776
777 void CaptureInterfacesDialog::on_compileBPF_clicked()
778 {
779     QStringList interfaces;
780     foreach (QTreeWidgetItem *ti, ui->interfaceTree->selectedItems()) {
781         interfaces.append(ti->text(col_interface_));
782     }
783
784     QString filter = ui->captureFilterComboBox->currentText();
785     CompiledFilterOutput *cfo = new CompiledFilterOutput(this, interfaces, filter);
786
787     cfo->show();
788 }
789
790 bool CaptureInterfacesDialog::saveOptionsToPreferences()
791 {
792     if (ui->rbPcapng->isChecked()) {
793         global_capture_opts.use_pcapng = true;
794         prefs.capture_pcap_ng = true;
795     } else {
796         global_capture_opts.use_pcapng = false;
797         prefs.capture_pcap_ng = false;
798     }
799
800     QString filename = ui->filenameLineEdit->text();
801     if (filename.length() > 0) {
802         /* User specified a file to which the capture should be written. */
803         global_capture_opts.saving_to_file = true;
804         global_capture_opts.save_file = qstring_strdup(filename);
805         global_capture_opts.orig_save_file = qstring_strdup(filename);
806         /* Save the directory name for future file dialogs. */
807         set_last_open_dir(get_dirname(filename.toUtf8().data()));
808     } else {
809         /* User didn't specify a file; save to a temporary file. */
810         global_capture_opts.save_file = NULL;
811     }
812
813     global_capture_opts.has_ring_num_files = ui->RbCheckBox->isChecked();
814
815     if (global_capture_opts.has_ring_num_files) {
816         global_capture_opts.ring_num_files = ui->RbSpinBox->value();
817         if (global_capture_opts.ring_num_files > RINGBUFFER_MAX_NUM_FILES)
818             global_capture_opts.ring_num_files = RINGBUFFER_MAX_NUM_FILES;
819 #if RINGBUFFER_MIN_NUM_FILES > 0
820         else if (global_capture_opts.ring_num_files < RINGBUFFER_MIN_NUM_FILES)
821             global_capture_opts.ring_num_files = RINGBUFFER_MIN_NUM_FILES;
822 #endif
823     }
824     global_capture_opts.multi_files_on = ui->gbNewFileAuto->isChecked();
825     if (global_capture_opts.multi_files_on) {
826         global_capture_opts.has_file_duration = ui->SecsCheckBox->isChecked();
827         if (global_capture_opts.has_file_duration) {
828             global_capture_opts.file_duration = ui->SecsSpinBox->value();
829             int index = ui->SecsComboBox->currentIndex();
830             switch (index) {
831             case 1: global_capture_opts.file_duration *= 60;
832                 break;
833             case 2: global_capture_opts.file_duration *= 3600;
834                 break;
835             }
836          }
837          global_capture_opts.has_autostop_filesize = ui->MBCheckBox->isChecked();
838          if (global_capture_opts.has_autostop_filesize) {
839              global_capture_opts.autostop_filesize = ui->MBSpinBox->value();
840              int index = ui->MBComboBox->currentIndex();
841              switch (index) {
842              case 1: if (global_capture_opts.autostop_filesize > 2000) {
843                  QMessageBox::warning(this, tr("Error"),
844                                           tr("Multiple files: Requested filesize too large! The filesize cannot be greater than 2 GiB."));
845                  return false;
846                  } else {
847                      global_capture_opts.autostop_filesize *= 1000;
848                  }
849                  break;
850              case 2: if (global_capture_opts.autostop_filesize > 2) {
851                      QMessageBox::warning(this, tr("Error"),
852                                               tr("Multiple files: Requested filesize too large! The filesize cannot be greater than 2 GiB."));
853                      return false;
854                      } else {
855                          global_capture_opts.autostop_filesize *= 1000000;
856                      }
857                  break;
858              }
859          }
860          /* test if the settings are ok for a ringbuffer */
861          if (global_capture_opts.save_file == NULL) {
862              QMessageBox::warning(this, tr("Error"),
863                                       tr("Multiple files: No capture file name given! You must specify a filename if you want to use multiple files."));
864              return false;
865          } else if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
866              QMessageBox::warning(this, tr("Error"),
867                                       tr("Multiple files: No file limit given! You must specify a file size or duration at which is switched to the next capture file\n if you want to use multiple files."));
868              g_free(global_capture_opts.save_file);
869              global_capture_opts.save_file = NULL;
870              return false;
871          }
872     } else {
873         global_capture_opts.has_autostop_filesize = ui->stopMBCheckBox->isChecked();
874         if (global_capture_opts.has_autostop_filesize) {
875             global_capture_opts.autostop_filesize = ui->stopMBSpinBox->value();
876             int index = ui->stopMBComboBox->currentIndex();
877             switch (index) {
878             case 1: if (global_capture_opts.autostop_filesize > 2000) {
879                 QMessageBox::warning(this, tr("Error"),
880                                          tr("Multiple files: Requested filesize too large! The filesize cannot be greater than 2 GiB."));
881                 return false;
882                 } else {
883                     global_capture_opts.autostop_filesize *= 1000;
884                 }
885                 break;
886             case 2: if (global_capture_opts.autostop_filesize > 2) {
887                     QMessageBox::warning(this, tr("Error"),
888                                              tr("Multiple files: Requested filesize too large! The filesize cannot be greater than 2 GiB."));
889                     return false;
890                     } else {
891                         global_capture_opts.autostop_filesize *= 1000000;
892                     }
893                 break;
894             }
895         }
896     }
897
898     global_capture_opts.has_autostop_duration = ui->stopSecsCheckBox->isChecked();
899     if (global_capture_opts.has_autostop_duration) {
900         global_capture_opts.autostop_duration = ui->stopSecsSpinBox->value();
901         int index = ui->stopSecsComboBox->currentIndex();
902         switch (index) {
903         case 1: global_capture_opts.autostop_duration *= 60;
904             break;
905         case 2: global_capture_opts.autostop_duration *= 3600;
906             break;
907         }
908     }
909
910     global_capture_opts.has_autostop_packets = ui->stopPktCheckBox->isChecked();
911     if (global_capture_opts.has_autostop_packets) {
912         global_capture_opts.autostop_packets = ui->stopPktSpinBox->value();
913     }
914
915     global_capture_opts.has_autostop_files = ui->stopFilesCheckBox->isChecked();
916     if (global_capture_opts.has_autostop_files) {
917         global_capture_opts.autostop_files = ui->stopFilesSpinBox->value();
918     }
919
920     interface_t *device;
921
922     for (int col = col_link_; col <= col_filter_; col++) {
923         if (ui->interfaceTree->isColumnHidden(col)) {
924             continue;
925         }
926         /* All entries are separated by comma. There is also one before the first interface to be able to identify
927            word boundaries. As 'lo' is part of 'nflog' an exact match is necessary. */
928         switch (col) {
929         case col_link_:
930         {
931             QStringList link_list;
932
933             for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) {
934                 QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row);
935                 QString device_name = ti->data(col_interface_, Qt::UserRole).toString();
936                 device = getDeviceByName(device_name);
937                 if (!device || device->active_dlt == -1) {
938                     continue;
939                 }
940                 link_list << QString("%1(%2)").arg(device->name).arg(device->active_dlt);
941             }
942             g_free(prefs.capture_devices_linktypes);
943             prefs.capture_devices_linktypes = qstring_strdup(link_list.join(","));
944             break;
945         }
946 #ifdef SHOW_BUFFER_COLUMN
947         case col_buffer_:
948         {
949             QStringList buffer_size_list;
950
951             for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) {
952                 QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row);
953                 QString device_name = ti->data(col_interface_, Qt::UserRole).toString();
954                 device = getDeviceByName(device_name);
955                 if (!device || device->buffer == -1) {
956                     continue;
957                 }
958                 buffer_size_list << QString("%1(%2)").arg(device->name).arg(device->buffer);
959             }
960             g_free(prefs.capture_devices_buffersize);
961             prefs.capture_devices_buffersize = qstring_strdup(buffer_size_list.join(","));
962             break;
963         }
964 #endif // HAVE_BUFFER_SETTING
965         case col_snaplen_:
966         {
967             QStringList snaplen_list;
968
969             for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) {
970                 QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row);
971                 QString device_name = ti->data(col_interface_, Qt::UserRole).toString();
972                 device = getDeviceByName(device_name);
973                 if (!device) continue;
974                 snaplen_list << QString("%1:%2(%3)")
975                                 .arg(device->name)
976                                 .arg(device->has_snaplen)
977                                 .arg(device->has_snaplen ? device->snaplen : WTAP_MAX_PACKET_SIZE);
978             }
979             g_free(prefs.capture_devices_snaplen);
980             prefs.capture_devices_snaplen = qstring_strdup(snaplen_list.join(","));
981             break;
982         }
983         case col_pmode_:
984         {
985             QStringList pmode_list;
986
987             for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) {
988                 QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row);
989                 QString device_name = ti->data(col_interface_, Qt::UserRole).toString();
990                 device = getDeviceByName(device_name);
991                 if (!device || device->pmode == -1) {
992                     continue;
993                 }
994                 pmode_list << QString("%1(%2)").arg(device->name).arg(device->pmode);
995             }
996             g_free(prefs.capture_devices_pmode);
997             prefs.capture_devices_pmode = qstring_strdup(pmode_list.join(","));
998             break;
999         }
1000
1001 #ifdef SHOW_MONITOR_COLUMN
1002         case col_monitor_:
1003         {
1004             QStringList monitor_list;
1005
1006             for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) {
1007                 QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row);
1008                 QString device_name = ti->data(col_interface_, Qt::UserRole).toString();
1009                 device = getDeviceByName(device_name);
1010                 if (!device || !device->monitor_mode_supported || (device->monitor_mode_supported && !device->monitor_mode_enabled)) {
1011                     continue;
1012                 }
1013                 monitor_list << device->name;
1014             }
1015             g_free(prefs.capture_devices_monitor_mode);
1016             prefs.capture_devices_monitor_mode = qstring_strdup(monitor_list.join(","));
1017             break;
1018         }
1019 #endif // HAVE_MONITOR_SETTING
1020
1021 #if 0
1022             // The device cfilter should have been applied at this point.
1023             // We shouldn't change it here.
1024         case col_filter_:
1025         {
1026             // XXX Update selected interfaces only?
1027             for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) {
1028                 QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row);
1029                 QString device_name = ti->data(col_interface_, Qt::UserRole).toString();
1030                 device = getDeviceByName(device_name);
1031                 if (!device) continue;
1032                 g_free(device->cfilter);
1033                 if (ti->text(col_filter_).isEmpty()) {
1034                     device->cfilter = NULL;
1035                 } else {
1036                     device->cfilter = qstring_strdup(ti->text(col_filter_));
1037                 }
1038             }
1039         }
1040 #endif
1041         }
1042     }
1043     if (!prefs.gui_use_pref_save) {
1044         prefs_main_write();
1045     }
1046     return true;
1047 }
1048
1049 void CaptureInterfacesDialog::updateSelectedFilter()
1050 {
1051     // Should match MainWelcome::interfaceSelected.
1052     QPair <const QString, bool> sf_pair = CaptureFilterEdit::getSelectedFilter();
1053     const QString user_filter = sf_pair.first;
1054     bool conflict = sf_pair.second;
1055
1056     if (conflict) {
1057         ui->captureFilterComboBox->lineEdit()->clear();
1058         ui->captureFilterComboBox->setConflict(true);
1059     } else {
1060         ui->captureFilterComboBox->lineEdit()->setText(user_filter);
1061     }
1062 }
1063
1064 void CaptureInterfacesDialog::on_manageButton_clicked()
1065 {
1066     if (saveOptionsToPreferences()) {
1067         ManageInterfacesDialog *dlg = new ManageInterfacesDialog(this);
1068         dlg->show();
1069     }
1070 }
1071
1072 void CaptureInterfacesDialog::changeEvent(QEvent* event)
1073 {
1074     if (0 != event)
1075     {
1076         switch (event->type())
1077         {
1078         case QEvent::LanguageChange:
1079             ui->retranslateUi(this);
1080             break;
1081         default:
1082             break;
1083         }
1084     }
1085     QDialog::changeEvent(event);
1086 }
1087
1088 interface_t *CaptureInterfacesDialog::getDeviceByName(const QString device_name)
1089 {
1090     for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
1091         interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
1092         if (device_name.compare(QString().fromUtf8(device->name)) == 0) {
1093             return device;
1094         }
1095     }
1096     return NULL;
1097 }
1098
1099 //
1100 // InterfaceTreeItem
1101 //
1102 bool InterfaceTreeWidgetItem::operator< (const QTreeWidgetItem &other) const {
1103     if (treeWidget()->sortColumn() == col_traffic_) {
1104         QList<int> points = data(col_traffic_, Qt::UserRole).value<QList<int> >();
1105         QList<int> other_points = other.data(col_traffic_, Qt::UserRole).value<QList<int> >();
1106         double avg = 0, other_avg = 0;
1107         foreach (int point, points) {
1108             avg += (double) point / points.length();
1109         }
1110         foreach (int point, other_points) {
1111             other_avg += (double) point / other_points.length();
1112         }
1113         return avg < other_avg;
1114     }
1115     return QTreeWidgetItem::operator<(other);
1116 }
1117
1118
1119 //
1120 // InterfaceTreeDelegate
1121 //
1122
1123 #include <QComboBox>
1124
1125 InterfaceTreeDelegate::InterfaceTreeDelegate(QObject *parent)
1126     : QStyledItemDelegate(parent), tree_(NULL)
1127 {
1128 }
1129
1130
1131 InterfaceTreeDelegate::~InterfaceTreeDelegate()
1132 {
1133 }
1134
1135
1136 QWidget* InterfaceTreeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &idx) const
1137 {
1138     QWidget *w = NULL;
1139 #ifdef SHOW_BUFFER_COLUMN
1140     gint buffer = DEFAULT_CAPTURE_BUFFER_SIZE;
1141 #endif
1142     guint snap = WTAP_MAX_PACKET_SIZE;
1143     GList *links = NULL;
1144
1145     if (idx.column() > 1 && idx.data().toString().compare(UTF8_EM_DASH)) {
1146         QTreeWidgetItem *ti = tree_->topLevelItem(idx.row());
1147         QString interface_name = ti->text(col_interface_);
1148         interface_t *device = find_device_by_if_name(interface_name);
1149
1150         if (device) {
1151 #ifdef SHOW_BUFFER_COLUMN
1152             buffer = device->buffer;
1153 #endif
1154             snap = device->snaplen;
1155             links = device->links;
1156         }
1157         switch (idx.column()) {
1158         case col_interface_:
1159         case col_traffic_:
1160             break;
1161         case col_link_:
1162         {
1163             GList *list;
1164             link_row *linkr;
1165             QStringList valid_link_types;
1166
1167             // XXX The GTK+ UI fills in all link types, valid or not. We add
1168             // only the valid ones. If we *do* wish to include invalid link
1169             // types we'll have to jump through the hoops necessary to disable
1170             // QComboBox items.
1171
1172             for (list = links; list != NULL; list = g_list_next(list)) {
1173                 linkr = (link_row*)(list->data);
1174                 if (linkr->dlt >= 0) {
1175                     valid_link_types << linkr->name;
1176                 }
1177             }
1178
1179             if (valid_link_types.size() < 2) {
1180                 break;
1181             }
1182             QComboBox *cb = new QComboBox(parent);
1183             cb->addItems(valid_link_types);
1184
1185             connect(cb, SIGNAL(currentIndexChanged(QString)), this, SLOT(linkTypeChanged(QString)));
1186             w = (QWidget*) cb;
1187             break;
1188         }
1189         case col_snaplen_:
1190         {
1191             QSpinBox *sb = new QSpinBox(parent);
1192             sb->setRange(1, 65535);
1193             sb->setValue(snap);
1194             sb->setWrapping(true);
1195             connect(sb, SIGNAL(valueChanged(int)), this, SLOT(snapshotLengthChanged(int)));
1196             w = (QWidget*) sb;
1197             break;
1198         }
1199 #ifdef SHOW_BUFFER_COLUMN
1200         case col_buffer_:
1201         {
1202             QSpinBox *sb = new QSpinBox(parent);
1203             sb->setRange(1, 65535);
1204             sb->setValue(buffer);
1205             sb->setWrapping(true);
1206             connect(sb, SIGNAL(valueChanged(int)), this, SLOT(bufferSizeChanged(int)));
1207             w = (QWidget*) sb;
1208             break;
1209         }
1210 #endif
1211         case col_filter_:
1212         {
1213             CaptureFilterCombo *cf = new CaptureFilterCombo(parent, true);
1214             connect(cf->lineEdit(), SIGNAL(textEdited(QString)), this, SIGNAL(filterChanged(QString)));
1215             w = (QWidget*) cf;
1216         }
1217         default:
1218             break;
1219         }
1220 //        if (w) {
1221 //            ti->setSizeHint(index.column(), w->sizeHint());
1222 //        }
1223     }
1224     return w;
1225 }
1226
1227 bool InterfaceTreeDelegate::eventFilter(QObject *object, QEvent *event)
1228 {
1229     QComboBox * comboBox = dynamic_cast<QComboBox*>(object);
1230     if (comboBox) {
1231         if (event->type() == QEvent::MouseButtonRelease) {
1232             comboBox->showPopup();
1233             return true;
1234         }
1235     } else {
1236         return QStyledItemDelegate::eventFilter(object, event);
1237     }
1238     return false;
1239 }
1240
1241 void InterfaceTreeDelegate::linkTypeChanged(QString selected_link_type)
1242 {
1243     GList *list;
1244     link_row *temp;
1245     interface_t *device;
1246
1247     QTreeWidgetItem *ti = tree_->currentItem();
1248     if (!ti) {
1249         return;
1250     }
1251     QString interface_name = ti->text(col_interface_);
1252     device = find_device_by_if_name(interface_name);
1253     if (!device) {
1254         return;
1255     }
1256     for (list = device->links; list != NULL; list = g_list_next(list)) {
1257         temp = (link_row*) (list->data);
1258         if (!selected_link_type.compare(temp->name)) {
1259             device->active_dlt = temp->dlt;
1260         }
1261     }
1262     // XXX We might want to verify that active_dlt is valid at this point.
1263 }
1264
1265 void InterfaceTreeDelegate::snapshotLengthChanged(int value)
1266 {
1267     interface_t *device;
1268     QTreeWidgetItem *ti = tree_->currentItem();
1269     if (!ti) {
1270         return;
1271     }
1272     QString interface_name = ti->text(col_interface_);
1273     device = find_device_by_if_name(interface_name);
1274     if (!device) {
1275         return;
1276     }
1277     if (value != WTAP_MAX_PACKET_SIZE) {
1278         device->has_snaplen = true;
1279         device->snaplen = value;
1280     } else {
1281         device->has_snaplen = false;
1282         device->snaplen = WTAP_MAX_PACKET_SIZE;
1283     }
1284 }
1285
1286 void InterfaceTreeDelegate::bufferSizeChanged(int value)
1287 {
1288 #ifdef SHOW_BUFFER_COLUMN
1289     interface_t *device;
1290     QTreeWidgetItem *ti = tree_->currentItem();
1291     if (!ti) {
1292         return;
1293     }
1294     QString interface_name = ti->text(col_interface_);
1295     device = find_device_by_if_name(interface_name);
1296     if (!device) {
1297         return;
1298     }
1299     device->buffer = value;
1300 #else
1301     Q_UNUSED(value);
1302 #endif
1303 }
1304
1305 #endif /* HAVE_LIBPCAP */
1306
1307 /*
1308  * Editor modelines
1309  *
1310  * Local Variables:
1311  * c-basic-offset: 4
1312  * tab-width: 8
1313  * indent-tabs-mode: nil
1314  * End:
1315  *
1316  * ex: set shiftwidth=4 tabstop=8 expandtab:
1317  * :indentSize=4:tabSize=8:noTabs=true:
1318  */