Try to fix a Qt 5.5.0 + Visual Studio 2013 warning.
[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/color_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;
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, &is_ip, &is_tcp, &is_udp, &is_sctp, &is_ssl, &is_rtp);
1079         }
1080     }
1081
1082     have_filter_expr = !packet_list_->getFilterFromRowAndColumn().isEmpty();
1083
1084     main_ui_->actionEditMarkPacket->setEnabled(frame_selected);
1085     main_ui_->actionEditMarkAllDisplayed->setEnabled(have_frames);
1086     /* Unlike un-ignore, do not allow unmark of all frames when no frames are displayed  */
1087     main_ui_->actionEditUnmarkAllDisplayed->setEnabled(have_marked);
1088     main_ui_->actionEditNextMark->setEnabled(another_is_marked);
1089     main_ui_->actionEditPreviousMark->setEnabled(another_is_marked);
1090
1091 #ifdef WANT_PACKET_EDITOR
1092 //    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/EditPacket",
1093 //                         frame_selected);
1094 #endif // WANT_PACKET_EDITOR
1095     main_ui_->actionEditPacketComment->setEnabled(frame_selected && wtap_dump_can_write(capture_file_.capFile()->linktypes, WTAP_COMMENT_PER_PACKET));
1096
1097     main_ui_->actionEditIgnorePacket->setEnabled(frame_selected);
1098     main_ui_->actionEditIgnoreAllDisplayed->setEnabled(have_filtered);
1099     /* Allow un-ignore of all frames even with no frames currently displayed */
1100     main_ui_->actionEditUnignoreAllDisplayed->setEnabled(have_ignored);
1101
1102     main_ui_->actionEditSetTimeReference->setEnabled(frame_selected);
1103     main_ui_->actionEditUnsetAllTimeReferences->setEnabled(have_time_ref);
1104     main_ui_->actionEditNextTimeReference->setEnabled(another_is_time_ref);
1105     main_ui_->actionEditPreviousTimeReference->setEnabled(another_is_time_ref);
1106     main_ui_->actionEditTimeShift->setEnabled(have_frames);
1107
1108     main_ui_->actionGoGoToLinkedPacket->setEnabled(false);
1109
1110     main_ui_->actionAnalyzeAAFSelected->setEnabled(have_filter_expr);
1111     main_ui_->actionAnalyzeAAFNotSelected->setEnabled(have_filter_expr);
1112     main_ui_->actionAnalyzeAAFAndSelected->setEnabled(have_filter_expr);
1113     main_ui_->actionAnalyzeAAFOrSelected->setEnabled(have_filter_expr);
1114     main_ui_->actionAnalyzeAAFAndNotSelected->setEnabled(have_filter_expr);
1115     main_ui_->actionAnalyzeAAFOrNotSelected->setEnabled(have_filter_expr);
1116
1117     main_ui_->actionAnalyzePAFSelected->setEnabled(have_filter_expr);
1118     main_ui_->actionAnalyzePAFNotSelected->setEnabled(have_filter_expr);
1119     main_ui_->actionAnalyzePAFAndSelected->setEnabled(have_filter_expr);
1120     main_ui_->actionAnalyzePAFOrSelected->setEnabled(have_filter_expr);
1121     main_ui_->actionAnalyzePAFAndNotSelected->setEnabled(have_filter_expr);
1122     main_ui_->actionAnalyzePAFOrNotSelected->setEnabled(have_filter_expr);
1123
1124     main_ui_->actionAnalyzeFollowTCPStream->setEnabled(is_tcp);
1125     main_ui_->actionAnalyzeFollowUDPStream->setEnabled(is_udp);
1126     main_ui_->actionAnalyzeFollowSSLStream->setEnabled(is_ssl);
1127
1128     foreach (QAction *cc_action, cc_actions) {
1129         cc_action->setEnabled(frame_selected);
1130     }
1131     main_ui_->actionViewColorizeNewConversationRule->setEnabled(frame_selected);
1132
1133     main_ui_->actionViewColorizeResetColorization->setEnabled(tmp_color_filters_used());
1134
1135     main_ui_->actionViewColorizeNewConversationRule->setEnabled(frame_selected);
1136
1137     main_ui_->actionViewShowPacketInNewWindow->setEnabled(frame_selected);
1138     main_ui_->actionViewEditResolvedName->setEnabled(frame_selected && is_ip);
1139
1140     main_ui_->menuConversationFilter->clear();
1141
1142     packet_list_->conversationMenu()->clear();
1143     packet_list_->colorizeMenu()->clear();
1144
1145     for (GList *color_list_entry = color_conv_filter_list; color_list_entry; color_list_entry = g_list_next(color_list_entry)) {
1146         // Main menu items
1147         color_conversation_filter_t* color_filter = (color_conversation_filter_t *)color_list_entry->data;
1148         QAction *conv_action = main_ui_->menuConversationFilter->addAction(color_filter->display_name);
1149
1150         bool enable = false;
1151         QString filter;
1152         if (capture_file_.capFile()->edt) {
1153             enable = color_filter->is_filter_valid(&capture_file_.capFile()->edt->pi);
1154             filter = gchar_free_to_qstring(color_filter->build_filter_string(&capture_file_.capFile()->edt->pi));
1155         }
1156         conv_action->setEnabled(enable);
1157         conv_action->setData(filter);
1158         connect(conv_action, SIGNAL(triggered()), this, SLOT(applyConversationFilter()));
1159
1160         // Packet list context menu items
1161         packet_list_->conversationMenu()->addAction(conv_action);
1162
1163         QMenu *submenu = packet_list_->colorizeMenu()->addMenu(conv_action->text());
1164         int i = 1;
1165         foreach (QAction *cc_action, cc_actions) {
1166             QAction *colorize_action = submenu->addAction(cc_action->icon(), cc_action->text());
1167             colorize_action->setProperty(color_number_property_, i++);
1168             colorize_action->setData(filter);
1169             colorize_action->setEnabled(enable);
1170             connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1171         }
1172
1173         QAction *conv_rule_action = submenu->addAction(main_ui_->actionViewColorizeNewConversationRule->text());
1174         conv_rule_action->setData(conv_action->data());
1175         conv_rule_action->setEnabled(enable);
1176         connect(conv_rule_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1177     }
1178
1179 //    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/NameResolution/ResolveName",
1180 //                         frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
1181 //                                            gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns));
1182 //    set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ToolsMenu/FirewallACLRules",
1183 //                         frame_selected);
1184     main_ui_->menuTcpStreamGraphs->setEnabled(is_tcp);
1185     main_ui_->actionSCTPAnalyseThisAssociation->setEnabled(is_sctp);
1186     main_ui_->actionSCTPShowAllAssociations->setEnabled(is_sctp);
1187     main_ui_->actionSCTPFilterThisAssociation->setEnabled(is_sctp);
1188     main_ui_->actionTelephonyRTPStreamAnalysis->setEnabled(is_rtp);
1189 }
1190
1191 void MainWindow::setMenusForSelectedTreeRow(field_info *fi) {
1192
1193     bool can_match_selected = false;
1194     bool is_framenum = false;
1195     bool have_field_info = false;
1196     bool have_subtree = false;
1197     bool can_open_url = false;
1198     QString field_filter;
1199     int field_id = -1;
1200
1201     QList<QAction *> cc_actions = QList<QAction *>()
1202             << main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
1203             << main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
1204             << main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
1205             << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
1206             << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
1207
1208     if (capture_file_.capFile()) {
1209         capture_file_.capFile()->finfo_selected = fi;
1210
1211         if (fi && fi->tree_type != -1) {
1212             have_subtree = true;
1213         }
1214     }
1215
1216     if (capture_file_.capFile() != NULL && fi != NULL) {
1217         header_field_info *hfinfo = fi->hfinfo;
1218         int linked_frame = -1;
1219
1220         have_field_info = true;
1221         can_match_selected = proto_can_match_selected(capture_file_.capFile()->finfo_selected, capture_file_.capFile()->edt);
1222         if (hfinfo && hfinfo->type == FT_FRAMENUM) {
1223             is_framenum = true;
1224             linked_frame = fvalue_get_uinteger(&fi->value);
1225         }
1226
1227         char *tmp_field = proto_construct_match_selected_string(fi, capture_file_.capFile()->edt);
1228         field_filter = QString(tmp_field);
1229         wmem_free(NULL, tmp_field);
1230
1231         field_id = fi->hfinfo->id;
1232         /* if the selected field isn't a protocol, get its parent */
1233         if (!proto_registrar_is_protocol(field_id)) {
1234             field_id = proto_registrar_get_parent(fi->hfinfo->id);
1235         }
1236
1237         if (field_id >= 0 && !proto_is_private(field_id)) {
1238             can_open_url = true;
1239             main_ui_->actionContextWikiProtocolPage->setData(field_id);
1240             main_ui_->actionContextFilterFieldReference->setData(field_id);
1241         } else {
1242             main_ui_->actionContextWikiProtocolPage->setData(QVariant());
1243             main_ui_->actionContextFilterFieldReference->setData(QVariant());
1244         }
1245
1246         if (linked_frame > 0) {
1247             main_ui_->actionGoGoToLinkedPacket->setData(linked_frame);
1248         } else {
1249             main_ui_->actionGoGoToLinkedPacket->setData(QVariant());
1250         }
1251     }
1252
1253     // Always enable / disable the following items.
1254     main_ui_->actionFileExportPacketBytes->setEnabled(have_field_info);
1255
1256     main_ui_->actionCopyAllVisibleItems->setEnabled(capture_file_.capFile() != NULL);
1257     main_ui_->actionCopyAllVisibleSelectedTreeItems->setEnabled(can_match_selected);
1258     main_ui_->actionEditCopyDescription->setEnabled(can_match_selected);
1259     main_ui_->actionEditCopyFieldName->setEnabled(can_match_selected);
1260     main_ui_->actionEditCopyValue->setEnabled(can_match_selected);
1261     main_ui_->actionEditCopyAsFilter->setEnabled(can_match_selected);
1262
1263     main_ui_->actionViewExpandSubtrees->setEnabled(have_subtree);
1264
1265     main_ui_->actionGoGoToLinkedPacket->setEnabled(is_framenum);
1266
1267     main_ui_->actionAnalyzeCreateAColumn->setEnabled(can_match_selected);
1268
1269     main_ui_->actionContextShowLinkedPacketInNewWindow->setEnabled(is_framenum);
1270
1271     main_ui_->actionContextWikiProtocolPage->setEnabled(can_open_url);
1272     main_ui_->actionContextFilterFieldReference->setEnabled(can_open_url);
1273
1274
1275     // Only enable / disable the following items if we have focus so that we
1276     // don't clobber anything we may have set in setMenusForSelectedPacket.
1277     if (!proto_tree_ || !proto_tree_->hasFocus()) return;
1278
1279     main_ui_->menuConversationFilter->clear();
1280     for (GList *color_list_entry = color_conv_filter_list; color_list_entry; color_list_entry = g_list_next(color_list_entry)) {
1281         color_conversation_filter_t* color_filter = (color_conversation_filter_t *)color_list_entry->data;
1282         QAction *conv_action = main_ui_->menuConversationFilter->addAction(color_filter->display_name);
1283
1284         bool conv_enable = false;
1285         QString conv_filter;
1286         if (capture_file_.capFile() && capture_file_.capFile()->edt) {
1287             conv_enable = color_filter->is_filter_valid(&capture_file_.capFile()->edt->pi);
1288             conv_filter = color_filter->build_filter_string(&capture_file_.capFile()->edt->pi);
1289         }
1290         conv_action->setEnabled(conv_enable);
1291         conv_action->setData(conv_filter);
1292         connect(conv_action, SIGNAL(triggered()), this, SLOT(applyConversationFilter()));
1293     }
1294
1295     proto_tree_->colorizeMenu()->clear();
1296     int i = 1;
1297     foreach (QAction *cc_action, cc_actions) {
1298         QAction *colorize_action = proto_tree_->colorizeMenu()->addAction(cc_action->icon(), cc_action->text());
1299         colorize_action->setProperty(color_number_property_, i++);
1300         colorize_action->setData(field_filter);
1301         colorize_action->setEnabled(!field_filter.isEmpty());
1302         connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1303     }
1304
1305     QAction *conv_rule_action = proto_tree_->colorizeMenu()->addAction(main_ui_->actionViewColorizeNewConversationRule->text());
1306     conv_rule_action->setData(field_filter);
1307     conv_rule_action->setEnabled(!field_filter.isEmpty());
1308     connect(conv_rule_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1309
1310 //    set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ResolveName",
1311 //                         frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
1312 //                                            gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns));
1313
1314
1315     main_ui_->actionAnalyzeAAFSelected->setEnabled(can_match_selected);
1316     main_ui_->actionAnalyzeAAFNotSelected->setEnabled(can_match_selected);
1317     main_ui_->actionAnalyzeAAFAndSelected->setEnabled(can_match_selected);
1318     main_ui_->actionAnalyzeAAFOrSelected->setEnabled(can_match_selected);
1319     main_ui_->actionAnalyzeAAFAndNotSelected->setEnabled(can_match_selected);
1320     main_ui_->actionAnalyzeAAFOrNotSelected->setEnabled(can_match_selected);
1321
1322     main_ui_->actionAnalyzePAFSelected->setEnabled(can_match_selected);
1323     main_ui_->actionAnalyzePAFNotSelected->setEnabled(can_match_selected);
1324     main_ui_->actionAnalyzePAFAndSelected->setEnabled(can_match_selected);
1325     main_ui_->actionAnalyzePAFOrSelected->setEnabled(can_match_selected);
1326     main_ui_->actionAnalyzePAFAndNotSelected->setEnabled(can_match_selected);
1327     main_ui_->actionAnalyzePAFOrNotSelected->setEnabled(can_match_selected);
1328 }
1329
1330 void MainWindow::interfaceSelectionChanged()
1331 {
1332 #ifdef HAVE_LIBPCAP
1333     // XXX This doesn't disable the toolbar button when using
1334     // QtMacExtras.
1335     if (global_capture_opts.num_selected > 0 && capture_filter_valid_) {
1336         main_ui_->actionCaptureStart->setEnabled(true);
1337     } else {
1338         main_ui_->actionCaptureStart->setEnabled(false);
1339     }
1340 #endif // HAVE_LIBPCAP
1341 }
1342
1343 void MainWindow::captureFilterSyntaxChanged(bool valid)
1344 {
1345     capture_filter_valid_ = valid;
1346     interfaceSelectionChanged();
1347 }
1348
1349 void MainWindow::startInterfaceCapture(bool valid)
1350 {
1351     capture_filter_valid_ = valid;
1352     startCapture();
1353 }
1354
1355 void MainWindow::redissectPackets()
1356 {
1357     if (capture_file_.capFile())
1358         cf_redissect_packets(capture_file_.capFile());
1359     main_ui_->statusBar->expertUpdate();
1360
1361     proto_free_deregistered_fields();
1362 }
1363
1364 void MainWindow::fieldsChanged()
1365 {
1366     color_filters_reload();
1367     tap_listeners_dfilter_recompile();
1368
1369     if (!df_combo_box_->checkDisplayFilter()) {
1370         g_free(CaptureFile::globalCapFile()->dfilter);
1371         CaptureFile::globalCapFile()->dfilter = NULL;
1372     }
1373
1374     if (have_custom_cols(&CaptureFile::globalCapFile()->cinfo)) {
1375         // Recreate packet list columns according to new/changed/deleted fields
1376         packet_list_->fieldsChanged(CaptureFile::globalCapFile());
1377     }
1378
1379     emit reloadFields();
1380 }
1381
1382 void MainWindow::showAccordionFrame(AccordionFrame *show_frame, bool toggle)
1383 {
1384     QList<AccordionFrame *>frame_list = QList<AccordionFrame *>()
1385             << main_ui_->goToFrame << main_ui_->searchFrame
1386             << main_ui_->addressEditorFrame << main_ui_->columnEditorFrame
1387             << main_ui_->preferenceEditorFrame;
1388
1389     frame_list.removeAll(show_frame);
1390     foreach (AccordionFrame *af, frame_list) af->animatedHide();
1391
1392     if (toggle) {
1393         if (show_frame->isVisible()) {
1394             show_frame->animatedHide();
1395             return;
1396         }
1397     }
1398     show_frame->animatedShow();
1399 }
1400
1401 void MainWindow::showColumnEditor(int column)
1402 {
1403     previous_focus_ = wsApp->focusWidget();
1404     connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
1405     showAccordionFrame(main_ui_->columnEditorFrame);
1406     main_ui_->columnEditorFrame->editColumn(column);
1407 }
1408
1409 void MainWindow::showPreferenceEditor()
1410 {
1411     showAccordionFrame(main_ui_->preferenceEditorFrame);
1412 }
1413
1414 void MainWindow::initViewColorizeMenu()
1415 {
1416     QList<QAction *> cc_actions = QList<QAction *>()
1417             << main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
1418             << main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
1419             << main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
1420             << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
1421             << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
1422
1423     guint8 color_num = 1;
1424
1425     foreach (QAction *cc_action, cc_actions) {
1426         cc_action->setData(color_num);
1427         connect(cc_action, SIGNAL(triggered()), this, SLOT(colorizeConversation()));
1428
1429         const color_filter_t *colorf = color_filters_tmp_color(color_num);
1430         if (colorf) {
1431             QColor bg = ColorUtils::fromColorT(colorf->bg_color);
1432             QColor fg = ColorUtils::fromColorT(colorf->fg_color);
1433             cc_action->setIcon(StockIcon::colorIcon(bg.rgb(), fg.rgb(), QString::number(color_num)));
1434         }
1435         color_num++;
1436     }
1437
1438 #ifdef Q_OS_MAC
1439     // Spotlight uses Cmd+Space
1440     main_ui_->actionViewColorizeResetColorization->setShortcut(QKeySequence("Meta+Space"));
1441 #endif
1442 }
1443
1444 void MainWindow::addStatsPluginsToMenu() {
1445     GList          *cfg_list = stats_tree_get_cfg_list();
1446     GList          *iter = g_list_first(cfg_list);
1447     QAction        *stats_tree_action;
1448     QMenu          *parent_menu;
1449     bool            first_item = true;
1450
1451     while (iter) {
1452         stats_tree_cfg *cfg = (stats_tree_cfg*)iter->data;
1453         if (cfg->plugin) {
1454             if (first_item) {
1455                 main_ui_->menuStatistics->addSeparator();
1456                 first_item = false;
1457             }
1458
1459             parent_menu = main_ui_->menuStatistics;
1460             // gtk/main_menubar.c compresses double slashes, hence SkipEmptyParts
1461             QStringList cfg_name_parts = QString(cfg->name).split("/", QString::SkipEmptyParts);
1462             if (cfg_name_parts.isEmpty()) continue;
1463
1464             QString stat_name = cfg_name_parts.takeLast();
1465             if (!cfg_name_parts.isEmpty()) {
1466                 QString menu_name = cfg_name_parts.join("/");
1467                 parent_menu = findOrAddMenu(parent_menu, menu_name);
1468             }
1469
1470             stats_tree_action = new QAction(stat_name, this);
1471             stats_tree_action->setData(cfg->abbr);
1472             parent_menu->addAction(stats_tree_action);
1473             connect(stats_tree_action, SIGNAL(triggered()), this, SLOT(actionStatisticsPlugin_triggered()));
1474         }
1475         iter = g_list_next(iter);
1476     }
1477     g_list_free(cfg_list);
1478 }
1479
1480 void MainWindow::setFeaturesEnabled(bool enabled)
1481 {
1482     main_ui_->menuBar->setEnabled(enabled);
1483     main_ui_->mainToolBar->setEnabled(enabled);
1484     main_ui_->displayFilterToolBar->setEnabled(enabled);
1485     if(enabled)
1486     {
1487         main_ui_->statusBar->clearMessage();
1488     }
1489     else
1490     {
1491         main_ui_->statusBar->showMessage(tr("Please wait while Wireshark is initializing" UTF8_HORIZONTAL_ELLIPSIS));
1492     }
1493 }
1494
1495 // Display Filter Toolbar
1496
1497 void MainWindow::on_actionDisplayFilterExpression_triggered()
1498 {
1499     DisplayFilterExpressionDialog *dfe_dialog = new DisplayFilterExpressionDialog(this);
1500
1501     connect(dfe_dialog, SIGNAL(insertDisplayFilter(QString)),
1502             df_combo_box_->lineEdit(), SLOT(insertFilter(const QString &)));
1503
1504     dfe_dialog->show();
1505 }
1506
1507 // On Qt4 + OS X with unifiedTitleAndToolBarOnMac set it's possible to make
1508 // the main window obnoxiously wide.
1509
1510 void MainWindow::displayFilterButtonClicked()
1511 {
1512     QAction *dfb_action = qobject_cast<QAction*>(sender());
1513
1514     if (dfb_action) {
1515         df_combo_box_->lineEdit()->setText(dfb_action->data().toString());
1516         df_combo_box_->applyDisplayFilter();
1517         df_combo_box_->lineEdit()->setFocus();
1518     }
1519 }
1520
1521 void MainWindow::openStatCommandDialog(const QString &menu_path, const char *arg, void *userdata)
1522 {
1523     QString slot = QString("statCommand%1").arg(menu_path);
1524     QMetaObject::invokeMethod(this, slot.toLatin1().constData(), Q_ARG(const char *, arg), Q_ARG(void *, userdata));
1525 }
1526
1527 void MainWindow::openTapParameterDialog(const QString cfg_str, const QString arg, void *userdata)
1528 {
1529     TapParameterDialog *tp_dialog = TapParameterDialog::showTapParameterStatistics(*this, capture_file_, cfg_str, arg, userdata);
1530     if (!tp_dialog) return;
1531
1532     connect(tp_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
1533             this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
1534     connect(tp_dialog, SIGNAL(updateFilter(QString)),
1535             df_combo_box_->lineEdit(), SLOT(setText(QString)));
1536     tp_dialog->show();
1537 }
1538
1539 void MainWindow::openTapParameterDialog()
1540 {
1541     QAction *tpa = qobject_cast<QAction *>(QObject::sender());
1542     if (!tpa) return;
1543
1544     const QString cfg_str = tpa->data().toString();
1545     openTapParameterDialog(cfg_str, NULL, NULL);
1546 }
1547
1548 // File Menu
1549
1550 void MainWindow::on_actionFileOpen_triggered()
1551 {
1552     openCaptureFile();
1553 }
1554
1555 void MainWindow::on_actionFileMerge_triggered()
1556 {
1557     mergeCaptureFile();
1558 }
1559
1560 void MainWindow::on_actionFileImportFromHexDump_triggered()
1561 {
1562     importCaptureFile();
1563 }
1564
1565 void MainWindow::on_actionFileClose_triggered() {
1566     if (testCaptureFileClose())
1567         main_ui_->mainStack->setCurrentWidget(main_welcome_);
1568 }
1569
1570 void MainWindow::on_actionFileSave_triggered()
1571 {
1572     saveCaptureFile(capture_file_.capFile(), FALSE);
1573 }
1574
1575 void MainWindow::on_actionFileSaveAs_triggered()
1576 {
1577     saveAsCaptureFile(capture_file_.capFile());
1578 }
1579
1580 void MainWindow::on_actionFileSetListFiles_triggered()
1581 {
1582     file_set_dialog_.exec();
1583 }
1584
1585 void MainWindow::on_actionFileSetNextFile_triggered()
1586 {
1587     fileset_entry *entry = fileset_get_next();
1588
1589     if (entry) {
1590         QString new_cf_path = entry->fullname;
1591         openCaptureFile(new_cf_path);
1592     }
1593 }
1594
1595 void MainWindow::on_actionFileSetPreviousFile_triggered()
1596 {
1597     fileset_entry *entry = fileset_get_previous();
1598
1599     if (entry) {
1600         QString new_cf_path = entry->fullname;
1601         openCaptureFile(new_cf_path);
1602     }
1603 }
1604
1605 void MainWindow::on_actionFileExportPackets_triggered()
1606 {
1607     exportSelectedPackets();
1608 }
1609
1610 void MainWindow::on_actionFileExportAsPlainText_triggered()
1611 {
1612     exportDissections(export_type_text);
1613 }
1614
1615 void MainWindow::on_actionFileExportAsCSV_triggered()
1616 {
1617     exportDissections(export_type_csv);
1618 }
1619
1620 void MainWindow::on_actionFileExportAsCArrays_triggered()
1621 {
1622     exportDissections(export_type_carrays);
1623 }
1624
1625 void MainWindow::on_actionFileExportAsPSML_triggered()
1626 {
1627     exportDissections(export_type_psml);
1628 }
1629
1630 void MainWindow::on_actionFileExportAsPDML_triggered()
1631 {
1632     exportDissections(export_type_pdml);
1633 }
1634
1635 void MainWindow::on_actionFileExportPacketBytes_triggered()
1636 {
1637     QString file_name;
1638
1639     if (!capture_file_.capFile() || !capture_file_.capFile()->finfo_selected) return;
1640
1641     file_name = QFileDialog::getSaveFileName(this,
1642                                              wsApp->windowTitleString(tr("Export Selected Packet Bytes")),
1643                                              wsApp->lastOpenDir().canonicalPath(),
1644                                              tr("Raw data (*.bin *.dat *.raw);;Any File (*.*)")
1645                                              );
1646
1647     if (file_name.length() > 0) {
1648         const guint8 *data_p;
1649         int fd;
1650
1651         data_p = tvb_get_ptr(capture_file_.capFile()->finfo_selected->ds_tvb, 0, -1) +
1652                 capture_file_.capFile()->finfo_selected->start;
1653         fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
1654         if (fd == -1) {
1655             open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
1656             return;
1657         }
1658         if (write(fd, data_p, capture_file_.capFile()->finfo_selected->length) < 0) {
1659             write_failure_alert_box(file_name.toUtf8().constData(), errno);
1660             ::close(fd);
1661             return;
1662         }
1663         if (::close(fd) < 0) {
1664             write_failure_alert_box(file_name.toUtf8().constData(), errno);
1665             return;
1666         }
1667
1668         /* Save the directory name for future file dialogs. */
1669         wsApp->setLastOpenDir(&file_name);
1670     }
1671 }
1672 void MainWindow::on_actionFileExportPDU_triggered()
1673 {
1674     ExportPDUDialog *exportpdu_dialog = new ExportPDUDialog(this);
1675
1676     if (exportpdu_dialog->isMinimized() == true)
1677     {
1678         exportpdu_dialog->showNormal();
1679     }
1680     else
1681     {
1682         exportpdu_dialog->show();
1683     }
1684
1685     exportpdu_dialog->raise();
1686     exportpdu_dialog->activateWindow();
1687 }
1688
1689 void MainWindow::on_actionFileExportSSLSessionKeys_triggered()
1690 {
1691     QString file_name;
1692     QString save_title;
1693     int keylist_len;
1694
1695     keylist_len = ssl_session_key_count();
1696     /* don't show up the dialog, if no data has to be saved */
1697     if (keylist_len < 1) {
1698         /* shouldn't happen as the menu item should have been greyed out */
1699         QMessageBox::warning(
1700                     this,
1701                     tr("No Keys"),
1702                     tr("There are no SSL Session Keys to save."),
1703                     QMessageBox::Ok
1704                     );
1705         return;
1706     }
1707
1708     save_title.append(wsApp->windowTitleString(tr("Export SSL Session Keys (%1 key%2").
1709             arg(keylist_len).arg(plurality(keylist_len, "", "s"))));
1710     file_name = QFileDialog::getSaveFileName(this,
1711                                              save_title,
1712                                              wsApp->lastOpenDir().canonicalPath(),
1713                                              tr("SSL Session Keys (*.keys *.txt);;Any File (*.*)")
1714                                              );
1715     if (file_name.length() > 0) {
1716         gchar *keylist;
1717         int fd;
1718
1719         keylist = ssl_export_sessions();
1720         fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
1721         if (fd == -1) {
1722             open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
1723             g_free(keylist);
1724             return;
1725         }
1726         /*
1727          * Thanks, Microsoft, for not using size_t for the third argument to
1728          * _write().  Presumably this string will be <= 4GiB long....
1729          */
1730         if (ws_write(fd, keylist, (unsigned int)strlen(keylist)) < 0) {
1731             write_failure_alert_box(file_name.toUtf8().constData(), errno);
1732             ::close(fd);
1733             g_free(keylist);
1734             return;
1735         }
1736         if (::close(fd) < 0) {
1737             write_failure_alert_box(file_name.toUtf8().constData(), errno);
1738             g_free(keylist);
1739             return;
1740         }
1741
1742         /* Save the directory name for future file dialogs. */
1743         wsApp->setLastOpenDir(&file_name);
1744         g_free(keylist);
1745     }
1746 }
1747
1748 void MainWindow::on_actionFileExportObjectsDICOM_triggered()
1749 {
1750     new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Dicom);
1751 }
1752
1753 void MainWindow::on_actionStatisticsHpfeeds_triggered()
1754 {
1755     openStatisticsTreeDialog("hpfeeds");
1756 }
1757
1758 void MainWindow::on_actionFileExportObjectsHTTP_triggered()
1759 {
1760     new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Http);
1761 }
1762
1763 void MainWindow::on_actionFileExportObjectsSMB_triggered()
1764 {
1765     new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Smb);
1766 }
1767
1768 void MainWindow::on_actionFileExportObjectsTFTP_triggered()
1769 {
1770     new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Tftp);
1771 }
1772
1773 void MainWindow::on_actionFilePrint_triggered()
1774 {
1775     PrintDialog pdlg(this, capture_file_.capFile());
1776
1777     pdlg.exec();
1778 }
1779
1780 // Edit Menu
1781
1782 void MainWindow::recursiveCopyProtoTreeItems(QTreeWidgetItem *item, QString &clip, int ident_level) {
1783     if (!item->isExpanded()) return;
1784
1785     for (int i_item = 0; i_item < item->childCount(); i_item += 1) {
1786         clip.append(QString("    ").repeated(ident_level));
1787         clip.append(item->child(i_item)->text(0));
1788         clip.append("\n");
1789
1790         recursiveCopyProtoTreeItems(item->child(i_item), clip, ident_level + 1);
1791     }
1792 }
1793
1794 // XXX This should probably be somewhere else.
1795 void MainWindow::actionEditCopyTriggered(MainWindow::CopySelected selection_type)
1796 {
1797     char label_str[ITEM_LABEL_LENGTH];
1798     QString clip;
1799
1800     if (!capture_file_.capFile()) return;
1801
1802     field_info *finfo_selected = capture_file_.capFile()->finfo_selected;
1803
1804     switch(selection_type) {
1805     case CopySelectedDescription:
1806         if (finfo_selected && finfo_selected->rep
1807                 && strlen (finfo_selected->rep->representation) > 0) {
1808             clip.append(finfo_selected->rep->representation);
1809         }
1810         break;
1811     case CopySelectedFieldName:
1812         if (finfo_selected && finfo_selected->hfinfo->abbrev != 0) {
1813             clip.append(finfo_selected->hfinfo->abbrev);
1814         }
1815         break;
1816     case CopySelectedValue:
1817         if (finfo_selected && capture_file_.capFile()->edt != 0) {
1818             gchar* field_str = get_node_field_value(finfo_selected, capture_file_.capFile()->edt);
1819             clip.append(field_str);
1820             g_free(field_str);
1821         }
1822         break;
1823     case CopyAllVisibleItems:
1824         for (int i_item = 0; i_item < proto_tree_->topLevelItemCount(); i_item += 1) {
1825             clip.append(proto_tree_->topLevelItem(i_item)->text(0));
1826             clip.append("\n");
1827
1828             recursiveCopyProtoTreeItems(proto_tree_->topLevelItem(i_item), clip, 1);
1829         }
1830
1831         break;
1832     case CopyAllVisibleSelectedTreeItems:
1833         if (proto_tree_->selectedItems().count() > 0) {
1834             clip.append(proto_tree_->currentItem()->text(0));
1835             clip.append("\n");
1836
1837             recursiveCopyProtoTreeItems(proto_tree_->currentItem(), clip, 1);
1838         }
1839         break;
1840     }
1841
1842     if (clip.length() == 0) {
1843         /* If no representation then... Try to read the value */
1844         proto_item_fill_label(capture_file_.capFile()->finfo_selected, label_str);
1845         clip.append(label_str);
1846     }
1847
1848     if (clip.length()) {
1849         wsApp->clipboard()->setText(clip);
1850     } else {
1851         QString err = tr("Couldn't copy text. Try another item.");
1852         main_ui_->statusBar->pushTemporaryStatus(err);
1853     }
1854 }
1855
1856 void MainWindow::on_actionCopyAllVisibleItems_triggered()
1857 {
1858     actionEditCopyTriggered(CopyAllVisibleItems);
1859 }
1860
1861 void MainWindow::on_actionCopyAllVisibleSelectedTreeItems_triggered()
1862 {
1863     actionEditCopyTriggered(CopyAllVisibleSelectedTreeItems);
1864 }
1865
1866 void MainWindow::on_actionEditCopyDescription_triggered()
1867 {
1868     actionEditCopyTriggered(CopySelectedDescription);
1869 }
1870
1871 void MainWindow::on_actionEditCopyFieldName_triggered()
1872 {
1873     actionEditCopyTriggered(CopySelectedFieldName);
1874 }
1875
1876 void MainWindow::on_actionEditCopyValue_triggered()
1877 {
1878     actionEditCopyTriggered(CopySelectedValue);
1879 }
1880
1881 void MainWindow::on_actionEditCopyAsFilter_triggered()
1882 {
1883     matchFieldFilter(FilterAction::ActionCopy, FilterAction::ActionTypePlain);
1884 }
1885
1886 void MainWindow::on_actionEditFindPacket_triggered()
1887 {
1888     if (packet_list_->model()->rowCount() < 1) {
1889         return;
1890     }
1891     previous_focus_ = wsApp->focusWidget();
1892     connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
1893     showAccordionFrame(main_ui_->searchFrame, true);
1894 }
1895
1896 void MainWindow::on_actionEditFindNext_triggered()
1897 {
1898     main_ui_->searchFrame->findNext();
1899 }
1900
1901 void MainWindow::on_actionEditFindPrevious_triggered()
1902 {
1903     main_ui_->searchFrame->findPrevious();
1904 }
1905
1906 void MainWindow::on_actionEditMarkPacket_triggered()
1907 {
1908     packet_list_->markFrame();
1909 }
1910
1911 void MainWindow::on_actionEditMarkAllDisplayed_triggered()
1912 {
1913     packet_list_->markAllDisplayedFrames(true);
1914 }
1915
1916 void MainWindow::on_actionEditUnmarkAllDisplayed_triggered()
1917 {
1918     packet_list_->markAllDisplayedFrames(false);
1919 }
1920
1921 void MainWindow::on_actionEditNextMark_triggered()
1922 {
1923     if (capture_file_.capFile())
1924         cf_find_packet_marked(capture_file_.capFile(), SD_FORWARD);
1925 }
1926
1927 void MainWindow::on_actionEditPreviousMark_triggered()
1928 {
1929     if (capture_file_.capFile())
1930         cf_find_packet_marked(capture_file_.capFile(), SD_BACKWARD);
1931 }
1932
1933 void MainWindow::on_actionEditIgnorePacket_triggered()
1934 {
1935     packet_list_->ignoreFrame();
1936 }
1937
1938 void MainWindow::on_actionEditIgnoreAllDisplayed_triggered()
1939 {
1940     packet_list_->ignoreAllDisplayedFrames(true);
1941 }
1942
1943 void MainWindow::on_actionEditUnignoreAllDisplayed_triggered()
1944 {
1945     packet_list_->ignoreAllDisplayedFrames(false);
1946 }
1947
1948 void MainWindow::on_actionEditSetTimeReference_triggered()
1949 {
1950     packet_list_->setTimeReference();
1951 }
1952
1953 void MainWindow::on_actionEditUnsetAllTimeReferences_triggered()
1954 {
1955     packet_list_->unsetAllTimeReferences();
1956 }
1957
1958 void MainWindow::on_actionEditNextTimeReference_triggered()
1959 {
1960     if (!capture_file_.capFile()) return;
1961     cf_find_packet_time_reference(capture_file_.capFile(), SD_FORWARD);
1962 }
1963
1964 void MainWindow::on_actionEditPreviousTimeReference_triggered()
1965 {
1966     if (!capture_file_.capFile()) return;
1967     cf_find_packet_time_reference(capture_file_.capFile(), SD_BACKWARD);
1968 }
1969
1970 void MainWindow::on_actionEditTimeShift_triggered()
1971 {
1972     TimeShiftDialog ts_dialog(this, capture_file_.capFile());
1973     connect(this, SIGNAL(setCaptureFile(capture_file*)),
1974             &ts_dialog, SLOT(setCaptureFile(capture_file*)));
1975     ts_dialog.exec();
1976 }
1977
1978 void MainWindow::on_actionEditPacketComment_triggered()
1979 {
1980     PacketCommentDialog pc_dialog(this, packet_list_->packetComment());
1981     if (pc_dialog.exec() == QDialog::Accepted) {
1982         packet_list_->setPacketComment(pc_dialog.text());
1983         updateForUnsavedChanges();
1984     }
1985 }
1986
1987 void MainWindow::on_actionEditConfigurationProfiles_triggered()
1988 {
1989     ProfileDialog cp_dialog;
1990
1991     cp_dialog.exec();
1992 }
1993
1994 void MainWindow::showPreferencesDialog(PreferencesDialog::PreferencesPane start_pane)
1995 {
1996     PreferencesDialog pref_dialog(this);
1997
1998     pref_dialog.setPane(start_pane);
1999     pref_dialog.exec();
2000
2001     // Emitting PacketDissectionChanged directly from a QDialog can cause
2002     // problems on OS X.
2003     wsApp->flushAppSignals();
2004 }
2005
2006 void MainWindow::showPreferencesDialog(QString module_name)
2007 {
2008     PreferencesDialog pref_dialog(this);
2009
2010     pref_dialog.setPane(module_name);
2011     pref_dialog.exec();
2012
2013     // Emitting PacketDissectionChanged directly from a QDialog can cause
2014     // problems on OS X.
2015     wsApp->flushAppSignals();
2016 }
2017
2018 void MainWindow::on_actionEditPreferences_triggered()
2019 {
2020     showPreferencesDialog();
2021 }
2022
2023 // View Menu
2024
2025 void MainWindow::showHideMainWidgets(QAction *action)
2026 {
2027     if (!action) {
2028         return;
2029     }
2030     bool show = action->isChecked();
2031     QWidget *widget = action->data().value<QWidget*>();
2032
2033     // We may have come from the toolbar context menu, so check/uncheck each
2034     // action as well.
2035     if (widget == main_ui_->mainToolBar) {
2036         recent.main_toolbar_show = show;
2037         main_ui_->actionViewMainToolbar->setChecked(show);
2038     } else if (widget == main_ui_->displayFilterToolBar) {
2039         recent.filter_toolbar_show = show;
2040         main_ui_->actionViewFilterToolbar->setChecked(show);
2041      } else if (widget == main_ui_->wirelessToolBar) {
2042         recent.wireless_toolbar_show = show;
2043         main_ui_->actionViewWirelessToolbar->setChecked(show);
2044     } else if (widget == main_ui_->statusBar) {
2045         recent.statusbar_show = show;
2046         main_ui_->actionViewStatusBar->setChecked(show);
2047     } else if (widget == packet_list_) {
2048         recent.packet_list_show = show;
2049         main_ui_->actionViewPacketList->setChecked(show);
2050     } else if (widget == proto_tree_) {
2051         recent.tree_view_show = show;
2052         main_ui_->actionViewPacketDetails->setChecked(show);
2053     } else if (widget == byte_view_tab_) {
2054         recent.byte_view_show = show;
2055         main_ui_->actionViewPacketBytes->setChecked(show);
2056     }
2057
2058     if (widget) {
2059         widget->setVisible(show);
2060     }
2061 }
2062
2063 Q_DECLARE_METATYPE(ts_type)
2064
2065 void MainWindow::setTimestampFormat(QAction *action)
2066 {
2067     if (!action) {
2068         return;
2069     }
2070     ts_type tsf = action->data().value<ts_type>();
2071     if (recent.gui_time_format != tsf) {
2072         timestamp_set_type(tsf);
2073         recent.gui_time_format = tsf;
2074         if (capture_file_.capFile()) {
2075             /* This call adjusts column width */
2076             cf_timestamp_auto_precision(capture_file_.capFile());
2077         }
2078         if (packet_list_) {
2079             packet_list_->columnsChanged();
2080         }
2081     }
2082 }
2083
2084 Q_DECLARE_METATYPE(ts_precision)
2085
2086 void MainWindow::setTimestampPrecision(QAction *action)
2087 {
2088     if (!action) {
2089         return;
2090     }
2091     ts_precision tsp = action->data().value<ts_precision>();
2092     if (recent.gui_time_precision != tsp) {
2093         /* the actual precision will be set in packet_list_queue_draw() below */
2094         timestamp_set_precision(tsp);
2095         recent.gui_time_precision = tsp;
2096         if (capture_file_.capFile()) {
2097             /* This call adjusts column width */
2098             cf_timestamp_auto_precision(capture_file_.capFile());
2099         }
2100         if (packet_list_) {
2101             packet_list_->columnsChanged();
2102         }
2103     }
2104 }
2105
2106 void MainWindow::on_actionViewTimeDisplaySecondsWithHoursAndMinutes_triggered(bool checked)
2107 {
2108     if (checked) {
2109         recent.gui_seconds_format = TS_SECONDS_HOUR_MIN_SEC;
2110     } else {
2111         recent.gui_seconds_format = TS_SECONDS_DEFAULT;
2112     }
2113     timestamp_set_seconds_type(recent.gui_seconds_format);
2114
2115     if (capture_file_.capFile()) {
2116         /* This call adjusts column width */
2117         cf_timestamp_auto_precision(capture_file_.capFile());
2118     }
2119     if (packet_list_) {
2120         packet_list_->columnsChanged();
2121     }
2122 }
2123
2124 void MainWindow::on_actionViewEditResolvedName_triggered()
2125 {
2126 //    int column = packet_list_->selectedColumn();
2127     int column = -1;
2128
2129     if (packet_list_->currentIndex().isValid()) {
2130         column = packet_list_->currentIndex().column();
2131     }
2132
2133     main_ui_->addressEditorFrame->editAddresses(capture_file_, column);
2134     showAccordionFrame(main_ui_->addressEditorFrame);
2135 }
2136
2137 void MainWindow::setNameResolution()
2138 {
2139     gbl_resolv_flags.mac_name = main_ui_->actionViewNameResolutionPhysical->isChecked() ? TRUE : FALSE;
2140     gbl_resolv_flags.network_name = main_ui_->actionViewNameResolutionNetwork->isChecked() ? TRUE : FALSE;
2141     gbl_resolv_flags.transport_name = main_ui_->actionViewNameResolutionTransport->isChecked() ? TRUE : FALSE;
2142
2143     if (packet_list_) {
2144         packet_list_->columnsChanged();
2145     }
2146 }
2147
2148 void MainWindow::on_actionViewNameResolutionPhysical_triggered()
2149 {
2150     setNameResolution();
2151 }
2152
2153 void MainWindow::on_actionViewNameResolutionNetwork_triggered()
2154 {
2155     setNameResolution();
2156 }
2157
2158 void MainWindow::on_actionViewNameResolutionTransport_triggered()
2159 {
2160     setNameResolution();
2161 }
2162
2163 void MainWindow::zoomText()
2164 {
2165     // Scale by 10%, rounding to nearest half point, minimum 1 point.
2166     // XXX Small sizes repeat. It might just be easier to create a map of multipliers.
2167     mono_font_ = QFont(wsApp->monospaceFont());
2168     qreal zoom_size = wsApp->monospaceFont().pointSize() * 2 * qPow(1.1, recent.gui_zoom_level);
2169     zoom_size = qRound(zoom_size) / 2.0;
2170     zoom_size = qMax(zoom_size, 1.0);
2171     mono_font_.setPointSizeF(zoom_size);
2172     emit monospaceFontChanged(mono_font_);
2173 }
2174
2175 void MainWindow::on_actionViewZoomIn_triggered()
2176 {
2177     recent.gui_zoom_level++;
2178     zoomText();
2179 }
2180
2181 void MainWindow::on_actionViewZoomOut_triggered()
2182 {
2183     recent.gui_zoom_level--;
2184     zoomText();
2185 }
2186
2187 void MainWindow::on_actionViewNormalSize_triggered()
2188 {
2189     recent.gui_zoom_level = 0;
2190     zoomText();
2191 }
2192
2193 void MainWindow::on_actionViewColorizePacketList_triggered(bool checked) {
2194     recent.packet_list_colorize = checked;
2195     color_filters_enable(checked);
2196     packet_list_->packetListModel()->resetColorized();
2197     packet_list_->update();
2198 }
2199
2200 void MainWindow::on_actionViewColoringRules_triggered()
2201 {
2202     ColoringRulesDialog coloring_rules_dialog(this);
2203
2204     coloring_rules_dialog.exec();
2205 }
2206
2207 // actionViewColorizeConversation1 - 10
2208 void MainWindow::colorizeConversation(bool create_rule)
2209 {
2210     QAction *cc_action = qobject_cast<QAction *>(sender());
2211     if (!cc_action) return;
2212
2213     if (capture_file_.capFile() && capture_file_.capFile()->current_frame) {
2214         packet_info *pi = &capture_file_.capFile()->edt->pi;
2215         guint8 cc_num = cc_action->data().toUInt();
2216         gchar *filter = NULL;
2217
2218         const color_conversation_filter_t *color_filter = find_color_conversation_filter("tcp");
2219         if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2220             filter = color_filter->build_filter_string(pi);
2221         if (filter == NULL) {
2222             color_filter = find_color_conversation_filter("udp");
2223             if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2224                 filter = color_filter->build_filter_string(pi);
2225         }
2226         if (filter == NULL) {
2227             color_filter = find_color_conversation_filter("ip");
2228             if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2229                 filter = color_filter->build_filter_string(pi);
2230         }
2231         if (filter == NULL) {
2232             color_filter = find_color_conversation_filter("ipv6");
2233             if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2234                 filter = color_filter->build_filter_string(pi);
2235         }
2236         if (filter == NULL) {
2237             color_filter = find_color_conversation_filter("eth");
2238             if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2239                 filter = color_filter->build_filter_string(pi);
2240         }
2241         if( filter == NULL ) {
2242             main_ui_->statusBar->pushTemporaryStatus(tr("Unable to build conversation filter."));
2243             return;
2244         }
2245
2246         if (create_rule) {
2247             ColoringRulesDialog coloring_rules_dialog(this, filter);
2248             coloring_rules_dialog.exec();
2249         } else {
2250             color_filters_set_tmp(cc_num, filter, FALSE);
2251             packet_list_->recolorPackets();
2252         }
2253     }
2254     setMenusForSelectedPacket();
2255 }
2256
2257 void MainWindow::colorizeWithFilter()
2258 {
2259     QAction *colorize_action = qobject_cast<QAction *>(sender());
2260     if (!colorize_action) return;
2261
2262     QString filter = colorize_action->data().toString();
2263     if (filter.isEmpty()) return;
2264
2265     bool ok = false;
2266     int color_number = colorize_action->property(color_number_property_).toInt(&ok);
2267
2268     if (ok) {
2269         // Assume "Color X"
2270         color_filters_set_tmp(color_number, filter.toUtf8().constData(), FALSE);
2271         packet_list_->recolorPackets();
2272     } else {
2273         // New coloring rule
2274         ColoringRulesDialog coloring_rules_dialog(window(), filter);
2275         coloring_rules_dialog.exec();
2276     }
2277     main_ui_->actionViewColorizeResetColorization->setEnabled(tmp_color_filters_used());
2278 }
2279
2280 void MainWindow::on_actionViewColorizeResetColorization_triggered()
2281 {
2282     color_filters_reset_tmp();
2283     packet_list_->recolorPackets();
2284     setMenusForSelectedPacket();
2285 }
2286
2287 void MainWindow::on_actionViewColorizeNewConversationRule_triggered()
2288 {
2289     colorizeConversation(true);
2290 }
2291
2292 void MainWindow::on_actionViewResizeColumns_triggered()
2293 {
2294     for (int col = 0; col < packet_list_->packetListModel()->columnCount(); col++) {
2295         packet_list_->resizeColumnToContents(col);
2296         recent_set_column_width(col, packet_list_->columnWidth(col));
2297     }
2298 }
2299
2300 void MainWindow::openPacketDialog(bool from_reference)
2301 {
2302     frame_data * fdata;
2303
2304     /* Find the frame for which we're popping up a dialog */
2305     if(from_reference) {
2306         guint32 framenum = fvalue_get_uinteger(&(capture_file_.capFile()->finfo_selected->value));
2307         if (framenum == 0)
2308             return;
2309
2310         fdata = frame_data_sequence_find(capture_file_.capFile()->frames, framenum);
2311     } else {
2312         fdata = capture_file_.capFile()->current_frame;
2313     }
2314
2315     /* If we have a frame, pop up the dialog */
2316     if (fdata) {
2317         PacketDialog *packet_dialog = new PacketDialog(*this, capture_file_, fdata);
2318
2319         connect(this, SIGNAL(monospaceFontChanged(QFont)),
2320                 packet_dialog, SIGNAL(monospaceFontChanged(QFont)));
2321         connect(this, SIGNAL(closePacketDialogs()),
2322                 packet_dialog, SLOT(close()));
2323         zoomText(); // Emits monospaceFontChanged
2324
2325         packet_dialog->show();
2326     }
2327 }
2328
2329 void MainWindow::on_actionViewInternalsConversationHashTables_triggered()
2330 {
2331     ConversationHashTablesDialog *conversation_hash_tables_dlg = new ConversationHashTablesDialog(this);
2332     conversation_hash_tables_dlg->show();
2333 }
2334
2335 void MainWindow::on_actionViewInternalsDissectorTables_triggered()
2336 {
2337     DissectorTablesDialog *dissector_tables_dlg = new DissectorTablesDialog(this);
2338     dissector_tables_dlg->show();
2339 }
2340
2341 void MainWindow::on_actionViewInternalsSupportedProtocols_triggered()
2342 {
2343     SupportedProtocolsDialog *supported_protocols_dlg = new SupportedProtocolsDialog(this);
2344     supported_protocols_dlg->show();
2345 }
2346
2347 void MainWindow::on_actionViewShowPacketInNewWindow_triggered()
2348 {
2349     openPacketDialog();
2350 }
2351
2352 // This is only used in ProtoTree. Defining it here makes more sense.
2353 void MainWindow::on_actionContextShowLinkedPacketInNewWindow_triggered()
2354 {
2355     openPacketDialog(true);
2356 }
2357
2358 void MainWindow::on_actionViewReload_triggered()
2359 {
2360     cf_reload(CaptureFile::globalCapFile());
2361 }
2362
2363 // Expand / collapse slots in proto_tree
2364
2365 // Go Menu
2366
2367 // Analyze Menu
2368
2369 void MainWindow::matchFieldFilter(FilterAction::Action action, FilterAction::ActionType filter_type)
2370 {
2371     QString field_filter;
2372
2373     if (packet_list_->contextMenuActive() || packet_list_->hasFocus()) {
2374         field_filter = packet_list_->getFilterFromRowAndColumn();
2375     } else if (capture_file_.capFile() && capture_file_.capFile()->finfo_selected) {
2376         char *tmp_field = proto_construct_match_selected_string(capture_file_.capFile()->finfo_selected,
2377                                                        capture_file_.capFile()->edt);
2378         field_filter = QString(tmp_field);
2379         wmem_free(NULL, tmp_field);
2380     }
2381
2382     if (field_filter.isEmpty()) {
2383         QString err = tr("No filter available. Try another ");
2384         err.append(packet_list_->contextMenuActive() ? "column" : "item");
2385         err.append(".");
2386         main_ui_->statusBar->pushTemporaryStatus(err);
2387         return;
2388     }
2389
2390     filterAction(field_filter, action, filter_type);
2391 }
2392
2393 static FilterDialog *display_filter_dlg_ = NULL;
2394 void MainWindow::on_actionAnalyzeDisplayFilters_triggered()
2395 {
2396     if (!display_filter_dlg_) {
2397         display_filter_dlg_ = new FilterDialog(this, FilterDialog::DisplayFilter);
2398     }
2399     display_filter_dlg_->show();
2400     display_filter_dlg_->raise();
2401     display_filter_dlg_->activateWindow();
2402 }
2403
2404 struct epan_uat;
2405 void MainWindow::on_actionAnalyzeDisplayFilterMacros_triggered()
2406 {
2407     struct epan_uat* dfm_uat;
2408     dfilter_macro_get_uat(&dfm_uat);
2409     UatDialog uat_dlg(parentWidget(), dfm_uat);
2410
2411     uat_dlg.exec();
2412     // Emitting PacketDissectionChanged directly from a QDialog can cause
2413     // problems on OS X.
2414     wsApp->flushAppSignals();
2415 }
2416
2417 void MainWindow::on_actionAnalyzeCreateAColumn_triggered()
2418 {
2419     gint colnr = 0;
2420
2421     if ( capture_file_.capFile() != 0 && capture_file_.capFile()->finfo_selected != 0 )
2422     {
2423         colnr = column_prefs_add_custom(COL_CUSTOM, capture_file_.capFile()->finfo_selected->hfinfo->name,
2424                     capture_file_.capFile()->finfo_selected->hfinfo->abbrev,0);
2425
2426         packet_list_->columnsChanged();
2427         packet_list_->resizeColumnToContents(colnr);
2428
2429         prefs_main_write();
2430     }
2431 }
2432
2433 void MainWindow::applyConversationFilter()
2434 {
2435     QAction *cfa = qobject_cast<QAction*>(sender());
2436     if (!cfa) return;
2437
2438     QString new_filter = cfa->data().toString();
2439     if (new_filter.isEmpty()) return;
2440
2441     df_combo_box_->lineEdit()->setText(new_filter);
2442     df_combo_box_->applyDisplayFilter();
2443 }
2444
2445 // XXX We could probably create the analyze and prepare actions
2446 // dynamically using FilterActions and consolidate the methods
2447 // below into one callback.
2448 void MainWindow::on_actionAnalyzeAAFSelected_triggered()
2449 {
2450     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypePlain);
2451 }
2452
2453 void MainWindow::on_actionAnalyzeAAFNotSelected_triggered()
2454 {
2455     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeNot);
2456 }
2457
2458 void MainWindow::on_actionAnalyzeAAFAndSelected_triggered()
2459 {
2460     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeAnd);
2461 }
2462
2463 void MainWindow::on_actionAnalyzeAAFOrSelected_triggered()
2464 {
2465     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeOr);
2466 }
2467
2468 void MainWindow::on_actionAnalyzeAAFAndNotSelected_triggered()
2469 {
2470     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeAndNot);
2471 }
2472
2473 void MainWindow::on_actionAnalyzeAAFOrNotSelected_triggered()
2474 {
2475     matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeOrNot);
2476 }
2477
2478 void MainWindow::on_actionAnalyzePAFSelected_triggered()
2479 {
2480     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypePlain);
2481 }
2482
2483 void MainWindow::on_actionAnalyzePAFNotSelected_triggered()
2484 {
2485     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeNot);
2486 }
2487
2488 void MainWindow::on_actionAnalyzePAFAndSelected_triggered()
2489 {
2490     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeAnd);
2491 }
2492
2493 void MainWindow::on_actionAnalyzePAFOrSelected_triggered()
2494 {
2495     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeOr);
2496 }
2497
2498 void MainWindow::on_actionAnalyzePAFAndNotSelected_triggered()
2499 {
2500     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeAndNot);
2501 }
2502
2503 void MainWindow::on_actionAnalyzePAFOrNotSelected_triggered()
2504 {
2505     matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeOrNot);
2506 }
2507
2508 void MainWindow::on_actionAnalyzeEnabledProtocols_triggered()
2509 {
2510     EnabledProtocolsDialog enable_proto_dialog(this);
2511     enable_proto_dialog.exec();
2512
2513     // Emitting PacketDissectionChanged directly from a QDialog can cause
2514     // problems on OS X.
2515     wsApp->flushAppSignals();
2516 }
2517
2518 void MainWindow::on_actionAnalyzeDecodeAs_triggered()
2519 {
2520     QAction *da_action = qobject_cast<QAction*>(sender());
2521     bool create_new = false;
2522     if (da_action && da_action->data().toBool() == true) {
2523         create_new = true;
2524     }
2525
2526     DecodeAsDialog da_dialog(this, capture_file_.capFile(), create_new);
2527     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2528             &da_dialog, SLOT(setCaptureFile(capture_file*)));
2529     da_dialog.exec();
2530
2531     // Emitting PacketDissectionChanged directly from a QDialog can cause
2532     // problems on OS X.
2533     wsApp->flushAppSignals();
2534 }
2535
2536 #ifdef HAVE_LUA
2537 void MainWindow::on_actionAnalyzeReloadLuaPlugins_triggered()
2538 {
2539     if (wsApp->isReloadingLua())
2540         return;
2541
2542     wsApp->setReloadingLua(true);
2543
2544     wslua_reload_plugins(NULL, NULL);
2545     funnel_statistics_reload_menus();
2546     reloadDynamicMenus();
2547     closePacketDialogs();
2548
2549     // Preferences may have been deleted so close all widgets using prefs
2550     proto_tree_->closeContextMenu();
2551     main_ui_->preferenceEditorFrame->animatedHide();
2552
2553     char *gdp_path, *dp_path;
2554     (void) wsApp->readConfigurationFiles(&gdp_path, &dp_path);
2555
2556     fieldsChanged();
2557     redissectPackets();
2558
2559     wsApp->setReloadingLua(false);
2560     SimpleDialog::displayQueuedMessages();
2561 }
2562 #endif
2563
2564 void MainWindow::openFollowStreamDialog(follow_type_t type) {
2565     FollowStreamDialog *fsd = new FollowStreamDialog(*this, capture_file_, type);
2566     connect(fsd, SIGNAL(updateFilter(QString, bool)), this, SLOT(filterPackets(QString, bool)));
2567     connect(fsd, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
2568
2569     fsd->show();
2570     fsd->follow(getFilter());
2571 }
2572
2573 void MainWindow::on_actionAnalyzeFollowTCPStream_triggered()
2574 {
2575     openFollowStreamDialog(FOLLOW_TCP);
2576 }
2577
2578 void MainWindow::on_actionAnalyzeFollowUDPStream_triggered()
2579 {
2580     openFollowStreamDialog(FOLLOW_UDP);
2581 }
2582
2583 void MainWindow::on_actionAnalyzeFollowSSLStream_triggered()
2584 {
2585     openFollowStreamDialog(FOLLOW_SSL);
2586 }
2587
2588 void MainWindow::openSCTPAllAssocsDialog()
2589 {
2590     SCTPAllAssocsDialog *sctp_dialog = new SCTPAllAssocsDialog(this, capture_file_.capFile());
2591     connect(sctp_dialog, SIGNAL(filterPackets(QString,bool)),
2592             this, SLOT(filterPackets(QString,bool)));
2593     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2594             sctp_dialog, SLOT(setCaptureFile(capture_file*)));
2595     sctp_dialog->fillTable();
2596
2597     if (sctp_dialog->isMinimized() == true)
2598     {
2599         sctp_dialog->showNormal();
2600     }
2601     else
2602     {
2603         sctp_dialog->show();
2604     }
2605
2606     sctp_dialog->raise();
2607     sctp_dialog->activateWindow();
2608 }
2609
2610 void MainWindow::on_actionSCTPShowAllAssociations_triggered()
2611 {
2612     openSCTPAllAssocsDialog();
2613 }
2614
2615 void MainWindow::on_actionSCTPAnalyseThisAssociation_triggered()
2616 {
2617     SCTPAssocAnalyseDialog *sctp_analyse = new SCTPAssocAnalyseDialog(this, NULL, capture_file_.capFile());
2618     connect(sctp_analyse, SIGNAL(filterPackets(QString,bool)),
2619             this, SLOT(filterPackets(QString,bool)));
2620
2621     if (sctp_analyse->isMinimized() == true)
2622     {
2623         sctp_analyse->showNormal();
2624     }
2625     else
2626     {
2627         sctp_analyse->show();
2628     }
2629
2630     sctp_analyse->raise();
2631     sctp_analyse->activateWindow();
2632 }
2633
2634 void MainWindow::on_actionSCTPFilterThisAssociation_triggered()
2635 {
2636     sctp_assoc_info_t* assoc = SCTPAssocAnalyseDialog::findAssocForPacket(capture_file_.capFile());
2637     if (assoc) {
2638         QString newFilter = QString("sctp.assoc_index==%1").arg(assoc->assoc_id);
2639         assoc = NULL;
2640         emit filterPackets(newFilter, false);
2641     }
2642 }
2643
2644 // -z wlan,stat
2645 void MainWindow::statCommandWlanStatistics(const char *arg, void *)
2646 {
2647     WlanStatisticsDialog *wlan_stats_dlg = new WlanStatisticsDialog(*this, capture_file_, arg);
2648     connect(wlan_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2649             this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2650     wlan_stats_dlg->show();
2651 }
2652
2653 void MainWindow::on_actionWirelessWlanStatistics_triggered()
2654 {
2655     statCommandWlanStatistics(NULL, NULL);
2656 }
2657
2658 // -z expert
2659 void MainWindow::statCommandExpertInfo(const char *, void *)
2660 {
2661     ExpertInfoDialog *expert_dialog = new ExpertInfoDialog(*this, capture_file_);
2662     const DisplayFilterEdit *df_edit = dynamic_cast<DisplayFilterEdit *>(df_combo_box_->lineEdit());
2663
2664     expert_dialog->setDisplayFilter(df_edit->text());
2665
2666     connect(expert_dialog, SIGNAL(goToPacket(int, int)),
2667             packet_list_, SLOT(goToPacket(int, int)));
2668     connect(expert_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2669             this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2670
2671     expert_dialog->show();
2672 }
2673
2674 void MainWindow::on_actionAnalyzeExpertInfo_triggered()
2675 {
2676     statCommandExpertInfo(NULL, NULL);
2677 }
2678
2679
2680 // Next / previous / first / last slots in packet_list
2681
2682 // Statistics Menu
2683
2684 void MainWindow::on_actionStatisticsFlowGraph_triggered()
2685 {
2686     SequenceDialog *sequence_dialog = new SequenceDialog(*this, capture_file_);
2687     connect(sequence_dialog, SIGNAL(goToPacket(int)),
2688             packet_list_, SLOT(goToPacket(int)));
2689     sequence_dialog->show();
2690 }
2691
2692 void MainWindow::openTcpStreamDialog(int graph_type)
2693 {
2694     TCPStreamDialog *stream_dialog = new TCPStreamDialog(this, capture_file_.capFile(), (tcp_graph_type)graph_type);
2695     connect(stream_dialog, SIGNAL(goToPacket(int)),
2696             packet_list_, SLOT(goToPacket(int)));
2697     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2698             stream_dialog, SLOT(setCaptureFile(capture_file*)));
2699     stream_dialog->show();
2700 }
2701
2702 void MainWindow::on_actionStatisticsTcpStreamStevens_triggered()
2703 {
2704     openTcpStreamDialog(GRAPH_TSEQ_STEVENS);
2705 }
2706
2707 void MainWindow::on_actionStatisticsTcpStreamTcptrace_triggered()
2708 {
2709     openTcpStreamDialog(GRAPH_TSEQ_TCPTRACE);
2710 }
2711
2712 void MainWindow::on_actionStatisticsTcpStreamThroughput_triggered()
2713 {
2714     openTcpStreamDialog(GRAPH_THROUGHPUT);
2715 }
2716
2717 void MainWindow::on_actionStatisticsTcpStreamRoundTripTime_triggered()
2718 {
2719     openTcpStreamDialog(GRAPH_RTT);
2720 }
2721
2722 void MainWindow::on_actionStatisticsTcpStreamWindowScaling_triggered()
2723 {
2724     openTcpStreamDialog(GRAPH_WSCALE);
2725 }
2726
2727 // -z mcast,stat
2728 void MainWindow::statCommandMulticastStatistics(const char *arg, void *)
2729 {
2730     MulticastStatisticsDialog *mcast_stats_dlg = new MulticastStatisticsDialog(*this, capture_file_, arg);
2731     connect(mcast_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2732             this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2733     mcast_stats_dlg->show();
2734 }
2735
2736 void MainWindow::on_actionStatisticsUdpMulticastStreams_triggered()
2737 {
2738     statCommandMulticastStatistics(NULL, NULL);
2739 }
2740
2741 void MainWindow::openStatisticsTreeDialog(const gchar *abbr)
2742 {
2743     StatsTreeDialog *st_dialog = new StatsTreeDialog(*this, capture_file_, abbr);
2744 //    connect(st_dialog, SIGNAL(goToPacket(int)),
2745 //            packet_list_, SLOT(goToPacket(int)));
2746     st_dialog->show();
2747 }
2748
2749 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Topic_triggered()
2750 {
2751     openStatisticsTreeDialog("lbmr_topic_ads_topic");
2752 }
2753
2754 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Source_triggered()
2755 {
2756     openStatisticsTreeDialog("lbmr_topic_ads_source");
2757 }
2758
2759 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Transport_triggered()
2760 {
2761     openStatisticsTreeDialog("lbmr_topic_ads_transport");
2762 }
2763
2764 void MainWindow::on_actionStatistics29WestTopics_Queries_by_Topic_triggered()
2765 {
2766     openStatisticsTreeDialog("lbmr_topic_queries_topic");
2767 }
2768
2769 void MainWindow::on_actionStatistics29WestTopics_Queries_by_Receiver_triggered()
2770 {
2771     openStatisticsTreeDialog("lbmr_topic_queries_receiver");
2772 }
2773
2774 void MainWindow::on_actionStatistics29WestTopics_Wildcard_Queries_by_Pattern_triggered()
2775 {
2776     openStatisticsTreeDialog("lbmr_topic_queries_pattern");
2777 }
2778
2779 void MainWindow::on_actionStatistics29WestTopics_Wildcard_Queries_by_Receiver_triggered()
2780 {
2781     openStatisticsTreeDialog("lbmr_topic_queries_pattern_receiver");
2782 }
2783
2784 void MainWindow::on_actionStatistics29WestQueues_Advertisements_by_Queue_triggered()
2785 {
2786     openStatisticsTreeDialog("lbmr_queue_ads_queue");
2787 }
2788
2789 void MainWindow::on_actionStatistics29WestQueues_Advertisements_by_Source_triggered()
2790 {
2791     openStatisticsTreeDialog("lbmr_queue_ads_source");
2792 }
2793
2794 void MainWindow::on_actionStatistics29WestQueues_Queries_by_Queue_triggered()
2795 {
2796     openStatisticsTreeDialog("lbmr_queue_queries_queue");
2797 }
2798
2799 void MainWindow::on_actionStatistics29WestQueues_Queries_by_Receiver_triggered()
2800 {
2801     openStatisticsTreeDialog("lbmr_queue_queries_receiver");
2802 }
2803
2804 void MainWindow::on_actionStatistics29WestUIM_Streams_triggered()
2805 {
2806     LBMStreamDialog *stream_dialog = new LBMStreamDialog(this, capture_file_.capFile());
2807 //    connect(stream_dialog, SIGNAL(goToPacket(int)),
2808 //            packet_list_, SLOT(goToPacket(int)));
2809     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2810             stream_dialog, SLOT(setCaptureFile(capture_file*)));
2811     stream_dialog->show();
2812 }
2813
2814 void MainWindow::on_actionStatistics29WestUIM_Stream_Flow_Graph_triggered()
2815 {
2816     LBMUIMFlowDialog * uimflow_dialog = new LBMUIMFlowDialog(this, capture_file_.capFile());
2817     connect(uimflow_dialog, SIGNAL(goToPacket(int)),
2818             packet_list_, SLOT(goToPacket(int)));
2819     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2820             uimflow_dialog, SLOT(setCaptureFile(capture_file*)));
2821     uimflow_dialog->show();
2822 }
2823
2824 void MainWindow::on_actionStatistics29WestLBTRM_triggered()
2825 {
2826     LBMLBTRMTransportDialog * lbtrm_dialog = new LBMLBTRMTransportDialog(this, capture_file_.capFile());
2827     connect(lbtrm_dialog, SIGNAL(goToPacket(int)),
2828             packet_list_, SLOT(goToPacket(int)));
2829     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2830             lbtrm_dialog, SLOT(setCaptureFile(capture_file*)));
2831     lbtrm_dialog->show();
2832 }
2833 void MainWindow::on_actionStatistics29WestLBTRU_triggered()
2834 {
2835     LBMLBTRUTransportDialog * lbtru_dialog = new LBMLBTRUTransportDialog(this, capture_file_.capFile());
2836     connect(lbtru_dialog, SIGNAL(goToPacket(int)),
2837             packet_list_, SLOT(goToPacket(int)));
2838     connect(this, SIGNAL(setCaptureFile(capture_file*)),
2839             lbtru_dialog, SLOT(setCaptureFile(capture_file*)));
2840     lbtru_dialog->show();
2841 }
2842
2843 void MainWindow::on_actionStatisticsANCP_triggered()
2844 {
2845     openStatisticsTreeDialog("ancp");
2846 }
2847
2848 void MainWindow::on_actionStatisticsBACappInstanceId_triggered()
2849 {
2850     openStatisticsTreeDialog("bacapp_instanceid");
2851 }
2852
2853 void MainWindow::on_actionStatisticsBACappIP_triggered()
2854 {
2855     openStatisticsTreeDialog("bacapp_ip");
2856 }
2857
2858 void MainWindow::on_actionStatisticsBACappObjectId_triggered()
2859 {
2860     openStatisticsTreeDialog("bacapp_objectid");
2861 }
2862
2863 void MainWindow::on_actionStatisticsBACappService_triggered()
2864 {
2865     openStatisticsTreeDialog("bacapp_service");
2866 }
2867
2868 void MainWindow::on_actionStatisticsCollectd_triggered()
2869 {
2870     openStatisticsTreeDialog("collectd");
2871 }
2872
2873 // -z conv,...
2874 void MainWindow::statCommandConversations(const char *arg, void *userdata)
2875 {
2876     ConversationDialog *conv_dialog = new ConversationDialog(*this, capture_file_, GPOINTER_TO_INT(userdata), arg);
2877     connect(conv_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2878             this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2879     connect(conv_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
2880             this, SLOT(openFollowStreamDialog(follow_type_t)));
2881     connect(conv_dialog, SIGNAL(openTcpStreamGraph(int)),
2882             this, SLOT(openTcpStreamDialog(int)));
2883     conv_dialog->show();
2884 }
2885
2886 void MainWindow::on_actionStatisticsConversations_triggered()
2887 {
2888     statCommandConversations(NULL, NULL);
2889 }
2890
2891 // -z endpoints,...
2892 void MainWindow::statCommandEndpoints(const char *arg, void *userdata)
2893 {
2894     EndpointDialog *endp_dialog = new EndpointDialog(*this, capture_file_, GPOINTER_TO_INT(userdata), arg);
2895     connect(endp_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2896             this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2897     connect(endp_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
2898             this, SLOT(openFollowStreamDialog(follow_type_t)));
2899     connect(endp_dialog, SIGNAL(openTcpStreamGraph(int)),
2900             this, SLOT(openTcpStreamDialog(int)));
2901     endp_dialog->show();
2902 }
2903
2904 void MainWindow::on_actionStatisticsEndpoints_triggered()
2905 {
2906     statCommandEndpoints(NULL, NULL);
2907 }
2908
2909 void MainWindow::on_actionStatisticsHART_IP_triggered()
2910 {
2911     openStatisticsTreeDialog("hart_ip");
2912 }
2913
2914 void MainWindow::on_actionStatisticsHTTPPacketCounter_triggered()
2915 {
2916     openStatisticsTreeDialog("http");
2917 }
2918
2919 void MainWindow::on_actionStatisticsHTTPRequests_triggered()
2920 {
2921     openStatisticsTreeDialog("http_req");
2922 }
2923
2924 void MainWindow::on_actionStatisticsHTTPLoadDistribution_triggered()
2925 {
2926     openStatisticsTreeDialog("http_srv");
2927 }
2928
2929 void MainWindow::on_actionStatisticsPacketLengths_triggered()
2930 {
2931     openStatisticsTreeDialog("plen");
2932 }
2933
2934 // -z io,stat
2935 void MainWindow::statCommandIOGraph(const char *, void *)
2936 {
2937     IOGraphDialog *iog_dialog = new IOGraphDialog(*this, capture_file_);
2938     connect(iog_dialog, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
2939     connect(this, SIGNAL(reloadFields()), iog_dialog, SLOT(reloadFields()));
2940     iog_dialog->show();
2941 }
2942
2943 void MainWindow::on_actionStatisticsIOGraph_triggered()
2944 {
2945     statCommandIOGraph(NULL, NULL);
2946 }
2947
2948 void MainWindow::on_actionStatisticsSametime_triggered()
2949 {
2950     openStatisticsTreeDialog("sametime");
2951 }
2952
2953 void MainWindow::on_actionStatisticsDNS_triggered()
2954 {
2955     openStatisticsTreeDialog("dns");
2956 }
2957
2958 void MainWindow::actionStatisticsPlugin_triggered()
2959 {
2960     QAction* action = qobject_cast<QAction*>(sender());
2961     if(action) {
2962         openStatisticsTreeDialog(action->data().toString().toUtf8());
2963     }
2964 }
2965
2966 void MainWindow::on_actionStatisticsHTTP2_triggered()
2967 {
2968     openStatisticsTreeDialog("http2");
2969
2970 }
2971
2972 // Telephony Menu
2973
2974 void MainWindow::openVoipCallsDialog(bool all_flows)
2975 {
2976     VoipCallsDialog *voip_calls_dialog = new VoipCallsDialog(*this, capture_file_, all_flows);
2977     connect(voip_calls_dialog, SIGNAL(goToPacket(int)),
2978             packet_list_, SLOT(goToPacket(int)));
2979     connect(voip_calls_dialog, SIGNAL(updateFilter(QString, bool)),
2980             this, SLOT(filterPackets(QString, bool)));
2981     voip_calls_dialog->show();
2982 }
2983
2984 void MainWindow::on_actionTelephonyVoipCalls_triggered()
2985 {
2986     openVoipCallsDialog();
2987 }
2988
2989 void MainWindow::on_actionTelephonyGsmMapSummary_triggered()
2990 {
2991     GsmMapSummaryDialog *gms_dialog = new GsmMapSummaryDialog(*this, capture_file_);
2992     gms_dialog->show();
2993 }
2994
2995 void MainWindow::on_actionTelephonyIax2StreamAnalysis_triggered()
2996 {
2997     Iax2AnalysisDialog *iax2_analysis_dialog = new  Iax2AnalysisDialog(*this, capture_file_);
2998     connect(iax2_analysis_dialog, SIGNAL(goToPacket(int)),
2999             packet_list_, SLOT(goToPacket(int)));
3000     iax2_analysis_dialog->show();
3001 }
3002
3003 void MainWindow::on_actionTelephonyISUPMessages_triggered()
3004 {
3005     openStatisticsTreeDialog("isup_msg");
3006 }
3007
3008 // -z mac-lte,stat
3009 void MainWindow::statCommandLteMacStatistics(const char *arg, void *)
3010 {
3011     LteMacStatisticsDialog *lte_mac_stats_dlg = new LteMacStatisticsDialog(*this, capture_file_, arg);
3012     connect(lte_mac_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
3013             this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
3014     lte_mac_stats_dlg->show();
3015 }
3016
3017 void MainWindow::on_actionTelephonyLteMacStatistics_triggered()
3018 {
3019     statCommandLteMacStatistics(NULL, NULL);
3020 }
3021
3022 void MainWindow::statCommandLteRlcStatistics(const char *arg, void *)
3023 {
3024     LteRlcStatisticsDialog *lte_rlc_stats_dlg = new LteRlcStatisticsDialog(*this, capture_file_, arg);
3025     connect(lte_rlc_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
3026             this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
3027     lte_rlc_stats_dlg->show();
3028 }
3029
3030 void MainWindow::on_actionTelephonyLteRlcStatistics_triggered()
3031 {
3032     statCommandLteRlcStatistics(NULL, NULL);
3033 }
3034
3035 void MainWindow::on_actionTelephonyLteRlcGraph_triggered()
3036 {
3037     LteRlcGraphDialog *lrg_dialog = new LteRlcGraphDialog(*this, capture_file_);
3038     lrg_dialog->show();
3039 }
3040
3041 void MainWindow::on_actionTelephonyMtp3Summary_triggered()
3042 {
3043     Mtp3SummaryDialog *mtp3s_dialog = new Mtp3SummaryDialog(*this, capture_file_);
3044     mtp3s_dialog->show();
3045 }
3046
3047 void MainWindow::on_actionTelephonyRTPStreams_triggered()
3048 {
3049     RtpStreamDialog *rtp_stream_dialog = new  RtpStreamDialog(*this, capture_file_);
3050     connect(rtp_stream_dialog, SIGNAL(packetsMarked()),
3051             packet_list_, SLOT(redrawVisiblePackets()));
3052     connect(rtp_stream_dialog, SIGNAL(goToPacket(int)),
3053             packet_list_, SLOT(goToPacket(int)));
3054     connect(rtp_stream_dialog, SIGNAL(updateFilter(QString, bool)),
3055             this, SLOT(filterPackets(QString, bool)));
3056     rtp_stream_dialog->show();
3057 }
3058
3059 void MainWindow::on_actionTelephonyRTPStreamAnalysis_triggered()
3060 {
3061     RtpAnalysisDialog *rtp_analysis_dialog = new  RtpAnalysisDialog(*this, capture_file_);
3062     connect(rtp_analysis_dialog, SIGNAL(goToPacket(int)),
3063             packet_list_, SLOT(goToPacket(int)));
3064     rtp_analysis_dialog->show();
3065 }
3066
3067 void MainWindow::on_actionTelephonyRTSPPacketCounter_triggered()
3068 {
3069     openStatisticsTreeDialog("rtsp");
3070 }
3071
3072 void MainWindow::on_actionTelephonySMPPOperations_triggered()
3073 {
3074     openStatisticsTreeDialog("smpp_commands");
3075 }
3076
3077 void MainWindow::on_actionTelephonyUCPMessages_triggered()
3078 {
3079     openStatisticsTreeDialog("ucp_messages");
3080 }
3081
3082 void MainWindow::on_actionTelephonySipFlows_triggered()
3083 {
3084     openVoipCallsDialog(true);
3085 }
3086
3087 // Bluetooth Menu
3088
3089 void MainWindow::on_actionBluetoothATT_Server_Attributes_triggered()
3090 {
3091     BluetoothAttServerAttributesDialog *bluetooth_att_sever_attributes_dialog = new BluetoothAttServerAttributesDialog(*this, capture_file_);
3092     connect(bluetooth_att_sever_attributes_dialog, SIGNAL(goToPacket(int)),
3093             packet_list_, SLOT(goToPacket(int)));
3094     connect(bluetooth_att_sever_attributes_dialog, SIGNAL(updateFilter(QString, bool)),
3095             this, SLOT(filterPackets(QString, bool)));
3096     bluetooth_att_sever_attributes_dialog->show();
3097 }
3098
3099 void MainWindow::on_actionBluetoothDevices_triggered()
3100 {
3101     BluetoothDevicesDialog *bluetooth_devices_dialog = new BluetoothDevicesDialog(*this, capture_file_);
3102     connect(bluetooth_devices_dialog, SIGNAL(goToPacket(int)),
3103             packet_list_, SLOT(goToPacket(int)));
3104     connect(bluetooth_devices_dialog, SIGNAL(updateFilter(QString, bool)),
3105             this, SLOT(filterPackets(QString, bool)));
3106     bluetooth_devices_dialog->show();
3107 }
3108
3109 void MainWindow::on_actionBluetoothHCI_Summary_triggered()
3110 {
3111     BluetoothHciSummaryDialog *bluetooth_hci_summary_dialog = new BluetoothHciSummaryDialog(*this, capture_file_);
3112     connect(bluetooth_hci_summary_dialog, SIGNAL(goToPacket(int)),
3113             packet_list_, SLOT(goToPacket(int)));
3114     connect(bluetooth_hci_summary_dialog, SIGNAL(updateFilter(QString, bool)),
3115             this, SLOT(filterPackets(QString, bool)));
3116     bluetooth_hci_summary_dialog->show();
3117 }
3118
3119 // Help Menu
3120 void MainWindow::on_actionHelpContents_triggered() {
3121
3122     wsApp->helpTopicAction(HELP_CONTENT);
3123 }
3124
3125 void MainWindow::on_actionHelpMPWireshark_triggered() {
3126
3127     wsApp->helpTopicAction(LOCALPAGE_MAN_WIRESHARK);
3128 }
3129
3130 void MainWindow::on_actionHelpMPWireshark_Filter_triggered() {
3131     wsApp->helpTopicAction(LOCALPAGE_MAN_WIRESHARK_FILTER);
3132 }
3133
3134 void MainWindow::on_actionHelpMPCapinfos_triggered() {
3135     wsApp->helpTopicAction(LOCALPAGE_MAN_CAPINFOS);
3136 }
3137
3138 void MainWindow::on_actionHelpMPDumpcap_triggered() {
3139     wsApp->helpTopicAction(LOCALPAGE_MAN_DUMPCAP);
3140 }
3141
3142 void MainWindow::on_actionHelpMPEditcap_triggered() {
3143     wsApp->helpTopicAction(LOCALPAGE_MAN_EDITCAP);
3144 }
3145
3146 void MainWindow::on_actionHelpMPMergecap_triggered() {
3147     wsApp->helpTopicAction(LOCALPAGE_MAN_MERGECAP);
3148 }
3149
3150 void MainWindow::on_actionHelpMPRawShark_triggered() {
3151     wsApp->helpTopicAction(LOCALPAGE_MAN_RAWSHARK);
3152 }
3153
3154 void MainWindow::on_actionHelpMPReordercap_triggered() {
3155     wsApp->helpTopicAction(LOCALPAGE_MAN_REORDERCAP);
3156 }
3157
3158  void MainWindow::on_actionHelpMPText2cap_triggered() {
3159     wsApp->helpTopicAction(LOCALPAGE_MAN_TEXT2PCAP);
3160 }
3161
3162 void MainWindow::on_actionHelpMPTShark_triggered() {
3163     wsApp->helpTopicAction(LOCALPAGE_MAN_TSHARK);
3164 }
3165
3166 void MainWindow::on_actionHelpWebsite_triggered() {
3167
3168     wsApp->helpTopicAction(ONLINEPAGE_HOME);
3169 }
3170
3171 void MainWindow::on_actionHelpFAQ_triggered() {
3172
3173     wsApp->helpTopicAction(ONLINEPAGE_FAQ);
3174 }
3175
3176 void MainWindow::on_actionHelpAsk_triggered() {
3177
3178     wsApp->helpTopicAction(ONLINEPAGE_ASK);
3179 }
3180
3181 void MainWindow::on_actionHelpDownloads_triggered() {
3182
3183     wsApp->helpTopicAction(ONLINEPAGE_DOWNLOAD);
3184 }
3185
3186 void MainWindow::on_actionHelpWiki_triggered() {
3187
3188     wsApp->helpTopicAction(ONLINEPAGE_WIKI);
3189 }
3190
3191 void MainWindow::on_actionHelpSampleCaptures_triggered() {
3192
3193     wsApp->helpTopicAction(ONLINEPAGE_SAMPLE_FILES);
3194 }
3195
3196 #ifdef HAVE_SOFTWARE_UPDATE
3197 void MainWindow::checkForUpdates()
3198 {
3199     software_update_check();
3200 }
3201 #endif
3202
3203 void MainWindow::on_actionHelpAbout_triggered()
3204 {
3205     AboutDialog *about_dialog = new AboutDialog(this);
3206
3207     if (about_dialog->isMinimized() == true)
3208     {
3209         about_dialog->showNormal();
3210     }
3211     else
3212     {
3213         about_dialog->show();
3214     }
3215
3216     about_dialog->raise();
3217     about_dialog->activateWindow();
3218 }
3219
3220 void MainWindow::on_actionGoGoToPacket_triggered() {
3221     if (packet_list_->model()->rowCount() < 1) {
3222         return;
3223     }
3224     previous_focus_ = wsApp->focusWidget();
3225     connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
3226
3227     showAccordionFrame(main_ui_->goToFrame, true);
3228     if (main_ui_->goToFrame->isVisible()) {
3229         main_ui_->goToLineEdit->clear();
3230         main_ui_->goToLineEdit->setFocus();
3231     }
3232 }
3233
3234 void MainWindow::on_actionGoGoToLinkedPacket_triggered()
3235 {
3236     QAction *gta = qobject_cast<QAction*>(sender());
3237     if (!gta) return;
3238
3239     bool ok = false;
3240     int packet_num = gta->data().toInt(&ok);
3241     if (!ok) return;
3242
3243     packet_list_->goToPacket(packet_num);
3244 }
3245
3246 void MainWindow::on_actionGoAutoScroll_toggled(bool checked)
3247 {
3248     packet_list_->setAutoScroll(checked);
3249 }
3250
3251 void MainWindow::resetPreviousFocus() {
3252     previous_focus_ = NULL;
3253 }
3254
3255 void MainWindow::on_goToCancel_clicked()
3256 {
3257     main_ui_->goToFrame->animatedHide();
3258     if (previous_focus_) {
3259         disconnect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
3260         previous_focus_->setFocus();
3261         resetPreviousFocus();
3262     }
3263 }
3264
3265 void MainWindow::on_goToGo_clicked()
3266 {
3267     gotoFrame(main_ui_->goToLineEdit->text().toInt());
3268
3269     on_goToCancel_clicked();
3270 }
3271
3272 void MainWindow::on_goToLineEdit_returnPressed()
3273 {
3274     on_goToGo_clicked();
3275 }
3276
3277 void MainWindow::on_actionCaptureStart_triggered()
3278 {
3279 //#ifdef HAVE_AIRPCAP
3280 //  airpcap_if_active = airpcap_if_selected;
3281 //  if (airpcap_if_active)
3282 //    airpcap_set_toolbar_start_capture(airpcap_if_active);
3283 //#endif
3284
3285 //  if (cap_open_w) {
3286 //    /*
3287 //     * There's an options dialog; get the values from it and close it.
3288 //     */
3289 //    gboolean success;
3290
3291 //    /* Determine if "capture start" while building of the "capture options" window */
3292 //    /*  is in progress. If so, ignore the "capture start.                          */
3293 //    /* XXX: Would it be better/cleaner for the "capture options" window code to    */
3294 //    /*      disable the capture start button temporarily ?                         */
3295 //    if (cap_open_complete == FALSE) {
3296 //      return;  /* Building options window: ignore "capture start" */
3297 //    }
3298 //    success = capture_dlg_prep(cap_open_w);
3299 //    window_destroy(GTK_WIDGET(cap_open_w));
3300 //    if (!success)
3301 //      return;   /* error in options dialog */
3302 //  }
3303
3304 #ifdef HAVE_LIBPCAP
3305     if (global_capture_opts.num_selected == 0) {
3306         QString err_msg = tr("No Interface Selected");
3307         main_ui_->statusBar->pushTemporaryStatus(err_msg);
3308         main_ui_->actionCaptureStart->setChecked(false);
3309         return;
3310     }
3311
3312     /* XXX - will closing this remove a temporary file? */
3313     QString before_what(tr(" before starting a new capture"));
3314     if (testCaptureFileClose(FALSE, before_what)) {
3315         startCapture();
3316     } else {
3317         // simply clicking the button sets it to 'checked' even though we've
3318         // decided to do nothing, so undo that
3319         main_ui_->actionCaptureStart->setChecked(false);
3320     }
3321 #endif // HAVE_LIBPCAP
3322 }
3323
3324 void MainWindow::on_actionCaptureStop_triggered()
3325 {
3326     stopCapture();
3327 }
3328
3329 void MainWindow::on_actionCaptureRestart_triggered()
3330 {
3331 /* TODO: GTK use only this: capture_restart(&cap_session_); */
3332     captureStop();
3333     startCapture();
3334 }
3335
3336 static FilterDialog *capture_filter_dlg_ = NULL;
3337 void MainWindow::on_actionCaptureCaptureFilters_triggered()
3338 {
3339     if (!capture_filter_dlg_) {
3340         capture_filter_dlg_ = new FilterDialog(this, FilterDialog::CaptureFilter);
3341     }
3342     capture_filter_dlg_->show();
3343     capture_filter_dlg_->raise();
3344     capture_filter_dlg_->activateWindow();
3345 }
3346
3347 void MainWindow::on_actionStatisticsCaptureFileProperties_triggered()
3348 {
3349     CaptureFilePropertiesDialog *capture_file_properties_dialog = new CaptureFilePropertiesDialog(*this, capture_file_);
3350     connect(capture_file_properties_dialog, SIGNAL(captureCommentChanged()),
3351             this, SLOT(updateForUnsavedChanges()));
3352     capture_file_properties_dialog->show();
3353 }
3354
3355 void MainWindow::on_actionStatisticsResolvedAddresses_triggered()
3356 {
3357     ResolvedAddressesDialog *resolved_addresses_dialog = new ResolvedAddressesDialog(this, &capture_file_);
3358     resolved_addresses_dialog->show();
3359 }
3360
3361 void MainWindow::on_actionStatisticsProtocolHierarchy_triggered()
3362 {
3363     ProtocolHierarchyDialog *phd = new ProtocolHierarchyDialog(*this, capture_file_);
3364     connect(phd, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
3365             this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
3366     phd->show();
3367 }
3368
3369 #ifdef HAVE_LIBPCAP
3370 void MainWindow::on_actionCaptureOptions_triggered()
3371 {
3372     connect(&capture_interfaces_dialog_, SIGNAL(setFilterValid(bool)), this, SLOT(startInterfaceCapture(bool)));
3373     capture_interfaces_dialog_.SetTab(0);
3374     capture_interfaces_dialog_.updateInterfaces();
3375
3376     if (capture_interfaces_dialog_.isMinimized() == true)
3377     {
3378         capture_interfaces_dialog_.showNormal();
3379     }
3380     else
3381     {
3382         capture_interfaces_dialog_.show();
3383     }
3384
3385     capture_interfaces_dialog_.raise();
3386     capture_interfaces_dialog_.activateWindow();
3387 }
3388
3389 void MainWindow::on_actionCaptureRefreshInterfaces_triggered()
3390 {
3391     wsApp->refreshLocalInterfaces();
3392 }
3393 #endif
3394
3395 void MainWindow::externalMenuItem_triggered()
3396 {
3397     QAction * triggerAction = NULL;
3398     QVariant v;
3399     ext_menubar_t * entry = NULL;
3400
3401     if ( QObject::sender() != NULL)
3402     {
3403         triggerAction = (QAction *)QObject::sender();
3404         v = triggerAction->data();
3405
3406         if ( v.canConvert<void *>())
3407         {
3408             entry = (ext_menubar_t *)v.value<void *>();
3409
3410             if ( entry->type == EXT_MENUBAR_ITEM )
3411             {
3412                 entry->callback(EXT_MENUBAR_QT_GUI, (gpointer) ((void *)main_ui_), entry->user_data);
3413             }
3414             else
3415             {
3416                 QDesktopServices::openUrl(QUrl(QString((gchar *)entry->user_data)));
3417             }
3418         }
3419     }
3420 }
3421
3422 void MainWindow::gotoFrame(int packet_num)
3423 {
3424     if ( packet_num > 0 )
3425     {
3426         packet_list_->goToPacket(packet_num);
3427     }
3428 }
3429
3430 #ifdef HAVE_EXTCAP
3431 void MainWindow::extcap_options_finished(int result)
3432 {
3433     if ( result == QDialog::Accepted )
3434     {
3435         startCapture();
3436     }
3437     this->main_welcome_->getInterfaceTree()->interfaceListChanged();
3438 }
3439
3440 void MainWindow::showExtcapOptionsDialog(QString &device_name)
3441 {
3442     ExtcapOptionsDialog * extcap_options_dialog = ExtcapOptionsDialog::createForDevice(device_name, this);
3443     /* The dialog returns null, if the given device name is not a valid extcap device */
3444     if ( extcap_options_dialog != NULL )
3445     {
3446         connect(extcap_options_dialog, SIGNAL(finished(int)),
3447                 this, SLOT(extcap_options_finished(int)));
3448         extcap_options_dialog->show();
3449     }
3450 }
3451 #endif
3452
3453 // Q_DECLARE_METATYPE(field_info *) called in proto_tree.h
3454
3455 void MainWindow::on_actionContextCopyBytesHexTextDump_triggered()
3456 {
3457     QAction *ca = qobject_cast<QAction*>(sender());
3458     if (!ca) return;
3459
3460     field_info *fi = ca->data().value<field_info *>();
3461
3462     byte_view_tab_->copyData(ByteViewTab::copyDataHexTextDump, fi);
3463 }
3464
3465 void MainWindow::on_actionContextCopyBytesHexDump_triggered()
3466 {
3467     QAction *ca = qobject_cast<QAction*>(sender());
3468     if (!ca) return;
3469
3470     field_info *fi = ca->data().value<field_info *>();
3471
3472     byte_view_tab_->copyData(ByteViewTab::copyDataHexDump, fi);
3473 }
3474
3475 void MainWindow::on_actionContextCopyBytesPrintableText_triggered()
3476 {
3477     QAction *ca = qobject_cast<QAction*>(sender());
3478     if (!ca) return;
3479
3480     field_info *fi = ca->data().value<field_info *>();
3481
3482     byte_view_tab_->copyData(ByteViewTab::copyDataPrintableText, fi);
3483 }
3484
3485 void MainWindow::on_actionContextCopyBytesHexStream_triggered()
3486 {
3487     QAction *ca = qobject_cast<QAction*>(sender());
3488     if (!ca) return;
3489
3490     field_info *fi = ca->data().value<field_info *>();
3491
3492     byte_view_tab_->copyData(ByteViewTab::copyDataHexStream, fi);
3493 }
3494
3495 void MainWindow::on_actionContextCopyBytesBinary_triggered()
3496 {
3497     QAction *ca = qobject_cast<QAction*>(sender());
3498     if (!ca) return;
3499
3500     field_info *fi = ca->data().value<field_info *>();
3501
3502     byte_view_tab_->copyData(ByteViewTab::copyDataBinary, fi);
3503 }
3504
3505 void MainWindow::on_actionContextWikiProtocolPage_triggered()
3506 {
3507     QAction *wa = qobject_cast<QAction*>(sender());
3508     if (!wa) return;
3509
3510     bool ok = false;
3511     int field_id = wa->data().toInt(&ok);
3512     if (!ok) return;
3513
3514     const QString proto_abbrev = proto_registrar_get_abbrev(field_id);
3515
3516     int ret = QMessageBox::question(this, wsApp->windowTitleString(tr("Wiki Page for %1").arg(proto_abbrev)),
3517                                    tr("<p>The Wireshark Wiki is maintained by the community.</p>"
3518                                       "<p>The page you are about to load might be wonderful, "
3519                                       "incomplete, wrong, or nonexistent.</p>"
3520                                       "<p>Proceed to the wiki?</p>"),
3521                                    QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
3522
3523     if (ret != QMessageBox::Yes) return;
3524
3525     QUrl wiki_url = QString("https://wiki.wireshark.org/Protocols/%1").arg(proto_abbrev);
3526     QDesktopServices::openUrl(wiki_url);
3527 }
3528
3529 void MainWindow::on_actionContextFilterFieldReference_triggered()
3530 {
3531     QAction *wa = qobject_cast<QAction*>(sender());
3532     if (!wa) return;
3533
3534     bool ok = false;
3535     int field_id = wa->data().toInt(&ok);
3536     if (!ok) return;
3537
3538     const QString proto_abbrev = proto_registrar_get_abbrev(field_id);
3539
3540     QUrl dfref_url = QString("https://www.wireshark.org/docs/dfref/%1/%2")
3541             .arg(proto_abbrev[0])
3542             .arg(proto_abbrev);
3543     QDesktopServices::openUrl(dfref_url);
3544 }
3545
3546 #ifdef _MSC_VER
3547 #pragma warning(pop)
3548 #endif
3549
3550 /*
3551  * Editor modelines
3552  *
3553  * Local Variables:
3554  * c-basic-offset: 4
3555  * tab-width: 8
3556  * indent-tabs-mode: nil
3557  * End:
3558  *
3559  * ex: set shiftwidth=4 tabstop=8 expandtab:
3560  * :indentSize=4:tabSize=8:noTabs=true:
3561  */