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