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