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.
32 // Qt 5.5.0 + Visual C++ 2013
35 #pragma warning(disable:4996)
38 #include "main_window.h"
39 #include <ui_main_window.h>
47 #include "ui/capture.h"
50 #include "color_filters.h"
52 #include "wsutil/file_util.h"
53 #include "wsutil/filesystem.h"
54 #include <wsutil/str_util.h>
56 #include "epan/addr_resolv.h"
57 #include "epan/dissector_filters.h"
58 #include "epan/column.h"
59 #include "epan/dfilter/dfilter-macro.h"
60 #include "epan/epan_dissect.h"
61 #include "epan/filter_expressions.h"
62 #include "epan/prefs.h"
64 #include "epan/value_string.h"
67 #include <epan/wslua/init_wslua.h>
70 #include "ui/alert_box.h"
72 #include "ui/capture_ui_utils.h"
75 #include "ui/capture_globals.h"
76 #include "ui/help_url.h"
77 #include "ui/main_statusbar.h"
78 #include "ui/preference_utils.h"
79 #include "ui/recent.h"
80 #include "ui/recent_utils.h"
81 #include "ui/ssl_key_export.h"
82 #include "ui/ui_util.h"
83 #include "ui/qt/simple_dialog.h"
85 #ifdef HAVE_SOFTWARE_UPDATE
86 #include "ui/software_update.h"
89 #include "about_dialog.h"
90 #include "bluetooth_att_server_attributes_dialog.h"
91 #include "bluetooth_devices_dialog.h"
92 #include "bluetooth_hci_summary_dialog.h"
93 #include "capture_file_dialog.h"
94 #include "capture_file_properties_dialog.h"
95 #include "color_utils.h"
96 #include "coloring_rules_dialog.h"
97 #include "conversation_dialog.h"
98 #include "conversation_hash_tables_dialog.h"
99 #include "enabled_protocols_dialog.h"
100 #include "decode_as_dialog.h"
101 #include "display_filter_edit.h"
102 #include "display_filter_expression_dialog.h"
103 #include "dissector_tables_dialog.h"
104 #include "endpoint_dialog.h"
105 #include "expert_info_dialog.h"
106 #include "export_object_dialog.h"
107 #include "export_pdu_dialog.h"
109 #include "extcap_options_dialog.h"
111 #include "filter_action.h"
112 #include "filter_dialog.h"
113 #include "funnel_statistics.h"
114 #include "gsm_map_summary_dialog.h"
115 #include "iax2_analysis_dialog.h"
116 #include "io_graph_dialog.h"
117 #include "lbm_stream_dialog.h"
118 #include "lbm_uimflow_dialog.h"
119 #include "lbm_lbtrm_transport_dialog.h"
120 #include "lbm_lbtru_transport_dialog.h"
121 #include "lte_mac_statistics_dialog.h"
122 #include "lte_rlc_statistics_dialog.h"
123 #include "lte_rlc_graph_dialog.h"
124 #include "mtp3_summary_dialog.h"
125 #include "multicast_statistics_dialog.h"
126 #include "packet_comment_dialog.h"
127 #include "packet_dialog.h"
128 #include "packet_list.h"
129 #include "preferences_dialog.h"
130 #include "print_dialog.h"
131 #include "profile_dialog.h"
132 #include "protocol_hierarchy_dialog.h"
133 #include "qt_ui_utils.h"
134 #include "resolved_addresses_dialog.h"
135 #include "rpc_service_response_time_dialog.h"
136 #include "rtp_stream_dialog.h"
137 #include "rtp_analysis_dialog.h"
138 #include "sctp_all_assocs_dialog.h"
139 #include "sctp_assoc_analyse_dialog.h"
140 #include "sctp_graph_dialog.h"
141 #include "sequence_dialog.h"
142 #include "stats_tree_dialog.h"
143 #include "stock_icon.h"
144 #include "supported_protocols_dialog.h"
145 #include "tap_parameter_dialog.h"
146 #include "tcp_stream_dialog.h"
147 #include "time_shift_dialog.h"
148 #include "uat_dialog.h"
149 #include "voip_calls_dialog.h"
150 #include "wireshark_application.h"
151 #include "wlan_statistics_dialog.h"
153 #include <QClipboard>
155 #include <QMessageBox>
156 #include <QMetaObject>
158 #include <QDesktopServices>
166 static const char *dfe_property_ = "display filter expression"; //TODO : Fix Translate
168 // We're too lazy to sublcass QAction.
169 static const char *color_number_property_ = "color number";
171 bool MainWindow::openCaptureFile(QString cf_path, QString read_filter, unsigned int type)
173 QString file_name = "";
174 dfilter_t *rfcode = NULL;
179 // was a file name given as function parameter?
180 name_param = !cf_path.isEmpty();
184 if (cf_path.isEmpty()) {
185 CaptureFileDialog open_dlg(this, capture_file_.capFile(), read_filter);
187 switch (prefs.gui_fileopen_style) {
189 case FO_STYLE_LAST_OPENED:
190 /* The user has specified that we should start out in the last directory
191 we looked in. If we've already opened a file, use its containing
192 directory, if we could determine it, as the directory, otherwise
193 use the "last opened" directory saved in the preferences file if
195 /* This is now the default behaviour in file_selection_new() */
198 case FO_STYLE_SPECIFIED:
199 /* The user has specified that we should always start out in a
200 specified directory; if they've specified that directory,
201 start out by showing the files in that dir. */
202 if (prefs.gui_fileopen_dir[0] != '\0')
203 open_dlg.setDirectory(prefs.gui_fileopen_dir);
207 if (open_dlg.open(file_name, type)) {
214 if (!testCaptureFileClose(false)) {
218 if (dfilter_compile(read_filter.toUtf8().constData(), &rfcode, &err_msg)) {
219 cf_set_rfcode(CaptureFile::globalCapFile(), rfcode);
221 /* Not valid. Tell the user, and go back and run the file
222 selection box again once they dismiss the alert. */
223 //bad_dfilter_alert_box(top_level, read_filter->str);
224 QMessageBox::warning(this, tr("Invalid Display Filter"),
225 QString("The filter expression ") +
227 QString(" isn't a valid display filter. (") +
228 err_msg + QString(")."),
232 // go back to the selection dialogue only if the file
233 // was selected from this dialogue
239 /* Try to open the capture file. This closes the current file if it succeeds. */
240 CaptureFile::globalCapFile()->window = this;
241 if (cf_open(CaptureFile::globalCapFile(), cf_path.toUtf8().constData(), type, FALSE, &err) != CF_OK) {
242 /* We couldn't open it; don't dismiss the open dialog box,
243 just leave it around so that the user can, after they
244 dismiss the alert box popped up for the open error,
246 CaptureFile::globalCapFile()->window = NULL;
248 dfilter_free(rfcode);
253 switch (cf_read(CaptureFile::globalCapFile(), FALSE)) {
257 /* Just because we got an error, that doesn't mean we were unable
258 to read any of the file; we handle what we could get from the
262 case CF_READ_ABORTED:
263 /* The user bailed out of re-reading the capture file; the
264 capture file has been closed - just free the capture file name
265 string and return (without changing the last containing
267 capture_file_.setCapFile(NULL);
272 // get_dirname overwrites its path. Hopefully this isn't a problem.
273 wsApp->setLastOpenDir(get_dirname(cf_path.toUtf8().data()));
275 main_ui_->statusBar->showExpert();
280 void MainWindow::filterPackets(QString new_filter, bool force)
282 cf_status_t cf_status;
284 cf_status = cf_filter_packets(CaptureFile::globalCapFile(), new_filter.toUtf8().data(), force);
286 if (cf_status == CF_OK) {
287 emit displayFilterSuccess(true);
288 if (new_filter.length() > 0) {
289 int index = df_combo_box_->findText(new_filter);
291 df_combo_box_->insertItem(0, new_filter);
292 df_combo_box_->setCurrentIndex(0);
294 df_combo_box_->setCurrentIndex(index);
297 df_combo_box_->lineEdit()->clear();
300 emit displayFilterSuccess(false);
304 // A new layout should be applied when it differs from the old layout AND
305 // at the following times:
307 // - When the preferences change
308 // - When the profile changes
309 void MainWindow::layoutPanes()
311 QVector<unsigned> new_layout = QVector<unsigned>() << prefs.gui_layout_type
312 << prefs.gui_layout_content_1
313 << prefs.gui_layout_content_2
314 << prefs.gui_layout_content_3;
315 if (cur_layout_ == new_layout) return;
317 QSplitter *parents[3];
318 int current_row = capture_file_.currentRow();
320 // Reparent all widgets and add them back in the proper order below.
321 // This hides each widget as well.
322 packet_list_->freeze(); // Clears tree and byte view tabs.
323 packet_list_->setParent(main_ui_->mainStack);
324 proto_tree_->setParent(main_ui_->mainStack);
325 byte_view_tab_->setParent(main_ui_->mainStack);
326 empty_pane_.setParent(main_ui_->mainStack);
327 extra_split_.setParent(main_ui_->mainStack);
329 // XXX We should try to preserve geometries if we can, e.g. by
330 // checking to see if the layout type is the same.
331 switch(prefs.gui_layout_type) {
334 extra_split_.setOrientation(Qt::Horizontal);
337 master_split_.setOrientation(Qt::Vertical);
342 extra_split_.setOrientation(Qt::Vertical);
345 master_split_.setOrientation(Qt::Horizontal);
349 g_assert_not_reached();
352 switch(prefs.gui_layout_type) {
355 parents[0] = &master_split_;
356 parents[1] = &master_split_;
357 parents[2] = &master_split_;
361 parents[0] = &master_split_;
362 parents[1] = &extra_split_;
363 parents[2] = &extra_split_;
367 parents[0] = &extra_split_;
368 parents[1] = &extra_split_;
369 parents[2] = &master_split_;
372 g_assert_not_reached();
375 if (parents[0] == &extra_split_) {
376 master_split_.addWidget(&extra_split_);
379 parents[0]->addWidget(getLayoutWidget(prefs.gui_layout_content_1));
381 if (parents[2] == &extra_split_) {
382 master_split_.addWidget(&extra_split_);
385 parents[1]->addWidget(getLayoutWidget(prefs.gui_layout_content_2));
386 parents[2]->addWidget(getLayoutWidget(prefs.gui_layout_content_3));
388 const QList<QWidget *> ms_children = master_split_.findChildren<QWidget *>();
390 extra_split_.setVisible(ms_children.contains(&extra_split_));
391 packet_list_->setVisible(ms_children.contains(packet_list_) && recent.packet_list_show);
392 proto_tree_->setVisible(ms_children.contains(proto_tree_) && recent.tree_view_show);
393 byte_view_tab_->setVisible(ms_children.contains(byte_view_tab_) && recent.byte_view_show);
395 packet_list_->thaw();
396 cf_select_packet(capture_file_.capFile(), current_row); // XXX Doesn't work for row 0?
397 cur_layout_ = new_layout;
400 // The recent layout geometry should be applied after the layout has been
401 // applied AND at the following times:
403 // - When the profile changes
404 void MainWindow::applyRecentPaneGeometry()
406 // XXX This shrinks slightly each time the application is run. For some
407 // reason the master_split_ geometry is two pixels shorter when
408 // saveWindowGeometry is invoked.
410 // This is also an awful lot of trouble to go through to reuse the GTK+
411 // pane settings. We might want to add gui.geometry_main_master_sizes
412 // and gui.geometry_main_extra_sizes and save QSplitter::saveState in
415 // Force a geometry recalculation
416 QWidget *cur_w = main_ui_->mainStack->currentWidget();
417 main_ui_->mainStack->setCurrentWidget(&master_split_);
418 QRect geom = master_split_.geometry();
419 QList<int> master_sizes = master_split_.sizes();
420 QList<int> extra_sizes = extra_split_.sizes();
421 main_ui_->mainStack->setCurrentWidget(cur_w);
423 int master_last_size = master_split_.orientation() == Qt::Vertical ? geom.height() : geom.width();
424 int extra_last_size = extra_split_.orientation() == Qt::Vertical ? geom.height() : geom.width();
426 if (recent.gui_geometry_main_upper_pane > 0) {
427 master_sizes[0] = recent.gui_geometry_main_upper_pane + 1; // Add back mystery pixel
428 master_last_size -= recent.gui_geometry_main_upper_pane + master_split_.handleWidth();
431 if (recent.gui_geometry_main_lower_pane > 0) {
432 if (master_sizes.length() > 2) {
433 master_sizes[1] = recent.gui_geometry_main_lower_pane + 1; // Add back mystery pixel
434 master_last_size -= recent.gui_geometry_main_lower_pane + master_split_.handleWidth();
435 } else if (extra_sizes.length() > 0) {
436 extra_sizes[0] = recent.gui_geometry_main_lower_pane; // No mystery pixel
437 extra_last_size -= recent.gui_geometry_main_lower_pane + extra_split_.handleWidth();
438 extra_sizes.last() = extra_last_size;
442 master_sizes.last() = master_last_size;
444 master_split_.setSizes(master_sizes);
445 extra_split_.setSizes(extra_sizes);
448 void MainWindow::layoutToolbars()
450 Qt::ToolButtonStyle tbstyle = Qt::ToolButtonIconOnly;
451 switch (prefs.gui_toolbar_main_style) {
453 tbstyle = Qt::ToolButtonTextOnly;
456 tbstyle = Qt::ToolButtonTextUnderIcon;
460 main_ui_->mainToolBar->setToolButtonStyle(tbstyle);
463 void MainWindow::updatePreferenceActions()
465 main_ui_->actionViewNameResolutionPhysical->setChecked(gbl_resolv_flags.mac_name);
466 main_ui_->actionViewNameResolutionNetwork->setChecked(gbl_resolv_flags.network_name);
467 main_ui_->actionViewNameResolutionTransport->setChecked(gbl_resolv_flags.transport_name);
469 // Should this be a "recent" setting?
470 main_ui_->actionGoAutoScroll->setChecked(prefs.capture_auto_scroll);
473 void MainWindow::filterAction(QString &action_filter, FilterAction::Action action, FilterAction::ActionType type)
475 QString cur_filter, new_filter;
477 if (!df_combo_box_) return;
478 cur_filter = df_combo_box_->lineEdit()->text();
481 case FilterAction::ActionTypePlain:
482 new_filter = action_filter;
484 case FilterAction::ActionTypeAnd:
485 if (cur_filter.length()) {
486 new_filter = "(" + cur_filter + ") && (" + action_filter + ")";
488 new_filter = action_filter;
491 case FilterAction::ActionTypeOr:
492 if (cur_filter.length()) {
493 new_filter = "(" + cur_filter + ") || (" + action_filter + ")";
495 new_filter = action_filter;
498 case FilterAction::ActionTypeNot:
499 new_filter = "!(" + action_filter + ")";
501 case FilterAction::ActionTypeAndNot:
502 if (cur_filter.length()) {
503 new_filter = "(" + cur_filter + ") && !(" + action_filter + ")";
505 new_filter = "!(" + action_filter + ")";
508 case FilterAction::ActionTypeOrNot:
509 if (cur_filter.length()) {
510 new_filter = "(" + cur_filter + ") || !(" + action_filter + ")";
512 new_filter = "!(" + action_filter + ")";
516 g_assert_not_reached();
521 case FilterAction::ActionApply:
522 df_combo_box_->lineEdit()->setText(new_filter);
523 df_combo_box_->applyDisplayFilter();
525 case FilterAction::ActionPrepare:
526 df_combo_box_->lineEdit()->setText(new_filter);
527 df_combo_box_->lineEdit()->setFocus();
529 case FilterAction::ActionWebLookup:
531 QString url = QString("https://www.google.com/search?q=") + new_filter;
532 QDesktopServices::openUrl(QUrl(url));
535 case FilterAction::ActionCopy:
536 wsApp->clipboard()->setText(new_filter);
539 qDebug() << "FIX FilterAction::Action" << action << "not implemented";
546 void MainWindow::captureCapturePrepared(capture_session *) {
548 setTitlebarForCaptureInProgress();
550 setWindowIcon(wsApp->captureIcon());
552 /* Disable menu items that make no sense if you're currently running
554 setForCaptureInProgress(true);
555 // set_capture_if_dialog_for_capture_in_progress(TRUE);
557 // /* Don't set up main window for a capture file. */
558 // main_set_for_capture_file(FALSE);
559 main_ui_->mainStack->setCurrentWidget(&master_split_);
560 #endif // HAVE_LIBPCAP
563 void MainWindow::captureCaptureUpdateStarted(capture_session *) {
566 /* We've done this in "prepared" above, but it will be cleared while
567 switching to the next multiple file. */
568 setTitlebarForCaptureInProgress();
570 setForCaptureInProgress(true);
572 setForCapturedPackets(true);
573 #endif // HAVE_LIBPCAP
575 void MainWindow::captureCaptureUpdateFinished(capture_session *) {
578 /* The capture isn't stopping any more - it's stopped. */
579 capture_stopping_ = false;
581 /* Update the main window as appropriate */
582 updateForUnsavedChanges();
584 /* Enable menu items that make sense if you're not currently running
586 setForCaptureInProgress(false);
588 setWindowIcon(wsApp->normalIcon());
590 if (global_capture_opts.quit_after_cap) {
591 // Command line asked us to quit after capturing.
592 // Don't pop up a dialog to ask for unsaved files etc.
595 #endif // HAVE_LIBPCAP
597 void MainWindow::captureCaptureFixedStarted(capture_session *) {
599 #endif // HAVE_LIBPCAP
601 void MainWindow::captureCaptureFixedFinished(capture_session *) {
604 /* The capture isn't stopping any more - it's stopped. */
605 capture_stopping_ = false;
607 /* Enable menu items that make sense if you're not currently running
609 setForCaptureInProgress(false);
611 setWindowIcon(wsApp->normalIcon());
613 if (global_capture_opts.quit_after_cap) {
614 // Command line asked us to quit after capturing.
615 // Don't pop up a dialog to ask for unsaved files etc.
618 #endif // HAVE_LIBPCAP
620 void MainWindow::captureCaptureStopping(capture_session *) {
623 capture_stopping_ = true;
624 setMenusForCaptureStopping();
625 #endif // HAVE_LIBPCAP
627 void MainWindow::captureCaptureFailed(capture_session *) {
629 /* Capture isn't stopping any more. */
630 capture_stopping_ = false;
632 setForCaptureInProgress(false);
633 main_ui_->mainStack->setCurrentWidget(main_welcome_);
635 setWindowIcon(wsApp->normalIcon());
637 if (global_capture_opts.quit_after_cap) {
638 // Command line asked us to quit after capturing.
639 // Don't pop up a dialog to ask for unsaved files etc.
642 #endif // HAVE_LIBPCAP
646 // Callbacks from cfile.c and file.c via CaptureFile::captureFileCallback
648 void MainWindow::captureFileOpened() {
649 if (capture_file_.window() != this) return;
651 file_set_dialog_.fileOpened(capture_file_.capFile());
652 setMenusForFileSet(true);
653 emit setCaptureFile(capture_file_.capFile());
656 void MainWindow::captureFileReadStarted(const QString &action) {
657 // tap_param_dlg_update();
659 /* Set up main window for a capture file. */
660 // main_set_for_capture_file(TRUE);
662 main_ui_->statusBar->popFileStatus();
663 QString msg = QString(tr("%1: %2")).arg(action).arg(capture_file_.fileName());
664 QString msgtip = QString();
665 main_ui_->statusBar->pushFileStatus(msg, msgtip);
666 main_ui_->mainStack->setCurrentWidget(&master_split_);
667 WiresharkApplication::processEvents();
670 void MainWindow::captureFileReadFinished() {
673 if (!capture_file_.capFile()->is_tempfile && capture_file_.capFile()->filename) {
674 /* Add this filename to the list of recent files in the "Recent Files" submenu */
675 add_menu_recent_capture_file(capture_file_.capFile()->filename);
677 /* Remember folder for next Open dialog and save it in recent */
678 dir_path = get_dirname(g_strdup(capture_file_.capFile()->filename));
679 wsApp->setLastOpenDir(dir_path);
683 /* Update the appropriate parts of the main window. */
684 updateForUnsavedChanges();
686 /* Enable menu items that make sense if you have some captured packets. */
687 setForCapturedPackets(true);
689 main_ui_->statusBar->setFileName(capture_file_);
691 packet_list_->captureFileReadFinished();
693 emit setDissectedCaptureFile(capture_file_.capFile());
696 // Our event loop becomes nested whenever we call update_progress_dlg, which
697 // includes several places in file.c. The GTK+ UI stays out of trouble by
698 // showing a modal progress dialog. We attempt to do the equivalent below by
699 // disabling parts of the main window. At a minumum the ProgressFrame in the
700 // main status bar must remain accessible.
702 // We might want to do this any time the main status bar progress frame is
704 void MainWindow::captureFileRetapStarted()
706 // XXX Push a status message?
707 main_ui_->actionFileClose->setEnabled(false);
708 main_ui_->actionViewReload->setEnabled(false);
709 main_ui_->centralWidget->setEnabled(false);
712 void MainWindow::captureFileRetapFinished()
714 main_ui_->actionFileClose->setEnabled(true);
715 main_ui_->actionViewReload->setEnabled(true);
716 main_ui_->centralWidget->setEnabled(true);
719 void MainWindow::captureFileClosing() {
720 setMenusForCaptureFile(true);
721 setForCapturedPackets(false);
722 setMenusForSelectedPacket();
723 setForCaptureInProgress(false);
725 // Reset expert information indicator
726 main_ui_->statusBar->captureFileClosing();
727 main_ui_->searchFrame->animatedHide();
728 // gtk_widget_show(expert_info_none);
729 emit setCaptureFile(NULL);
730 emit setDissectedCaptureFile(NULL);
733 void MainWindow::captureFileClosed() {
734 packets_bar_update();
736 file_set_dialog_.fileClosed();
737 setMenusForFileSet(false);
739 // Reset expert information indicator
740 main_ui_->statusBar->captureFileClosing();
742 main_ui_->statusBar->popFileStatus();
744 setTitlebarForSelectedTreeRow();
745 setMenusForSelectedTreeRow();
747 if (!global_capture_opts.multi_files_on)
748 main_ui_->mainStack->setCurrentWidget(main_welcome_);
751 void MainWindow::captureFileSaveStarted(const QString &file_path)
753 QFileInfo file_info(file_path);
754 main_ui_->statusBar->popFileStatus();
755 main_ui_->statusBar->pushFileStatus(tr("Saving %1" UTF8_HORIZONTAL_ELLIPSIS).arg(file_info.baseName()));
758 void MainWindow::filterExpressionsChanged()
760 // Recreate filter buttons
761 foreach (QAction *act, main_ui_->displayFilterToolBar->actions()) {
762 // Permanent actions shouldn't have data
763 if (act->property(dfe_property_).isValid() || act->isSeparator()) {
764 main_ui_->displayFilterToolBar->removeAction(act);
770 for (struct filter_expression *fe = *pfilter_expression_head; fe != NULL; fe = fe->next) {
771 if (!fe->enabled) continue;
772 QAction *dfb_action = new QAction(fe->label, main_ui_->displayFilterToolBar);
773 dfb_action->setToolTip(fe->expression);
774 dfb_action->setData(fe->expression);
775 dfb_action->setProperty(dfe_property_, true);
776 main_ui_->displayFilterToolBar->addAction(dfb_action);
777 connect(dfb_action, SIGNAL(triggered()), this, SLOT(displayFilterButtonClicked()));
780 main_ui_->displayFilterToolBar->insertSeparator(dfb_action);
789 // ui/gtk/capture_dlg.c:start_capture_confirmed
791 void MainWindow::startCapture() {
793 interface_options interface_opts;
796 /* did the user ever select a capture interface before? */
797 if(global_capture_opts.num_selected == 0) {
798 QString msg = QString(tr("No interface selected"));
799 main_ui_->statusBar->pushTemporaryStatus(msg);
800 main_ui_->actionCaptureStart->setChecked(false);
804 main_ui_->mainStack->setCurrentWidget(&master_split_);
806 // Ideally we should have disabled the start capture
807 // toolbar buttons and menu items. This may not be the
808 // case, e.g. with QtMacExtras.
809 if(!capture_filter_valid_) {
810 QString msg = QString(tr("Invalid capture filter"));
811 main_ui_->statusBar->pushTemporaryStatus(msg);
812 main_ui_->actionCaptureStart->setChecked(false);
816 /* XXX - we might need to init other pref data as well... */
818 /* XXX - can this ever happen? */
819 if (cap_session_.state != CAPTURE_STOPPED)
822 /* close the currently loaded capture file */
823 cf_close((capture_file *) cap_session_.cf);
825 /* Copy the selected interfaces to the set of interfaces to use for
827 collect_ifaces(&global_capture_opts);
829 CaptureFile::globalCapFile()->window = this;
830 if (capture_start(&global_capture_opts, &cap_session_, main_window_update)) {
831 capture_options *capture_opts = cap_session_.capture_opts;
832 GString *interface_names;
834 /* enable autoscroll timer as needed. */
835 packet_list_->setAutoScroll(main_ui_->actionGoAutoScroll->isChecked());
837 /* Add "interface name<live capture in progress>" on main status bar */
838 interface_names = get_iface_list_string(capture_opts, 0);
839 if (strlen (interface_names->str) > 0) {
840 g_string_append(interface_names, ":");
842 g_string_append(interface_names, " ");
844 main_ui_->statusBar->popFileStatus();
845 QString msg = QString().sprintf("%s<live capture in progress>", interface_names->str);
846 QString msgtip = QString().sprintf("to file: %s", (capture_opts->save_file) ? capture_opts->save_file : "");
847 main_ui_->statusBar->pushFileStatus(msg, msgtip);
848 g_string_free(interface_names, TRUE);
850 /* The capture succeeded, which means the capture filter syntax is
851 valid; add this capture filter to the recent capture filter list. */
852 for (i = 0; i < global_capture_opts.ifaces->len; i++) {
853 interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
854 if (interface_opts.cfilter) {
855 // cfilter_combo_add_recent(interface_opts.cfilter);
859 CaptureFile::globalCapFile()->window = NULL;
861 #endif // HAVE_LIBPCAP
864 // Copied from ui/gtk/gui_utils.c
865 void MainWindow::pipeTimeout() {
869 gboolean result, result1;
874 /* try to read data from the pipe only 5 times, to avoid blocking */
875 while(iterations < 5) {
876 /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: new iteration");*/
878 /* Oddly enough although Named pipes don't work on win9x,
879 PeekNamedPipe does !!! */
880 handle = (HANDLE) _get_osfhandle (pipe_source_);
881 result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
883 /* Get the child process exit status */
884 result1 = GetExitCodeProcess((HANDLE)*(pipe_child_process_),
887 /* If the Peek returned an error, or there are bytes to be read
888 or the childwatcher thread has terminated then call the normal
890 if (!result || avail > 0 || childstatus != STILL_ACTIVE) {
892 /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: data avail");*/
894 /* And call the real handler */
895 if (!pipe_input_cb_(pipe_source_, pipe_user_data_)) {
896 g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: input pipe closed, iterations: %u", iterations);
897 /* pipe closed, return false so that the old timer is not run again */
903 /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: no data avail");*/
904 /* No data, stop now */
913 void MainWindow::pipeActivated(int source) {
917 g_assert(source == pipe_source_);
919 pipe_notifier_->setEnabled(false);
920 if (pipe_input_cb_(pipe_source_, pipe_user_data_)) {
921 pipe_notifier_->setEnabled(true);
923 delete pipe_notifier_;
928 void MainWindow::pipeNotifierDestroyed() {
932 pipe_notifier_ = NULL;
936 void MainWindow::stopCapture() {
937 //#ifdef HAVE_AIRPCAP
938 // if (airpcap_if_active)
939 // airpcap_set_toolbar_stop_capture(airpcap_if_active);
943 capture_stop(&cap_session_);
944 #endif // HAVE_LIBPCAP
946 /* Pop the "<live capture in progress>" message off the status bar. */
947 main_ui_->statusBar->setFileName(capture_file_);
949 /* disable autoscroll timer if any. */
950 packet_list_->setAutoScroll(false);
953 // Keep focus rects from showing through the welcome screen. Primarily for
955 void MainWindow::mainStackChanged(int)
957 for (int i = 0; i < main_ui_->mainStack->count(); i++) {
958 main_ui_->mainStack->widget(i)->setEnabled(i == main_ui_->mainStack->currentIndex());
962 // XXX - Copied from ui/gtk/menus.c
965 * Add the capture filename (with an absolute path) to the "Recent Files" menu.
967 // XXX - We should probably create a RecentFile class.
968 void MainWindow::updateRecentFiles() {
970 QMenu *recentMenu = main_ui_->menuOpenRecentCaptureFile;
971 QString action_cf_name;
979 /* Iterate through the actions in menuOpenRecentCaptureFile,
980 * removing special items, a maybe duplicate entry and every item above count_max */
981 int shortcut = Qt::Key_0;
982 foreach (recent_item_status *ri, wsApp->recentItems()) {
984 ra = new QAction(recentMenu);
985 ra->setData(ri->filename);
986 // XXX - Needs get_recent_item_status or equivalent
987 ra->setEnabled(ri->accessible);
988 recentMenu->insertAction(NULL, ra);
989 action_cf_name = ra->data().toString();
990 if (shortcut <= Qt::Key_9) {
991 ra->setShortcut(Qt::META | shortcut);
994 ra->setText(action_cf_name);
995 connect(ra, SIGNAL(triggered()), this, SLOT(recentActionTriggered()));
998 if (recentMenu->actions().count() > 0) {
999 // Separator + "Clear"
1000 // XXX - Do we really need this?
1001 ra = new QAction(recentMenu);
1002 ra->setSeparator(true);
1003 recentMenu->insertAction(NULL, ra);
1005 ra = new QAction(recentMenu);
1006 ra->setText(tr("Clear Menu"));
1007 recentMenu->insertAction(NULL, ra);
1008 connect(ra, SIGNAL(triggered()), wsApp, SLOT(clearRecentItems()));
1010 if (main_ui_->actionDummyNoFilesFound) {
1011 recentMenu->addAction(main_ui_->actionDummyNoFilesFound);
1016 void MainWindow::recentActionTriggered() {
1017 QAction *ra = qobject_cast<QAction*>(sender());
1020 QString cfPath = ra->data().toString();
1021 openCaptureFile(cfPath);
1025 void MainWindow::setMenusForSelectedPacket()
1027 gboolean is_ip = FALSE, is_tcp = FALSE, is_udp = FALSE, is_sctp = FALSE, is_ssl = FALSE, is_rtp = FALSE, is_lte_rlc = FALSE;
1029 /* Making the menu context-sensitive allows for easier selection of the
1030 desired item and has the added benefit, with large captures, of
1031 avoiding needless looping through huge lists for marked, ignored,
1032 or time-referenced packets. */
1034 /* We have one or more items in the packet list */
1035 bool have_frames = false;
1036 /* A frame is selected */
1037 bool frame_selected = false;
1038 /* We have marked frames. (XXX - why check frame_selected?) */
1039 bool have_marked = false;
1040 /* We have a marked frame other than the current frame (i.e.,
1041 we have at least one marked frame, and either there's more
1042 than one marked frame or the current frame isn't marked). */
1043 bool another_is_marked = false;
1044 /* One or more frames are hidden by a display filter */
1045 bool have_filtered = false;
1046 /* One or more frames have been ignored */
1047 bool have_ignored = false;
1048 bool have_time_ref = false;
1049 /* We have a time reference frame other than the current frame (i.e.,
1050 we have at least one time reference frame, and either there's more
1051 than one time reference frame or the current frame isn't a
1052 time reference frame). (XXX - why check frame_selected?) */
1053 bool another_is_time_ref = false;
1054 /* We have a valid filter expression */
1055 bool have_filter_expr = false;
1057 QList<QAction *> cc_actions = QList<QAction *>()
1058 << main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
1059 << main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
1060 << main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
1061 << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
1062 << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
1064 if (capture_file_.capFile()) {
1065 frame_selected = capture_file_.capFile()->current_frame != NULL;
1066 have_frames = capture_file_.capFile()->count > 0;
1067 have_marked = frame_selected && capture_file_.capFile()->marked_count > 0;
1068 another_is_marked = have_marked &&
1069 !(capture_file_.capFile()->marked_count == 1 && capture_file_.capFile()->current_frame->flags.marked);
1070 have_filtered = capture_file_.capFile()->displayed_count > 0 && capture_file_.capFile()->displayed_count != capture_file_.capFile()->count;
1071 have_ignored = capture_file_.capFile()->ignored_count > 0;
1072 have_time_ref = capture_file_.capFile()->ref_time_count > 0;
1073 another_is_time_ref = frame_selected && have_time_ref &&
1074 !(capture_file_.capFile()->ref_time_count == 1 && capture_file_.capFile()->current_frame->flags.ref_time);
1076 if (capture_file_.capFile()->edt)
1078 proto_get_frame_protocols(capture_file_.capFile()->edt->pi.layers,
1079 &is_ip, &is_tcp, &is_udp, &is_sctp,
1080 &is_ssl, &is_rtp, &is_lte_rlc);
1084 have_filter_expr = !packet_list_->getFilterFromRowAndColumn().isEmpty();
1086 main_ui_->actionEditMarkPacket->setEnabled(frame_selected);
1087 main_ui_->actionEditMarkAllDisplayed->setEnabled(have_frames);
1088 /* Unlike un-ignore, do not allow unmark of all frames when no frames are displayed */
1089 main_ui_->actionEditUnmarkAllDisplayed->setEnabled(have_marked);
1090 main_ui_->actionEditNextMark->setEnabled(another_is_marked);
1091 main_ui_->actionEditPreviousMark->setEnabled(another_is_marked);
1093 #ifdef WANT_PACKET_EDITOR
1094 // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/EditPacket",
1096 #endif // WANT_PACKET_EDITOR
1097 main_ui_->actionEditPacketComment->setEnabled(frame_selected && wtap_dump_can_write(capture_file_.capFile()->linktypes, WTAP_COMMENT_PER_PACKET));
1099 main_ui_->actionEditIgnorePacket->setEnabled(frame_selected);
1100 main_ui_->actionEditIgnoreAllDisplayed->setEnabled(have_filtered);
1101 /* Allow un-ignore of all frames even with no frames currently displayed */
1102 main_ui_->actionEditUnignoreAllDisplayed->setEnabled(have_ignored);
1104 main_ui_->actionEditSetTimeReference->setEnabled(frame_selected);
1105 main_ui_->actionEditUnsetAllTimeReferences->setEnabled(have_time_ref);
1106 main_ui_->actionEditNextTimeReference->setEnabled(another_is_time_ref);
1107 main_ui_->actionEditPreviousTimeReference->setEnabled(another_is_time_ref);
1108 main_ui_->actionEditTimeShift->setEnabled(have_frames);
1110 main_ui_->actionGoGoToLinkedPacket->setEnabled(false);
1112 main_ui_->actionAnalyzeAAFSelected->setEnabled(have_filter_expr);
1113 main_ui_->actionAnalyzeAAFNotSelected->setEnabled(have_filter_expr);
1114 main_ui_->actionAnalyzeAAFAndSelected->setEnabled(have_filter_expr);
1115 main_ui_->actionAnalyzeAAFOrSelected->setEnabled(have_filter_expr);
1116 main_ui_->actionAnalyzeAAFAndNotSelected->setEnabled(have_filter_expr);
1117 main_ui_->actionAnalyzeAAFOrNotSelected->setEnabled(have_filter_expr);
1119 main_ui_->actionAnalyzePAFSelected->setEnabled(have_filter_expr);
1120 main_ui_->actionAnalyzePAFNotSelected->setEnabled(have_filter_expr);
1121 main_ui_->actionAnalyzePAFAndSelected->setEnabled(have_filter_expr);
1122 main_ui_->actionAnalyzePAFOrSelected->setEnabled(have_filter_expr);
1123 main_ui_->actionAnalyzePAFAndNotSelected->setEnabled(have_filter_expr);
1124 main_ui_->actionAnalyzePAFOrNotSelected->setEnabled(have_filter_expr);
1126 main_ui_->actionAnalyzeFollowTCPStream->setEnabled(is_tcp);
1127 main_ui_->actionAnalyzeFollowUDPStream->setEnabled(is_udp);
1128 main_ui_->actionAnalyzeFollowSSLStream->setEnabled(is_ssl);
1130 foreach (QAction *cc_action, cc_actions) {
1131 cc_action->setEnabled(frame_selected);
1133 main_ui_->actionViewColorizeNewConversationRule->setEnabled(frame_selected);
1135 main_ui_->actionViewColorizeResetColorization->setEnabled(tmp_color_filters_used());
1137 main_ui_->actionViewColorizeNewConversationRule->setEnabled(frame_selected);
1139 main_ui_->actionViewShowPacketInNewWindow->setEnabled(frame_selected);
1140 main_ui_->actionViewEditResolvedName->setEnabled(frame_selected && is_ip);
1142 main_ui_->menuConversationFilter->clear();
1144 packet_list_->conversationMenu()->clear();
1145 packet_list_->colorizeMenu()->clear();
1147 for (GList *conv_filter_list_entry = conv_filter_list; conv_filter_list_entry; conv_filter_list_entry = g_list_next(conv_filter_list_entry)) {
1149 conversation_filter_t* conv_filter = (conversation_filter_t *)conv_filter_list_entry->data;
1150 QAction *conv_action = main_ui_->menuConversationFilter->addAction(conv_filter->display_name);
1152 bool enable = false;
1154 if (capture_file_.capFile()->edt) {
1155 enable = conv_filter->is_filter_valid(&capture_file_.capFile()->edt->pi);
1156 filter = gchar_free_to_qstring(conv_filter->build_filter_string(&capture_file_.capFile()->edt->pi));
1158 conv_action->setEnabled(enable);
1159 conv_action->setData(filter);
1160 connect(conv_action, SIGNAL(triggered()), this, SLOT(applyConversationFilter()));
1162 // Packet list context menu items
1163 packet_list_->conversationMenu()->addAction(conv_action);
1165 QMenu *submenu = packet_list_->colorizeMenu()->addMenu(conv_action->text());
1167 foreach (QAction *cc_action, cc_actions) {
1168 QAction *colorize_action = submenu->addAction(cc_action->icon(), cc_action->text());
1169 colorize_action->setProperty(color_number_property_, i++);
1170 colorize_action->setData(filter);
1171 colorize_action->setEnabled(enable);
1172 connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1175 QAction *conv_rule_action = submenu->addAction(main_ui_->actionViewColorizeNewConversationRule->text());
1176 conv_rule_action->setData(conv_action->data());
1177 conv_rule_action->setEnabled(enable);
1178 connect(conv_rule_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1181 // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ViewMenu/NameResolution/ResolveName",
1182 // frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
1183 // gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns));
1184 // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ToolsMenu/FirewallACLRules",
1186 main_ui_->menuTcpStreamGraphs->setEnabled(is_tcp);
1187 main_ui_->actionSCTPAnalyseThisAssociation->setEnabled(is_sctp);
1188 main_ui_->actionSCTPShowAllAssociations->setEnabled(is_sctp);
1189 main_ui_->actionSCTPFilterThisAssociation->setEnabled(is_sctp);
1190 main_ui_->actionTelephonyRTPStreamAnalysis->setEnabled(is_rtp);
1191 main_ui_->actionTelephonyLteRlcGraph->setEnabled(is_lte_rlc);
1194 void MainWindow::setMenusForSelectedTreeRow(field_info *fi) {
1196 bool can_match_selected = false;
1197 bool is_framenum = false;
1198 bool have_field_info = false;
1199 bool have_subtree = false;
1200 bool can_open_url = false;
1201 QString field_filter;
1204 QList<QAction *> cc_actions = QList<QAction *>()
1205 << main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
1206 << main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
1207 << main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
1208 << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
1209 << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
1211 if (capture_file_.capFile()) {
1212 capture_file_.capFile()->finfo_selected = fi;
1214 if (fi && fi->tree_type != -1) {
1215 have_subtree = true;
1219 if (capture_file_.capFile() != NULL && fi != NULL) {
1220 header_field_info *hfinfo = fi->hfinfo;
1221 int linked_frame = -1;
1223 have_field_info = true;
1224 can_match_selected = proto_can_match_selected(capture_file_.capFile()->finfo_selected, capture_file_.capFile()->edt);
1225 if (hfinfo && hfinfo->type == FT_FRAMENUM) {
1227 linked_frame = fvalue_get_uinteger(&fi->value);
1230 char *tmp_field = proto_construct_match_selected_string(fi, capture_file_.capFile()->edt);
1231 field_filter = QString(tmp_field);
1232 wmem_free(NULL, tmp_field);
1234 field_id = fi->hfinfo->id;
1235 /* if the selected field isn't a protocol, get its parent */
1236 if (!proto_registrar_is_protocol(field_id)) {
1237 field_id = proto_registrar_get_parent(fi->hfinfo->id);
1240 if (field_id >= 0) {
1241 can_open_url = true;
1242 main_ui_->actionContextWikiProtocolPage->setData(field_id);
1243 main_ui_->actionContextFilterFieldReference->setData(field_id);
1245 main_ui_->actionContextWikiProtocolPage->setData(QVariant());
1246 main_ui_->actionContextFilterFieldReference->setData(QVariant());
1249 if (linked_frame > 0) {
1250 main_ui_->actionGoGoToLinkedPacket->setData(linked_frame);
1252 main_ui_->actionGoGoToLinkedPacket->setData(QVariant());
1256 // Always enable / disable the following items.
1257 main_ui_->actionFileExportPacketBytes->setEnabled(have_field_info);
1259 main_ui_->actionCopyAllVisibleItems->setEnabled(capture_file_.capFile() != NULL);
1260 main_ui_->actionCopyAllVisibleSelectedTreeItems->setEnabled(can_match_selected);
1261 main_ui_->actionEditCopyDescription->setEnabled(can_match_selected);
1262 main_ui_->actionEditCopyFieldName->setEnabled(can_match_selected);
1263 main_ui_->actionEditCopyValue->setEnabled(can_match_selected);
1264 main_ui_->actionEditCopyAsFilter->setEnabled(can_match_selected);
1266 main_ui_->actionViewExpandSubtrees->setEnabled(have_subtree);
1268 main_ui_->actionGoGoToLinkedPacket->setEnabled(is_framenum);
1270 main_ui_->actionAnalyzeCreateAColumn->setEnabled(can_match_selected);
1272 main_ui_->actionContextShowLinkedPacketInNewWindow->setEnabled(is_framenum);
1274 main_ui_->actionContextWikiProtocolPage->setEnabled(can_open_url);
1275 main_ui_->actionContextFilterFieldReference->setEnabled(can_open_url);
1278 // Only enable / disable the following items if we have focus so that we
1279 // don't clobber anything we may have set in setMenusForSelectedPacket.
1280 if (!proto_tree_ || !proto_tree_->hasFocus()) return;
1282 main_ui_->menuConversationFilter->clear();
1283 for (GList *conv_filter_list_entry = conv_filter_list; conv_filter_list_entry; conv_filter_list_entry = g_list_next(conv_filter_list_entry)) {
1284 conversation_filter_t* conv_filter = (conversation_filter_t *)conv_filter_list_entry->data;
1285 QAction *conv_action = main_ui_->menuConversationFilter->addAction(conv_filter->display_name);
1287 bool enable = false;
1289 if (capture_file_.capFile() && capture_file_.capFile()->edt) {
1290 enable = conv_filter->is_filter_valid(&capture_file_.capFile()->edt->pi);
1291 filter = conv_filter->build_filter_string(&capture_file_.capFile()->edt->pi);
1293 conv_action->setEnabled(enable);
1294 conv_action->setData(filter);
1295 connect(conv_action, SIGNAL(triggered()), this, SLOT(applyConversationFilter()));
1298 proto_tree_->colorizeMenu()->clear();
1300 foreach (QAction *cc_action, cc_actions) {
1301 QAction *colorize_action = proto_tree_->colorizeMenu()->addAction(cc_action->icon(), cc_action->text());
1302 colorize_action->setProperty(color_number_property_, i++);
1303 colorize_action->setData(field_filter);
1304 colorize_action->setEnabled(!field_filter.isEmpty());
1305 connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1308 QAction *conv_rule_action = proto_tree_->colorizeMenu()->addAction(main_ui_->actionViewColorizeNewConversationRule->text());
1309 conv_rule_action->setData(field_filter);
1310 conv_rule_action->setEnabled(!field_filter.isEmpty());
1311 connect(conv_rule_action, SIGNAL(triggered()), this, SLOT(colorizeWithFilter()));
1313 // set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ResolveName",
1314 // frame_selected && (gbl_resolv_flags.mac_name || gbl_resolv_flags.network_name ||
1315 // gbl_resolv_flags.transport_name || gbl_resolv_flags.concurrent_dns));
1318 main_ui_->actionAnalyzeAAFSelected->setEnabled(can_match_selected);
1319 main_ui_->actionAnalyzeAAFNotSelected->setEnabled(can_match_selected);
1320 main_ui_->actionAnalyzeAAFAndSelected->setEnabled(can_match_selected);
1321 main_ui_->actionAnalyzeAAFOrSelected->setEnabled(can_match_selected);
1322 main_ui_->actionAnalyzeAAFAndNotSelected->setEnabled(can_match_selected);
1323 main_ui_->actionAnalyzeAAFOrNotSelected->setEnabled(can_match_selected);
1325 main_ui_->actionAnalyzePAFSelected->setEnabled(can_match_selected);
1326 main_ui_->actionAnalyzePAFNotSelected->setEnabled(can_match_selected);
1327 main_ui_->actionAnalyzePAFAndSelected->setEnabled(can_match_selected);
1328 main_ui_->actionAnalyzePAFOrSelected->setEnabled(can_match_selected);
1329 main_ui_->actionAnalyzePAFAndNotSelected->setEnabled(can_match_selected);
1330 main_ui_->actionAnalyzePAFOrNotSelected->setEnabled(can_match_selected);
1333 void MainWindow::interfaceSelectionChanged()
1336 // XXX This doesn't disable the toolbar button when using
1338 if (global_capture_opts.num_selected > 0 && capture_filter_valid_) {
1339 main_ui_->actionCaptureStart->setEnabled(true);
1341 main_ui_->actionCaptureStart->setEnabled(false);
1343 #endif // HAVE_LIBPCAP
1346 void MainWindow::captureFilterSyntaxChanged(bool valid)
1348 capture_filter_valid_ = valid;
1349 interfaceSelectionChanged();
1352 void MainWindow::startInterfaceCapture(bool valid)
1354 capture_filter_valid_ = valid;
1358 void MainWindow::redissectPackets()
1360 if (capture_file_.capFile())
1361 cf_redissect_packets(capture_file_.capFile());
1362 main_ui_->statusBar->expertUpdate();
1364 proto_free_deregistered_fields();
1367 void MainWindow::fieldsChanged()
1369 color_filters_reload();
1370 tap_listeners_dfilter_recompile();
1372 if (!df_combo_box_->checkDisplayFilter()) {
1373 g_free(CaptureFile::globalCapFile()->dfilter);
1374 CaptureFile::globalCapFile()->dfilter = NULL;
1377 if (have_custom_cols(&CaptureFile::globalCapFile()->cinfo)) {
1378 // Recreate packet list columns according to new/changed/deleted fields
1379 packet_list_->fieldsChanged(CaptureFile::globalCapFile());
1382 emit reloadFields();
1385 void MainWindow::showAccordionFrame(AccordionFrame *show_frame, bool toggle)
1387 QList<AccordionFrame *>frame_list = QList<AccordionFrame *>()
1388 << main_ui_->goToFrame << main_ui_->searchFrame
1389 << main_ui_->addressEditorFrame << main_ui_->columnEditorFrame
1390 << main_ui_->preferenceEditorFrame;
1392 frame_list.removeAll(show_frame);
1393 foreach (AccordionFrame *af, frame_list) af->animatedHide();
1396 if (show_frame->isVisible()) {
1397 show_frame->animatedHide();
1401 show_frame->animatedShow();
1404 void MainWindow::showColumnEditor(int column)
1406 previous_focus_ = wsApp->focusWidget();
1407 connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
1408 showAccordionFrame(main_ui_->columnEditorFrame);
1409 main_ui_->columnEditorFrame->editColumn(column);
1412 void MainWindow::showPreferenceEditor()
1414 showAccordionFrame(main_ui_->preferenceEditorFrame);
1417 void MainWindow::initViewColorizeMenu()
1419 QList<QAction *> cc_actions = QList<QAction *>()
1420 << main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
1421 << main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
1422 << main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
1423 << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
1424 << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
1426 guint8 color_num = 1;
1428 foreach (QAction *cc_action, cc_actions) {
1429 cc_action->setData(color_num);
1430 connect(cc_action, SIGNAL(triggered()), this, SLOT(colorizeConversation()));
1432 const color_filter_t *colorf = color_filters_tmp_color(color_num);
1434 QColor bg = ColorUtils::fromColorT(colorf->bg_color);
1435 QColor fg = ColorUtils::fromColorT(colorf->fg_color);
1436 cc_action->setIcon(StockIcon::colorIcon(bg.rgb(), fg.rgb(), QString::number(color_num)));
1442 // Spotlight uses Cmd+Space
1443 main_ui_->actionViewColorizeResetColorization->setShortcut(QKeySequence("Meta+Space"));
1447 void MainWindow::addStatsPluginsToMenu() {
1448 GList *cfg_list = stats_tree_get_cfg_list();
1449 GList *iter = g_list_first(cfg_list);
1450 QAction *stats_tree_action;
1452 bool first_item = true;
1455 stats_tree_cfg *cfg = (stats_tree_cfg*)iter->data;
1458 main_ui_->menuStatistics->addSeparator();
1462 parent_menu = main_ui_->menuStatistics;
1463 // gtk/main_menubar.c compresses double slashes, hence SkipEmptyParts
1464 QStringList cfg_name_parts = QString(cfg->name).split("/", QString::SkipEmptyParts);
1465 if (cfg_name_parts.isEmpty()) continue;
1467 QString stat_name = cfg_name_parts.takeLast();
1468 if (!cfg_name_parts.isEmpty()) {
1469 QString menu_name = cfg_name_parts.join("/");
1470 parent_menu = findOrAddMenu(parent_menu, menu_name);
1473 stats_tree_action = new QAction(stat_name, this);
1474 stats_tree_action->setData(cfg->abbr);
1475 parent_menu->addAction(stats_tree_action);
1476 connect(stats_tree_action, SIGNAL(triggered()), this, SLOT(actionStatisticsPlugin_triggered()));
1478 iter = g_list_next(iter);
1480 g_list_free(cfg_list);
1483 void MainWindow::setFeaturesEnabled(bool enabled)
1485 main_ui_->menuBar->setEnabled(enabled);
1486 main_ui_->mainToolBar->setEnabled(enabled);
1487 main_ui_->displayFilterToolBar->setEnabled(enabled);
1490 main_ui_->statusBar->clearMessage();
1494 main_ui_->statusBar->showMessage(tr("Please wait while Wireshark is initializing" UTF8_HORIZONTAL_ELLIPSIS));
1498 // Display Filter Toolbar
1500 void MainWindow::on_actionDisplayFilterExpression_triggered()
1502 DisplayFilterExpressionDialog *dfe_dialog = new DisplayFilterExpressionDialog(this);
1504 connect(dfe_dialog, SIGNAL(insertDisplayFilter(QString)),
1505 df_combo_box_->lineEdit(), SLOT(insertFilter(const QString &)));
1510 // On Qt4 + OS X with unifiedTitleAndToolBarOnMac set it's possible to make
1511 // the main window obnoxiously wide.
1513 void MainWindow::displayFilterButtonClicked()
1515 QAction *dfb_action = qobject_cast<QAction*>(sender());
1518 df_combo_box_->lineEdit()->setText(dfb_action->data().toString());
1519 df_combo_box_->applyDisplayFilter();
1520 df_combo_box_->lineEdit()->setFocus();
1524 void MainWindow::openStatCommandDialog(const QString &menu_path, const char *arg, void *userdata)
1526 QString slot = QString("statCommand%1").arg(menu_path);
1527 QMetaObject::invokeMethod(this, slot.toLatin1().constData(), Q_ARG(const char *, arg), Q_ARG(void *, userdata));
1530 void MainWindow::openTapParameterDialog(const QString cfg_str, const QString arg, void *userdata)
1532 TapParameterDialog *tp_dialog = TapParameterDialog::showTapParameterStatistics(*this, capture_file_, cfg_str, arg, userdata);
1533 if (!tp_dialog) return;
1535 connect(tp_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
1536 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
1537 connect(tp_dialog, SIGNAL(updateFilter(QString)),
1538 df_combo_box_->lineEdit(), SLOT(setText(QString)));
1542 void MainWindow::openTapParameterDialog()
1544 QAction *tpa = qobject_cast<QAction *>(QObject::sender());
1547 const QString cfg_str = tpa->data().toString();
1548 openTapParameterDialog(cfg_str, NULL, NULL);
1553 void MainWindow::on_actionFileOpen_triggered()
1558 void MainWindow::on_actionFileMerge_triggered()
1563 void MainWindow::on_actionFileImportFromHexDump_triggered()
1565 importCaptureFile();
1568 void MainWindow::on_actionFileClose_triggered() {
1569 if (testCaptureFileClose())
1570 main_ui_->mainStack->setCurrentWidget(main_welcome_);
1573 void MainWindow::on_actionFileSave_triggered()
1575 saveCaptureFile(capture_file_.capFile(), FALSE);
1578 void MainWindow::on_actionFileSaveAs_triggered()
1580 saveAsCaptureFile(capture_file_.capFile());
1583 void MainWindow::on_actionFileSetListFiles_triggered()
1585 file_set_dialog_.exec();
1588 void MainWindow::on_actionFileSetNextFile_triggered()
1590 fileset_entry *entry = fileset_get_next();
1593 QString new_cf_path = entry->fullname;
1594 openCaptureFile(new_cf_path);
1598 void MainWindow::on_actionFileSetPreviousFile_triggered()
1600 fileset_entry *entry = fileset_get_previous();
1603 QString new_cf_path = entry->fullname;
1604 openCaptureFile(new_cf_path);
1608 void MainWindow::on_actionFileExportPackets_triggered()
1610 exportSelectedPackets();
1613 void MainWindow::on_actionFileExportAsPlainText_triggered()
1615 exportDissections(export_type_text);
1618 void MainWindow::on_actionFileExportAsCSV_triggered()
1620 exportDissections(export_type_csv);
1623 void MainWindow::on_actionFileExportAsCArrays_triggered()
1625 exportDissections(export_type_carrays);
1628 void MainWindow::on_actionFileExportAsPSML_triggered()
1630 exportDissections(export_type_psml);
1633 void MainWindow::on_actionFileExportAsPDML_triggered()
1635 exportDissections(export_type_pdml);
1638 void MainWindow::on_actionFileExportPacketBytes_triggered()
1642 if (!capture_file_.capFile() || !capture_file_.capFile()->finfo_selected) return;
1644 file_name = QFileDialog::getSaveFileName(this,
1645 wsApp->windowTitleString(tr("Export Selected Packet Bytes")),
1646 wsApp->lastOpenDir().canonicalPath(),
1647 tr("Raw data (*.bin *.dat *.raw);;Any File (*.*)")
1650 if (file_name.length() > 0) {
1651 const guint8 *data_p;
1654 data_p = tvb_get_ptr(capture_file_.capFile()->finfo_selected->ds_tvb, 0, -1) +
1655 capture_file_.capFile()->finfo_selected->start;
1656 fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
1658 open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
1661 if (write(fd, data_p, capture_file_.capFile()->finfo_selected->length) < 0) {
1662 write_failure_alert_box(file_name.toUtf8().constData(), errno);
1666 if (::close(fd) < 0) {
1667 write_failure_alert_box(file_name.toUtf8().constData(), errno);
1671 /* Save the directory name for future file dialogs. */
1672 wsApp->setLastOpenDir(&file_name);
1675 void MainWindow::on_actionFileExportPDU_triggered()
1677 ExportPDUDialog *exportpdu_dialog = new ExportPDUDialog(this);
1679 if (exportpdu_dialog->isMinimized() == true)
1681 exportpdu_dialog->showNormal();
1685 exportpdu_dialog->show();
1688 exportpdu_dialog->raise();
1689 exportpdu_dialog->activateWindow();
1692 void MainWindow::on_actionFileExportSSLSessionKeys_triggered()
1698 keylist_len = ssl_session_key_count();
1699 /* don't show up the dialog, if no data has to be saved */
1700 if (keylist_len < 1) {
1701 /* shouldn't happen as the menu item should have been greyed out */
1702 QMessageBox::warning(
1705 tr("There are no SSL Session Keys to save."),
1711 save_title.append(wsApp->windowTitleString(tr("Export SSL Session Keys (%1 key%2").
1712 arg(keylist_len).arg(plurality(keylist_len, "", "s"))));
1713 file_name = QFileDialog::getSaveFileName(this,
1715 wsApp->lastOpenDir().canonicalPath(),
1716 tr("SSL Session Keys (*.keys *.txt);;Any File (*.*)")
1718 if (file_name.length() > 0) {
1722 keylist = ssl_export_sessions();
1723 fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
1725 open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
1730 * Thanks, Microsoft, for not using size_t for the third argument to
1731 * _write(). Presumably this string will be <= 4GiB long....
1733 if (ws_write(fd, keylist, (unsigned int)strlen(keylist)) < 0) {
1734 write_failure_alert_box(file_name.toUtf8().constData(), errno);
1739 if (::close(fd) < 0) {
1740 write_failure_alert_box(file_name.toUtf8().constData(), errno);
1745 /* Save the directory name for future file dialogs. */
1746 wsApp->setLastOpenDir(&file_name);
1751 void MainWindow::on_actionFileExportObjectsDICOM_triggered()
1753 new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Dicom);
1756 void MainWindow::on_actionStatisticsHpfeeds_triggered()
1758 openStatisticsTreeDialog("hpfeeds");
1761 void MainWindow::on_actionFileExportObjectsHTTP_triggered()
1763 new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Http);
1766 void MainWindow::on_actionFileExportObjectsSMB_triggered()
1768 new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Smb);
1771 void MainWindow::on_actionFileExportObjectsTFTP_triggered()
1773 new ExportObjectDialog(*this, capture_file_, ExportObjectDialog::Tftp);
1776 void MainWindow::on_actionFilePrint_triggered()
1778 PrintDialog pdlg(this, capture_file_.capFile());
1785 void MainWindow::recursiveCopyProtoTreeItems(QTreeWidgetItem *item, QString &clip, int ident_level) {
1786 if (!item->isExpanded()) return;
1788 for (int i_item = 0; i_item < item->childCount(); i_item += 1) {
1789 clip.append(QString(" ").repeated(ident_level));
1790 clip.append(item->child(i_item)->text(0));
1793 recursiveCopyProtoTreeItems(item->child(i_item), clip, ident_level + 1);
1797 // XXX This should probably be somewhere else.
1798 void MainWindow::actionEditCopyTriggered(MainWindow::CopySelected selection_type)
1800 char label_str[ITEM_LABEL_LENGTH];
1803 if (!capture_file_.capFile()) return;
1805 field_info *finfo_selected = capture_file_.capFile()->finfo_selected;
1807 switch(selection_type) {
1808 case CopySelectedDescription:
1809 if (finfo_selected && finfo_selected->rep
1810 && strlen (finfo_selected->rep->representation) > 0) {
1811 clip.append(finfo_selected->rep->representation);
1814 case CopySelectedFieldName:
1815 if (finfo_selected && finfo_selected->hfinfo->abbrev != 0) {
1816 clip.append(finfo_selected->hfinfo->abbrev);
1819 case CopySelectedValue:
1820 if (finfo_selected && capture_file_.capFile()->edt != 0) {
1821 gchar* field_str = get_node_field_value(finfo_selected, capture_file_.capFile()->edt);
1822 clip.append(field_str);
1826 case CopyAllVisibleItems:
1827 for (int i_item = 0; i_item < proto_tree_->topLevelItemCount(); i_item += 1) {
1828 clip.append(proto_tree_->topLevelItem(i_item)->text(0));
1831 recursiveCopyProtoTreeItems(proto_tree_->topLevelItem(i_item), clip, 1);
1835 case CopyAllVisibleSelectedTreeItems:
1836 if (proto_tree_->selectedItems().count() > 0) {
1837 clip.append(proto_tree_->currentItem()->text(0));
1840 recursiveCopyProtoTreeItems(proto_tree_->currentItem(), clip, 1);
1845 if (clip.length() == 0) {
1846 /* If no representation then... Try to read the value */
1847 proto_item_fill_label(capture_file_.capFile()->finfo_selected, label_str);
1848 clip.append(label_str);
1851 if (clip.length()) {
1852 wsApp->clipboard()->setText(clip);
1854 QString err = tr("Couldn't copy text. Try another item.");
1855 main_ui_->statusBar->pushTemporaryStatus(err);
1859 void MainWindow::on_actionCopyAllVisibleItems_triggered()
1861 actionEditCopyTriggered(CopyAllVisibleItems);
1864 void MainWindow::on_actionCopyAllVisibleSelectedTreeItems_triggered()
1866 actionEditCopyTriggered(CopyAllVisibleSelectedTreeItems);
1869 void MainWindow::on_actionEditCopyDescription_triggered()
1871 actionEditCopyTriggered(CopySelectedDescription);
1874 void MainWindow::on_actionEditCopyFieldName_triggered()
1876 actionEditCopyTriggered(CopySelectedFieldName);
1879 void MainWindow::on_actionEditCopyValue_triggered()
1881 actionEditCopyTriggered(CopySelectedValue);
1884 void MainWindow::on_actionEditCopyAsFilter_triggered()
1886 matchFieldFilter(FilterAction::ActionCopy, FilterAction::ActionTypePlain);
1889 void MainWindow::on_actionEditFindPacket_triggered()
1891 if (packet_list_->model()->rowCount() < 1) {
1894 previous_focus_ = wsApp->focusWidget();
1895 connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
1896 showAccordionFrame(main_ui_->searchFrame, true);
1899 void MainWindow::on_actionEditFindNext_triggered()
1901 main_ui_->searchFrame->findNext();
1904 void MainWindow::on_actionEditFindPrevious_triggered()
1906 main_ui_->searchFrame->findPrevious();
1909 void MainWindow::on_actionEditMarkPacket_triggered()
1911 packet_list_->markFrame();
1914 void MainWindow::on_actionEditMarkAllDisplayed_triggered()
1916 packet_list_->markAllDisplayedFrames(true);
1919 void MainWindow::on_actionEditUnmarkAllDisplayed_triggered()
1921 packet_list_->markAllDisplayedFrames(false);
1924 void MainWindow::on_actionEditNextMark_triggered()
1926 if (capture_file_.capFile())
1927 cf_find_packet_marked(capture_file_.capFile(), SD_FORWARD);
1930 void MainWindow::on_actionEditPreviousMark_triggered()
1932 if (capture_file_.capFile())
1933 cf_find_packet_marked(capture_file_.capFile(), SD_BACKWARD);
1936 void MainWindow::on_actionEditIgnorePacket_triggered()
1938 packet_list_->ignoreFrame();
1941 void MainWindow::on_actionEditIgnoreAllDisplayed_triggered()
1943 packet_list_->ignoreAllDisplayedFrames(true);
1946 void MainWindow::on_actionEditUnignoreAllDisplayed_triggered()
1948 packet_list_->ignoreAllDisplayedFrames(false);
1951 void MainWindow::on_actionEditSetTimeReference_triggered()
1953 packet_list_->setTimeReference();
1956 void MainWindow::on_actionEditUnsetAllTimeReferences_triggered()
1958 packet_list_->unsetAllTimeReferences();
1961 void MainWindow::on_actionEditNextTimeReference_triggered()
1963 if (!capture_file_.capFile()) return;
1964 cf_find_packet_time_reference(capture_file_.capFile(), SD_FORWARD);
1967 void MainWindow::on_actionEditPreviousTimeReference_triggered()
1969 if (!capture_file_.capFile()) return;
1970 cf_find_packet_time_reference(capture_file_.capFile(), SD_BACKWARD);
1973 void MainWindow::on_actionEditTimeShift_triggered()
1975 TimeShiftDialog ts_dialog(this, capture_file_.capFile());
1976 connect(this, SIGNAL(setCaptureFile(capture_file*)),
1977 &ts_dialog, SLOT(setCaptureFile(capture_file*)));
1978 connect(&ts_dialog, SIGNAL(timeShifted()), packet_list_, SLOT(applyTimeShift()));
1982 void MainWindow::on_actionEditPacketComment_triggered()
1984 PacketCommentDialog pc_dialog(this, packet_list_->packetComment());
1985 if (pc_dialog.exec() == QDialog::Accepted) {
1986 packet_list_->setPacketComment(pc_dialog.text());
1987 updateForUnsavedChanges();
1991 void MainWindow::on_actionEditConfigurationProfiles_triggered()
1993 ProfileDialog cp_dialog;
1998 void MainWindow::showPreferencesDialog(PreferencesDialog::PreferencesPane start_pane)
2000 PreferencesDialog pref_dialog(this);
2002 pref_dialog.setPane(start_pane);
2005 // Emitting PacketDissectionChanged directly from a QDialog can cause
2006 // problems on OS X.
2007 wsApp->flushAppSignals();
2010 void MainWindow::showPreferencesDialog(QString module_name)
2012 PreferencesDialog pref_dialog(this);
2014 pref_dialog.setPane(module_name);
2017 // Emitting PacketDissectionChanged directly from a QDialog can cause
2018 // problems on OS X.
2019 wsApp->flushAppSignals();
2022 void MainWindow::on_actionEditPreferences_triggered()
2024 showPreferencesDialog();
2029 void MainWindow::showHideMainWidgets(QAction *action)
2034 bool show = action->isChecked();
2035 QWidget *widget = action->data().value<QWidget*>();
2037 // We may have come from the toolbar context menu, so check/uncheck each
2039 if (widget == main_ui_->mainToolBar) {
2040 recent.main_toolbar_show = show;
2041 main_ui_->actionViewMainToolbar->setChecked(show);
2042 } else if (widget == main_ui_->displayFilterToolBar) {
2043 recent.filter_toolbar_show = show;
2044 main_ui_->actionViewFilterToolbar->setChecked(show);
2045 } else if (widget == main_ui_->wirelessToolBar) {
2046 recent.wireless_toolbar_show = show;
2047 main_ui_->actionViewWirelessToolbar->setChecked(show);
2048 } else if (widget == main_ui_->statusBar) {
2049 recent.statusbar_show = show;
2050 main_ui_->actionViewStatusBar->setChecked(show);
2051 } else if (widget == packet_list_) {
2052 recent.packet_list_show = show;
2053 main_ui_->actionViewPacketList->setChecked(show);
2054 } else if (widget == proto_tree_) {
2055 recent.tree_view_show = show;
2056 main_ui_->actionViewPacketDetails->setChecked(show);
2057 } else if (widget == byte_view_tab_) {
2058 recent.byte_view_show = show;
2059 main_ui_->actionViewPacketBytes->setChecked(show);
2063 widget->setVisible(show);
2067 Q_DECLARE_METATYPE(ts_type)
2069 void MainWindow::setTimestampFormat(QAction *action)
2074 ts_type tsf = action->data().value<ts_type>();
2075 if (recent.gui_time_format != tsf) {
2076 timestamp_set_type(tsf);
2077 recent.gui_time_format = tsf;
2078 if (capture_file_.capFile()) {
2079 /* This call adjusts column width */
2080 cf_timestamp_auto_precision(capture_file_.capFile());
2083 packet_list_->columnsChanged();
2088 Q_DECLARE_METATYPE(ts_precision)
2090 void MainWindow::setTimestampPrecision(QAction *action)
2095 ts_precision tsp = action->data().value<ts_precision>();
2096 if (recent.gui_time_precision != tsp) {
2097 /* the actual precision will be set in packet_list_queue_draw() below */
2098 timestamp_set_precision(tsp);
2099 recent.gui_time_precision = tsp;
2100 if (capture_file_.capFile()) {
2101 /* This call adjusts column width */
2102 cf_timestamp_auto_precision(capture_file_.capFile());
2105 packet_list_->columnsChanged();
2110 void MainWindow::on_actionViewTimeDisplaySecondsWithHoursAndMinutes_triggered(bool checked)
2113 recent.gui_seconds_format = TS_SECONDS_HOUR_MIN_SEC;
2115 recent.gui_seconds_format = TS_SECONDS_DEFAULT;
2117 timestamp_set_seconds_type(recent.gui_seconds_format);
2119 if (capture_file_.capFile()) {
2120 /* This call adjusts column width */
2121 cf_timestamp_auto_precision(capture_file_.capFile());
2124 packet_list_->columnsChanged();
2128 void MainWindow::on_actionViewEditResolvedName_triggered()
2130 // int column = packet_list_->selectedColumn();
2133 if (packet_list_->currentIndex().isValid()) {
2134 column = packet_list_->currentIndex().column();
2137 main_ui_->addressEditorFrame->editAddresses(capture_file_, column);
2138 showAccordionFrame(main_ui_->addressEditorFrame);
2141 void MainWindow::setNameResolution()
2143 gbl_resolv_flags.mac_name = main_ui_->actionViewNameResolutionPhysical->isChecked() ? TRUE : FALSE;
2144 gbl_resolv_flags.network_name = main_ui_->actionViewNameResolutionNetwork->isChecked() ? TRUE : FALSE;
2145 gbl_resolv_flags.transport_name = main_ui_->actionViewNameResolutionTransport->isChecked() ? TRUE : FALSE;
2148 packet_list_->columnsChanged();
2152 void MainWindow::on_actionViewNameResolutionPhysical_triggered()
2154 setNameResolution();
2157 void MainWindow::on_actionViewNameResolutionNetwork_triggered()
2159 setNameResolution();
2162 void MainWindow::on_actionViewNameResolutionTransport_triggered()
2164 setNameResolution();
2167 void MainWindow::zoomText()
2169 // Scale by 10%, rounding to nearest half point, minimum 1 point.
2170 // XXX Small sizes repeat. It might just be easier to create a map of multipliers.
2171 mono_font_ = QFont(wsApp->monospaceFont());
2172 qreal zoom_size = wsApp->monospaceFont().pointSize() * 2 * qPow(1.1, recent.gui_zoom_level);
2173 zoom_size = qRound(zoom_size) / 2.0;
2174 zoom_size = qMax(zoom_size, 1.0);
2175 mono_font_.setPointSizeF(zoom_size);
2176 emit monospaceFontChanged(mono_font_);
2179 void MainWindow::on_actionViewZoomIn_triggered()
2181 recent.gui_zoom_level++;
2185 void MainWindow::on_actionViewZoomOut_triggered()
2187 recent.gui_zoom_level--;
2191 void MainWindow::on_actionViewNormalSize_triggered()
2193 recent.gui_zoom_level = 0;
2197 void MainWindow::on_actionViewColorizePacketList_triggered(bool checked) {
2198 recent.packet_list_colorize = checked;
2199 color_filters_enable(checked);
2200 packet_list_->packetListModel()->resetColorized();
2201 packet_list_->update();
2204 void MainWindow::on_actionViewColoringRules_triggered()
2206 ColoringRulesDialog coloring_rules_dialog(this);
2208 coloring_rules_dialog.exec();
2211 // actionViewColorizeConversation1 - 10
2212 void MainWindow::colorizeConversation(bool create_rule)
2214 QAction *cc_action = qobject_cast<QAction *>(sender());
2215 if (!cc_action) return;
2217 if (capture_file_.capFile() && capture_file_.capFile()->current_frame) {
2218 packet_info *pi = &capture_file_.capFile()->edt->pi;
2219 guint8 cc_num = cc_action->data().toUInt();
2220 gchar *filter = NULL;
2222 const conversation_filter_t *color_filter = find_conversation_filter("tcp");
2223 if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2224 filter = color_filter->build_filter_string(pi);
2225 if (filter == NULL) {
2226 color_filter = find_conversation_filter("udp");
2227 if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2228 filter = color_filter->build_filter_string(pi);
2230 if (filter == NULL) {
2231 color_filter = find_conversation_filter("ip");
2232 if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2233 filter = color_filter->build_filter_string(pi);
2235 if (filter == NULL) {
2236 color_filter = find_conversation_filter("ipv6");
2237 if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2238 filter = color_filter->build_filter_string(pi);
2240 if (filter == NULL) {
2241 color_filter = find_conversation_filter("eth");
2242 if ((color_filter != NULL) && (color_filter->is_filter_valid(pi)))
2243 filter = color_filter->build_filter_string(pi);
2245 if( filter == NULL ) {
2246 main_ui_->statusBar->pushTemporaryStatus(tr("Unable to build conversation filter."));
2251 ColoringRulesDialog coloring_rules_dialog(this, filter);
2252 coloring_rules_dialog.exec();
2254 color_filters_set_tmp(cc_num, filter, FALSE);
2255 packet_list_->recolorPackets();
2258 setMenusForSelectedPacket();
2261 void MainWindow::colorizeWithFilter()
2263 QAction *colorize_action = qobject_cast<QAction *>(sender());
2264 if (!colorize_action) return;
2266 QString filter = colorize_action->data().toString();
2267 if (filter.isEmpty()) return;
2270 int color_number = colorize_action->property(color_number_property_).toInt(&ok);
2274 color_filters_set_tmp(color_number, filter.toUtf8().constData(), FALSE);
2275 packet_list_->recolorPackets();
2277 // New coloring rule
2278 ColoringRulesDialog coloring_rules_dialog(window(), filter);
2279 coloring_rules_dialog.exec();
2281 main_ui_->actionViewColorizeResetColorization->setEnabled(tmp_color_filters_used());
2284 void MainWindow::on_actionViewColorizeResetColorization_triggered()
2286 color_filters_reset_tmp();
2287 packet_list_->recolorPackets();
2288 setMenusForSelectedPacket();
2291 void MainWindow::on_actionViewColorizeNewConversationRule_triggered()
2293 colorizeConversation(true);
2296 void MainWindow::on_actionViewResizeColumns_triggered()
2298 for (int col = 0; col < packet_list_->packetListModel()->columnCount(); col++) {
2299 packet_list_->resizeColumnToContents(col);
2300 recent_set_column_width(col, packet_list_->columnWidth(col));
2304 void MainWindow::openPacketDialog(bool from_reference)
2308 /* Find the frame for which we're popping up a dialog */
2309 if(from_reference) {
2310 guint32 framenum = fvalue_get_uinteger(&(capture_file_.capFile()->finfo_selected->value));
2314 fdata = frame_data_sequence_find(capture_file_.capFile()->frames, framenum);
2316 fdata = capture_file_.capFile()->current_frame;
2319 /* If we have a frame, pop up the dialog */
2321 PacketDialog *packet_dialog = new PacketDialog(*this, capture_file_, fdata);
2323 connect(this, SIGNAL(monospaceFontChanged(QFont)),
2324 packet_dialog, SIGNAL(monospaceFontChanged(QFont)));
2325 connect(this, SIGNAL(closePacketDialogs()),
2326 packet_dialog, SLOT(close()));
2327 zoomText(); // Emits monospaceFontChanged
2329 packet_dialog->show();
2333 void MainWindow::on_actionViewInternalsConversationHashTables_triggered()
2335 ConversationHashTablesDialog *conversation_hash_tables_dlg = new ConversationHashTablesDialog(this);
2336 conversation_hash_tables_dlg->show();
2339 void MainWindow::on_actionViewInternalsDissectorTables_triggered()
2341 DissectorTablesDialog *dissector_tables_dlg = new DissectorTablesDialog(this);
2342 dissector_tables_dlg->show();
2345 void MainWindow::on_actionViewInternalsSupportedProtocols_triggered()
2347 SupportedProtocolsDialog *supported_protocols_dlg = new SupportedProtocolsDialog(this);
2348 supported_protocols_dlg->show();
2351 void MainWindow::on_actionViewShowPacketInNewWindow_triggered()
2356 // This is only used in ProtoTree. Defining it here makes more sense.
2357 void MainWindow::on_actionContextShowLinkedPacketInNewWindow_triggered()
2359 openPacketDialog(true);
2362 void MainWindow::on_actionViewReload_triggered()
2364 cf_reload(CaptureFile::globalCapFile());
2367 void MainWindow::on_actionViewReload_as_File_Format_or_Capture_triggered()
2369 capture_file *cf = CaptureFile::globalCapFile();
2371 if (cf->open_type == WTAP_TYPE_AUTO)
2372 cf->open_type = open_info_name_to_type("MIME Files Format");
2373 else /* TODO: This should be latest format chosen by user */
2374 cf->open_type = WTAP_TYPE_AUTO;
2380 // Expand / collapse slots in proto_tree
2386 void MainWindow::matchFieldFilter(FilterAction::Action action, FilterAction::ActionType filter_type)
2388 QString field_filter;
2390 if (packet_list_->contextMenuActive() || packet_list_->hasFocus()) {
2391 field_filter = packet_list_->getFilterFromRowAndColumn();
2392 } else if (capture_file_.capFile() && capture_file_.capFile()->finfo_selected) {
2393 char *tmp_field = proto_construct_match_selected_string(capture_file_.capFile()->finfo_selected,
2394 capture_file_.capFile()->edt);
2395 field_filter = QString(tmp_field);
2396 wmem_free(NULL, tmp_field);
2399 if (field_filter.isEmpty()) {
2400 QString err = tr("No filter available. Try another ");
2401 err.append(packet_list_->contextMenuActive() ? "column" : "item");
2403 main_ui_->statusBar->pushTemporaryStatus(err);
2407 filterAction(field_filter, action, filter_type);
2410 static FilterDialog *display_filter_dlg_ = NULL;
2411 void MainWindow::on_actionAnalyzeDisplayFilters_triggered()
2413 if (!display_filter_dlg_) {
2414 display_filter_dlg_ = new FilterDialog(this, FilterDialog::DisplayFilter);
2416 display_filter_dlg_->show();
2417 display_filter_dlg_->raise();
2418 display_filter_dlg_->activateWindow();
2422 void MainWindow::on_actionAnalyzeDisplayFilterMacros_triggered()
2424 struct epan_uat* dfm_uat;
2425 dfilter_macro_get_uat(&dfm_uat);
2426 UatDialog uat_dlg(parentWidget(), dfm_uat);
2429 // Emitting PacketDissectionChanged directly from a QDialog can cause
2430 // problems on OS X.
2431 wsApp->flushAppSignals();
2434 void MainWindow::on_actionAnalyzeCreateAColumn_triggered()
2438 if ( capture_file_.capFile() != 0 && capture_file_.capFile()->finfo_selected != 0 )
2440 colnr = column_prefs_add_custom(COL_CUSTOM, capture_file_.capFile()->finfo_selected->hfinfo->name,
2441 capture_file_.capFile()->finfo_selected->hfinfo->abbrev,0);
2443 packet_list_->columnsChanged();
2444 packet_list_->resizeColumnToContents(colnr);
2450 void MainWindow::applyConversationFilter()
2452 QAction *cfa = qobject_cast<QAction*>(sender());
2455 QString new_filter = cfa->data().toString();
2456 if (new_filter.isEmpty()) return;
2458 df_combo_box_->lineEdit()->setText(new_filter);
2459 df_combo_box_->applyDisplayFilter();
2462 // XXX We could probably create the analyze and prepare actions
2463 // dynamically using FilterActions and consolidate the methods
2464 // below into one callback.
2465 void MainWindow::on_actionAnalyzeAAFSelected_triggered()
2467 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypePlain);
2470 void MainWindow::on_actionAnalyzeAAFNotSelected_triggered()
2472 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeNot);
2475 void MainWindow::on_actionAnalyzeAAFAndSelected_triggered()
2477 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeAnd);
2480 void MainWindow::on_actionAnalyzeAAFOrSelected_triggered()
2482 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeOr);
2485 void MainWindow::on_actionAnalyzeAAFAndNotSelected_triggered()
2487 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeAndNot);
2490 void MainWindow::on_actionAnalyzeAAFOrNotSelected_triggered()
2492 matchFieldFilter(FilterAction::ActionApply, FilterAction::ActionTypeOrNot);
2495 void MainWindow::on_actionAnalyzePAFSelected_triggered()
2497 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypePlain);
2500 void MainWindow::on_actionAnalyzePAFNotSelected_triggered()
2502 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeNot);
2505 void MainWindow::on_actionAnalyzePAFAndSelected_triggered()
2507 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeAnd);
2510 void MainWindow::on_actionAnalyzePAFOrSelected_triggered()
2512 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeOr);
2515 void MainWindow::on_actionAnalyzePAFAndNotSelected_triggered()
2517 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeAndNot);
2520 void MainWindow::on_actionAnalyzePAFOrNotSelected_triggered()
2522 matchFieldFilter(FilterAction::ActionPrepare, FilterAction::ActionTypeOrNot);
2525 void MainWindow::on_actionAnalyzeEnabledProtocols_triggered()
2527 EnabledProtocolsDialog enable_proto_dialog(this);
2528 enable_proto_dialog.exec();
2530 // Emitting PacketDissectionChanged directly from a QDialog can cause
2531 // problems on OS X.
2532 wsApp->flushAppSignals();
2535 void MainWindow::on_actionAnalyzeDecodeAs_triggered()
2537 QAction *da_action = qobject_cast<QAction*>(sender());
2538 bool create_new = false;
2539 if (da_action && da_action->data().toBool() == true) {
2543 DecodeAsDialog da_dialog(this, capture_file_.capFile(), create_new);
2544 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2545 &da_dialog, SLOT(setCaptureFile(capture_file*)));
2548 // Emitting PacketDissectionChanged directly from a QDialog can cause
2549 // problems on OS X.
2550 wsApp->flushAppSignals();
2554 void MainWindow::on_actionAnalyzeReloadLuaPlugins_triggered()
2556 if (wsApp->isReloadingLua())
2559 wsApp->setReloadingLua(true);
2561 wslua_reload_plugins(NULL, NULL);
2562 funnel_statistics_reload_menus();
2563 reloadDynamicMenus();
2564 closePacketDialogs();
2566 // Preferences may have been deleted so close all widgets using prefs
2567 proto_tree_->closeContextMenu();
2568 main_ui_->preferenceEditorFrame->animatedHide();
2570 char *gdp_path, *dp_path;
2571 (void) wsApp->readConfigurationFiles(&gdp_path, &dp_path);
2576 wsApp->setReloadingLua(false);
2577 SimpleDialog::displayQueuedMessages();
2581 void MainWindow::openFollowStreamDialog(follow_type_t type) {
2582 FollowStreamDialog *fsd = new FollowStreamDialog(*this, capture_file_, type);
2583 connect(fsd, SIGNAL(updateFilter(QString, bool)), this, SLOT(filterPackets(QString, bool)));
2584 connect(fsd, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
2587 fsd->follow(getFilter());
2590 void MainWindow::on_actionAnalyzeFollowTCPStream_triggered()
2592 openFollowStreamDialog(FOLLOW_TCP);
2595 void MainWindow::on_actionAnalyzeFollowUDPStream_triggered()
2597 openFollowStreamDialog(FOLLOW_UDP);
2600 void MainWindow::on_actionAnalyzeFollowSSLStream_triggered()
2602 openFollowStreamDialog(FOLLOW_SSL);
2605 void MainWindow::openSCTPAllAssocsDialog()
2607 SCTPAllAssocsDialog *sctp_dialog = new SCTPAllAssocsDialog(this, capture_file_.capFile());
2608 connect(sctp_dialog, SIGNAL(filterPackets(QString,bool)),
2609 this, SLOT(filterPackets(QString,bool)));
2610 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2611 sctp_dialog, SLOT(setCaptureFile(capture_file*)));
2612 sctp_dialog->fillTable();
2614 if (sctp_dialog->isMinimized() == true)
2616 sctp_dialog->showNormal();
2620 sctp_dialog->show();
2623 sctp_dialog->raise();
2624 sctp_dialog->activateWindow();
2627 void MainWindow::on_actionSCTPShowAllAssociations_triggered()
2629 openSCTPAllAssocsDialog();
2632 void MainWindow::on_actionSCTPAnalyseThisAssociation_triggered()
2634 SCTPAssocAnalyseDialog *sctp_analyse = new SCTPAssocAnalyseDialog(this, NULL, capture_file_.capFile());
2635 connect(sctp_analyse, SIGNAL(filterPackets(QString,bool)),
2636 this, SLOT(filterPackets(QString,bool)));
2638 if (sctp_analyse->isMinimized() == true)
2640 sctp_analyse->showNormal();
2644 sctp_analyse->show();
2647 sctp_analyse->raise();
2648 sctp_analyse->activateWindow();
2651 void MainWindow::on_actionSCTPFilterThisAssociation_triggered()
2653 sctp_assoc_info_t* assoc = SCTPAssocAnalyseDialog::findAssocForPacket(capture_file_.capFile());
2655 QString newFilter = QString("sctp.assoc_index==%1").arg(assoc->assoc_id);
2657 emit filterPackets(newFilter, false);
2662 void MainWindow::statCommandWlanStatistics(const char *arg, void *)
2664 WlanStatisticsDialog *wlan_stats_dlg = new WlanStatisticsDialog(*this, capture_file_, arg);
2665 connect(wlan_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2666 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2667 wlan_stats_dlg->show();
2670 void MainWindow::on_actionWirelessWlanStatistics_triggered()
2672 statCommandWlanStatistics(NULL, NULL);
2676 void MainWindow::statCommandExpertInfo(const char *, void *)
2678 ExpertInfoDialog *expert_dialog = new ExpertInfoDialog(*this, capture_file_);
2679 const DisplayFilterEdit *df_edit = dynamic_cast<DisplayFilterEdit *>(df_combo_box_->lineEdit());
2681 expert_dialog->setDisplayFilter(df_edit->text());
2683 connect(expert_dialog, SIGNAL(goToPacket(int, int)),
2684 packet_list_, SLOT(goToPacket(int, int)));
2685 connect(expert_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2686 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2688 expert_dialog->show();
2691 void MainWindow::on_actionAnalyzeExpertInfo_triggered()
2693 statCommandExpertInfo(NULL, NULL);
2697 // Next / previous / first / last slots in packet_list
2701 void MainWindow::on_actionStatisticsFlowGraph_triggered()
2703 SequenceDialog *sequence_dialog = new SequenceDialog(*this, capture_file_);
2704 connect(sequence_dialog, SIGNAL(goToPacket(int)),
2705 packet_list_, SLOT(goToPacket(int)));
2706 sequence_dialog->show();
2709 void MainWindow::openTcpStreamDialog(int graph_type)
2711 TCPStreamDialog *stream_dialog = new TCPStreamDialog(this, capture_file_.capFile(), (tcp_graph_type)graph_type);
2712 connect(stream_dialog, SIGNAL(goToPacket(int)),
2713 packet_list_, SLOT(goToPacket(int)));
2714 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2715 stream_dialog, SLOT(setCaptureFile(capture_file*)));
2716 stream_dialog->show();
2719 void MainWindow::on_actionStatisticsTcpStreamStevens_triggered()
2721 openTcpStreamDialog(GRAPH_TSEQ_STEVENS);
2724 void MainWindow::on_actionStatisticsTcpStreamTcptrace_triggered()
2726 openTcpStreamDialog(GRAPH_TSEQ_TCPTRACE);
2729 void MainWindow::on_actionStatisticsTcpStreamThroughput_triggered()
2731 openTcpStreamDialog(GRAPH_THROUGHPUT);
2734 void MainWindow::on_actionStatisticsTcpStreamRoundTripTime_triggered()
2736 openTcpStreamDialog(GRAPH_RTT);
2739 void MainWindow::on_actionStatisticsTcpStreamWindowScaling_triggered()
2741 openTcpStreamDialog(GRAPH_WSCALE);
2745 void MainWindow::statCommandMulticastStatistics(const char *arg, void *)
2747 MulticastStatisticsDialog *mcast_stats_dlg = new MulticastStatisticsDialog(*this, capture_file_, arg);
2748 connect(mcast_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2749 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2750 mcast_stats_dlg->show();
2753 void MainWindow::on_actionStatisticsUdpMulticastStreams_triggered()
2755 statCommandMulticastStatistics(NULL, NULL);
2758 void MainWindow::openStatisticsTreeDialog(const gchar *abbr)
2760 StatsTreeDialog *st_dialog = new StatsTreeDialog(*this, capture_file_, abbr);
2761 // connect(st_dialog, SIGNAL(goToPacket(int)),
2762 // packet_list_, SLOT(goToPacket(int)));
2766 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Topic_triggered()
2768 openStatisticsTreeDialog("lbmr_topic_ads_topic");
2771 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Source_triggered()
2773 openStatisticsTreeDialog("lbmr_topic_ads_source");
2776 void MainWindow::on_actionStatistics29WestTopics_Advertisements_by_Transport_triggered()
2778 openStatisticsTreeDialog("lbmr_topic_ads_transport");
2781 void MainWindow::on_actionStatistics29WestTopics_Queries_by_Topic_triggered()
2783 openStatisticsTreeDialog("lbmr_topic_queries_topic");
2786 void MainWindow::on_actionStatistics29WestTopics_Queries_by_Receiver_triggered()
2788 openStatisticsTreeDialog("lbmr_topic_queries_receiver");
2791 void MainWindow::on_actionStatistics29WestTopics_Wildcard_Queries_by_Pattern_triggered()
2793 openStatisticsTreeDialog("lbmr_topic_queries_pattern");
2796 void MainWindow::on_actionStatistics29WestTopics_Wildcard_Queries_by_Receiver_triggered()
2798 openStatisticsTreeDialog("lbmr_topic_queries_pattern_receiver");
2801 void MainWindow::on_actionStatistics29WestQueues_Advertisements_by_Queue_triggered()
2803 openStatisticsTreeDialog("lbmr_queue_ads_queue");
2806 void MainWindow::on_actionStatistics29WestQueues_Advertisements_by_Source_triggered()
2808 openStatisticsTreeDialog("lbmr_queue_ads_source");
2811 void MainWindow::on_actionStatistics29WestQueues_Queries_by_Queue_triggered()
2813 openStatisticsTreeDialog("lbmr_queue_queries_queue");
2816 void MainWindow::on_actionStatistics29WestQueues_Queries_by_Receiver_triggered()
2818 openStatisticsTreeDialog("lbmr_queue_queries_receiver");
2821 void MainWindow::on_actionStatistics29WestUIM_Streams_triggered()
2823 LBMStreamDialog *stream_dialog = new LBMStreamDialog(this, capture_file_.capFile());
2824 // connect(stream_dialog, SIGNAL(goToPacket(int)),
2825 // packet_list_, SLOT(goToPacket(int)));
2826 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2827 stream_dialog, SLOT(setCaptureFile(capture_file*)));
2828 stream_dialog->show();
2831 void MainWindow::on_actionStatistics29WestUIM_Stream_Flow_Graph_triggered()
2833 LBMUIMFlowDialog * uimflow_dialog = new LBMUIMFlowDialog(this, capture_file_.capFile());
2834 connect(uimflow_dialog, SIGNAL(goToPacket(int)),
2835 packet_list_, SLOT(goToPacket(int)));
2836 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2837 uimflow_dialog, SLOT(setCaptureFile(capture_file*)));
2838 uimflow_dialog->show();
2841 void MainWindow::on_actionStatistics29WestLBTRM_triggered()
2843 LBMLBTRMTransportDialog * lbtrm_dialog = new LBMLBTRMTransportDialog(this, capture_file_.capFile());
2844 connect(lbtrm_dialog, SIGNAL(goToPacket(int)),
2845 packet_list_, SLOT(goToPacket(int)));
2846 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2847 lbtrm_dialog, SLOT(setCaptureFile(capture_file*)));
2848 lbtrm_dialog->show();
2850 void MainWindow::on_actionStatistics29WestLBTRU_triggered()
2852 LBMLBTRUTransportDialog * lbtru_dialog = new LBMLBTRUTransportDialog(this, capture_file_.capFile());
2853 connect(lbtru_dialog, SIGNAL(goToPacket(int)),
2854 packet_list_, SLOT(goToPacket(int)));
2855 connect(this, SIGNAL(setCaptureFile(capture_file*)),
2856 lbtru_dialog, SLOT(setCaptureFile(capture_file*)));
2857 lbtru_dialog->show();
2860 void MainWindow::on_actionStatisticsANCP_triggered()
2862 openStatisticsTreeDialog("ancp");
2865 void MainWindow::on_actionStatisticsBACappInstanceId_triggered()
2867 openStatisticsTreeDialog("bacapp_instanceid");
2870 void MainWindow::on_actionStatisticsBACappIP_triggered()
2872 openStatisticsTreeDialog("bacapp_ip");
2875 void MainWindow::on_actionStatisticsBACappObjectId_triggered()
2877 openStatisticsTreeDialog("bacapp_objectid");
2880 void MainWindow::on_actionStatisticsBACappService_triggered()
2882 openStatisticsTreeDialog("bacapp_service");
2885 void MainWindow::on_actionStatisticsCollectd_triggered()
2887 openStatisticsTreeDialog("collectd");
2891 void MainWindow::statCommandConversations(const char *arg, void *userdata)
2893 ConversationDialog *conv_dialog = new ConversationDialog(*this, capture_file_, GPOINTER_TO_INT(userdata), arg);
2894 connect(conv_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2895 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2896 connect(conv_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
2897 this, SLOT(openFollowStreamDialog(follow_type_t)));
2898 connect(conv_dialog, SIGNAL(openTcpStreamGraph(int)),
2899 this, SLOT(openTcpStreamDialog(int)));
2900 conv_dialog->show();
2903 void MainWindow::on_actionStatisticsConversations_triggered()
2905 statCommandConversations(NULL, NULL);
2909 void MainWindow::statCommandEndpoints(const char *arg, void *userdata)
2911 EndpointDialog *endp_dialog = new EndpointDialog(*this, capture_file_, GPOINTER_TO_INT(userdata), arg);
2912 connect(endp_dialog, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
2913 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
2914 connect(endp_dialog, SIGNAL(openFollowStreamDialog(follow_type_t)),
2915 this, SLOT(openFollowStreamDialog(follow_type_t)));
2916 connect(endp_dialog, SIGNAL(openTcpStreamGraph(int)),
2917 this, SLOT(openTcpStreamDialog(int)));
2918 endp_dialog->show();
2921 void MainWindow::on_actionStatisticsEndpoints_triggered()
2923 statCommandEndpoints(NULL, NULL);
2926 void MainWindow::on_actionStatisticsHART_IP_triggered()
2928 openStatisticsTreeDialog("hart_ip");
2931 void MainWindow::on_actionStatisticsHTTPPacketCounter_triggered()
2933 openStatisticsTreeDialog("http");
2936 void MainWindow::on_actionStatisticsHTTPRequests_triggered()
2938 openStatisticsTreeDialog("http_req");
2941 void MainWindow::on_actionStatisticsHTTPLoadDistribution_triggered()
2943 openStatisticsTreeDialog("http_srv");
2946 void MainWindow::on_actionStatisticsPacketLengths_triggered()
2948 openStatisticsTreeDialog("plen");
2952 void MainWindow::statCommandIOGraph(const char *, void *)
2954 IOGraphDialog *iog_dialog = new IOGraphDialog(*this, capture_file_);
2955 connect(iog_dialog, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
2956 connect(this, SIGNAL(reloadFields()), iog_dialog, SLOT(reloadFields()));
2960 void MainWindow::on_actionStatisticsIOGraph_triggered()
2962 statCommandIOGraph(NULL, NULL);
2965 void MainWindow::on_actionStatisticsSametime_triggered()
2967 openStatisticsTreeDialog("sametime");
2970 void MainWindow::on_actionStatisticsDNS_triggered()
2972 openStatisticsTreeDialog("dns");
2975 void MainWindow::actionStatisticsPlugin_triggered()
2977 QAction* action = qobject_cast<QAction*>(sender());
2979 openStatisticsTreeDialog(action->data().toString().toUtf8());
2983 void MainWindow::on_actionStatisticsHTTP2_triggered()
2985 openStatisticsTreeDialog("http2");
2991 void MainWindow::openVoipCallsDialog(bool all_flows)
2993 VoipCallsDialog *voip_calls_dialog = new VoipCallsDialog(*this, capture_file_, all_flows);
2994 connect(voip_calls_dialog, SIGNAL(goToPacket(int)),
2995 packet_list_, SLOT(goToPacket(int)));
2996 connect(voip_calls_dialog, SIGNAL(updateFilter(QString, bool)),
2997 this, SLOT(filterPackets(QString, bool)));
2998 voip_calls_dialog->show();
3001 void MainWindow::on_actionTelephonyVoipCalls_triggered()
3003 openVoipCallsDialog();
3006 void MainWindow::on_actionTelephonyGsmMapSummary_triggered()
3008 GsmMapSummaryDialog *gms_dialog = new GsmMapSummaryDialog(*this, capture_file_);
3012 void MainWindow::on_actionTelephonyIax2StreamAnalysis_triggered()
3014 Iax2AnalysisDialog *iax2_analysis_dialog = new Iax2AnalysisDialog(*this, capture_file_);
3015 connect(iax2_analysis_dialog, SIGNAL(goToPacket(int)),
3016 packet_list_, SLOT(goToPacket(int)));
3017 iax2_analysis_dialog->show();
3020 void MainWindow::on_actionTelephonyISUPMessages_triggered()
3022 openStatisticsTreeDialog("isup_msg");
3026 void MainWindow::statCommandLteMacStatistics(const char *arg, void *)
3028 LteMacStatisticsDialog *lte_mac_stats_dlg = new LteMacStatisticsDialog(*this, capture_file_, arg);
3029 connect(lte_mac_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
3030 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
3031 lte_mac_stats_dlg->show();
3034 void MainWindow::on_actionTelephonyLteMacStatistics_triggered()
3036 statCommandLteMacStatistics(NULL, NULL);
3039 void MainWindow::statCommandLteRlcStatistics(const char *arg, void *)
3041 LteRlcStatisticsDialog *lte_rlc_stats_dlg = new LteRlcStatisticsDialog(*this, capture_file_, arg);
3042 connect(lte_rlc_stats_dlg, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
3043 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
3044 // N.B. It is necessary for the RLC Statistics window to launch the RLC graph in this way, to ensure
3045 // that the goToPacket() signal/slot connection gets set up...
3046 connect(lte_rlc_stats_dlg, SIGNAL(launchRLCGraph(bool, guint16, guint8, guint16, guint16, guint8)),
3047 this, SLOT(launchRLCGraph(bool, guint16, guint8, guint16, guint16, guint8)));
3049 lte_rlc_stats_dlg->show();
3052 void MainWindow::on_actionTelephonyLteRlcStatistics_triggered()
3054 statCommandLteRlcStatistics(NULL, NULL);
3057 void MainWindow::launchRLCGraph(bool channelKnown,
3058 guint16 ueid, guint8 rlcMode,
3059 guint16 channelType, guint16 channelId, guint8 direction)
3061 LteRlcGraphDialog *lrg_dialog = new LteRlcGraphDialog(*this, capture_file_, channelKnown);
3062 connect(lrg_dialog, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
3063 // This is a bit messy, but wanted to hide these parameters from users of
3064 // on_actionTelephonyLteRlcGraph_triggered().
3066 lrg_dialog->setChannelInfo(ueid, rlcMode, channelType, channelId, direction);
3071 void MainWindow::on_actionTelephonyLteRlcGraph_triggered()
3073 // We don't yet know the channel.
3074 launchRLCGraph(false, 0, 0, 0, 0, 0);
3077 void MainWindow::on_actionTelephonyMtp3Summary_triggered()
3079 Mtp3SummaryDialog *mtp3s_dialog = new Mtp3SummaryDialog(*this, capture_file_);
3080 mtp3s_dialog->show();
3083 void MainWindow::on_actionTelephonyRTPStreams_triggered()
3085 RtpStreamDialog *rtp_stream_dialog = new RtpStreamDialog(*this, capture_file_);
3086 connect(rtp_stream_dialog, SIGNAL(packetsMarked()),
3087 packet_list_, SLOT(redrawVisiblePackets()));
3088 connect(rtp_stream_dialog, SIGNAL(goToPacket(int)),
3089 packet_list_, SLOT(goToPacket(int)));
3090 connect(rtp_stream_dialog, SIGNAL(updateFilter(QString, bool)),
3091 this, SLOT(filterPackets(QString, bool)));
3092 rtp_stream_dialog->show();
3095 void MainWindow::on_actionTelephonyRTPStreamAnalysis_triggered()
3097 RtpAnalysisDialog *rtp_analysis_dialog = new RtpAnalysisDialog(*this, capture_file_);
3098 connect(rtp_analysis_dialog, SIGNAL(goToPacket(int)),
3099 packet_list_, SLOT(goToPacket(int)));
3100 rtp_analysis_dialog->show();
3103 void MainWindow::on_actionTelephonyRTSPPacketCounter_triggered()
3105 openStatisticsTreeDialog("rtsp");
3108 void MainWindow::on_actionTelephonySMPPOperations_triggered()
3110 openStatisticsTreeDialog("smpp_commands");
3113 void MainWindow::on_actionTelephonyUCPMessages_triggered()
3115 openStatisticsTreeDialog("ucp_messages");
3118 void MainWindow::on_actionTelephonySipFlows_triggered()
3120 openVoipCallsDialog(true);
3125 void MainWindow::on_actionBluetoothATT_Server_Attributes_triggered()
3127 BluetoothAttServerAttributesDialog *bluetooth_att_sever_attributes_dialog = new BluetoothAttServerAttributesDialog(*this, capture_file_);
3128 connect(bluetooth_att_sever_attributes_dialog, SIGNAL(goToPacket(int)),
3129 packet_list_, SLOT(goToPacket(int)));
3130 connect(bluetooth_att_sever_attributes_dialog, SIGNAL(updateFilter(QString, bool)),
3131 this, SLOT(filterPackets(QString, bool)));
3132 bluetooth_att_sever_attributes_dialog->show();
3135 void MainWindow::on_actionBluetoothDevices_triggered()
3137 BluetoothDevicesDialog *bluetooth_devices_dialog = new BluetoothDevicesDialog(*this, capture_file_);
3138 connect(bluetooth_devices_dialog, SIGNAL(goToPacket(int)),
3139 packet_list_, SLOT(goToPacket(int)));
3140 connect(bluetooth_devices_dialog, SIGNAL(updateFilter(QString, bool)),
3141 this, SLOT(filterPackets(QString, bool)));
3142 bluetooth_devices_dialog->show();
3145 void MainWindow::on_actionBluetoothHCI_Summary_triggered()
3147 BluetoothHciSummaryDialog *bluetooth_hci_summary_dialog = new BluetoothHciSummaryDialog(*this, capture_file_);
3148 connect(bluetooth_hci_summary_dialog, SIGNAL(goToPacket(int)),
3149 packet_list_, SLOT(goToPacket(int)));
3150 connect(bluetooth_hci_summary_dialog, SIGNAL(updateFilter(QString, bool)),
3151 this, SLOT(filterPackets(QString, bool)));
3152 bluetooth_hci_summary_dialog->show();
3156 void MainWindow::on_actionHelpContents_triggered() {
3158 wsApp->helpTopicAction(HELP_CONTENT);
3161 void MainWindow::on_actionHelpMPWireshark_triggered() {
3163 wsApp->helpTopicAction(LOCALPAGE_MAN_WIRESHARK);
3166 void MainWindow::on_actionHelpMPWireshark_Filter_triggered() {
3167 wsApp->helpTopicAction(LOCALPAGE_MAN_WIRESHARK_FILTER);
3170 void MainWindow::on_actionHelpMPCapinfos_triggered() {
3171 wsApp->helpTopicAction(LOCALPAGE_MAN_CAPINFOS);
3174 void MainWindow::on_actionHelpMPDumpcap_triggered() {
3175 wsApp->helpTopicAction(LOCALPAGE_MAN_DUMPCAP);
3178 void MainWindow::on_actionHelpMPEditcap_triggered() {
3179 wsApp->helpTopicAction(LOCALPAGE_MAN_EDITCAP);
3182 void MainWindow::on_actionHelpMPMergecap_triggered() {
3183 wsApp->helpTopicAction(LOCALPAGE_MAN_MERGECAP);
3186 void MainWindow::on_actionHelpMPRawShark_triggered() {
3187 wsApp->helpTopicAction(LOCALPAGE_MAN_RAWSHARK);
3190 void MainWindow::on_actionHelpMPReordercap_triggered() {
3191 wsApp->helpTopicAction(LOCALPAGE_MAN_REORDERCAP);
3194 void MainWindow::on_actionHelpMPText2cap_triggered() {
3195 wsApp->helpTopicAction(LOCALPAGE_MAN_TEXT2PCAP);
3198 void MainWindow::on_actionHelpMPTShark_triggered() {
3199 wsApp->helpTopicAction(LOCALPAGE_MAN_TSHARK);
3202 void MainWindow::on_actionHelpWebsite_triggered() {
3204 wsApp->helpTopicAction(ONLINEPAGE_HOME);
3207 void MainWindow::on_actionHelpFAQ_triggered() {
3209 wsApp->helpTopicAction(ONLINEPAGE_FAQ);
3212 void MainWindow::on_actionHelpAsk_triggered() {
3214 wsApp->helpTopicAction(ONLINEPAGE_ASK);
3217 void MainWindow::on_actionHelpDownloads_triggered() {
3219 wsApp->helpTopicAction(ONLINEPAGE_DOWNLOAD);
3222 void MainWindow::on_actionHelpWiki_triggered() {
3224 wsApp->helpTopicAction(ONLINEPAGE_WIKI);
3227 void MainWindow::on_actionHelpSampleCaptures_triggered() {
3229 wsApp->helpTopicAction(ONLINEPAGE_SAMPLE_FILES);
3232 #ifdef HAVE_SOFTWARE_UPDATE
3233 void MainWindow::checkForUpdates()
3235 software_update_check();
3239 void MainWindow::on_actionHelpAbout_triggered()
3241 AboutDialog *about_dialog = new AboutDialog(this);
3243 if (about_dialog->isMinimized() == true)
3245 about_dialog->showNormal();
3249 about_dialog->show();
3252 about_dialog->raise();
3253 about_dialog->activateWindow();
3256 void MainWindow::on_actionGoGoToPacket_triggered() {
3257 if (packet_list_->model()->rowCount() < 1) {
3260 previous_focus_ = wsApp->focusWidget();
3261 connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
3263 showAccordionFrame(main_ui_->goToFrame, true);
3264 if (main_ui_->goToFrame->isVisible()) {
3265 main_ui_->goToLineEdit->clear();
3266 main_ui_->goToLineEdit->setFocus();
3270 void MainWindow::on_actionGoGoToLinkedPacket_triggered()
3272 QAction *gta = qobject_cast<QAction*>(sender());
3276 int packet_num = gta->data().toInt(&ok);
3279 packet_list_->goToPacket(packet_num);
3282 void MainWindow::on_actionGoAutoScroll_toggled(bool checked)
3284 packet_list_->setAutoScroll(checked);
3287 void MainWindow::resetPreviousFocus() {
3288 previous_focus_ = NULL;
3291 void MainWindow::on_goToCancel_clicked()
3293 main_ui_->goToFrame->animatedHide();
3294 if (previous_focus_) {
3295 disconnect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
3296 previous_focus_->setFocus();
3297 resetPreviousFocus();
3301 void MainWindow::on_goToGo_clicked()
3303 gotoFrame(main_ui_->goToLineEdit->text().toInt());
3305 on_goToCancel_clicked();
3308 void MainWindow::on_goToLineEdit_returnPressed()
3310 on_goToGo_clicked();
3313 void MainWindow::on_actionCaptureStart_triggered()
3315 //#ifdef HAVE_AIRPCAP
3316 // airpcap_if_active = airpcap_if_selected;
3317 // if (airpcap_if_active)
3318 // airpcap_set_toolbar_start_capture(airpcap_if_active);
3321 // if (cap_open_w) {
3323 // * There's an options dialog; get the values from it and close it.
3325 // gboolean success;
3327 // /* Determine if "capture start" while building of the "capture options" window */
3328 // /* is in progress. If so, ignore the "capture start. */
3329 // /* XXX: Would it be better/cleaner for the "capture options" window code to */
3330 // /* disable the capture start button temporarily ? */
3331 // if (cap_open_complete == FALSE) {
3332 // return; /* Building options window: ignore "capture start" */
3334 // success = capture_dlg_prep(cap_open_w);
3335 // window_destroy(GTK_WIDGET(cap_open_w));
3337 // return; /* error in options dialog */
3341 if (global_capture_opts.num_selected == 0) {
3342 QString err_msg = tr("No Interface Selected");
3343 main_ui_->statusBar->pushTemporaryStatus(err_msg);
3344 main_ui_->actionCaptureStart->setChecked(false);
3348 /* XXX - will closing this remove a temporary file? */
3349 QString before_what(tr(" before starting a new capture"));
3350 if (testCaptureFileClose(FALSE, before_what)) {
3353 // simply clicking the button sets it to 'checked' even though we've
3354 // decided to do nothing, so undo that
3355 main_ui_->actionCaptureStart->setChecked(false);
3357 #endif // HAVE_LIBPCAP
3360 void MainWindow::on_actionCaptureStop_triggered()
3365 void MainWindow::on_actionCaptureRestart_triggered()
3367 /* TODO: GTK use only this: capture_restart(&cap_session_); */
3372 static FilterDialog *capture_filter_dlg_ = NULL;
3373 void MainWindow::on_actionCaptureCaptureFilters_triggered()
3375 if (!capture_filter_dlg_) {
3376 capture_filter_dlg_ = new FilterDialog(this, FilterDialog::CaptureFilter);
3378 capture_filter_dlg_->show();
3379 capture_filter_dlg_->raise();
3380 capture_filter_dlg_->activateWindow();
3383 void MainWindow::on_actionStatisticsCaptureFileProperties_triggered()
3385 CaptureFilePropertiesDialog *capture_file_properties_dialog = new CaptureFilePropertiesDialog(*this, capture_file_);
3386 connect(capture_file_properties_dialog, SIGNAL(captureCommentChanged()),
3387 this, SLOT(updateForUnsavedChanges()));
3388 capture_file_properties_dialog->show();
3391 void MainWindow::on_actionStatisticsResolvedAddresses_triggered()
3393 ResolvedAddressesDialog *resolved_addresses_dialog = new ResolvedAddressesDialog(this, &capture_file_);
3394 resolved_addresses_dialog->show();
3397 void MainWindow::on_actionStatisticsProtocolHierarchy_triggered()
3399 ProtocolHierarchyDialog *phd = new ProtocolHierarchyDialog(*this, capture_file_);
3400 connect(phd, SIGNAL(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)),
3401 this, SLOT(filterAction(QString&,FilterAction::Action,FilterAction::ActionType)));
3406 void MainWindow::on_actionCaptureOptions_triggered()
3408 connect(&capture_interfaces_dialog_, SIGNAL(setFilterValid(bool)), this, SLOT(startInterfaceCapture(bool)));
3409 capture_interfaces_dialog_.SetTab(0);
3410 capture_interfaces_dialog_.updateInterfaces();
3412 if (capture_interfaces_dialog_.isMinimized() == true)
3414 capture_interfaces_dialog_.showNormal();
3418 capture_interfaces_dialog_.show();
3421 capture_interfaces_dialog_.raise();
3422 capture_interfaces_dialog_.activateWindow();
3425 void MainWindow::on_actionCaptureRefreshInterfaces_triggered()
3427 wsApp->refreshLocalInterfaces();
3431 void MainWindow::externalMenuItem_triggered()
3433 QAction * triggerAction = NULL;
3435 ext_menubar_t * entry = NULL;
3437 if ( QObject::sender() != NULL)
3439 triggerAction = (QAction *)QObject::sender();
3440 v = triggerAction->data();
3442 if ( v.canConvert<void *>())
3444 entry = (ext_menubar_t *)v.value<void *>();
3446 if ( entry->type == EXT_MENUBAR_ITEM )
3448 entry->callback(EXT_MENUBAR_QT_GUI, (gpointer) ((void *)main_ui_), entry->user_data);
3452 QDesktopServices::openUrl(QUrl(QString((gchar *)entry->user_data)));
3458 void MainWindow::gotoFrame(int packet_num)
3460 if ( packet_num > 0 )
3462 packet_list_->goToPacket(packet_num);
3467 void MainWindow::extcap_options_finished(int result)
3469 if ( result == QDialog::Accepted )
3473 this->main_welcome_->getInterfaceTree()->interfaceListChanged();
3476 void MainWindow::showExtcapOptionsDialog(QString &device_name)
3478 ExtcapOptionsDialog * extcap_options_dialog = ExtcapOptionsDialog::createForDevice(device_name, this);
3479 /* The dialog returns null, if the given device name is not a valid extcap device */
3480 if ( extcap_options_dialog != NULL )
3482 connect(extcap_options_dialog, SIGNAL(finished(int)),
3483 this, SLOT(extcap_options_finished(int)));
3484 extcap_options_dialog->show();
3489 // Q_DECLARE_METATYPE(field_info *) called in proto_tree.h
3491 void MainWindow::on_actionContextCopyBytesHexTextDump_triggered()
3493 QAction *ca = qobject_cast<QAction*>(sender());
3496 field_info *fi = ca->data().value<field_info *>();
3498 byte_view_tab_->copyData(ByteViewTab::copyDataHexTextDump, fi);
3501 void MainWindow::on_actionContextCopyBytesHexDump_triggered()
3503 QAction *ca = qobject_cast<QAction*>(sender());
3506 field_info *fi = ca->data().value<field_info *>();
3508 byte_view_tab_->copyData(ByteViewTab::copyDataHexDump, fi);
3511 void MainWindow::on_actionContextCopyBytesPrintableText_triggered()
3513 QAction *ca = qobject_cast<QAction*>(sender());
3516 field_info *fi = ca->data().value<field_info *>();
3518 byte_view_tab_->copyData(ByteViewTab::copyDataPrintableText, fi);
3521 void MainWindow::on_actionContextCopyBytesHexStream_triggered()
3523 QAction *ca = qobject_cast<QAction*>(sender());
3526 field_info *fi = ca->data().value<field_info *>();
3528 byte_view_tab_->copyData(ByteViewTab::copyDataHexStream, fi);
3531 void MainWindow::on_actionContextCopyBytesBinary_triggered()
3533 QAction *ca = qobject_cast<QAction*>(sender());
3536 field_info *fi = ca->data().value<field_info *>();
3538 byte_view_tab_->copyData(ByteViewTab::copyDataBinary, fi);
3541 void MainWindow::on_actionContextWikiProtocolPage_triggered()
3543 QAction *wa = qobject_cast<QAction*>(sender());
3547 int field_id = wa->data().toInt(&ok);
3550 const QString proto_abbrev = proto_registrar_get_abbrev(field_id);
3552 int ret = QMessageBox::question(this, wsApp->windowTitleString(tr("Wiki Page for %1").arg(proto_abbrev)),
3553 tr("<p>The Wireshark Wiki is maintained by the community.</p>"
3554 "<p>The page you are about to load might be wonderful, "
3555 "incomplete, wrong, or nonexistent.</p>"
3556 "<p>Proceed to the wiki?</p>"),
3557 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
3559 if (ret != QMessageBox::Yes) return;
3561 QUrl wiki_url = QString("https://wiki.wireshark.org/Protocols/%1").arg(proto_abbrev);
3562 QDesktopServices::openUrl(wiki_url);
3565 void MainWindow::on_actionContextFilterFieldReference_triggered()
3567 QAction *wa = qobject_cast<QAction*>(sender());
3571 int field_id = wa->data().toInt(&ok);
3574 const QString proto_abbrev = proto_registrar_get_abbrev(field_id);
3576 QUrl dfref_url = QString("https://www.wireshark.org/docs/dfref/%1/%2")
3577 .arg(proto_abbrev[0])
3579 QDesktopServices::openUrl(dfref_url);
3583 #pragma warning(pop)
3592 * indent-tabs-mode: nil
3595 * ex: set shiftwidth=4 tabstop=8 expandtab:
3596 * :indentSize=4:tabSize=8:noTabs=true: