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