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