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