qt: add missing initializers (CID 1325722)
[metze/wireshark/wip.git] / ui / qt / manage_interfaces_dialog.cpp
1 /* manage_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 <glib.h>
23 #include "manage_interfaces_dialog.h"
24 #include <ui_manage_interfaces_dialog.h>
25 #include "epan/prefs.h"
26 #include "epan/to_str.h"
27 #include "ui/last_open_dir.h"
28 #include "capture_opts.h"
29 #include "ui/capture_globals.h"
30 #include "ui/qt/capture_interfaces_dialog.h"
31 #ifdef HAVE_PCAP_REMOTE
32 #include "ui/qt/remote_capture_dialog.h"
33 #include "ui/qt/remote_settings_dialog.h"
34 #endif
35 #include "ui/iface_lists.h"
36 #include "ui/preference_utils.h"
37 #include "ui/ui_util.h"
38 #include <wsutil/utf8_entities.h>
39
40 #include "qt_ui_utils.h"
41
42 #include "wireshark_application.h"
43
44 #include <QDebug>
45
46 #ifdef HAVE_LIBPCAP
47 #include <QCheckBox>
48 #include <QFileDialog>
49 #include <QHBoxLayout>
50 #include <QLineEdit>
51 #include <QStandardItemModel>
52 #include <QTreeWidgetItemIterator>
53
54 // To do:
55 // - Check the validity of pipes and remote interfaces and provide feedback
56 //   via hintLabel.
57 // - We might want to move PathChooserDelegate to its own module and use it in
58 //   other parts of the application such as the general preferences and UATs.
59 //   Qt Creator has a much more elaborate version from which we might want
60 //   to draw inspiration.
61
62 enum {
63     col_p_pipe_
64 };
65
66 enum
67 {
68     col_l_show_,
69     col_l_friendly_name_,
70     col_l_local_name_,
71     col_l_comment_
72 };
73
74 enum
75 {
76     col_r_show_,
77     col_r_host_dev_
78 };
79
80 enum {
81     tab_local_,
82     tab_pipe_,
83     tab_remote_
84 };
85
86 ManageInterfacesDialog::ManageInterfacesDialog(QWidget *parent) :
87     QDialog(parent),
88     ui(new Ui::ManageInterfacesDialog)
89 {
90     ui->setupUi(this);
91
92 #ifdef Q_OS_MAC
93     ui->addPipe->setAttribute(Qt::WA_MacSmallSize, true);
94     ui->addPipe->setAttribute(Qt::WA_MacSmallSize, true);
95     ui->addRemote->setAttribute(Qt::WA_MacSmallSize, true);
96     ui->delRemote->setAttribute(Qt::WA_MacSmallSize, true);
97 #endif
98
99     int one_em = fontMetrics().height();
100
101     ui->localList->setColumnWidth(col_l_show_, one_em * 3);
102 #ifndef Q_OS_WIN
103     ui->localList->setColumnHidden(col_l_friendly_name_, true);
104 #endif
105
106     ui->pipeList->setItemDelegateForColumn(col_p_pipe_, &new_pipe_item_delegate_);
107     new_pipe_item_delegate_.setTree(ui->pipeList);
108
109     showPipes();
110     showLocalInterfaces();
111
112 #if defined(HAVE_PCAP_REMOTE)
113     // The default indentation (20) means our checkboxes are shifted too far on Windows.
114     // Assume that our disclosure and checkbox controls are square, or at least fit within an em.
115     ui->remoteList->setIndentation(one_em);
116     ui->remoteList->setColumnWidth(col_r_show_, one_em * 4);
117     ui->remoteSettings->setEnabled(false);
118     showRemoteInterfaces();
119 #else
120     ui->remoteTab->setEnabled(false);
121 #endif
122
123     connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateWidgets()));
124     connect(this, SIGNAL(ifsChanged()), parent, SIGNAL(ifsChanged()));
125
126 #ifdef HAVE_PCAP_REMOTE
127     connect(this, SIGNAL(remoteAdded(GList*, remote_options*)), this, SLOT(addRemoteInterfaces(GList*, remote_options*)));
128     connect(this, SIGNAL(remoteSettingsChanged(interface_t *)), this, SLOT(setRemoteSettings(interface_t *)));
129     connect(ui->remoteList, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(remoteSelectionChanged(QTreeWidgetItem*, int)));
130 #endif
131
132     ui->tabWidget->setCurrentIndex(tab_local_);
133     updateWidgets();
134 }
135
136 ManageInterfacesDialog::~ManageInterfacesDialog()
137 {
138     delete ui;
139 }
140
141 void ManageInterfacesDialog::updateWidgets()
142 {
143     QString hint;
144
145     if (ui->pipeList->selectedItems().length() > 0) {
146         ui->delPipe->setEnabled(true);
147     } else {
148         ui->delPipe->setEnabled(false);
149     }
150
151 #ifdef HAVE_PCAP_REMOTE
152     bool enable_del_remote = false;
153     bool enable_remote_settings = false;
154     QTreeWidgetItem *item = ui->remoteList->currentItem();
155
156     if (item) {
157         if (item->childCount() < 1) { // Leaf
158             enable_remote_settings = true;
159         } else {
160             enable_del_remote = true;
161         }
162     }
163     ui->delRemote->setEnabled(enable_del_remote);
164     ui->remoteSettings->setEnabled(enable_remote_settings);
165 #endif
166
167     switch (ui->tabWidget->currentIndex()) {
168     case tab_pipe_:
169         hint = tr("This version of Wireshark does not save pipe settings.");
170         break;
171     case tab_remote_:
172 #ifdef HAVE_PCAP_REMOTE
173         hint = tr("This version of Wireshark does not save remote settings.");
174 #else
175         hint = tr("This version of Wireshark does not support remote interfaces.");
176 #endif
177         break;
178     default:
179         break;
180     }
181
182     hint.prepend("<small><i>");
183     hint.append("</i></small>");
184     ui->hintLabel->setText(hint);
185 }
186
187 void ManageInterfacesDialog::showPipes()
188 {
189     ui->pipeList->clear();
190
191     if (global_capture_opts.all_ifaces->len > 0) {
192         interface_t device;
193
194         for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
195             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
196
197             /* Continue if capture device is hidden */
198             if (device.hidden || device.type != IF_PIPE) {
199                 continue;
200             }
201             QTreeWidgetItem *item = new QTreeWidgetItem(ui->pipeList);
202             item->setFlags(item->flags() | Qt::ItemIsEditable);
203             item->setText(col_p_pipe_, device.display_name);
204         }
205     }
206 }
207
208 void ManageInterfacesDialog::on_buttonBox_accepted()
209 {
210     pipeAccepted();
211     localAccepted();
212 #ifdef HAVE_PCAP_REMOTE
213     remoteAccepted();
214 #endif
215     prefs_main_write();
216     emit ifsChanged();
217 }
218
219 const QString new_pipe_default_ = QObject::tr("New Pipe");
220 void ManageInterfacesDialog::on_addPipe_clicked()
221 {
222     QTreeWidgetItem *item = new QTreeWidgetItem(ui->pipeList);
223     item->setText(col_p_pipe_, new_pipe_default_);
224     item->setFlags(item->flags() | Qt::ItemIsEditable);
225     ui->pipeList->setCurrentItem(item);
226     ui->pipeList->editItem(item, col_p_pipe_);
227 }
228
229 void ManageInterfacesDialog::pipeAccepted()
230 {
231     interface_t device;
232
233     // First clear the current pipes
234     for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
235         device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
236         /* Continue if capture device is hidden or not a pipe */
237         if (device.hidden || device.type != IF_PIPE) {
238             continue;
239         }
240         global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
241     }
242
243     // Next rebuild a fresh list
244     QTreeWidgetItemIterator it(ui->pipeList);
245     while (*it) {
246         QString pipe_name = (*it)->text(col_p_pipe_);
247         if (pipe_name.isEmpty() || pipe_name == new_pipe_default_) {
248             ++it;
249             continue;
250         }
251
252         for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
253             // Instead of just deleting the device we might want to add a hint label
254             // and let the user know what's going to happen.
255             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
256             if (pipe_name.compare(device.name) == 0) { // Duplicate
257                 ++it;
258                 continue;
259             }
260         }
261
262         device.name         = qstring_strdup(pipe_name);
263         device.display_name = g_strdup(device.name);
264         device.hidden       = FALSE;
265         device.selected     = TRUE;
266         device.type         = IF_PIPE;
267         device.pmode        = global_capture_opts.default_options.promisc_mode;
268         device.has_snaplen  = global_capture_opts.default_options.has_snaplen;
269         device.snaplen      = global_capture_opts.default_options.snaplen;
270         device.cfilter      = g_strdup(global_capture_opts.default_options.cfilter);
271         device.addresses    = NULL;
272         device.no_addresses = 0;
273         device.last_packets = 0;
274         device.links        = NULL;
275 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
276         device.buffer       = DEFAULT_CAPTURE_BUFFER_SIZE;
277 #endif
278         device.active_dlt = -1;
279         device.locked = FALSE;
280         device.if_info.name = g_strdup(device.name);
281         device.if_info.friendly_name = NULL;
282         device.if_info.vendor_description = NULL;
283         device.if_info.addrs = NULL;
284         device.if_info.loopback = FALSE;
285         device.if_info.type = IF_PIPE;
286 #ifdef HAVE_EXTCAP
287         device.if_info.extcap = NULL;
288         device.external_cap_args_settings = NULL;
289 #endif
290 #if defined(HAVE_PCAP_CREATE)
291         device.monitor_mode_enabled = FALSE;
292         device.monitor_mode_supported = FALSE;
293 #endif
294         global_capture_opts.num_selected++;
295         g_array_append_val(global_capture_opts.all_ifaces, device);
296         ++it;
297     }
298 }
299
300 void ManageInterfacesDialog::on_delPipe_clicked()
301 {
302     // We're just managing a list of strings at this point.
303     delete ui->pipeList->currentItem();
304 }
305
306 void ManageInterfacesDialog::on_pipeList_currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)
307 {
308     updateWidgets();
309 }
310
311 void ManageInterfacesDialog::showLocalInterfaces()
312 {
313     guint i;
314     interface_t device;
315     gchar *pr_descr = g_strdup("");
316     char *comment = NULL;
317
318     ui->localList->clear();
319     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
320         device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
321         if (device.local && device.type != IF_PIPE && device.type != IF_STDIN) {
322             QTreeWidgetItem *item = new QTreeWidgetItem(ui->localList);
323             item->setFlags(item->flags() | Qt::ItemIsEditable);
324             if (prefs.capture_device && strstr(prefs.capture_device, device.name)) {
325                 // Force the default device to be checked.
326                 item->setFlags(item->flags() ^ Qt::ItemIsUserCheckable);
327                 item->setCheckState(col_l_show_, Qt::Checked);
328             } else {
329                 item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
330                 item->setCheckState(col_l_show_, device.hidden ? Qt::Unchecked : Qt::Checked);
331             }
332 #ifdef _WIN32
333             item->setText(col_l_friendly_name_, device.friendly_name);
334 #endif
335             item->setText(col_l_local_name_, device.name);
336
337             comment = capture_dev_user_descr_find(device.name);
338             if (comment) {
339                 item->setText(col_l_comment_, comment);
340                 g_free(comment);
341             }
342         } else {
343           continue;
344         }
345     }
346     g_free(pr_descr);
347 }
348
349 void ManageInterfacesDialog::saveLocalHideChanges(QTreeWidgetItem *item)
350 {
351     guint i;
352     interface_t device;
353
354     if (!item) {
355         return;
356     }
357
358     QString name = item->text(col_l_local_name_);
359     /* See if this is the currently selected capturing device */
360
361     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
362         device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
363         if (name.compare(device.name)) {
364             continue;
365         }
366         device.hidden = (item->checkState(col_l_show_) == Qt::Checked ? false : true);
367         global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
368         g_array_insert_val(global_capture_opts.all_ifaces, i, device);
369     }
370 }
371
372 void ManageInterfacesDialog::saveLocalCommentChanges(QTreeWidgetItem* item)
373 {
374     guint i;
375     interface_t device;
376
377     if (!item) {
378         return;
379     }
380
381     QString name = item->text(col_l_local_name_);
382     QString comment = item->text(col_l_comment_);
383     /* See if this is the currently selected capturing device */
384
385     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
386         device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
387         if (name.compare(device.name)) {
388             continue;
389         }
390
391         g_free(device.display_name);
392         // XXX The GTK+ UI uses the raw device name instead of the friendly name.
393         // This seems to make more sense.
394         gchar *if_string = device.friendly_name ? device.friendly_name : device.name;
395         if (comment.isEmpty()) {
396             device.display_name = g_strdup(if_string);
397         } else {
398             device.display_name = qstring_strdup(QString("%1: %2").arg(comment).arg(if_string));
399         }
400         global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
401         g_array_insert_val(global_capture_opts.all_ifaces, i, device);
402     }
403 }
404
405 #if 0 // Not needed?
406 void ManageInterfacesDialog::checkBoxChanged(QTreeWidgetItem* item)
407 {
408     guint i;
409     interface_t device;
410
411     if (!item) {
412         return;
413     }
414
415     QString name = item->text(col_l_local_name_);
416     /* See if this is the currently selected capturing device */
417
418     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
419         device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
420         if (name.compare(device.name)) {
421             continue;
422         }
423         if (prefs.capture_device && strstr(prefs.capture_device, device.name) && item->checkState() == Qt::Checked) {
424             /* Don't allow current interface to be hidden */
425             QMessageBox::warning(this, tr("Error"),
426                                  tr("Default interface cannot be hidden."));
427             item->setCheckState(Qt::Unchecked);
428             return;
429         }
430     }
431 }
432 #endif // checkBoxChanged not needed?
433
434 void ManageInterfacesDialog::localAccepted()
435 {
436
437     if (global_capture_opts.all_ifaces->len > 0) {
438         QStringList hide_list;
439         QStringList comment_list;
440         QTreeWidgetItemIterator it(ui->localList);
441         while (*it) {
442             if ((*it)->checkState(col_l_show_) != Qt::Checked) {
443                 hide_list << (*it)->text(col_l_local_name_);
444             }
445
446             if (!(*it)->text(col_l_local_name_).isEmpty()) {
447                 comment_list << QString("%1(%2)").arg((*it)->text(col_l_local_name_)).arg((*it)->text(col_l_comment_));
448             }
449
450             saveLocalHideChanges(*it);
451             saveLocalCommentChanges(*it);
452             ++it;
453         }
454         /* write new "hidden" string to preferences */
455         g_free(prefs.capture_devices_hide);
456         gchar *new_hide = qstring_strdup(hide_list.join(","));
457         prefs.capture_devices_hide = new_hide;
458         hide_interface(g_strdup(new_hide));
459
460         /* write new description string to preferences */
461         if (prefs.capture_devices_descr)
462             g_free(prefs.capture_devices_descr);
463         prefs.capture_devices_descr = qstring_strdup(comment_list.join(","));;
464     }
465 }
466
467 void ManageInterfacesDialog::on_buttonBox_helpRequested()
468 {
469     wsApp->helpTopicAction(HELP_CAPTURE_MANAGE_INTERFACES_DIALOG);
470 }
471
472 #ifdef HAVE_PCAP_REMOTE
473 void ManageInterfacesDialog::remoteSelectionChanged(QTreeWidgetItem*, int)
474 {
475     updateWidgets();
476 }
477
478 void ManageInterfacesDialog::addRemoteInterfaces(GList* rlist, remote_options *roptions)
479 {
480     GList *if_entry, *lt_entry;
481     if_info_t *if_info;
482     char *if_string = NULL;
483     gchar *descr, *str = NULL, *link_type_name = NULL, *auth_str;
484     if_capabilities_t *caps;
485     gint linktype_count;
486     bool monitor_mode, found = false;
487     GSList *curr_addr;
488     int ips = 0;
489     guint i;
490     if_addr_t *addr;
491     data_link_info_t *data_link_info;
492     GString *ip_str;
493     link_row *linkr = NULL;
494     interface_t device;
495
496     guint num_interfaces = global_capture_opts.all_ifaces->len;
497     for (if_entry = g_list_first(rlist); if_entry != NULL; if_entry = g_list_next(if_entry)) {
498         auth_str = NULL;
499         if_info = (if_info_t *)if_entry->data;
500         for (i = 0; i < num_interfaces; i++) {
501             device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
502             if (device.hidden)
503                 continue;
504             if (strcmp(device.name, if_info->name) == 0) {
505                 found = TRUE;
506                 break;
507             }
508         }
509         if (found) {
510             found = FALSE;
511             continue;
512         }
513         ip_str = g_string_new("");
514         str = "";
515         ips = 0;
516         device.name = g_strdup(if_info->name);
517         /* Is this interface hidden and, if so, should we include it
518            anyway? */
519         descr = capture_dev_user_descr_find(if_info->name);
520         if (descr != NULL) {
521             /* Yes, we have a user-supplied description; use it. */
522             if_string = g_strdup_printf("%s: %s", descr, if_info->name);
523             g_free(descr);
524         } else {
525             /* No, we don't have a user-supplied description; did we get
526                one from the OS or libpcap? */
527             if (if_info->vendor_description != NULL) {
528                 /* Yes - use it. */
529                 if_string = g_strdup_printf("%s: %s", if_info->vendor_description, if_info->name);
530             } else {
531                 /* No. */
532                 if_string = g_strdup(if_info->name);
533             }
534         } /* else descr != NULL */
535         if (if_info->loopback) {
536             device.display_name = g_strdup_printf("%s (loopback)", if_string);
537         } else {
538             device.display_name = g_strdup(if_string);
539         }
540 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
541         if ((device.buffer = capture_dev_user_buffersize_find(if_string)) == -1) {
542             device.buffer = global_capture_opts.default_options.buffer_size;
543         }
544 #endif
545         if (!capture_dev_user_pmode_find(if_string, &device.pmode)) {
546             device.pmode = global_capture_opts.default_options.promisc_mode;
547         }
548         if (!capture_dev_user_snaplen_find(if_string, &device.has_snaplen,
549                                            &device.snaplen)) {
550             device.has_snaplen = global_capture_opts.default_options.has_snaplen;
551             device.snaplen = global_capture_opts.default_options.snaplen;
552         }
553         device.cfilter = g_strdup(global_capture_opts.default_options.cfilter);
554         monitor_mode = prefs_capture_device_monitor_mode(if_string);
555 #ifdef HAVE_PCAP_REMOTE
556         if (roptions->remote_host_opts.auth_type == CAPTURE_AUTH_PWD) {
557             auth_str = g_strdup_printf("%s:%s", roptions->remote_host_opts.auth_username,
558                                        roptions->remote_host_opts.auth_password);
559         }
560 #endif
561         caps = capture_get_if_capabilities(if_string, monitor_mode, auth_str, NULL, main_window_update);
562         g_free(auth_str);
563         for (; (curr_addr = g_slist_nth(if_info->addrs, ips)) != NULL; ips++) {
564             address addr_str;
565             char* temp_addr_str = NULL;
566             if (ips != 0) {
567                 g_string_append(ip_str, "\n");
568             }
569             addr = (if_addr_t *)curr_addr->data;
570             switch (addr->ifat_type) {
571             case IF_AT_IPv4:
572                 SET_ADDRESS(&addr_str, AT_IPv4, 4, &addr->addr.ip4_addr);
573                 temp_addr_str = (char*)address_to_str(NULL, &addr_str);
574                 g_string_append(ip_str, temp_addr_str);
575                 break;
576             case IF_AT_IPv6:
577                 SET_ADDRESS(&addr_str, AT_IPv6, 16, addr->addr.ip6_addr);
578                 temp_addr_str = (char*)address_to_str(NULL, &addr_str);
579                 g_string_append(ip_str, temp_addr_str);
580                 break;
581             default:
582                 /* In case we add non-IP addresses */
583                 break;
584             }
585             wmem_free(NULL, temp_addr_str);
586         } /* for curr_addr */
587         linktype_count = 0;
588         device.links = NULL;
589         if (caps != NULL) {
590 #ifdef HAVE_PCAP_CREATE
591             device.monitor_mode_enabled = monitor_mode;
592             device.monitor_mode_supported = caps->can_set_rfmon;
593 #endif
594             for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
595                 data_link_info = (data_link_info_t *)lt_entry->data;
596                 linkr = (link_row *)g_malloc(sizeof(link_row));
597                 /*
598                  * For link-layer types libpcap/WinPcap doesn't know about, the
599                  * name will be "DLT n", and the description will be null.
600                  * We mark those as unsupported, and don't allow them to be
601                  * used.
602                  */
603                 if (data_link_info->description != NULL) {
604                     str = g_strdup_printf("%s", data_link_info->description);
605                     linkr->dlt = data_link_info->dlt;
606                 } else {
607                     str = g_strdup_printf("%s (not supported)", data_link_info->name);
608                     linkr->dlt = -1;
609                 }
610                 if (linktype_count == 0) {
611                     link_type_name = g_strdup(str);
612                     device.active_dlt = data_link_info->dlt;
613                 }
614                 linkr->name = g_strdup(str);
615                 g_free(str);
616                 device.links = g_list_append(device.links, linkr);
617                 linktype_count++;
618             } /* for link_types */
619         } else {
620 #if defined(HAVE_PCAP_CREATE)
621             device.monitor_mode_enabled = FALSE;
622             device.monitor_mode_supported = FALSE;
623 #endif
624             device.active_dlt = -1;
625             link_type_name = g_strdup("default");
626         }
627         device.addresses = g_strdup(ip_str->str);
628         device.no_addresses = ips;
629         device.remote_opts.src_type= roptions->src_type;
630         if (device.remote_opts.src_type == CAPTURE_IFREMOTE) {
631             device.local = FALSE;
632         }
633         device.remote_opts.remote_host_opts.remote_host = g_strdup(roptions->remote_host_opts.remote_host);
634         device.remote_opts.remote_host_opts.remote_port = g_strdup(roptions->remote_host_opts.remote_port);
635         device.remote_opts.remote_host_opts.auth_type = roptions->remote_host_opts.auth_type;
636         device.remote_opts.remote_host_opts.auth_username = g_strdup(roptions->remote_host_opts.auth_username);
637         device.remote_opts.remote_host_opts.auth_password = g_strdup(roptions->remote_host_opts.auth_password);
638         device.remote_opts.remote_host_opts.datatx_udp = roptions->remote_host_opts.datatx_udp;
639         device.remote_opts.remote_host_opts.nocap_rpcap = roptions->remote_host_opts.nocap_rpcap;
640         device.remote_opts.remote_host_opts.nocap_local = roptions->remote_host_opts.nocap_local;
641 #ifdef HAVE_PCAP_SETSAMPLING
642         device.remote_opts.sampling_method = roptions->sampling_method;
643         device.remote_opts.sampling_param = roptions->sampling_param;
644 #endif
645         device.selected = TRUE;
646         global_capture_opts.num_selected++;
647         g_array_append_val(global_capture_opts.all_ifaces, device);
648         g_string_free(ip_str, TRUE);
649     } /*for*/
650     showRemoteInterfaces();
651 }
652
653 // We don't actually store these. When we do we should make sure they're stored
654 // securely using CryptProtectData, the OS X Keychain, GNOME Keyring, KWallet, etc.
655 void ManageInterfacesDialog::remoteAccepted()
656 {
657     QTreeWidgetItemIterator it(ui->remoteList);
658
659     while(*it) {
660         for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
661             interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
662             if ((*it)->text(col_r_host_dev_).compare(device.name))
663                 continue;
664             device.hidden = ((*it)->checkState(col_r_show_) == Qt::Checked ? false : true);
665             global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
666             g_array_insert_val(global_capture_opts.all_ifaces, i, device);
667         }
668         ++it;
669     }
670 }
671
672 void ManageInterfacesDialog::on_remoteList_currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)
673 {
674     updateWidgets();
675 }
676
677 void ManageInterfacesDialog::on_remoteList_itemClicked(QTreeWidgetItem *item, int column)
678 {
679     if (!item || column != col_r_show_) {
680         return;
681     }
682
683     for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
684         interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
685         if (!device.local) {
686             if (item->text(col_r_host_dev_).compare(device.name))
687                 continue;
688             device.hidden = (item->checkState(col_r_show_) == Qt::Checked ? false : true);
689         }
690     }
691 }
692
693 void ManageInterfacesDialog::on_delRemote_clicked()
694 {
695     QTreeWidgetItem* item = ui->remoteList->currentItem();
696     if (!item) {
697         return;
698     }
699
700     for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
701         interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
702         if (item->text(col_r_host_dev_).compare(device.remote_opts.remote_host_opts.remote_host))
703             continue;
704         global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
705     }
706     delete item;
707     fflush(stdout); // ???
708 }
709
710 void ManageInterfacesDialog::on_addRemote_clicked()
711 {
712     RemoteCaptureDialog *dlg = new RemoteCaptureDialog(this);
713     dlg->show();
714 }
715
716 void ManageInterfacesDialog::showRemoteInterfaces()
717 {
718     guint i;
719     interface_t device;
720     QTreeWidgetItem *item = NULL;
721
722     // We assume that remote interfaces are grouped by host.
723     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
724         QTreeWidgetItem *child;
725         device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
726         if (!device.local) {
727             if (!item || item->text(col_r_host_dev_).compare(device.remote_opts.remote_host_opts.remote_host) != 0) {
728                 item = new QTreeWidgetItem(ui->remoteList);
729                 item->setText(col_r_host_dev_, device.remote_opts.remote_host_opts.remote_host);
730                 item->setExpanded(true);
731             }
732             child = new QTreeWidgetItem(item);
733             child->setCheckState(col_r_show_, device.hidden ? Qt::Unchecked : Qt::Checked);
734             child->setText(col_r_host_dev_, QString(device.name));
735         }
736     }
737 }
738
739 void ManageInterfacesDialog::on_remoteSettings_clicked()
740 {
741     guint i = 0;
742     interface_t device;
743     QTreeWidgetItem* item = ui->remoteList->currentItem();
744     if (!item) {
745         return;
746     }
747
748     for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
749         device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
750         if (!device.local) {
751             if (item->text(col_r_host_dev_).compare(device.name)) {
752                continue;
753             } else {
754                 RemoteSettingsDialog *dlg = new RemoteSettingsDialog(this, &device);
755                 dlg->show();
756                 break;
757             }
758         }
759     }
760 }
761
762 void ManageInterfacesDialog::setRemoteSettings(interface_t *iface)
763 {
764     for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) {
765         interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
766         if (!device.local) {
767             if (strcmp(iface->name, device.name)) {
768                 continue;
769             }
770             device.remote_opts.remote_host_opts.nocap_rpcap = iface->remote_opts.remote_host_opts.nocap_rpcap;
771             device.remote_opts.remote_host_opts.datatx_udp = iface->remote_opts.remote_host_opts.datatx_udp;
772 #ifdef HAVE_PCAP_SETSAMPLING
773             device.remote_opts.sampling_method = iface->remote_opts.sampling_method;
774             device.remote_opts.sampling_param = iface->remote_opts.sampling_param;
775 #endif //HAVE_PCAP_SETSAMPLING
776             global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
777             g_array_insert_val(global_capture_opts.all_ifaces, i, device);
778         }
779     }
780 }
781 #endif // HAVE_PCAP_REMOTE
782
783 PathChooserDelegate::PathChooserDelegate(QObject *parent)
784     : QStyledItemDelegate(parent)
785 {
786 }
787
788 PathChooserDelegate::~PathChooserDelegate()
789 {
790 }
791
792 QWidget* PathChooserDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &) const
793 {
794     QTreeWidgetItem *item = tree_->currentItem();
795     if (!item) {
796         return NULL;
797     }
798     path_item_ = item;
799
800     path_editor_ = new QWidget(parent);
801     QHBoxLayout *hbox = new QHBoxLayout(path_editor_);
802     path_editor_->setLayout(hbox);
803     path_le_ = new QLineEdit(path_editor_);
804     QPushButton *pb = new QPushButton(path_editor_);
805
806     path_le_->setText(item->text(col_p_pipe_));
807     pb->setText(QString(tr("Browse" UTF8_HORIZONTAL_ELLIPSIS)));
808
809     hbox->setContentsMargins(0, 0, 0, 0);
810     hbox->addWidget(path_le_);
811     hbox->addWidget(pb);
812     hbox->setSizeConstraint(QLayout::SetMinimumSize);
813
814     // Grow the item to match the editor. According to the QAbstractItemDelegate
815     // documenation we're supposed to reimplement sizeHint but this seems to work.
816     QSize size = option.rect.size();
817     size.setHeight(qMax(option.rect.height(), hbox->sizeHint().height()));
818     item->setData(col_p_pipe_, Qt::SizeHintRole, size);
819
820     path_le_->selectAll();
821     path_editor_->setFocusProxy(path_le_);
822     path_editor_->setFocusPolicy(path_le_->focusPolicy());
823
824     connect(path_le_, SIGNAL(destroyed()), this, SLOT(stopEditor()));
825     connect(pb, SIGNAL(pressed()), this, SLOT(browse_button_clicked()));
826     return path_editor_;
827 }
828
829 void PathChooserDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const
830 {
831     QRect rect = option.rect;
832
833     // Make sure the editor doesn't get squashed.
834     editor->adjustSize();
835     rect.setHeight(qMax(option.rect.height(), editor->height()));
836     editor->setGeometry(rect);
837 }
838
839 void PathChooserDelegate::stopEditor()
840 {
841     path_item_->setData(col_p_pipe_, Qt::SizeHintRole, QVariant());
842     path_item_->setText(col_p_pipe_, path_le_->text());
843 }
844
845 void PathChooserDelegate::browse_button_clicked()
846 {
847     char *open_dir = NULL;
848
849     switch (prefs.gui_fileopen_style) {
850
851     case FO_STYLE_LAST_OPENED:
852         open_dir = get_last_open_dir();
853         break;
854
855     case FO_STYLE_SPECIFIED:
856         if (prefs.gui_fileopen_dir[0] != '\0')
857             open_dir = prefs.gui_fileopen_dir;
858         break;
859     }
860     QString file_name = QFileDialog::getOpenFileName(tree_, tr("Open Pipe"), open_dir);
861     if (!file_name.isEmpty()) {
862         path_le_->setText(file_name);
863     }
864 }
865
866 #endif /* HAVE_LIBPCAP */
867
868 /*
869  * Editor modelines
870  *
871  * Local Variables:
872  * c-basic-offset: 4
873  * tab-width: 8
874  * indent-tabs-mode: nil
875  * End:
876  *
877  * ex: set shiftwidth=4 tabstop=8 expandtab:
878  * :indentSize=4:tabSize=8:noTabs=true:
879  */