Interface List: Change display to view/model
[metze/wireshark/wip.git] / ui / qt / main_window_slots.cpp
1 /* main_window_slots.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 // Qt 5.5.0 + Visual C++ 2013
25 #ifdef _MSC_VER
26 #pragma warning(push)
27 #pragma warning(disable:4996)
28 #endif
29
30 #include "main_window.h"
31 #include <ui_main_window.h>
32
33 #ifdef _WIN32
34 #include <windows.h>
35 #endif
36
37 #include "ui/commandline.h"
38
39 #ifdef HAVE_LIBPCAP
40 #include "ui/capture.h"
41 #endif
42
43 #include "epan/color_filters.h"
44
45 #include "wsutil/file_util.h"
46 #include "wsutil/filesystem.h"
47
48 #include "epan/addr_resolv.h"
49 #include "epan/column.h"
50 #include "epan/dfilter/dfilter-macro.h"
51 #include "epan/dissector_filters.h"
52 #include "epan/epan_dissect.h"
53 #include "epan/filter_expressions.h"
54 #include "epan/prefs.h"
55 #include "epan/uat.h"
56 #include "epan/value_string.h"
57
58 #ifdef HAVE_LUA
59 #include <epan/wslua/init_wslua.h>
60 #endif
61
62 #include "ui/alert_box.h"
63 #ifdef HAVE_LIBPCAP
64 #include "ui/capture_ui_utils.h"
65 #endif
66
67 #include "ui/capture_globals.h"
68 #include "ui/help_url.h"
69 #include "ui/main_statusbar.h"
70 #include "ui/preference_utils.h"
71 #include "ui/recent.h"
72 #include "ui/recent_utils.h"
73 #include "ui/ssl_key_export.h"
74 #include "ui/ui_util.h"
75 #include "ui/all_files_wildcard.h"
76 #include "ui/qt/simple_dialog.h"
77
78 #ifdef HAVE_SOFTWARE_UPDATE
79 #include "ui/software_update.h"
80 #endif
81
82 #include "about_dialog.h"
83 #include "bluetooth_att_server_attributes_dialog.h"
84 #include "bluetooth_devices_dialog.h"
85 #include "bluetooth_hci_summary_dialog.h"
86 #include "capture_file_dialog.h"
87 #include "capture_file_properties_dialog.h"
88 #ifdef HAVE_LIBPCAP
89 #include "capture_interfaces_dialog.h"
90 #endif
91 #include "color_utils.h"
92 #include "coloring_rules_dialog.h"
93 #include "conversation_dialog.h"
94 #include "conversation_colorize_action.h"
95 #include "conversation_hash_tables_dialog.h"
96 #include "enabled_protocols_dialog.h"
97 #include "decode_as_dialog.h"
98 #include "display_filter_edit.h"
99 #include "display_filter_expression_dialog.h"
100 #include "dissector_tables_dialog.h"
101 #include "endpoint_dialog.h"
102 #include "expert_info_dialog.h"
103 #include "export_object_dialog.h"
104 #include "export_pdu_dialog.h"
105 #ifdef HAVE_EXTCAP
106 #include "extcap_options_dialog.h"
107 #endif
108 #include "file_set_dialog.h"
109 #include "filter_action.h"
110 #include "filter_dialog.h"
111 #include "firewall_rules_dialog.h"
112 #include "funnel_statistics.h"
113 #include "gsm_map_summary_dialog.h"
114 #include "iax2_analysis_dialog.h"
115 #include "io_graph_dialog.h"
116 #include "lbm_stream_dialog.h"
117 #include "lbm_uimflow_dialog.h"
118 #include "lbm_lbtrm_transport_dialog.h"
119 #include "lbm_lbtru_transport_dialog.h"
120 #include "lte_mac_statistics_dialog.h"
121 #include "lte_rlc_statistics_dialog.h"
122 #include "lte_rlc_graph_dialog.h"
123 #include "mtp3_summary_dialog.h"
124 #include "multicast_statistics_dialog.h"
125 #include "packet_comment_dialog.h"
126 #include "packet_dialog.h"
127 #include "packet_list.h"
128 #include "preferences_dialog.h"
129 #include "print_dialog.h"
130 #include "profile_dialog.h"
131 #include "protocol_hierarchy_dialog.h"
132 #include "qt_ui_utils.h"
133 #include "resolved_addresses_dialog.h"
134 #include "rpc_service_response_time_dialog.h"
135 #include "rtp_stream_dialog.h"
136 #include "rtp_analysis_dialog.h"
137 #include "sctp_all_assocs_dialog.h"
138 #include "sctp_assoc_analyse_dialog.h"
139 #include "sctp_graph_dialog.h"
140 #include "sequence_dialog.h"
141 #include "show_packet_bytes_dialog.h"
142 #include "stats_tree_dialog.h"
143 #include "stock_icon.h"
144 #include "supported_protocols_dialog.h"
145 #include "tap_parameter_dialog.h"
146 #include "tcp_stream_dialog.h"
147 #include "time_shift_dialog.h"
148 #include "uat_dialog.h"
149 #include "voip_calls_dialog.h"
150 #include "wireshark_application.h"
151 #include "wlan_statistics_dialog.h"
152
153 #include <QClipboard>
154 #include <QFileInfo>
155 #include <QMessageBox>
156 #include <QMetaObject>
157 #include <QToolBar>
158 #include <QDesktopServices>
159 #include <QUrl>
160
161 // XXX You must uncomment QT_WINEXTRAS_LIB lines in CMakeList.txt and
162 // cmakeconfig.h.in.
163 // #if defined(QT_WINEXTRAS_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
164 // #include <QWinJumpList>
165 // #include <QWinJumpListCategory>
166 // #include <QWinJumpListItem>
167 // #endif
168
169 //
170 // Public slots
171 //
172
173 static const char *dfe_property_ = "display filter expression"; //TODO : Fix Translate
174
175 bool MainWindow::openCaptureFile(QString cf_path, QString read_filter, unsigned int type)
176 {
177     QString file_name = "";
178     dfilter_t *rfcode = NULL;
179     gchar *err_msg;
180     int err;
181     gboolean name_param;
182     gboolean ret = true;
183
184     // was a file name given as function parameter?
185     name_param = !cf_path.isEmpty();
186
187     for (;;) {
188
189         if (cf_path.isEmpty()) {
190             CaptureFileDialog open_dlg(this, capture_file_.capFile(), read_filter);
191
192             if (open_dlg.open(file_name, type)) {
193                 cf_path = file_name;
194             } else {
195                 ret = false;
196                 goto finish;
197             }
198         }
199
200         QString before_what(tr(" before opening another file"));
201         if (!testCaptureFileClose(before_what)) {
202             ret = false;
203             goto finish;
204         }
205
206         if (dfilter_compile(read_filter.toUtf8().constData(), &rfcode, &err_msg)) {
207             cf_set_rfcode(CaptureFile::globalCapFile(), rfcode);
208         } else {
209             /* Not valid.  Tell the user, and go back and run the file
210                selection box again once they dismiss the alert. */
211             //bad_dfilter_alert_box(top_level, read_filter->str);
212             QMessageBox::warning(this, tr("Invalid Display Filter"),
213                     QString("The filter expression ") +
214                     read_filter +
215                     QString(" isn't a valid display filter. (") +
216                     err_msg + QString(")."),
217                     QMessageBox::Ok);
218
219             if (!name_param) {
220                 // go back to the selection dialogue only if the file
221                 // was selected from this dialogue
222                 cf_path.clear();
223                 continue;
224             }
225         }
226
227         /* Try to open the capture file. This closes the current file if it succeeds. */
228         CaptureFile::globalCapFile()->window = this;
229         if (cf_open(CaptureFile::globalCapFile(), cf_path.toUtf8().constData(), type, FALSE, &err) != CF_OK) {
230             /* We couldn't open it; don't dismiss the open dialog box,
231                just leave it around so that the user can, after they
232                dismiss the alert box popped up for the open error,
233                try again. */
234             CaptureFile::globalCapFile()->window = NULL;
235             if (rfcode != NULL)
236                 dfilter_free(rfcode);
237             cf_path.clear();
238             continue;
239         }
240
241         switch (cf_read(CaptureFile::globalCapFile(), FALSE)) {
242
243         case CF_READ_OK:
244         case CF_READ_ERROR:
245             /* Just because we got an error, that doesn't mean we were unable
246                to read any of the file; we handle what we could get from the
247                file. */
248             break;
249
250         case CF_READ_ABORTED:
251             /* The user bailed out of re-reading the capture file; the
252                capture file has been closed - just free the capture file name
253                string and return (without changing the last containing
254                directory). */
255             capture_file_.setCapFile(NULL);
256             ret = false;
257             goto finish;
258         }
259         break;
260     }
261     // get_dirname overwrites its path.
262     wsApp->setLastOpenDir(get_dirname(cf_path.toUtf8().data()));
263
264     main_ui_->statusBar->showExpert();
265
266 finish:
267 #ifdef HAVE_LIBPCAP
268     if (global_commandline_info.quit_after_cap)
269         exit(0);
270 #endif
271     return ret;
272 }
273
274 void MainWindow::filterPackets(QString new_filter, bool force)
275 {
276     cf_status_t cf_status;
277
278     cf_status = cf_filter_packets(CaptureFile::globalCapFile(), new_filter.toUtf8().data(), force);
279
280     if (cf_status == CF_OK) {
281         emit displayFilterSuccess(true);
282         if (new_filter.length() > 0) {
283             int index = df_combo_box_->findText(new_filter);
284             if (index == -1) {
285                 df_combo_box_->insertItem(0, new_filter);
286                 df_combo_box_->setCurrentIndex(0);
287             } else {
288                 df_combo_box_->setCurrentIndex(index);
289             }
290         } else {
291             df_combo_box_->lineEdit()->clear();
292         }
293     } else {
294         emit displayFilterSuccess(false);
295     }
296     if (packet_list_) {
297         packet_list_->resetColumns();
298     }
299 }
300
301 // A new layout should be applied when it differs from the old layout AND
302 // at the following times:
303 // - At startup
304 // - When the preferences change
305 // - When the profile changes
306 void MainWindow::layoutPanes()
307 {
308     QVector<unsigned> new_layout = QVector<unsigned>() << prefs.gui_layout_type
309                                                        << prefs.gui_layout_content_1
310                                                        << prefs.gui_layout_content_2
311                                                        << prefs.gui_layout_content_3
312                                                        << recent.packet_list_show
313                                                        << recent.tree_view_show
314                                                        << recent.byte_view_show;
315
316     if (cur_layout_ == new_layout) return;
317
318     QSplitter *parents[3];
319     int current_row = capture_file_.currentRow();
320
321     // Reparent all widgets and add them back in the proper order below.
322     // This hides each widget as well.
323     packet_list_->freeze(); // Clears tree and byte view tabs.
324     packet_list_->setParent(main_ui_->mainStack);
325     proto_tree_->setParent(main_ui_->mainStack);
326     byte_view_tab_->setParent(main_ui_->mainStack);
327     empty_pane_.setParent(main_ui_->mainStack);
328     extra_split_.setParent(main_ui_->mainStack);
329
330     // XXX We should try to preserve geometries if we can, e.g. by
331     // checking to see if the layout type is the same.
332     switch(prefs.gui_layout_type) {
333     case(layout_type_2):
334     case(layout_type_1):
335         extra_split_.setOrientation(Qt::Horizontal);
336         /* Fall Through */
337     case(layout_type_5):
338         master_split_.setOrientation(Qt::Vertical);
339         break;
340
341     case(layout_type_4):
342     case(layout_type_3):
343         extra_split_.setOrientation(Qt::Vertical);
344         /* Fall Through */
345     case(layout_type_6):
346         master_split_.setOrientation(Qt::Horizontal);
347         break;
348
349     default:
350         g_assert_not_reached();
351     }
352
353     switch(prefs.gui_layout_type) {
354     case(layout_type_5):
355     case(layout_type_6):
356         parents[0] = &master_split_;
357         parents[1] = &master_split_;
358         parents[2] = &master_split_;
359         break;
360     case(layout_type_2):
361     case(layout_type_4):
362         parents[0] = &master_split_;
363         parents[1] = &extra_split_;
364         parents[2] = &extra_split_;
365         break;
366     case(layout_type_1):
367     case(layout_type_3):
368         parents[0] = &extra_split_;
369         parents[1] = &extra_split_;
370         parents[2] = &master_split_;
371         break;
372     default:
373         g_assert_not_reached();
374     }
375
376     if (parents[0] == &extra_split_) {
377         master_split_.addWidget(&extra_split_);
378     }
379
380     parents[0]->addWidget(getLayoutWidget(prefs.gui_layout_content_1));
381
382     if (parents[2] == &extra_split_) {
383         master_split_.addWidget(&extra_split_);
384     }
385
386     parents[1]->addWidget(getLayoutWidget(prefs.gui_layout_content_2));
387     parents[2]->addWidget(getLayoutWidget(prefs.gui_layout_content_3));
388
389     const QList<QWidget *> ms_children = master_split_.findChildren<QWidget *>();
390
391     extra_split_.setVisible(ms_children.contains(&extra_split_));
392     packet_list_->setVisible(ms_children.contains(packet_list_) && recent.packet_list_show);
393     proto_tree_->setVisible(ms_children.contains(proto_tree_) && recent.tree_view_show);
394     byte_view_tab_->setVisible(ms_children.contains(byte_view_tab_) && recent.byte_view_show);
395
396     packet_list_->thaw();
397     cf_select_packet(capture_file_.capFile(), current_row);  // XXX Doesn't work for row 0?
398     cur_layout_ = new_layout;
399 }
400
401 // The recent layout geometry should be applied after the layout has been
402 // applied AND at the following times:
403 // - At startup
404 // - When the profile changes
405 void MainWindow::applyRecentPaneGeometry()
406 {
407     // XXX This shrinks slightly each time the application is run. For some
408     // reason the master_split_ geometry is two pixels shorter when
409     // saveWindowGeometry is invoked.
410
411     // This is also an awful lot of trouble to go through to reuse the GTK+
412     // pane settings. We might want to add gui.geometry_main_master_sizes
413     // and gui.geometry_main_extra_sizes and save QSplitter::saveState in
414     // each.
415
416     // Force a geometry recalculation
417     QWidget *cur_w = main_ui_->mainStack->currentWidget();
418     main_ui_->mainStack->setCurrentWidget(&master_split_);
419     QRect geom = master_split_.geometry();
420     QList<int> master_sizes = master_split_.sizes();
421     QList<int> extra_sizes = extra_split_.sizes();
422     main_ui_->mainStack->setCurrentWidget(cur_w);
423
424     int master_last_size = master_split_.orientation() == Qt::Vertical ? geom.height() : geom.width();
425     int extra_last_size = extra_split_.orientation() == Qt::Vertical ? geom.height() : geom.width();
426
427     if (recent.gui_geometry_main_upper_pane > 0) {
428         master_sizes[0] = recent.gui_geometry_main_upper_pane + 1; // Add back mystery pixel
429         master_last_size -= recent.gui_geometry_main_upper_pane + master_split_.handleWidth();
430     }
431
432     if (recent.gui_geometry_main_lower_pane > 0) {
433         if (master_sizes.length() > 2) {
434             master_sizes[1] = recent.gui_geometry_main_lower_pane + 1; // Add back mystery pixel
435             master_last_size -= recent.gui_geometry_main_lower_pane + master_split_.handleWidth();
436         } else if (extra_sizes.length() > 0) {
437             extra_sizes[0] = recent.gui_geometry_main_lower_pane; // No mystery pixel
438             extra_last_size -= recent.gui_geometry_main_lower_pane + extra_split_.handleWidth();
439             extra_sizes.last() = extra_last_size;
440         }
441     }
442
443     master_sizes.last() = master_last_size;
444
445     master_split_.setSizes(master_sizes);
446     extra_split_.setSizes(extra_sizes);
447 }
448
449 void MainWindow::layoutToolbars()
450 {
451     Qt::ToolButtonStyle tbstyle = Qt::ToolButtonIconOnly;
452     switch (prefs.gui_toolbar_main_style) {
453     case TB_STYLE_TEXT:
454         tbstyle = Qt::ToolButtonTextOnly;
455         break;
456     case TB_STYLE_BOTH:
457         tbstyle = Qt::ToolButtonTextUnderIcon;
458         break;
459     }
460
461     main_ui_->mainToolBar->setToolButtonStyle(tbstyle);
462
463     main_ui_->mainToolBar->setVisible(recent.main_toolbar_show);
464     main_ui_->displayFilterToolBar->setVisible(recent.filter_toolbar_show);
465     main_ui_->wirelessToolBar->setVisible(recent.wireless_toolbar_show);
466     main_ui_->statusBar->setVisible(recent.statusbar_show);
467 }
468
469 void MainWindow::updatePreferenceActions()
470 {
471     main_ui_->actionViewNameResolutionPhysical->setChecked(gbl_resolv_flags.mac_name);
472     main_ui_->actionViewNameResolutionNetwork->setChecked(gbl_resolv_flags.network_name);
473     main_ui_->actionViewNameResolutionTransport->setChecked(gbl_resolv_flags.transport_name);
474
475     // Should this be a "recent" setting?
476     main_ui_->actionGoAutoScroll->setChecked(prefs.capture_auto_scroll);
477 }
478
479 void MainWindow::updateRecentActions()
480 {
481     main_ui_->actionViewMainToolbar->setChecked(recent.main_toolbar_show);
482     main_ui_->actionViewFilterToolbar->setChecked(recent.filter_toolbar_show);
483     main_ui_->actionViewWirelessToolbar->setChecked(recent.wireless_toolbar_show);
484     main_ui_->actionViewStatusBar->setChecked(recent.statusbar_show);
485     main_ui_->actionViewPacketList->setChecked(recent.packet_list_show);
486     main_ui_->actionViewPacketDetails->setChecked(recent.tree_view_show);
487     main_ui_->actionViewPacketBytes->setChecked(recent.byte_view_show);
488
489     foreach (QAction* tda, td_actions.keys()) {
490         if (recent.gui_time_format == td_actions[tda]) {
491             tda->setChecked(true);
492         }
493     }
494     foreach (QAction* tpa, tp_actions.keys()) {
495         if (recent.gui_time_precision == tp_actions[tpa]) {
496             tpa->setChecked(true);
497             break;
498         }
499     }
500     main_ui_->actionViewTimeDisplaySecondsWithHoursAndMinutes->setChecked(recent.gui_seconds_format == TS_SECONDS_HOUR_MIN_SEC);
501
502     main_ui_->actionViewColorizePacketList->setChecked(recent.packet_list_colorize);
503 }
504
505 // Don't connect to this directly. Connect to or emit fiterAction(...) instead.
506 void MainWindow::queuedFilterAction(QString action_filter, FilterAction::Action action, FilterAction::ActionType type)
507 {
508     QString cur_filter, new_filter;
509
510     if (!df_combo_box_) return;
511     cur_filter = df_combo_box_->lineEdit()->text();
512
513     switch (type) {
514     case FilterAction::ActionTypePlain:
515         new_filter = action_filter;
516         break;
517     case FilterAction::ActionTypeAnd:
518         if (cur_filter.length()) {
519             new_filter = "(" + cur_filter + ") && (" + action_filter + ")";
520         } else {
521             new_filter = action_filter;
522         }
523         break;
524     case FilterAction::ActionTypeOr:
525         if (cur_filter.length()) {
526             new_filter = "(" + cur_filter + ") || (" + action_filter + ")";
527         } else {
528             new_filter = action_filter;
529         }
530         break;
531     case FilterAction::ActionTypeNot:
532         new_filter = "!(" + action_filter + ")";
533         break;
534     case FilterAction::ActionTypeAndNot:
535         if (cur_filter.length()) {
536             new_filter = "(" + cur_filter + ") && !(" + action_filter + ")";
537         } else {
538             new_filter = "!(" + action_filter + ")";
539         }
540         break;
541     case FilterAction::ActionTypeOrNot:
542         if (cur_filter.length()) {
543             new_filter = "(" + cur_filter + ") || !(" + action_filter + ")";
544         } else {
545             new_filter = "!(" + action_filter + ")";
546         }
547         break;
548     default:
549         g_assert_not_reached();
550         break;
551     }
552
553     switch(action) {
554     case FilterAction::ActionApply:
555         df_combo_box_->lineEdit()->setText(new_filter);
556         df_combo_box_->applyDisplayFilter();
557         break;
558     case FilterAction::ActionColorize:
559         colorizeWithFilter(new_filter.toUtf8());
560         break;
561     case FilterAction::ActionCopy:
562         wsApp->clipboard()->setText(new_filter);
563         break;
564     case FilterAction::ActionFind:
565         main_ui_->searchFrame->findFrameWithFilter(new_filter);
566         break;
567     case FilterAction::ActionPrepare:
568         df_combo_box_->lineEdit()->setText(new_filter);
569         df_combo_box_->lineEdit()->setFocus();
570         break;
571     case FilterAction::ActionWebLookup:
572     {
573         QString url = QString("https://www.google.com/search?q=") + new_filter;
574         QDesktopServices::openUrl(QUrl(url));
575         break;
576     }
577     default:
578         g_assert_not_reached();
579         break;
580     }
581 }
582
583 // Capture callbacks
584
585 void MainWindow::captureCapturePrepared(capture_session *) {
586 #ifdef HAVE_LIBPCAP
587     setTitlebarForCaptureInProgress();
588
589     setWindowIcon(wsApp->captureIcon());
590
591     /* Disable menu items that make no sense if you're currently running
592        a capture. */
593     setForCaptureInProgress(true);
594 //    set_capture_if_dialog_for_capture_in_progress(TRUE);
595
596 //    /* Don't set up main window for a capture file. */
597 //    main_set_for_capture_file(FALSE);
598     main_ui_->mainStack->setCurrentWidget(&master_split_);
599 #endif // HAVE_LIBPCAP
600 }
601
602 void MainWindow::captureCaptureUpdateStarted(capture_session *) {
603 #ifdef HAVE_LIBPCAP
604
605     /* We've done this in "prepared" above, but it will be cleared while
606        switching to the next multiple file. */
607     setTitlebarForCaptureInProgress();
608
609     setForCaptureInProgress(true);
610
611     setForCapturedPackets(true);
612 #endif // HAVE_LIBPCAP
613 }
614 void MainWindow::captureCaptureUpdateFinished(capture_session *) {
615 #ifdef HAVE_LIBPCAP
616
617     /* The capture isn't stopping any more - it's stopped. */
618     capture_stopping_ = false;
619
620     /* Update the main window as appropriate */
621     updateForUnsavedChanges();
622
623     /* Enable menu items that make sense if you're not currently running
624      a capture. */
625     setForCaptureInProgress(false);
626     setMenusForCaptureFile();
627
628     setWindowIcon(wsApp->normalIcon());
629
630     if (global_commandline_info.quit_after_cap) {
631         // Command line asked us to quit after capturing.
632         // Don't pop up a dialog to ask for unsaved files etc.
633         exit(0);
634     }
635 #endif // HAVE_LIBPCAP
636 }
637 void MainWindow::captureCaptureFixedStarted(capture_session *) {
638 #ifdef HAVE_LIBPCAP
639 #endif // HAVE_LIBPCAP
640 }
641 void MainWindow::captureCaptureFixedFinished(capture_session *) {
642 #ifdef HAVE_LIBPCAP
643
644     /* The capture isn't stopping any more - it's stopped. */
645     capture_stopping_ = false;
646
647     /* Enable menu items that make sense if you're not currently running
648      a capture. */
649     setForCaptureInProgress(false);
650     setMenusForCaptureFile();
651
652     setWindowIcon(wsApp->normalIcon());
653
654     if (global_commandline_info.quit_after_cap) {
655         // Command line asked us to quit after capturing.
656         // Don't pop up a dialog to ask for unsaved files etc.
657         exit(0);
658     }
659 #endif // HAVE_LIBPCAP
660 }
661 void MainWindow::captureCaptureStopping(capture_session *) {
662 #ifdef HAVE_LIBPCAP
663
664     capture_stopping_ = true;
665     setMenusForCaptureStopping();
666 #endif // HAVE_LIBPCAP
667 }
668 void MainWindow::captureCaptureFailed(capture_session *) {
669 #ifdef HAVE_LIBPCAP
670     /* Capture isn't stopping any more. */
671     capture_stopping_ = false;
672
673     setForCaptureInProgress(false);
674     main_ui_->mainStack->setCurrentWidget(main_welcome_);
675
676     // Reset expert information indicator
677     main_ui_->statusBar->captureFileClosing();
678     main_ui_->statusBar->popFileStatus();
679
680     setWindowIcon(wsApp->normalIcon());
681
682     if (global_commandline_info.quit_after_cap) {
683         // Command line asked us to quit after capturing.
684         // Don't pop up a dialog to ask for unsaved files etc.
685         exit(0);
686     }
687 #endif // HAVE_LIBPCAP
688 }
689
690
691 // Callbacks from cfile.c and file.c via CaptureFile::captureFileCallback
692
693 void MainWindow::captureFileOpened() {
694     if (capture_file_.window() != this) return;
695
696     file_set_dialog_->fileOpened(capture_file_.capFile());
697     setMenusForFileSet(true);
698     emit setCaptureFile(capture_file_.capFile());
699 }
700
701 void MainWindow::captureFileReadStarted(const QString &action) {
702 //    tap_param_dlg_update();
703
704     /* Set up main window for a capture file. */
705 //    main_set_for_capture_file(TRUE);
706
707     main_ui_->statusBar->popFileStatus();
708     QString msg = QString(tr("%1: %2")).arg(action).arg(capture_file_.fileName());
709     QString msgtip = QString();
710     main_ui_->statusBar->pushFileStatus(msg, msgtip);
711     main_ui_->mainStack->setCurrentWidget(&master_split_);
712     main_ui_->actionAnalyzeReloadLuaPlugins->setEnabled(false);
713
714     WiresharkApplication::processEvents();
715 }
716
717 void MainWindow::captureFileReadFinished() {
718     gchar *dir_path;
719
720     if (!capture_file_.capFile()->is_tempfile && capture_file_.capFile()->filename) {
721         /* Add this filename to the list of recent files in the "Recent Files" submenu */
722         add_menu_recent_capture_file(capture_file_.capFile()->filename);
723
724         /* Remember folder for next Open dialog and save it in recent */
725         dir_path = g_strdup(capture_file_.capFile()->filename);
726         wsApp->setLastOpenDir(get_dirname(dir_path));
727         g_free(dir_path);
728     }
729
730     /* Update the appropriate parts of the main window. */
731     updateForUnsavedChanges();
732
733     /* Enable menu items that make sense if you have some captured packets. */
734     setForCapturedPackets(true);
735
736     main_ui_->statusBar->setFileName(capture_file_);
737     main_ui_->actionAnalyzeReloadLuaPlugins->setEnabled(true);
738
739     packet_list_->captureFileReadFinished();
740
741     emit setDissectedCaptureFile(capture_file_.capFile());
742 }
743
744 void MainWindow::captureFileRetapStarted()
745 {
746     // XXX Push a status message?
747     freeze();
748 }
749
750 void MainWindow::captureFileRetapFinished()
751 {
752     thaw();
753 }
754
755 void MainWindow::captureFileFlushTapsData()
756 {
757     draw_tap_listeners(FALSE);
758 }
759
760 void MainWindow::captureFileClosing() {
761     setMenusForCaptureFile(true);
762     setForCapturedPackets(false);
763     setForCaptureInProgress(false);
764
765     // Reset expert information indicator
766     main_ui_->statusBar->captureFileClosing();
767     main_ui_->searchFrame->animatedHide();
768 //    gtk_widget_show(expert_info_none);
769     emit setCaptureFile(NULL);
770     emit setDissectedCaptureFile(NULL);
771 }
772
773 void MainWindow::captureFileClosed() {
774     packets_bar_update();
775
776     file_set_dialog_->fileClosed();
777     setMenusForFileSet(false);
778     setWindowModified(false);
779
780     // Reset expert information indicator
781     main_ui_->statusBar->captureFileClosing();
782     main_ui_->statusBar->popFileStatus();
783
784     setWSWindowTitle();
785     setWindowIcon(wsApp->normalIcon());
786     setMenusForSelectedPacket();
787     setMenusForSelectedTreeRow();
788
789 #ifdef HAVE_LIBPCAP
790     if (!global_capture_opts.multi_files_on)
791         main_ui_->mainStack->setCurrentWidget(main_welcome_);
792 #endif
793 }
794
795 void MainWindow::captureFileSaveStarted(const QString &file_path)
796 {
797     QFileInfo file_info(file_path);
798     main_ui_->statusBar->popFileStatus();
799     main_ui_->statusBar->pushFileStatus(tr("Saving %1" UTF8_HORIZONTAL_ELLIPSIS).arg(file_info.baseName()));
800 }
801
802 void MainWindow::filterExpressionsChanged()
803 {
804     // Recreate filter buttons
805     foreach (QAction *act, filter_expression_toolbar_->actions()) {
806         // Permanent actions shouldn't have data
807         if (act->property(dfe_property_).isValid()) {
808             filter_expression_toolbar_->removeAction(act);
809             delete act;
810         }
811     }
812
813     // XXX Add a context menu for removing and changing buttons.
814     for (struct filter_expression *fe = *pfilter_expression_head; fe != NULL; fe = fe->next) {
815         if (!fe->enabled) continue;
816         QAction *dfb_action = new QAction(fe->label, filter_expression_toolbar_);
817         dfb_action->setToolTip(fe->expression);
818         dfb_action->setData(fe->expression);
819         dfb_action->setProperty(dfe_property_, true);
820         filter_expression_toolbar_->addAction(dfb_action);
821         connect(dfb_action, SIGNAL(triggered()), this, SLOT(displayFilterButtonClicked()));
822     }
823     main_ui_->displayFilterToolBar->adjustSize();
824 }
825
826 //
827 // Private slots
828 //
829
830 // ui/gtk/capture_dlg.c:start_capture_confirmed
831
832 void MainWindow::startCapture() {
833 #ifdef HAVE_LIBPCAP
834     interface_options interface_opts;
835     guint i;
836
837     /* did the user ever select a capture interface before? */
838     if(global_capture_opts.num_selected == 0) {
839         QString msg = QString(tr("No interface selected"));
840         main_ui_->statusBar->pushTemporaryStatus(msg);
841         main_ui_->actionCaptureStart->setChecked(false);
842         return;
843     }
844
845     // Ideally we should have disabled the start capture
846     // toolbar buttons and menu items. This may not be the
847     // case, e.g. with QtMacExtras.
848     if(!capture_filter_valid_) {
849         QString msg = QString(tr("Invalid capture filter"));
850         main_ui_->statusBar->pushTemporaryStatus(msg);
851         main_ui_->actionCaptureStart->setChecked(false);
852         return;
853     }
854
855     main_ui_->mainStack->setCurrentWidget(&master_split_);
856
857     /* XXX - we might need to init other pref data as well... */
858
859     /* XXX - can this ever happen? */
860     if (cap_session_.state != CAPTURE_STOPPED)
861       return;
862
863     /* close the currently loaded capture file */
864     cf_close((capture_file *) cap_session_.cf);
865
866     /* Copy the selected interfaces to the set of interfaces to use for
867        this capture. */
868     collect_ifaces(&global_capture_opts);
869
870     CaptureFile::globalCapFile()->window = this;
871     if (capture_start(&global_capture_opts, &cap_session_, &info_data_, main_window_update)) {
872         capture_options *capture_opts = cap_session_.capture_opts;
873         GString *interface_names;
874
875         /* Add "interface name<live capture in progress>" on main status bar */
876         interface_names = get_iface_list_string(capture_opts, 0);
877         if (strlen (interface_names->str) > 0) {
878             g_string_append(interface_names, ":");
879         }
880         g_string_append(interface_names, " ");
881
882         main_ui_->statusBar->popFileStatus();
883         QString msg = QString().sprintf("%s<live capture in progress>", interface_names->str);
884         QString msgtip = QString().sprintf("to file: %s", (capture_opts->save_file) ? capture_opts->save_file : "");
885         main_ui_->statusBar->pushFileStatus(msg, msgtip);
886         g_string_free(interface_names, TRUE);
887
888         /* The capture succeeded, which means the capture filter syntax is
889          valid; add this capture filter to the recent capture filter list. */
890         QByteArray filter_ba;
891         for (i = 0; i < global_capture_opts.ifaces->len; i++) {
892             interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
893             if (interface_opts.cfilter) {
894                 recent_add_cfilter(interface_opts.name, interface_opts.cfilter);
895                 if (filter_ba.isEmpty()) {
896                     filter_ba = interface_opts.cfilter;
897                 } else {
898                     /* Not the first selected interface; is its capture filter
899                        the same as the one the other interfaces we've looked
900                        at have? */
901                     if (strcmp(interface_opts.cfilter, filter_ba.constData()) != 0) {
902                       /* No, so not all selected interfaces have the same capture
903                          filter. */
904                         filter_ba.clear();
905                     }
906                 }
907             }
908         }
909         if (!filter_ba.isEmpty()) {
910             recent_add_cfilter(NULL, filter_ba.constData());
911         }
912     } else {
913         CaptureFile::globalCapFile()->window = NULL;
914     }
915 #endif // HAVE_LIBPCAP
916 }
917
918 // Copied from ui/gtk/gui_utils.c
919 void MainWindow::pipeTimeout() {
920 #ifdef _WIN32
921     HANDLE handle;
922     DWORD avail = 0;
923     gboolean result, result1;
924     DWORD childstatus;
925     gint iterations = 0;
926
927
928     /* try to read data from the pipe only 5 times, to avoid blocking */
929     while(iterations < 5) {
930         /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: new iteration");*/
931
932         /* Oddly enough although Named pipes don't work on win9x,
933            PeekNamedPipe does !!! */
934         handle = (HANDLE) _get_osfhandle (pipe_source_);
935         result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
936
937         /* Get the child process exit status */
938         result1 = GetExitCodeProcess((HANDLE)*(pipe_child_process_),
939                                      &childstatus);
940
941         /* If the Peek returned an error, or there are bytes to be read
942            or the childwatcher thread has terminated then call the normal
943            callback */
944         if (!result || avail > 0 || childstatus != STILL_ACTIVE) {
945
946             /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: data avail");*/
947
948             /* And call the real handler */
949             if (!pipe_input_cb_(pipe_source_, pipe_user_data_)) {
950                 g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: input pipe closed, iterations: %u", iterations);
951                 /* pipe closed, return false so that the old timer is not run again */
952                 delete pipe_timer_;
953                 return;
954             }
955         }
956         else {
957             /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: no data avail");*/
958             /* No data, stop now */
959             break;
960         }
961
962         iterations++;
963     }
964 #endif // _WIN32
965 }
966
967 void MainWindow::pipeActivated(int source) {
968 #ifdef _WIN32
969     Q_UNUSED(source);
970 #else
971     g_assert(source == pipe_source_);
972
973     pipe_notifier_->setEnabled(false);
974     if (pipe_input_cb_(pipe_source_, pipe_user_data_)) {
975         pipe_notifier_->setEnabled(true);
976     } else {
977         delete pipe_notifier_;
978     }
979 #endif // _WIN32
980 }
981
982 void MainWindow::pipeNotifierDestroyed()
983 {
984     /* Pop the "<live capture in progress>" message off the status bar. */
985     main_ui_->statusBar->setFileName(capture_file_);
986
987 #ifdef _WIN32
988     pipe_timer_ = NULL;
989 #else
990     pipe_notifier_ = NULL;
991 #endif // _WIN32
992 }
993
994 void MainWindow::stopCapture() {
995 //#ifdef HAVE_AIRPCAP
996 //  if (airpcap_if_active)
997 //    airpcap_set_toolbar_stop_capture(airpcap_if_active);
998 //#endif
999
1000 #ifdef HAVE_LIBPCAP
1001     capture_stop(&cap_session_);
1002 #endif // HAVE_LIBPCAP
1003
1004 }
1005
1006 // Keep focus rects from showing through the welcome screen. Primarily for
1007 // OS X.
1008 void MainWindow::mainStackChanged(int)
1009 {
1010     for (int i = 0; i < main_ui_->mainStack->count(); i++) {
1011         main_ui_->mainStack->widget(i)->setEnabled(i == main_ui_->mainStack->currentIndex());
1012     }
1013 }
1014
1015 // XXX - Copied from ui/gtk/menus.c
1016
1017 /**
1018  * Add the capture filename (with an absolute path) to the "Recent Files" menu.
1019  */
1020 // XXX - We should probably create a RecentFile class.
1021 void MainWindow::updateRecentFiles() {
1022     QAction *ra;
1023     QMenu *recentMenu = main_ui_->menuOpenRecentCaptureFile;
1024     QString action_cf_name;
1025
1026     if (!recentMenu) {
1027         return;
1028     }
1029     recentMenu->clear();
1030
1031 // #if defined(QT_WINEXTRAS_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
1032 //     QWinJumpList recent_jl(this);
1033 //     QWinJumpListCategory *recent_jlc = recent_jl.recent();
1034 //     if (recent_jlc) {
1035 //         recent_jlc->clear();
1036 //         recent_jlc->setVisible(true);
1037 //     }
1038 // #endif
1039 #if defined(Q_OS_MAC) && QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
1040     if (!dock_menu_) {
1041         dock_menu_ = new QMenu();
1042         dock_menu_->setAsDockMenu();
1043     }
1044     dock_menu_->clear();
1045 #endif
1046
1047     /* Iterate through the actions in menuOpenRecentCaptureFile,
1048      * removing special items, a maybe duplicate entry and every item above count_max */
1049     int shortcut = Qt::Key_0;
1050     foreach (recent_item_status *ri, wsApp->recentItems()) {
1051         // Add the new item
1052         ra = new QAction(recentMenu);
1053         ra->setData(ri->filename);
1054         // XXX - Needs get_recent_item_status or equivalent
1055         ra->setEnabled(ri->accessible);
1056         recentMenu->insertAction(NULL, ra);
1057         action_cf_name = ra->data().toString();
1058         if (shortcut <= Qt::Key_9) {
1059             ra->setShortcut(Qt::META | shortcut);
1060             shortcut++;
1061         }
1062         ra->setText(action_cf_name);
1063         connect(ra, SIGNAL(triggered()), this, SLOT(recentActionTriggered()));
1064
1065 // This is slow, at least on my VM here. The added links also open Wireshark
1066 // in a new window. It might make more sense to add a recent item when we
1067 // open a capture file.
1068 // #if defined(QT_WINEXTRAS_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
1069 //     if (recent_jlc) {
1070 //         QFileInfo fi(ri->filename);
1071 //         QWinJumpListItem *jli = recent_jlc->addLink(
1072 //             fi.fileName(),
1073 //             QApplication::applicationFilePath(),
1074 //             QStringList() << "-r" << ri->filename
1075 //         );
1076 //         // XXX set icon
1077 //         jli->setWorkingDirectory(QDir::toNativeSeparators(QApplication::applicationDirPath()));
1078 //     }
1079 // #endif
1080 #if defined(Q_OS_MAC) && QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
1081         QAction *rda = new QAction(dock_menu_);
1082         QFileInfo fi(ri->filename);
1083         rda->setText(fi.fileName());
1084         dock_menu_->insertAction(NULL, rda);
1085         connect(rda, SIGNAL(triggered()), ra, SLOT(trigger()));
1086 #endif
1087     }
1088
1089     if (recentMenu->actions().count() > 0) {
1090         // Separator + "Clear"
1091         // XXX - Do we really need this?
1092         ra = new QAction(recentMenu);
1093         ra->setSeparator(true);
1094         recentMenu->insertAction(NULL, ra);
1095
1096         ra = new QAction(recentMenu);
1097         ra->setText(tr("Clear Menu"));
1098         recentMenu->insertAction(NULL, ra);
1099         connect(ra, SIGNAL(triggered()), wsApp, SLOT(clearRecentItems()));
1100     } else {
1101         if (main_ui_->actionDummyNoFilesFound) {
1102             recentMenu->addAction(main_ui_->actionDummyNoFilesFound);
1103         }
1104     }
1105 }
1106
1107 void MainWindow::recentActionTriggered() {
1108     QAction *ra = qobject_cast<QAction*>(sender());
1109
1110     if (ra) {
1111         QString cfPath = ra->data().toString();
1112         openCaptureFile(cfPath);
1113     }
1114 }
1115
1116 void MainWindow::setMenusForSelectedPacket()
1117 {
1118     gboolean is_ip = FALSE, is_tcp = FALSE, is_udp = FALSE, is_sctp = FALSE, is_ssl = FALSE, is_rtp = FALSE, is_lte_rlc = FALSE, is_http = FALSE;
1119
1120     /* Making the menu context-sensitive allows for easier selection of the
1121        desired item and has the added benefit, with large captures, of
1122        avoiding needless looping through huge lists for marked, ignored,
1123        or time-referenced packets. */
1124
1125     /* We have one or more items in the packet list */
1126     bool have_frames = false;
1127     /* A frame is selected */
1128     bool frame_selected = false;
1129     /* We have marked frames.  (XXX - why check frame_selected?) */
1130     bool have_marked = false;
1131     /* We have a marked frame other than the current frame (i.e.,
1132        we have at least one marked frame, and either there's more
1133        than one marked frame or the current frame isn't marked). */
1134     bool another_is_marked = false;
1135     /* One or more frames are hidden by a display filter */
1136     bool have_filtered = false;
1137     /* One or more frames have been ignored */
1138     bool have_ignored = false;
1139     bool have_time_ref = false;
1140     /* We have a time reference frame other than the current frame (i.e.,
1141        we have at least one time reference frame, and either there's more
1142        than one time reference frame or the current frame isn't a
1143        time reference frame). (XXX - why check frame_selected?) */
1144     bool another_is_time_ref = false;
1145     /* We have a valid filter expression */
1146     bool have_filter_expr = false;
1147
1148     QList<QAction *> cc_actions = QList<QAction *>()
1149             << main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
1150             << main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
1151             << main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
1152             << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
1153             << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
1154
1155     if (capture_file_.capFile()) {
1156         frame_selected = capture_file_.capFile()->current_frame != NULL;
1157         have_frames = capture_file_.capFile()->count > 0;
1158         have_marked = frame_selected && capture_file_.capFile()->marked_count > 0;
1159         another_is_marked = have_marked &&
1160                 !(capture_file_.capFile()->marked_count == 1 && capture_file_.capFile()->current_frame->flags.marked);
1161         have_filtered = capture_file_.capFile()->displayed_count > 0 && capture_file_.capFile()->displayed_count != capture_file_.capFile()->count;
1162         have_ignored = capture_file_.capFile()->ignored_count > 0;
1163         have_time_ref = capture_file_.capFile()->ref_time_count > 0;
1164         another_is_time_ref = frame_selected && have_time_ref &&
1165                 !(capture_file_.capFile()->ref_time_count == 1 && capture_file_.capFile()->current_frame->flags.ref_time);
1166
1167         if (capture_file_.capFile()->edt)
1168         {
1169             proto_get_frame_protocols(capture_file_.capFile()->edt->pi.layers,
1170                                       &is_ip, &is_tcp, &is_udp, &is_sctp,
1171                                       &is_ssl, &is_rtp, &is_lte_rlc);
1172             is_http = proto_is_frame_protocol(capture_file_.capFile()->edt->pi.layers, "http");
1173         }
1174     }
1175
1176     have_filter_expr = !packet_list_->getFilterFromRowAndColumn().isEmpty();
1177
1178     main_ui_->actionEditMarkPacket->setEnabled(frame_selected);
1179     main_ui_->actionEditMarkAllDisplayed->setEnabled(have_frames);
1180     /* Unlike un-ignore, do not allow unmark of all frames when no frames are displayed  */
1181     main_ui_->actionEditUnmarkAllDisplayed->setEnabled(have_marked);
1182     main_ui_->actionEditNextMark->setEnabled(another_is_marked);
1183     main_ui_->actionEditPreviousMark->setEnabled(another_is_marked);
1184
1185 #ifdef WANT_PACKET_EDITOR
1186 //    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/EditPacket",
1187 //                         frame_selected);
1188 #endif // WANT_PACKET_EDITOR
1189     main_ui_->actionEditPacketComment->setEnabled(frame_selected && wtap_dump_can_write(capture_file_.capFile()->linktypes, WTAP_COMMENT_PER_PACKET));
1190
1191     main_ui_->actionEditIgnorePacket->setEnabled(frame_selected);
1192     main_ui_->actionEditIgnoreAllDisplayed->setEnabled(have_filtered);
1193     /* Allow un-ignore of all frames even with no frames currently displayed */
1194     main_ui_->actionEditUnignoreAllDisplayed->setEnabled(have_ignored);
1195
1196     main_ui_->actionEditSetTimeReference->setEnabled(frame_selected);
1197     main_ui_->actionEditUnsetAllTimeReferences->setEnabled(have_time_ref);
1198     main_ui_->actionEditNextTimeReference->setEnabled(another_is_time_ref);
1199     main_ui_->actionEditPreviousTimeReference->setEnabled(another_is_time_ref);
1200     main_ui_->actionEditTimeShift->setEnabled(have_frames);
1201
1202     main_ui_->actionGoGoToLinkedPacket->setEnabled(false);
1203
1204     main_ui_->actionAnalyzeAAFSelected->setEnabled(have_filter_expr);
1205     main_ui_->actionAnalyzeAAFNotSelected->setEnabled(have_filter_expr);
1206     main_ui_->actionAnalyzeAAFAndSelected->setEnabled(have_filter_expr);
1207     main_ui_->actionAnalyzeAAFOrSelected->setEnabled(have_filter_expr);
1208     main_ui_->actionAnalyzeAAFAndNotSelected->setEnabled(have_filter_expr);
1209     main_ui_->actionAnalyzeAAFOrNotSelected->setEnabled(have_filter_expr);
1210
1211     main_ui_->actionAnalyzePAFSelected->setEnabled(have_filter_expr);
1212     main_ui_->actionAnalyzePAFNotSelected->setEnabled(have_filter_expr);
1213     main_ui_->actionAnalyzePAFAndSelected->setEnabled(have_filter_expr);
1214     main_ui_->actionAnalyzePAFOrSelected->setEnabled(have_filter_expr);
1215     main_ui_->actionAnalyzePAFAndNotSelected->setEnabled(have_filter_expr);
1216     main_ui_->actionAnalyzePAFOrNotSelected->setEnabled(have_filter_expr);
1217
1218     main_ui_->actionAnalyzeFollowTCPStream->setEnabled(is_tcp);
1219     main_ui_->actionAnalyzeFollowUDPStream->setEnabled(is_udp);
1220     main_ui_->actionAnalyzeFollowSSLStream->setEnabled(is_ssl);
1221     main_ui_->actionAnalyzeFollowHTTPStream->setEnabled(is_http);
1222
1223     foreach (QAction *cc_action, cc_actions) {
1224         cc_action->setEnabled(frame_selected);
1225     }
1226     main_ui_->actionViewColorizeNewColoringRule->setEnabled(frame_selected);
1227
1228     main_ui_->actionViewColorizeResetColorization->setEnabled(tmp_color_filters_used());
1229
1230     main_ui_->actionViewShowPacketInNewWindow->setEnabled(frame_selected);
1231     main_ui_->actionViewEditResolvedName->setEnabled(frame_selected && is_ip);
1232
1233     emit packetInfoChanged(capture_file_.packetInfo());
1234
1235 //    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/NameResolution/ResolveName",
1236 //                         frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
1237 //                                            gbl_resolv_flags.transport_name));
1238
1239     main_ui_->actionToolsFirewallAclRules->setEnabled(frame_selected);
1240
1241     main_ui_->actionStatisticsTcpStreamRoundTripTime->setEnabled(is_tcp);
1242     main_ui_->actionStatisticsTcpStreamStevens->setEnabled(is_tcp);
1243     main_ui_->actionStatisticsTcpStreamTcptrace->setEnabled(is_tcp);
1244     main_ui_->actionStatisticsTcpStreamThroughput->setEnabled(is_tcp);
1245     main_ui_->actionStatisticsTcpStreamWindowScaling->setEnabled(is_tcp);
1246
1247     main_ui_->actionSCTPAnalyseThisAssociation->setEnabled(is_sctp);
1248     main_ui_->actionSCTPShowAllAssociations->setEnabled(is_sctp);
1249     main_ui_->actionSCTPFilterThisAssociation->setEnabled(is_sctp);
1250     main_ui_->actionTelephonyRTPStreamAnalysis->setEnabled(is_rtp);
1251     main_ui_->actionTelephonyLteRlcGraph->setEnabled(is_lte_rlc);
1252 }
1253
1254 void MainWindow::setMenusForSelectedTreeRow(field_info *fi) {
1255
1256     bool can_match_selected = false;
1257     bool is_framenum = false;
1258     bool have_field_info = false;
1259     bool have_subtree = false;
1260     bool can_open_url = false;
1261     QByteArray field_filter;
1262     int field_id = -1;
1263
1264     if (capture_file_.capFile()) {
1265         capture_file_.capFile()->finfo_selected = fi;
1266
1267         if (fi && fi->tree_type != -1) {
1268             have_subtree = true;
1269         }
1270     }
1271
1272     if (capture_file_.capFile() != NULL && fi != NULL) {
1273         header_field_info *hfinfo = fi->hfinfo;
1274         int linked_frame = -1;
1275
1276         have_field_info = true;
1277         can_match_selected = proto_can_match_selected(capture_file_.capFile()->finfo_selected, capture_file_.capFile()->edt);
1278         if (hfinfo && hfinfo->type == FT_FRAMENUM) {
1279             is_framenum = true;
1280             linked_frame = fvalue_get_uinteger(&fi->value);
1281         }
1282
1283         char *tmp_field = proto_construct_match_selected_string(fi, capture_file_.capFile()->edt);
1284         field_filter = tmp_field;
1285         wmem_free(NULL, tmp_field);
1286
1287         field_id = fi->hfinfo->id;
1288         /* if the selected field isn't a protocol, get its parent */
1289         if (!proto_registrar_is_protocol(field_id)) {
1290             field_id = proto_registrar_get_parent(fi->hfinfo->id);
1291         }
1292
1293         if (field_id >= 0) {
1294             can_open_url = true;
1295             main_ui_->actionContextWikiProtocolPage->setData(field_id);
1296             main_ui_->actionContextFilterFieldReference->setData(field_id);
1297         } else {
1298             main_ui_->actionContextWikiProtocolPage->setData(QVariant());
1299             main_ui_->actionContextFilterFieldReference->setData(QVariant());
1300         }
1301
1302         if (linked_frame > 0) {
1303             main_ui_->actionGoGoToLinkedPacket->setData(linked_frame);
1304         } else {
1305             main_ui_->actionGoGoToLinkedPacket->setData(QVariant());
1306         }
1307     }
1308
1309     // Always enable / disable the following items.
1310     main_ui_->actionFileExportPacketBytes->setEnabled(have_field_info);
1311
1312     main_ui_->actionCopyAllVisibleItems->setEnabled(capture_file_.capFile() != NULL);
1313     main_ui_->actionCopyAllVisibleSelectedTreeItems->setEnabled(can_match_selected);
1314     main_ui_->actionEditCopyDescription->setEnabled(can_match_selected);
1315     main_ui_->actionEditCopyFieldName->setEnabled(can_match_selected);
1316     main_ui_->actionEditCopyValue->setEnabled(can_match_selected);
1317     main_ui_->actionEditCopyAsFilter->setEnabled(can_match_selected);
1318
1319     main_ui_->actionViewExpandSubtrees->setEnabled(have_subtree);
1320
1321     main_ui_->actionGoGoToLinkedPacket->setEnabled(is_framenum);
1322
1323     main_ui_->actionAnalyzeCreateAColumn->setEnabled(can_match_selected);
1324
1325     main_ui_->actionContextShowLinkedPacketInNewWindow->setEnabled(is_framenum);
1326
1327     main_ui_->actionContextWikiProtocolPage->setEnabled(can_open_url);
1328     main_ui_->actionContextFilterFieldReference->setEnabled(can_open_url);
1329
1330
1331     // Only enable / disable the following items if we have focus so that we
1332     // don't clobber anything we may have set in setMenusForSelectedPacket.
1333     if (!proto_tree_ || !proto_tree_->hasFocus()) return;
1334
1335     emit packetInfoChanged(capture_file_.packetInfo());
1336     emit fieldFilterChanged(field_filter);
1337
1338 //    set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ResolveName",
1339 //                         frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
1340 //                                            gbl_resolv_flags.transport_name));
1341
1342     main_ui_->actionAnalyzeAAFSelected->setEnabled(can_match_selected);
1343     main_ui_->actionAnalyzeAAFNotSelected->setEnabled(can_match_selected);
1344     main_ui_->actionAnalyzeAAFAndSelected->setEnabled(can_match_selected);
1345     main_ui_->actionAnalyzeAAFOrSelected->setEnabled(can_match_selected);
1346     main_ui_->actionAnalyzeAAFAndNotSelected->setEnabled(can_match_selected);
1347     main_ui_->actionAnalyzeAAFOrNotSelected->setEnabled(can_match_selected);
1348
1349     main_ui_->actionAnalyzePAFSelected->setEnabled(can_match_selected);
1350     main_ui_->actionAnalyzePAFNotSelected->setEnabled(can_match_selected);
1351     main_ui_->actionAnalyzePAFAndSelected->setEnabled(can_match_selected);
1352     main_ui_->actionAnalyzePAFOrSelected->setEnabled(can_match_selected);
1353     main_ui_->actionAnalyzePAFAndNotSelected->setEnabled(can_match_selected);
1354     main_ui_->actionAnalyzePAFOrNotSelected->setEnabled(can_match_selected);
1355 }
1356
1357 void MainWindow::interfaceSelectionChanged()
1358 {
1359 #ifdef HAVE_LIBPCAP
1360     // XXX This doesn't disable the toolbar button when using
1361     // QtMacExtras.
1362     if (global_capture_opts.num_selected > 0 && capture_filter_valid_) {
1363         main_ui_->actionCaptureStart->setEnabled(true);
1364     } else {
1365         main_ui_->actionCaptureStart->setEnabled(false);
1366     }
1367 #endif // HAVE_LIBPCAP
1368 }
1369
1370 void MainWindow::captureFilterSyntaxChanged(bool valid)
1371 {
1372     capture_filter_valid_ = valid;
1373     interfaceSelectionChanged();
1374 }
1375
1376 void MainWindow::startInterfaceCapture(bool valid, const QString capture_filter)
1377 {
1378     capture_filter_valid_ = valid;
1379     main_welcome_->setCaptureFilter(capture_filter);
1380     // The interface tree will update the selected interfaces via its timer
1381     // so no need to do anything here.
1382     startCapture();
1383 }
1384
1385 void MainWindow::applyGlobalCommandLineOptions()
1386 {
1387     if (global_commandline_info.time_format != TS_NOT_SET) {
1388         foreach (QAction* tda, td_actions.keys()) {
1389             if (global_commandline_info.time_format == td_actions[tda]) {
1390                 tda->setChecked(true);
1391                 recent.gui_time_format = global_commandline_info.time_format;
1392                 timestamp_set_type(global_commandline_info.time_format);
1393                 break;
1394             }
1395         }
1396     }
1397 }
1398
1399 void MainWindow::redissectPackets()
1400 {
1401     if (capture_file_.capFile()) {
1402         cf_redissect_packets(capture_file_.capFile());
1403         main_ui_->statusBar->expertUpdate();
1404     }
1405
1406     proto_free_deregistered_fields();
1407 }
1408
1409 void MainWindow::checkDisplayFilter()
1410 {
1411     if (!df_combo_box_->checkDisplayFilter()) {
1412         g_free(CaptureFile::globalCapFile()->dfilter);
1413         CaptureFile::globalCapFile()->dfilter = NULL;
1414     }
1415 }
1416
1417 void MainWindow::fieldsChanged()
1418 {
1419     gchar *err_msg = NULL;
1420     if (!color_filters_reload(&err_msg, color_filter_add_cb)) {
1421         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
1422         g_free(err_msg);
1423     }
1424     tap_listeners_dfilter_recompile();
1425
1426     emit checkDisplayFilter();
1427
1428     if (have_custom_cols(&CaptureFile::globalCapFile()->cinfo)) {
1429         // Recreate packet list columns according to new/changed/deleted fields
1430         packet_list_->fieldsChanged(CaptureFile::globalCapFile());
1431     }
1432
1433     emit reloadFields();
1434 }
1435
1436 void MainWindow::reloadLuaPlugins()
1437 {
1438 #ifdef HAVE_LUA
1439     if (wsApp->isReloadingLua())
1440         return;
1441
1442     wsApp->setReloadingLua(true);
1443
1444     wslua_reload_plugins(NULL, NULL);
1445     funnel_statistics_reload_menus();
1446     reloadDynamicMenus();
1447     closePacketDialogs();
1448
1449     // Preferences may have been deleted so close all widgets using prefs
1450     proto_tree_->closeContextMenu();
1451     main_ui_->preferenceEditorFrame->animatedHide();
1452
1453     char *gdp_path, *dp_path;
1454     wsApp->readConfigurationFiles(&gdp_path, &dp_path, true);
1455
1456     prefs_apply_all();
1457     fieldsChanged();
1458     redissectPackets();
1459
1460     wsApp->setReloadingLua(false);
1461     SimpleDialog::displayQueuedMessages();
1462 #endif
1463 }
1464
1465 void MainWindow::showAccordionFrame(AccordionFrame *show_frame, bool toggle)
1466 {
1467     QList<AccordionFrame *>frame_list = QList<AccordionFrame *>()
1468             << main_ui_->goToFrame << main_ui_->searchFrame
1469             << main_ui_->addressEditorFrame << main_ui_->columnEditorFrame
1470             << main_ui_->preferenceEditorFrame << main_ui_->filterExpressionFrame;
1471
1472     frame_list.removeAll(show_frame);
1473     foreach (AccordionFrame *af, frame_list) af->animatedHide();
1474
1475     if (toggle) {
1476         if (show_frame->isVisible()) {
1477             show_frame->animatedHide();
1478             return;
1479         }
1480     }
1481     show_frame->animatedShow();
1482 }
1483
1484 void MainWindow::showColumnEditor(int column)
1485 {
1486     previous_focus_ = wsApp->focusWidget();
1487     connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
1488     showAccordionFrame(main_ui_->columnEditorFrame);
1489     main_ui_->columnEditorFrame->editColumn(column);
1490 }
1491
1492 void MainWindow::showPreferenceEditor()
1493 {
1494     showAccordionFrame(main_ui_->preferenceEditorFrame);
1495 }
1496
1497 void MainWindow::initViewColorizeMenu()
1498 {
1499     QList<QAction *> cc_actions = QList<QAction *>()
1500             << main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
1501             << main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
1502             << main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
1503             << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
1504             << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
1505
1506     guint8 color_num = 1;
1507
1508     foreach (QAction *cc_action, cc_actions) {
1509         cc_action->setData(color_num);
1510         connect(cc_action, SIGNAL(triggered()), this, SLOT(colorizeConversation()));
1511
1512         const color_filter_t *colorf = color_filters_tmp_color(color_num);
1513         if (colorf) {
1514             QColor bg = ColorUtils::fromColorT(colorf->bg_color);
1515             QColor fg = ColorUtils::fromColorT(colorf->fg_color);
1516             cc_action->setIcon(StockIcon::colorIcon(bg.rgb(), fg.rgb(), QString::number(color_num)));
1517         }
1518         color_num++;
1519     }
1520
1521 #ifdef Q_OS_MAC
1522     // Spotlight uses Cmd+Space
1523     main_ui_->actionViewColorizeResetColorization->setShortcut(QKeySequence("Meta+Space"));
1524 #endif
1525 }
1526
1527 void MainWindow::addStatsPluginsToMenu() {
1528     GList          *cfg_list = stats_tree_get_cfg_list();
1529     GList          *iter = g_list_first(cfg_list);
1530     QAction        *stats_tree_action;
1531     QMenu          *parent_menu;
1532     bool            first_item = true;
1533
1534     while (iter) {
1535         stats_tree_cfg *cfg = (stats_tree_cfg*)iter->data;
1536         if (cfg->plugin) {
1537             if (first_item) {
1538                 main_ui_->menuStatistics->addSeparator();
1539                 first_item = false;
1540             }
1541
1542             parent_menu = main_ui_->menuStatistics;
1543             // gtk/main_menubar.c compresses double slashes, hence SkipEmptyParts
1544             QStringList cfg_name_parts = QString(cfg->name).split("/", QString::SkipEmptyParts);
1545             if (cfg_name_parts.isEmpty()) continue;
1546
1547             QString stat_name = cfg_name_parts.takeLast();
1548             if (!cfg_name_parts.isEmpty()) {
1549                 QString menu_name = cfg_name_parts.join("/");
1550                 parent_menu = findOrAddMenu(parent_menu, menu_name);
1551             }
1552
1553             stats_tree_action = new QAction(stat_name, this);
1554             stats_tree_action->setData(cfg->abbr);
1555             parent_menu->addAction(stats_tree_action);
1556             connect(stats_tree_action, SIGNAL(triggered()), this, SLOT(actionStatisticsPlugin_triggered()));
1557         }
1558         iter = g_list_next(iter);
1559     }
1560     g_list_free(cfg_list);
1561 }
1562
1563 void MainWindow::setFeaturesEnabled(bool enabled)
1564 {
1565     main_ui_->menuBar->setEnabled(enabled);
1566     main_ui_->mainToolBar->setEnabled(enabled);
1567     main_ui_->displayFilterToolBar->setEnabled(enabled);
1568     if(enabled)
1569     {
1570         main_ui_->statusBar->clearMessage();
1571 #ifdef HAVE_LIBPCAP
1572         main_ui_->actionGoAutoScroll->setChecked(auto_scroll_live);
1573 #endif
1574     }
1575     else
1576     {
1577         main_ui_->statusBar->showMessage(tr("Please wait while Wireshark is initializing" UTF8_HORIZONTAL_ELLIPSIS));
1578     }
1579 }
1580
1581 // Display Filter Toolbar
1582
1583 void MainWindow::on_actionDisplayFilterExpression_triggered()
1584 {
1585     DisplayFilterExpressionDialog *dfe_dialog = new DisplayFilterExpressionDialog(this);
1586
1587     connect(dfe_dialog, SIGNAL(insertDisplayFilter(QString)),
1588             df_combo_box_->lineEdit(), SLOT(insertFilter(const QString &)));
1589
1590     dfe_dialog->show();
1591 }
1592
1593 void MainWindow::on_actionNewDisplayFilterExpression_triggered()
1594 {
1595     main_ui_->filterExpressionFrame->addExpression(df_combo_box_->lineEdit()->text());
1596     showAccordionFrame(main_ui_->filterExpressionFrame);
1597 }
1598
1599 // On Qt4 + OS X with unifiedTitleAndToolBarOnMac set it's possible to make
1600 // the main window obnoxiously wide.
1601
1602 void MainWindow::displayFilterButtonClicked()
1603 {
1604     QAction *dfb_action = qobject_cast<QAction*>(sender());
1605
1606     if (dfb_action) {
1607         df_combo_box_->lineEdit()->setText(dfb_action->data().toString());
1608         df_combo_box_->applyDisplayFilter();
1609         df_combo_box_->lineEdit()->setFocus();
1610     }
1611 }
1612
1613 void MainWindow::openStatCommandDialog(const QString &menu_path, const char *arg, void *userdata)
1614 {
1615     QString slot = QString("statCommand%1").arg(menu_path);
1616     QMetaObject::invokeMethod(this, slot.toLatin1().constData(), Q_ARG(const char *, arg), Q_ARG(void *, userdata));
1617 }
1618
1619 void MainWindow::openTapParameterDialog(const QString cfg_str, const QString arg, void *userdata)
1620 {
1621     TapParameterDialog *tp_dialog = TapParameterDialog::showTapParameterStatistics(*this, capture_file_, cfg_str, arg, userdata);
1622     if (!tp_dialog) return;
1623
1624     connect(tp_dialog, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
1625             this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
1626     connect(tp_dialog, SIGNAL(updateFilter(QString)),
1627             df_combo_box_->lineEdit(), SLOT(setText(QString)));
1628     tp_dialog->show();
1629 }
1630
1631 void MainWindow::openTapParameterDialog()
1632 {
1633     QAction *tpa = qobject_cast<QAction *>(QObject::sender());
1634     if (!tpa) return;
1635
1636     const QString cfg_str = tpa->data().toString();
1637     openTapParameterDialog(cfg_str, NULL, NULL);
1638 }
1639
1640 void MainWindow::byteViewTabChanged(int tab_index)
1641 {
1642     QWidget *new_tab = byte_view_tab_->widget(tab_index);
1643     if (new_tab) {
1644         setTabOrder(proto_tree_, new_tab);
1645         setTabOrder(new_tab, df_combo_box_->lineEdit()); // XXX Toolbar instead?
1646     }
1647 }
1648
1649 // File Menu
1650
1651 void MainWindow::on_actionFileOpen_triggered()
1652 {
1653     openCaptureFile();
1654 }
1655
1656 void MainWindow::on_actionFileMerge_triggered()
1657 {
1658     mergeCaptureFile();
1659 }
1660
1661 void MainWindow::on_actionFileImportFromHexDump_triggered()
1662 {
1663     importCaptureFile();
1664 }
1665
1666 void MainWindow::on_actionFileClose_triggered() {
1667     QString before_what(tr(" before closing the file"));
1668     if (testCaptureFileClose(before_what))
1669         main_ui_->mainStack->setCurrentWidget(main_welcome_);
1670 }
1671
1672 void MainWindow::on_actionFileSave_triggered()
1673 {
1674     saveCaptureFile(capture_file_.capFile(), false);
1675 }
1676
1677 void MainWindow::on_actionFileSaveAs_triggered()
1678 {
1679     saveAsCaptureFile(capture_file_.capFile());
1680 }
1681
1682 void MainWindow::on_actionFileSetListFiles_triggered()
1683 {
1684     file_set_dialog_->show();
1685 }
1686
1687 void MainWindow::on_actionFileSetNextFile_triggered()
1688 {
1689     fileset_entry *entry = fileset_get_next();
1690
1691     if (entry) {
1692         QString new_cf_path = entry->fullname;
1693         openCaptureFile(new_cf_path);
1694     }
1695 }
1696
1697 void MainWindow::on_actionFileSetPreviousFile_triggered()
1698 {
1699     fileset_entry *entry = fileset_get_previous();
1700
1701     if (entry) {
1702         QString new_cf_path = entry->fullname;
1703         openCaptureFile(new_cf_path);
1704     }
1705 }
1706
1707 void MainWindow::on_actionFileExportPackets_triggered()
1708 {
1709     exportSelectedPackets();
1710 }
1711
1712 void MainWindow::on_actionFileExportAsPlainText_triggered()
1713 {
1714     exportDissections(export_type_text);
1715 }
1716
1717 void MainWindow::on_actionFileExportAsCSV_triggered()
1718 {
1719     exportDissections(export_type_csv);
1720 }
1721
1722 void MainWindow::on_actionFileExportAsCArrays_triggered()
1723 {
1724     exportDissections(export_type_carrays);
1725 }
1726
1727 void MainWindow::on_actionFileExportAsPSML_triggered()
1728 {
1729     exportDissections(export_type_psml);
1730 }
1731
1732 void MainWindow::on_actionFileExportAsPDML_triggered()
1733 {
1734     exportDissections(export_type_pdml);
1735 }
1736
1737 void MainWindow::on_actionFileExportAsJSON_triggered()
1738 {
1739     exportDissections(export_type_json);
1740 }
1741
1742 void MainWindow::on_actionFileExportPacketBytes_triggered()
1743 {
1744     QString file_name;
1745
1746     if (!capture_file_.capFile() || !capture_file_.capFile()->finfo_selected) return;
1747
1748     file_name = QFileDialog::getSaveFileName(this,
1749                                              wsApp->windowTitleString(tr("Export Selected Packet Bytes")),
1750                                              wsApp->lastOpenDir().canonicalPath(),
1751                                              tr("Raw data (*.bin *.dat *.raw);;All Files (" ALL_FILES_WILDCARD ")")
1752                                              );
1753
1754     if (file_name.length() > 0) {
1755         const guint8 *data_p;
1756         int fd;
1757
1758         data_p = tvb_get_ptr(capture_file_.capFile()->finfo_selected->ds_tvb, 0, -1) +
1759                 capture_file_.capFile()->finfo_selected->start;
1760         fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
1761         if (fd == -1) {
1762             open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
1763             return;
1764         }
1765         if (ws_write(fd, data_p, capture_file_.capFile()->finfo_selected->length) < 0) {
1766             write_failure_alert_box(file_name.toUtf8().constData(), errno);
1767             ws_close(fd);
1768             return;
1769         }
1770         if (ws_close(fd) < 0) {
1771             write_failure_alert_box(file_name.toUtf8().constData(), errno);
1772             return;
1773         }
1774
1775         /* Save the directory name for future file dialogs. */
1776         wsApp->setLastOpenDir(&file_name);
1777     }
1778 }
1779
1780 void MainWindow::on_actionContextShowPacketBytes_triggered()
1781 {
1782     ShowPacketBytesDialog *spbd = new ShowPacketBytesDialog(*this, capture_file_);
1783     spbd->show();
1784 }
1785
1786 void MainWindow::on_actionFileExportPDU_triggered()
1787 {
1788     ExportPDUDialog *exportpdu_dialog = new ExportPDUDialog(this);
1789
1790     if (exportpdu_dialog->isMinimized() == true)
1791     {
1792         exportpdu_dialog->showNormal();
1793     }
1794     else
1795     {
1796         exportpdu_dialog->show();
1797     }
1798
1799     exportpdu_dialog->raise();
1800     exportpdu_dialog->activateWindow();
1801 }
1802
1803 void MainWindow::on_actionFileExportSSLSessionKeys_triggered()
1804 {
1805     QString file_name;
1806     QString save_title;
1807     int keylist_len;
1808
1809     keylist_len = ssl_session_key_count();
1810     /* don't show up the dialog, if no data has to be saved */
1811     if (keylist_len < 1) {
1812         /* shouldn't happen as the menu item should have been greyed out */
1813         QMessageBox::warning(
1814                     this,
1815                     tr("No Keys"),
1816                     tr("There are no SSL Session Keys to save."),
1817                     QMessageBox::Ok
1818                     );
1819         return;
1820     }
1821
1822     save_title.append(wsApp->windowTitleString(tr("Export SSL Session Keys (%Ln key(s))", "", keylist_len)));
1823     file_name = QFileDialog::getSaveFileName(this,
1824                                              save_title,
1825                                              wsApp->lastOpenDir().canonicalPath(),
1826                                              tr("SSL Session Keys (*.keys *.txt);;All Files (" ALL_FILES_WILDCARD ")")
1827                                              );
1828     if (file_name.length() > 0) {
1829         gchar *keylist;
1830         int fd;
1831
1832         keylist = ssl_export_sessions();
1833         fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
1834         if (fd == -1) {
1835             open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
1836             g_free(keylist);
1837             return;
1838         }
1839         /*
1840          * Thanks, Microsoft, for not using size_t for the third argument to
1841          * _write().  Presumably this string will be <= 4GiB long....
1842          */
1843         if (ws_write(fd, keylist, (unsigned int)strlen(keylist)) < 0) {
1844             write_failure_alert_box(file_name.toUtf8().constData(), errno);
1845             ws_close(fd);
1846             g_free(keylist);
1847             return;
1848         }
1849         if (ws_close(fd) < 0) {
1850             write_failure_alert_box(file_name.toUtf8().constData(), errno);
1851             g_free(keylist);
1852             return;
1853         }
1854
1855         /* Save the directory name for future file dialogs. */
1856         wsApp->setLastOpenDir(&file_name);
1857         g_free(keylist);
1858     }
1859 }
1860
1861 void MainWindow::on_actionFileExportObjectsDICOM_triggered()
1862 {
1863     new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Dicom);
1864 }
1865
1866 void MainWindow::on_actionStatisticsHpfeeds_triggered()
1867 {
1868     openStatisticsTreeDialog("hpfeeds");
1869 }
1870
1871 void MainWindow::on_actionFileExportObjectsHTTP_triggered()
1872 {
1873     new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Http);
1874 }
1875
1876 void MainWindow::on_actionFileExportObjectsSMB_triggered()
1877 {
1878     new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Smb);
1879 }
1880
1881 void MainWindow::on_actionFileExportObjectsTFTP_triggered()
1882 {
1883     new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Tftp);
1884 }
1885
1886 void MainWindow::on_actionFilePrint_triggered()
1887 {
1888     PrintDialog pdlg(this, capture_file_.capFile());
1889
1890     pdlg.exec();
1891 }
1892
1893 // Edit Menu
1894
1895 void MainWindow::recursiveCopyProtoTreeItems(QTreeWidgetItem *item, QString &clip, int ident_level) {
1896     if (!item->isExpanded()) return;
1897
1898     for (int i_item = 0; i_item < item->childCount(); i_item += 1) {
1899         clip.append(QString("    ").repeated(ident_level));
1900         clip.append(item->child(i_item)->text(0));
1901         clip.append("\n");
1902
1903         recursiveCopyProtoTreeItems(item->child(i_item), clip, ident_level + 1);
1904     }
1905 }
1906
1907 // XXX This should probably be somewhere else.
1908 void MainWindow::actionEditCopyTriggered(MainWindow::CopySelected selection_type)
1909 {
1910     char label_str[ITEM_LABEL_LENGTH];
1911     QString clip;
1912
1913     if (!capture_file_.capFile()) return;
1914
1915     field_info *finfo_selected = capture_file_.capFile()->finfo_selected;
1916
1917     switch(selection_type) {
1918     case CopySelectedDescription:
1919         if (finfo_selected && finfo_selected->rep
1920                 && strlen (finfo_selected->rep->representation) > 0) {
1921             clip.append(finfo_selected->rep->representation);
1922         }
1923         break;
1924     case CopySelectedFieldName:
1925         if (finfo_selected && finfo_selected->hfinfo->abbrev != 0) {
1926             clip.append(finfo_selected->hfinfo->abbrev);
1927         }
1928         break;
1929     case CopySelectedValue:
1930         if (finfo_selected && capture_file_.capFile()->edt != 0) {
1931             gchar* field_str = get_node_field_value(finfo_selected, capture_file_.capFile()->edt);
1932             clip.append(field_str);
1933             g_free(field_str);
1934         }
1935         break;
1936     case CopyAllVisibleItems:
1937         for (int i_item = 0; i_item < proto_tree_->topLevelItemCount(); i_item += 1) {
1938             clip.append(proto_tree_->topLevelItem(i_item)->text(0));
1939             clip.append("\n");
1940
1941             recursiveCopyProtoTreeItems(proto_tree_->topLevelItem(i_item), clip, 1);
1942         }
1943
1944         break;
1945     case CopyAllVisibleSelectedTreeItems:
1946         if (proto_tree_->selectedItems().count() > 0) {
1947             clip.append(proto_tree_->currentItem()->text(0));
1948             clip.append("\n");
1949
1950             recursiveCopyProtoTreeItems(proto_tree_->currentItem(), clip, 1);
1951         }
1952         break;
1953     }
1954
1955     if (clip.length() == 0) {
1956         /* If no representation then... Try to read the value */
1957         proto_item_fill_label(capture_file_.capFile()->finfo_selected, label_str);
1958         clip.append(label_str);
1959     }
1960
1961     if (clip.length()) {
1962         wsApp->clipboard()->setText(clip);
1963     } else {
1964         QString err = tr("Couldn't copy text. Try another item.");
1965         main_ui_->statusBar->pushTemporaryStatus(err);
1966     }
1967 }
1968
1969 void MainWindow::on_actionCopyAllVisibleItems_triggered()
1970 {
1971     actionEditCopyTriggered(CopyAllVisibleItems);
1972 }
1973
1974 void MainWindow::on_actionCopyAllVisibleSelectedTreeItems_triggered()
1975 {
1976     actionEditCopyTriggered(CopyAllVisibleSelectedTreeItems);
1977 }
1978
1979 void MainWindow::on_actionEditCopyDescription_triggered()
1980 {
1981     actionEditCopyTriggered(CopySelectedDescription);
1982 }
1983
1984 void MainWindow::on_actionEditCopyFieldName_triggered()
1985 {
1986     actionEditCopyTriggered(CopySelectedFieldName);
1987 }
1988
1989 void MainWindow::on_actionEditCopyValue_triggered()
1990 {
1991     actionEditCopyTriggered(CopySelectedValue);
1992 }
1993
1994 void MainWindow::on_actionEditCopyAsFilter_triggered()
1995 {
1996     matchFieldFilter(FilterAction::ActionCopy, FilterAction::ActionTypePlain);
1997 }
1998
1999 void MainWindow::on_actionEditFindPacket_triggered()
2000 {
2001     if (packet_list_->packetListModel()->rowCount() < 1) {
2002         return;
2003     }
2004     previous_focus_ = wsApp->focusWidget();
2005     connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
2006     showAccordionFrame(main_ui_->searchFrame, true);
2007     if (main_ui_->searchFrame->isVisible()) {
2008         main_ui_->searchFrame->setFocus();
2009     }
2010 }
2011
2012 void MainWindow::on_actionEditFindNext_triggered()
2013 {
2014     main_ui_->searchFrame->findNext();
2015 }
2016
2017 void MainWindow::on_actionEditFindPrevious_triggered()
2018 {
2019     main_ui_->searchFrame->findPrevious();
2020 }
2021
2022 void MainWindow::on_actionEditMarkPacket_triggered()
2023 {
2024     freeze();
2025     packet_list_->markFrame();
2026     thaw();
2027 }
2028
2029 void MainWindow::on_actionEditMarkAllDisplayed_triggered()
2030 {
2031     freeze();
2032     packet_list_->markAllDisplayedFrames(true);
2033     thaw();
2034 }
2035
2036 void MainWindow::on_actionEditUnmarkAllDisplayed_triggered()
2037 {
2038     freeze();
2039     packet_list_->markAllDisplayedFrames(false);
2040     thaw();
2041 }
2042
2043 void MainWindow::on_actionEditNextMark_triggered()
2044 {
2045     if (capture_file_.capFile())
2046         cf_find_packet_marked(capture_file_.capFile(), SD_FORWARD);
2047 }
2048
2049 void MainWindow::on_actionEditPreviousMark_triggered()
2050 {
2051     if (capture_file_.capFile())
2052         cf_find_packet_marked(capture_file_.capFile(), SD_BACKWARD);
2053 }
2054
2055 void MainWindow::on_actionEditIgnorePacket_triggered()
2056 {
2057     freeze();
2058     packet_list_->ignoreFrame();
2059     thaw();
2060 }
2061
2062 void MainWindow::on_actionEditIgnoreAllDisplayed_triggered()
2063 {
2064     freeze();
2065     packet_list_->ignoreAllDisplayedFrames(true);
2066     thaw();
2067 }
2068
2069 void MainWindow::on_actionEditUnignoreAllDisplayed_triggered()
2070 {
2071     freeze();
2072     packet_list_->ignoreAllDisplayedFrames(false);
2073     thaw();
2074 }
2075
2076 void MainWindow::on_actionEditSetTimeReference_triggered()
2077 {
2078     packet_list_->setTimeReference();
2079 }
2080
2081 void MainWindow::on_actionEditUnsetAllTimeReferences_triggered()
2082 {
2083     packet_list_->unsetAllTimeReferences();
2084 }
2085
2086 void MainWindow::on_actionEditNextTimeReference_triggered()
2087 {
2088     if (!capture_file_.capFile()) return;
2089     cf_find_packet_time_reference(capture_file_.capFile(), SD_FORWARD);
2090 }
2091
2092 void MainWindow::on_actionEditPreviousTimeReference_triggered()
2093 {
2094     if (!capture_file_.capFile()) return;
2095     cf_find_packet_time_reference(capture_file_.capFile(), SD_BACKWARD);
2096 }
2097
2098 void MainWindow::on_actionEditTimeShift_triggered()
2099 {
2100     TimeShiftDialog ts_dialog(this, capture_file_.capFile());
2101     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2102             &ts_dialog, SLOT(setCaptureFile(capture_file*)));
2103     connect(&ts_dialog, SIGNAL(timeShifted()), packet_list_, SLOT(applyTimeShift()));
2104     ts_dialog.exec();
2105 }
2106
2107 void MainWindow::on_actionEditPacketComment_triggered()
2108 {
2109     PacketCommentDialog pc_dialog(this, packet_list_->packetComment());
2110     if (pc_dialog.exec() == QDialog::Accepted) {
2111         packet_list_->setPacketComment(pc_dialog.text());
2112         updateForUnsavedChanges();
2113     }
2114 }
2115
2116 void MainWindow::on_actionEditConfigurationProfiles_triggered()
2117 {
2118     ProfileDialog cp_dialog;
2119
2120     cp_dialog.exec();
2121 }
2122
2123 void MainWindow::showPreferencesDialog(PreferencesDialog::PreferencesPane start_pane)
2124 {
2125     PreferencesDialog pref_dialog(this);
2126
2127     pref_dialog.setPane(start_pane);
2128     pref_dialog.exec();
2129
2130     // Emitting PacketDissectionChanged directly from a QDialog can cause
2131     // problems on OS X.
2132     wsApp->flushAppSignals();
2133 }
2134
2135 void MainWindow::showPreferencesDialog(QString module_name)
2136 {
2137     PreferencesDialog pref_dialog(this);
2138
2139     pref_dialog.setPane(module_name);
2140     pref_dialog.exec();
2141
2142     // Emitting PacketDissectionChanged directly from a QDialog can cause
2143     // problems on OS X.
2144     wsApp->flushAppSignals();
2145 }
2146
2147 void MainWindow::on_actionEditPreferences_triggered()
2148 {
2149     showPreferencesDialog();
2150 }
2151
2152 // View Menu
2153
2154 void MainWindow::showHideMainWidgets(QAction *action)
2155 {
2156     if (!action) {
2157         return;
2158     }
2159     bool show = action->isChecked();
2160     QWidget *widget = action->data().value<QWidget*>();
2161
2162     // We may have come from the toolbar context menu, so check/uncheck each
2163     // action as well.
2164     if (widget == main_ui_->mainToolBar) {
2165         recent.main_toolbar_show = show;
2166         main_ui_->actionViewMainToolbar->setChecked(show);
2167     } else if (widget == main_ui_->displayFilterToolBar) {
2168         recent.filter_toolbar_show = show;
2169         main_ui_->actionViewFilterToolbar->setChecked(show);
2170      } else if (widget == main_ui_->wirelessToolBar) {
2171         recent.wireless_toolbar_show = show;
2172         main_ui_->actionViewWirelessToolbar->setChecked(show);
2173     } else if (widget == main_ui_->statusBar) {
2174         recent.statusbar_show = show;
2175         main_ui_->actionViewStatusBar->setChecked(show);
2176     } else if (widget == packet_list_) {
2177         recent.packet_list_show = show;
2178         main_ui_->actionViewPacketList->setChecked(show);
2179     } else if (widget == proto_tree_) {
2180         recent.tree_view_show = show;
2181         main_ui_->actionViewPacketDetails->setChecked(show);
2182     } else if (widget == byte_view_tab_) {
2183         recent.byte_view_show = show;
2184         main_ui_->actionViewPacketBytes->setChecked(show);
2185     }
2186
2187     if (widget) {
2188         widget->setVisible(show);
2189     }
2190 }
2191
2192 Q_DECLARE_METATYPE(ts_type)
2193
2194 void MainWindow::setTimestampFormat(QAction *action)
2195 {
2196     if (!action) {
2197         return;
2198     }
2199     ts_type tsf = action->data().value<ts_type>();
2200     if (recent.gui_time_format != tsf) {
2201         timestamp_set_type(tsf);
2202         recent.gui_time_format = tsf;
2203
2204         if (packet_list_) {
2205             packet_list_->resetColumns();
2206         }
2207         if (capture_file_.capFile()) {
2208             /* This call adjusts column width */
2209             cf_timestamp_auto_precision(capture_file_.capFile());
2210         }
2211     }
2212 }
2213
2214 Q_DECLARE_METATYPE(ts_precision)
2215
2216 void MainWindow::setTimestampPrecision(QAction *action)
2217 {
2218     if (!action) {
2219         return;
2220     }
2221     ts_precision tsp = action->data().value<ts_precision>();
2222     if (recent.gui_time_precision != tsp) {
2223         /* the actual precision will be set in packet_list_queue_draw() below */
2224         timestamp_set_precision(tsp);
2225         recent.gui_time_precision = tsp;
2226
2227         if (packet_list_) {
2228             packet_list_->resetColumns();
2229         }
2230         if (capture_file_.capFile()) {
2231             /* This call adjusts column width */
2232             cf_timestamp_auto_precision(capture_file_.capFile());
2233         }
2234     }
2235 }
2236
2237 void MainWindow::on_actionViewTimeDisplaySecondsWithHoursAndMinutes_triggered(bool checked)
2238 {
2239     if (checked) {
2240         recent.gui_seconds_format = TS_SECONDS_HOUR_MIN_SEC;
2241     } else {
2242         recent.gui_seconds_format = TS_SECONDS_DEFAULT;
2243     }
2244     timestamp_set_seconds_type(recent.gui_seconds_format);
2245
2246     if (packet_list_) {
2247         packet_list_->resetColumns();
2248     }
2249     if (capture_file_.capFile()) {
2250         /* This call adjusts column width */
2251         cf_timestamp_auto_precision(capture_file_.capFile());
2252     }
2253 }
2254
2255 void MainWindow::on_actionViewEditResolvedName_triggered()
2256 {
2257 //    int column = packet_list_->selectedColumn();
2258     int column = -1;
2259
2260     if (packet_list_->currentIndex().isValid()) {
2261         column = packet_list_->currentIndex().column();
2262     }
2263
2264     main_ui_->addressEditorFrame->editAddresses(capture_file_, column);
2265     showAccordionFrame(main_ui_->addressEditorFrame);
2266 }
2267
2268 void MainWindow::setNameResolution()
2269 {
2270     gbl_resolv_flags.mac_name = main_ui_->actionViewNameResolutionPhysical->isChecked() ? TRUE : FALSE;
2271     gbl_resolv_flags.network_name = main_ui_->actionViewNameResolutionNetwork->isChecked() ? TRUE : FALSE;
2272     gbl_resolv_flags.transport_name = main_ui_->actionViewNameResolutionTransport->isChecked() ? TRUE : FALSE;
2273
2274     if (packet_list_) {
2275         packet_list_->resetColumns();
2276     }
2277     wsApp->emitAppSignal(WiresharkApplication::NameResolutionChanged);
2278 }
2279
2280 void MainWindow::on_actionViewNameResolutionPhysical_triggered()
2281 {
2282     setNameResolution();
2283 }
2284
2285 void MainWindow::on_actionViewNameResolutionNetwork_triggered()
2286 {
2287     setNameResolution();
2288 }
2289
2290 void MainWindow::on_actionViewNameResolutionTransport_triggered()
2291 {
2292     setNameResolution();
2293 }
2294
2295 void MainWindow::zoomText()
2296 {
2297     // Scale by 10%, rounding to nearest half point, minimum 1 point.
2298     // XXX Small sizes repeat. It might just be easier to create a map of multipliers.
2299     mono_font_ = QFont(wsApp->monospaceFont());
2300     qreal zoom_size = wsApp->monospaceFont().pointSize() * 2 * qPow(qreal(1.1), recent.gui_zoom_level);
2301     zoom_size = qRound(zoom_size) / qreal(2.0);
2302     zoom_size = qMax(zoom_size, qreal(1.0));
2303     mono_font_.setPointSizeF(zoom_size);
2304     emit monospaceFontChanged(mono_font_);
2305 }
2306
2307 void MainWindow::on_actionViewZoomIn_triggered()
2308 {
2309     recent.gui_zoom_level++;
2310     zoomText();
2311 }
2312
2313 void MainWindow::on_actionViewZoomOut_triggered()
2314 {
2315     recent.gui_zoom_level--;
2316     zoomText();
2317 }
2318
2319 void MainWindow::on_actionViewNormalSize_triggered()
2320 {
2321     recent.gui_zoom_level = 0;
2322     zoomText();
2323 }
2324
2325 void MainWindow::on_actionViewColorizePacketList_triggered(bool checked) {
2326     recent.packet_list_colorize = checked;
2327     packet_list_enable_color(checked);
2328     packet_list_->packetListModel()->resetColorized();
2329 }
2330
2331 void MainWindow::on_actionViewColoringRules_triggered()
2332 {
2333     ColoringRulesDialog coloring_rules_dialog(this);
2334     connect(&coloring_rules_dialog, SIGNAL(accepted()),
2335             packet_list_, SLOT(recolorPackets()));
2336     coloring_rules_dialog.exec();
2337 }
2338
2339 // actionViewColorizeConversation1 - 10
2340 void MainWindow::colorizeConversation(bool create_rule)
2341 {
2342     QAction *colorize_action = qobject_cast<QAction *>(sender());
2343     if (!colorize_action) return;
2344
2345     if (capture_file_.capFile() && capture_file_.capFile()->current_frame) {
2346         packet_info *pi = capture_file_.packetInfo();
2347         guint8 cc_num = colorize_action->data().toUInt();
2348         gchar *filter = NULL;
2349
2350         const conversation_filter_t *color_filter = find_conversation_filter("tcp");
2351         if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2352             filter = color_filter->build_filter_string(pi);
2353         if (filter == NULL) {
2354             color_filter = find_conversation_filter("udp");
2355             if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2356                 filter = color_filter->build_filter_string(pi);
2357         }
2358         if (filter == NULL) {
2359             color_filter = find_conversation_filter("ip");
2360             if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2361                 filter = color_filter->build_filter_string(pi);
2362         }
2363         if (filter == NULL) {
2364             color_filter = find_conversation_filter("ipv6");
2365             if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2366                 filter = color_filter->build_filter_string(pi);
2367         }
2368         if (filter == NULL) {
2369             color_filter = find_conversation_filter("eth");
2370             if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2371                 filter = color_filter->build_filter_string(pi);
2372         }
2373         if (filter == NULL) {
2374             main_ui_->statusBar->pushTemporaryStatus(tr("Unable to build conversation filter."));
2375             return;
2376         }
2377
2378         if (create_rule) {
2379             ColoringRulesDialog coloring_rules_dialog(this, filter);
2380             connect(&coloring_rules_dialog, SIGNAL(accepted()),
2381                     packet_list_, SLOT(recolorPackets()));
2382             coloring_rules_dialog.exec();
2383         } else {
2384             gchar *err_msg = NULL;
2385             if (!color_filters_set_tmp(cc_num, filter, FALSE, &err_msg)) {
2386                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
2387                 g_free(err_msg);
2388             }
2389             packet_list_->recolorPackets();
2390         }
2391     }
2392     setMenusForSelectedPacket();
2393 }
2394
2395 void MainWindow::colorizeActionTriggered()
2396 {
2397     QByteArray filter;
2398     int color_number = -1;
2399
2400     ConversationAction *conv_action = qobject_cast<ConversationAction *>(sender());
2401     if (conv_action) {
2402         filter = conv_action->filter();
2403         color_number = conv_action->colorNumber();
2404     } else {
2405         ColorizeAction *colorize_action = qobject_cast<ColorizeAction *>(sender());
2406         if (colorize_action) {
2407             filter = colorize_action->filter();
2408             color_number = colorize_action->colorNumber();
2409         }
2410     }
2411
2412     colorizeWithFilter(filter, color_number);
2413 }
2414
2415 void MainWindow::colorizeWithFilter(QByteArray filter, int color_number)
2416 {
2417     if (filter.isEmpty()) return;
2418
2419     if (color_number > 0) {
2420         // Assume "Color X"
2421         gchar *err_msg = NULL;
2422         if (!color_filters_set_tmp(color_number, filter.constData(), FALSE, &err_msg)) {
2423             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
2424             g_free(err_msg);
2425         }
2426         packet_list_->recolorPackets();
2427     } else {
2428         // New coloring rule
2429         ColoringRulesDialog coloring_rules_dialog(window(), filter);
2430         connect(&coloring_rules_dialog, SIGNAL(accepted()),
2431                 packet_list_, SLOT(recolorPackets()));
2432         coloring_rules_dialog.exec();
2433     }
2434     main_ui_->actionViewColorizeResetColorization->setEnabled(tmp_color_filters_used());
2435 }
2436
2437 void MainWindow::on_actionViewColorizeResetColorization_triggered()
2438 {
2439     gchar *err_msg = NULL;
2440     if (!color_filters_reset_tmp(&err_msg)) {
2441         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
2442         g_free(err_msg);
2443     }
2444     packet_list_->recolorPackets();
2445     setMenusForSelectedPacket();
2446 }
2447
2448 void MainWindow::on_actionViewColorizeNewColoringRule_triggered()
2449 {
2450     colorizeConversation(true);
2451 }
2452
2453 void MainWindow::on_actionViewResizeColumns_triggered()
2454 {
2455     for (int col = 0; col < packet_list_->packetListModel()->columnCount(); col++) {
2456         packet_list_->resizeColumnToContents(col);
2457         recent_set_column_width(col, packet_list_->columnWidth(col));
2458     }
2459 }
2460
2461 void MainWindow::openPacketDialog(bool from_reference)
2462 {
2463     frame_data * fdata;
2464
2465     /* Find the frame for which we're popping up a dialog */
2466     if(from_reference) {
2467         guint32 framenum = fvalue_get_uinteger(&(capture_file_.capFile()->finfo_selected->value));
2468         if (framenum == 0)
2469             return;
2470
2471         fdata = frame_data_sequence_find(capture_file_.capFile()->frames, framenum);
2472     } else {
2473         fdata = capture_file_.capFile()->current_frame;
2474     }
2475
2476     /* If we have a frame, pop up the dialog */
2477     if (fdata) {
2478         PacketDialog *packet_dialog = new PacketDialog(*this, capture_file_, fdata);
2479
2480         connect(this, SIGNAL(monospaceFontChanged(QFont)),
2481                 packet_dialog, SIGNAL(monospaceFontChanged(QFont)));
2482         connect(this, SIGNAL(closePacketDialogs()),
2483                 packet_dialog, SLOT(close()));
2484         zoomText(); // Emits monospaceFontChanged
2485
2486         packet_dialog->show();
2487     }
2488 }
2489
2490 void MainWindow::on_actionViewInternalsConversationHashTables_triggered()
2491 {
2492     ConversationHashTablesDialog *conversation_hash_tables_dlg = new ConversationHashTablesDialog(this);
2493     conversation_hash_tables_dlg->show();
2494 }
2495
2496 void MainWindow::on_actionViewInternalsDissectorTables_triggered()
2497 {
2498     DissectorTablesDialog *dissector_tables_dlg = new DissectorTablesDialog(this);
2499     dissector_tables_dlg->show();
2500 }
2501
2502 void MainWindow::on_actionViewInternalsSupportedProtocols_triggered()
2503 {
2504     SupportedProtocolsDialog *supported_protocols_dlg = new SupportedProtocolsDialog(this);
2505     supported_protocols_dlg->show();
2506 }
2507
2508 void MainWindow::on_actionViewShowPacketInNewWindow_triggered()
2509 {
2510     openPacketDialog();
2511 }
2512
2513 // This is only used in ProtoTree. Defining it here makes more sense.
2514 void MainWindow::on_actionContextShowLinkedPacketInNewWindow_triggered()
2515 {
2516     openPacketDialog(true);
2517 }
2518
2519 void MainWindow::on_actionViewReload_triggered()
2520 {
2521     capture_file *cf = CaptureFile::globalCapFile();
2522
2523     if (cf->unsaved_changes) {
2524         QString before_what(tr(" before reloading the file"));
2525         if (!testCaptureFileClose(before_what, Reload))
2526             return;
2527     }
2528
2529     cf_reload(cf);
2530 }
2531
2532 void MainWindow::on_actionViewReload_as_File_Format_or_Capture_triggered()
2533 {
2534     capture_file *cf = CaptureFile::globalCapFile();
2535
2536     if (cf->unsaved_changes) {
2537         QString before_what(tr(" before reloading the file"));
2538         if (!testCaptureFileClose(before_what, Reload))
2539             return;
2540     }
2541
2542     if (cf->open_type == WTAP_TYPE_AUTO)
2543         cf->open_type = open_info_name_to_type("MIME Files Format");
2544     else /* TODO: This should be latest format chosen by user */
2545         cf->open_type = WTAP_TYPE_AUTO;
2546
2547     cf_reload(cf);
2548 }
2549
2550
2551 // Expand / collapse slots in proto_tree
2552
2553 // Go Menu
2554
2555 // Analyze Menu
2556
2557 void MainWindow::matchFieldFilter(FilterAction::Action action, FilterAction::ActionType filter_type)
2558 {
2559     QString field_filter;
2560
2561     if (packet_list_->contextMenuActive() || packet_list_->hasFocus()) {
2562         field_filter = packet_list_->getFilterFromRowAndColumn();
2563     } else if (capture_file_.capFile() && capture_file_.capFile()->finfo_selected) {
2564         char *tmp_field = proto_construct_match_selected_string(capture_file_.capFile()->finfo_selected,
2565                                                        capture_file_.capFile()->edt);
2566         field_filter = QString(tmp_field);
2567         wmem_free(NULL, tmp_field);
2568     }
2569
2570     if (field_filter.isEmpty()) {
2571         QString err = tr("No filter available. Try another ");
2572         err.append(packet_list_->contextMenuActive() ? "column" : "item");
2573         err.append(".");
2574         main_ui_->statusBar->pushTemporaryStatus(err);
2575         return;
2576     }
2577
2578     emit filterAction(field_filter, action, filter_type);
2579 }
2580
2581 static FilterDialog *display_filter_dlg_ = NULL;
2582 void MainWindow::on_actionAnalyzeDisplayFilters_triggered()
2583 {
2584     if (!display_filter_dlg_) {
2585         display_filter_dlg_ = new FilterDialog(this, FilterDialog::DisplayFilter);
2586     }
2587     display_filter_dlg_->show();
2588     display_filter_dlg_->raise();
2589     display_filter_dlg_->activateWindow();
2590 }
2591
2592 struct epan_uat;
2593 void MainWindow::on_actionAnalyzeDisplayFilterMacros_triggered()
2594 {
2595     struct epan_uat* dfm_uat;
2596     dfilter_macro_get_uat(&dfm_uat);
2597     UatDialog uat_dlg(parentWidget(), dfm_uat);
2598
2599     uat_dlg.exec();
2600     // Emitting PacketDissectionChanged directly from a QDialog can cause
2601     // problems on OS X.
2602     wsApp->flushAppSignals();
2603 }
2604
2605 void MainWindow::on_actionAnalyzeCreateAColumn_triggered()
2606 {
2607     gint colnr = 0;
2608
2609     if (capture_file_.capFile() != 0 && capture_file_.capFile()->finfo_selected != 0) {
2610         colnr = column_prefs_add_custom(COL_CUSTOM, capture_file_.capFile()->finfo_selected->hfinfo->name,
2611                     capture_file_.capFile()->finfo_selected->hfinfo->abbrev,0);
2612
2613         packet_list_->columnsChanged();
2614         packet_list_->resizeColumnToContents(colnr);
2615
2616         prefs_main_write();
2617     }
2618 }
2619
2620 void MainWindow::applyConversationFilter()
2621 {
2622     ConversationAction *conv_action = qobject_cast<ConversationAction*>(sender());
2623     if (!conv_action) return;
2624
2625     packet_info *pinfo = capture_file_.packetInfo();
2626     if (!pinfo) return;
2627
2628     QByteArray conv_filter = conv_action->filter();
2629     if (conv_filter.isEmpty()) return;
2630
2631     if (conv_action->isFilterValid(pinfo)) {
2632
2633         df_combo_box_->lineEdit()->setText(conv_filter);
2634         df_combo_box_->applyDisplayFilter();
2635     }
2636 }
2637
2638 // XXX We could probably create the analyze and prepare actions
2639 // dynamically using FilterActions and consolidate the methods
2640 // below into one callback.
2641 void MainWindow::on_actionAnalyzeAAFSelected_triggered()
2642 {
2643     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypePlain);
2644 }
2645
2646 void MainWindow::on_actionAnalyzeAAFNotSelected_triggered()
2647 {
2648     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeNot);
2649 }
2650
2651 void MainWindow::on_actionAnalyzeAAFAndSelected_triggered()
2652 {
2653     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeAnd);
2654 }
2655
2656 void MainWindow::on_actionAnalyzeAAFOrSelected_triggered()
2657 {
2658     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeOr);
2659 }
2660
2661 void MainWindow::on_actionAnalyzeAAFAndNotSelected_triggered()
2662 {
2663     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeAndNot);
2664 }
2665
2666 void MainWindow::on_actionAnalyzeAAFOrNotSelected_triggered()
2667 {
2668     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeOrNot);
2669 }
2670
2671 void MainWindow::on_actionAnalyzePAFSelected_triggered()
2672 {
2673     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypePlain);
2674 }
2675
2676 void MainWindow::on_actionAnalyzePAFNotSelected_triggered()
2677 {
2678     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeNot);
2679 }
2680
2681 void MainWindow::on_actionAnalyzePAFAndSelected_triggered()
2682 {
2683     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeAnd);
2684 }
2685
2686 void MainWindow::on_actionAnalyzePAFOrSelected_triggered()
2687 {
2688     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeOr);
2689 }
2690
2691 void MainWindow::on_actionAnalyzePAFAndNotSelected_triggered()
2692 {
2693     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeAndNot);
2694 }
2695
2696 void MainWindow::on_actionAnalyzePAFOrNotSelected_triggered()
2697 {
2698     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeOrNot);
2699 }
2700
2701 void MainWindow::on_actionAnalyzeEnabledProtocols_triggered()
2702 {
2703     EnabledProtocolsDialog enable_proto_dialog(this);
2704     enable_proto_dialog.exec();
2705
2706     // Emitting PacketDissectionChanged directly from a QDialog can cause
2707     // problems on OS X.
2708     wsApp->flushAppSignals();
2709 }
2710
2711 void MainWindow::on_actionAnalyzeDecodeAs_triggered()
2712 {
2713     QAction *da_action = qobject_cast<QAction*>(sender());
2714     bool create_new = false;
2715     if (da_action && da_action->data().toBool() == true) {
2716         create_new = true;
2717     }
2718
2719     DecodeAsDialog da_dialog(this, capture_file_.capFile(), create_new);
2720     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2721             &da_dialog, SLOT(setCaptureFile(capture_file*)));
2722     da_dialog.exec();
2723
2724     // Emitting PacketDissectionChanged directly from a QDialog can cause
2725     // problems on OS X.
2726     wsApp->flushAppSignals();
2727 }
2728
2729 void MainWindow::on_actionAnalyzeReloadLuaPlugins_triggered()
2730 {
2731     reloadLuaPlugins();
2732 }
2733
2734 void MainWindow::openFollowStreamDialog(follow_type_t type) {
2735     FollowStreamDialog *fsd = new FollowStreamDialog(*this, capture_file_, type);
2736     connect(fsd, SIGNAL(updateFilter(QString, bool)), this, SLOT(filterPackets(QString, bool)));
2737     connect(fsd, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
2738
2739     fsd->show();
2740     fsd->follow(getFilter());
2741 }
2742
2743 void MainWindow::on_actionAnalyzeFollowTCPStream_triggered()
2744 {
2745     openFollowStreamDialog(FOLLOW_TCP);
2746 }
2747
2748 void MainWindow::on_actionAnalyzeFollowUDPStream_triggered()
2749 {
2750     openFollowStreamDialog(FOLLOW_UDP);
2751 }
2752
2753 void MainWindow::on_actionAnalyzeFollowSSLStream_triggered()
2754 {
2755     openFollowStreamDialog(FOLLOW_SSL);
2756 }
2757
2758 void MainWindow::on_actionAnalyzeFollowHTTPStream_triggered()
2759 {
2760     openFollowStreamDialog(FOLLOW_HTTP);
2761 }
2762
2763 void MainWindow::openSCTPAllAssocsDialog()
2764 {
2765     SCTPAllAssocsDialog *sctp_dialog = new SCTPAllAssocsDialog(this, capture_file_.capFile());
2766     connect(sctp_dialog, SIGNAL(filterPackets(QString,bool)),
2767             this, SLOT(filterPackets(QString,bool)));
2768     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2769             sctp_dialog, SLOT(setCaptureFile(capture_file*)));
2770     sctp_dialog->fillTable();
2771
2772     if (sctp_dialog->isMinimized() == true)
2773     {
2774         sctp_dialog->showNormal();
2775     }
2776     else
2777     {
2778         sctp_dialog->show();
2779     }
2780
2781     sctp_dialog->raise();
2782     sctp_dialog->activateWindow();
2783 }
2784
2785 void MainWindow::on_actionSCTPShowAllAssociations_triggered()
2786 {
2787     openSCTPAllAssocsDialog();
2788 }
2789
2790 void MainWindow::on_actionSCTPAnalyseThisAssociation_triggered()
2791 {
2792     SCTPAssocAnalyseDialog *sctp_analyse = new SCTPAssocAnalyseDialog(this, NULL, capture_file_.capFile());
2793     connect(sctp_analyse, SIGNAL(filterPackets(QString,bool)),
2794             this, SLOT(filterPackets(QString,bool)));
2795
2796     if (sctp_analyse->isMinimized() == true)
2797     {
2798         sctp_analyse->showNormal();
2799     }
2800     else
2801     {
2802         sctp_analyse->show();
2803     }
2804
2805     sctp_analyse->raise();
2806     sctp_analyse->activateWindow();
2807 }
2808
2809 void MainWindow::on_actionSCTPFilterThisAssociation_triggered()
2810 {
2811     sctp_assoc_info_t* assoc = SCTPAssocAnalyseDialog::findAssocForPacket(capture_file_.capFile());
2812     if (assoc) {
2813         QString newFilter = QString("sctp.assoc_index==%1").arg(assoc->assoc_id);
2814         assoc = NULL;
2815         emit filterPackets(newFilter, false);
2816     }
2817 }
2818
2819 // -z wlan,stat
2820 void MainWindow::statCommandWlanStatistics(const char *arg, void *)
2821 {
2822     WlanStatisticsDialog *wlan_stats_dlg = new WlanStatisticsDialog(*this, capture_file_, arg);
2823     connect(wlan_stats_dlg, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
2824             this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
2825     wlan_stats_dlg->show();
2826 }
2827
2828 void MainWindow::on_actionWirelessWlanStatistics_triggered()
2829 {
2830     statCommandWlanStatistics(NULL, NULL);
2831 }
2832
2833 // -z expert
2834 void MainWindow::statCommandExpertInfo(const char *, void *)
2835 {
2836     ExpertInfoDialog *expert_dialog = new ExpertInfoDialog(*this, capture_file_);
2837     const DisplayFilterEdit *df_edit = dynamic_cast<DisplayFilterEdit *>(df_combo_box_->lineEdit());
2838
2839     expert_dialog->setDisplayFilter(df_edit->text());
2840
2841     connect(expert_dialog, SIGNAL(goToPacket(int, int)),
2842             packet_list_, SLOT(goToPacket(int, int)));
2843     connect(expert_dialog, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
2844             this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
2845
2846     expert_dialog->show();
2847 }
2848
2849 void MainWindow::on_actionAnalyzeExpertInfo_triggered()
2850 {
2851     statCommandExpertInfo(NULL, NULL);
2852 }
2853
2854
2855 // Next / previous / first / last slots in packet_list
2856
2857 // Statistics Menu
2858
2859 void MainWindow::on_actionStatisticsFlowGraph_triggered()
2860 {
2861     SequenceDialog *sequence_dialog = new SequenceDialog(*this, capture_file_);
2862     connect(sequence_dialog, SIGNAL(goToPacket(int)),
2863             packet_list_, SLOT(goToPacket(int)));
2864     sequence_dialog->show();
2865 }
2866
2867 void MainWindow::openTcpStreamDialog(int graph_type)
2868 {
2869     TCPStreamDialog *stream_dialog = new TCPStreamDialog(this, capture_file_.capFile(), (tcp_graph_type)graph_type);
2870     connect(stream_dialog, SIGNAL(goToPacket(int)),
2871             packet_list_, SLOT(goToPacket(int)));
2872     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2873             stream_dialog, SLOT(setCaptureFile(capture_file*)));
2874     if (stream_dialog->result() == QDialog::Accepted) {
2875         stream_dialog->show();
2876     }
2877 }
2878
2879 void MainWindow::on_actionStatisticsTcpStreamStevens_triggered()
2880 {
2881     openTcpStreamDialog(GRAPH_TSEQ_STEVENS);
2882 }
2883
2884 void MainWindow::on_actionStatisticsTcpStreamTcptrace_triggered()
2885 {
2886     openTcpStreamDialog(GRAPH_TSEQ_TCPTRACE);
2887 }
2888
2889 void MainWindow::on_actionStatisticsTcpStreamThroughput_triggered()
2890 {
2891     openTcpStreamDialog(GRAPH_THROUGHPUT);
2892 }
2893
2894 void MainWindow::on_actionStatisticsTcpStreamRoundTripTime_triggered()
2895 {
2896     openTcpStreamDialog(GRAPH_RTT);
2897 }
2898
2899 void MainWindow::on_actionStatisticsTcpStreamWindowScaling_triggered()
2900 {
2901     openTcpStreamDialog(GRAPH_WSCALE);
2902 }
2903
2904 // -z mcast,stat
2905 void MainWindow::statCommandMulticastStatistics(const char *arg, void *)
2906 {
2907     MulticastStatisticsDialog *mcast_stats_dlg = new MulticastStatisticsDialog(*this, capture_file_, arg);
2908     connect(mcast_stats_dlg, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
2909             this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
2910     mcast_stats_dlg->show();
2911 }
2912
2913 void MainWindow::on_actionStatisticsUdpMulticastStreams_triggered()
2914 {
2915     statCommandMulticastStatistics(NULL, NULL);
2916 }
2917
2918 void MainWindow::openStatisticsTreeDialog(const gchar *abbr)
2919 {
2920     StatsTreeDialog *st_dialog = new StatsTreeDialog(*this, capture_file_, abbr);
2921 //    connect(st_dialog, SIGNAL(goToPacket(int)),
2922 //            packet_list_, SLOT(goToPacket(int)));
2923     st_dialog->show();
2924 }
2925
2926 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Topic_triggered()
2927 {
2928     openStatisticsTreeDialog("lbmr_topic_ads_topic");
2929 }
2930
2931 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Source_triggered()
2932 {
2933     openStatisticsTreeDialog("lbmr_topic_ads_source");
2934 }
2935
2936 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Transport_triggered()
2937 {
2938     openStatisticsTreeDialog("lbmr_topic_ads_transport");
2939 }
2940
2941 void MainWindow::on_actionStatistics29WestTopics_Queries_by_Topic_triggered()
2942 {
2943     openStatisticsTreeDialog("lbmr_topic_queries_topic");
2944 }
2945
2946 void MainWindow::on_actionStatistics29WestTopics_Queries_by_Receiver_triggered()
2947 {
2948     openStatisticsTreeDialog("lbmr_topic_queries_receiver");
2949 }
2950
2951 void MainWindow::on_actionStatistics29WestTopics_Wildcard_Queries_by_Pattern_triggered()
2952 {
2953     openStatisticsTreeDialog("lbmr_topic_queries_pattern");
2954 }
2955
2956 void MainWindow::on_actionStatistics29WestTopics_Wildcard_Queries_by_Receiver_triggered()
2957 {
2958     openStatisticsTreeDialog("lbmr_topic_queries_pattern_receiver");
2959 }
2960
2961 void MainWindow::on_actionStatistics29WestQueues_Advertisements_by_Queue_triggered()
2962 {
2963     openStatisticsTreeDialog("lbmr_queue_ads_queue");
2964 }
2965
2966 void MainWindow::on_actionStatistics29WestQueues_Advertisements_by_Source_triggered()
2967 {
2968     openStatisticsTreeDialog("lbmr_queue_ads_source");
2969 }
2970
2971 void MainWindow::on_actionStatistics29WestQueues_Queries_by_Queue_triggered()
2972 {
2973     openStatisticsTreeDialog("lbmr_queue_queries_queue");
2974 }
2975
2976 void MainWindow::on_actionStatistics29WestQueues_Queries_by_Receiver_triggered()
2977 {
2978     openStatisticsTreeDialog("lbmr_queue_queries_receiver");
2979 }
2980
2981 void MainWindow::on_actionStatistics29WestUIM_Streams_triggered()
2982 {
2983     LBMStreamDialog *stream_dialog = new LBMStreamDialog(this, capture_file_.capFile());
2984 //    connect(stream_dialog, SIGNAL(goToPacket(int)),
2985 //            packet_list_, SLOT(goToPacket(int)));
2986     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2987             stream_dialog, SLOT(setCaptureFile(capture_file*)));
2988     stream_dialog->show();
2989 }
2990
2991 void MainWindow::on_actionStatistics29WestUIM_Stream_Flow_Graph_triggered()
2992 {
2993     LBMUIMFlowDialog * uimflow_dialog = new LBMUIMFlowDialog(this, capture_file_.capFile());
2994     connect(uimflow_dialog, SIGNAL(goToPacket(int)),
2995             packet_list_, SLOT(goToPacket(int)));
2996     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2997             uimflow_dialog, SLOT(setCaptureFile(capture_file*)));
2998     uimflow_dialog->show();
2999 }
3000
3001 void MainWindow::on_actionStatistics29WestLBTRM_triggered()
3002 {
3003     LBMLBTRMTransportDialog * lbtrm_dialog = new LBMLBTRMTransportDialog(this, capture_file_.capFile());
3004     connect(lbtrm_dialog, SIGNAL(goToPacket(int)),
3005             packet_list_, SLOT(goToPacket(int)));
3006     connect(this, SIGNAL(setCaptureFile(capture_file*)),
3007             lbtrm_dialog, SLOT(setCaptureFile(capture_file*)));
3008     lbtrm_dialog->show();
3009 }
3010 void MainWindow::on_actionStatistics29WestLBTRU_triggered()
3011 {
3012     LBMLBTRUTransportDialog * lbtru_dialog = new LBMLBTRUTransportDialog(this, capture_file_.capFile());
3013     connect(lbtru_dialog, SIGNAL(goToPacket(int)),
3014             packet_list_, SLOT(goToPacket(int)));
3015     connect(this, SIGNAL(setCaptureFile(capture_file*)),
3016             lbtru_dialog, SLOT(setCaptureFile(capture_file*)));
3017     lbtru_dialog->show();
3018 }
3019
3020 void MainWindow::on_actionStatisticsANCP_triggered()
3021 {
3022     openStatisticsTreeDialog("ancp");
3023 }
3024
3025 void MainWindow::on_actionStatisticsBACappInstanceId_triggered()
3026 {
3027     openStatisticsTreeDialog("bacapp_instanceid");
3028 }
3029
3030 void MainWindow::on_actionStatisticsBACappIP_triggered()
3031 {
3032     openStatisticsTreeDialog("bacapp_ip");
3033 }
3034
3035 void MainWindow::on_actionStatisticsBACappObjectId_triggered()
3036 {
3037     openStatisticsTreeDialog("bacapp_objectid");
3038 }
3039
3040 void MainWindow::on_actionStatisticsBACappService_triggered()
3041 {
3042     openStatisticsTreeDialog("bacapp_service");
3043 }
3044
3045 void MainWindow::on_actionStatisticsCollectd_triggered()
3046 {
3047     openStatisticsTreeDialog("collectd");
3048 }
3049
3050 // -z conv,...
3051 void MainWindow::statCommandConversations(const char *arg, void *userdata)
3052 {
3053     ConversationDialog *conv_dialog = new ConversationDialog(*this, capture_file_, GPOINTER_TO_INT(userdata), arg);
3054     connect(conv_dialog, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
3055             this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
3056     connect(conv_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
3057             this, SLOT(openFollowStreamDialog(follow_type_t)));
3058     connect(conv_dialog, SIGNAL(openTcpStreamGraph(int)),
3059             this, SLOT(openTcpStreamDialog(int)));
3060     conv_dialog->show();
3061 }
3062
3063 void MainWindow::on_actionStatisticsConversations_triggered()
3064 {
3065     statCommandConversations(NULL, NULL);
3066 }
3067
3068 // -z endpoints,...
3069 void MainWindow::statCommandEndpoints(const char *arg, void *userdata)
3070 {
3071     EndpointDialog *endp_dialog = new EndpointDialog(*this, capture_file_, GPOINTER_TO_INT(userdata), arg);
3072     connect(endp_dialog, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
3073             this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
3074     connect(endp_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
3075             this, SLOT(openFollowStreamDialog(follow_type_t)));
3076     connect(endp_dialog, SIGNAL(openTcpStreamGraph(int)),
3077             this, SLOT(openTcpStreamDialog(int)));
3078     endp_dialog->show();
3079 }
3080
3081 void MainWindow::on_actionStatisticsEndpoints_triggered()
3082 {
3083     statCommandEndpoints(NULL, NULL);
3084 }
3085
3086 void MainWindow::on_actionStatisticsHART_IP_triggered()
3087 {
3088     openStatisticsTreeDialog("hart_ip");
3089 }
3090
3091 void MainWindow::on_actionStatisticsHTTPPacketCounter_triggered()
3092 {
3093     openStatisticsTreeDialog("http");
3094 }
3095
3096 void MainWindow::on_actionStatisticsHTTPRequests_triggered()
3097 {
3098     openStatisticsTreeDialog("http_req");
3099 }
3100
3101 void MainWindow::on_actionStatisticsHTTPLoadDistribution_triggered()
3102 {
3103     openStatisticsTreeDialog("http_srv");
3104 }
3105
3106 void MainWindow::on_actionStatisticsPacketLengths_triggered()
3107 {
3108     openStatisticsTreeDialog("plen");
3109 }
3110
3111 // -z io,stat
3112 void MainWindow::statCommandIOGraph(const char *, void *)
3113 {
3114     IOGraphDialog *iog_dialog = new IOGraphDialog(*this, capture_file_);
3115     connect(iog_dialog, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
3116     connect(this, SIGNAL(reloadFields()), iog_dialog, SLOT(reloadFields()));
3117     iog_dialog->show();
3118 }
3119
3120 void MainWindow::on_actionStatisticsIOGraph_triggered()
3121 {
3122     statCommandIOGraph(NULL, NULL);
3123 }
3124
3125 void MainWindow::on_actionStatisticsSametime_triggered()
3126 {
3127     openStatisticsTreeDialog("sametime");
3128 }
3129
3130 void MainWindow::on_actionStatisticsDNS_triggered()
3131 {
3132     openStatisticsTreeDialog("dns");
3133 }
3134
3135 void MainWindow::actionStatisticsPlugin_triggered()
3136 {
3137     QAction* action = qobject_cast<QAction*>(sender());
3138     if(action) {
3139         openStatisticsTreeDialog(action->data().toString().toUtf8());
3140     }
3141 }
3142
3143 void MainWindow::on_actionStatisticsHTTP2_triggered()
3144 {
3145     openStatisticsTreeDialog("http2");
3146
3147 }
3148
3149 // Telephony Menu
3150
3151 void MainWindow::openVoipCallsDialog(bool all_flows)
3152 {
3153     VoipCallsDialog *voip_calls_dialog = new VoipCallsDialog(*this, capture_file_, all_flows);
3154     connect(voip_calls_dialog, SIGNAL(goToPacket(int)),
3155             packet_list_, SLOT(goToPacket(int)));
3156     connect(voip_calls_dialog, SIGNAL(updateFilter(QString, bool)),
3157             this, SLOT(filterPackets(QString, bool)));
3158     voip_calls_dialog->show();
3159 }
3160
3161 void MainWindow::on_actionTelephonyVoipCalls_triggered()
3162 {
3163     openVoipCallsDialog();
3164 }
3165
3166 void MainWindow::on_actionTelephonyGsmMapSummary_triggered()
3167 {
3168     GsmMapSummaryDialog *gms_dialog = new GsmMapSummaryDialog(*this, capture_file_);
3169     gms_dialog->show();
3170 }
3171
3172 void MainWindow::on_actionTelephonyIax2StreamAnalysis_triggered()
3173 {
3174     Iax2AnalysisDialog *iax2_analysis_dialog = new  Iax2AnalysisDialog(*this, capture_file_);
3175     connect(iax2_analysis_dialog, SIGNAL(goToPacket(int)),
3176             packet_list_, SLOT(goToPacket(int)));
3177     iax2_analysis_dialog->show();
3178 }
3179
3180 void MainWindow::on_actionTelephonyISUPMessages_triggered()
3181 {
3182     openStatisticsTreeDialog("isup_msg");
3183 }
3184
3185 // -z mac-lte,stat
3186 void MainWindow::statCommandLteMacStatistics(const char *arg, void *)
3187 {
3188     LteMacStatisticsDialog *lte_mac_stats_dlg = new LteMacStatisticsDialog(*this, capture_file_, arg);
3189     connect(lte_mac_stats_dlg, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
3190             this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
3191     lte_mac_stats_dlg->show();
3192 }
3193
3194 void MainWindow::on_actionTelephonyLteMacStatistics_triggered()
3195 {
3196     statCommandLteMacStatistics(NULL, NULL);
3197 }
3198
3199 void MainWindow::statCommandLteRlcStatistics(const char *arg, void *)
3200 {
3201     LteRlcStatisticsDialog *lte_rlc_stats_dlg = new LteRlcStatisticsDialog(*this, capture_file_, arg);
3202     connect(lte_rlc_stats_dlg, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
3203             this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
3204     // N.B. It is necessary for the RLC Statistics window to launch the RLC graph in this way, to ensure
3205     // that the goToPacket() signal/slot connection gets set up...
3206     connect(lte_rlc_stats_dlg, SIGNAL(launchRLCGraph(bool, guint16, guint8, guint16, guint16, guint8)),
3207             this, SLOT(launchRLCGraph(bool, guint16, guint8, guint16, guint16, guint8)));
3208
3209     lte_rlc_stats_dlg->show();
3210 }
3211
3212 void MainWindow::on_actionTelephonyLteRlcStatistics_triggered()
3213 {
3214     statCommandLteRlcStatistics(NULL, NULL);
3215 }
3216
3217 void MainWindow::launchRLCGraph(bool channelKnown,
3218                                 guint16 ueid, guint8 rlcMode,
3219                                 guint16 channelType, guint16 channelId, guint8 direction)
3220 {
3221     LteRlcGraphDialog *lrg_dialog = new LteRlcGraphDialog(*this, capture_file_, channelKnown);
3222     connect(lrg_dialog, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
3223     // This is a bit messy, but wanted to hide these parameters from users of
3224     // on_actionTelephonyLteRlcGraph_triggered().
3225     if (channelKnown) {
3226         lrg_dialog->setChannelInfo(ueid, rlcMode, channelType, channelId, direction);
3227     }
3228     lrg_dialog->show();
3229 }
3230
3231 void MainWindow::on_actionTelephonyLteRlcGraph_triggered()
3232 {
3233     // We don't yet know the channel.
3234     launchRLCGraph(false, 0, 0, 0, 0, 0);
3235 }
3236
3237 void MainWindow::on_actionTelephonyMtp3Summary_triggered()
3238 {
3239     Mtp3SummaryDialog *mtp3s_dialog = new Mtp3SummaryDialog(*this, capture_file_);
3240     mtp3s_dialog->show();
3241 }
3242
3243 void MainWindow::on_actionTelephonyRTPStreams_triggered()
3244 {
3245     RtpStreamDialog *rtp_stream_dialog = new  RtpStreamDialog(*this, capture_file_);
3246     connect(rtp_stream_dialog, SIGNAL(packetsMarked()),
3247             packet_list_, SLOT(redrawVisiblePackets()));
3248     connect(rtp_stream_dialog, SIGNAL(goToPacket(int)),
3249             packet_list_, SLOT(goToPacket(int)));
3250     connect(rtp_stream_dialog, SIGNAL(updateFilter(QString, bool)),
3251             this, SLOT(filterPackets(QString, bool)));
3252     rtp_stream_dialog->show();
3253 }
3254
3255 void MainWindow::on_actionTelephonyRTPStreamAnalysis_triggered()
3256 {
3257     RtpAnalysisDialog *rtp_analysis_dialog = new  RtpAnalysisDialog(*this, capture_file_);
3258     connect(rtp_analysis_dialog, SIGNAL(goToPacket(int)),
3259             packet_list_, SLOT(goToPacket(int)));
3260     rtp_analysis_dialog->show();
3261 }
3262
3263 void MainWindow::on_actionTelephonyRTSPPacketCounter_triggered()
3264 {
3265     openStatisticsTreeDialog("rtsp");
3266 }
3267
3268 void MainWindow::on_actionTelephonySMPPOperations_triggered()
3269 {
3270     openStatisticsTreeDialog("smpp_commands");
3271 }
3272
3273 void MainWindow::on_actionTelephonyUCPMessages_triggered()
3274 {
3275     openStatisticsTreeDialog("ucp_messages");
3276 }
3277
3278 void MainWindow::on_actionTelephonySipFlows_triggered()
3279 {
3280     openVoipCallsDialog(true);
3281 }
3282
3283 // Wireless Menu
3284
3285 void MainWindow::on_actionBluetoothATT_Server_Attributes_triggered()
3286 {
3287     BluetoothAttServerAttributesDialog *bluetooth_att_sever_attributes_dialog = new BluetoothAttServerAttributesDialog(*this, capture_file_);
3288     connect(bluetooth_att_sever_attributes_dialog, SIGNAL(goToPacket(int)),
3289             packet_list_, SLOT(goToPacket(int)));
3290     connect(bluetooth_att_sever_attributes_dialog, SIGNAL(updateFilter(QString, bool)),
3291             this, SLOT(filterPackets(QString, bool)));
3292     bluetooth_att_sever_attributes_dialog->show();
3293 }
3294
3295 void MainWindow::on_actionBluetoothDevices_triggered()
3296 {
3297     BluetoothDevicesDialog *bluetooth_devices_dialog = new BluetoothDevicesDialog(*this, capture_file_, packet_list_);
3298     connect(bluetooth_devices_dialog, SIGNAL(goToPacket(int)),
3299             packet_list_, SLOT(goToPacket(int)));
3300     connect(bluetooth_devices_dialog, SIGNAL(updateFilter(QString, bool)),
3301             this, SLOT(filterPackets(QString, bool)));
3302     bluetooth_devices_dialog->show();
3303 }
3304
3305 void MainWindow::on_actionBluetoothHCI_Summary_triggered()
3306 {
3307     BluetoothHciSummaryDialog *bluetooth_hci_summary_dialog = new BluetoothHciSummaryDialog(*this, capture_file_);
3308     connect(bluetooth_hci_summary_dialog, SIGNAL(goToPacket(int)),
3309             packet_list_, SLOT(goToPacket(int)));
3310     connect(bluetooth_hci_summary_dialog, SIGNAL(updateFilter(QString, bool)),
3311             this, SLOT(filterPackets(QString, bool)));
3312     bluetooth_hci_summary_dialog->show();
3313 }
3314
3315 // Tools Menu
3316
3317 void MainWindow::on_actionToolsFirewallAclRules_triggered()
3318 {
3319     FirewallRulesDialog *firewall_rules_dialog = new FirewallRulesDialog(*this, capture_file_);
3320     firewall_rules_dialog->show();
3321 }
3322
3323
3324 // Help Menu
3325 void MainWindow::on_actionHelpContents_triggered() {
3326
3327     wsApp->helpTopicAction(HELP_CONTENT);
3328 }
3329
3330 void MainWindow::on_actionHelpMPWireshark_triggered() {
3331
3332     wsApp->helpTopicAction(LOCALPAGE_MAN_WIRESHARK);
3333 }
3334
3335 void MainWindow::on_actionHelpMPWireshark_Filter_triggered() {
3336     wsApp->helpTopicAction(LOCALPAGE_MAN_WIRESHARK_FILTER);
3337 }
3338
3339 void MainWindow::on_actionHelpMPCapinfos_triggered() {
3340     wsApp->helpTopicAction(LOCALPAGE_MAN_CAPINFOS);
3341 }
3342
3343 void MainWindow::on_actionHelpMPDumpcap_triggered() {
3344     wsApp->helpTopicAction(LOCALPAGE_MAN_DUMPCAP);
3345 }
3346
3347 void MainWindow::on_actionHelpMPEditcap_triggered() {
3348     wsApp->helpTopicAction(LOCALPAGE_MAN_EDITCAP);
3349 }
3350
3351 void MainWindow::on_actionHelpMPMergecap_triggered() {
3352     wsApp->helpTopicAction(LOCALPAGE_MAN_MERGECAP);
3353 }
3354
3355 void MainWindow::on_actionHelpMPRawShark_triggered() {
3356     wsApp->helpTopicAction(LOCALPAGE_MAN_RAWSHARK);
3357 }
3358
3359 void MainWindow::on_actionHelpMPReordercap_triggered() {
3360     wsApp->helpTopicAction(LOCALPAGE_MAN_REORDERCAP);
3361 }
3362
3363  void MainWindow::on_actionHelpMPText2cap_triggered() {
3364     wsApp->helpTopicAction(LOCALPAGE_MAN_TEXT2PCAP);
3365 }
3366
3367 void MainWindow::on_actionHelpMPTShark_triggered() {
3368     wsApp->helpTopicAction(LOCALPAGE_MAN_TSHARK);
3369 }
3370
3371 void MainWindow::on_actionHelpWebsite_triggered() {
3372
3373     wsApp->helpTopicAction(ONLINEPAGE_HOME);
3374 }
3375
3376 void MainWindow::on_actionHelpFAQ_triggered() {
3377
3378     wsApp->helpTopicAction(ONLINEPAGE_FAQ);
3379 }
3380
3381 void MainWindow::on_actionHelpAsk_triggered() {
3382
3383     wsApp->helpTopicAction(ONLINEPAGE_ASK);
3384 }
3385
3386 void MainWindow::on_actionHelpDownloads_triggered() {
3387
3388     wsApp->helpTopicAction(ONLINEPAGE_DOWNLOAD);
3389 }
3390
3391 void MainWindow::on_actionHelpWiki_triggered() {
3392
3393     wsApp->helpTopicAction(ONLINEPAGE_WIKI);
3394 }
3395
3396 void MainWindow::on_actionHelpSampleCaptures_triggered() {
3397
3398     wsApp->helpTopicAction(ONLINEPAGE_SAMPLE_FILES);
3399 }
3400
3401 #ifdef HAVE_SOFTWARE_UPDATE
3402 void MainWindow::checkForUpdates()
3403 {
3404     software_update_check();
3405 }
3406 #endif
3407
3408 void MainWindow::on_actionHelpAbout_triggered()
3409 {
3410     AboutDialog *about_dialog = new AboutDialog(this);
3411
3412     if (about_dialog->isMinimized() == true)
3413     {
3414         about_dialog->showNormal();
3415     }
3416     else
3417     {
3418         about_dialog->show();
3419     }
3420
3421     about_dialog->raise();
3422     about_dialog->activateWindow();
3423 }
3424
3425 void MainWindow::on_actionGoGoToPacket_triggered() {
3426     if (packet_list_->packetListModel()->rowCount() < 1) {
3427         return;
3428     }
3429     previous_focus_ = wsApp->focusWidget();
3430     connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
3431
3432     showAccordionFrame(main_ui_->goToFrame, true);
3433     if (main_ui_->goToFrame->isVisible()) {
3434         main_ui_->goToLineEdit->clear();
3435         main_ui_->goToLineEdit->setFocus();
3436     }
3437 }
3438
3439 void MainWindow::on_actionGoGoToLinkedPacket_triggered()
3440 {
3441     QAction *gta = qobject_cast<QAction*>(sender());
3442     if (!gta) return;
3443
3444     bool ok = false;
3445     int packet_num = gta->data().toInt(&ok);
3446     if (!ok) return;
3447
3448     packet_list_->goToPacket(packet_num);
3449 }
3450
3451 // gtk/main_menubar.c:goto_conversation_frame
3452 void MainWindow::goToConversationFrame(bool go_next) {
3453     gchar     *filter       = NULL;
3454     dfilter_t *dfcode       = NULL;
3455     gboolean   found_packet = FALSE;
3456     packet_info *pi = &(capture_file_.capFile()->edt->pi);
3457     conversation_filter_t* conv_filter;
3458
3459     /* Try to build a conversation
3460      * filter in the order TCP, UDP, IP, Ethernet and apply the
3461      * coloring */
3462     conv_filter = find_conversation_filter("tcp");
3463     if ((conv_filter != NULL) && (conv_filter->is_filter_valid(pi)))
3464         filter = conv_filter->build_filter_string(pi);
3465     conv_filter = find_conversation_filter("udp");
3466     if ((conv_filter != NULL) && (conv_filter->is_filter_valid(pi)))
3467         filter = conv_filter->build_filter_string(pi);
3468     conv_filter = find_conversation_filter("ip");
3469     if ((conv_filter != NULL) && (conv_filter->is_filter_valid(pi)))
3470         filter = conv_filter->build_filter_string(pi);
3471     conv_filter = find_conversation_filter("ipv6");
3472     if ((conv_filter != NULL) && (conv_filter->is_filter_valid(pi)))
3473         filter = conv_filter->build_filter_string(pi);
3474
3475     if (filter == NULL) {
3476         main_ui_->statusBar->pushTemporaryStatus(tr("Unable to build conversation filter."));
3477         g_free(filter);
3478         return;
3479     }
3480
3481     if (!dfilter_compile(filter, &dfcode, NULL)) {
3482         /* The attempt failed; report an error. */
3483         main_ui_->statusBar->pushTemporaryStatus(tr("Error compiling filter for this conversation."));
3484         g_free(filter);
3485         return;
3486     }
3487
3488     found_packet = cf_find_packet_dfilter(capture_file_.capFile(), dfcode, go_next ? SD_FORWARD : SD_BACKWARD);
3489
3490     if (!found_packet) {
3491         /* We didn't find a packet */
3492         main_ui_->statusBar->pushTemporaryStatus(tr("No previous/next packet in conversation."));
3493     }
3494
3495     dfilter_free(dfcode);
3496     g_free(filter);
3497 }
3498
3499 void MainWindow::on_actionGoNextConversationPacket_triggered()
3500 {
3501     goToConversationFrame(true);
3502 }
3503
3504 void MainWindow::on_actionGoPreviousConversationPacket_triggered()
3505 {
3506     goToConversationFrame(false);
3507 }
3508
3509 void MainWindow::on_actionGoAutoScroll_toggled(bool checked)
3510 {
3511     packet_list_->setVerticalAutoScroll(checked);
3512 }
3513
3514 void MainWindow::resetPreviousFocus() {
3515     previous_focus_ = NULL;
3516 }
3517
3518 void MainWindow::on_goToCancel_clicked()
3519 {
3520     main_ui_->goToFrame->animatedHide();
3521     if (previous_focus_) {
3522         disconnect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
3523         previous_focus_->setFocus();
3524         resetPreviousFocus();
3525     }
3526 }
3527
3528 void MainWindow::on_goToGo_clicked()
3529 {
3530     gotoFrame(main_ui_->goToLineEdit->text().toInt());
3531
3532     on_goToCancel_clicked();
3533 }
3534
3535 void MainWindow::on_goToLineEdit_returnPressed()
3536 {
3537     on_goToGo_clicked();
3538 }
3539
3540 void MainWindow::on_actionCaptureStart_triggered()
3541 {
3542 //#ifdef HAVE_AIRPCAP
3543 //  airpcap_if_active = airpcap_if_selected;
3544 //  if (airpcap_if_active)
3545 //    airpcap_set_toolbar_start_capture(airpcap_if_active);
3546 //#endif
3547
3548 //  if (cap_open_w) {
3549 //    /*
3550 //     * There's an options dialog; get the values from it and close it.
3551 //     */
3552 //    gboolean success;
3553
3554 //    /* Determine if "capture start" while building of the "capture options" window */
3555 //    /*  is in progress. If so, ignore the "capture start.                          */
3556 //    /* XXX: Would it be better/cleaner for the "capture options" window code to    */
3557 //    /*      disable the capture start button temporarily ?                         */
3558 //    if (cap_open_complete == FALSE) {
3559 //      return;  /* Building options window: ignore "capture start" */
3560 //    }
3561 //    success = capture_dlg_prep(cap_open_w);
3562 //    window_destroy(GTK_WIDGET(cap_open_w));
3563 //    if (!success)
3564 //      return;   /* error in options dialog */
3565 //  }
3566
3567 #ifdef HAVE_LIBPCAP
3568     if (global_capture_opts.num_selected == 0) {
3569         QString err_msg = tr("No Interface Selected");
3570         main_ui_->statusBar->pushTemporaryStatus(err_msg);
3571         main_ui_->actionCaptureStart->setChecked(false);
3572         return;
3573     }
3574
3575     /* XXX - will closing this remove a temporary file? */
3576     QString before_what(tr(" before starting a new capture"));
3577     if (testCaptureFileClose(before_what)) {
3578         startCapture();
3579     } else {
3580         // simply clicking the button sets it to 'checked' even though we've
3581         // decided to do nothing, so undo that
3582         main_ui_->actionCaptureStart->setChecked(false);
3583     }
3584 #endif // HAVE_LIBPCAP
3585 }
3586
3587 void MainWindow::on_actionCaptureStop_triggered()
3588 {
3589     stopCapture();
3590 }
3591
3592 void MainWindow::on_actionCaptureRestart_triggered()
3593 {
3594     QString before_what(tr(" before restarting the capture"));
3595     if (!testCaptureFileClose(before_what, Restart))
3596         return;
3597
3598 /* TODO: GTK use only this: capture_restart(&cap_session_); */
3599     startCapture();
3600 }
3601
3602 static FilterDialog *capture_filter_dlg_ = NULL;
3603 void MainWindow::on_actionCaptureCaptureFilters_triggered()
3604 {
3605     if (!capture_filter_dlg_) {
3606         capture_filter_dlg_ = new FilterDialog(this, FilterDialog::CaptureFilter);
3607     }
3608     capture_filter_dlg_->show();
3609     capture_filter_dlg_->raise();
3610     capture_filter_dlg_->activateWindow();
3611 }
3612
3613 void MainWindow::on_actionStatisticsCaptureFileProperties_triggered()
3614 {
3615     CaptureFilePropertiesDialog *capture_file_properties_dialog = new CaptureFilePropertiesDialog(*this, capture_file_);
3616     connect(capture_file_properties_dialog, SIGNAL(captureCommentChanged()),
3617             this, SLOT(updateForUnsavedChanges()));
3618     capture_file_properties_dialog->show();
3619 }
3620
3621 void MainWindow::on_actionStatisticsResolvedAddresses_triggered()
3622 {
3623     ResolvedAddressesDialog *resolved_addresses_dialog = new ResolvedAddressesDialog(this, &capture_file_);
3624     resolved_addresses_dialog->show();
3625 }
3626
3627 void MainWindow::on_actionStatisticsProtocolHierarchy_triggered()
3628 {
3629     ProtocolHierarchyDialog *phd = new ProtocolHierarchyDialog(*this, capture_file_);
3630     connect(phd, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
3631             this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)));
3632     phd->show();
3633 }
3634
3635 #ifdef HAVE_LIBPCAP
3636 void MainWindow::on_actionCaptureOptions_triggered()
3637 {
3638     if (!capture_interfaces_dialog_) {
3639         capture_interfaces_dialog_ = new CaptureInterfacesDialog(this);
3640
3641         connect(capture_interfaces_dialog_, SIGNAL(startCapture()), this, SLOT(startCapture()));
3642         connect(capture_interfaces_dialog_, SIGNAL(stopCapture()), this, SLOT(stopCapture()));
3643
3644         connect(capture_interfaces_dialog_, SIGNAL(getPoints(int,PointList*)),
3645                 this->main_welcome_->getInterfaceFrame(), SLOT(getPoints(int,PointList*)));
3646         connect(capture_interfaces_dialog_, SIGNAL(interfacesChanged()),
3647                 this->main_welcome_, SLOT(interfaceSelected()));
3648         connect(capture_interfaces_dialog_, SIGNAL(interfacesChanged()),
3649                 this->main_welcome_->getInterfaceFrame(), SLOT(updateSelectedInterfaces()));
3650         connect(capture_interfaces_dialog_, SIGNAL(interfaceListChanged()),
3651                 this->main_welcome_->getInterfaceFrame(), SLOT(interfaceListChanged()));
3652         connect(capture_interfaces_dialog_, SIGNAL(captureFilterTextEdited(QString)),
3653                 this->main_welcome_, SLOT(setCaptureFilterText(QString)));
3654
3655         connect(capture_interfaces_dialog_, SIGNAL(setFilterValid(bool, const QString)),
3656                 this, SLOT(startInterfaceCapture(bool, const QString)));
3657     }
3658     capture_interfaces_dialog_->setTab(0);
3659     capture_interfaces_dialog_->updateInterfaces();
3660
3661     if (capture_interfaces_dialog_->isMinimized()) {
3662         capture_interfaces_dialog_->showNormal();
3663     } else {
3664         capture_interfaces_dialog_->show();
3665     }
3666
3667     capture_interfaces_dialog_->raise();
3668     capture_interfaces_dialog_->activateWindow();
3669 }
3670
3671 void MainWindow::on_actionCaptureRefreshInterfaces_triggered()
3672 {
3673     main_ui_->actionCaptureRefreshInterfaces->setEnabled(false);
3674     wsApp->refreshLocalInterfaces();
3675     main_ui_->actionCaptureRefreshInterfaces->setEnabled(true);
3676 }
3677 #endif
3678
3679 void MainWindow::externalMenuItem_triggered()
3680 {
3681     QAction * triggerAction = NULL;
3682     QVariant v;
3683     ext_menubar_t * entry = NULL;
3684
3685     if (QObject::sender()) {
3686         triggerAction = (QAction *)QObject::sender();
3687         v = triggerAction->data();
3688
3689         if (v.canConvert<void *>()) {
3690             entry = (ext_menubar_t *)v.value<void *>();
3691
3692             if (entry->type == EXT_MENUBAR_ITEM) {
3693                 entry->callback(EXT_MENUBAR_QT_GUI, (gpointer) ((void *)main_ui_), entry->user_data);
3694             } else {
3695                 QDesktopServices::openUrl(QUrl(QString((gchar *)entry->user_data)));
3696             }
3697         }
3698     }
3699 }
3700
3701 void MainWindow::gotoFrame(int packet_num)
3702 {
3703     if (packet_num > 0) {
3704         packet_list_->goToPacket(packet_num);
3705     }
3706 }
3707
3708 #ifdef HAVE_EXTCAP
3709 void MainWindow::extcap_options_finished(int result)
3710 {
3711     if (result == QDialog::Accepted) {
3712         startCapture();
3713     }
3714     this->main_welcome_->getInterfaceFrame()->interfaceListChanged();
3715 }
3716
3717 void MainWindow::showExtcapOptionsDialog(QString &device_name)
3718 {
3719     ExtcapOptionsDialog * extcap_options_dialog = ExtcapOptionsDialog::createForDevice(device_name, this);
3720     /* The dialog returns null, if the given device name is not a valid extcap device */
3721     if (extcap_options_dialog) {
3722         connect(extcap_options_dialog, SIGNAL(finished(int)),
3723                 this, SLOT(extcap_options_finished(int)));
3724         extcap_options_dialog->show();
3725     }
3726 }
3727 #endif
3728
3729 // Q_DECLARE_METATYPE(field_info *) called in proto_tree.h
3730
3731 void MainWindow::on_actionContextCopyBytesHexTextDump_triggered()
3732 {
3733     QAction *ca = qobject_cast<QAction*>(sender());
3734     if (!ca) return;
3735
3736     field_info *fi = ca->data().value<field_info *>();
3737
3738     byte_view_tab_->copyData(ByteViewTab::copyDataHexTextDump, fi);
3739 }
3740
3741 void MainWindow::on_actionContextCopyBytesHexDump_triggered()
3742 {
3743     QAction *ca = qobject_cast<QAction*>(sender());
3744     if (!ca) return;
3745
3746     field_info *fi = ca->data().value<field_info *>();
3747
3748     byte_view_tab_->copyData(ByteViewTab::copyDataHexDump, fi);
3749 }
3750
3751 void MainWindow::on_actionContextCopyBytesPrintableText_triggered()
3752 {
3753     QAction *ca = qobject_cast<QAction*>(sender());
3754     if (!ca) return;
3755
3756     field_info *fi = ca->data().value<field_info *>();
3757
3758     byte_view_tab_->copyData(ByteViewTab::copyDataPrintableText, fi);
3759 }
3760
3761 void MainWindow::on_actionContextCopyBytesHexStream_triggered()
3762 {
3763     QAction *ca = qobject_cast<QAction*>(sender());
3764     if (!ca) return;
3765
3766     field_info *fi = ca->data().value<field_info *>();
3767
3768     byte_view_tab_->copyData(ByteViewTab::copyDataHexStream, fi);
3769 }
3770
3771 void MainWindow::on_actionContextCopyBytesBinary_triggered()
3772 {
3773     QAction *ca = qobject_cast<QAction*>(sender());
3774     if (!ca) return;
3775
3776     field_info *fi = ca->data().value<field_info *>();
3777
3778     byte_view_tab_->copyData(ByteViewTab::copyDataBinary, fi);
3779 }
3780
3781 void MainWindow::on_actionContextCopyBytesEscapedString_triggered()
3782 {
3783     QAction *ca = qobject_cast<QAction*>(sender());
3784     if (!ca) return;
3785
3786     field_info *fi = ca->data().value<field_info *>();
3787
3788     byte_view_tab_->copyData(ByteViewTab::copyDataEscapedString, fi);
3789 }
3790
3791 void MainWindow::on_actionContextWikiProtocolPage_triggered()
3792 {
3793     QAction *wa = qobject_cast<QAction*>(sender());
3794     if (!wa) return;
3795
3796     bool ok = false;
3797     int field_id = wa->data().toInt(&ok);
3798     if (!ok) return;
3799
3800     const QString proto_abbrev = proto_registrar_get_abbrev(field_id);
3801
3802     int ret = QMessageBox::question(this, wsApp->windowTitleString(tr("Wiki Page for %1").arg(proto_abbrev)),
3803                                    tr("<p>The Wireshark Wiki is maintained by the community.</p>"
3804                                       "<p>The page you are about to load might be wonderful, "
3805                                       "incomplete, wrong, or nonexistent.</p>"
3806                                       "<p>Proceed to the wiki?</p>"),
3807                                    QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
3808
3809     if (ret != QMessageBox::Yes) return;
3810
3811     QUrl wiki_url = QString("https://wiki.wireshark.org/Protocols/%1").arg(proto_abbrev);
3812     QDesktopServices::openUrl(wiki_url);
3813 }
3814
3815 void MainWindow::on_actionContextFilterFieldReference_triggered()
3816 {
3817     QAction *wa = qobject_cast<QAction*>(sender());
3818     if (!wa) return;
3819
3820     bool ok = false;
3821     int field_id = wa->data().toInt(&ok);
3822     if (!ok) return;
3823
3824     const QString proto_abbrev = proto_registrar_get_abbrev(field_id);
3825
3826     QUrl dfref_url = QString("https://www.wireshark.org/docs/dfref/%1/%2")
3827             .arg(proto_abbrev[0])
3828             .arg(proto_abbrev);
3829     QDesktopServices::openUrl(dfref_url);
3830 }
3831
3832 #ifdef _MSC_VER
3833 #pragma warning(pop)
3834 #endif
3835
3836 /*
3837  * Editor modelines
3838  *
3839  * Local Variables:
3840  * c-basic-offset: 4
3841  * tab-width: 8
3842  * indent-tabs-mode: nil
3843  * End:
3844  *
3845  * ex: set shiftwidth=4 tabstop=8 expandtab:
3846  * :indentSize=4:tabSize=8:noTabs=true:
3847  */