1 /* main_window_slots.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
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.
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.
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.
24 // Qt 5.5.0 + Visual C++ 2013
27 #pragma warning(disable:4996)
30 #include "main_window.h"
31 #include <ui_main_window.h>
38 #include "ui/capture.h"
41 #include "color_filters.h"
43 #include "wsutil/file_util.h"
44 #include "wsutil/filesystem.h"
45 #include <wsutil/str_util.h>
47 #include "epan/addr_resolv.h"
48 #include "epan/dissector_filters.h"
49 #include "epan/column.h"
50 #include "epan/dfilter/dfilter-macro.h"
51 #include "epan/epan_dissect.h"
52 #include "epan/filter_expressions.h"
53 #include "epan/prefs.h"
55 #include "epan/value_string.h"
58 #include <epan/wslua/init_wslua.h>
61 #include "ui/alert_box.h"
63 #include "ui/capture_ui_utils.h"
66 #include "ui/capture_globals.h"
67 #include "ui/help_url.h"
68 #include "ui/main_statusbar.h"
69 #include "ui/preference_utils.h"
70 #include "ui/recent.h"
71 #include "ui/recent_utils.h"
72 #include "ui/ssl_key_export.h"
73 #include "ui/ui_util.h"
74 #include "ui/qt/simple_dialog.h"
76 #ifdef HAVE_SOFTWARE_UPDATE
77 #include "ui/software_update.h"
80 #include "about_dialog.h"
81 #include "bluetooth_att_server_attributes_dialog.h"
82 #include "bluetooth_devices_dialog.h"
83 #include "bluetooth_hci_summary_dialog.h"
84 #include "capture_file_dialog.h"
85 #include "capture_file_properties_dialog.h"
86 #include "color_utils.h"
87 #include "coloring_rules_dialog.h"
88 #include "conversation_dialog.h"
89 #include "conversation_hash_tables_dialog.h"
90 #include "enabled_protocols_dialog.h"
91 #include "decode_as_dialog.h"
92 #include "display_filter_edit.h"
93 #include "display_filter_expression_dialog.h"
94 #include "dissector_tables_dialog.h"
95 #include "endpoint_dialog.h"
96 #include "expert_info_dialog.h"
97 #include "export_object_dialog.h"
98 #include "export_pdu_dialog.h"
100 #include "extcap_options_dialog.h"
102 #include "filter_action.h"
103 #include "filter_dialog.h"
104 #include "funnel_statistics.h"
105 #include "gsm_map_summary_dialog.h"
106 #include "iax2_analysis_dialog.h"
107 #include "io_graph_dialog.h"
108 #include "lbm_stream_dialog.h"
109 #include "lbm_uimflow_dialog.h"
110 #include "lbm_lbtrm_transport_dialog.h"
111 #include "lbm_lbtru_transport_dialog.h"
112 #include "lte_mac_statistics_dialog.h"
113 #include "lte_rlc_statistics_dialog.h"
114 #include "lte_rlc_graph_dialog.h"
115 #include "mtp3_summary_dialog.h"
116 #include "multicast_statistics_dialog.h"
117 #include "packet_comment_dialog.h"
118 #include "packet_dialog.h"
119 #include "packet_list.h"
120 #include "preferences_dialog.h"
121 #include "print_dialog.h"
122 #include "profile_dialog.h"
123 #include "protocol_hierarchy_dialog.h"
124 #include "qt_ui_utils.h"
125 #include "resolved_addresses_dialog.h"
126 #include "rpc_service_response_time_dialog.h"
127 #include "rtp_stream_dialog.h"
128 #include "rtp_analysis_dialog.h"
129 #include "sctp_all_assocs_dialog.h"
130 #include "sctp_assoc_analyse_dialog.h"
131 #include "sctp_graph_dialog.h"
132 #include "sequence_dialog.h"
133 #include "stats_tree_dialog.h"
134 #include "stock_icon.h"
135 #include "supported_protocols_dialog.h"
136 #include "tap_parameter_dialog.h"
137 #include "tcp_stream_dialog.h"
138 #include "time_shift_dialog.h"
139 #include "uat_dialog.h"
140 #include "voip_calls_dialog.h"
141 #include "wireshark_application.h"
142 #include "wlan_statistics_dialog.h"
144 #include <QClipboard>
146 #include <QMessageBox>
147 #include <QMetaObject>
149 #include <QDesktopServices>
157 static const char *dfe_property_ = "display filter expression"; //TODO : Fix Translate
159 // We're too lazy to sublcass QAction.
160 static const char *color_number_property_ = "color number";
162 bool MainWindow::openCaptureFile(QString cf_path, QString read_filter, unsigned int type)
164 QString file_name = "";
165 dfilter_t *rfcode = NULL;
170 // was a file name given as function parameter?
171 name_param = !cf_path.isEmpty();
175 if (cf_path.isEmpty()) {
176 CaptureFileDialog open_dlg(this, capture_file_.capFile(), read_filter);
178 switch (prefs.gui_fileopen_style) {
180 case FO_STYLE_LAST_OPENED:
181 /* The user has specified that we should start out in the last directory
182 we looked in. If we've already opened a file, use its containing
183 directory, if we could determine it, as the directory, otherwise
184 use the "last opened" directory saved in the preferences file if
186 /* This is now the default behaviour in file_selection_new() */
189 case FO_STYLE_SPECIFIED:
190 /* The user has specified that we should always start out in a
191 specified directory; if they've specified that directory,
192 start out by showing the files in that dir. */
193 if (prefs.gui_fileopen_dir[0] != '\0')
194 open_dlg.setDirectory(prefs.gui_fileopen_dir);
198 if (open_dlg.open(file_name, type)) {
205 if (!testCaptureFileClose(false)) {
209 if (dfilter_compile(read_filter.toUtf8().constData(), &rfcode, &err_msg)) {
210 cf_set_rfcode(CaptureFile::globalCapFile(), rfcode);
212 /* Not valid. Tell the user, and go back and run the file
213 selection box again once they dismiss the alert. */
214 //bad_dfilter_alert_box(top_level, read_filter->str);
215 QMessageBox::warning(this, tr("Invalid Display Filter"),
216 QString("The filter expression ") +
218 QString(" isn't a valid display filter. (") +
219 err_msg + QString(")."),
223 // go back to the selection dialogue only if the file
224 // was selected from this dialogue
230 /* Try to open the capture file. This closes the current file if it succeeds. */
231 CaptureFile::globalCapFile()->window = this;
232 if (cf_open(CaptureFile::globalCapFile(), cf_path.toUtf8().constData(), type, FALSE, &err) != CF_OK) {
233 /* We couldn't open it; don't dismiss the open dialog box,
234 just leave it around so that the user can, after they
235 dismiss the alert box popped up for the open error,
237 CaptureFile::globalCapFile()->window = NULL;
239 dfilter_free(rfcode);
244 switch (cf_read(CaptureFile::globalCapFile(), FALSE)) {
248 /* Just because we got an error, that doesn't mean we were unable
249 to read any of the file; we handle what we could get from the
253 case CF_READ_ABORTED:
254 /* The user bailed out of re-reading the capture file; the
255 capture file has been closed - just free the capture file name
256 string and return (without changing the last containing
258 capture_file_.setCapFile(NULL);
263 // get_dirname overwrites its path. Hopefully this isn't a problem.
264 wsApp->setLastOpenDir(get_dirname(cf_path.toUtf8().data()));
266 main_ui_->statusBar->showExpert();
271 void MainWindow::filterPackets(QString new_filter, bool force)
273 cf_status_t cf_status;
275 cf_status = cf_filter_packets(CaptureFile::globalCapFile(), new_filter.toUtf8().data(), force);
277 if (cf_status == CF_OK) {
278 emit displayFilterSuccess(true);
279 if (new_filter.length() > 0) {
280 int index = df_combo_box_->findText(new_filter);
282 df_combo_box_->insertItem(0, new_filter);
283 df_combo_box_->setCurrentIndex(0);
285 df_combo_box_->setCurrentIndex(index);
288 df_combo_box_->lineEdit()->clear();
291 emit displayFilterSuccess(false);
295 // A new layout should be applied when it differs from the old layout AND
296 // at the following times:
298 // - When the preferences change
299 // - When the profile changes
300 void MainWindow::layoutPanes()
302 QVector<unsigned> new_layout = QVector<unsigned>() << prefs.gui_layout_type
303 << prefs.gui_layout_content_1
304 << prefs.gui_layout_content_2
305 << prefs.gui_layout_content_3;
306 if (cur_layout_ == new_layout) return;
308 QSplitter *parents[3];
309 int current_row = capture_file_.currentRow();
311 // Reparent all widgets and add them back in the proper order below.
312 // This hides each widget as well.
313 packet_list_->freeze(); // Clears tree and byte view tabs.
314 packet_list_->setParent(main_ui_->mainStack);
315 proto_tree_->setParent(main_ui_->mainStack);
316 byte_view_tab_->setParent(main_ui_->mainStack);
317 empty_pane_.setParent(main_ui_->mainStack);
318 extra_split_.setParent(main_ui_->mainStack);
320 // XXX We should try to preserve geometries if we can, e.g. by
321 // checking to see if the layout type is the same.
322 switch(prefs.gui_layout_type) {
325 extra_split_.setOrientation(Qt::Horizontal);
328 master_split_.setOrientation(Qt::Vertical);
333 extra_split_.setOrientation(Qt::Vertical);
336 master_split_.setOrientation(Qt::Horizontal);
340 g_assert_not_reached();
343 switch(prefs.gui_layout_type) {
346 parents[0] = &master_split_;
347 parents[1] = &master_split_;
348 parents[2] = &master_split_;
352 parents[0] = &master_split_;
353 parents[1] = &extra_split_;
354 parents[2] = &extra_split_;
358 parents[0] = &extra_split_;
359 parents[1] = &extra_split_;
360 parents[2] = &master_split_;
363 g_assert_not_reached();
366 if (parents[0] == &extra_split_) {
367 master_split_.addWidget(&extra_split_);
370 parents[0]->addWidget(getLayoutWidget(prefs.gui_layout_content_1));
372 if (parents[2] == &extra_split_) {
373 master_split_.addWidget(&extra_split_);
376 parents[1]->addWidget(getLayoutWidget(prefs.gui_layout_content_2));
377 parents[2]->addWidget(getLayoutWidget(prefs.gui_layout_content_3));
379 const QList<QWidget *> ms_children = master_split_.findChildren<QWidget *>();
381 extra_split_.setVisible(ms_children.contains(&extra_split_));
382 packet_list_->setVisible(ms_children.contains(packet_list_) && recent.packet_list_show);
383 proto_tree_->setVisible(ms_children.contains(proto_tree_) && recent.tree_view_show);
384 byte_view_tab_->setVisible(ms_children.contains(byte_view_tab_) && recent.byte_view_show);
386 packet_list_->thaw();
387 cf_select_packet(capture_file_.capFile(), current_row); // XXX Doesn't work for row 0?
388 cur_layout_ = new_layout;
391 // The recent layout geometry should be applied after the layout has been
392 // applied AND at the following times:
394 // - When the profile changes
395 void MainWindow::applyRecentPaneGeometry()
397 // XXX This shrinks slightly each time the application is run. For some
398 // reason the master_split_ geometry is two pixels shorter when
399 // saveWindowGeometry is invoked.
401 // This is also an awful lot of trouble to go through to reuse the GTK+
402 // pane settings. We might want to add gui.geometry_main_master_sizes
403 // and gui.geometry_main_extra_sizes and save QSplitter::saveState in
406 // Force a geometry recalculation
407 QWidget *cur_w = main_ui_->mainStack->currentWidget();
408 main_ui_->mainStack->setCurrentWidget(&master_split_);
409 QRect geom = master_split_.geometry();
410 QList<int> master_sizes = master_split_.sizes();
411 QList<int> extra_sizes = extra_split_.sizes();
412 main_ui_->mainStack->setCurrentWidget(cur_w);
414 int master_last_size = master_split_.orientation() == Qt::Vertical ? geom.height() : geom.width();
415 int extra_last_size = extra_split_.orientation() == Qt::Vertical ? geom.height() : geom.width();
417 if (recent.gui_geometry_main_upper_pane > 0) {
418 master_sizes[0] = recent.gui_geometry_main_upper_pane + 1; // Add back mystery pixel
419 master_last_size -= recent.gui_geometry_main_upper_pane + master_split_.handleWidth();
422 if (recent.gui_geometry_main_lower_pane > 0) {
423 if (master_sizes.length() > 2) {
424 master_sizes[1] = recent.gui_geometry_main_lower_pane + 1; // Add back mystery pixel
425 master_last_size -= recent.gui_geometry_main_lower_pane + master_split_.handleWidth();
426 } else if (extra_sizes.length() > 0) {
427 extra_sizes[0] = recent.gui_geometry_main_lower_pane; // No mystery pixel
428 extra_last_size -= recent.gui_geometry_main_lower_pane + extra_split_.handleWidth();
429 extra_sizes.last() = extra_last_size;
433 master_sizes.last() = master_last_size;
435 master_split_.setSizes(master_sizes);
436 extra_split_.setSizes(extra_sizes);
439 void MainWindow::layoutToolbars()
441 Qt::ToolButtonStyle tbstyle = Qt::ToolButtonIconOnly;
442 switch (prefs.gui_toolbar_main_style) {
444 tbstyle = Qt::ToolButtonTextOnly;
447 tbstyle = Qt::ToolButtonTextUnderIcon;
451 main_ui_->mainToolBar->setToolButtonStyle(tbstyle);
454 void MainWindow::updatePreferenceActions()
456 main_ui_->actionViewNameResolutionPhysical->setChecked(gbl_resolv_flags.mac_name);
457 main_ui_->actionViewNameResolutionNetwork->setChecked(gbl_resolv_flags.network_name);
458 main_ui_->actionViewNameResolutionTransport->setChecked(gbl_resolv_flags.transport_name);
460 // Should this be a "recent" setting?
461 main_ui_->actionGoAutoScroll->setChecked(prefs.capture_auto_scroll);
464 void MainWindow::filterAction(QString &action_filter, FilterAction::Action action, FilterAction::ActionType type)
466 QString cur_filter, new_filter;
468 if (!df_combo_box_) return;
469 cur_filter = df_combo_box_->lineEdit()->text();
472 case FilterAction::ActionTypePlain:
473 new_filter = action_filter;
475 case FilterAction::ActionTypeAnd:
476 if (cur_filter.length()) {
477 new_filter = "(" + cur_filter + ") && (" + action_filter + ")";
479 new_filter = action_filter;
482 case FilterAction::ActionTypeOr:
483 if (cur_filter.length()) {
484 new_filter = "(" + cur_filter + ") || (" + action_filter + ")";
486 new_filter = action_filter;
489 case FilterAction::ActionTypeNot:
490 new_filter = "!(" + action_filter + ")";
492 case FilterAction::ActionTypeAndNot:
493 if (cur_filter.length()) {
494 new_filter = "(" + cur_filter + ") && !(" + action_filter + ")";
496 new_filter = "!(" + action_filter + ")";
499 case FilterAction::ActionTypeOrNot:
500 if (cur_filter.length()) {
501 new_filter = "(" + cur_filter + ") || !(" + action_filter + ")";
503 new_filter = "!(" + action_filter + ")";
507 g_assert_not_reached();
512 case FilterAction::ActionApply:
513 df_combo_box_->lineEdit()->setText(new_filter);
514 df_combo_box_->applyDisplayFilter();
516 case FilterAction::ActionPrepare:
517 df_combo_box_->lineEdit()->setText(new_filter);
518 df_combo_box_->lineEdit()->setFocus();
520 case FilterAction::ActionWebLookup:
522 QString url = QString("https://www.google.com/search?q=") + new_filter;
523 QDesktopServices::openUrl(QUrl(url));
526 case FilterAction::ActionCopy:
527 wsApp->clipboard()->setText(new_filter);
530 qDebug() << "FIX FilterAction::Action" << action << "not implemented";
537 void MainWindow::captureCapturePrepared(capture_session *) {
539 setTitlebarForCaptureInProgress();
541 setWindowIcon(wsApp->captureIcon());
543 /* Disable menu items that make no sense if you're currently running
545 setForCaptureInProgress(true);
546 // set_capture_if_dialog_for_capture_in_progress(TRUE);
548 // /* Don't set up main window for a capture file. */
549 // main_set_for_capture_file(FALSE);
550 main_ui_->mainStack->setCurrentWidget(&master_split_);
551 #endif // HAVE_LIBPCAP
554 void MainWindow::captureCaptureUpdateStarted(capture_session *) {
557 /* We've done this in "prepared" above, but it will be cleared while
558 switching to the next multiple file. */
559 setTitlebarForCaptureInProgress();
561 setForCaptureInProgress(true);
563 setForCapturedPackets(true);
564 #endif // HAVE_LIBPCAP
566 void MainWindow::captureCaptureUpdateFinished(capture_session *) {
569 /* The capture isn't stopping any more - it's stopped. */
570 capture_stopping_ = false;
572 /* Update the main window as appropriate */
573 updateForUnsavedChanges();
575 /* Enable menu items that make sense if you're not currently running
577 setForCaptureInProgress(false);
579 setWindowIcon(wsApp->normalIcon());
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.
586 #endif // HAVE_LIBPCAP
588 void MainWindow::captureCaptureFixedStarted(capture_session *) {
590 #endif // HAVE_LIBPCAP
592 void MainWindow::captureCaptureFixedFinished(capture_session *) {
595 /* The capture isn't stopping any more - it's stopped. */
596 capture_stopping_ = false;
598 /* Enable menu items that make sense if you're not currently running
600 setForCaptureInProgress(false);
602 setWindowIcon(wsApp->normalIcon());
604 if (global_capture_opts.quit_after_cap) {
605 // Command line asked us to quit after capturing.
606 // Don't pop up a dialog to ask for unsaved files etc.
609 #endif // HAVE_LIBPCAP
611 void MainWindow::captureCaptureStopping(capture_session *) {
614 capture_stopping_ = true;
615 setMenusForCaptureStopping();
616 #endif // HAVE_LIBPCAP
618 void MainWindow::captureCaptureFailed(capture_session *) {
620 /* Capture isn't stopping any more. */
621 capture_stopping_ = false;
623 setForCaptureInProgress(false);
624 main_ui_->mainStack->setCurrentWidget(main_welcome_);
626 setWindowIcon(wsApp->normalIcon());
628 if (global_capture_opts.quit_after_cap) {
629 // Command line asked us to quit after capturing.
630 // Don't pop up a dialog to ask for unsaved files etc.
633 #endif // HAVE_LIBPCAP
637 // Callbacks from cfile.c and file.c via CaptureFile::captureFileCallback
639 void MainWindow::captureFileOpened() {
640 if (capture_file_.window() != this) return;
642 file_set_dialog_.fileOpened(capture_file_.capFile());
643 setMenusForFileSet(true);
644 emit setCaptureFile(capture_file_.capFile());
647 void MainWindow::captureFileReadStarted(const QString &action) {
648 // tap_param_dlg_update();
650 /* Set up main window for a capture file. */
651 // main_set_for_capture_file(TRUE);
653 main_ui_->statusBar->popFileStatus();
654 QString msg = QString(tr("%1: %2")).arg(action).arg(capture_file_.fileName());
655 QString msgtip = QString();
656 main_ui_->statusBar->pushFileStatus(msg, msgtip);
657 main_ui_->mainStack->setCurrentWidget(&master_split_);
658 WiresharkApplication::processEvents();
661 void MainWindow::captureFileReadFinished() {
664 if (!capture_file_.capFile()->is_tempfile && capture_file_.capFile()->filename) {
665 /* Add this filename to the list of recent files in the "Recent Files" submenu */
666 add_menu_recent_capture_file(capture_file_.capFile()->filename);
668 /* Remember folder for next Open dialog and save it in recent */
669 dir_path = get_dirname(g_strdup(capture_file_.capFile()->filename));
670 wsApp->setLastOpenDir(dir_path);
674 /* Update the appropriate parts of the main window. */
675 updateForUnsavedChanges();
677 /* Enable menu items that make sense if you have some captured packets. */
678 setForCapturedPackets(true);
680 main_ui_->statusBar->setFileName(capture_file_);
682 packet_list_->captureFileReadFinished();
684 emit setDissectedCaptureFile(capture_file_.capFile());
687 // Our event loop becomes nested whenever we call update_progress_dlg, which
688 // includes several places in file.c. The GTK+ UI stays out of trouble by
689 // showing a modal progress dialog. We attempt to do the equivalent below by
690 // disabling parts of the main window. At a minumum the ProgressFrame in the
691 // main status bar must remain accessible.
693 // We might want to do this any time the main status bar progress frame is
695 void MainWindow::captureFileRetapStarted()
697 // XXX Push a status message?
698 main_ui_->actionFileClose->setEnabled(false);
699 main_ui_->actionViewReload->setEnabled(false);
700 main_ui_->centralWidget->setEnabled(false);
703 void MainWindow::captureFileRetapFinished()
705 main_ui_->actionFileClose->setEnabled(true);
706 main_ui_->actionViewReload->setEnabled(true);
707 main_ui_->centralWidget->setEnabled(true);
710 void MainWindow::captureFileClosing() {
711 setMenusForCaptureFile(true);
712 setForCapturedPackets(false);
713 setMenusForSelectedPacket();
714 setForCaptureInProgress(false);
716 // Reset expert information indicator
717 main_ui_->statusBar->captureFileClosing();
718 main_ui_->searchFrame->animatedHide();
719 // gtk_widget_show(expert_info_none);
720 emit setCaptureFile(NULL);
721 emit setDissectedCaptureFile(NULL);
724 void MainWindow::captureFileClosed() {
725 packets_bar_update();
727 file_set_dialog_.fileClosed();
728 setMenusForFileSet(false);
729 setWindowModified(false);
731 // Reset expert information indicator
732 main_ui_->statusBar->captureFileClosing();
734 main_ui_->statusBar->popFileStatus();
736 setTitlebarForSelectedTreeRow();
737 setMenusForSelectedTreeRow();
739 if (!global_capture_opts.multi_files_on)
740 main_ui_->mainStack->setCurrentWidget(main_welcome_);
743 void MainWindow::captureFileSaveStarted(const QString &file_path)
745 QFileInfo file_info(file_path);
746 main_ui_->statusBar->popFileStatus();
747 main_ui_->statusBar->pushFileStatus(tr("Saving %1" UTF8_HORIZONTAL_ELLIPSIS).arg(file_info.baseName()));
750 void MainWindow::filterExpressionsChanged()
752 // Recreate filter buttons
753 foreach (QAction *act, main_ui_->displayFilterToolBar->actions()) {
754 // Permanent actions shouldn't have data
755 if (act->property(dfe_property_).isValid()) {
756 main_ui_->displayFilterToolBar->removeAction(act);
761 // XXX Add a context menu for removing and changing buttons.
762 for (struct filter_expression *fe = *pfilter_expression_head; fe != NULL; fe = fe->next) {
763 if (!fe->enabled) continue;
764 QAction *dfb_action = new QAction(fe->label, main_ui_->displayFilterToolBar);
765 dfb_action->setToolTip(fe->expression);
766 dfb_action->setData(fe->expression);
767 dfb_action->setProperty(dfe_property_, true);
768 main_ui_->displayFilterToolBar->addAction(dfb_action);
769 connect(dfb_action, SIGNAL(triggered()), this, SLOT(displayFilterButtonClicked()));
777 // ui/gtk/capture_dlg.c:start_capture_confirmed
779 void MainWindow::startCapture() {
781 interface_options interface_opts;
784 /* did the user ever select a capture interface before? */
785 if(global_capture_opts.num_selected == 0) {
786 QString msg = QString(tr("No interface selected"));
787 main_ui_->statusBar->pushTemporaryStatus(msg);
788 main_ui_->actionCaptureStart->setChecked(false);
792 main_ui_->mainStack->setCurrentWidget(&master_split_);
794 // Ideally we should have disabled the start capture
795 // toolbar buttons and menu items. This may not be the
796 // case, e.g. with QtMacExtras.
797 if(!capture_filter_valid_) {
798 QString msg = QString(tr("Invalid capture filter"));
799 main_ui_->statusBar->pushTemporaryStatus(msg);
800 main_ui_->actionCaptureStart->setChecked(false);
804 /* XXX - we might need to init other pref data as well... */
806 /* XXX - can this ever happen? */
807 if (cap_session_.state != CAPTURE_STOPPED)
810 /* close the currently loaded capture file */
811 cf_close((capture_file *) cap_session_.cf);
813 /* Copy the selected interfaces to the set of interfaces to use for
815 collect_ifaces(&global_capture_opts);
817 CaptureFile::globalCapFile()->window = this;
818 if (capture_start(&global_capture_opts, &cap_session_, main_window_update)) {
819 capture_options *capture_opts = cap_session_.capture_opts;
820 GString *interface_names;
822 /* enable autoscroll timer as needed. */
823 packet_list_->setAutoScroll(main_ui_->actionGoAutoScroll->isChecked());
825 /* Add "interface name<live capture in progress>" on main status bar */
826 interface_names = get_iface_list_string(capture_opts, 0);
827 if (strlen (interface_names->str) > 0) {
828 g_string_append(interface_names, ":");
830 g_string_append(interface_names, " ");
832 main_ui_->statusBar->popFileStatus();
833 QString msg = QString().sprintf("%s<live capture in progress>", interface_names->str);
834 QString msgtip = QString().sprintf("to file: %s", (capture_opts->save_file) ? capture_opts->save_file : "");
835 main_ui_->statusBar->pushFileStatus(msg, msgtip);
836 g_string_free(interface_names, TRUE);
838 /* The capture succeeded, which means the capture filter syntax is
839 valid; add this capture filter to the recent capture filter list. */
840 for (i = 0; i < global_capture_opts.ifaces->len; i++) {
841 interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
842 if (interface_opts.cfilter) {
843 // cfilter_combo_add_recent(interface_opts.cfilter);
847 CaptureFile::globalCapFile()->window = NULL;
849 #endif // HAVE_LIBPCAP
852 // Copied from ui/gtk/gui_utils.c
853 void MainWindow::pipeTimeout() {
857 gboolean result, result1;
862 /* try to read data from the pipe only 5 times, to avoid blocking */
863 while(iterations < 5) {
864 /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: new iteration");*/
866 /* Oddly enough although Named pipes don't work on win9x,
867 PeekNamedPipe does !!! */
868 handle = (HANDLE) _get_osfhandle (pipe_source_);
869 result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
871 /* Get the child process exit status */
872 result1 = GetExitCodeProcess((HANDLE)*(pipe_child_process_),
875 /* If the Peek returned an error, or there are bytes to be read
876 or the childwatcher thread has terminated then call the normal
878 if (!result || avail > 0 || childstatus != STILL_ACTIVE) {
880 /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: data avail");*/
882 /* And call the real handler */
883 if (!pipe_input_cb_(pipe_source_, pipe_user_data_)) {
884 g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: input pipe closed, iterations: %u", iterations);
885 /* pipe closed, return false so that the old timer is not run again */
891 /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: no data avail");*/
892 /* No data, stop now */
901 void MainWindow::pipeActivated(int source) {
905 g_assert(source == pipe_source_);
907 pipe_notifier_->setEnabled(false);
908 if (pipe_input_cb_(pipe_source_, pipe_user_data_)) {
909 pipe_notifier_->setEnabled(true);
911 delete pipe_notifier_;
916 void MainWindow::pipeNotifierDestroyed() {
920 pipe_notifier_ = NULL;
924 void MainWindow::stopCapture() {
925 //#ifdef HAVE_AIRPCAP
926 // if (airpcap_if_active)
927 // airpcap_set_toolbar_stop_capture(airpcap_if_active);
931 capture_stop(&cap_session_);
932 #endif // HAVE_LIBPCAP
934 /* Pop the "<live capture in progress>" message off the status bar. */
935 main_ui_->statusBar->setFileName(capture_file_);
937 /* disable autoscroll timer if any. */
938 packet_list_->setAutoScroll(false);
941 // Keep focus rects from showing through the welcome screen. Primarily for
943 void MainWindow::mainStackChanged(int)
945 for (int i = 0; i < main_ui_->mainStack->count(); i++) {
946 main_ui_->mainStack->widget(i)->setEnabled(i == main_ui_->mainStack->currentIndex());
950 // XXX - Copied from ui/gtk/menus.c
953 * Add the capture filename (with an absolute path) to the "Recent Files" menu.
955 // XXX - We should probably create a RecentFile class.
956 void MainWindow::updateRecentFiles() {
958 QMenu *recentMenu = main_ui_->menuOpenRecentCaptureFile;
959 QString action_cf_name;
967 /* Iterate through the actions in menuOpenRecentCaptureFile,
968 * removing special items, a maybe duplicate entry and every item above count_max */
969 int shortcut = Qt::Key_0;
970 foreach (recent_item_status *ri, wsApp->recentItems()) {
972 ra = new QAction(recentMenu);
973 ra->setData(ri->filename);
974 // XXX - Needs get_recent_item_status or equivalent
975 ra->setEnabled(ri->accessible);
976 recentMenu->insertAction(NULL, ra);
977 action_cf_name = ra->data().toString();
978 if (shortcut <= Qt::Key_9) {
979 ra->setShortcut(Qt::META | shortcut);
982 ra->setText(action_cf_name);
983 connect(ra, SIGNAL(triggered()), this, SLOT(recentActionTriggered()));
986 if (recentMenu->actions().count() > 0) {
987 // Separator + "Clear"
988 // XXX - Do we really need this?
989 ra = new QAction(recentMenu);
990 ra->setSeparator(true);
991 recentMenu->insertAction(NULL, ra);
993 ra = new QAction(recentMenu);
994 ra->setText(tr("Clear Menu"));
995 recentMenu->insertAction(NULL, ra);
996 connect(ra, SIGNAL(triggered()), wsApp, SLOT(clearRecentItems()));
998 if (main_ui_->actionDummyNoFilesFound) {
999 recentMenu->addAction(main_ui_->actionDummyNoFilesFound);
1004 void MainWindow::recentActionTriggered() {
1005 QAction *ra = qobject_cast<QAction*>(sender());
1008 QString cfPath = ra->data().toString();
1009 openCaptureFile(cfPath);
1013 void MainWindow::setMenusForSelectedPacket()
1015 gboolean is_ip = FALSE, is_tcp = FALSE, is_udp = FALSE, is_sctp = FALSE, is_ssl = FALSE, is_rtp = FALSE, is_lte_rlc = FALSE;
1017 /* Making the menu context-sensitive allows for easier selection of the
1018 desired item and has the added benefit, with large captures, of
1019 avoiding needless looping through huge lists for marked, ignored,
1020 or time-referenced packets. */
1022 /* We have one or more items in the packet list */
1023 bool have_frames = false;
1024 /* A frame is selected */
1025 bool frame_selected = false;
1026 /* We have marked frames. (XXX - why check frame_selected?) */
1027 bool have_marked = false;
1028 /* We have a marked frame other than the current frame (i.e.,
1029 we have at least one marked frame, and either there's more
1030 than one marked frame or the current frame isn't marked). */
1031 bool another_is_marked = false;
1032 /* One or more frames are hidden by a display filter */
1033 bool have_filtered = false;
1034 /* One or more frames have been ignored */
1035 bool have_ignored = false;
1036 bool have_time_ref = false;
1037 /* We have a time reference frame other than the current frame (i.e.,
1038 we have at least one time reference frame, and either there's more
1039 than one time reference frame or the current frame isn't a
1040 time reference frame). (XXX - why check frame_selected?) */
1041 bool another_is_time_ref = false;
1042 /* We have a valid filter expression */
1043 bool have_filter_expr = false;
1045 QList<QAction *> cc_actions = QList<QAction *>()
1046 << main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
1047 << main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
1048 << main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
1049 << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
1050 << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
1052 if (capture_file_.capFile()) {
1053 frame_selected = capture_file_.capFile()->current_frame != NULL;
1054 have_frames = capture_file_.capFile()->count > 0;
1055 have_marked = frame_selected && capture_file_.capFile()->marked_count > 0;
1056 another_is_marked = have_marked &&
1057 !(capture_file_.capFile()->marked_count == 1 && capture_file_.capFile()->current_frame->flags.marked);
1058 have_filtered = capture_file_.capFile()->displayed_count > 0 && capture_file_.capFile()->displayed_count != capture_file_.capFile()->count;
1059 have_ignored = capture_file_.capFile()->ignored_count > 0;
1060 have_time_ref = capture_file_.capFile()->ref_time_count > 0;
1061 another_is_time_ref = frame_selected && have_time_ref &&
1062 !(capture_file_.capFile()->ref_time_count == 1 && capture_file_.capFile()->current_frame->flags.ref_time);
1064 if (capture_file_.capFile()->edt)
1066 proto_get_frame_protocols(capture_file_.capFile()->edt->pi.layers,
1067 &is_ip, &is_tcp, &is_udp, &is_sctp,
1068 &is_ssl, &is_rtp, &is_lte_rlc);
1072 have_filter_expr = !packet_list_->getFilterFromRowAndColumn().isEmpty();
1074 main_ui_->actionEditMarkPacket->setEnabled(frame_selected);
1075 main_ui_->actionEditMarkAllDisplayed->setEnabled(have_frames);
1076 /* Unlike un-ignore, do not allow unmark of all frames when no frames are displayed */
1077 main_ui_->actionEditUnmarkAllDisplayed->setEnabled(have_marked);
1078 main_ui_->actionEditNextMark->setEnabled(another_is_marked);
1079 main_ui_->actionEditPreviousMark->setEnabled(another_is_marked);
1081 #ifdef WANT_PACKET_EDITOR
1082 // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/EditPacket",
1084 #endif // WANT_PACKET_EDITOR
1085 main_ui_->actionEditPacketComment->setEnabled(frame_selected && wtap_dump_can_write(capture_file_.capFile()->linktypes, WTAP_COMMENT_PER_PACKET));
1087 main_ui_->actionEditIgnorePacket->setEnabled(frame_selected);
1088 main_ui_->actionEditIgnoreAllDisplayed->setEnabled(have_filtered);
1089 /* Allow un-ignore of all frames even with no frames currently displayed */
1090 main_ui_->actionEditUnignoreAllDisplayed->setEnabled(have_ignored);
1092 main_ui_->actionEditSetTimeReference->setEnabled(frame_selected);
1093 main_ui_->actionEditUnsetAllTimeReferences->setEnabled(have_time_ref);
1094 main_ui_->actionEditNextTimeReference->setEnabled(another_is_time_ref);
1095 main_ui_->actionEditPreviousTimeReference->setEnabled(another_is_time_ref);
1096 main_ui_->actionEditTimeShift->setEnabled(have_frames);
1098 main_ui_->actionGoGoToLinkedPacket->setEnabled(false);
1100 main_ui_->actionAnalyzeAAFSelected->setEnabled(have_filter_expr);
1101 main_ui_->actionAnalyzeAAFNotSelected->setEnabled(have_filter_expr);
1102 main_ui_->actionAnalyzeAAFAndSelected->setEnabled(have_filter_expr);
1103 main_ui_->actionAnalyzeAAFOrSelected->setEnabled(have_filter_expr);
1104 main_ui_->actionAnalyzeAAFAndNotSelected->setEnabled(have_filter_expr);
1105 main_ui_->actionAnalyzeAAFOrNotSelected->setEnabled(have_filter_expr);
1107 main_ui_->actionAnalyzePAFSelected->setEnabled(have_filter_expr);
1108 main_ui_->actionAnalyzePAFNotSelected->setEnabled(have_filter_expr);
1109 main_ui_->actionAnalyzePAFAndSelected->setEnabled(have_filter_expr);
1110 main_ui_->actionAnalyzePAFOrSelected->setEnabled(have_filter_expr);
1111 main_ui_->actionAnalyzePAFAndNotSelected->setEnabled(have_filter_expr);
1112 main_ui_->actionAnalyzePAFOrNotSelected->setEnabled(have_filter_expr);
1114 main_ui_->actionAnalyzeFollowTCPStream->setEnabled(is_tcp);
1115 main_ui_->actionAnalyzeFollowUDPStream->setEnabled(is_udp);
1116 main_ui_->actionAnalyzeFollowSSLStream->setEnabled(is_ssl);
1118 foreach (QAction *cc_action, cc_actions) {
1119 cc_action->setEnabled(frame_selected);
1121 main_ui_->actionViewColorizeNewConversationRule->setEnabled(frame_selected);
1123 main_ui_->actionViewColorizeResetColorization->setEnabled(tmp_color_filters_used());
1125 main_ui_->actionViewColorizeNewConversationRule->setEnabled(frame_selected);
1127 main_ui_->actionViewShowPacketInNewWindow->setEnabled(frame_selected);
1128 main_ui_->actionViewEditResolvedName->setEnabled(frame_selected && is_ip);
1130 main_ui_->menuConversationFilter->clear();
1132 packet_list_->conversationMenu()->clear();
1133 packet_list_->colorizeMenu()->clear();
1135 for (GList *conv_filter_list_entry = conv_filter_list; conv_filter_list_entry; conv_filter_list_entry = g_list_next(conv_filter_list_entry)) {
1137 conversation_filter_t* conv_filter = (conversation_filter_t *)conv_filter_list_entry->data;
1138 QAction *conv_action = main_ui_->menuConversationFilter->addAction(conv_filter->display_name);
1140 bool enable = false;
1142 if (capture_file_.capFile()->edt) {
1143 enable = conv_filter->is_filter_valid(&capture_file_.capFile()->edt->pi);
1144 filter = gchar_free_to_qstring(conv_filter->build_filter_string(&capture_file_.capFile()->edt->pi));
1146 conv_action->setEnabled(enable);
1147 conv_action->setData(filter);
1148 connect(conv_action, SIGNAL(triggered()), this, SLOT(applyConversationFilter()));
1150 // Packet list context menu items
1151 packet_list_->conversationMenu()->addAction(conv_action);
1153 QMenu *submenu = packet_list_->colorizeMenu()->addMenu(conv_action->text());
1155 foreach (QAction *cc_action, cc_actions) {
1156 QAction *colorize_action = submenu->addAction(cc_action->icon(), cc_action->text());
1157 colorize_action->setProperty(color_number_property_, i++);
1158 colorize_action->setData(filter);
1159 colorize_action->setEnabled(enable);
1160 connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1163 QAction *conv_rule_action = submenu->addAction(main_ui_->actionViewColorizeNewConversationRule->text());
1164 conv_rule_action->setData(conv_action->data());
1165 conv_rule_action->setEnabled(enable);
1166 connect(conv_rule_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1169 // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/NameResolution/ResolveName",
1170 // frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
1171 // gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns));
1172 // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ToolsMenu/FirewallACLRules",
1174 main_ui_->menuTcpStreamGraphs->setEnabled(is_tcp);
1175 main_ui_->actionSCTPAnalyseThisAssociation->setEnabled(is_sctp);
1176 main_ui_->actionSCTPShowAllAssociations->setEnabled(is_sctp);
1177 main_ui_->actionSCTPFilterThisAssociation->setEnabled(is_sctp);
1178 main_ui_->actionTelephonyRTPStreamAnalysis->setEnabled(is_rtp);
1179 main_ui_->actionTelephonyLteRlcGraph->setEnabled(is_lte_rlc);
1182 void MainWindow::setMenusForSelectedTreeRow(field_info *fi) {
1184 bool can_match_selected = false;
1185 bool is_framenum = false;
1186 bool have_field_info = false;
1187 bool have_subtree = false;
1188 bool can_open_url = false;
1189 QString field_filter;
1192 QList<QAction *> cc_actions = QList<QAction *>()
1193 << main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
1194 << main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
1195 << main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
1196 << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
1197 << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
1199 if (capture_file_.capFile()) {
1200 capture_file_.capFile()->finfo_selected = fi;
1202 if (fi && fi->tree_type != -1) {
1203 have_subtree = true;
1207 if (capture_file_.capFile() != NULL && fi != NULL) {
1208 header_field_info *hfinfo = fi->hfinfo;
1209 int linked_frame = -1;
1211 have_field_info = true;
1212 can_match_selected = proto_can_match_selected(capture_file_.capFile()->finfo_selected, capture_file_.capFile()->edt);
1213 if (hfinfo && hfinfo->type == FT_FRAMENUM) {
1215 linked_frame = fvalue_get_uinteger(&fi->value);
1218 char *tmp_field = proto_construct_match_selected_string(fi, capture_file_.capFile()->edt);
1219 field_filter = QString(tmp_field);
1220 wmem_free(NULL, tmp_field);
1222 field_id = fi->hfinfo->id;
1223 /* if the selected field isn't a protocol, get its parent */
1224 if (!proto_registrar_is_protocol(field_id)) {
1225 field_id = proto_registrar_get_parent(fi->hfinfo->id);
1228 if (field_id >= 0) {
1229 can_open_url = true;
1230 main_ui_->actionContextWikiProtocolPage->setData(field_id);
1231 main_ui_->actionContextFilterFieldReference->setData(field_id);
1233 main_ui_->actionContextWikiProtocolPage->setData(QVariant());
1234 main_ui_->actionContextFilterFieldReference->setData(QVariant());
1237 if (linked_frame > 0) {
1238 main_ui_->actionGoGoToLinkedPacket->setData(linked_frame);
1240 main_ui_->actionGoGoToLinkedPacket->setData(QVariant());
1244 // Always enable / disable the following items.
1245 main_ui_->actionFileExportPacketBytes->setEnabled(have_field_info);
1247 main_ui_->actionCopyAllVisibleItems->setEnabled(capture_file_.capFile() != NULL);
1248 main_ui_->actionCopyAllVisibleSelectedTreeItems->setEnabled(can_match_selected);
1249 main_ui_->actionEditCopyDescription->setEnabled(can_match_selected);
1250 main_ui_->actionEditCopyFieldName->setEnabled(can_match_selected);
1251 main_ui_->actionEditCopyValue->setEnabled(can_match_selected);
1252 main_ui_->actionEditCopyAsFilter->setEnabled(can_match_selected);
1254 main_ui_->actionViewExpandSubtrees->setEnabled(have_subtree);
1256 main_ui_->actionGoGoToLinkedPacket->setEnabled(is_framenum);
1258 main_ui_->actionAnalyzeCreateAColumn->setEnabled(can_match_selected);
1260 main_ui_->actionContextShowLinkedPacketInNewWindow->setEnabled(is_framenum);
1262 main_ui_->actionContextWikiProtocolPage->setEnabled(can_open_url);
1263 main_ui_->actionContextFilterFieldReference->setEnabled(can_open_url);
1266 // Only enable / disable the following items if we have focus so that we
1267 // don't clobber anything we may have set in setMenusForSelectedPacket.
1268 if (!proto_tree_ || !proto_tree_->hasFocus()) return;
1270 main_ui_->menuConversationFilter->clear();
1271 for (GList *conv_filter_list_entry = conv_filter_list; conv_filter_list_entry; conv_filter_list_entry = g_list_next(conv_filter_list_entry)) {
1272 conversation_filter_t* conv_filter = (conversation_filter_t *)conv_filter_list_entry->data;
1273 QAction *conv_action = main_ui_->menuConversationFilter->addAction(conv_filter->display_name);
1275 bool enable = false;
1277 if (capture_file_.capFile() && capture_file_.capFile()->edt) {
1278 enable = conv_filter->is_filter_valid(&capture_file_.capFile()->edt->pi);
1279 filter = conv_filter->build_filter_string(&capture_file_.capFile()->edt->pi);
1281 conv_action->setEnabled(enable);
1282 conv_action->setData(filter);
1283 connect(conv_action, SIGNAL(triggered()), this, SLOT(applyConversationFilter()));
1286 proto_tree_->colorizeMenu()->clear();
1288 foreach (QAction *cc_action, cc_actions) {
1289 QAction *colorize_action = proto_tree_->colorizeMenu()->addAction(cc_action->icon(), cc_action->text());
1290 colorize_action->setProperty(color_number_property_, i++);
1291 colorize_action->setData(field_filter);
1292 colorize_action->setEnabled(!field_filter.isEmpty());
1293 connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1296 QAction *conv_rule_action = proto_tree_->colorizeMenu()->addAction(main_ui_->actionViewColorizeNewConversationRule->text());
1297 conv_rule_action->setData(field_filter);
1298 conv_rule_action->setEnabled(!field_filter.isEmpty());
1299 connect(conv_rule_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1301 // set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ResolveName",
1302 // frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
1303 // gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns));
1306 main_ui_->actionAnalyzeAAFSelected->setEnabled(can_match_selected);
1307 main_ui_->actionAnalyzeAAFNotSelected->setEnabled(can_match_selected);
1308 main_ui_->actionAnalyzeAAFAndSelected->setEnabled(can_match_selected);
1309 main_ui_->actionAnalyzeAAFOrSelected->setEnabled(can_match_selected);
1310 main_ui_->actionAnalyzeAAFAndNotSelected->setEnabled(can_match_selected);
1311 main_ui_->actionAnalyzeAAFOrNotSelected->setEnabled(can_match_selected);
1313 main_ui_->actionAnalyzePAFSelected->setEnabled(can_match_selected);
1314 main_ui_->actionAnalyzePAFNotSelected->setEnabled(can_match_selected);
1315 main_ui_->actionAnalyzePAFAndSelected->setEnabled(can_match_selected);
1316 main_ui_->actionAnalyzePAFOrSelected->setEnabled(can_match_selected);
1317 main_ui_->actionAnalyzePAFAndNotSelected->setEnabled(can_match_selected);
1318 main_ui_->actionAnalyzePAFOrNotSelected->setEnabled(can_match_selected);
1321 void MainWindow::interfaceSelectionChanged()
1324 // XXX This doesn't disable the toolbar button when using
1326 if (global_capture_opts.num_selected > 0 && capture_filter_valid_) {
1327 main_ui_->actionCaptureStart->setEnabled(true);
1329 main_ui_->actionCaptureStart->setEnabled(false);
1331 #endif // HAVE_LIBPCAP
1334 void MainWindow::captureFilterSyntaxChanged(bool valid)
1336 capture_filter_valid_ = valid;
1337 interfaceSelectionChanged();
1340 void MainWindow::startInterfaceCapture(bool valid)
1342 capture_filter_valid_ = valid;
1346 void MainWindow::redissectPackets()
1348 if (capture_file_.capFile())
1349 cf_redissect_packets(capture_file_.capFile());
1350 main_ui_->statusBar->expertUpdate();
1352 proto_free_deregistered_fields();
1355 void MainWindow::fieldsChanged()
1357 color_filters_reload();
1358 tap_listeners_dfilter_recompile();
1360 if (!df_combo_box_->checkDisplayFilter()) {
1361 g_free(CaptureFile::globalCapFile()->dfilter);
1362 CaptureFile::globalCapFile()->dfilter = NULL;
1365 if (have_custom_cols(&CaptureFile::globalCapFile()->cinfo)) {
1366 // Recreate packet list columns according to new/changed/deleted fields
1367 packet_list_->fieldsChanged(CaptureFile::globalCapFile());
1370 emit reloadFields();
1373 void MainWindow::showAccordionFrame(AccordionFrame *show_frame, bool toggle)
1375 QList<AccordionFrame *>frame_list = QList<AccordionFrame *>()
1376 << main_ui_->goToFrame << main_ui_->searchFrame
1377 << main_ui_->addressEditorFrame << main_ui_->columnEditorFrame
1378 << main_ui_->preferenceEditorFrame;
1380 frame_list.removeAll(show_frame);
1381 foreach (AccordionFrame *af, frame_list) af->animatedHide();
1384 if (show_frame->isVisible()) {
1385 show_frame->animatedHide();
1389 show_frame->animatedShow();
1392 void MainWindow::showColumnEditor(int column)
1394 previous_focus_ = wsApp->focusWidget();
1395 connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
1396 showAccordionFrame(main_ui_->columnEditorFrame);
1397 main_ui_->columnEditorFrame->editColumn(column);
1400 void MainWindow::showPreferenceEditor()
1402 showAccordionFrame(main_ui_->preferenceEditorFrame);
1405 void MainWindow::initViewColorizeMenu()
1407 QList<QAction *> cc_actions = QList<QAction *>()
1408 << main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
1409 << main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
1410 << main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
1411 << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
1412 << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
1414 guint8 color_num = 1;
1416 foreach (QAction *cc_action, cc_actions) {
1417 cc_action->setData(color_num);
1418 connect(cc_action, SIGNAL(triggered()), this, SLOT(colorizeConversation()));
1420 const color_filter_t *colorf = color_filters_tmp_color(color_num);
1422 QColor bg = ColorUtils::fromColorT(colorf->bg_color);
1423 QColor fg = ColorUtils::fromColorT(colorf->fg_color);
1424 cc_action->setIcon(StockIcon::colorIcon(bg.rgb(), fg.rgb(), QString::number(color_num)));
1430 // Spotlight uses Cmd+Space
1431 main_ui_->actionViewColorizeResetColorization->setShortcut(QKeySequence("Meta+Space"));
1435 void MainWindow::addStatsPluginsToMenu() {
1436 GList *cfg_list = stats_tree_get_cfg_list();
1437 GList *iter = g_list_first(cfg_list);
1438 QAction *stats_tree_action;
1440 bool first_item = true;
1443 stats_tree_cfg *cfg = (stats_tree_cfg*)iter->data;
1446 main_ui_->menuStatistics->addSeparator();
1450 parent_menu = main_ui_->menuStatistics;
1451 // gtk/main_menubar.c compresses double slashes, hence SkipEmptyParts
1452 QStringList cfg_name_parts = QString(cfg->name).split("/", QString::SkipEmptyParts);
1453 if (cfg_name_parts.isEmpty()) continue;
1455 QString stat_name = cfg_name_parts.takeLast();
1456 if (!cfg_name_parts.isEmpty()) {
1457 QString menu_name = cfg_name_parts.join("/");
1458 parent_menu = findOrAddMenu(parent_menu, menu_name);
1461 stats_tree_action = new QAction(stat_name, this);
1462 stats_tree_action->setData(cfg->abbr);
1463 parent_menu->addAction(stats_tree_action);
1464 connect(stats_tree_action, SIGNAL(triggered()), this, SLOT(actionStatisticsPlugin_triggered()));
1466 iter = g_list_next(iter);
1468 g_list_free(cfg_list);
1471 void MainWindow::setFeaturesEnabled(bool enabled)
1473 main_ui_->menuBar->setEnabled(enabled);
1474 main_ui_->mainToolBar->setEnabled(enabled);
1475 main_ui_->displayFilterToolBar->setEnabled(enabled);
1478 main_ui_->statusBar->clearMessage();
1482 main_ui_->statusBar->showMessage(tr("Please wait while Wireshark is initializing" UTF8_HORIZONTAL_ELLIPSIS));
1486 // Display Filter Toolbar
1488 void MainWindow::on_actionDisplayFilterExpression_triggered()
1490 DisplayFilterExpressionDialog *dfe_dialog = new DisplayFilterExpressionDialog(this);
1492 connect(dfe_dialog, SIGNAL(insertDisplayFilter(QString)),
1493 df_combo_box_->lineEdit(), SLOT(insertFilter(const QString &)));
1498 void MainWindow::on_actionNewDisplayFilterExpression_triggered()
1500 main_ui_->filterExpressionFrame->addExpression(df_combo_box_->lineEdit()->text());
1501 showAccordionFrame(main_ui_->filterExpressionFrame);
1504 // On Qt4 + OS X with unifiedTitleAndToolBarOnMac set it's possible to make
1505 // the main window obnoxiously wide.
1507 void MainWindow::displayFilterButtonClicked()
1509 QAction *dfb_action = qobject_cast<QAction*>(sender());
1512 df_combo_box_->lineEdit()->setText(dfb_action->data().toString());
1513 df_combo_box_->applyDisplayFilter();
1514 df_combo_box_->lineEdit()->setFocus();
1518 void MainWindow::openStatCommandDialog(const QString &menu_path, const char *arg, void *userdata)
1520 QString slot = QString("statCommand%1").arg(menu_path);
1521 QMetaObject::invokeMethod(this, slot.toLatin1().constData(), Q_ARG(const char *, arg), Q_ARG(void *, userdata));
1524 void MainWindow::openTapParameterDialog(const QString cfg_str, const QString arg, void *userdata)
1526 TapParameterDialog *tp_dialog = TapParameterDialog::showTapParameterStatistics(*this, capture_file_, cfg_str, arg, userdata);
1527 if (!tp_dialog) return;
1529 connect(tp_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
1530 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
1531 connect(tp_dialog, SIGNAL(updateFilter(QString)),
1532 df_combo_box_->lineEdit(), SLOT(setText(QString)));
1536 void MainWindow::openTapParameterDialog()
1538 QAction *tpa = qobject_cast<QAction *>(QObject::sender());
1541 const QString cfg_str = tpa->data().toString();
1542 openTapParameterDialog(cfg_str, NULL, NULL);
1547 void MainWindow::on_actionFileOpen_triggered()
1552 void MainWindow::on_actionFileMerge_triggered()
1557 void MainWindow::on_actionFileImportFromHexDump_triggered()
1559 importCaptureFile();
1562 void MainWindow::on_actionFileClose_triggered() {
1563 if (testCaptureFileClose())
1564 main_ui_->mainStack->setCurrentWidget(main_welcome_);
1567 void MainWindow::on_actionFileSave_triggered()
1569 saveCaptureFile(capture_file_.capFile(), FALSE);
1572 void MainWindow::on_actionFileSaveAs_triggered()
1574 saveAsCaptureFile(capture_file_.capFile());
1577 void MainWindow::on_actionFileSetListFiles_triggered()
1579 file_set_dialog_.exec();
1582 void MainWindow::on_actionFileSetNextFile_triggered()
1584 fileset_entry *entry = fileset_get_next();
1587 QString new_cf_path = entry->fullname;
1588 openCaptureFile(new_cf_path);
1592 void MainWindow::on_actionFileSetPreviousFile_triggered()
1594 fileset_entry *entry = fileset_get_previous();
1597 QString new_cf_path = entry->fullname;
1598 openCaptureFile(new_cf_path);
1602 void MainWindow::on_actionFileExportPackets_triggered()
1604 exportSelectedPackets();
1607 void MainWindow::on_actionFileExportAsPlainText_triggered()
1609 exportDissections(export_type_text);
1612 void MainWindow::on_actionFileExportAsCSV_triggered()
1614 exportDissections(export_type_csv);
1617 void MainWindow::on_actionFileExportAsCArrays_triggered()
1619 exportDissections(export_type_carrays);
1622 void MainWindow::on_actionFileExportAsPSML_triggered()
1624 exportDissections(export_type_psml);
1627 void MainWindow::on_actionFileExportAsPDML_triggered()
1629 exportDissections(export_type_pdml);
1632 void MainWindow::on_actionFileExportPacketBytes_triggered()
1636 if (!capture_file_.capFile() || !capture_file_.capFile()->finfo_selected) return;
1638 file_name = QFileDialog::getSaveFileName(this,
1639 wsApp->windowTitleString(tr("Export Selected Packet Bytes")),
1640 wsApp->lastOpenDir().canonicalPath(),
1641 tr("Raw data (*.bin *.dat *.raw);;Any File (*.*)")
1644 if (file_name.length() > 0) {
1645 const guint8 *data_p;
1648 data_p = tvb_get_ptr(capture_file_.capFile()->finfo_selected->ds_tvb, 0, -1) +
1649 capture_file_.capFile()->finfo_selected->start;
1650 fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
1652 open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
1655 if (write(fd, data_p, capture_file_.capFile()->finfo_selected->length) < 0) {
1656 write_failure_alert_box(file_name.toUtf8().constData(), errno);
1660 if (::close(fd) < 0) {
1661 write_failure_alert_box(file_name.toUtf8().constData(), errno);
1665 /* Save the directory name for future file dialogs. */
1666 wsApp->setLastOpenDir(&file_name);
1669 void MainWindow::on_actionFileExportPDU_triggered()
1671 ExportPDUDialog *exportpdu_dialog = new ExportPDUDialog(this);
1673 if (exportpdu_dialog->isMinimized() == true)
1675 exportpdu_dialog->showNormal();
1679 exportpdu_dialog->show();
1682 exportpdu_dialog->raise();
1683 exportpdu_dialog->activateWindow();
1686 void MainWindow::on_actionFileExportSSLSessionKeys_triggered()
1692 keylist_len = ssl_session_key_count();
1693 /* don't show up the dialog, if no data has to be saved */
1694 if (keylist_len < 1) {
1695 /* shouldn't happen as the menu item should have been greyed out */
1696 QMessageBox::warning(
1699 tr("There are no SSL Session Keys to save."),
1705 save_title.append(wsApp->windowTitleString(tr("Export SSL Session Keys (%1 key%2").
1706 arg(keylist_len).arg(plurality(keylist_len, "", "s"))));
1707 file_name = QFileDialog::getSaveFileName(this,
1709 wsApp->lastOpenDir().canonicalPath(),
1710 tr("SSL Session Keys (*.keys *.txt);;Any File (*.*)")
1712 if (file_name.length() > 0) {
1716 keylist = ssl_export_sessions();
1717 fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
1719 open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
1724 * Thanks, Microsoft, for not using size_t for the third argument to
1725 * _write(). Presumably this string will be <= 4GiB long....
1727 if (ws_write(fd, keylist, (unsigned int)strlen(keylist)) < 0) {
1728 write_failure_alert_box(file_name.toUtf8().constData(), errno);
1733 if (::close(fd) < 0) {
1734 write_failure_alert_box(file_name.toUtf8().constData(), errno);
1739 /* Save the directory name for future file dialogs. */
1740 wsApp->setLastOpenDir(&file_name);
1745 void MainWindow::on_actionFileExportObjectsDICOM_triggered()
1747 new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Dicom);
1750 void MainWindow::on_actionStatisticsHpfeeds_triggered()
1752 openStatisticsTreeDialog("hpfeeds");
1755 void MainWindow::on_actionFileExportObjectsHTTP_triggered()
1757 new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Http);
1760 void MainWindow::on_actionFileExportObjectsSMB_triggered()
1762 new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Smb);
1765 void MainWindow::on_actionFileExportObjectsTFTP_triggered()
1767 new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Tftp);
1770 void MainWindow::on_actionFilePrint_triggered()
1772 PrintDialog pdlg(this, capture_file_.capFile());
1779 void MainWindow::recursiveCopyProtoTreeItems(QTreeWidgetItem *item, QString &clip, int ident_level) {
1780 if (!item->isExpanded()) return;
1782 for (int i_item = 0; i_item < item->childCount(); i_item += 1) {
1783 clip.append(QString(" ").repeated(ident_level));
1784 clip.append(item->child(i_item)->text(0));
1787 recursiveCopyProtoTreeItems(item->child(i_item), clip, ident_level + 1);
1791 // XXX This should probably be somewhere else.
1792 void MainWindow::actionEditCopyTriggered(MainWindow::CopySelected selection_type)
1794 char label_str[ITEM_LABEL_LENGTH];
1797 if (!capture_file_.capFile()) return;
1799 field_info *finfo_selected = capture_file_.capFile()->finfo_selected;
1801 switch(selection_type) {
1802 case CopySelectedDescription:
1803 if (finfo_selected && finfo_selected->rep
1804 && strlen (finfo_selected->rep->representation) > 0) {
1805 clip.append(finfo_selected->rep->representation);
1808 case CopySelectedFieldName:
1809 if (finfo_selected && finfo_selected->hfinfo->abbrev != 0) {
1810 clip.append(finfo_selected->hfinfo->abbrev);
1813 case CopySelectedValue:
1814 if (finfo_selected && capture_file_.capFile()->edt != 0) {
1815 gchar* field_str = get_node_field_value(finfo_selected, capture_file_.capFile()->edt);
1816 clip.append(field_str);
1820 case CopyAllVisibleItems:
1821 for (int i_item = 0; i_item < proto_tree_->topLevelItemCount(); i_item += 1) {
1822 clip.append(proto_tree_->topLevelItem(i_item)->text(0));
1825 recursiveCopyProtoTreeItems(proto_tree_->topLevelItem(i_item), clip, 1);
1829 case CopyAllVisibleSelectedTreeItems:
1830 if (proto_tree_->selectedItems().count() > 0) {
1831 clip.append(proto_tree_->currentItem()->text(0));
1834 recursiveCopyProtoTreeItems(proto_tree_->currentItem(), clip, 1);
1839 if (clip.length() == 0) {
1840 /* If no representation then... Try to read the value */
1841 proto_item_fill_label(capture_file_.capFile()->finfo_selected, label_str);
1842 clip.append(label_str);
1845 if (clip.length()) {
1846 wsApp->clipboard()->setText(clip);
1848 QString err = tr("Couldn't copy text. Try another item.");
1849 main_ui_->statusBar->pushTemporaryStatus(err);
1853 void MainWindow::on_actionCopyAllVisibleItems_triggered()
1855 actionEditCopyTriggered(CopyAllVisibleItems);
1858 void MainWindow::on_actionCopyAllVisibleSelectedTreeItems_triggered()
1860 actionEditCopyTriggered(CopyAllVisibleSelectedTreeItems);
1863 void MainWindow::on_actionEditCopyDescription_triggered()
1865 actionEditCopyTriggered(CopySelectedDescription);
1868 void MainWindow::on_actionEditCopyFieldName_triggered()
1870 actionEditCopyTriggered(CopySelectedFieldName);
1873 void MainWindow::on_actionEditCopyValue_triggered()
1875 actionEditCopyTriggered(CopySelectedValue);
1878 void MainWindow::on_actionEditCopyAsFilter_triggered()
1880 matchFieldFilter(FilterAction::ActionCopy, FilterAction::ActionTypePlain);
1883 void MainWindow::on_actionEditFindPacket_triggered()
1885 if (packet_list_->model()->rowCount() < 1) {
1888 previous_focus_ = wsApp->focusWidget();
1889 connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
1890 showAccordionFrame(main_ui_->searchFrame, true);
1893 void MainWindow::on_actionEditFindNext_triggered()
1895 main_ui_->searchFrame->findNext();
1898 void MainWindow::on_actionEditFindPrevious_triggered()
1900 main_ui_->searchFrame->findPrevious();
1903 void MainWindow::on_actionEditMarkPacket_triggered()
1905 packet_list_->markFrame();
1908 void MainWindow::on_actionEditMarkAllDisplayed_triggered()
1910 packet_list_->markAllDisplayedFrames(true);
1913 void MainWindow::on_actionEditUnmarkAllDisplayed_triggered()
1915 packet_list_->markAllDisplayedFrames(false);
1918 void MainWindow::on_actionEditNextMark_triggered()
1920 if (capture_file_.capFile())
1921 cf_find_packet_marked(capture_file_.capFile(), SD_FORWARD);
1924 void MainWindow::on_actionEditPreviousMark_triggered()
1926 if (capture_file_.capFile())
1927 cf_find_packet_marked(capture_file_.capFile(), SD_BACKWARD);
1930 void MainWindow::on_actionEditIgnorePacket_triggered()
1932 packet_list_->ignoreFrame();
1935 void MainWindow::on_actionEditIgnoreAllDisplayed_triggered()
1937 packet_list_->ignoreAllDisplayedFrames(true);
1940 void MainWindow::on_actionEditUnignoreAllDisplayed_triggered()
1942 packet_list_->ignoreAllDisplayedFrames(false);
1945 void MainWindow::on_actionEditSetTimeReference_triggered()
1947 packet_list_->setTimeReference();
1950 void MainWindow::on_actionEditUnsetAllTimeReferences_triggered()
1952 packet_list_->unsetAllTimeReferences();
1955 void MainWindow::on_actionEditNextTimeReference_triggered()
1957 if (!capture_file_.capFile()) return;
1958 cf_find_packet_time_reference(capture_file_.capFile(), SD_FORWARD);
1961 void MainWindow::on_actionEditPreviousTimeReference_triggered()
1963 if (!capture_file_.capFile()) return;
1964 cf_find_packet_time_reference(capture_file_.capFile(), SD_BACKWARD);
1967 void MainWindow::on_actionEditTimeShift_triggered()
1969 TimeShiftDialog ts_dialog(this, capture_file_.capFile());
1970 connect(this, SIGNAL(setCaptureFile(capture_file*)),
1971 &ts_dialog, SLOT(setCaptureFile(capture_file*)));
1972 connect(&ts_dialog, SIGNAL(timeShifted()), packet_list_, SLOT(applyTimeShift()));
1976 void MainWindow::on_actionEditPacketComment_triggered()
1978 PacketCommentDialog pc_dialog(this, packet_list_->packetComment());
1979 if (pc_dialog.exec() == QDialog::Accepted) {
1980 packet_list_->setPacketComment(pc_dialog.text());
1981 updateForUnsavedChanges();
1985 void MainWindow::on_actionEditConfigurationProfiles_triggered()
1987 ProfileDialog cp_dialog;
1992 void MainWindow::showPreferencesDialog(PreferencesDialog::PreferencesPane start_pane)
1994 PreferencesDialog pref_dialog(this);
1996 pref_dialog.setPane(start_pane);
1999 // Emitting PacketDissectionChanged directly from a QDialog can cause
2000 // problems on OS X.
2001 wsApp->flushAppSignals();
2004 void MainWindow::showPreferencesDialog(QString module_name)
2006 PreferencesDialog pref_dialog(this);
2008 pref_dialog.setPane(module_name);
2011 // Emitting PacketDissectionChanged directly from a QDialog can cause
2012 // problems on OS X.
2013 wsApp->flushAppSignals();
2016 void MainWindow::on_actionEditPreferences_triggered()
2018 showPreferencesDialog();
2023 void MainWindow::showHideMainWidgets(QAction *action)
2028 bool show = action->isChecked();
2029 QWidget *widget = action->data().value<QWidget*>();
2031 // We may have come from the toolbar context menu, so check/uncheck each
2033 if (widget == main_ui_->mainToolBar) {
2034 recent.main_toolbar_show = show;
2035 main_ui_->actionViewMainToolbar->setChecked(show);
2036 } else if (widget == main_ui_->displayFilterToolBar) {
2037 recent.filter_toolbar_show = show;
2038 main_ui_->actionViewFilterToolbar->setChecked(show);
2039 } else if (widget == main_ui_->wirelessToolBar) {
2040 recent.wireless_toolbar_show = show;
2041 main_ui_->actionViewWirelessToolbar->setChecked(show);
2042 } else if (widget == main_ui_->statusBar) {
2043 recent.statusbar_show = show;
2044 main_ui_->actionViewStatusBar->setChecked(show);
2045 } else if (widget == packet_list_) {
2046 recent.packet_list_show = show;
2047 main_ui_->actionViewPacketList->setChecked(show);
2048 } else if (widget == proto_tree_) {
2049 recent.tree_view_show = show;
2050 main_ui_->actionViewPacketDetails->setChecked(show);
2051 } else if (widget == byte_view_tab_) {
2052 recent.byte_view_show = show;
2053 main_ui_->actionViewPacketBytes->setChecked(show);
2057 widget->setVisible(show);
2061 Q_DECLARE_METATYPE(ts_type)
2063 void MainWindow::setTimestampFormat(QAction *action)
2068 ts_type tsf = action->data().value<ts_type>();
2069 if (recent.gui_time_format != tsf) {
2070 timestamp_set_type(tsf);
2071 recent.gui_time_format = tsf;
2072 if (capture_file_.capFile()) {
2073 /* This call adjusts column width */
2074 cf_timestamp_auto_precision(capture_file_.capFile());
2077 packet_list_->columnsChanged();
2082 Q_DECLARE_METATYPE(ts_precision)
2084 void MainWindow::setTimestampPrecision(QAction *action)
2089 ts_precision tsp = action->data().value<ts_precision>();
2090 if (recent.gui_time_precision != tsp) {
2091 /* the actual precision will be set in packet_list_queue_draw() below */
2092 timestamp_set_precision(tsp);
2093 recent.gui_time_precision = tsp;
2094 if (capture_file_.capFile()) {
2095 /* This call adjusts column width */
2096 cf_timestamp_auto_precision(capture_file_.capFile());
2099 packet_list_->columnsChanged();
2104 void MainWindow::on_actionViewTimeDisplaySecondsWithHoursAndMinutes_triggered(bool checked)
2107 recent.gui_seconds_format = TS_SECONDS_HOUR_MIN_SEC;
2109 recent.gui_seconds_format = TS_SECONDS_DEFAULT;
2111 timestamp_set_seconds_type(recent.gui_seconds_format);
2113 if (capture_file_.capFile()) {
2114 /* This call adjusts column width */
2115 cf_timestamp_auto_precision(capture_file_.capFile());
2118 packet_list_->columnsChanged();
2122 void MainWindow::on_actionViewEditResolvedName_triggered()
2124 // int column = packet_list_->selectedColumn();
2127 if (packet_list_->currentIndex().isValid()) {
2128 column = packet_list_->currentIndex().column();
2131 main_ui_->addressEditorFrame->editAddresses(capture_file_, column);
2132 showAccordionFrame(main_ui_->addressEditorFrame);
2135 void MainWindow::setNameResolution()
2137 gbl_resolv_flags.mac_name = main_ui_->actionViewNameResolutionPhysical->isChecked() ? TRUE : FALSE;
2138 gbl_resolv_flags.network_name = main_ui_->actionViewNameResolutionNetwork->isChecked() ? TRUE : FALSE;
2139 gbl_resolv_flags.transport_name = main_ui_->actionViewNameResolutionTransport->isChecked() ? TRUE : FALSE;
2142 packet_list_->columnsChanged();
2146 void MainWindow::on_actionViewNameResolutionPhysical_triggered()
2148 setNameResolution();
2151 void MainWindow::on_actionViewNameResolutionNetwork_triggered()
2153 setNameResolution();
2156 void MainWindow::on_actionViewNameResolutionTransport_triggered()
2158 setNameResolution();
2161 void MainWindow::zoomText()
2163 // Scale by 10%, rounding to nearest half point, minimum 1 point.
2164 // XXX Small sizes repeat. It might just be easier to create a map of multipliers.
2165 mono_font_ = QFont(wsApp->monospaceFont());
2166 qreal zoom_size = wsApp->monospaceFont().pointSize() * 2 * qPow(1.1, recent.gui_zoom_level);
2167 zoom_size = qRound(zoom_size) / 2.0;
2168 zoom_size = qMax(zoom_size, 1.0);
2169 mono_font_.setPointSizeF(zoom_size);
2170 emit monospaceFontChanged(mono_font_);
2173 void MainWindow::on_actionViewZoomIn_triggered()
2175 recent.gui_zoom_level++;
2179 void MainWindow::on_actionViewZoomOut_triggered()
2181 recent.gui_zoom_level--;
2185 void MainWindow::on_actionViewNormalSize_triggered()
2187 recent.gui_zoom_level = 0;
2191 void MainWindow::on_actionViewColorizePacketList_triggered(bool checked) {
2192 recent.packet_list_colorize = checked;
2193 color_filters_enable(checked);
2194 packet_list_->packetListModel()->resetColorized();
2195 packet_list_->update();
2198 void MainWindow::on_actionViewColoringRules_triggered()
2200 ColoringRulesDialog coloring_rules_dialog(this);
2202 coloring_rules_dialog.exec();
2205 // actionViewColorizeConversation1 - 10
2206 void MainWindow::colorizeConversation(bool create_rule)
2208 QAction *cc_action = qobject_cast<QAction *>(sender());
2209 if (!cc_action) return;
2211 if (capture_file_.capFile() && capture_file_.capFile()->current_frame) {
2212 packet_info *pi = &capture_file_.capFile()->edt->pi;
2213 guint8 cc_num = cc_action->data().toUInt();
2214 gchar *filter = NULL;
2216 const conversation_filter_t *color_filter = find_conversation_filter("tcp");
2217 if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2218 filter = color_filter->build_filter_string(pi);
2219 if (filter == NULL) {
2220 color_filter = find_conversation_filter("udp");
2221 if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2222 filter = color_filter->build_filter_string(pi);
2224 if (filter == NULL) {
2225 color_filter = find_conversation_filter("ip");
2226 if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2227 filter = color_filter->build_filter_string(pi);
2229 if (filter == NULL) {
2230 color_filter = find_conversation_filter("ipv6");
2231 if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2232 filter = color_filter->build_filter_string(pi);
2234 if (filter == NULL) {
2235 color_filter = find_conversation_filter("eth");
2236 if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2237 filter = color_filter->build_filter_string(pi);
2239 if( filter == NULL ) {
2240 main_ui_->statusBar->pushTemporaryStatus(tr("Unable to build conversation filter."));
2245 ColoringRulesDialog coloring_rules_dialog(this, filter);
2246 coloring_rules_dialog.exec();
2248 color_filters_set_tmp(cc_num, filter, FALSE);
2249 packet_list_->recolorPackets();
2252 setMenusForSelectedPacket();
2255 void MainWindow::colorizeWithFilter()
2257 QAction *colorize_action = qobject_cast<QAction *>(sender());
2258 if (!colorize_action) return;
2260 QString filter = colorize_action->data().toString();
2261 if (filter.isEmpty()) return;
2264 int color_number = colorize_action->property(color_number_property_).toInt(&ok);
2268 color_filters_set_tmp(color_number, filter.toUtf8().constData(), FALSE);
2269 packet_list_->recolorPackets();
2271 // New coloring rule
2272 ColoringRulesDialog coloring_rules_dialog(window(), filter);
2273 coloring_rules_dialog.exec();
2275 main_ui_->actionViewColorizeResetColorization->setEnabled(tmp_color_filters_used());
2278 void MainWindow::on_actionViewColorizeResetColorization_triggered()
2280 color_filters_reset_tmp();
2281 packet_list_->recolorPackets();
2282 setMenusForSelectedPacket();
2285 void MainWindow::on_actionViewColorizeNewConversationRule_triggered()
2287 colorizeConversation(true);
2290 void MainWindow::on_actionViewResizeColumns_triggered()
2292 for (int col = 0; col < packet_list_->packetListModel()->columnCount(); col++) {
2293 packet_list_->resizeColumnToContents(col);
2294 recent_set_column_width(col, packet_list_->columnWidth(col));
2298 void MainWindow::openPacketDialog(bool from_reference)
2302 /* Find the frame for which we're popping up a dialog */
2303 if(from_reference) {
2304 guint32 framenum = fvalue_get_uinteger(&(capture_file_.capFile()->finfo_selected->value));
2308 fdata = frame_data_sequence_find(capture_file_.capFile()->frames, framenum);
2310 fdata = capture_file_.capFile()->current_frame;
2313 /* If we have a frame, pop up the dialog */
2315 PacketDialog *packet_dialog = new PacketDialog(*this, capture_file_, fdata);
2317 connect(this, SIGNAL(monospaceFontChanged(QFont)),
2318 packet_dialog, SIGNAL(monospaceFontChanged(QFont)));
2319 connect(this, SIGNAL(closePacketDialogs()),
2320 packet_dialog, SLOT(close()));
2321 zoomText(); // Emits monospaceFontChanged
2323 packet_dialog->show();
2327 void MainWindow::on_actionViewInternalsConversationHashTables_triggered()
2329 ConversationHashTablesDialog *conversation_hash_tables_dlg = new ConversationHashTablesDialog(this);
2330 conversation_hash_tables_dlg->show();
2333 void MainWindow::on_actionViewInternalsDissectorTables_triggered()
2335 DissectorTablesDialog *dissector_tables_dlg = new DissectorTablesDialog(this);
2336 dissector_tables_dlg->show();
2339 void MainWindow::on_actionViewInternalsSupportedProtocols_triggered()
2341 SupportedProtocolsDialog *supported_protocols_dlg = new SupportedProtocolsDialog(this);
2342 supported_protocols_dlg->show();
2345 void MainWindow::on_actionViewShowPacketInNewWindow_triggered()
2350 // This is only used in ProtoTree. Defining it here makes more sense.
2351 void MainWindow::on_actionContextShowLinkedPacketInNewWindow_triggered()
2353 openPacketDialog(true);
2356 void MainWindow::on_actionViewReload_triggered()
2358 cf_reload(CaptureFile::globalCapFile());
2361 void MainWindow::on_actionViewReload_as_File_Format_or_Capture_triggered()
2363 capture_file *cf = CaptureFile::globalCapFile();
2365 if (cf->open_type == WTAP_TYPE_AUTO)
2366 cf->open_type = open_info_name_to_type("MIME Files Format");
2367 else /* TODO: This should be latest format chosen by user */
2368 cf->open_type = WTAP_TYPE_AUTO;
2374 // Expand / collapse slots in proto_tree
2380 void MainWindow::matchFieldFilter(FilterAction::Action action, FilterAction::ActionType filter_type)
2382 QString field_filter;
2384 if (packet_list_->contextMenuActive() || packet_list_->hasFocus()) {
2385 field_filter = packet_list_->getFilterFromRowAndColumn();
2386 } else if (capture_file_.capFile() && capture_file_.capFile()->finfo_selected) {
2387 char *tmp_field = proto_construct_match_selected_string(capture_file_.capFile()->finfo_selected,
2388 capture_file_.capFile()->edt);
2389 field_filter = QString(tmp_field);
2390 wmem_free(NULL, tmp_field);
2393 if (field_filter.isEmpty()) {
2394 QString err = tr("No filter available. Try another ");
2395 err.append(packet_list_->contextMenuActive() ? "column" : "item");
2397 main_ui_->statusBar->pushTemporaryStatus(err);
2401 filterAction(field_filter, action, filter_type);
2404 static FilterDialog *display_filter_dlg_ = NULL;
2405 void MainWindow::on_actionAnalyzeDisplayFilters_triggered()
2407 if (!display_filter_dlg_) {
2408 display_filter_dlg_ = new FilterDialog(this, FilterDialog::DisplayFilter);
2410 display_filter_dlg_->show();
2411 display_filter_dlg_->raise();
2412 display_filter_dlg_->activateWindow();
2416 void MainWindow::on_actionAnalyzeDisplayFilterMacros_triggered()
2418 struct epan_uat* dfm_uat;
2419 dfilter_macro_get_uat(&dfm_uat);
2420 UatDialog uat_dlg(parentWidget(), dfm_uat);
2423 // Emitting PacketDissectionChanged directly from a QDialog can cause
2424 // problems on OS X.
2425 wsApp->flushAppSignals();
2428 void MainWindow::on_actionAnalyzeCreateAColumn_triggered()
2432 if ( capture_file_.capFile() != 0 && capture_file_.capFile()->finfo_selected != 0 )
2434 colnr = column_prefs_add_custom(COL_CUSTOM, capture_file_.capFile()->finfo_selected->hfinfo->name,
2435 capture_file_.capFile()->finfo_selected->hfinfo->abbrev,0);
2437 packet_list_->columnsChanged();
2438 packet_list_->resizeColumnToContents(colnr);
2444 void MainWindow::applyConversationFilter()
2446 QAction *cfa = qobject_cast<QAction*>(sender());
2449 QString new_filter = cfa->data().toString();
2450 if (new_filter.isEmpty()) return;
2452 df_combo_box_->lineEdit()->setText(new_filter);
2453 df_combo_box_->applyDisplayFilter();
2456 // XXX We could probably create the analyze and prepare actions
2457 // dynamically using FilterActions and consolidate the methods
2458 // below into one callback.
2459 void MainWindow::on_actionAnalyzeAAFSelected_triggered()
2461 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypePlain);
2464 void MainWindow::on_actionAnalyzeAAFNotSelected_triggered()
2466 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeNot);
2469 void MainWindow::on_actionAnalyzeAAFAndSelected_triggered()
2471 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeAnd);
2474 void MainWindow::on_actionAnalyzeAAFOrSelected_triggered()
2476 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeOr);
2479 void MainWindow::on_actionAnalyzeAAFAndNotSelected_triggered()
2481 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeAndNot);
2484 void MainWindow::on_actionAnalyzeAAFOrNotSelected_triggered()
2486 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeOrNot);
2489 void MainWindow::on_actionAnalyzePAFSelected_triggered()
2491 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypePlain);
2494 void MainWindow::on_actionAnalyzePAFNotSelected_triggered()
2496 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeNot);
2499 void MainWindow::on_actionAnalyzePAFAndSelected_triggered()
2501 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeAnd);
2504 void MainWindow::on_actionAnalyzePAFOrSelected_triggered()
2506 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeOr);
2509 void MainWindow::on_actionAnalyzePAFAndNotSelected_triggered()
2511 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeAndNot);
2514 void MainWindow::on_actionAnalyzePAFOrNotSelected_triggered()
2516 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeOrNot);
2519 void MainWindow::on_actionAnalyzeEnabledProtocols_triggered()
2521 EnabledProtocolsDialog enable_proto_dialog(this);
2522 enable_proto_dialog.exec();
2524 // Emitting PacketDissectionChanged directly from a QDialog can cause
2525 // problems on OS X.
2526 wsApp->flushAppSignals();
2529 void MainWindow::on_actionAnalyzeDecodeAs_triggered()
2531 QAction *da_action = qobject_cast<QAction*>(sender());
2532 bool create_new = false;
2533 if (da_action && da_action->data().toBool() == true) {
2537 DecodeAsDialog da_dialog(this, capture_file_.capFile(), create_new);
2538 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2539 &da_dialog, SLOT(setCaptureFile(capture_file*)));
2542 // Emitting PacketDissectionChanged directly from a QDialog can cause
2543 // problems on OS X.
2544 wsApp->flushAppSignals();
2548 void MainWindow::on_actionAnalyzeReloadLuaPlugins_triggered()
2550 if (wsApp->isReloadingLua())
2553 wsApp->setReloadingLua(true);
2555 wslua_reload_plugins(NULL, NULL);
2556 funnel_statistics_reload_menus();
2557 reloadDynamicMenus();
2558 closePacketDialogs();
2560 // Preferences may have been deleted so close all widgets using prefs
2561 proto_tree_->closeContextMenu();
2562 main_ui_->preferenceEditorFrame->animatedHide();
2564 char *gdp_path, *dp_path;
2565 (void) wsApp->readConfigurationFiles(&gdp_path, &dp_path);
2570 wsApp->setReloadingLua(false);
2571 SimpleDialog::displayQueuedMessages();
2575 void MainWindow::openFollowStreamDialog(follow_type_t type) {
2576 FollowStreamDialog *fsd = new FollowStreamDialog(*this, capture_file_, type);
2577 connect(fsd, SIGNAL(updateFilter(QString, bool)), this, SLOT(filterPackets(QString, bool)));
2578 connect(fsd, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
2581 fsd->follow(getFilter());
2584 void MainWindow::on_actionAnalyzeFollowTCPStream_triggered()
2586 openFollowStreamDialog(FOLLOW_TCP);
2589 void MainWindow::on_actionAnalyzeFollowUDPStream_triggered()
2591 openFollowStreamDialog(FOLLOW_UDP);
2594 void MainWindow::on_actionAnalyzeFollowSSLStream_triggered()
2596 openFollowStreamDialog(FOLLOW_SSL);
2599 void MainWindow::openSCTPAllAssocsDialog()
2601 SCTPAllAssocsDialog *sctp_dialog = new SCTPAllAssocsDialog(this, capture_file_.capFile());
2602 connect(sctp_dialog, SIGNAL(filterPackets(QString,bool)),
2603 this, SLOT(filterPackets(QString,bool)));
2604 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2605 sctp_dialog, SLOT(setCaptureFile(capture_file*)));
2606 sctp_dialog->fillTable();
2608 if (sctp_dialog->isMinimized() == true)
2610 sctp_dialog->showNormal();
2614 sctp_dialog->show();
2617 sctp_dialog->raise();
2618 sctp_dialog->activateWindow();
2621 void MainWindow::on_actionSCTPShowAllAssociations_triggered()
2623 openSCTPAllAssocsDialog();
2626 void MainWindow::on_actionSCTPAnalyseThisAssociation_triggered()
2628 SCTPAssocAnalyseDialog *sctp_analyse = new SCTPAssocAnalyseDialog(this, NULL, capture_file_.capFile());
2629 connect(sctp_analyse, SIGNAL(filterPackets(QString,bool)),
2630 this, SLOT(filterPackets(QString,bool)));
2632 if (sctp_analyse->isMinimized() == true)
2634 sctp_analyse->showNormal();
2638 sctp_analyse->show();
2641 sctp_analyse->raise();
2642 sctp_analyse->activateWindow();
2645 void MainWindow::on_actionSCTPFilterThisAssociation_triggered()
2647 sctp_assoc_info_t* assoc = SCTPAssocAnalyseDialog::findAssocForPacket(capture_file_.capFile());
2649 QString newFilter = QString("sctp.assoc_index==%1").arg(assoc->assoc_id);
2651 emit filterPackets(newFilter, false);
2656 void MainWindow::statCommandWlanStatistics(const char *arg, void *)
2658 WlanStatisticsDialog *wlan_stats_dlg = new WlanStatisticsDialog(*this, capture_file_, arg);
2659 connect(wlan_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2660 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2661 wlan_stats_dlg->show();
2664 void MainWindow::on_actionWirelessWlanStatistics_triggered()
2666 statCommandWlanStatistics(NULL, NULL);
2670 void MainWindow::statCommandExpertInfo(const char *, void *)
2672 ExpertInfoDialog *expert_dialog = new ExpertInfoDialog(*this, capture_file_);
2673 const DisplayFilterEdit *df_edit = dynamic_cast<DisplayFilterEdit *>(df_combo_box_->lineEdit());
2675 expert_dialog->setDisplayFilter(df_edit->text());
2677 connect(expert_dialog, SIGNAL(goToPacket(int, int)),
2678 packet_list_, SLOT(goToPacket(int, int)));
2679 connect(expert_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2680 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2682 expert_dialog->show();
2685 void MainWindow::on_actionAnalyzeExpertInfo_triggered()
2687 statCommandExpertInfo(NULL, NULL);
2691 // Next / previous / first / last slots in packet_list
2695 void MainWindow::on_actionStatisticsFlowGraph_triggered()
2697 SequenceDialog *sequence_dialog = new SequenceDialog(*this, capture_file_);
2698 connect(sequence_dialog, SIGNAL(goToPacket(int)),
2699 packet_list_, SLOT(goToPacket(int)));
2700 sequence_dialog->show();
2703 void MainWindow::openTcpStreamDialog(int graph_type)
2705 TCPStreamDialog *stream_dialog = new TCPStreamDialog(this, capture_file_.capFile(), (tcp_graph_type)graph_type);
2706 connect(stream_dialog, SIGNAL(goToPacket(int)),
2707 packet_list_, SLOT(goToPacket(int)));
2708 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2709 stream_dialog, SLOT(setCaptureFile(capture_file*)));
2710 stream_dialog->show();
2713 void MainWindow::on_actionStatisticsTcpStreamStevens_triggered()
2715 openTcpStreamDialog(GRAPH_TSEQ_STEVENS);
2718 void MainWindow::on_actionStatisticsTcpStreamTcptrace_triggered()
2720 openTcpStreamDialog(GRAPH_TSEQ_TCPTRACE);
2723 void MainWindow::on_actionStatisticsTcpStreamThroughput_triggered()
2725 openTcpStreamDialog(GRAPH_THROUGHPUT);
2728 void MainWindow::on_actionStatisticsTcpStreamRoundTripTime_triggered()
2730 openTcpStreamDialog(GRAPH_RTT);
2733 void MainWindow::on_actionStatisticsTcpStreamWindowScaling_triggered()
2735 openTcpStreamDialog(GRAPH_WSCALE);
2739 void MainWindow::statCommandMulticastStatistics(const char *arg, void *)
2741 MulticastStatisticsDialog *mcast_stats_dlg = new MulticastStatisticsDialog(*this, capture_file_, arg);
2742 connect(mcast_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2743 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2744 mcast_stats_dlg->show();
2747 void MainWindow::on_actionStatisticsUdpMulticastStreams_triggered()
2749 statCommandMulticastStatistics(NULL, NULL);
2752 void MainWindow::openStatisticsTreeDialog(const gchar *abbr)
2754 StatsTreeDialog *st_dialog = new StatsTreeDialog(*this, capture_file_, abbr);
2755 // connect(st_dialog, SIGNAL(goToPacket(int)),
2756 // packet_list_, SLOT(goToPacket(int)));
2760 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Topic_triggered()
2762 openStatisticsTreeDialog("lbmr_topic_ads_topic");
2765 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Source_triggered()
2767 openStatisticsTreeDialog("lbmr_topic_ads_source");
2770 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Transport_triggered()
2772 openStatisticsTreeDialog("lbmr_topic_ads_transport");
2775 void MainWindow::on_actionStatistics29WestTopics_Queries_by_Topic_triggered()
2777 openStatisticsTreeDialog("lbmr_topic_queries_topic");
2780 void MainWindow::on_actionStatistics29WestTopics_Queries_by_Receiver_triggered()
2782 openStatisticsTreeDialog("lbmr_topic_queries_receiver");
2785 void MainWindow::on_actionStatistics29WestTopics_Wildcard_Queries_by_Pattern_triggered()
2787 openStatisticsTreeDialog("lbmr_topic_queries_pattern");
2790 void MainWindow::on_actionStatistics29WestTopics_Wildcard_Queries_by_Receiver_triggered()
2792 openStatisticsTreeDialog("lbmr_topic_queries_pattern_receiver");
2795 void MainWindow::on_actionStatistics29WestQueues_Advertisements_by_Queue_triggered()
2797 openStatisticsTreeDialog("lbmr_queue_ads_queue");
2800 void MainWindow::on_actionStatistics29WestQueues_Advertisements_by_Source_triggered()
2802 openStatisticsTreeDialog("lbmr_queue_ads_source");
2805 void MainWindow::on_actionStatistics29WestQueues_Queries_by_Queue_triggered()
2807 openStatisticsTreeDialog("lbmr_queue_queries_queue");
2810 void MainWindow::on_actionStatistics29WestQueues_Queries_by_Receiver_triggered()
2812 openStatisticsTreeDialog("lbmr_queue_queries_receiver");
2815 void MainWindow::on_actionStatistics29WestUIM_Streams_triggered()
2817 LBMStreamDialog *stream_dialog = new LBMStreamDialog(this, capture_file_.capFile());
2818 // connect(stream_dialog, SIGNAL(goToPacket(int)),
2819 // packet_list_, SLOT(goToPacket(int)));
2820 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2821 stream_dialog, SLOT(setCaptureFile(capture_file*)));
2822 stream_dialog->show();
2825 void MainWindow::on_actionStatistics29WestUIM_Stream_Flow_Graph_triggered()
2827 LBMUIMFlowDialog * uimflow_dialog = new LBMUIMFlowDialog(this, capture_file_.capFile());
2828 connect(uimflow_dialog, SIGNAL(goToPacket(int)),
2829 packet_list_, SLOT(goToPacket(int)));
2830 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2831 uimflow_dialog, SLOT(setCaptureFile(capture_file*)));
2832 uimflow_dialog->show();
2835 void MainWindow::on_actionStatistics29WestLBTRM_triggered()
2837 LBMLBTRMTransportDialog * lbtrm_dialog = new LBMLBTRMTransportDialog(this, capture_file_.capFile());
2838 connect(lbtrm_dialog, SIGNAL(goToPacket(int)),
2839 packet_list_, SLOT(goToPacket(int)));
2840 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2841 lbtrm_dialog, SLOT(setCaptureFile(capture_file*)));
2842 lbtrm_dialog->show();
2844 void MainWindow::on_actionStatistics29WestLBTRU_triggered()
2846 LBMLBTRUTransportDialog * lbtru_dialog = new LBMLBTRUTransportDialog(this, capture_file_.capFile());
2847 connect(lbtru_dialog, SIGNAL(goToPacket(int)),
2848 packet_list_, SLOT(goToPacket(int)));
2849 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2850 lbtru_dialog, SLOT(setCaptureFile(capture_file*)));
2851 lbtru_dialog->show();
2854 void MainWindow::on_actionStatisticsANCP_triggered()
2856 openStatisticsTreeDialog("ancp");
2859 void MainWindow::on_actionStatisticsBACappInstanceId_triggered()
2861 openStatisticsTreeDialog("bacapp_instanceid");
2864 void MainWindow::on_actionStatisticsBACappIP_triggered()
2866 openStatisticsTreeDialog("bacapp_ip");
2869 void MainWindow::on_actionStatisticsBACappObjectId_triggered()
2871 openStatisticsTreeDialog("bacapp_objectid");
2874 void MainWindow::on_actionStatisticsBACappService_triggered()
2876 openStatisticsTreeDialog("bacapp_service");
2879 void MainWindow::on_actionStatisticsCollectd_triggered()
2881 openStatisticsTreeDialog("collectd");
2885 void MainWindow::statCommandConversations(const char *arg, void *userdata)
2887 ConversationDialog *conv_dialog = new ConversationDialog(*this, capture_file_, GPOINTER_TO_INT(userdata), arg);
2888 connect(conv_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2889 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2890 connect(conv_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
2891 this, SLOT(openFollowStreamDialog(follow_type_t)));
2892 connect(conv_dialog, SIGNAL(openTcpStreamGraph(int)),
2893 this, SLOT(openTcpStreamDialog(int)));
2894 conv_dialog->show();
2897 void MainWindow::on_actionStatisticsConversations_triggered()
2899 statCommandConversations(NULL, NULL);
2903 void MainWindow::statCommandEndpoints(const char *arg, void *userdata)
2905 EndpointDialog *endp_dialog = new EndpointDialog(*this, capture_file_, GPOINTER_TO_INT(userdata), arg);
2906 connect(endp_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2907 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2908 connect(endp_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
2909 this, SLOT(openFollowStreamDialog(follow_type_t)));
2910 connect(endp_dialog, SIGNAL(openTcpStreamGraph(int)),
2911 this, SLOT(openTcpStreamDialog(int)));
2912 endp_dialog->show();
2915 void MainWindow::on_actionStatisticsEndpoints_triggered()
2917 statCommandEndpoints(NULL, NULL);
2920 void MainWindow::on_actionStatisticsHART_IP_triggered()
2922 openStatisticsTreeDialog("hart_ip");
2925 void MainWindow::on_actionStatisticsHTTPPacketCounter_triggered()
2927 openStatisticsTreeDialog("http");
2930 void MainWindow::on_actionStatisticsHTTPRequests_triggered()
2932 openStatisticsTreeDialog("http_req");
2935 void MainWindow::on_actionStatisticsHTTPLoadDistribution_triggered()
2937 openStatisticsTreeDialog("http_srv");
2940 void MainWindow::on_actionStatisticsPacketLengths_triggered()
2942 openStatisticsTreeDialog("plen");
2946 void MainWindow::statCommandIOGraph(const char *, void *)
2948 IOGraphDialog *iog_dialog = new IOGraphDialog(*this, capture_file_);
2949 connect(iog_dialog, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
2950 connect(this, SIGNAL(reloadFields()), iog_dialog, SLOT(reloadFields()));
2954 void MainWindow::on_actionStatisticsIOGraph_triggered()
2956 statCommandIOGraph(NULL, NULL);
2959 void MainWindow::on_actionStatisticsSametime_triggered()
2961 openStatisticsTreeDialog("sametime");
2964 void MainWindow::on_actionStatisticsDNS_triggered()
2966 openStatisticsTreeDialog("dns");
2969 void MainWindow::actionStatisticsPlugin_triggered()
2971 QAction* action = qobject_cast<QAction*>(sender());
2973 openStatisticsTreeDialog(action->data().toString().toUtf8());
2977 void MainWindow::on_actionStatisticsHTTP2_triggered()
2979 openStatisticsTreeDialog("http2");
2985 void MainWindow::openVoipCallsDialog(bool all_flows)
2987 VoipCallsDialog *voip_calls_dialog = new VoipCallsDialog(*this, capture_file_, all_flows);
2988 connect(voip_calls_dialog, SIGNAL(goToPacket(int)),
2989 packet_list_, SLOT(goToPacket(int)));
2990 connect(voip_calls_dialog, SIGNAL(updateFilter(QString, bool)),
2991 this, SLOT(filterPackets(QString, bool)));
2992 voip_calls_dialog->show();
2995 void MainWindow::on_actionTelephonyVoipCalls_triggered()
2997 openVoipCallsDialog();
3000 void MainWindow::on_actionTelephonyGsmMapSummary_triggered()
3002 GsmMapSummaryDialog *gms_dialog = new GsmMapSummaryDialog(*this, capture_file_);
3006 void MainWindow::on_actionTelephonyIax2StreamAnalysis_triggered()
3008 Iax2AnalysisDialog *iax2_analysis_dialog = new Iax2AnalysisDialog(*this, capture_file_);
3009 connect(iax2_analysis_dialog, SIGNAL(goToPacket(int)),
3010 packet_list_, SLOT(goToPacket(int)));
3011 iax2_analysis_dialog->show();
3014 void MainWindow::on_actionTelephonyISUPMessages_triggered()
3016 openStatisticsTreeDialog("isup_msg");
3020 void MainWindow::statCommandLteMacStatistics(const char *arg, void *)
3022 LteMacStatisticsDialog *lte_mac_stats_dlg = new LteMacStatisticsDialog(*this, capture_file_, arg);
3023 connect(lte_mac_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
3024 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
3025 lte_mac_stats_dlg->show();
3028 void MainWindow::on_actionTelephonyLteMacStatistics_triggered()
3030 statCommandLteMacStatistics(NULL, NULL);
3033 void MainWindow::statCommandLteRlcStatistics(const char *arg, void *)
3035 LteRlcStatisticsDialog *lte_rlc_stats_dlg = new LteRlcStatisticsDialog(*this, capture_file_, arg);
3036 connect(lte_rlc_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
3037 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
3038 // N.B. It is necessary for the RLC Statistics window to launch the RLC graph in this way, to ensure
3039 // that the goToPacket() signal/slot connection gets set up...
3040 connect(lte_rlc_stats_dlg, SIGNAL(launchRLCGraph(bool, guint16, guint8, guint16, guint16, guint8)),
3041 this, SLOT(launchRLCGraph(bool, guint16, guint8, guint16, guint16, guint8)));
3043 lte_rlc_stats_dlg->show();
3046 void MainWindow::on_actionTelephonyLteRlcStatistics_triggered()
3048 statCommandLteRlcStatistics(NULL, NULL);
3051 void MainWindow::launchRLCGraph(bool channelKnown,
3052 guint16 ueid, guint8 rlcMode,
3053 guint16 channelType, guint16 channelId, guint8 direction)
3055 LteRlcGraphDialog *lrg_dialog = new LteRlcGraphDialog(*this, capture_file_, channelKnown);
3056 connect(lrg_dialog, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
3057 // This is a bit messy, but wanted to hide these parameters from users of
3058 // on_actionTelephonyLteRlcGraph_triggered().
3060 lrg_dialog->setChannelInfo(ueid, rlcMode, channelType, channelId, direction);
3065 void MainWindow::on_actionTelephonyLteRlcGraph_triggered()
3067 // We don't yet know the channel.
3068 launchRLCGraph(false, 0, 0, 0, 0, 0);
3071 void MainWindow::on_actionTelephonyMtp3Summary_triggered()
3073 Mtp3SummaryDialog *mtp3s_dialog = new Mtp3SummaryDialog(*this, capture_file_);
3074 mtp3s_dialog->show();
3077 void MainWindow::on_actionTelephonyRTPStreams_triggered()
3079 RtpStreamDialog *rtp_stream_dialog = new RtpStreamDialog(*this, capture_file_);
3080 connect(rtp_stream_dialog, SIGNAL(packetsMarked()),
3081 packet_list_, SLOT(redrawVisiblePackets()));
3082 connect(rtp_stream_dialog, SIGNAL(goToPacket(int)),
3083 packet_list_, SLOT(goToPacket(int)));
3084 connect(rtp_stream_dialog, SIGNAL(updateFilter(QString, bool)),
3085 this, SLOT(filterPackets(QString, bool)));
3086 rtp_stream_dialog->show();
3089 void MainWindow::on_actionTelephonyRTPStreamAnalysis_triggered()
3091 RtpAnalysisDialog *rtp_analysis_dialog = new RtpAnalysisDialog(*this, capture_file_);
3092 connect(rtp_analysis_dialog, SIGNAL(goToPacket(int)),
3093 packet_list_, SLOT(goToPacket(int)));
3094 rtp_analysis_dialog->show();
3097 void MainWindow::on_actionTelephonyRTSPPacketCounter_triggered()
3099 openStatisticsTreeDialog("rtsp");
3102 void MainWindow::on_actionTelephonySMPPOperations_triggered()
3104 openStatisticsTreeDialog("smpp_commands");
3107 void MainWindow::on_actionTelephonyUCPMessages_triggered()
3109 openStatisticsTreeDialog("ucp_messages");
3112 void MainWindow::on_actionTelephonySipFlows_triggered()
3114 openVoipCallsDialog(true);
3119 void MainWindow::on_actionBluetoothATT_Server_Attributes_triggered()
3121 BluetoothAttServerAttributesDialog *bluetooth_att_sever_attributes_dialog = new BluetoothAttServerAttributesDialog(*this, capture_file_);
3122 connect(bluetooth_att_sever_attributes_dialog, SIGNAL(goToPacket(int)),
3123 packet_list_, SLOT(goToPacket(int)));
3124 connect(bluetooth_att_sever_attributes_dialog, SIGNAL(updateFilter(QString, bool)),
3125 this, SLOT(filterPackets(QString, bool)));
3126 bluetooth_att_sever_attributes_dialog->show();
3129 void MainWindow::on_actionBluetoothDevices_triggered()
3131 BluetoothDevicesDialog *bluetooth_devices_dialog = new BluetoothDevicesDialog(*this, capture_file_);
3132 connect(bluetooth_devices_dialog, SIGNAL(goToPacket(int)),
3133 packet_list_, SLOT(goToPacket(int)));
3134 connect(bluetooth_devices_dialog, SIGNAL(updateFilter(QString, bool)),
3135 this, SLOT(filterPackets(QString, bool)));
3136 bluetooth_devices_dialog->show();
3139 void MainWindow::on_actionBluetoothHCI_Summary_triggered()
3141 BluetoothHciSummaryDialog *bluetooth_hci_summary_dialog = new BluetoothHciSummaryDialog(*this, capture_file_);
3142 connect(bluetooth_hci_summary_dialog, SIGNAL(goToPacket(int)),
3143 packet_list_, SLOT(goToPacket(int)));
3144 connect(bluetooth_hci_summary_dialog, SIGNAL(updateFilter(QString, bool)),
3145 this, SLOT(filterPackets(QString, bool)));
3146 bluetooth_hci_summary_dialog->show();
3150 void MainWindow::on_actionHelpContents_triggered() {
3152 wsApp->helpTopicAction(HELP_CONTENT);
3155 void MainWindow::on_actionHelpMPWireshark_triggered() {
3157 wsApp->helpTopicAction(LOCALPAGE_MAN_WIRESHARK);
3160 void MainWindow::on_actionHelpMPWireshark_Filter_triggered() {
3161 wsApp->helpTopicAction(LOCALPAGE_MAN_WIRESHARK_FILTER);
3164 void MainWindow::on_actionHelpMPCapinfos_triggered() {
3165 wsApp->helpTopicAction(LOCALPAGE_MAN_CAPINFOS);
3168 void MainWindow::on_actionHelpMPDumpcap_triggered() {
3169 wsApp->helpTopicAction(LOCALPAGE_MAN_DUMPCAP);
3172 void MainWindow::on_actionHelpMPEditcap_triggered() {
3173 wsApp->helpTopicAction(LOCALPAGE_MAN_EDITCAP);
3176 void MainWindow::on_actionHelpMPMergecap_triggered() {
3177 wsApp->helpTopicAction(LOCALPAGE_MAN_MERGECAP);
3180 void MainWindow::on_actionHelpMPRawShark_triggered() {
3181 wsApp->helpTopicAction(LOCALPAGE_MAN_RAWSHARK);
3184 void MainWindow::on_actionHelpMPReordercap_triggered() {
3185 wsApp->helpTopicAction(LOCALPAGE_MAN_REORDERCAP);
3188 void MainWindow::on_actionHelpMPText2cap_triggered() {
3189 wsApp->helpTopicAction(LOCALPAGE_MAN_TEXT2PCAP);
3192 void MainWindow::on_actionHelpMPTShark_triggered() {
3193 wsApp->helpTopicAction(LOCALPAGE_MAN_TSHARK);
3196 void MainWindow::on_actionHelpWebsite_triggered() {
3198 wsApp->helpTopicAction(ONLINEPAGE_HOME);
3201 void MainWindow::on_actionHelpFAQ_triggered() {
3203 wsApp->helpTopicAction(ONLINEPAGE_FAQ);
3206 void MainWindow::on_actionHelpAsk_triggered() {
3208 wsApp->helpTopicAction(ONLINEPAGE_ASK);
3211 void MainWindow::on_actionHelpDownloads_triggered() {
3213 wsApp->helpTopicAction(ONLINEPAGE_DOWNLOAD);
3216 void MainWindow::on_actionHelpWiki_triggered() {
3218 wsApp->helpTopicAction(ONLINEPAGE_WIKI);
3221 void MainWindow::on_actionHelpSampleCaptures_triggered() {
3223 wsApp->helpTopicAction(ONLINEPAGE_SAMPLE_FILES);
3226 #ifdef HAVE_SOFTWARE_UPDATE
3227 void MainWindow::checkForUpdates()
3229 software_update_check();
3233 void MainWindow::on_actionHelpAbout_triggered()
3235 AboutDialog *about_dialog = new AboutDialog(this);
3237 if (about_dialog->isMinimized() == true)
3239 about_dialog->showNormal();
3243 about_dialog->show();
3246 about_dialog->raise();
3247 about_dialog->activateWindow();
3250 void MainWindow::on_actionGoGoToPacket_triggered() {
3251 if (packet_list_->model()->rowCount() < 1) {
3254 previous_focus_ = wsApp->focusWidget();
3255 connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
3257 showAccordionFrame(main_ui_->goToFrame, true);
3258 if (main_ui_->goToFrame->isVisible()) {
3259 main_ui_->goToLineEdit->clear();
3260 main_ui_->goToLineEdit->setFocus();
3264 void MainWindow::on_actionGoGoToLinkedPacket_triggered()
3266 QAction *gta = qobject_cast<QAction*>(sender());
3270 int packet_num = gta->data().toInt(&ok);
3273 packet_list_->goToPacket(packet_num);
3276 void MainWindow::on_actionGoAutoScroll_toggled(bool checked)
3278 packet_list_->setAutoScroll(checked);
3281 void MainWindow::resetPreviousFocus() {
3282 previous_focus_ = NULL;
3285 void MainWindow::on_goToCancel_clicked()
3287 main_ui_->goToFrame->animatedHide();
3288 if (previous_focus_) {
3289 disconnect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
3290 previous_focus_->setFocus();
3291 resetPreviousFocus();
3295 void MainWindow::on_goToGo_clicked()
3297 gotoFrame(main_ui_->goToLineEdit->text().toInt());
3299 on_goToCancel_clicked();
3302 void MainWindow::on_goToLineEdit_returnPressed()
3304 on_goToGo_clicked();
3307 void MainWindow::on_actionCaptureStart_triggered()
3309 //#ifdef HAVE_AIRPCAP
3310 // airpcap_if_active = airpcap_if_selected;
3311 // if (airpcap_if_active)
3312 // airpcap_set_toolbar_start_capture(airpcap_if_active);
3315 // if (cap_open_w) {
3317 // * There's an options dialog; get the values from it and close it.
3319 // gboolean success;
3321 // /* Determine if "capture start" while building of the "capture options" window */
3322 // /* is in progress. If so, ignore the "capture start. */
3323 // /* XXX: Would it be better/cleaner for the "capture options" window code to */
3324 // /* disable the capture start button temporarily ? */
3325 // if (cap_open_complete == FALSE) {
3326 // return; /* Building options window: ignore "capture start" */
3328 // success = capture_dlg_prep(cap_open_w);
3329 // window_destroy(GTK_WIDGET(cap_open_w));
3331 // return; /* error in options dialog */
3335 if (global_capture_opts.num_selected == 0) {
3336 QString err_msg = tr("No Interface Selected");
3337 main_ui_->statusBar->pushTemporaryStatus(err_msg);
3338 main_ui_->actionCaptureStart->setChecked(false);
3342 /* XXX - will closing this remove a temporary file? */
3343 QString before_what(tr(" before starting a new capture"));
3344 if (testCaptureFileClose(FALSE, before_what)) {
3347 // simply clicking the button sets it to 'checked' even though we've
3348 // decided to do nothing, so undo that
3349 main_ui_->actionCaptureStart->setChecked(false);
3351 #endif // HAVE_LIBPCAP
3354 void MainWindow::on_actionCaptureStop_triggered()
3359 void MainWindow::on_actionCaptureRestart_triggered()
3361 /* TODO: GTK use only this: capture_restart(&cap_session_); */
3366 static FilterDialog *capture_filter_dlg_ = NULL;
3367 void MainWindow::on_actionCaptureCaptureFilters_triggered()
3369 if (!capture_filter_dlg_) {
3370 capture_filter_dlg_ = new FilterDialog(this, FilterDialog::CaptureFilter);
3372 capture_filter_dlg_->show();
3373 capture_filter_dlg_->raise();
3374 capture_filter_dlg_->activateWindow();
3377 void MainWindow::on_actionStatisticsCaptureFileProperties_triggered()
3379 CaptureFilePropertiesDialog *capture_file_properties_dialog = new CaptureFilePropertiesDialog(*this, capture_file_);
3380 connect(capture_file_properties_dialog, SIGNAL(captureCommentChanged()),
3381 this, SLOT(updateForUnsavedChanges()));
3382 capture_file_properties_dialog->show();
3385 void MainWindow::on_actionStatisticsResolvedAddresses_triggered()
3387 ResolvedAddressesDialog *resolved_addresses_dialog = new ResolvedAddressesDialog(this, &capture_file_);
3388 resolved_addresses_dialog->show();
3391 void MainWindow::on_actionStatisticsProtocolHierarchy_triggered()
3393 ProtocolHierarchyDialog *phd = new ProtocolHierarchyDialog(*this, capture_file_);
3394 connect(phd, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
3395 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
3400 void MainWindow::on_actionCaptureOptions_triggered()
3402 connect(&capture_interfaces_dialog_, SIGNAL(setFilterValid(bool)), this, SLOT(startInterfaceCapture(bool)));
3403 capture_interfaces_dialog_.SetTab(0);
3404 capture_interfaces_dialog_.updateInterfaces();
3406 if (capture_interfaces_dialog_.isMinimized() == true)
3408 capture_interfaces_dialog_.showNormal();
3412 capture_interfaces_dialog_.show();
3415 capture_interfaces_dialog_.raise();
3416 capture_interfaces_dialog_.activateWindow();
3419 void MainWindow::on_actionCaptureRefreshInterfaces_triggered()
3421 wsApp->refreshLocalInterfaces();
3425 void MainWindow::externalMenuItem_triggered()
3427 QAction * triggerAction = NULL;
3429 ext_menubar_t * entry = NULL;
3431 if ( QObject::sender() != NULL)
3433 triggerAction = (QAction *)QObject::sender();
3434 v = triggerAction->data();
3436 if ( v.canConvert<void *>())
3438 entry = (ext_menubar_t *)v.value<void *>();
3440 if ( entry->type == EXT_MENUBAR_ITEM )
3442 entry->callback(EXT_MENUBAR_QT_GUI, (gpointer) ((void *)main_ui_), entry->user_data);
3446 QDesktopServices::openUrl(QUrl(QString((gchar *)entry->user_data)));
3452 void MainWindow::gotoFrame(int packet_num)
3454 if ( packet_num > 0 )
3456 packet_list_->goToPacket(packet_num);
3461 void MainWindow::extcap_options_finished(int result)
3463 if ( result == QDialog::Accepted )
3467 this->main_welcome_->getInterfaceTree()->interfaceListChanged();
3470 void MainWindow::showExtcapOptionsDialog(QString &device_name)
3472 ExtcapOptionsDialog * extcap_options_dialog = ExtcapOptionsDialog::createForDevice(device_name, this);
3473 /* The dialog returns null, if the given device name is not a valid extcap device */
3474 if ( extcap_options_dialog != NULL )
3476 connect(extcap_options_dialog, SIGNAL(finished(int)),
3477 this, SLOT(extcap_options_finished(int)));
3478 extcap_options_dialog->show();
3483 // Q_DECLARE_METATYPE(field_info *) called in proto_tree.h
3485 void MainWindow::on_actionContextCopyBytesHexTextDump_triggered()
3487 QAction *ca = qobject_cast<QAction*>(sender());
3490 field_info *fi = ca->data().value<field_info *>();
3492 byte_view_tab_->copyData(ByteViewTab::copyDataHexTextDump, fi);
3495 void MainWindow::on_actionContextCopyBytesHexDump_triggered()
3497 QAction *ca = qobject_cast<QAction*>(sender());
3500 field_info *fi = ca->data().value<field_info *>();
3502 byte_view_tab_->copyData(ByteViewTab::copyDataHexDump, fi);
3505 void MainWindow::on_actionContextCopyBytesPrintableText_triggered()
3507 QAction *ca = qobject_cast<QAction*>(sender());
3510 field_info *fi = ca->data().value<field_info *>();
3512 byte_view_tab_->copyData(ByteViewTab::copyDataPrintableText, fi);
3515 void MainWindow::on_actionContextCopyBytesHexStream_triggered()
3517 QAction *ca = qobject_cast<QAction*>(sender());
3520 field_info *fi = ca->data().value<field_info *>();
3522 byte_view_tab_->copyData(ByteViewTab::copyDataHexStream, fi);
3525 void MainWindow::on_actionContextCopyBytesBinary_triggered()
3527 QAction *ca = qobject_cast<QAction*>(sender());
3530 field_info *fi = ca->data().value<field_info *>();
3532 byte_view_tab_->copyData(ByteViewTab::copyDataBinary, fi);
3535 void MainWindow::on_actionContextWikiProtocolPage_triggered()
3537 QAction *wa = qobject_cast<QAction*>(sender());
3541 int field_id = wa->data().toInt(&ok);
3544 const QString proto_abbrev = proto_registrar_get_abbrev(field_id);
3546 int ret = QMessageBox::question(this, wsApp->windowTitleString(tr("Wiki Page for %1").arg(proto_abbrev)),
3547 tr("<p>The Wireshark Wiki is maintained by the community.</p>"
3548 "<p>The page you are about to load might be wonderful, "
3549 "incomplete, wrong, or nonexistent.</p>"
3550 "<p>Proceed to the wiki?</p>"),
3551 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
3553 if (ret != QMessageBox::Yes) return;
3555 QUrl wiki_url = QString("https://wiki.wireshark.org/Protocols/%1").arg(proto_abbrev);
3556 QDesktopServices::openUrl(wiki_url);
3559 void MainWindow::on_actionContextFilterFieldReference_triggered()
3561 QAction *wa = qobject_cast<QAction*>(sender());
3565 int field_id = wa->data().toInt(&ok);
3568 const QString proto_abbrev = proto_registrar_get_abbrev(field_id);
3570 QUrl dfref_url = QString("https://www.wireshark.org/docs/dfref/%1/%2")
3571 .arg(proto_abbrev[0])
3573 QDesktopServices::openUrl(dfref_url);
3577 #pragma warning(pop)
3586 * indent-tabs-mode: nil
3589 * ex: set shiftwidth=4 tabstop=8 expandtab:
3590 * :indentSize=4:tabSize=8:noTabs=true: