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