From c4e8a3222648fcf22ca207f1815ebbf7cd144eeb Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 19 Sep 2024 06:14:26 +0200 Subject: Adding upstream version 4.4.0. Signed-off-by: Daniel Baumann --- ui/qt/CMakeLists.txt | 26 +- ui/qt/about_dialog.cpp | 102 +- ui/qt/about_dialog.ui | 2 +- ui/qt/accordion_frame.cpp | 3 +- ui/qt/address_editor_frame.cpp | 30 +- ui/qt/bluetooth_att_server_attributes_dialog.cpp | 81 +- ui/qt/bluetooth_att_server_attributes_dialog.h | 2 - ui/qt/bluetooth_att_server_attributes_dialog.ui | 2 +- ui/qt/bluetooth_device_dialog.cpp | 10 +- ui/qt/bluetooth_device_dialog.h | 24 +- ui/qt/bluetooth_devices_dialog.cpp | 15 +- ui/qt/bluetooth_devices_dialog.h | 2 - ui/qt/bluetooth_hci_summary_dialog.cpp | 13 +- ui/qt/bluetooth_hci_summary_dialog.h | 2 - ui/qt/byte_view_tab.cpp | 2 +- ui/qt/capture_comment_dialog.cpp | 252 ++++ ui/qt/capture_comment_dialog.h | 42 + ui/qt/capture_comment_dialog.ui | 33 + ui/qt/capture_event.h | 1 + ui/qt/capture_file.cpp | 12 +- ui/qt/capture_file.h | 10 +- ui/qt/capture_file_dialog.cpp | 208 +--- ui/qt/capture_file_dialog.h | 42 +- ui/qt/capture_file_properties_dialog.cpp | 241 ++-- ui/qt/capture_file_properties_dialog.h | 4 +- ui/qt/capture_file_properties_dialog.ui | 73 +- ui/qt/capture_filter_syntax_worker.cpp | 14 +- ui/qt/capture_info_dialog.cpp | 4 +- ui/qt/capture_options_dialog.cpp | 194 ++- ui/qt/capture_options_dialog.h | 3 + ui/qt/capture_options_dialog.ui | 69 +- ui/qt/capture_preferences_frame.cpp | 11 +- ui/qt/capture_preferences_frame.h | 2 + ui/qt/capture_preferences_frame.ui | 10 + ui/qt/coloring_rules_dialog.cpp | 6 +- ui/qt/column_editor_frame.cpp | 57 +- ui/qt/column_editor_frame.h | 1 + ui/qt/column_editor_frame.ui | 10 +- ui/qt/column_preferences_frame.cpp | 2 - ui/qt/compiled_filter_output.cpp | 31 +- ui/qt/compiled_filter_output.h | 14 +- ui/qt/conversation_colorize_action.cpp | 2 - ui/qt/conversation_dialog.cpp | 18 +- ui/qt/conversation_dialog.h | 2 +- ui/qt/conversation_hash_tables_dialog.cpp | 18 +- ui/qt/decode_as_dialog.cpp | 6 +- ui/qt/decode_as_dialog.h | 2 - ui/qt/display_filter_expression_dialog.cpp | 4 +- ui/qt/endpoint_dialog.cpp | 25 +- ui/qt/expert_info_dialog.h | 2 - ui/qt/export_dissection_dialog.cpp | 131 +- ui/qt/export_dissection_dialog.h | 15 +- ui/qt/export_object_action.cpp | 1 - ui/qt/export_object_action.h | 1 - ui/qt/export_pdu_dialog.cpp | 11 + ui/qt/export_pdu_dialog.h | 1 + ui/qt/export_pdu_dialog.ui | 22 +- ui/qt/extcap_argument.cpp | 49 +- ui/qt/extcap_argument.h | 1 + ui/qt/extcap_argument_multiselect.cpp | 2 +- ui/qt/extcap_options_dialog.cpp | 91 +- ui/qt/extcap_options_dialog.h | 5 +- ui/qt/extcap_options_dialog.ui | 2 +- ui/qt/file_set_dialog.cpp | 2 - ui/qt/file_set_dialog.h | 2 - ui/qt/filter_action.cpp | 24 - ui/qt/filter_dialog.cpp | 144 ++- ui/qt/filter_dialog.h | 8 +- ui/qt/filter_expression_frame.cpp | 2 +- ui/qt/firewall_rules_dialog.cpp | 6 +- ui/qt/firewall_rules_dialog.h | 8 +- ui/qt/follow_stream_action.cpp | 1 - ui/qt/follow_stream_action.h | 1 - ui/qt/follow_stream_dialog.cpp | 620 ++++----- ui/qt/follow_stream_dialog.h | 48 +- ui/qt/follow_stream_dialog.ui | 47 +- ui/qt/font_color_preferences_frame.cpp | 5 +- ui/qt/funnel_statistics.cpp | 72 +- ui/qt/funnel_statistics.h | 14 +- ui/qt/funnel_string_dialog.cpp | 2 +- ui/qt/funnel_string_dialog.h | 2 - ui/qt/funnel_text_dialog.cpp | 4 +- ui/qt/funnel_text_dialog.h | 6 +- ui/qt/geometry_state_dialog.cpp | 85 +- ui/qt/geometry_state_dialog.h | 34 +- ui/qt/glib_mainloop_on_qeventloop.cpp | 4 +- ui/qt/glib_mainloop_on_qeventloop.h | 5 +- ui/qt/gsm_map_summary_dialog.cpp | 2 - ui/qt/iax2_analysis_dialog.cpp | 66 +- ui/qt/iax2_analysis_dialog.h | 7 +- ui/qt/import_text_dialog.cpp | 59 +- ui/qt/import_text_dialog.h | 4 +- ui/qt/interface_frame.cpp | 32 +- ui/qt/interface_frame.h | 5 +- ui/qt/interface_toolbar.cpp | 16 +- ui/qt/interface_toolbar.h | 2 - ui/qt/interface_toolbar_reader.cpp | 4 +- ui/qt/io_console_dialog.cpp | 1 + ui/qt/io_graph_action.cpp | 134 ++ ui/qt/io_graph_action.h | 47 + ui/qt/io_graph_dialog.cpp | 1454 +++++++++++++++------- ui/qt/io_graph_dialog.h | 102 +- ui/qt/io_graph_dialog.ui | 54 +- ui/qt/layout_preferences_frame.cpp | 12 +- ui/qt/lbm_lbtrm_transport_dialog.cpp | 116 +- ui/qt/lbm_lbtrm_transport_dialog.h | 2 - ui/qt/lbm_lbtru_transport_dialog.cpp | 173 ++- ui/qt/lbm_lbtru_transport_dialog.h | 2 - ui/qt/lbm_stream_dialog.cpp | 62 +- ui/qt/lbm_stream_dialog.h | 2 - ui/qt/lte_mac_statistics_dialog.cpp | 140 ++- ui/qt/lte_mac_statistics_dialog.h | 34 +- ui/qt/lte_rlc_graph_dialog.cpp | 101 +- ui/qt/lte_rlc_graph_dialog.h | 13 +- ui/qt/lte_rlc_statistics_dialog.cpp | 292 +++-- ui/qt/lte_rlc_statistics_dialog.h | 12 +- ui/qt/main.cpp | 178 ++- ui/qt/main_application.cpp | 149 ++- ui/qt/main_application.h | 32 +- ui/qt/main_status_bar.cpp | 131 +- ui/qt/main_status_bar.h | 2 +- ui/qt/main_window.cpp | 88 +- ui/qt/main_window.h | 24 +- ui/qt/main_window_layout.cpp | 116 +- ui/qt/main_window_preferences_frame.cpp | 22 +- ui/qt/main_window_preferences_frame.h | 1 + ui/qt/main_window_preferences_frame.ui | 10 + ui/qt/manage_interfaces_dialog.cpp | 180 ++- ui/qt/manage_interfaces_dialog.h | 5 +- ui/qt/manager/wireshark_preference.cpp | 2 +- ui/qt/manuf_dialog.cpp | 4 +- ui/qt/models/astringlist_list_model.cpp | 1 - ui/qt/models/astringlist_list_model.h | 1 + ui/qt/models/atap_data_model.cpp | 49 +- ui/qt/models/atap_data_model.h | 8 +- ui/qt/models/coloring_rules_delegate.cpp | 2 +- ui/qt/models/coloring_rules_model.cpp | 10 +- ui/qt/models/coloring_rules_model.h | 1 - ui/qt/models/column_list_model.cpp | 103 +- ui/qt/models/column_list_model.h | 6 +- ui/qt/models/decode_as_delegate.cpp | 16 +- ui/qt/models/decode_as_delegate.h | 9 +- ui/qt/models/decode_as_model.cpp | 71 +- ui/qt/models/decode_as_model.h | 44 +- ui/qt/models/dissector_tables_model.cpp | 15 +- ui/qt/models/enabled_protocols_model.cpp | 7 +- ui/qt/models/enabled_protocols_model.h | 2 +- ui/qt/models/expert_info_model.cpp | 6 +- ui/qt/models/export_objects_model.cpp | 2 +- ui/qt/models/fileset_entry_model.cpp | 7 +- ui/qt/models/fileset_entry_model.h | 2 - ui/qt/models/filter_list_model.cpp | 49 +- ui/qt/models/filter_list_model.h | 3 +- ui/qt/models/info_proxy_model.cpp | 1 - ui/qt/models/interface_sort_filter_model.cpp | 39 +- ui/qt/models/interface_sort_filter_model.h | 2 - ui/qt/models/interface_tree_cache_model.cpp | 38 +- ui/qt/models/interface_tree_cache_model.h | 8 +- ui/qt/models/interface_tree_model.cpp | 22 +- ui/qt/models/interface_tree_model.h | 26 +- ui/qt/models/packet_list_model.cpp | 87 +- ui/qt/models/packet_list_model.h | 19 +- ui/qt/models/packet_list_record.cpp | 17 +- ui/qt/models/packet_list_record.h | 4 +- ui/qt/models/pref_delegate.cpp | 4 +- ui/qt/models/pref_models.cpp | 103 +- ui/qt/models/pref_models.h | 60 +- ui/qt/models/profile_model.cpp | 99 +- ui/qt/models/profile_model.h | 10 +- ui/qt/models/proto_tree_model.cpp | 8 +- ui/qt/models/proto_tree_model.h | 4 +- ui/qt/models/related_packet_delegate.cpp | 4 +- ui/qt/models/related_packet_delegate.h | 4 +- ui/qt/models/resolved_addresses_models.cpp | 66 +- ui/qt/models/resolved_addresses_models.h | 7 + ui/qt/models/sparkline_delegate.cpp | 2 +- ui/qt/models/uat_delegate.h | 1 - ui/qt/models/uat_model.cpp | 175 ++- ui/qt/models/uat_model.h | 14 +- ui/qt/models/voip_calls_info_model.cpp | 8 +- ui/qt/models/voip_calls_info_model.h | 1 - ui/qt/module_preferences_scroll_area.cpp | 69 +- ui/qt/module_preferences_scroll_area.h | 2 - ui/qt/mtp3_summary_dialog.cpp | 2 - ui/qt/multicast_statistics_dialog.cpp | 8 +- ui/qt/packet_comment_dialog.h | 2 - ui/qt/packet_diagram.cpp | 19 +- ui/qt/packet_dialog.cpp | 74 +- ui/qt/packet_dialog.h | 2 + ui/qt/packet_dialog.ui | 31 +- ui/qt/packet_list.cpp | 213 ++-- ui/qt/packet_list.h | 13 +- ui/qt/packet_range_group_box.cpp | 8 +- ui/qt/packet_range_group_box.h | 2 - ui/qt/preference_editor_frame.cpp | 38 +- ui/qt/preference_editor_frame.ui | 8 +- ui/qt/preferences_dialog.cpp | 77 +- ui/qt/preferences_dialog.h | 6 +- ui/qt/preferences_dialog.ui | 36 +- ui/qt/print_dialog.cpp | 48 +- ui/qt/print_dialog.h | 6 +- ui/qt/profile_dialog.cpp | 82 +- ui/qt/profile_dialog.h | 20 +- ui/qt/profile_dialog.ui | 40 +- ui/qt/progress_frame.cpp | 36 +- ui/qt/progress_frame.h | 12 +- ui/qt/proto_tree.cpp | 38 +- ui/qt/proto_tree.h | 2 +- ui/qt/protocol_hierarchy_dialog.cpp | 2 +- ui/qt/protocol_hierarchy_dialog.h | 2 +- ui/qt/protocol_preferences_menu.cpp | 10 +- ui/qt/remote_capture_dialog.cpp | 64 +- ui/qt/remote_capture_dialog.h | 2 - ui/qt/resolved_addresses_dialog.cpp | 62 +- ui/qt/resolved_addresses_dialog.h | 8 + ui/qt/resolved_addresses_dialog.ui | 29 +- ui/qt/response_time_delay_dialog.cpp | 2 +- ui/qt/rpc_service_response_time_dialog.cpp | 26 +- ui/qt/rpc_service_response_time_dialog.h | 8 +- ui/qt/rsa_keys_frame.cpp | 8 +- ui/qt/rsa_keys_frame.h | 2 +- ui/qt/rtp_analysis_dialog.cpp | 24 +- ui/qt/rtp_analysis_dialog.h | 4 +- ui/qt/rtp_audio_stream.cpp | 32 +- ui/qt/rtp_audio_stream.h | 8 +- ui/qt/rtp_player_dialog.cpp | 69 +- ui/qt/rtp_player_dialog.h | 7 +- ui/qt/rtp_stream_dialog.cpp | 15 +- ui/qt/sctp_all_assocs_dialog.cpp | 42 +- ui/qt/sctp_all_assocs_dialog.h | 4 +- ui/qt/sctp_assoc_analyse_dialog.cpp | 8 +- ui/qt/sctp_assoc_analyse_dialog.h | 6 +- ui/qt/sctp_chunk_statistics_dialog.cpp | 12 +- ui/qt/sctp_chunk_statistics_dialog.h | 3 +- ui/qt/sctp_graph_arwnd_dialog.cpp | 6 +- ui/qt/sctp_graph_arwnd_dialog.h | 7 +- ui/qt/sctp_graph_byte_dialog.cpp | 10 +- ui/qt/sctp_graph_byte_dialog.h | 5 +- ui/qt/sctp_graph_dialog.cpp | 26 +- ui/qt/sctp_graph_dialog.h | 61 +- ui/qt/search_frame.cpp | 88 +- ui/qt/search_frame.h | 2 + ui/qt/search_frame.ui | 156 ++- ui/qt/sequence_diagram.cpp | 43 +- ui/qt/sequence_diagram.h | 6 +- ui/qt/sequence_dialog.cpp | 228 +++- ui/qt/sequence_dialog.h | 14 +- ui/qt/sequence_dialog.ui | 10 - ui/qt/service_response_time_dialog.cpp | 10 +- ui/qt/show_packet_bytes_dialog.cpp | 94 +- ui/qt/show_packet_bytes_dialog.h | 9 +- ui/qt/show_packet_bytes_dialog.ui | 7 + ui/qt/simple_dialog.cpp | 12 +- ui/qt/simple_dialog.h | 2 - ui/qt/simple_statistics_dialog.cpp | 6 +- ui/qt/stats_tree_dialog.cpp | 16 +- ui/qt/stats_tree_dialog.h | 2 - ui/qt/strip_headers_dialog.cpp | 11 + ui/qt/strip_headers_dialog.h | 1 + ui/qt/strip_headers_dialog.ui | 22 +- ui/qt/supported_protocols_dialog.cpp | 2 +- ui/qt/tap_parameter_dialog.cpp | 15 +- ui/qt/tap_parameter_dialog.h | 2 - ui/qt/tcp_stream_dialog.cpp | 137 +- ui/qt/tcp_stream_dialog.h | 7 +- ui/qt/time_shift_dialog.cpp | 10 +- ui/qt/time_shift_dialog.h | 2 - ui/qt/uat_dialog.cpp | 126 +- ui/qt/uat_dialog.h | 4 +- ui/qt/uat_dialog.ui | 14 +- ui/qt/uat_frame.cpp | 127 +- ui/qt/uat_frame.h | 3 + ui/qt/uat_frame.ui | 14 +- ui/qt/utils/color_utils.cpp | 5 + ui/qt/utils/color_utils.h | 10 +- ui/qt/utils/data_printer.cpp | 54 +- ui/qt/utils/data_printer.h | 5 +- ui/qt/utils/frame_information.cpp | 4 +- ui/qt/utils/profile_switcher.cpp | 140 +++ ui/qt/utils/profile_switcher.h | 48 + ui/qt/utils/proto_node.cpp | 4 +- ui/qt/utils/qt_ui_utils.cpp | 116 +- ui/qt/utils/qt_ui_utils.h | 12 +- ui/qt/utils/rtp_audio_file.cpp | 16 +- ui/qt/utils/rtp_audio_file.h | 10 +- ui/qt/utils/rtp_audio_routing_filter.cpp | 2 +- ui/qt/utils/wireshark_zip_helper.cpp | 9 +- ui/qt/utils/wireshark_zip_helper.h | 6 +- ui/qt/voip_calls_dialog.cpp | 20 +- ui/qt/voip_calls_dialog.h | 3 +- ui/qt/welcome_page.cpp | 125 +- ui/qt/welcome_page.h | 2 +- ui/qt/widgets/additional_toolbar.cpp | 24 +- ui/qt/widgets/byte_view_text.cpp | 5 +- ui/qt/widgets/capture_filter_combo.cpp | 2 +- ui/qt/widgets/capture_filter_edit.cpp | 4 +- ui/qt/widgets/compression_group_box.cpp | 69 + ui/qt/widgets/compression_group_box.h | 41 + ui/qt/widgets/copy_from_profile_button.h | 1 - ui/qt/widgets/display_filter_combo.cpp | 89 +- ui/qt/widgets/display_filter_combo.h | 7 + ui/qt/widgets/display_filter_edit.cpp | 73 +- ui/qt/widgets/dissector_syntax_line_edit.cpp | 15 +- ui/qt/widgets/dissector_syntax_line_edit.h | 7 +- ui/qt/widgets/field_filter_edit.cpp | 6 +- ui/qt/widgets/filter_expression_toolbar.cpp | 34 +- ui/qt/widgets/filter_expression_toolbar.h | 2 - ui/qt/widgets/follow_stream_text.cpp | 118 +- ui/qt/widgets/follow_stream_text.h | 18 +- ui/qt/widgets/label_stack.cpp | 4 +- ui/qt/widgets/label_stack.h | 3 +- ui/qt/widgets/path_selection_edit.cpp | 12 +- ui/qt/widgets/profile_tree_view.cpp | 63 +- ui/qt/widgets/profile_tree_view.h | 13 +- ui/qt/widgets/qcp_axis_ticker_elided.cpp | 74 ++ ui/qt/widgets/qcp_axis_ticker_elided.h | 38 + ui/qt/widgets/qcp_axis_ticker_si.cpp | 74 ++ ui/qt/widgets/qcp_axis_ticker_si.h | 42 + ui/qt/widgets/qcp_string_legend_item.cpp | 46 + ui/qt/widgets/qcp_string_legend_item.h | 35 + ui/qt/widgets/resize_header_view.cpp | 45 + ui/qt/widgets/resize_header_view.h | 31 + ui/qt/widgets/resolved_addresses_view.cpp | 261 ++++ ui/qt/widgets/resolved_addresses_view.h | 50 + ui/qt/widgets/rowmove_tree_view.cpp | 98 ++ ui/qt/widgets/rowmove_tree_view.h | 35 + ui/qt/widgets/rtp_audio_graph.cpp | 2 - ui/qt/widgets/splash_overlay.h | 2 - ui/qt/widgets/syntax_line_edit.cpp | 30 +- ui/qt/widgets/traffic_tab.cpp | 77 +- ui/qt/widgets/traffic_tab.h | 14 +- ui/qt/widgets/traffic_tree.cpp | 56 +- ui/qt/widgets/traffic_tree.h | 2 - ui/qt/widgets/traffic_types_list.cpp | 42 +- ui/qt/widgets/traffic_types_list.h | 4 +- ui/qt/widgets/wireless_timeline.cpp | 78 +- ui/qt/widgets/wireless_timeline.h | 14 +- ui/qt/widgets/wireshark_file_dialog.cpp | 15 +- ui/qt/widgets/wireshark_file_dialog.h | 9 +- ui/qt/wireless_frame.cpp | 23 +- ui/qt/wireshark_application.cpp | 2 +- ui/qt/wireshark_de.ts | 925 +++++++++++--- ui/qt/wireshark_dialog.cpp | 4 +- ui/qt/wireshark_dialog.h | 21 +- ui/qt/wireshark_en.ts | 813 ++++++++++-- ui/qt/wireshark_es.ts | 1017 +++++++++++---- ui/qt/wireshark_fr.ts | 969 +++++++++++--- ui/qt/wireshark_it.ts | 933 +++++++++++--- ui/qt/wireshark_ja_JP.ts | 899 ++++++++++--- ui/qt/wireshark_ko.ts | 913 +++++++++++--- ui/qt/wireshark_main_window.cpp | 664 +++++----- ui/qt/wireshark_main_window.h | 28 +- ui/qt/wireshark_main_window.ui | 55 +- ui/qt/wireshark_main_window_slots.cpp | 478 ++++--- ui/qt/wireshark_pl.ts | 1349 ++++++++++++++------ ui/qt/wireshark_ru.ts | 1338 +++++++++++++++----- ui/qt/wireshark_sv.ts | 1037 ++++++++++++--- ui/qt/wireshark_tr_TR.ts | 921 +++++++++++--- ui/qt/wireshark_uk.ts | 967 +++++++++++--- ui/qt/wireshark_zh_CN.ts | 891 ++++++++++--- ui/qt/wlan_statistics_dialog.cpp | 6 +- 361 files changed, 20030 insertions(+), 7628 deletions(-) create mode 100644 ui/qt/capture_comment_dialog.cpp create mode 100644 ui/qt/capture_comment_dialog.h create mode 100644 ui/qt/capture_comment_dialog.ui create mode 100644 ui/qt/io_graph_action.cpp create mode 100644 ui/qt/io_graph_action.h create mode 100644 ui/qt/utils/profile_switcher.cpp create mode 100644 ui/qt/utils/profile_switcher.h create mode 100644 ui/qt/widgets/compression_group_box.cpp create mode 100644 ui/qt/widgets/compression_group_box.h create mode 100644 ui/qt/widgets/qcp_axis_ticker_elided.cpp create mode 100644 ui/qt/widgets/qcp_axis_ticker_elided.h create mode 100644 ui/qt/widgets/qcp_axis_ticker_si.cpp create mode 100644 ui/qt/widgets/qcp_axis_ticker_si.h create mode 100644 ui/qt/widgets/qcp_string_legend_item.cpp create mode 100644 ui/qt/widgets/qcp_string_legend_item.h create mode 100644 ui/qt/widgets/resize_header_view.cpp create mode 100644 ui/qt/widgets/resize_header_view.h create mode 100644 ui/qt/widgets/resolved_addresses_view.cpp create mode 100644 ui/qt/widgets/resolved_addresses_view.h create mode 100644 ui/qt/widgets/rowmove_tree_view.cpp create mode 100644 ui/qt/widgets/rowmove_tree_view.h (limited to 'ui/qt') diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index 6a1aab9a..3308d6f2 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -22,6 +22,7 @@ set(WIRESHARK_WIDGET_HEADERS widgets/capture_filter_combo.h widgets/capture_filter_edit.h widgets/clickable_label.h + widgets/compression_group_box.h widgets/copy_from_profile_button.h widgets/detachable_tabwidget.h widgets/display_filter_combo.h @@ -45,7 +46,13 @@ set(WIRESHARK_WIDGET_HEADERS widgets/path_selection_edit.h widgets/pref_module_view.h widgets/profile_tree_view.h + widgets/qcp_axis_ticker_elided.h + widgets/qcp_axis_ticker_si.h + widgets/qcp_string_legend_item.h widgets/range_syntax_lineedit.h + widgets/resize_header_view.h + widgets/resolved_addresses_view.h + widgets/rowmove_tree_view.h widgets/rtp_audio_graph.h widgets/splash_overlay.h widgets/stock_icon_tool_button.h @@ -73,6 +80,7 @@ set(WIRESHARK_UTILS_HEADERS utils/field_information.h utils/frame_information.h utils/idata_printable.h + utils/profile_switcher.h utils/proto_node.h utils/qt_ui_utils.h utils/rtp_audio_file.h @@ -140,6 +148,7 @@ set(WIRESHARK_QT_HEADERS bluetooth_devices_dialog.h bluetooth_hci_summary_dialog.h byte_view_tab.h + capture_comment_dialog.h capture_file_dialog.h capture_file_properties_dialog.h capture_file.h @@ -171,7 +180,6 @@ set(WIRESHARK_QT_HEADERS file_set_dialog.h filter_action.h filter_dialog.h - filter_dialog.h filter_expression_frame.h firewall_rules_dialog.h follow_stream_action.h @@ -189,6 +197,7 @@ set(WIRESHARK_QT_HEADERS interface_toolbar_reader.h interface_toolbar.h io_console_dialog.h + io_graph_action.h io_graph_dialog.h layout_preferences_frame.h lbm_lbtrm_transport_dialog.h @@ -282,6 +291,7 @@ set(WIRESHARK_WIDGET_SRCS widgets/capture_filter_combo.cpp widgets/capture_filter_edit.cpp widgets/clickable_label.cpp + widgets/compression_group_box.cpp widgets/copy_from_profile_button.cpp widgets/detachable_tabwidget.cpp widgets/display_filter_combo.cpp @@ -305,7 +315,13 @@ set(WIRESHARK_WIDGET_SRCS widgets/path_selection_edit.cpp widgets/pref_module_view.cpp widgets/profile_tree_view.cpp + widgets/qcp_axis_ticker_elided.cpp + widgets/qcp_axis_ticker_si.cpp + widgets/qcp_string_legend_item.cpp widgets/range_syntax_lineedit.cpp + widgets/resize_header_view.cpp + widgets/resolved_addresses_view.cpp + widgets/rowmove_tree_view.cpp widgets/rtp_audio_graph.cpp widgets/splash_overlay.cpp widgets/stock_icon_tool_button.cpp @@ -332,6 +348,7 @@ set(WIRESHARK_UTILS_SRCS utils/data_printer.cpp utils/field_information.cpp utils/frame_information.cpp + utils/profile_switcher.cpp utils/proto_node.cpp utils/qt_ui_utils.cpp utils/rtp_audio_file.cpp @@ -394,6 +411,7 @@ set(WIRESHARK_QT_SRC bluetooth_devices_dialog.cpp bluetooth_hci_summary_dialog.cpp byte_view_tab.cpp + capture_comment_dialog.cpp capture_file_dialog.cpp capture_file_properties_dialog.cpp capture_file.cpp @@ -439,6 +457,7 @@ set(WIRESHARK_QT_SRC interface_toolbar_reader.cpp interface_toolbar.cpp io_console_dialog.cpp + io_graph_action.cpp layout_preferences_frame.cpp lbm_lbtrm_transport_dialog.cpp lbm_lbtru_transport_dialog.cpp @@ -558,6 +577,7 @@ set(WIRESHARK_QT_UI bluetooth_device_dialog.ui bluetooth_devices_dialog.ui bluetooth_hci_summary_dialog.ui + capture_comment_dialog.ui capture_file_properties_dialog.ui capture_info_dialog.ui capture_options_dialog.ui @@ -799,6 +819,9 @@ if(USE_qt6) if(Qt6Multimedia_FOUND) target_link_libraries(qtui PUBLIC Qt6::Multimedia) endif() + if(Qt6DBus_FOUND) + target_link_libraries(qtui PUBLIC Qt6::DBus) + endif() endif() target_include_directories(qtui @@ -810,6 +833,7 @@ target_include_directories(qtui ${QT5_INCLUDE_DIRS} ${GCRYPT_INCLUDE_DIRS} ${MINIZIP_INCLUDE_DIRS} + ${MINIZIPNG_INCLUDE_DIRS} ${PCAP_INCLUDE_DIRS} ${SPEEXDSP_INCLUDE_DIRS} ${WINSPARKLE_INCLUDE_DIRS} diff --git a/ui/qt/about_dialog.cpp b/ui/qt/about_dialog.cpp index 01513030..ea111228 100644 --- a/ui/qt/about_dialog.cpp +++ b/ui/qt/about_dialog.cpp @@ -29,16 +29,12 @@ #include #endif -#include "ui/alert_box.h" #include "ui/util.h" -#include "ui/help_url.h" -#include -#include "file.h" -#include "wsutil/file_util.h" -#include "wsutil/tempfile.h" +#include "wsutil/filesystem.h" #include "wsutil/plugins.h" #include "wsutil/version_info.h" + #include "ui/capture_globals.h" #include "extcap.h" @@ -100,7 +96,33 @@ QStringList AuthorListModel::headerColumns() const return QStringList() << tr("Name") << tr("Email"); } +#ifdef HAVE_PLUGINS static void plugins_add_description(const char *name, const char *version, + uint32_t flags, const char *filename, + void *user_data) +{ + QList *plugin_data = (QList *)user_data; + QStringList plugin_types; + if (flags & WS_PLUGIN_DESC_DISSECTOR) + plugin_types << "dissector"; + if (flags & WS_PLUGIN_DESC_FILE_TYPE) + plugin_types << "file type"; + if (flags & WS_PLUGIN_DESC_CODEC) + plugin_types << "codec"; + if (flags & WS_PLUGIN_DESC_EPAN) + plugin_types << "epan"; + if (flags & WS_PLUGIN_DESC_TAP_LISTENER) + plugin_types << "tap listener"; + if (flags & WS_PLUGIN_DESC_DFILTER) + plugin_types << "dfilter"; + if (plugin_types.empty()) + plugin_types << "unknown"; + QStringList plugin_row = QStringList() << name << version << plugin_types.join(", ") << filename; + *plugin_data << plugin_row; +} +#endif + +static void other_plugins_add_description(const char *name, const char *version, const char *types, const char *filename, void *user_data) { @@ -109,7 +131,7 @@ static void plugins_add_description(const char *name, const char *version, *plugin_data << plugin_row; } -PluginListModel::PluginListModel(QObject * parent) : AStringListListModel(parent) +PluginListModel::PluginListModel(QObject *parent) : AStringListListModel(parent) { QList plugin_data; #ifdef HAVE_PLUGINS @@ -117,10 +139,10 @@ PluginListModel::PluginListModel(QObject * parent) : AStringListListModel(parent #endif #ifdef HAVE_LUA - wslua_plugins_get_descriptions(plugins_add_description, &plugin_data); + wslua_plugins_get_descriptions(other_plugins_add_description, &plugin_data); #endif - extcap_get_descriptions(plugins_add_description, &plugin_data); + extcap_get_descriptions(other_plugins_add_description, &plugin_data); typeNames_ << QString(""); foreach(QStringList row, plugin_data) @@ -179,35 +201,36 @@ FolderListModel::FolderListModel(QObject * parent): AStringListListModel(parent) { /* "file open" */ - appendRow(QStringList() << tr("\"File\" dialogs") << get_open_dialog_initial_dir() << tr("capture files")); + appendRow(QStringList() << tr("\"File\" dialog location") << get_open_dialog_initial_dir() << tr("Capture files")); /* temp */ - appendRow(QStringList() << tr("Temp") << (global_capture_opts.temp_dir && global_capture_opts.temp_dir[0] ? global_capture_opts.temp_dir : g_get_tmp_dir()) << tr("untitled capture files")); + appendRow(QStringList() << tr("Temp") << (global_capture_opts.temp_dir && global_capture_opts.temp_dir[0] ? global_capture_opts.temp_dir : g_get_tmp_dir()) + << tr("Untitled capture files")); /* pers conf */ appendRow(QStringList() << tr("Personal configuration") - << gchar_free_to_qstring(get_persconffile_path("", FALSE)) - << tr("dfilters, preferences, ethers, …")); + << gchar_free_to_qstring(get_persconffile_path("", false)) + << tr("Preferences, profiles, manuf, …")); /* global conf */ QString dirPath = get_datafile_dir(); if (! dirPath.isEmpty()) { appendRow (QStringList() << tr("Global configuration") << dirPath - << tr("dfilters, preferences, manuf, …")); + << tr("Preferences, profiles, manuf, …")); } /* system */ appendRow(QStringList() << tr("System") << get_systemfile_dir() << tr("ethers, ipxnets")); /* program */ - appendRow(QStringList() << tr("Program") << get_progfile_dir() << tr("program files")); + appendRow(QStringList() << tr("Program") << get_progfile_dir() << tr("Program files")); #ifdef HAVE_PLUGINS /* pers plugins */ - appendRow(QStringList() << tr("Personal Plugins") << get_plugins_pers_dir_with_version() << tr("binary plugins")); + appendRow(QStringList() << tr("Personal Plugins") << get_plugins_pers_dir_with_version() << tr("Binary plugins")); /* global plugins */ - appendRow(QStringList() << tr("Global Plugins") << get_plugins_dir_with_version() << tr("binary plugins")); + appendRow(QStringList() << tr("Global Plugins") << get_plugins_dir_with_version() << tr("Binary plugins")); #endif #ifdef HAVE_LUA @@ -219,12 +242,12 @@ FolderListModel::FolderListModel(QObject * parent): #endif /* Extcap */ - appendRow(QStringList() << tr("Personal Extcap path") << QString(get_extcap_pers_dir()) << tr("external capture (extcap) plugins")); - appendRow(QStringList() << tr("Global Extcap path") << QString(get_extcap_dir()) << tr("external capture (extcap) plugins")); + appendRow(QStringList() << tr("Personal Extcap path") << QString(get_extcap_pers_dir()) << tr("External capture (extcap) plugins")); + appendRow(QStringList() << tr("Global Extcap path") << QString(get_extcap_dir()) << tr("External capture (extcap) plugins")); #ifdef HAVE_MAXMINDDB /* MaxMind DB */ - QStringList maxMindDbPaths = QString(maxmind_db_get_paths()).split(G_SEARCHPATH_SEPARATOR_S); + QStringList maxMindDbPaths = gchar_free_to_qstring(maxmind_db_get_paths()).split(G_SEARCHPATH_SEPARATOR_S); foreach(QString path, maxMindDbPaths) appendRow(QStringList() << tr("MaxMind DB path") << path.trimmed() << tr("MaxMind DB database search path")); #endif @@ -263,17 +286,10 @@ AboutDialog::AboutDialog(QWidget *parent) : QFile f_acknowledgements; QFile f_license; - AuthorListModel * authorModel = new AuthorListModel(this); - AStringListListSortFilterProxyModel * proxyAuthorModel = new AStringListListSortFilterProxyModel(this); - proxyAuthorModel->setSourceModel(authorModel); - proxyAuthorModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - proxyAuthorModel->setColumnToFilter(0); - proxyAuthorModel->setColumnToFilter(1); - ui->tblAuthors->setModel(proxyAuthorModel); - ui->tblAuthors->setRootIsDecorated(false); - ui->tblAuthors->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->tblAuthors, &QTreeView::customContextMenuRequested, this, &AboutDialog::handleCopyMenu); - connect(ui->searchAuthors, &QLineEdit::textChanged, proxyAuthorModel, &AStringListListSortFilterProxyModel::setFilter); + if (!is_packet_configuration_namespace()) { + setWindowTitle(tr("About Logray")); + ui->tabWidget->setTabText(ui->tabWidget->indexOf(ui->tab_wireshark), tr("Logray")); + } /* Wireshark tab */ updateWiresharkText(); @@ -286,11 +302,27 @@ AboutDialog::AboutDialog(QWidget *parent) : ui->label_logo->setPixmap(QPixmap(":/about/wssplash_dev.png")); #endif + /* Authors */ + AuthorListModel * authorModel = new AuthorListModel(this); + AStringListListSortFilterProxyModel * authorProxyModel = new AStringListListSortFilterProxyModel(this); + authorProxyModel->setSourceModel(authorModel); + authorProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + authorProxyModel->setColumnToFilter(0); + authorProxyModel->setColumnToFilter(1); + ui->tblAuthors->setModel(authorProxyModel); + ui->tblAuthors->setRootIsDecorated(false); + ui->tblAuthors->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->tblAuthors, &QTreeView::customContextMenuRequested, this, &AboutDialog::handleCopyMenu); + connect(ui->searchAuthors, &QLineEdit::textChanged, authorProxyModel, &AStringListListSortFilterProxyModel::setFilter); + /* Folders */ FolderListModel * folderModel = new FolderListModel(this); AStringListListSortFilterProxyModel * folderProxyModel = new AStringListListSortFilterProxyModel(this); folderProxyModel->setSourceModel(folderModel); + folderProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + folderProxyModel->setColumnToFilter(0); folderProxyModel->setColumnToFilter(1); + folderProxyModel->setColumnToFilter(2); folderProxyModel->setFilterType(AStringListListSortFilterProxyModel::FilterByStart); AStringListListUrlProxyModel * folderDisplayModel = new AStringListListUrlProxyModel(this); folderDisplayModel->setSourceModel(folderProxyModel); @@ -306,13 +338,16 @@ AboutDialog::AboutDialog(QWidget *parent) : connect(ui->searchFolders, &QLineEdit::textChanged, folderProxyModel, &AStringListListSortFilterProxyModel::setFilter); connect(ui->tblFolders, &QTreeView::doubleClicked, this, &AboutDialog::urlDoubleClicked); - /* Plugins */ ui->label_no_plugins->hide(); PluginListModel * pluginModel = new PluginListModel(this); AStringListListSortFilterProxyModel * pluginFilterModel = new AStringListListSortFilterProxyModel(this); pluginFilterModel->setSourceModel(pluginModel); + pluginFilterModel->setFilterCaseSensitivity(Qt::CaseInsensitive); pluginFilterModel->setColumnToFilter(0); + pluginFilterModel->setColumnToFilter(1); + pluginFilterModel->setColumnToFilter(2); + pluginFilterModel->setColumnToFilter(3); AStringListListSortFilterProxyModel * pluginTypeModel = new AStringListListSortFilterProxyModel(this); pluginTypeModel->setSourceModel(pluginFilterModel); pluginTypeModel->setColumnToFilter(2); @@ -344,6 +379,7 @@ AboutDialog::AboutDialog(QWidget *parent) : AStringListListSortFilterProxyModel * shortcutProxyModel = new AStringListListSortFilterProxyModel(this); shortcutProxyModel->setSourceModel(shortcutModel); shortcutProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + shortcutProxyModel->setColumnToFilter(0); shortcutProxyModel->setColumnToFilter(1); shortcutProxyModel->setColumnToFilter(2); ui->tblShortcuts->setModel(shortcutProxyModel); @@ -438,7 +474,7 @@ void AboutDialog::showEvent(QShowEvent * event) void AboutDialog::updateWiresharkText() { - QString vcs_version_info_str = get_ws_vcs_version_info(); + QString vcs_version_info_str = is_packet_configuration_namespace() ? get_ws_vcs_version_info() : get_lr_vcs_version_info(); QString copyright_info_str = get_copyright_info(); QString license_info_str = get_license_info(); QString comp_info_str = gstring_free_to_qbytearray(get_compiled_version_info(gather_wireshark_qt_compiled_info)); diff --git a/ui/qt/about_dialog.ui b/ui/qt/about_dialog.ui index 4b515de0..bb6de142 100644 --- a/ui/qt/about_dialog.ui +++ b/ui/qt/about_dialog.ui @@ -157,7 +157,7 @@ - Filter by path + Search Folders diff --git a/ui/qt/accordion_frame.cpp b/ui/qt/accordion_frame.cpp index 8f8cc430..bc1a77d5 100644 --- a/ui/qt/accordion_frame.cpp +++ b/ui/qt/accordion_frame.cpp @@ -8,7 +8,6 @@ */ #include "config.h" -#include #include "accordion_frame.h" @@ -104,4 +103,4 @@ void AccordionFrame::updateStyleSheet() #endif setStyleSheet(style_sheet); -} \ No newline at end of file +} diff --git a/ui/qt/address_editor_frame.cpp b/ui/qt/address_editor_frame.cpp index fb044418..034ac27b 100644 --- a/ui/qt/address_editor_frame.cpp +++ b/ui/qt/address_editor_frame.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include "file.h" #include "frame_tvbuff.h" @@ -55,8 +53,9 @@ AddressEditorFrame::~AddressEditorFrame() QString AddressEditorFrame::addressToString(const FieldInformation& finfo) { address addr; - ws_in4_addr ipv4; - const ws_in6_addr* ipv6; + QString addr_str; + const ipv4_addr_and_mask *ipv4; + const ipv6_addr_and_prefix *ipv6; if (!finfo.isValid()) { return QString(); @@ -69,18 +68,24 @@ QString AddressEditorFrame::addressToString(const FieldInformation& finfo) // proto_item_fill_display_label, but that gives us // the currently resolved version, if resolution is // available and enabled. We want the unresolved string. - ipv4 = fvalue_get_uinteger(finfo.fieldInfo()->value); - set_address(&addr, AT_IPv4, 4, &ipv4); - return gchar_free_to_qstring(address_to_str(NULL, &addr)); + ipv4 = fvalue_get_ipv4(finfo.fieldInfo()->value); + set_address_ipv4(&addr, ipv4); + addr_str = gchar_free_to_qstring(address_to_str(NULL, &addr)); + free_address(&addr); + break; case FT_IPv6: ipv6 = fvalue_get_ipv6(finfo.fieldInfo()->value); - set_address(&addr, AT_IPv6, sizeof(ws_in6_addr), ipv6); - return gchar_free_to_qstring(address_to_str(NULL, &addr)); + set_address_ipv6(&addr, ipv6); + addr_str = gchar_free_to_qstring(address_to_str(NULL, &addr)); + free_address(&addr); + break; default: - return QString(); + addr_str = QString(); } + return addr_str; } +// NOLINTNEXTLINE(misc-no-recursion) void AddressEditorFrame::addAddresses(const ProtoNode& node, QStringList& addresses) { QString addrString = addressToString(FieldInformation(&node)); @@ -89,6 +94,7 @@ void AddressEditorFrame::addAddresses(const ProtoNode& node, QStringList& addres } ProtoNode::ChildIterator kids = node.children(); while (kids.element().isValid()) { + // We recurse here, but we're limited by tree depth checks in epan addAddresses(kids.element(), addresses); kids.next(); } @@ -119,13 +125,13 @@ void AddressEditorFrame::editAddresses(CaptureFile &cf, int column) // have one in cap_file_->edt->tree as we have a current frame), but // this is only a single frame that's previously been dissected so // the performance hit is slight anyway. - epan_dissect_init(&edt, cap_file_->epan, TRUE, TRUE); + epan_dissect_init(&edt, cap_file_->epan, true, true); col_custom_prime_edt(&edt, &cap_file_->cinfo); epan_dissect_run(&edt, cap_file_->cd_t, &cap_file_->rec, frame_tvbuff_new_buffer(&cap_file_->provider, cap_file_->current_frame, &cap_file_->buf), cap_file_->current_frame, &cap_file_->cinfo); - epan_dissect_fill_in_columns(&edt, TRUE, TRUE); + epan_dissect_fill_in_columns(&edt, true, true); addAddresses(ProtoNode(edt.tree), addresses); diff --git a/ui/qt/bluetooth_att_server_attributes_dialog.cpp b/ui/qt/bluetooth_att_server_attributes_dialog.cpp index 00330b3c..8191d495 100644 --- a/ui/qt/bluetooth_att_server_attributes_dialog.cpp +++ b/ui/qt/bluetooth_att_server_attributes_dialog.cpp @@ -52,6 +52,24 @@ btatt_handle_tap_reset(void *tapinfo_ptr) tapinfo->tap_reset(tapinfo); } +static QTreeWidgetItem * +item_with_handle_get(QTreeWidget *tableTree, uint16_t handle) +{ + QTreeWidgetItemIterator i_item(tableTree); + + while (*i_item) { + QTreeWidgetItem *item = static_cast(*i_item); + + if (item->data(1, Qt::UserRole).value() == handle) { + return item; + } + + ++i_item; + } + + return NULL; +} + BluetoothAttServerAttributesDialog::BluetoothAttServerAttributesDialog(QWidget &parent, CaptureFile &cf) : WiresharkDialog(parent, cf), ui(new Ui::BluetoothAttServerAttributesDialog) @@ -98,9 +116,9 @@ BluetoothAttServerAttributesDialog::~BluetoothAttServerAttributesDialog() void BluetoothAttServerAttributesDialog::captureFileClosed() { - ui->interfaceComboBox->setEnabled(FALSE); - ui->deviceComboBox->setEnabled(FALSE); - ui->removeDuplicatesCheckBox->setEnabled(FALSE); + ui->interfaceComboBox->setEnabled(false); + ui->deviceComboBox->setEnabled(false); + ui->removeDuplicatesCheckBox->setEnabled(false); WiresharkDialog::captureFileClosed(); } @@ -170,11 +188,11 @@ void BluetoothAttServerAttributesDialog::on_actionMark_Unmark_Row_triggered() QBrush fg; QBrush bg; - bool is_marked = TRUE; + bool is_marked = true; for (int i = 0; i < ui->tableTreeWidget->columnCount(); i += 1) { if (current_item->background(i) != QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg))) - is_marked = FALSE; + is_marked = false; } if (is_marked) { @@ -245,7 +263,7 @@ tap_packet_status BluetoothAttServerAttributesDialog::tapPacket(void *tapinfo_pt QString handle; QString uuid; QString uuid_name; - gchar *addr = NULL; + char *addr = NULL; if (dialog->file_closed_) return TAP_PACKET_DONT_REDRAW; @@ -254,10 +272,11 @@ tap_packet_status BluetoothAttServerAttributesDialog::tapPacket(void *tapinfo_pt return TAP_PACKET_DONT_REDRAW; if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) { - gchar *interface; + char *interface; const char *interface_name; - interface_name = epan_get_interface_name(pinfo->epan, pinfo->rec->rec_header.packet_header.interface_id); + unsigned section_number = pinfo->rec->presence_flags & WTAP_HAS_SECTION_NUMBER ? pinfo->rec->section_number : 0; + interface_name = epan_get_interface_name(pinfo->epan, pinfo->rec->rec_header.packet_header.interface_id, section_number); interface = wmem_strdup_printf(pinfo->pool, "%u: %s", pinfo->rec->rec_header.packet_header.interface_id, interface_name); if (dialog->ui->interfaceComboBox->findText(interface) == -1) @@ -286,24 +305,48 @@ tap_packet_status BluetoothAttServerAttributesDialog::tapPacket(void *tapinfo_pt uuid_name = QString(print_bluetooth_uuid(pinfo->pool, &tap_handles->uuid)); if (dialog->ui->removeDuplicatesCheckBox->checkState() == Qt::Checked) { - QTreeWidgetItemIterator i_item(dialog->ui->tableTreeWidget); - - while (*i_item) { - QTreeWidgetItem *item = static_cast(*i_item); + QTreeWidgetItem *item = item_with_handle_get(dialog->ui->tableTreeWidget, + tap_handles->handle); + if (item) { if (item->text(column_number_handle) == handle && item->text(column_number_uuid) == uuid && item->text(column_number_uuid_name) == uuid_name) return TAP_PACKET_REDRAW; - ++i_item; } } - QTreeWidgetItem *item = new QTreeWidgetItem(dialog->ui->tableTreeWidget); - item->setText(column_number_handle, handle); - item->setText(column_number_uuid, uuid); - item->setText(column_number_uuid_name, uuid_name); - item->setData(0, Qt::UserRole, QVariant::fromValue(pinfo->num)); + QTreeWidgetItem *parent = NULL; + + if (tap_handles->attribute_type == ATTRIBUTE_TYPE_SERVICE) { + /* Service declarations are the top level items */ + parent = dialog->ui->tableTreeWidget->invisibleRootItem(); + } else if ((tap_handles->uuid.bt_uuid == UUID_GATT_INCLUDE_DECLARATION) || + (tap_handles->uuid.bt_uuid == UUID_GATT_CHARACTERISTIC_DECLARATION)) { + /* Characteristic and include declarations are part of services. */ + parent = item_with_handle_get(dialog->ui->tableTreeWidget, + tap_handles->service_handle); + } else { + /* Each characteristic may have several attributes. */ + parent = item_with_handle_get(dialog->ui->tableTreeWidget, + tap_handles->char_decl_handle); + } + + if (parent) { + QTreeWidgetItem *item = new QTreeWidgetItem(parent); + + item->setText(column_number_handle, handle); + item->setText(column_number_uuid, uuid); + item->setText(column_number_uuid_name, uuid_name); + item->setData(0, Qt::UserRole, QVariant::fromValue(pinfo->num)); + item->setData(1, Qt::UserRole, QVariant::fromValue(tap_handles->handle)); + + parent->setExpanded(true); + } else { + /* Do not insert items without a known parent into the tree. + * The parent will likely be found later. + */ + } for (int i = 0; i < dialog->ui->tableTreeWidget->columnCount(); i++) { dialog->ui->tableTreeWidget->resizeColumnToContents(i); @@ -336,7 +379,7 @@ void BluetoothAttServerAttributesDialog::on_tableTreeWidget_itemActivated(QTreeW if (file_closed_) return; - guint32 frame_number = item->data(0, Qt::UserRole).value(); + uint32_t frame_number = item->data(0, Qt::UserRole).value(); emit goToPacket(frame_number); } diff --git a/ui/qt/bluetooth_att_server_attributes_dialog.h b/ui/qt/bluetooth_att_server_attributes_dialog.h index 2d2a4f88..b377d9cc 100644 --- a/ui/qt/bluetooth_att_server_attributes_dialog.h +++ b/ui/qt/bluetooth_att_server_attributes_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include "wireshark_dialog.h" #include "cfile.h" diff --git a/ui/qt/bluetooth_att_server_attributes_dialog.ui b/ui/qt/bluetooth_att_server_attributes_dialog.ui index ba67973f..a51d3864 100644 --- a/ui/qt/bluetooth_att_server_attributes_dialog.ui +++ b/ui/qt/bluetooth_att_server_attributes_dialog.ui @@ -35,7 +35,7 @@ false - false + true true diff --git a/ui/qt/bluetooth_device_dialog.cpp b/ui/qt/bluetooth_device_dialog.cpp index 6e679b8a..d9729c5b 100644 --- a/ui/qt/bluetooth_device_dialog.cpp +++ b/ui/qt/bluetooth_device_dialog.cpp @@ -100,7 +100,7 @@ bluetooth_devices_tap(void *data) } -BluetoothDeviceDialog::BluetoothDeviceDialog(QWidget &parent, CaptureFile &cf, QString bdAddr, QString name, guint32 interface_id, guint32 adapter_id, gboolean is_local) : +BluetoothDeviceDialog::BluetoothDeviceDialog(QWidget &parent, CaptureFile &cf, QString bdAddr, QString name, uint32_t interface_id, uint32_t adapter_id, bool is_local) : WiresharkDialog(parent, cf), ui(new Ui::BluetoothDeviceDialog) { @@ -234,7 +234,7 @@ void BluetoothDeviceDialog::on_actionMark_Unmark_Row_triggered() { QBrush fg; QBrush bg; - bool is_marked = TRUE; + bool is_marked = true; QTableWidgetItem *current_item = ui->tableWidget->currentItem(); if (!current_item) @@ -243,7 +243,7 @@ void BluetoothDeviceDialog::on_actionMark_Unmark_Row_triggered() for (int i = 0; i < ui->tableWidget->columnCount(); i += 1) { QTableWidgetItem *item = ui->tableWidget->item(current_item->row(), i); if (item->background() != QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg))) - is_marked = FALSE; + is_marked = false; } if (is_marked) { @@ -339,7 +339,7 @@ void BluetoothDeviceDialog::tapReset(void *tapinfo_ptr) *tapinfo->changes = 0; } -void BluetoothDeviceDialog::updateChanges(QTableWidget *tableWidget, QString value, const int row, guint *changes, packet_info *pinfo) +void BluetoothDeviceDialog::updateChanges(QTableWidget *tableWidget, QString value, const int row, unsigned *changes, packet_info *pinfo) { QTableWidgetItem *item = tableWidget->item(row, column_number_value); bluetooth_item_data_t *item_data = VariantPointer::asPtr(item->data(Qt::UserRole)); @@ -379,7 +379,7 @@ tap_packet_status BluetoothDeviceDialog::tapPacket(void *tapinfo_ptr, packet_inf bluetooth_device_tap_t *tap_device = static_cast(const_cast(data)); QString bd_addr; QString bd_addr_oui; - const gchar *manuf; + const char *manuf; QTableWidget *tableWidget; QTableWidgetItem *item; QString field; diff --git a/ui/qt/bluetooth_device_dialog.h b/ui/qt/bluetooth_device_dialog.h index 7ae37bce..a0b408f0 100644 --- a/ui/qt/bluetooth_device_dialog.h +++ b/ui/qt/bluetooth_device_dialog.h @@ -12,8 +12,6 @@ #include "config.h" -#include - #include "wireshark_dialog.h" #include "cfile.h" @@ -32,18 +30,18 @@ typedef struct _bluetooth_device_tapinfo_t { tap_reset_cb tap_reset; tap_packet_cb tap_packet; QString bdAddr; - guint32 interface_id; - guint32 adapter_id; - gboolean is_local; + uint32_t interface_id; + uint32_t adapter_id; + bool is_local; void *ui; - guint *changes; + unsigned *changes; } bluetooth_device_tapinfo_t; typedef struct _bluetooth_item_data_t { - guint32 interface_id; - guint32 adapter_id; - guint32 frame_number; - gint changes; + uint32_t interface_id; + uint32_t adapter_id; + uint32_t frame_number; + int changes; } bluetooth_item_data_t; namespace Ui { @@ -55,7 +53,7 @@ class BluetoothDeviceDialog : public WiresharkDialog Q_OBJECT public: - explicit BluetoothDeviceDialog(QWidget &parent, CaptureFile &cf, QString bdAddr, QString name, guint32 interface_id, guint32 adapter_id, gboolean is_local); + explicit BluetoothDeviceDialog(QWidget &parent, CaptureFile &cf, QString bdAddr, QString name, uint32_t interface_id, uint32_t adapter_id, bool is_local); ~BluetoothDeviceDialog(); public slots: @@ -77,11 +75,11 @@ private: bluetooth_device_tapinfo_t tapinfo_; QMenu context_menu_; - guint changes_; + unsigned changes_; static void tapReset(void *tapinfo_ptr); static tap_packet_status tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *data, tap_flags_t flags); - static void updateChanges(QTableWidget *tableWidget, QString value, const int row, guint *changes, packet_info *pinfo); + static void updateChanges(QTableWidget *tableWidget, QString value, const int row, unsigned *changes, packet_info *pinfo); static void saveItemData(QTableWidgetItem *item, bluetooth_device_tap_t *tap_device, packet_info *pinfo); private slots: diff --git a/ui/qt/bluetooth_devices_dialog.cpp b/ui/qt/bluetooth_devices_dialog.cpp index 87d77772..0772b3d7 100644 --- a/ui/qt/bluetooth_devices_dialog.cpp +++ b/ui/qt/bluetooth_devices_dialog.cpp @@ -112,8 +112,8 @@ BluetoothDevicesDialog::~BluetoothDevicesDialog() void BluetoothDevicesDialog::captureFileClosed() { - ui->interfaceComboBox->setEnabled(FALSE); - ui->showInformationStepsCheckBox->setEnabled(FALSE); + ui->interfaceComboBox->setEnabled(false); + ui->showInformationStepsCheckBox->setEnabled(false); WiresharkDialog::captureFileClosed(); } @@ -187,11 +187,11 @@ void BluetoothDevicesDialog::on_actionMark_Unmark_Row_triggered() { QBrush fg; QBrush bg; - bool is_marked = TRUE; + bool is_marked = true; for (int i = 0; i < ui->tableTreeWidget->columnCount(); i += 1) { if (ui->tableTreeWidget->currentItem()->background(i) != QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg))) - is_marked = FALSE; + is_marked = false; } if (is_marked) { @@ -260,7 +260,7 @@ tap_packet_status BluetoothDevicesDialog::tapPacket(void *tapinfo_ptr, packet_in bluetooth_device_tap_t *tap_device = static_cast(const_cast(data)); QString bd_addr; QString bd_addr_oui; - const gchar *manuf; + const char *manuf; QTreeWidgetItem *item = NULL; if (dialog->file_closed_) @@ -270,10 +270,11 @@ tap_packet_status BluetoothDevicesDialog::tapPacket(void *tapinfo_ptr, packet_in return TAP_PACKET_DONT_REDRAW; if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) { - gchar *interface; + char *interface; const char *interface_name; - interface_name = epan_get_interface_name(pinfo->epan, pinfo->rec->rec_header.packet_header.interface_id); + unsigned section_number = pinfo->rec->presence_flags & WTAP_HAS_SECTION_NUMBER ? pinfo->rec->section_number : 0; + interface_name = epan_get_interface_name(pinfo->epan, pinfo->rec->rec_header.packet_header.interface_id, section_number); interface = wmem_strdup_printf(pinfo->pool, "%u: %s", pinfo->rec->rec_header.packet_header.interface_id, interface_name); if (dialog->ui->interfaceComboBox->findText(interface) == -1) diff --git a/ui/qt/bluetooth_devices_dialog.h b/ui/qt/bluetooth_devices_dialog.h index cf78d9a0..d26039d7 100644 --- a/ui/qt/bluetooth_devices_dialog.h +++ b/ui/qt/bluetooth_devices_dialog.h @@ -12,8 +12,6 @@ #include "config.h" -#include - #include "wireshark_dialog.h" #include "cfile.h" #include "packet_list.h" diff --git a/ui/qt/bluetooth_hci_summary_dialog.cpp b/ui/qt/bluetooth_hci_summary_dialog.cpp index 15d2df5e..c4e59283 100644 --- a/ui/qt/bluetooth_hci_summary_dialog.cpp +++ b/ui/qt/bluetooth_hci_summary_dialog.cpp @@ -157,8 +157,8 @@ void BluetoothHciSummaryDialog::captureFileClosing() void BluetoothHciSummaryDialog::captureFileClosed() { - ui->interfaceComboBox->setEnabled(FALSE); - ui->adapterComboBox->setEnabled(FALSE); + ui->interfaceComboBox->setEnabled(false); + ui->adapterComboBox->setEnabled(false); WiresharkDialog::captureFileClosed(); } @@ -232,11 +232,11 @@ void BluetoothHciSummaryDialog::on_actionMark_Unmark_Row_triggered() { QBrush fg; QBrush bg; - bool is_marked = TRUE; + bool is_marked = true; for (int i = 0; i < ui->tableTreeWidget->columnCount(); i += 1) { if (ui->tableTreeWidget->currentItem()->background(i) != QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg))) - is_marked = FALSE; + is_marked = false; } if (is_marked) { @@ -360,10 +360,11 @@ tap_packet_status BluetoothHciSummaryDialog::tapPacket(void *tapinfo_ptr, packet name = tr("Unknown"); if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) { - gchar *interface; + char *interface; const char *interface_name; - interface_name = epan_get_interface_name(pinfo->epan, pinfo->rec->rec_header.packet_header.interface_id); + unsigned section_number = pinfo->rec->presence_flags & WTAP_HAS_SECTION_NUMBER ? pinfo->rec->section_number : 0; + interface_name = epan_get_interface_name(pinfo->epan, pinfo->rec->rec_header.packet_header.interface_id, section_number); interface = wmem_strdup_printf(pinfo->pool, "%u: %s", pinfo->rec->rec_header.packet_header.interface_id, interface_name); if (dialog->ui->interfaceComboBox->findText(interface) == -1) diff --git a/ui/qt/bluetooth_hci_summary_dialog.h b/ui/qt/bluetooth_hci_summary_dialog.h index 8bba405e..61796640 100644 --- a/ui/qt/bluetooth_hci_summary_dialog.h +++ b/ui/qt/bluetooth_hci_summary_dialog.h @@ -12,8 +12,6 @@ #include "config.h" -#include - #include "wireshark_dialog.h" #include "cfile.h" #include "packet_list.h" diff --git a/ui/qt/byte_view_tab.cpp b/ui/qt/byte_view_tab.cpp index cf23c24c..6cb8add7 100644 --- a/ui/qt/byte_view_tab.cpp +++ b/ui/qt/byte_view_tab.cpp @@ -308,7 +308,7 @@ void ByteViewTab::selectedFieldChanged(FieldInformation *selected) if (cap_file_->search_in_progress && (cap_file_->hex || (cap_file_->string && cap_file_->packet_data))) { // In the hex view, only highlight the target bytes or string. The entire // field can then be displayed by clicking on any of the bytes in the field. - f_start = cap_file_->search_pos - cap_file_->search_len + 1; + f_start = (int)cap_file_->search_pos; f_length = (int) cap_file_->search_len; } else { f_start = selected->position().start; diff --git a/ui/qt/capture_comment_dialog.cpp b/ui/qt/capture_comment_dialog.cpp new file mode 100644 index 00000000..8bea4ca4 --- /dev/null +++ b/ui/qt/capture_comment_dialog.cpp @@ -0,0 +1,252 @@ +/* packet_comment_dialog.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "capture_comment_dialog.h" +#include + +#include "file.h" + +#include "ui/simple_dialog.h" +#include "ui/qt/utils/qt_ui_utils.h" +#include "main_application.h" + +#include +#include +#include + +class CaptureCommentTabWidget : public QTabWidget +{ + Q_OBJECT +public: + CaptureCommentTabWidget(QWidget *parent = nullptr) : QTabWidget(parent) + { + + setTabsClosable(true); + setMovable(true); + connect(this, &QTabWidget::tabCloseRequested, this, &CaptureCommentTabWidget::closeTab); + connect(tabBar(), &QTabBar::tabMoved, this, &CaptureCommentTabWidget::setTabTitles); + } + int addTab(QWidget *page); + void tabRemoved(int index) override; + void closeTab(int index); + void setReadOnly(bool ro); + char** getCommentsText(); + +private: + void setTabTitles(int from, int to); +}; + +int CaptureCommentTabWidget::addTab(QWidget *page) +{ + return QTabWidget::addTab(page, tr("Comment %1").arg(count() + 1)); +} + +void CaptureCommentTabWidget::closeTab(int index) +{ + QPlainTextEdit *te; + te = qobject_cast(widget(index)); + if (te != nullptr) { + removeTab(index); + delete te; + } +} + +void CaptureCommentTabWidget::setReadOnly(bool ro) +{ + QPlainTextEdit *commentTextEdit; + for (int index = 0; index < count(); index++) { + commentTextEdit = qobject_cast(widget(index)); + if (commentTextEdit != nullptr) { + commentTextEdit->setReadOnly(ro); + } + } +} + +void CaptureCommentTabWidget::tabRemoved(int index) +{ + setTabTitles(index, count() - 1); +} + +char** CaptureCommentTabWidget::getCommentsText() +{ + /* glib 2.68 and later have g_strv_builder which is slightly + * more convenient. + */ + QPlainTextEdit *te; + GPtrArray *ptr_array = g_ptr_array_new_full(count() + 1, g_free); + for (int index = 0; index < count(); index++) { + te = qobject_cast(widget(index)); + if (te != nullptr) { + char *str = qstring_strdup(te->toPlainText()); + + /* + * Make sure this would fit in a pcapng option. + * + * XXX - 65535 is the maximum size for an option in pcapng; + * what if another capture file format supports larger + * comments? + */ + if (strlen(str) > 65535) { + /* It doesn't fit. Give up. */ + g_ptr_array_free(ptr_array, true); + return nullptr; + } + g_ptr_array_add(ptr_array, str); + } + } + g_ptr_array_add(ptr_array, nullptr); + return (char**)g_ptr_array_free(ptr_array, false); +} + +void CaptureCommentTabWidget::setTabTitles(int from, int to) +{ + if (from < to) { + for (; from <= to; from++) { + this->setTabText(from, tr("Comment %1").arg(from + 1)); + } + } else { + for (; from >= to; from--) { + this->setTabText(from, tr("Comment %1").arg(from + 1)); + } + } +} + +CaptureCommentDialog::CaptureCommentDialog(QWidget &parent, CaptureFile &capture_file) : + WiresharkDialog(parent, capture_file), + ui(new Ui::CaptureCommentDialog) +{ + + ui->setupUi(this); + loadGeometry(); + setWindowSubtitle(tr("Edit Capture Comments")); + + ui->sectionTabWidget->setTabBarAutoHide(true); + this->actionAddButton = ui->buttonBox->addButton(tr("Add Comment"), QDialogButtonBox::ActionRole); + connect(this->actionAddButton, &QPushButton::clicked, this, &CaptureCommentDialog::addComment); + + connect(this, SIGNAL(captureCommentChanged()), + mainApp->mainWindow(), SLOT(updateForUnsavedChanges())); + QTimer::singleShot(0, this, SLOT(updateWidgets())); +} + +CaptureCommentDialog::~CaptureCommentDialog() +{ + delete ui; +} + +void CaptureCommentDialog::addComment() +{ + QPlainTextEdit *commentTextEdit; + CaptureCommentTabWidget *currentTW = qobject_cast(ui->sectionTabWidget->currentWidget()); + if (currentTW != nullptr) { + commentTextEdit = new QPlainTextEdit(currentTW); + + currentTW->addTab(commentTextEdit); + } +} + +void CaptureCommentDialog::updateWidgets() +{ + QPlainTextEdit *commentTextEdit; + CaptureCommentTabWidget *shbTW; + QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save); + + if (file_closed_ || !cap_file_.isValid()) { + for (int shb = 0; shb < ui->sectionTabWidget->count(); shb++) { + shbTW = qobject_cast(ui->sectionTabWidget->widget(shb)); + shbTW->setReadOnly(true); + } + if (save_bt) { + save_bt->setEnabled(false); + } + actionAddButton->setEnabled(false); + WiresharkDialog::updateWidgets(); + return; + } + + bool enable = wtap_dump_can_write(cap_file_.capFile()->linktypes, WTAP_COMMENT_PER_SECTION); + save_bt->setEnabled(enable); + actionAddButton->setEnabled(enable); + + unsigned num_shbs = wtap_file_get_num_shbs(cap_file_.capFile()->provider.wth); + for (unsigned shb_idx = 0; shb_idx < num_shbs; shb_idx++) { + shbTW = qobject_cast(ui->sectionTabWidget->widget(shb_idx)); + if (shbTW == nullptr) { + shbTW = new CaptureCommentTabWidget(ui->sectionTabWidget); + ui->sectionTabWidget->addTab(shbTW, tr("Section %1").arg(shb_idx + 1)); + } + wtap_block_t shb = wtap_file_get_shb(cap_file_.capFile()->provider.wth, shb_idx); + unsigned num_comments = wtap_block_count_option(shb, OPT_COMMENT); + char *shb_comment; + for (unsigned index = 0; index < num_comments; index++) { + commentTextEdit = qobject_cast(shbTW->widget(index)); + if (commentTextEdit == nullptr) { + commentTextEdit = new QPlainTextEdit(shbTW); + shbTW->addTab(commentTextEdit); + } + if (wtap_block_get_nth_string_option_value(shb, OPT_COMMENT, index, + &shb_comment) == WTAP_OPTTYPE_SUCCESS) { + commentTextEdit->setPlainText(shb_comment); + } else { + // XXX: Should we warn about this failure? + commentTextEdit->setPlainText(""); + } + commentTextEdit->setReadOnly(!enable); + } + for (unsigned index = shbTW->count(); index > num_comments; index--) { + shbTW->closeTab(index - 1); + } + } + + WiresharkDialog::updateWidgets(); +} + +void CaptureCommentDialog::on_buttonBox_helpRequested() +{ +// mainApp->helpTopicAction(HELP_CAPTURE_COMMENT_DIALOG); +} + +void CaptureCommentDialog::on_buttonBox_accepted() +{ + int ret = QDialog::Rejected; + + if (file_closed_ || !cap_file_.capFile()->filename) { + done(ret); + return; + } + + if (wtap_dump_can_write(cap_file_.capFile()->linktypes, WTAP_COMMENT_PER_SECTION)) + { + CaptureCommentTabWidget *current; + char** comments_text; + for (int shb_idx = 0; shb_idx < ui->sectionTabWidget->count(); shb_idx++) { + current = qobject_cast(ui->sectionTabWidget->widget(shb_idx)); + comments_text = current->getCommentsText(); + if (comments_text == nullptr) { + /* This is the only error we track currently, so it must be + * this. Tell the user and give up. */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + "A comment is too large to save in a capture file."); + done(ret); + return; + } + cf_update_section_comments(cap_file_.capFile(), shb_idx, comments_text); + emit captureCommentChanged(); + ret = QDialog::Accepted; + } + } + done(ret); +} + +void CaptureCommentDialog::on_buttonBox_rejected() +{ + reject(); +} + +#include "capture_comment_dialog.moc" diff --git a/ui/qt/capture_comment_dialog.h b/ui/qt/capture_comment_dialog.h new file mode 100644 index 00000000..5e7cb2b3 --- /dev/null +++ b/ui/qt/capture_comment_dialog.h @@ -0,0 +1,42 @@ +/** @file + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef CAPTURE_COMMENT_DIALOG_H +#define CAPTURE_COMMENT_DIALOG_H + +#include "wireshark_dialog.h" + +namespace Ui { +class CaptureCommentDialog; +} + +class CaptureCommentDialog : public WiresharkDialog +{ + Q_OBJECT + +public: + explicit CaptureCommentDialog(QWidget &parent, CaptureFile &capture_file); + ~CaptureCommentDialog(); + +signals: + void captureCommentChanged(); + +private slots: + void addComment(); + void updateWidgets(); + void on_buttonBox_helpRequested(); + void on_buttonBox_accepted(); + void on_buttonBox_rejected(); + +private: + QPushButton *actionAddButton; + Ui::CaptureCommentDialog *ui; +}; + +#endif // CAPTURE_COMMENT_DIALOG_H diff --git a/ui/qt/capture_comment_dialog.ui b/ui/qt/capture_comment_dialog.ui new file mode 100644 index 00000000..a30dec03 --- /dev/null +++ b/ui/qt/capture_comment_dialog.ui @@ -0,0 +1,33 @@ + + + CaptureCommentDialog + + + + 0 + 0 + 400 + 300 + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Save + + + + + + + diff --git a/ui/qt/capture_event.h b/ui/qt/capture_event.h index b4db282b..3959ed17 100644 --- a/ui/qt/capture_event.h +++ b/ui/qt/capture_event.h @@ -11,6 +11,7 @@ #define CAPTURE_EVENT_H #include +#include typedef struct _capture_session capture_session; diff --git a/ui/qt/capture_file.cpp b/ui/qt/capture_file.cpp index 0fd088b9..5de2c9d4 100644 --- a/ui/qt/capture_file.cpp +++ b/ui/qt/capture_file.cpp @@ -85,9 +85,9 @@ CaptureFile::CaptureFile(QObject *parent, capture_file *cap_file) : file_state_(QString()) { #ifdef HAVE_LIBPCAP - capture_callback_add(captureCallback, (gpointer) this); + capture_callback_add(captureCallback, (void *) this); #endif - cf_callback_add(captureFileCallback, (gpointer) this); + cf_callback_add(captureFileCallback, (void *) this); } CaptureFile::~CaptureFile() @@ -239,7 +239,7 @@ capture_file *CaptureFile::globalCapFile() return &cfile; } -gpointer CaptureFile::window() +void *CaptureFile::window() { if (cap_file_) return cap_file_->window; return NULL; @@ -250,7 +250,7 @@ void CaptureFile::setCaptureStopFlag(bool stop_flag) if (cap_file_) cap_file_->stop_flag = stop_flag; } -void CaptureFile::captureFileCallback(gint event, gpointer data, gpointer user_data) +void CaptureFile::captureFileCallback(int event, void *data, void *user_data) { CaptureFile *capture_file = static_cast(user_data); if (!capture_file) return; @@ -259,7 +259,7 @@ void CaptureFile::captureFileCallback(gint event, gpointer data, gpointer user_d } #ifdef HAVE_LIBPCAP -void CaptureFile::captureCallback(gint event, capture_session *cap_session, gpointer user_data) +void CaptureFile::captureCallback(int event, capture_session *cap_session, void *user_data) { CaptureFile *capture_file = static_cast(user_data); if (!capture_file) return; @@ -268,7 +268,7 @@ void CaptureFile::captureCallback(gint event, capture_session *cap_session, gpoi } #endif -void CaptureFile::captureFileEvent(int event, gpointer data) +void CaptureFile::captureFileEvent(int event, void *data) { switch(event) { case(cf_cb_file_opened): diff --git a/ui/qt/capture_file.h b/ui/qt/capture_file.h index 2249f8e0..89be807f 100644 --- a/ui/qt/capture_file.h +++ b/ui/qt/capture_file.h @@ -14,8 +14,6 @@ #include -#include - #include "cfile.h" #include "capture_event.h" @@ -117,7 +115,7 @@ public: // XXX This shouldn't be needed. static capture_file *globalCapFile(); - gpointer window(); + void *window(); signals: void captureEvent(CaptureEvent); @@ -146,12 +144,12 @@ public slots: void setCaptureStopFlag(bool stop_flag = true); private: - static void captureFileCallback(gint event, gpointer data, gpointer user_data); + static void captureFileCallback(int event, void *data, void *user_data); #ifdef HAVE_LIBPCAP - static void captureCallback(gint event, capture_session *cap_session, gpointer user_data); + static void captureCallback(int event, capture_session *cap_session, void *user_data); #endif - void captureFileEvent(int event, gpointer data); + void captureFileEvent(int event, void *data); void captureSessionEvent(int event, capture_session *cap_session); const QString &getFileBasename(); diff --git a/ui/qt/capture_file_dialog.cpp b/ui/qt/capture_file_dialog.cpp index 797f09a3..884cb3f9 100644 --- a/ui/qt/capture_file_dialog.cpp +++ b/ui/qt/capture_file_dialog.cpp @@ -17,12 +17,6 @@ #include "capture_file_dialog.h" -#ifdef Q_OS_WIN -#include -#include "ui/packet_range.h" -#include "ui/win32/file_dlg_win32.h" -#else // Q_OS_WIN - #include #include "wsutil/filesystem.h" #include "wsutil/nstime.h" @@ -40,12 +34,10 @@ #include #include #include -#endif // ! Q_OS_WIN #include #include -#include "epan/prefs.h" #include #include @@ -55,38 +47,13 @@ static const double HEIGHT_SCALE_FACTOR = 1.4; CaptureFileDialog::CaptureFileDialog(QWidget *parent, capture_file *cf) : WiresharkFileDialog(parent), cap_file_(cf), -#if !defined(Q_OS_WIN) display_filter_edit_(NULL), default_ft_(-1), save_bt_(NULL), help_topic_(TOPIC_ACTION_NONE) -#else - file_type_(-1) -#endif { - switch (prefs.gui_fileopen_style) { - case FO_STYLE_LAST_OPENED: - /* The user has specified that we should start out in the last - * directory in which we opened a file. - * - * The open dialog initial directory will be that directory - * unless we've never opened a file, in which case it will - * be the user's personal data file directory. - */ - setDirectory(mainApp->openDialogInitialDir()); - break; - - case FO_STYLE_SPECIFIED: - /* The user has specified that we should always start out in a - * specified directory; if they've specified that directory, - * start out by showing the files in that dir. - */ - if (prefs.gui_fileopen_dir[0] != '\0') - setDirectory(prefs.gui_fileopen_dir); - break; - } + setDirectory(mainApp->openDialogInitialDir()); -#if !defined(Q_OS_WIN) // Add extra widgets // https://wiki.qt.io/Qt_project_org_faq#How_can_I_add_widgets_to_my_QFileDialog_instance.3F setOption(QFileDialog::DontUseNativeDialog, true); @@ -103,14 +70,10 @@ CaptureFileDialog::CaptureFileDialog(QWidget *parent, capture_file *cf) : // Left and right boxes for controls and preview h_box->addLayout(&left_v_box_); h_box->addLayout(&right_v_box_); - -#else // Q_OS_WIN - merge_type_ = 0; -#endif // Q_OS_WIN } check_savability_t CaptureFileDialog::checkSaveAsWithComments(QWidget *parent, capture_file *cf, int file_type) { - guint32 comment_types; + uint32_t comment_types; bool all_comment_types_supported = true; /* What types of comments do we have? */ @@ -191,7 +154,7 @@ check_savability_t CaptureFileDialog::checkSaveAsWithComments(QWidget *parent, c */ QList buttons = msg_dialog.buttons(); for (int i = 0; i < buttons.size(); ++i) { - QPushButton *button = static_cast(buttons.at(i));; + QPushButton *button = static_cast(buttons.at(i)); button->setAutoDefault(false); } @@ -234,7 +197,6 @@ check_savability_t CaptureFileDialog::checkSaveAsWithComments(QWidget *parent, c } -#ifndef Q_OS_WIN void CaptureFileDialog::accept() { // @@ -255,7 +217,6 @@ void CaptureFileDialog::accept() } WiresharkFileDialog::accept(); } -#endif // ! Q_OS_WIN // You have to use open, merge, saveAs, or exportPackets. We should @@ -265,98 +226,6 @@ int CaptureFileDialog::exec() { } - -// Windows -// We use native file dialogs here, rather than the Qt dialog -#ifdef Q_OS_WIN -int CaptureFileDialog::selectedFileType() { - return file_type_; -} - -wtap_compression_type CaptureFileDialog::compressionType() { - return compression_type_; -} - -int CaptureFileDialog::open(QString &file_name, unsigned int &type, QString &display_filter) { - QString title_str = mainApp->windowTitleString(tr("Open Capture File")); - GString *fname = g_string_new(file_name.toUtf8().constData()); - GString *dfilter = g_string_new(display_filter.toUtf8().constData()); - gboolean wof_status; - - // XXX Add a widget->HWND routine to qt_ui_utils and use it instead. - wof_status = win32_open_file((HWND)parentWidget()->effectiveWinId(), title_str.toStdWString().c_str(), fname, &type, dfilter); - file_name = fname->str; - display_filter = dfilter->str; - - g_string_free(fname, TRUE); - g_string_free(dfilter, TRUE); - - return (int) wof_status; -} - -check_savability_t CaptureFileDialog::saveAs(QString &file_name, bool must_support_all_comments) { - QString title_str = mainApp->windowTitleString(tr("Save Capture File As")); - GString *fname = g_string_new(file_name.toUtf8().constData()); - gboolean wsf_status; - - wsf_status = win32_save_as_file((HWND)parentWidget()->effectiveWinId(), title_str.toStdWString().c_str(), cap_file_, fname, &file_type_, &compression_type_, must_support_all_comments); - file_name = fname->str; - - g_string_free(fname, TRUE); - - if (wsf_status) { - return checkSaveAsWithComments(parentWidget(), cap_file_, file_type_); - } - - return CANCELLED; -} - -check_savability_t CaptureFileDialog::exportSelectedPackets(QString &file_name, packet_range_t *range, QString selRange) { - QString title_str = mainApp->windowTitleString(tr("Export Specified Packets")); - GString *fname = g_string_new(file_name.toUtf8().constData()); - gboolean wespf_status; - - if (selRange.length() > 0) - { - packet_range_convert_selection_str(range, selRange.toUtf8().constData()); - } - - wespf_status = win32_export_specified_packets_file((HWND)parentWidget()->effectiveWinId(), title_str.toStdWString().c_str(), cap_file_, fname, &file_type_, &compression_type_, range); - file_name = fname->str; - - g_string_free(fname, TRUE); - - if (wespf_status) { - return checkSaveAsWithComments(parentWidget(), cap_file_, file_type_); - } - - return CANCELLED; -} - -int CaptureFileDialog::merge(QString &file_name, QString &display_filter) { - QString title_str = mainApp->windowTitleString(tr("Merge Capture File")); - GString *fname = g_string_new(file_name.toUtf8().constData()); - GString *dfilter = g_string_new(display_filter.toUtf8().constData()); - gboolean wmf_status; - - - wmf_status = win32_merge_file((HWND)parentWidget()->effectiveWinId(), title_str.toStdWString().c_str(), fname, dfilter, &merge_type_); - file_name = fname->str; - display_filter = dfilter->str; - - g_string_free(fname, TRUE); - g_string_free(dfilter, TRUE); - - return (int) wmf_status; -} - -int CaptureFileDialog::mergeType() { - return merge_type_; -} - -#else // ! Q_OS_WIN -// Not Windows -// We use the Qt dialogs here QString CaptureFileDialog::fileExtensionType(int et, bool extension_globs) { QString extension_type_name; @@ -420,7 +289,7 @@ QString CaptureFileDialog::fileType(int ft, QStringList &suffixes) filter = " ("; - extensions_list = wtap_get_file_extensions_list(ft, TRUE); + extensions_list = wtap_get_file_extensions_list(ft, true); if (extensions_list == NULL) { /* This file type doesn't have any particular extension conventionally used for it, so we'll just use a @@ -438,7 +307,7 @@ QString CaptureFileDialog::fileType(int ft, QStringList &suffixes) for (GSList *extension = extensions_list; extension != NULL; extension = g_slist_next(extension)) { QString suffix((char *)extension->data); - filter += " *." + suffix;; + filter += " *." + suffix; suffixes << suffix; } wtap_free_extensions_list(extensions_list); @@ -549,23 +418,22 @@ void CaptureFileDialog::fixFilenameExtension() } // Fixup the new suffix based on whether we're compressing or not. - if (compressionType() == WTAP_UNCOMPRESSED) { - // Not compressing; strip off any compression suffix - GSList *compression_type_extensions = wtap_get_all_compression_type_extensions_list(); - for (GSList *compression_type_extension = compression_type_extensions; - compression_type_extension != NULL; - compression_type_extension = g_slist_next(compression_type_extension)) { - QString suffix = QString(".") + (char *)compression_type_extension->data; - if (new_suffix.endsWith(suffix)) { - // - // It ends with this compression suffix; chop it off. - // - new_suffix.chop(suffix.size()); - break; - } + // Strip off any compression suffix + GSList *compression_type_extensions = wtap_get_all_compression_type_extensions_list(); + for (GSList *compression_type_extension = compression_type_extensions; + compression_type_extension != NULL; + compression_type_extension = g_slist_next(compression_type_extension)) { + QString suffix = QString(".") + (char *)compression_type_extension->data; + if (new_suffix.endsWith(suffix)) { + // + // It ends with this compression suffix; chop it off. + // + new_suffix.chop(suffix.size()); + break; } - g_slist_free(compression_type_extensions); - } else { + } + g_slist_free(compression_type_extensions); + if (compressionType() != WTAP_UNCOMPRESSED) { // Compressing; append the appropriate compression suffix. QString compressed_file_extension = QString(".") + wtap_compression_type_extension(compressionType()); if (valid_extensions.contains(new_suffix + compressed_file_extension)) { @@ -634,7 +502,7 @@ int CaptureFileDialog::selectedFileType() { } wtap_compression_type CaptureFileDialog::compressionType() { - return compress_.isChecked() ? WTAP_GZIP_COMPRESSED : WTAP_UNCOMPRESSED; + return compress_group_box_.compressionType(); } void CaptureFileDialog::addDisplayFilterEdit(QString &display_filter) { @@ -670,15 +538,11 @@ void CaptureFileDialog::addFormatTypeSelector(QVBoxLayout &v_box) { } void CaptureFileDialog::addGzipControls(QVBoxLayout &v_box) { - compress_.setText(tr("Compress with g&zip")); - if (cap_file_->compression_type == WTAP_GZIP_COMPRESSED && - wtap_dump_can_compress(default_ft_)) { - compress_.setChecked(true); - } else { - compress_.setChecked(false); + if (wtap_dump_can_compress(default_ft_)) { + compress_group_box_.setCompressionType(cap_file_->compression_type); } - v_box.addWidget(&compress_, 0, Qt::AlignTop); - connect(&compress_, &QCheckBox::stateChanged, this, &CaptureFileDialog::fixFilenameExtension); + v_box.addWidget(&compress_group_box_, 0, Qt::AlignTop); + connect(&compress_group_box_, &CompressionGroupBox::stateChanged, this, &CaptureFileDialog::fixFilenameExtension); } @@ -724,7 +588,7 @@ int CaptureFileDialog::open(QString &file_name, unsigned int &type, QString &dis } if (WiresharkFileDialog::exec() && selectedFiles().length() > 0) { - file_name = selectedFiles()[0]; + file_name = selectedNativePath(); type = open_info_name_to_type(qPrintable(format_type_.currentText())); display_filter.append(display_filter_edit_->text()); @@ -757,7 +621,7 @@ check_savability_t CaptureFileDialog::saveAs(QString &file_name, bool must_suppo if (WiresharkFileDialog::exec() && selectedFiles().length() > 0) { int file_type; - file_name = selectedFiles()[0]; + file_name = selectedNativePath(); file_type = selectedFileType(); /* Is the file type bogus? */ if (file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) { @@ -807,7 +671,7 @@ check_savability_t CaptureFileDialog::exportSelectedPackets(QString &file_name, if (WiresharkFileDialog::exec() && selectedFiles().length() > 0) { int file_type; - file_name = selectedFiles()[0]; + file_name = selectedNativePath(); file_type = selectedFileType(); /* Is the file type bogus? */ if (file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) { @@ -842,7 +706,7 @@ int CaptureFileDialog::merge(QString &file_name, QString &display_filter) { resize(width() * WIDTH_SCALE_FACTOR, height() * HEIGHT_SCALE_FACTOR + right_v_box_.minimumSize().height() + display_filter_edit_->minimumSize().height()); if (WiresharkFileDialog::exec() && selectedFiles().length() > 0) { - file_name.append(selectedFiles()[0]); + file_name.append(selectedNativePath()); display_filter.append(display_filter_edit_->text()); return QDialog::Accepted; @@ -853,9 +717,9 @@ int CaptureFileDialog::merge(QString &file_name, QString &display_filter) { QStringList CaptureFileDialog::buildFileSaveAsTypeList(bool must_support_all_comments) { QStringList filters; - guint32 required_comment_types; + uint32_t required_comment_types; GArray *savable_file_types_subtypes; - guint i; + unsigned i; type_hash_.clear(); type_suffixes_.clear(); @@ -885,7 +749,7 @@ QStringList CaptureFileDialog::buildFileSaveAsTypeList(bool must_support_all_com filters << type_name + fileType(ft, type_suffixes_[type_name]); type_hash_[type_name] = ft; } - g_array_free(savable_file_types_subtypes, TRUE); + g_array_free(savable_file_types_subtypes, true); } return filters; @@ -909,7 +773,7 @@ void CaptureFileDialog::preview(const QString & path) { wtap *wth; int err; - gchar *err_info; + char *err_info; ws_file_preview_stats stats; ws_file_preview_stats_status status; time_t ti_time; @@ -933,7 +797,7 @@ void CaptureFileDialog::preview(const QString & path) return; } - wth = wtap_open_offline(path.toUtf8().data(), WTAP_TYPE_AUTO, &err, &err_info, TRUE); + wth = wtap_open_offline(path.toUtf8().data(), WTAP_TYPE_AUTO, &err, &err_info, true); if (wth == NULL) { if (err == WTAP_ERR_FILE_UNKNOWN_FORMAT) { preview_format_.setText(tr("unknown file format")); @@ -952,7 +816,7 @@ void CaptureFileDialog::preview(const QString & path) preview_format_.setText(QString::fromUtf8(wtap_file_type_subtype_description(wtap_file_type_subtype(wth)))); // Size - gint64 filesize = wtap_file_size(wth, &err); + int64_t filesize = wtap_file_size(wth, &err); // Finder and Windows Explorer use IEC. What do the various Linux file managers use? QString size_str(gchar_free_to_qstring(format_size(filesize, FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_IEC))); @@ -1033,5 +897,3 @@ void CaptureFileDialog::on_buttonBox_helpRequested() { if (help_topic_ != TOPIC_ACTION_NONE) mainApp->helpTopicAction(help_topic_); } - -#endif // ! Q_OS_WIN diff --git a/ui/qt/capture_file_dialog.h b/ui/qt/capture_file_dialog.h index 1e22ad8b..2c48100a 100644 --- a/ui/qt/capture_file_dialog.h +++ b/ui/qt/capture_file_dialog.h @@ -12,11 +12,10 @@ #include -#ifndef Q_OS_WIN #include +#include #include "packet_range_group_box.h" #include "ui/help_url.h" -#endif // Q_OS_WIN #include @@ -43,14 +42,27 @@ class CaptureFileDialog : public WiresharkFileDialog // // You can subclass QFileDialog (which we've done here) and add widgets as // described at - // https://web.archive.org/web/20100528190736/http://developer.qt.nokia.com/faq/answer/how_can_i_add_widgets_to_my_qfiledialog_instance + // + // https://web.archive.org/web/20100528190736/http://developer.qt.nokia.com/faq/answer/how_can_i_add_widgets_to_my_qfiledialog_instance + // // However, Qt's idea of what a file dialog looks like isn't what Microsoft // and Apple think a file dialog looks like. // - // On Windows Vista and later we should probably use IFileOpenDialog. On earlier - // versions of Windows (including XP) we should use GetOpenFileName, which is - // what we do in ui/win32/file_dlg_win32.c. macOS we should use NSOpenPanel. On - // other platforms we should fall back to QFileDialog. + // On Windows, we should probably use the Common Item Dialog: + // + // https://learn.microsoft.com/en-us/windows/win32/shell/common-file-dialog + // + // We currently use GetOpenFileNam in ui/win32/file_dlg_win32.c. + // + // On macOS we should use NSOpenPanel and NSSavePanel: + // + // https://developer.apple.com/documentation/appkit/nsopenpanel?language=objc + // https://developer.apple.com/documentation/appkit/nssavepanel?language=objc + // + // On other platforms we should fall back to QFileDialog (or maybe + // KDE's or GTK+/GNOME's file dialog, as appropriate for the desktop + // environment being used, if QFileDialog doesn't do so with various + // platform plugins). // // Yes, that's four implementations of the same window. // @@ -62,9 +74,6 @@ class CaptureFileDialog : public WiresharkFileDialog public: explicit CaptureFileDialog(QWidget *parent = NULL, capture_file *cf = NULL); static check_savability_t checkSaveAsWithComments(QWidget * -#if defined(Q_OS_WIN) - parent -#endif // Q_OS_WIN , capture_file *cf, int file_type); int mergeType(); @@ -74,7 +83,6 @@ public: private: capture_file *cap_file_; -#if !defined(Q_OS_WIN) void addMergeControls(QVBoxLayout &v_box); void addFormatTypeSelector(QVBoxLayout &v_box); void addDisplayFilterEdit(QString &display_filter); @@ -110,25 +118,17 @@ private: int default_ft_; - QCheckBox compress_; + CompressionGroupBox compress_group_box_; PacketRangeGroupBox packet_range_group_box_; QPushButton *save_bt_; topic_action_e help_topic_; -#else // Q_OS_WIN - int file_type_; - int merge_type_; - wtap_compression_type compression_type_; -#endif // Q_OS_WIN - signals: public slots: -#ifndef Q_OS_WIN void accept() Q_DECL_OVERRIDE; -#endif int exec() Q_DECL_OVERRIDE; int open(QString &file_name, unsigned int &type, QString &display_filter); check_savability_t saveAs(QString &file_name, bool must_support_comments); @@ -136,11 +136,9 @@ public slots: int merge(QString &file_name, QString &display_filter); private slots: -#if !defined(Q_OS_WIN) void fixFilenameExtension(); void preview(const QString & path); void on_buttonBox_helpRequested(); -#endif // Q_OS_WIN }; #endif // CAPTURE_FILE_DIALOG_H diff --git a/ui/qt/capture_file_properties_dialog.cpp b/ui/qt/capture_file_properties_dialog.cpp index c7705681..9b4458dc 100644 --- a/ui/qt/capture_file_properties_dialog.cpp +++ b/ui/qt/capture_file_properties_dialog.cpp @@ -15,12 +15,16 @@ #include "ui/simple_dialog.h" #include "ui/summary.h" +#include "wiretap/secrets-types.h" + +#include "wsutil/filesystem.h" #include "wsutil/str_util.h" #include "wsutil/utf8_entities.h" #include "wsutil/version_info.h" #include #include "main_application.h" +#include "capture_comment_dialog.h" #include #include @@ -39,10 +43,6 @@ CaptureFilePropertiesDialog::CaptureFilePropertiesDialog(QWidget &parent, Captur ui->detailsTextEdit->setAcceptRichText(true); - // make the details box larger than the comments - ui->splitter->setStretchFactor(0, 6); - ui->splitter->setStretchFactor(1, 1); - QPushButton *button = ui->buttonBox->button(QDialogButtonBox::Reset); if (button) { button->setText(tr("Refresh")); @@ -53,16 +53,14 @@ CaptureFilePropertiesDialog::CaptureFilePropertiesDialog(QWidget &parent, Captur button->setText(tr("Copy To Clipboard")); } - button = ui->buttonBox->button(QDialogButtonBox::Save); - if (button) { - button->setText(tr("Save Comments")); - } - button = ui->buttonBox->button(QDialogButtonBox::Close); if (button) { button->setDefault(true); } + ui->buttonBox->addButton(ui->actionEditButton, QDialogButtonBox::ActionRole); + connect(ui->actionEditButton, &QPushButton::clicked, this, &CaptureFilePropertiesDialog::addCaptureComment); + setWindowSubtitle(tr("Capture File Properties")); QTimer::singleShot(0, this, SLOT(updateWidgets())); } @@ -81,34 +79,16 @@ CaptureFilePropertiesDialog::~CaptureFilePropertiesDialog() void CaptureFilePropertiesDialog::updateWidgets() { QPushButton *refresh_bt = ui->buttonBox->button(QDialogButtonBox::Reset); - QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save); if (file_closed_ || !cap_file_.isValid()) { if (refresh_bt) { refresh_bt->setEnabled(false); } - ui->commentsTextEdit->setReadOnly(true); - if (save_bt) { - save_bt->setEnabled(false); - } WiresharkDialog::updateWidgets(); return; } - bool enable = wtap_dump_can_write(cap_file_.capFile()->linktypes, WTAP_COMMENT_PER_SECTION); - save_bt->setEnabled(enable); - ui->commentsTextEdit->setEnabled(enable); - fillDetails(); - // XXX - this just handles the first comment in the first section; - // add support for multiple sections with multiple comments. - wtap_block_t shb = wtap_file_get_shb(cap_file_.capFile()->provider.wth, 0); - char *shb_comment; - if (wtap_block_get_nth_string_option_value(shb, OPT_COMMENT, 0, - &shb_comment) == WTAP_OPTTYPE_SUCCESS) - ui->commentsTextEdit->setText(shb_comment); - else - ui->commentsTextEdit->setText(NULL); WiresharkDialog::updateWidgets(); } @@ -192,7 +172,7 @@ QString CaptureFilePropertiesDialog::summaryToHtml() QString encaps_str; if (summary.file_encap_type == WTAP_ENCAP_PER_PACKET) { - for (guint i = 0; i < summary.packet_encap_types->len; i++) + for (unsigned i = 0; i < summary.packet_encap_types->len; i++) { encaps_str = QString(wtap_encap_description(g_array_index(summary.packet_encap_types, int, i))); } @@ -221,15 +201,23 @@ QString CaptureFilePropertiesDialog::summaryToHtml() out << table_begin; // start time - out << table_row_begin - << table_vheader_tmpl.arg(tr("First packet")) - << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.start_time)) + out << table_row_begin; + if (is_packet_configuration_namespace()) { + out << table_vheader_tmpl.arg(tr("First packet")); + } else { + out << table_vheader_tmpl.arg(tr("First event")); + } + out << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.start_time)) << table_row_end; // stop time - out << table_row_begin - << table_vheader_tmpl.arg(tr("Last packet")) - << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.stop_time)) + out << table_row_begin; + if (is_packet_configuration_namespace()) { + out << table_vheader_tmpl.arg(tr("Last packet")); + } else { + out << table_vheader_tmpl.arg(tr("Last event")); + } + out << table_data_tmpl.arg(time_t_to_qstring((time_t)summary.stop_time)) << table_row_end; // elapsed seconds (capture duration) @@ -257,20 +245,21 @@ QString CaptureFilePropertiesDialog::summaryToHtml() } // Information from file sections. - for (guint section_number = 0; + for (unsigned section_number = 0; section_number < wtap_file_get_num_shbs(cap_file_.capFile()->provider.wth); section_number++) { // If we have more than one section, add headers for each section. if (wtap_file_get_num_shbs(cap_file_.capFile()->provider.wth) > 1) out << section_tmpl_.arg(QString(tr("Section %1")) - .arg(section_number)); + .arg(section_number + 1)); + + wtap_block_t shb_inf = wtap_file_get_shb(cap_file_.capFile()->provider.wth, section_number); // Capture Section out << section_tmpl_.arg(tr("Capture")); out << table_begin; - wtap_block_t shb_inf = wtap_file_get_shb(cap_file_.capFile()->provider.wth, section_number); char *str; if (shb_inf != nullptr) { @@ -317,15 +306,25 @@ QString CaptureFilePropertiesDialog::summaryToHtml() out << table_begin; out << table_ul_row_begin - << table_hheader20_tmpl.arg(tr("Interface")) - << table_hheader20_tmpl.arg(tr("Dropped packets")) - << table_hheader20_tmpl.arg(tr("Capture filter")) - << table_hheader20_tmpl.arg(tr("Link type")) - << table_hheader20_tmpl.arg(tr("Packet size limit (snaplen)")) - << table_row_end; + << table_hheader20_tmpl.arg(tr("Interface")); + if (is_packet_configuration_namespace()) { + out << table_hheader20_tmpl.arg(tr("Dropped packets")); + } else { + out << table_hheader20_tmpl.arg(tr("Dropped events")); + } + out << table_hheader20_tmpl.arg(tr("Capture filter")) + << table_hheader20_tmpl.arg(tr("Link type")); + if (is_packet_configuration_namespace()) { + out << table_hheader20_tmpl.arg(tr("Packet size limit (snaplen)")); + } else { + out << table_hheader20_tmpl.arg(tr("Event size limit (snaplen)")); + } + out << table_row_end; } - for (guint i = 0; i < summary.ifaces->len; i++) { + // XXX: The mapping of interfaces to different SHBs isn't + // handled correctly here or elsewhere + for (unsigned i = 0; i < summary.ifaces->len; i++) { iface_summary_info iface; iface = g_array_index(summary.ifaces, iface_summary_info, i); @@ -342,7 +341,7 @@ QString CaptureFilePropertiesDialog::summaryToHtml() if (iface.drops_known) { interface_drops = QString("%1 (%2%)").arg(iface.drops).arg(QString::number( /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */ - summary.packet_count ? (100.0 * (gint64)iface.drops)/summary.packet_count : 0, 'f', 1)); + summary.packet_count ? (100.0 * (int64_t)iface.drops)/summary.packet_count : 0, 'f', 1)); } /* Capture filter */ @@ -366,6 +365,57 @@ QString CaptureFilePropertiesDialog::summaryToHtml() if (summary.ifaces->len > 0) { out << table_end; } + + unsigned num_comments = wtap_block_count_option(shb_inf, OPT_COMMENT); + if (num_comments > 0) { + out << section_tmpl_.arg(tr("Comments")); + char *shb_comment; + for (unsigned i = 0; i < num_comments; i++) { + if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, i, + &shb_comment) == WTAP_OPTTYPE_SUCCESS) { + QString section_comment = shb_comment; + QString section_comment_html; + if (num_comments > 1) { + out << tr("Comment %1: ").arg(i+1); + } + + QString comment_escaped = html_escape(section_comment).replace('\n', "
"); + out << para_tmpl_.arg(comment_escaped); + } + } + } + } + + // Done with the interfaces + for (unsigned i = 0; i < summary.ifaces->len; i++) { + iface_summary_info iface; + iface = g_array_index(summary.ifaces, iface_summary_info, i); + + g_free(iface.descr); + g_free(iface.name); + g_free(iface.cfilter); + } + g_array_free(summary.ifaces, true); + + if (wtap_file_get_num_dsbs(cap_file_.capFile()->provider.wth) > 0) { + out << section_tmpl_.arg(tr("Decryption Secrets")); + out << table_begin; + out << table_ul_row_begin + << table_hheader20_tmpl.arg(tr("Type")) + << table_hheader20_tmpl.arg(tr("Size")) + << table_row_end; + // XXX: A DSB can have (multiple) comments, we could add that too. + for (unsigned section_number = 0; + section_number < wtap_file_get_num_dsbs(cap_file_.capFile()->provider.wth); + section_number++) { + wtap_block_t dsb = wtap_file_get_dsb(cap_file_.capFile()->provider.wth, section_number); + wtapng_dsb_mandatory_t *dsb_mand = (wtapng_dsb_mandatory_t*)wtap_block_get_mandatory_data(dsb); + out << table_row_begin + << table_data_tmpl.arg(secrets_type_description(dsb_mand->secrets_type)) + << table_data_tmpl.arg(tr("%1 bytes").arg(dsb_mand->secrets_len)) + << table_row_end; + } + out << table_end; } // Statistics Section @@ -395,9 +445,13 @@ QString CaptureFilePropertiesDialog::summaryToHtml() .arg(100.0 * summary.marked_count / summary.packet_count, 1, 'f', 1); } - out << table_row_begin - << table_data_tmpl.arg(tr("Packets")) - << table_data_tmpl.arg(summary.packet_count) + out << table_row_begin; + if (is_packet_configuration_namespace()) { + out << table_data_tmpl.arg(tr("Packets")); + } else { + out << table_data_tmpl.arg(tr("Events")); + } + out << table_data_tmpl.arg(summary.packet_count) << table_data_tmpl.arg(displayed_str) << table_data_tmpl.arg(marked_str) << table_row_end; @@ -441,17 +495,21 @@ QString CaptureFilePropertiesDialog::summaryToHtml() // Average packet size captured_str = displayed_str = marked_str = n_a; if (summary.packet_count > 0) { - captured_str = QString::number((guint64) ((double)summary.bytes/summary.packet_count + 0.5)); + captured_str = QString::number((uint64_t) ((double)summary.bytes/summary.packet_count + 0.5)); } if (summary.filtered_count > 0) { - displayed_str = QString::number((guint64) ((double)summary.filtered_bytes/summary.filtered_count + 0.5)); + displayed_str = QString::number((uint64_t) ((double)summary.filtered_bytes/summary.filtered_count + 0.5)); } if (summary.marked_count > 0) { - marked_str = QString::number((guint64) ((double)summary.marked_bytes/summary.marked_count + 0.5)); + marked_str = QString::number((uint64_t) ((double)summary.marked_bytes/summary.marked_count + 0.5)); } - out << table_row_begin - << table_data_tmpl.arg(tr("Average packet size, B")) - << table_data_tmpl.arg(captured_str) + out << table_row_begin; + if (is_packet_configuration_namespace()) { + out << table_data_tmpl.arg(tr("Average packet size, B")); + } else { + out << table_data_tmpl.arg(tr("Average event size, B")); + } + out << table_data_tmpl.arg(captured_str) << table_data_tmpl.arg(displayed_str) << table_data_tmpl.arg(marked_str) << table_row_end; @@ -533,36 +591,21 @@ void CaptureFilePropertiesDialog::fillDetails() cursor.insertHtml(summary); cursor.insertBlock(); // Work around rendering oddity. - // XXX - this just shows the first comment in the first section; - // add support for multiple sections with multiple comments. - wtap_block_t shb = wtap_file_get_shb(cap_file_.capFile()->provider.wth, 0); - char *shb_comment; - if (wtap_block_get_nth_string_option_value(shb, OPT_COMMENT, 0, - &shb_comment) == WTAP_OPTTYPE_SUCCESS) { - QString section_comment = shb_comment; - QString section_comment_html; - - if (!section_comment.isEmpty()) { - QString comment_escaped = html_escape(section_comment).replace('\n', "
"); - section_comment_html += section_tmpl_.arg(QString(tr("Section Comment"))); - section_comment_html += para_tmpl_.arg(comment_escaped); - - cursor.insertBlock(); - cursor.insertHtml(section_comment_html); - } - } - if (cap_file_.capFile()->packet_comment_count > 0) { cursor.insertBlock(); - cursor.insertHtml(section_tmpl_.arg(tr("Packet Comments"))); + if (is_packet_configuration_namespace()) { + cursor.insertHtml(section_tmpl_.arg(tr("Packet Comments"))); + } else { + cursor.insertHtml(section_tmpl_.arg(tr("Event Comments"))); + } - for (guint32 framenum = 1; framenum <= cap_file_.capFile()->count ; framenum++) { + for (uint32_t framenum = 1; framenum <= cap_file_.capFile()->count ; framenum++) { frame_data *fdata = frame_data_sequence_find(cap_file_.capFile()->provider.frames, framenum); wtap_block_t pkt_block = cf_get_packet_block(cap_file_.capFile(), fdata); if (pkt_block) { - guint n_comments = wtap_block_count_option(pkt_block, OPT_COMMENT); - for (guint i = 0; i < n_comments; i++) { + unsigned n_comments = wtap_block_count_option(pkt_block, OPT_COMMENT); + for (unsigned i = 0; i < n_comments; i++) { char *comment_text; if (WTAP_OPTTYPE_SUCCESS == wtap_block_get_nth_string_option_value(pkt_block, OPT_COMMENT, i, &comment_text)) { QString frame_comment_html = tr("

Frame %1: ").arg(framenum); @@ -598,45 +641,31 @@ void CaptureFilePropertiesDialog::changeEvent(QEvent* event) QDialog::changeEvent(event); } -void CaptureFilePropertiesDialog::on_buttonBox_helpRequested() +void CaptureFilePropertiesDialog::addCaptureComment() { - mainApp->helpTopicAction(HELP_STATS_SUMMARY_DIALOG); + CaptureCommentDialog* cc_dialog; + cc_dialog = new CaptureCommentDialog(*this, cap_file_); + connect(cc_dialog, &CaptureCommentDialog::captureCommentChanged, this, &CaptureFilePropertiesDialog::updateWidgets); + //cc_dialog->setWindowModality(Qt::ApplicationModal); + cc_dialog->setAttribute(Qt::WA_DeleteOnClose); + cc_dialog->show(); } -void CaptureFilePropertiesDialog::on_buttonBox_accepted() +void CaptureFilePropertiesDialog::on_buttonBox_helpRequested() { - if (file_closed_ || !cap_file_.capFile()->filename) { - return; - } - - if (wtap_dump_can_write(cap_file_.capFile()->linktypes, WTAP_COMMENT_PER_SECTION)) - { - gchar *str = qstring_strdup(ui->commentsTextEdit->toPlainText()); - - /* - * Make sure this would fit in a pcapng option. - * - * XXX - 65535 is the maximum size for an option in pcapng; - * what if another capture file format supports larger - * comments? - */ - if (strlen(str) > 65535) { - /* It doesn't fit. Tell the user and give up. */ - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, - "That comment is too large to save in a capture file."); - return; - } - cf_update_section_comment(cap_file_.capFile(), str); - emit captureCommentChanged(); - fillDetails(); - } + mainApp->helpTopicAction(HELP_STATS_SUMMARY_DIALOG); } void CaptureFilePropertiesDialog::on_buttonBox_clicked(QAbstractButton *button) { if (button == ui->buttonBox->button(QDialogButtonBox::Apply)) { QClipboard *clipboard = QApplication::clipboard(); - QString details = tr("Created by Wireshark %1\n\n").arg(get_ws_vcs_version_info()); + QString details; + if (is_packet_configuration_namespace()) { + details = tr("Created by Wireshark %1\n\n").arg(get_ws_vcs_version_info()); + } else { + details = tr("Created by Logray %1\n\n").arg(get_lr_vcs_version_info()); + } details.append(ui->detailsTextEdit->toPlainText()); clipboard->setText(details); } else if (button == ui->buttonBox->button(QDialogButtonBox::Reset)) { diff --git a/ui/qt/capture_file_properties_dialog.h b/ui/qt/capture_file_properties_dialog.h index dd1698a6..27b8d86f 100644 --- a/ui/qt/capture_file_properties_dialog.h +++ b/ui/qt/capture_file_properties_dialog.h @@ -14,8 +14,6 @@ #include -#include - #include #include @@ -62,8 +60,8 @@ private: private slots: void updateWidgets(); + void addCaptureComment(); void on_buttonBox_helpRequested(); - void on_buttonBox_accepted(); void on_buttonBox_clicked(QAbstractButton *button); void on_buttonBox_rejected(); }; diff --git a/ui/qt/capture_file_properties_dialog.ui b/ui/qt/capture_file_properties_dialog.ui index bf5cd634..65b28f12 100644 --- a/ui/qt/capture_file_properties_dialog.ui +++ b/ui/qt/capture_file_properties_dialog.ui @@ -21,65 +21,38 @@ - - - Qt::Vertical - - - false - - - false - - - - - - - Details - - - - - - - true - - - - - - - - - - - Capture file comments - - - - - - - - 0 - 10 - - - - - - + + + + + + Details + + + + + + + true + + + + - QDialogButtonBox::Apply|QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Reset|QDialogButtonBox::Save + QDialogButtonBox::Apply|QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Reset + + + Edit Comments + + diff --git a/ui/qt/capture_filter_syntax_worker.cpp b/ui/qt/capture_filter_syntax_worker.cpp index 89ef981c..0fb6b543 100644 --- a/ui/qt/capture_filter_syntax_worker.cpp +++ b/ui/qt/capture_filter_syntax_worker.cpp @@ -10,7 +10,6 @@ #include "config.h" #ifdef HAVE_LIBPCAP -#include #ifdef __MINGW32__ #include <_bsd_types.h> @@ -50,8 +49,8 @@ static QMutex pcap_compile_mtx_; void CaptureFilterSyntaxWorker::checkFilter(const QString filter) { #ifdef HAVE_LIBPCAP - QSet active_dlts; - QSet active_extcap; + QSet active_dlts; + QSet active_extcap; struct bpf_program fcode; pcap_t *pd; int pc_err; @@ -66,7 +65,7 @@ void CaptureFilterSyntaxWorker::checkFilter(const QString filter) return; } - for (guint if_idx = 0; if_idx < global_capture_opts.all_ifaces->len; if_idx++) { + for (unsigned if_idx = 0; if_idx < global_capture_opts.all_ifaces->len; if_idx++) { interface_t *device; device = &g_array_index(global_capture_opts.all_ifaces, interface_t, if_idx); @@ -85,7 +84,7 @@ void CaptureFilterSyntaxWorker::checkFilter(const QString filter) } } - foreach(gint dlt, active_dlts.values()) { + foreach(int dlt, active_dlts.values()) { pcap_compile_mtx_.lock(); pd = pcap_open_dead(dlt, DUMMY_SNAPLENGTH); if (pd == NULL) @@ -109,6 +108,7 @@ void CaptureFilterSyntaxWorker::checkFilter(const QString filter) err_str = pcap_geterr(pd); } else { DEBUG_SYNTAX_CHECK("unknown", "known good"); + pcap_freecode(&fcode); } pcap_close(pd); @@ -118,9 +118,9 @@ void CaptureFilterSyntaxWorker::checkFilter(const QString filter) } // If it's already invalid, don't bother to check extcap if (state != SyntaxLineEdit::Invalid) { - foreach(guint extcapif, active_extcap.values()) { + foreach(unsigned extcapif, active_extcap.values()) { interface_t *device; - gchar *error = NULL; + char *error = NULL; device = &g_array_index(global_capture_opts.all_ifaces, interface_t, extcapif); extcap_filter_status status = extcap_verify_capture_filter(device->name, filter.toUtf8().constData(), &error); diff --git a/ui/qt/capture_info_dialog.cpp b/ui/qt/capture_info_dialog.cpp index 5a29652c..e171ba3d 100644 --- a/ui/qt/capture_info_dialog.cpp +++ b/ui/qt/capture_info_dialog.cpp @@ -19,7 +19,7 @@ #include "ui/capture.h" #include "capture_info_dialog.h" -#include "ui_capture_info_dialog.h" +#include #include "main_application.h" @@ -146,7 +146,7 @@ void CaptureInfoModel::updateInfo() if (!cap_info_) return; GHashTableIter iter; - gpointer key, value; + void *key, *value; samples_++; other_points_.append(cap_info_->counts->other - last_other_); diff --git a/ui/qt/capture_options_dialog.cpp b/ui/qt/capture_options_dialog.cpp index a0aed791..6763f14d 100644 --- a/ui/qt/capture_options_dialog.cpp +++ b/ui/qt/capture_options_dialog.cpp @@ -94,10 +94,10 @@ enum static interface_t *find_device_by_if_name(const QString &interface_name) { interface_t *device; - guint i; + unsigned i; for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (!interface_name.compare(device->display_name) && !device->hidden && device->type != IF_PIPE) { + if (!interface_name.compare(device->display_name) && !device->hidden && device->if_info.type != IF_PIPE) { return device; } } @@ -214,6 +214,7 @@ CaptureOptionsDialog::CaptureOptionsDialog(QWidget *parent) : #endif #ifndef SHOW_MONITOR_COLUMN ui->interfaceTree->setColumnHidden(col_monitor_, true); + ui->captureMonitorModeCheckBox->setVisible(false); #endif ui->interfaceTree->setItemDelegateForColumn(col_filter_, &interface_item_delegate_); @@ -222,6 +223,7 @@ CaptureOptionsDialog::CaptureOptionsDialog(QWidget *parent) : ui->filenameLineEdit->setPlaceholderText(tr("Leave blank to use a temporary file")); ui->rbCompressionNone->setChecked(true); + ui->rbTimeNum->setChecked(true); ui->tempDirLineEdit->setPlaceholderText(g_get_tmp_dir()); ui->tempDirLineEdit->setText(global_capture_opts.temp_dir); @@ -246,6 +248,27 @@ CaptureOptionsDialog::CaptureOptionsDialog(QWidget *parent) : connect(ui->interfaceTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem*,int))); connect(ui->tempDirBrowseButton, SIGNAL(clicked()), this, SLOT(tempDirBrowseButtonClicked())); + // Ring buffer minimums (all 1 except # of files) + ui->PktSpinBox->setMinimum(1); + ui->MBSpinBox->setMinimum(1); + ui->SecsSpinBox->setMinimum(1); + ui->IntervalSecsSpinBox->setMinimum(1); + ui->RbSpinBox->setMinimum(2); + + // Autostop minimums + ui->stopPktSpinBox->setMinimum(1); + ui->stopFilesSpinBox->setMinimum(1); + ui->stopMBSpinBox->setMinimum(1); + ui->stopSecsSpinBox->setMinimum(1); + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + connect(ui->MBComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &CaptureOptionsDialog::MBComboBoxIndexChanged); + connect(ui->stopMBComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &CaptureOptionsDialog::stopMBComboBoxIndexChanged); +#else + connect(ui->MBComboBox, &QComboBox::currentIndexChanged, this, &CaptureOptionsDialog::MBComboBoxIndexChanged); + connect(ui->stopMBComboBox, &QComboBox::currentIndexChanged, this, &CaptureOptionsDialog::stopMBComboBoxIndexChanged); +#endif + ui->tabWidget->setCurrentIndex(0); updateWidgets(); @@ -266,14 +289,14 @@ void CaptureOptionsDialog::updateGlobalDeviceSelections() while (*iter) { QString device_name = (*iter)->data(col_interface_, Qt::UserRole).value(); - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (device_name.compare(QString().fromUtf8(device->name)) == 0) { if ((*iter)->isSelected()) { - device->selected = TRUE; + device->selected = true; global_capture_opts.num_selected++; } else { - device->selected = FALSE; + device->selected = false; } break; } @@ -294,7 +317,7 @@ void CaptureOptionsDialog::updateFromGlobalDeviceSelections() while (*iter) { QString device_name = (*iter)->data(col_interface_, Qt::UserRole).value(); - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (device_name.compare(QString().fromUtf8(device->name)) == 0) { if ((bool)device->selected != (*iter)->isSelected()) { @@ -373,22 +396,27 @@ void CaptureOptionsDialog::on_capturePromModeCheckBox_toggled(bool checked) } } -void CaptureOptionsDialog::browseButtonClicked() +void CaptureOptionsDialog::on_captureMonitorModeCheckBox_toggled(bool checked) { - const char *open_dir = NULL; - - switch (prefs.gui_fileopen_style) { - - case FO_STYLE_LAST_OPENED: - open_dir = get_open_dialog_initial_dir(); - break; + interface_t *device; + prefs.capture_monitor_mode = checked; + for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) { + InterfaceTreeWidgetItem *ti = dynamic_cast(ui->interfaceTree->topLevelItem(row)); + if (!ti) continue; - case FO_STYLE_SPECIFIED: - if (prefs.gui_fileopen_dir[0] != '\0') - open_dir = prefs.gui_fileopen_dir; - break; + QString device_name = ti->data(col_interface_, Qt::UserRole).toString(); + device = getDeviceByName(device_name); + if (!device) continue; + if (device->monitor_mode_supported) { + device->monitor_mode_enabled = checked; + ti->updateInterfaceColumns(device); + } } - QString file_name = WiresharkFileDialog::getSaveFileName(this, tr("Specify a Capture File"), open_dir); +} + +void CaptureOptionsDialog::browseButtonClicked() +{ + QString file_name = WiresharkFileDialog::getSaveFileName(this, tr("Specify a Capture File"), get_open_dialog_initial_dir()); ui->filenameLineEdit->setText(file_name); } @@ -416,15 +444,15 @@ void CaptureOptionsDialog::interfaceItemChanged(QTreeWidgetItem *item, int colum switch(column) { case col_pmode_: - device->pmode = item->checkState(col_pmode_) == Qt::Checked ? TRUE : FALSE; + device->pmode = item->checkState(col_pmode_) == Qt::Checked ? true : false; ti->updateInterfaceColumns(device); break; #ifdef SHOW_MONITOR_COLUMN case col_monitor_: { - gboolean monitor_mode = FALSE; - if (ti->checkState(col_monitor_) == Qt::Checked) monitor_mode = TRUE; + bool monitor_mode = false; + if (ti->checkState(col_monitor_) == Qt::Checked) monitor_mode = true; if_capabilities_t *caps; char *auth_str = NULL; @@ -444,15 +472,16 @@ void CaptureOptionsDialog::interfaceItemChanged(QTreeWidgetItem *item, int colum if (caps != Q_NULLPTR) { for (int i = static_cast(g_list_length(device->links)) - 1; i >= 0; i--) { - GList* rem = g_list_nth(device->links, static_cast(i)); + GList* rem = g_list_nth(device->links, static_cast(i)); device->links = g_list_remove_link(device->links, rem); g_list_free_1(rem); } device->active_dlt = -1; device->monitor_mode_supported = caps->can_set_rfmon; - device->monitor_mode_enabled = monitor_mode; + device->monitor_mode_enabled = monitor_mode && caps->can_set_rfmon; + GList *lt_list = device->monitor_mode_enabled ? caps->data_link_types_rfmon : caps->data_link_types; - for (GList *lt_entry = caps->data_link_types; lt_entry != Q_NULLPTR; lt_entry = gxx_list_next(lt_entry)) { + for (GList *lt_entry = lt_list; lt_entry != Q_NULLPTR; lt_entry = gxx_list_next(lt_entry)) { link_row *linkr = new link_row(); data_link_info_t *data_link_info = gxx_list_data(data_link_info_t *, lt_entry); /* @@ -470,7 +499,7 @@ void CaptureOptionsDialog::interfaceItemChanged(QTreeWidgetItem *item, int colum } linkr->name = g_strdup(data_link_info->description); } else { - gchar *str; + char *str; /* XXX - should we just omit them? */ str = ws_strdup_printf("%s (not supported)", data_link_info->name); linkr->dlt = -1; @@ -483,8 +512,8 @@ void CaptureOptionsDialog::interfaceItemChanged(QTreeWidgetItem *item, int colum } else { /* We don't know whether this supports monitor mode or not; don't ask for monitor mode. */ - device->monitor_mode_enabled = FALSE; - device->monitor_mode_supported = FALSE; + device->monitor_mode_enabled = false; + device->monitor_mode_supported = false; } ti->updateInterfaceColumns(device); @@ -565,6 +594,36 @@ void CaptureOptionsDialog::itemDoubleClicked(QTreeWidgetItem *item, int column) } } +void CaptureOptionsDialog::MBComboBoxIndexChanged(int index) +{ + switch (index) { + case 0: // kilobytes + ui->MBSpinBox->setMaximum(2000000000); + break; + case 1: // megabytes + ui->MBSpinBox->setMaximum(2000000); + break; + case 2: // gigabytes + ui->MBSpinBox->setMaximum(2000); + break; + } +} + +void CaptureOptionsDialog::stopMBComboBoxIndexChanged(int index) +{ + switch (index) { + case 0: // kilobytes + ui->stopMBSpinBox->setMaximum(2000000000); + break; + case 1: // megabytes + ui->stopMBSpinBox->setMaximum(2000000); + break; + case 2: // gigabytes + ui->stopMBSpinBox->setMaximum(2000); + break; + } +} + void CaptureOptionsDialog::on_gbStopCaptureAuto_toggled(bool checked) { global_capture_opts.has_file_interval = checked; @@ -578,7 +637,7 @@ void CaptureOptionsDialog::on_gbNewFileAuto_toggled(bool checked) ui->stopMBComboBox->setEnabled(checked?false:true); ui->gbCompression->setEnabled(checked); ui->rbCompressionNone->setEnabled(checked); -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_ZLIBNG) ui->rbCompressionGzip->setEnabled(checked); #else ui->rbCompressionGzip->setEnabled(false); @@ -665,6 +724,8 @@ void CaptureOptionsDialog::updateInterfaces() ui->rbPcap->setChecked(true); } ui->capturePromModeCheckBox->setChecked(prefs.capture_prom_mode); + ui->captureMonitorModeCheckBox->setChecked(prefs.capture_monitor_mode); + ui->captureMonitorModeCheckBox->setEnabled(false); if (global_capture_opts.saving_to_file) { ui->filenameLineEdit->setText(QString(global_capture_opts.orig_save_file)); @@ -781,10 +842,10 @@ void CaptureOptionsDialog::updateInterfaces() ui->interfaceTree->clear(); #ifdef SHOW_BUFFER_COLUMN - gint buffer; + int buffer; #endif - gint snaplen; - gboolean hassnap, pmode; + int snaplen; + bool hassnap, pmode; QList selected_interfaces; disconnect(ui->interfaceTree, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(interfaceItemChanged(QTreeWidgetItem*,int))); @@ -792,7 +853,7 @@ void CaptureOptionsDialog::updateInterfaces() if (global_capture_opts.all_ifaces->len > 0) { interface_t *device; - for (guint device_idx = 0; device_idx < global_capture_opts.all_ifaces->len; device_idx++) { + for (unsigned device_idx = 0; device_idx < global_capture_opts.all_ifaces->len; device_idx++) { device = &g_array_index(global_capture_opts.all_ifaces, interface_t, device_idx); /* Continue if capture device is hidden */ @@ -835,11 +896,11 @@ void CaptureOptionsDialog::updateInterfaces() if (capture_dev_user_snaplen_find(device->name, &hassnap, &snaplen)) { /* Default snap length set in preferences */ device->snaplen = snaplen; - device->has_snaplen = snaplen == WTAP_MAX_PACKET_SIZE_STANDARD ? FALSE : hassnap; + device->has_snaplen = snaplen == WTAP_MAX_PACKET_SIZE_STANDARD ? false : hassnap; } else { /* No preferences set yet, use default values */ device->snaplen = WTAP_MAX_PACKET_SIZE_STANDARD; - device->has_snaplen = FALSE; + device->has_snaplen = false; } #ifdef SHOW_BUFFER_COLUMN @@ -849,6 +910,11 @@ void CaptureOptionsDialog::updateInterfaces() } else { device->buffer = DEFAULT_CAPTURE_BUFFER_SIZE; } +#endif +#ifdef SHOW_MONITOR_COLUMN + if (device->monitor_mode_supported) { + ui->captureMonitorModeCheckBox->setEnabled(true); + } #endif ti->updateInterfaceColumns(device); @@ -921,14 +987,14 @@ void CaptureOptionsDialog::updateStatistics(void) disconnect(ui->interfaceTree, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(interfaceItemChanged(QTreeWidgetItem*,int))); for (int row = 0; row < ui->interfaceTree->topLevelItemCount(); row++) { - for (guint if_idx = 0; if_idx < global_capture_opts.all_ifaces->len; if_idx++) { + for (unsigned if_idx = 0; if_idx < global_capture_opts.all_ifaces->len; if_idx++) { QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row); if (!ti) { continue; } device = &g_array_index(global_capture_opts.all_ifaces, interface_t, if_idx); QString device_name = ti->text(col_interface_); - if (device_name.compare(device->display_name) || device->hidden || device->type == IF_PIPE) { + if (device_name.compare(device->display_name) || device->hidden || device->if_info.type == IF_PIPE) { continue; } QList points = ti->data(col_traffic_, Qt::UserRole).value >(); @@ -942,13 +1008,17 @@ void CaptureOptionsDialog::updateStatistics(void) void CaptureOptionsDialog::on_compileBPF_clicked() { - QStringList interfaces; + QList interfaces; foreach (QTreeWidgetItem *ti, ui->interfaceTree->selectedItems()) { - interfaces.append(ti->text(col_interface_)); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + interfaces.emplaceBack(ti->text(col_interface_), ti->text(col_filter_)); +#else + interfaces.append(InterfaceFilter(ti->text(col_interface_), ti->text(col_filter_))); +#endif } QString filter = ui->captureFilterComboBox->currentText(); - CompiledFilterOutput *cfo = new CompiledFilterOutput(this, interfaces, filter); + CompiledFilterOutput *cfo = new CompiledFilterOutput(this, interfaces); cfo->show(); } @@ -1033,17 +1103,17 @@ bool CaptureOptionsDialog::saveOptionsToPreferences() global_capture_opts.autostop_filesize = ui->MBSpinBox->value(); int index = ui->MBComboBox->currentIndex(); switch (index) { - case 1: if (global_capture_opts.autostop_filesize > 2000) { + case 1: if (global_capture_opts.autostop_filesize > 2000000) { QMessageBox::warning(this, tr("Error"), - tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB.")); + tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB.")); return false; } else { global_capture_opts.autostop_filesize *= 1000; } break; - case 2: if (global_capture_opts.autostop_filesize > 2) { + case 2: if (global_capture_opts.autostop_filesize > 2000) { QMessageBox::warning(this, tr("Error"), - tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB.")); + tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB.")); return false; } else { global_capture_opts.autostop_filesize *= 1000000; @@ -1072,17 +1142,17 @@ bool CaptureOptionsDialog::saveOptionsToPreferences() global_capture_opts.autostop_filesize = ui->stopMBSpinBox->value(); int index = ui->stopMBComboBox->currentIndex(); switch (index) { - case 1: if (global_capture_opts.autostop_filesize > 2000) { + case 1: if (global_capture_opts.autostop_filesize > 2000000) { QMessageBox::warning(this, tr("Error"), - tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB.")); + tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB.")); return false; } else { global_capture_opts.autostop_filesize *= 1000; } break; - case 2: if (global_capture_opts.autostop_filesize > 2) { + case 2: if (global_capture_opts.autostop_filesize > 2000) { QMessageBox::warning(this, tr("Error"), - tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB.")); + tr("Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB.")); return false; } else { global_capture_opts.autostop_filesize *= 1000000; @@ -1185,7 +1255,7 @@ bool CaptureOptionsDialog::saveOptionsToPreferences() QTreeWidgetItem *ti = ui->interfaceTree->topLevelItem(row); QString device_name = ti->data(col_interface_, Qt::UserRole).toString(); device = getDeviceByName(device_name); - if (!device || device->pmode == -1) { + if (!device || !device->pmode) { continue; } pmode_list << QString("%1(%2)").arg(device->name).arg(device->pmode); @@ -1248,6 +1318,14 @@ bool CaptureOptionsDialog::saveOptionsToPreferences() global_capture_opts.compress_type = NULL; } + if (ui->rbTimeNum->isChecked() ) { + global_capture_opts.has_nametimenum = true; + } else if (ui->rbNumTime->isChecked() ) { + global_capture_opts.has_nametimenum = false; + } else { + global_capture_opts.has_nametimenum = false; + } + prefs_main_write(); return true; } @@ -1293,7 +1371,7 @@ void CaptureOptionsDialog::changeEvent(QEvent* event) interface_t *CaptureOptionsDialog::getDeviceByName(const QString device_name) { - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (device_name.compare(QString().fromUtf8(device->name)) == 0) { return device; @@ -1328,6 +1406,13 @@ QVariant InterfaceTreeWidgetItem::data(int column, int role) const return QVariant::fromValue(points); } + if (column == col_snaplen_ && role == Qt::DisplayRole) { + QVariant data = QTreeWidgetItem::data(column, role); + if (data.toInt() == WTAP_MAX_PACKET_SIZE_STANDARD || data.toInt() == 0) { + return InterfaceTreeDelegate::tr("default"); + } + return data; + } return QTreeWidgetItem::data(column, role); } @@ -1366,9 +1451,9 @@ QWidget* InterfaceTreeDelegate::createEditor(QWidget *parent, const QStyleOption { QWidget *w = NULL; #ifdef SHOW_BUFFER_COLUMN - gint buffer = DEFAULT_CAPTURE_BUFFER_SIZE; + int buffer = DEFAULT_CAPTURE_BUFFER_SIZE; #endif - guint snap = WTAP_MAX_PACKET_SIZE_STANDARD; + unsigned snap = WTAP_MAX_PACKET_SIZE_STANDARD; GList *links = NULL; if (idx.column() > 1 && idx.data().toString().compare(UTF8_EM_DASH)) { @@ -1419,9 +1504,10 @@ QWidget* InterfaceTreeDelegate::createEditor(QWidget *parent, const QStyleOption case col_snaplen_: { QSpinBox *sb = new QSpinBox(parent); - sb->setRange(1, WTAP_MAX_PACKET_SIZE_STANDARD); + sb->setRange(0, WTAP_MAX_PACKET_SIZE_STANDARD); sb->setValue(snap); sb->setWrapping(true); + sb->setSpecialValueText(tr("default")); connect(sb, SIGNAL(valueChanged(int)), this, SLOT(snapshotLengthChanged(int))); w = (QWidget*) sb; break; @@ -1505,7 +1591,7 @@ void InterfaceTreeDelegate::snapshotLengthChanged(int value) if (!device) { return; } - if (value != WTAP_MAX_PACKET_SIZE_STANDARD) { + if (value != WTAP_MAX_PACKET_SIZE_STANDARD && value != 0) { device->has_snaplen = true; device->snaplen = value; } else { diff --git a/ui/qt/capture_options_dialog.h b/ui/qt/capture_options_dialog.h index e9eea761..cc57467e 100644 --- a/ui/qt/capture_options_dialog.h +++ b/ui/qt/capture_options_dialog.h @@ -70,6 +70,7 @@ protected: private slots: void on_capturePromModeCheckBox_toggled(bool checked); + void on_captureMonitorModeCheckBox_toggled(bool checked); void on_gbStopCaptureAuto_toggled(bool checked); void on_cbUpdatePacketsRT_toggled(bool checked); void on_cbAutoScroll_toggled(bool checked); @@ -94,6 +95,8 @@ private slots: void itemDoubleClicked(QTreeWidgetItem *item, int column); void changeEvent(QEvent* event); void tempDirBrowseButtonClicked(); + void MBComboBoxIndexChanged(int index); + void stopMBComboBoxIndexChanged(int index); signals: void startCapture(); diff --git a/ui/qt/capture_options_dialog.ui b/ui/qt/capture_options_dialog.ui index f1e89146..c9eba3b6 100644 --- a/ui/qt/capture_options_dialog.ui +++ b/ui/qt/capture_options_dialog.ui @@ -97,6 +97,16 @@ + + + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + + + Enable monitor mode on all 802.11 interfaces + + + @@ -321,12 +331,6 @@ QAbstractSpinBox::PlusMinus - - 1 - - - 1000000 - 1 @@ -375,9 +379,6 @@ QAbstractSpinBox::PlusMinus - - 1 - 1000000 @@ -431,9 +432,6 @@ For example, use 1 hour to have a new file created every hour on the hour. QAbstractSpinBox::PlusMinus - - 1 - 1000000 @@ -473,7 +471,7 @@ For example, use 1 hour to have a new file created every hour on the hour. compression - + @@ -497,6 +495,44 @@ For example, use 1 hour to have a new file created every hour on the hour. + + + + File infix pattern + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + + + + + + YYYYmmDDHHMMSS_NNNNN + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + + + nameTimeNumBG + + + + + + + NNNNN_YYYYmmDDHHMMSS + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + + + nameTimeNumBG + + + + + + @@ -530,9 +566,6 @@ For example, use 1 hour to have a new file created every hour on the hour. true - - 2 - 65535 @@ -820,9 +853,6 @@ For example, use 1 hour to have a new file created every hour on the hour. QAbstractSpinBox::PlusMinus - - 2147483647 - 1 @@ -972,5 +1002,6 @@ For example, use 1 hour to have a new file created every hour on the hour. + diff --git a/ui/qt/capture_preferences_frame.cpp b/ui/qt/capture_preferences_frame.cpp index 361eb656..b20bfbed 100644 --- a/ui/qt/capture_preferences_frame.cpp +++ b/ui/qt/capture_preferences_frame.cpp @@ -36,6 +36,7 @@ CapturePreferencesFrame::CapturePreferencesFrame(QWidget *parent) : pref_device_ = prefFromPrefPtr(&prefs.capture_device); pref_prom_mode_ = prefFromPrefPtr(&prefs.capture_prom_mode); + pref_monitor_mode_ = prefFromPrefPtr(&prefs.capture_monitor_mode); pref_pcap_ng_ = prefFromPrefPtr(&prefs.capture_pcap_ng); pref_real_time_ = prefFromPrefPtr(&prefs.capture_real_time); pref_update_interval_ = prefFromPrefPtr(&prefs.capture_update_interval); @@ -71,7 +72,7 @@ void CapturePreferencesFrame::updateWidgets() } ui->defaultInterfaceComboBox->clear(); if ((global_capture_opts.all_ifaces->len == 0) && - (prefs_get_bool_value(pref_no_interface_load_, pref_stashed) == FALSE)) { + (prefs_get_bool_value(pref_no_interface_load_, pref_stashed) == false)) { /* * No interfaces - try refreshing the local interfaces, to * see whether any have showed up (or privileges have changed @@ -79,7 +80,7 @@ void CapturePreferencesFrame::updateWidgets() */ mainApp->refreshLocalInterfaces(); } - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); /* Continue if capture device is hidden */ @@ -122,6 +123,7 @@ void CapturePreferencesFrame::updateWidgets() } ui->capturePromModeCheckBox->setChecked(prefs_get_bool_value(pref_prom_mode_, pref_stashed)); + ui->captureMonitorModeCheckBox->setChecked(prefs_get_bool_value(pref_monitor_mode_, pref_stashed)); ui->capturePcapNgCheckBox->setChecked(prefs_get_bool_value(pref_pcap_ng_, pref_stashed)); ui->captureRealTimeCheckBox->setChecked(prefs_get_bool_value(pref_real_time_, pref_stashed)); ui->captureUpdateIntervalLineEdit->setText(QString::number(prefs_get_uint_value_real(pref_update_interval_, pref_stashed))); @@ -142,6 +144,11 @@ void CapturePreferencesFrame::on_capturePromModeCheckBox_toggled(bool checked) prefs_set_bool_value(pref_prom_mode_, checked, pref_stashed); } +void CapturePreferencesFrame::on_captureMonitorModeCheckBox_toggled(bool checked) +{ + prefs_set_bool_value(pref_monitor_mode_, checked, pref_stashed); +} + void CapturePreferencesFrame::on_capturePcapNgCheckBox_toggled(bool checked) { prefs_set_bool_value(pref_pcap_ng_, checked, pref_stashed); diff --git a/ui/qt/capture_preferences_frame.h b/ui/qt/capture_preferences_frame.h index 33cf29b8..35e3b495 100644 --- a/ui/qt/capture_preferences_frame.h +++ b/ui/qt/capture_preferences_frame.h @@ -32,6 +32,7 @@ protected: private slots: void on_defaultInterfaceComboBox_editTextChanged(const QString &new_iface); void on_capturePromModeCheckBox_toggled(bool checked); + void on_captureMonitorModeCheckBox_toggled(bool checked); void on_capturePcapNgCheckBox_toggled(bool checked); void on_captureRealTimeCheckBox_toggled(bool checked); void on_captureUpdateIntervalLineEdit_textChanged(const QString &new_str); @@ -43,6 +44,7 @@ private: pref_t *pref_device_; pref_t *pref_prom_mode_; + pref_t *pref_monitor_mode_; pref_t *pref_pcap_ng_; pref_t *pref_real_time_; pref_t *pref_update_interval_; diff --git a/ui/qt/capture_preferences_frame.ui b/ui/qt/capture_preferences_frame.ui index b5a0b4b8..c0a76efd 100644 --- a/ui/qt/capture_preferences_frame.ui +++ b/ui/qt/capture_preferences_frame.ui @@ -67,6 +67,16 @@ + + + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + + + Capture packets in monitor mode on 802.11 devices + + + diff --git a/ui/qt/coloring_rules_dialog.cpp b/ui/qt/coloring_rules_dialog.cpp index 20eb72b2..c33013b6 100644 --- a/ui/qt/coloring_rules_dialog.cpp +++ b/ui/qt/coloring_rules_dialog.cpp @@ -96,7 +96,7 @@ ColoringRulesDialog::ColoringRulesDialog(QWidget *parent, QString add_filter) : ui->buttonBox->addButton(copy_button, QDialogButtonBox::ActionRole); connect(copy_button, &CopyFromProfileButton::copyProfile, this, &ColoringRulesDialog::copyFromProfile); - QString abs_path = gchar_free_to_qstring(get_persconffile_path(COLORFILTERS_FILE_NAME, TRUE)); + QString abs_path = gchar_free_to_qstring(get_persconffile_path(COLORFILTERS_FILE_NAME, true)); if (file_exists(abs_path.toUtf8().constData())) { ui->pathLabel->setText(abs_path); ui->pathLabel->setUrl(QUrl::fromLocalFile(abs_path).toString()); @@ -229,7 +229,7 @@ void ColoringRulesDialog::updateHint(QModelIndex idx) if (errors_.count() > 0) { //take the list of QModelIndexes and sort them so first color rule error is displayed - //This isn't the most efficent algorithm, but the list shouldn't be large to matter + //This isn't the most efficient algorithm, but the list shouldn't be large to matter QList keys = errors_.keys(); //list is not guaranteed to be sorted, so force it @@ -315,7 +315,7 @@ void ColoringRulesDialog::changeColor(bool foreground) if (!current.isValid()) return; - QColorDialog *color_dlg = new QColorDialog(); + QColorDialog *color_dlg = new QColorDialog(this); color_dlg->setCurrentColor(colorRuleModel_.data(current, foreground ? Qt::ForegroundRole : Qt::BackgroundRole).toString()); connect(color_dlg, &QColorDialog::colorSelected, std::bind(&ColoringRulesDialog::colorChanged, this, foreground, std::placeholders::_1)); diff --git a/ui/qt/column_editor_frame.cpp b/ui/qt/column_editor_frame.cpp index ea527b9a..4525ea2c 100644 --- a/ui/qt/column_editor_frame.cpp +++ b/ui/qt/column_editor_frame.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include #include #include @@ -25,6 +23,7 @@ #include #include #include +#include ColumnEditorFrame::ColumnEditorFrame(QWidget *parent) : AccordionFrame(parent), @@ -43,10 +42,32 @@ ColumnEditorFrame::ColumnEditorFrame(QWidget *parent) : ui->typeComboBox->addItem(col_format_desc(i), QVariant(i)); } + // We want a behavior where the occurrenceLineEdit and type line edit + // will shrink, but where they won't expand past their needed space. + // Setting a stretch factor will make them expand (ignoring their + // SizePolicy) unless we also set the maximum width to their size hints. + // + ui->horizontalLayout->setStretchFactor(ui->titleLineEdit, 2); + ui->horizontalLayout->setStretchFactor(ui->occurrenceLineEdit, 1); + ui->occurrenceLineEdit->setMaximumWidth(ui->occurrenceLineEdit->sizeHint().width()); + // On Windows, this is necessary to make the popup be the width of the + // longest item, instead of the width matching the combobox and using + // ellipses. (Linux has the popup wider by default.) + ui->typeComboBox->view()->setMinimumWidth(ui->typeComboBox->sizeHint().width()); + // This lets the typeComboBox shrink a bit if the width is very small. + ui->typeComboBox->setMinimumContentsLength(20); + connect(ui->fieldsNameLineEdit, &FieldFilterEdit::textChanged, ui->fieldsNameLineEdit, &FieldFilterEdit::checkCustomColumn); connect(ui->fieldsNameLineEdit, &FieldFilterEdit::textChanged, this, &ColumnEditorFrame::checkCanResolve); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + connect(ui->typeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &ColumnEditorFrame::typeChanged); +#else + connect(ui->typeComboBox, &QComboBox::currentIndexChanged, this, + &ColumnEditorFrame::typeChanged); +#endif } ColumnEditorFrame::~ColumnEditorFrame() @@ -82,6 +103,34 @@ void ColumnEditorFrame::setFields(int index) ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); } +void ColumnEditorFrame::typeChanged(int index) +{ + // The fieldsNameLineEdit and occurrenceLineEdit are only relevant if the + // typeComboBox is COL_CUSTOM. The text for "Custom" is small. So when + // COL_CUSTOM is selected, shrink the size of the typeComboBox to what is + // necessary for "Custom" and give extra space to the fieldsNameLineEdit. + // For any other column type, do the reverse. + if (index == COL_CUSTOM) { + int width = fontMetrics().boundingRect(ui->typeComboBox->currentText()).width(); + if (!ui->typeComboBox->itemIcon(index).isNull()) { + width += ui->typeComboBox->iconSize().width() + 4; + } + QStyleOptionComboBox opt; + opt.initFrom(ui->typeComboBox); + QSize sh(width, ui->typeComboBox->height()); + width = ui->typeComboBox->style()->sizeFromContents(QStyle::CT_ComboBox, &opt, sh, ui->typeComboBox).width(); + ui->typeComboBox->setMaximumWidth(width); + ui->fieldsNameLineEdit->setMaximumWidth(16777215); // Default (no) maximum + ui->horizontalLayout->setStretchFactor(ui->typeComboBox, 1); + ui->horizontalLayout->setStretchFactor(ui->fieldsNameLineEdit, 4); + } else { + ui->typeComboBox->setMaximumWidth(ui->typeComboBox->sizeHint().width()); + ui->fieldsNameLineEdit->setMaximumWidth(ui->fieldsNameLineEdit->sizeHint().width()); + ui->horizontalLayout->setStretchFactor(ui->typeComboBox, 2); + ui->horizontalLayout->setStretchFactor(ui->fieldsNameLineEdit, 1); + } +} + void ColumnEditorFrame::editColumn(int column) { cur_column_ = column; @@ -146,12 +195,8 @@ void ColumnEditorFrame::on_buttonBox_accepted() set_column_title(cur_column_, col_str.constData()); set_column_format(cur_column_, ui->typeComboBox->currentIndex()); if (ui->typeComboBox->currentIndex() == COL_CUSTOM) { - gint width = recent_get_column_width(cur_column_); - gchar xalign = recent_get_column_xalign(cur_column_); col_str = ui->fieldsNameLineEdit->text().toUtf8(); set_column_custom_fields(cur_column_, col_str.constData()); - recent_set_column_width(cur_column_, width); - recent_set_column_xalign(cur_column_, xalign); if (!ui->occurrenceLineEdit->text().isEmpty()) { set_column_custom_occurrence(cur_column_, ui->occurrenceLineEdit->text().toInt()); } diff --git a/ui/qt/column_editor_frame.h b/ui/qt/column_editor_frame.h index 3778fb0d..6bd18cbb 100644 --- a/ui/qt/column_editor_frame.h +++ b/ui/qt/column_editor_frame.h @@ -47,6 +47,7 @@ private: QString saved_fields_; QString saved_occurrence_; void setFields(int index); + void typeChanged(int index); }; #endif // COLUMN_EDITOR_FRAME_H diff --git a/ui/qt/column_editor_frame.ui b/ui/qt/column_editor_frame.ui index 682be2bc..781b2d9b 100644 --- a/ui/qt/column_editor_frame.ui +++ b/ui/qt/column_editor_frame.ui @@ -19,7 +19,7 @@ QFrame::Plain - + 0 @@ -43,7 +43,7 @@ - 20 + 10 5 @@ -66,7 +66,7 @@ - 20 + 10 5 @@ -89,7 +89,7 @@ - 20 + 10 5 @@ -125,7 +125,7 @@ - 20 + 10 5 diff --git a/ui/qt/column_preferences_frame.cpp b/ui/qt/column_preferences_frame.cpp index 961e2737..3bfd8bdb 100644 --- a/ui/qt/column_preferences_frame.cpp +++ b/ui/qt/column_preferences_frame.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include #include #include diff --git a/ui/qt/compiled_filter_output.cpp b/ui/qt/compiled_filter_output.cpp index 1db9c899..7e7d778e 100644 --- a/ui/qt/compiled_filter_output.cpp +++ b/ui/qt/compiled_filter_output.cpp @@ -28,10 +28,9 @@ #include #include -CompiledFilterOutput::CompiledFilterOutput(QWidget *parent, QStringList &intList, QString &compile_filter) : +CompiledFilterOutput::CompiledFilterOutput(QWidget *parent, QList &intList) : GeometryStateDialog(parent), intList_(intList), - compile_filter_(compile_filter), ui(new Ui::CompiledFilterOutput) { ui->setupUi(this); @@ -47,8 +46,7 @@ CompiledFilterOutput::CompiledFilterOutput(QWidget *parent, QStringList &intList close_bt->setDefault(true); interface_list_ = ui->interfaceList; - pcap_compile_mtx = g_new(GMutex,1); - g_mutex_init(pcap_compile_mtx); + g_mutex_init(&pcap_compile_mtx_); #ifdef HAVE_LIBPCAP compileFilter(); #endif @@ -64,6 +62,7 @@ CompiledFilterOutput::~CompiledFilterOutput() parentWidget()->activateWindow(); } delete ui; + g_mutex_clear(&pcap_compile_mtx_); } #ifdef HAVE_LIBPCAP @@ -71,21 +70,21 @@ void CompiledFilterOutput::compileFilter() { struct bpf_program fcode; - foreach (QString interfaces, intList_) { - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + foreach (InterfaceFilter current, intList_) { + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); - if (interfaces.compare(device->display_name)) { + if (current.interface.compare(device->display_name)) { continue; } else { pcap_t *pd = pcap_open_dead(device->active_dlt, WTAP_MAX_PACKET_SIZE_STANDARD); if (pd == NULL) break; - g_mutex_lock(pcap_compile_mtx); - if (pcap_compile(pd, &fcode, compile_filter_.toUtf8().data(), 1, 0) < 0) { - compile_results.insert(interfaces, QString(pcap_geterr(pd))); - g_mutex_unlock(pcap_compile_mtx); - ui->interfaceList->addItem(new QListWidgetItem(QIcon(":expert/expert_error.png"),interfaces)); + g_mutex_lock(&pcap_compile_mtx_); + if (pcap_compile(pd, &fcode, current.filter.toUtf8().data(), 1, 0) < 0) { + compile_results.insert(current.interface, QString(pcap_geterr(pd))); + g_mutex_unlock(&pcap_compile_mtx_); + ui->interfaceList->addItem(new QListWidgetItem(QIcon(":expert/expert_error.png"), current.interface)); } else { GString *bpf_code_dump = g_string_new(""); struct bpf_insn *insn = fcode.bf_insns; @@ -94,11 +93,13 @@ void CompiledFilterOutput::compileFilter() g_string_append(bpf_code_dump, bpf_image(insn, ii)); g_string_append(bpf_code_dump, "\n"); } - g_mutex_unlock(pcap_compile_mtx); - compile_results.insert(interfaces, QString(bpf_code_dump->str)); + g_mutex_unlock(&pcap_compile_mtx_); + compile_results.insert(current.interface, QString(bpf_code_dump->str)); g_string_free(bpf_code_dump, TRUE); - ui->interfaceList->addItem(new QListWidgetItem(interfaces)); + ui->interfaceList->addItem(new QListWidgetItem(current.interface)); + pcap_freecode(&fcode); } + pcap_close(pd); break; } } diff --git a/ui/qt/compiled_filter_output.h b/ui/qt/compiled_filter_output.h index a94fc4f0..d87c7c29 100644 --- a/ui/qt/compiled_filter_output.h +++ b/ui/qt/compiled_filter_output.h @@ -19,6 +19,13 @@ #include +struct InterfaceFilter { + InterfaceFilter(QString intf, QString filt) : interface(intf), filter(filt) {} + + QString interface; + QString filter; +}; + namespace Ui { class CompiledFilterOutput; } @@ -28,10 +35,9 @@ class CompiledFilterOutput : public GeometryStateDialog Q_OBJECT private: - QStringList intList_; - QString &compile_filter_; + QList intList_; Ui::CompiledFilterOutput *ui; - GMutex *pcap_compile_mtx; + GMutex pcap_compile_mtx_; QHash compile_results; QListWidget *interface_list_; QPushButton *copy_bt_; @@ -40,7 +46,7 @@ private: #endif public: - explicit CompiledFilterOutput(QWidget *parent = 0, QStringList &intList = *new QStringList(), QString &filter = *new QString()); + explicit CompiledFilterOutput(QWidget *parent = 0, QList &intList = *new QList()); ~CompiledFilterOutput(); diff --git a/ui/qt/conversation_colorize_action.cpp b/ui/qt/conversation_colorize_action.cpp index 9518e1ee..cb358472 100644 --- a/ui/qt/conversation_colorize_action.cpp +++ b/ui/qt/conversation_colorize_action.cpp @@ -11,8 +11,6 @@ #include -#include - #include "epan/conversation_filter.h" #include diff --git a/ui/qt/conversation_dialog.cpp b/ui/qt/conversation_dialog.cpp index bad3d6d2..cd69e434 100644 --- a/ui/qt/conversation_dialog.cpp +++ b/ui/qt/conversation_dialog.cpp @@ -71,7 +71,7 @@ ConversationDialog::ConversationDialog(QWidget &parent, CaptureFile &cf) : { trafficList()->setProtocolInfo(table_name_, &(recent.conversation_tabs)); - trafficTab()->setProtocolInfo(table_name_, trafficList(), &(recent.conversation_tabs_columns), &createModel); + trafficTab()->setProtocolInfo(table_name_, trafficList(), &(recent.conversation_tabs), &(recent.conversation_tabs_columns), &createModel); trafficTab()->setDelegate(&createDelegate); trafficTab()->setDelegate(&createDelegate); trafficTab()->setFilter(cf.displayFilter()); @@ -148,6 +148,9 @@ void ConversationDialog::graphTcp() void ConversationDialog::tabChanged(int) { + // By default we'll open the last known opened tab from the Profile + GList *selected_tab = NULL; + bool follow = false; bool graph = false; @@ -155,6 +158,19 @@ void ConversationDialog::tabChanged(int) QVariant proto_id = trafficTab()->currentItemData(ATapDataModel::PROTO_ID); if (!proto_id.isNull()) { follow = (get_follow_by_proto_id(proto_id.toInt()) != nullptr); + + for (GList * endTab = recent.conversation_tabs; endTab; endTab = endTab->next) { + int protoId = proto_get_id_by_short_name((const char *)endTab->data); + if ((protoId > -1) && (protoId==proto_id.toInt())) { + selected_tab = endTab; + } + } + + // Move the selected tab to the head + if (selected_tab != nullptr) { + recent.conversation_tabs = g_list_remove_link(recent.conversation_tabs, selected_tab); + recent.conversation_tabs = g_list_prepend(recent.conversation_tabs, selected_tab->data); + } } int endpointType = trafficTab()->currentItemData(ATapDataModel::ENDPOINT_DATATYPE).toInt(); switch(endpointType) { diff --git a/ui/qt/conversation_dialog.h b/ui/qt/conversation_dialog.h index 5ad058ac..e54b67f4 100644 --- a/ui/qt/conversation_dialog.h +++ b/ui/qt/conversation_dialog.h @@ -28,7 +28,7 @@ protected: void captureFileClosing(); signals: - void openFollowStreamDialog(int proto_id, guint stream_num, guint sub_stream_num); + void openFollowStreamDialog(int proto_id, unsigned stream_num, unsigned sub_stream_num); private: QPushButton *follow_bt_; diff --git a/ui/qt/conversation_hash_tables_dialog.cpp b/ui/qt/conversation_hash_tables_dialog.cpp index cc699dae..f7f4fc74 100644 --- a/ui/qt/conversation_hash_tables_dialog.cpp +++ b/ui/qt/conversation_hash_tables_dialog.cpp @@ -12,8 +12,6 @@ #include "config.h" -#include - #include #include @@ -21,7 +19,7 @@ #include "main_application.h" static void -fill_named_table(gpointer key, gpointer value _U_, gpointer user_data) +fill_named_table(void *key, void *value _U_, void *user_data) { const conversation_element_t *elements = static_cast(key); QString* html_table = static_cast(user_data); @@ -38,6 +36,8 @@ fill_named_table(gpointer key, gpointer value _U_, gpointer user_data) int uint_count = 1; int uint64_count = 1; int int_count = 1; + int int64_count = 1; + int blob_count = 1; for (const conversation_element_t *cur_el = elements; ; cur_el++) { QString title; switch (cur_el->type) { @@ -59,6 +59,12 @@ fill_named_table(gpointer key, gpointer value _U_, gpointer user_data) case CE_INT: title = QString("Int %1").arg(int_count++); break; + case CE_INT64: + title = QString("Int64 %1").arg(int64_count++); + break; + case CE_BLOB: + title = QString("Blob %1").arg(blob_count++); + break; case CE_CONVERSATION_TYPE: html_table->append(QString("Endpoint")); goto title_done; @@ -93,6 +99,12 @@ title_done: case CE_INT: val = QString::number(cur_el->int_val); break; + case CE_INT64: + val = QString::number(cur_el->int64_val); + break; + case CE_BLOB: + val = QString(QByteArray::fromRawData((const char *)cur_el->blob.val, (int)cur_el->blob.len).toHex()); + break; case CE_CONVERSATION_TYPE: html_table->append(QString("%1").arg(QString::number(cur_el->conversation_type_val))); goto val_done; diff --git a/ui/qt/decode_as_dialog.cpp b/ui/qt/decode_as_dialog.cpp index edc6ccc7..c45fae2e 100644 --- a/ui/qt/decode_as_dialog.cpp +++ b/ui/qt/decode_as_dialog.cpp @@ -65,7 +65,7 @@ DecodeAsDialog::DecodeAsDialog(QWidget *parent, capture_file *cf, bool create_ne setWindowTitle(mainApp->windowTitleString(tr("Decode As…"))); - QString abs_path = gchar_free_to_qstring(get_persconffile_path(DECODE_AS_ENTRIES_FILE_NAME, TRUE)); + QString abs_path = gchar_free_to_qstring(get_persconffile_path(DECODE_AS_ENTRIES_FILE_NAME, true)); if (file_exists(abs_path.toUtf8().constData())) { ui->pathLabel->setText(abs_path); ui->pathLabel->setUrl(QUrl::fromLocalFile(abs_path).toString()); @@ -137,7 +137,7 @@ void DecodeAsDialog::on_decodeAsTreeView_currentItemChanged(const QModelIndex &c void DecodeAsDialog::copyFromProfile(QString filename) { - const gchar *err = NULL; + const char *err = NULL; if (!model_->copyFromProfile(filename, &err)) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Error while loading %s: %s", filename.toUtf8().constData(), err); @@ -213,7 +213,7 @@ void DecodeAsDialog::on_buttonBox_clicked(QAbstractButton *button) break; case QDialogButtonBox::Save: { - gchar* err = NULL; + char* err = NULL; applyChanges(); if (save_decode_as_entries(&err) < 0) { diff --git a/ui/qt/decode_as_dialog.h b/ui/qt/decode_as_dialog.h index 8765489a..73d664d3 100644 --- a/ui/qt/decode_as_dialog.h +++ b/ui/qt/decode_as_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include "cfile.h" #include #include diff --git a/ui/qt/display_filter_expression_dialog.cpp b/ui/qt/display_filter_expression_dialog.cpp index e071d0ab..d192ec4f 100644 --- a/ui/qt/display_filter_expression_dialog.cpp +++ b/ui/qt/display_filter_expression_dialog.cpp @@ -316,9 +316,9 @@ void DisplayFilterExpressionDialog::updateWidgets() void DisplayFilterExpressionDialog::fillEnumBooleanValues(const true_false_string *tfs) { - QListWidgetItem *eli = new QListWidgetItem(tfs_get_string(TRUE, tfs), ui->enumListWidget); + QListWidgetItem *eli = new QListWidgetItem(tfs_get_string(true, tfs), ui->enumListWidget); eli->setData(Qt::UserRole, QString("1")); - eli = new QListWidgetItem(tfs_get_string(FALSE, tfs), ui->enumListWidget); + eli = new QListWidgetItem(tfs_get_string(false, tfs), ui->enumListWidget); eli->setData(Qt::UserRole, QString("0")); } diff --git a/ui/qt/endpoint_dialog.cpp b/ui/qt/endpoint_dialog.cpp index 38a30be2..d3fd98d0 100644 --- a/ui/qt/endpoint_dialog.cpp +++ b/ui/qt/endpoint_dialog.cpp @@ -69,7 +69,7 @@ EndpointDialog::EndpointDialog(QWidget &parent, CaptureFile &cf) : { trafficList()->setProtocolInfo(table_name_, &(recent.endpoint_tabs)); - trafficTab()->setProtocolInfo(table_name_, trafficList(), &(recent.endpoint_tabs_columns), &createModel); + trafficTab()->setProtocolInfo(table_name_, trafficList(), &(recent.endpoint_tabs), &(recent.endpoint_tabs_columns), &createModel); trafficTab()->setFilter(cf.displayFilter()); connect(trafficTab(), &TrafficTab::filterAction, this, &EndpointDialog::filterAction); @@ -111,6 +111,29 @@ void EndpointDialog::tabChanged(int idx) Q_UNUSED(idx); #endif + + // By default we'll open the last known opened tab from the Profile + GList *selected_tab = NULL; + + if (!file_closed_) { + QVariant proto_id = trafficTab()->currentItemData(ATapDataModel::PROTO_ID); + if (!proto_id.isNull()) { + + for (GList * endTab = recent.endpoint_tabs; endTab; endTab = endTab->next) { + int protoId = proto_get_id_by_short_name((const char *)endTab->data); + if ((protoId > -1) && (protoId==proto_id.toInt())) { + selected_tab = endTab; + } + } + + // Move the selected tab to the head + if (selected_tab != nullptr) { + recent.endpoint_tabs = g_list_remove_link(recent.endpoint_tabs, selected_tab); + recent.endpoint_tabs = g_list_prepend(recent.endpoint_tabs, selected_tab->data); + } + } + } + TrafficTableDialog::currentTabChanged(); } diff --git a/ui/qt/expert_info_dialog.h b/ui/qt/expert_info_dialog.h index 1494ffb4..38eb8f09 100644 --- a/ui/qt/expert_info_dialog.h +++ b/ui/qt/expert_info_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include "filter_action.h" #include "wireshark_dialog.h" #include diff --git a/ui/qt/export_dissection_dialog.cpp b/ui/qt/export_dissection_dialog.cpp index 5b09efcd..3a51bfd4 100644 --- a/ui/qt/export_dissection_dialog.cpp +++ b/ui/qt/export_dissection_dialog.cpp @@ -9,12 +9,6 @@ #include "export_dissection_dialog.h" -#ifdef Q_OS_WIN -#include -#include "ui/packet_range.h" -#include "ui/win32/file_dlg_win32.h" -#else // Q_OS_WIN - #include "ui/alert_box.h" #include "ui/help_url.h" #include "ui/util.h" @@ -28,12 +22,9 @@ #include #include #include -#endif // Q_OS_WIN -#include #include "main_application.h" -#if !defined(Q_OS_WIN) static const QStringList export_extensions = QStringList() << "" << "txt" @@ -44,45 +35,16 @@ static const QStringList export_extensions = QStringList() << "c" << "json"; -#endif - ExportDissectionDialog::ExportDissectionDialog(QWidget *parent, capture_file *cap_file, export_type_e export_type, QString selRange): WiresharkFileDialog(parent), export_type_(export_type), cap_file_(cap_file) -#if !defined(Q_OS_WIN) , save_bt_(NULL) -#else - , sel_range_(selRange) -#endif /* Q_OS_WIN */ { setWindowTitle(mainApp->windowTitleString(tr("Export Packet Dissections"))); - switch (prefs.gui_fileopen_style) { - - case FO_STYLE_LAST_OPENED: - /* The user has specified that we should start out in the last directory - * we looked in. If we've already opened a file, use its containing - * directory, if we could determine it, as the directory, otherwise - * use the "last opened" directory saved in the preferences file if - * there was one. - */ - setDirectory(mainApp->openDialogInitialDir()); - break; - - case FO_STYLE_SPECIFIED: - /* The user has specified that we should always start out in a - * specified directory; if they've specified that directory, - * start out by showing the files in that dir. - */ - if (prefs.gui_fileopen_dir[0] != '\0') - setDirectory(prefs.gui_fileopen_dir); - break; - } + setDirectory(mainApp->openDialogInitialDir()); -#if !defined(Q_OS_WIN) - // Add extra widgets - // https://wiki.qt.io/Qt_project_org_faq#How_can_I_add_widgets_to_my_QFileDialog_instance.3F setOption(QFileDialog::DontUseNativeDialog, true); QDialogButtonBox *button_box = findChild(); QGridLayout *fd_grid = qobject_cast(layout()); @@ -119,7 +81,7 @@ ExportDissectionDialog::ExportDissectionDialog(QWidget *parent, capture_file *ca /* Init the export range */ packet_range_init(&print_args_.range, cap_file_); /* Default to displayed packets */ - print_args_.range.process_filtered = TRUE; + print_args_.range.process_filtered = true; packet_range_group_box_.initRange(&print_args_.range, selRange); h_box->addWidget(&packet_range_group_box_); @@ -128,47 +90,39 @@ ExportDissectionDialog::ExportDissectionDialog(QWidget *parent, capture_file *ca if (button_box) { button_box->addButton(QDialogButtonBox::Help); - connect(button_box, SIGNAL(helpRequested()), this, SLOT(on_buttonBox_helpRequested())); + connect(button_box, &QDialogButtonBox::helpRequested, this, &ExportDissectionDialog::on_buttonBox_helpRequested); save_bt_ = button_box->button(QDialogButtonBox::Save); } if (save_bt_) { - connect(&packet_range_group_box_, SIGNAL(validityChanged(bool)), - this, SLOT(checkValidity())); - connect(&packet_format_group_box_, SIGNAL(formatChanged()), - this, SLOT(checkValidity())); + connect(&packet_range_group_box_, &PacketRangeGroupBox::validityChanged, + this, &ExportDissectionDialog::checkValidity); + connect(&packet_format_group_box_, &PacketFormatGroupBox::formatChanged, + this, &ExportDissectionDialog::checkValidity); + save_bt_->installEventFilter(this); } - connect(this, SIGNAL(filterSelected(QString)), this, SLOT(exportTypeChanged(QString))); + connect(this, &ExportDissectionDialog::filterSelected, this, &ExportDissectionDialog::exportTypeChanged); // Grow the dialog to account for the extra widgets. resize(width(), height() + (packet_range_group_box_.height() * 2 / 3)); - connect(this, SIGNAL(filesSelected(QStringList)), this, SLOT(dialogAccepted(QStringList))); -#else // Q_OS_WIN -#endif // Q_OS_WIN + connect(this, &ExportDissectionDialog::filesSelected, this, &ExportDissectionDialog::dialogAccepted); } ExportDissectionDialog::~ExportDissectionDialog() { -#if !defined(Q_OS_WIN) g_free(print_args_.file); packet_range_cleanup(&print_args_.range); -#endif } void ExportDissectionDialog::show() { -#if !defined(Q_OS_WIN) if (cap_file_) { WiresharkFileDialog::show(); } -#else // Q_OS_WIN - win32_export_file((HWND)parentWidget()->effectiveWinId(), windowTitle().toStdWString().c_str(), cap_file_, export_type_, sel_range_.toStdString().c_str()); -#endif // Q_OS_WIN } -#ifndef Q_OS_WIN void ExportDissectionDialog::dialogAccepted(const QStringList &selected) { if (selected.length() > 0) { @@ -179,19 +133,19 @@ void ExportDissectionDialog::dialogAccepted(const QStringList &selected) */ hide(); cf_print_status_t status; - QString file_name = selected[0]; + QString file_name = QDir::toNativeSeparators(selected[0]); /* Fill in our print (and export) args */ print_args_.file = qstring_strdup(file_name); print_args_.format = PR_FMT_TEXT; - print_args_.to_file = TRUE; + print_args_.to_file = true; print_args_.cmd = NULL; - print_args_.print_summary = TRUE; - print_args_.print_col_headings = TRUE; + print_args_.print_summary = true; + print_args_.print_col_headings = true; print_args_.print_dissections = print_dissections_as_displayed; - print_args_.print_hex = FALSE; - print_args_.print_formfeed = FALSE; + print_args_.print_hex = false; + print_args_.print_formfeed = false; switch (export_type_) { case export_type_text: /* Text */ @@ -208,12 +162,12 @@ void ExportDissectionDialog::dialogAccepted(const QStringList &selected) } print_args_.print_hex = packet_format_group_box_.bytesEnabled(); print_args_.hexdump_options = packet_format_group_box_.getHexdumpOptions(); - print_args_.stream = print_stream_text_new(TRUE, print_args_.file); + print_args_.stream = print_stream_text_new(true, print_args_.file); if (print_args_.stream == NULL) { - open_failure_alert_box(print_args_.file, errno, TRUE); + open_failure_alert_box(print_args_.file, errno, true); return; } - status = cf_print_packets(cap_file_, &print_args_, TRUE); + status = cf_print_packets(cap_file_, &print_args_, true); break; case export_type_csv: /* CSV */ status = cf_write_csv_packets(cap_file_, &print_args_); @@ -238,14 +192,14 @@ void ExportDissectionDialog::dialogAccepted(const QStringList &selected) case CF_PRINT_OK: break; case CF_PRINT_OPEN_ERROR: - open_failure_alert_box(print_args_.file, errno, TRUE); + open_failure_alert_box(print_args_.file, errno, true); break; case CF_PRINT_WRITE_ERROR: write_failure_alert_box(print_args_.file, errno); break; } - gchar *dirname; + char *dirname; /* Save the directory name for future file dialogs. */ dirname = get_dirname(print_args_.file); /* Overwrites file_name data */ set_last_open_dir(dirname); @@ -266,28 +220,55 @@ void ExportDissectionDialog::exportTypeChanged(QString name_filter) setDefaultSuffix(export_extensions[export_type_]); } -void ExportDissectionDialog::checkValidity() +bool ExportDissectionDialog::isValid() { - bool enable = true; - - if (!save_bt_) return; + bool valid = true; - if (!packet_range_group_box_.isValid()) enable = false; + if (!packet_range_group_box_.isValid()) valid = false; if (export_type_ == export_type_text) { if (! packet_format_group_box_.summaryEnabled() && ! packet_format_group_box_.detailsEnabled() && ! packet_format_group_box_.bytesEnabled()) { - enable = false; + valid = false; } } - save_bt_->setEnabled(enable); + return valid; +} + +void ExportDissectionDialog::checkValidity() +{ + if (!save_bt_) return; + + save_bt_->setEnabled(isValid()); } void ExportDissectionDialog::on_buttonBox_helpRequested() { mainApp->helpTopicAction(HELP_EXPORT_FILE_DIALOG); } -#endif // Q_OS_WIN + +bool ExportDissectionDialog::eventFilter(QObject *obj, QEvent *event) +{ + // The QFileDialogPrivate will enable the Ok (Open/Save) button when + // anything is typed or selected. We can't catch that beforehand, so + // watch for the enable status change and re-disable it if the + // group boxes are invalid. + // We could do extra work (here and elsewhere) not to disable the button + // if what's selected in the dialog is a directory, but even with save_bt_ + // disabled clicking on the directory still opens it. + if (event->type() == QEvent::EnabledChange) { + QPushButton *button = qobject_cast(obj); + if (button && button == save_bt_) { + // The button is already changed by the time we get this event. + if (button->isEnabled() && !isValid()) { + button->setEnabled(false); + return true; + } + } + } + + return QObject::eventFilter(obj, event); +} diff --git a/ui/qt/export_dissection_dialog.h b/ui/qt/export_dissection_dialog.h index 6d794918..47cb8ac8 100644 --- a/ui/qt/export_dissection_dialog.h +++ b/ui/qt/export_dissection_dialog.h @@ -12,18 +12,14 @@ #include -#include - #include "file.h" #include "epan/print.h" #include "ui/file_dialog.h" #include -#ifndef Q_OS_WIN #include "packet_range_group_box.h" #include "packet_format_group_box.h" -#endif // Q_OS_WIN #include @@ -38,18 +34,18 @@ public: public slots: void show(); +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + private slots: -#ifndef Q_OS_WIN void dialogAccepted(const QStringList &selected); void exportTypeChanged(QString name_filter); void checkValidity(); void on_buttonBox_helpRequested(); -#endif // Q_OS_WIN private: export_type_e export_type_; capture_file *cap_file_; -#ifndef Q_OS_WIN print_args_t print_args_; QMap export_type_map_; @@ -58,9 +54,8 @@ private: PacketFormatGroupBox packet_format_group_box_; QPushButton *save_bt_; -#else - QString sel_range_; -#endif // Q_OS_WIN + + bool isValid(); }; #endif // EXPORT_DISSECTION_DIALOG_H diff --git a/ui/qt/export_object_action.cpp b/ui/qt/export_object_action.cpp index bccf84ff..84626647 100644 --- a/ui/qt/export_object_action.cpp +++ b/ui/qt/export_object_action.cpp @@ -9,7 +9,6 @@ #include -#include #include #include #include diff --git a/ui/qt/export_object_action.h b/ui/qt/export_object_action.h index e4cc4cc5..7e6f0656 100644 --- a/ui/qt/export_object_action.h +++ b/ui/qt/export_object_action.h @@ -12,7 +12,6 @@ #include "config.h" -#include #include #include diff --git a/ui/qt/export_pdu_dialog.cpp b/ui/qt/export_pdu_dialog.cpp index 09709e18..27b77842 100644 --- a/ui/qt/export_pdu_dialog.cpp +++ b/ui/qt/export_pdu_dialog.cpp @@ -19,6 +19,8 @@ #include "ui/export_pdu_ui_utils.h" #include "ui/capture_globals.h" +#include "main_application.h" + ExportPDUDialog::ExportPDUDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ExportPDUDialog) @@ -27,12 +29,15 @@ ExportPDUDialog::ExportPDUDialog(QWidget *parent) : ui->setupUi(this); + setWindowTitle(mainApp->windowTitleString(tr("Export PDUs"))); + for (tap_name_list = get_export_pdu_tap_list(); tap_name_list; tap_name_list = g_slist_next(tap_name_list)) { if (export_pdu_tap_get_encap((const char*)tap_name_list->data) == WTAP_ENCAP_WIRESHARK_UPPER_PDU) { ui->comboBox->addItem((const char*)(tap_name_list->data)); } } } + void ExportPDUDialog::on_buttonBox_accepted() { const QByteArray& filter = ui->displayFilterLineEdit->text().toUtf8(); @@ -40,6 +45,12 @@ void ExportPDUDialog::on_buttonBox_accepted() do_export_pdu(filter.constData(), global_capture_opts.temp_dir, tap_name.constData()); } + +void ExportPDUDialog::on_buttonBox_helpRequested() +{ + mainApp->helpTopicAction(HELP_EXPORT_PDUS_DIALOG); +} + ExportPDUDialog::~ExportPDUDialog() { delete ui; diff --git a/ui/qt/export_pdu_dialog.h b/ui/qt/export_pdu_dialog.h index e76399a9..48d76f71 100644 --- a/ui/qt/export_pdu_dialog.h +++ b/ui/qt/export_pdu_dialog.h @@ -30,6 +30,7 @@ private: private slots: void on_buttonBox_accepted(); + void on_buttonBox_helpRequested(); }; #endif // EXPORT_PDU_DIALOG_H diff --git a/ui/qt/export_pdu_dialog.ui b/ui/qt/export_pdu_dialog.ui index 2a0fae81..6127ba8b 100644 --- a/ui/qt/export_pdu_dialog.ui +++ b/ui/qt/export_pdu_dialog.ui @@ -26,7 +26,7 @@ Qt::Horizontal - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Help @@ -75,32 +75,12 @@ accepted() ExportPDUDialog accept() - - - 248 - 254 - - - 157 - 274 - - buttonBox rejected() ExportPDUDialog reject() - - - 316 - 260 - - - 286 - 274 - - diff --git a/ui/qt/extcap_argument.cpp b/ui/qt/extcap_argument.cpp index 0a965a79..84cbf906 100644 --- a/ui/qt/extcap_argument.cpp +++ b/ui/qt/extcap_argument.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -105,7 +106,7 @@ QString ExtArgTimestamp::prefValue() bool ExtArgTimestamp::isSetDefaultValueSupported() { - return TRUE; + return true; } void ExtArgTimestamp::setDefaultValue() @@ -230,7 +231,7 @@ QString ExtArgSelector::value() bool ExtArgSelector::isSetDefaultValueSupported() { - return TRUE; + return true; } void ExtArgSelector::setDefaultValue() @@ -313,6 +314,11 @@ void ExtArgEditSelector::setDefaultValue() ExtArgRadio::ExtArgRadio(extcap_arg * argument, QObject * parent) : ExtcapArgument(argument, parent), selectorGroup(0), callStrings(0) {} +ExtArgRadio::~ExtArgRadio() { + if (callStrings != nullptr) + delete callStrings; +} + QWidget * ExtArgRadio::createEditor(QWidget * parent) { int count = 0; @@ -394,7 +400,7 @@ bool ExtArgRadio::isValid() bool ExtArgRadio::isSetDefaultValueSupported() { - return TRUE; + return true; } void ExtArgRadio::setDefaultValue() @@ -497,7 +503,7 @@ bool ExtArgBool::defaultBool() if (_argument) { - if (extcap_complex_get_bool(_argument->default_complex) == (gboolean)TRUE) + if (extcap_complex_get_bool(_argument->default_complex) == true) result = true; } @@ -511,7 +517,7 @@ QString ExtArgBool::defaultValue() bool ExtArgBool::isSetDefaultValueSupported() { - return TRUE; + return true; } void ExtArgBool::setDefaultValue() @@ -618,7 +624,7 @@ bool ExtArgText::isValid() bool ExtArgText::isSetDefaultValueSupported() { - return TRUE; + return true; } void ExtArgText::setDefaultValue() @@ -654,14 +660,14 @@ QWidget * ExtArgNumber::createEditor(QWidget * parent) val = extcap_complex_get_int(_argument->range_start); else if (_argument->arg_type == EXTCAP_ARG_UNSIGNED) { - guint tmp = extcap_complex_get_uint(_argument->range_start); - if (tmp > G_MAXINT) + unsigned tmp = extcap_complex_get_uint(_argument->range_start); + if (tmp > INT_MAX) { ws_log(LOG_DOMAIN_CAPTURE, LOG_LEVEL_DEBUG, "Defined value for range_start of %s exceeds valid integer range", _argument->call); - val = G_MAXINT; + val = INT_MAX; } else - val = (gint)tmp; + val = (int)tmp; } textValidator->setBottom(val); @@ -679,14 +685,14 @@ QWidget * ExtArgNumber::createEditor(QWidget * parent) val = extcap_complex_get_int(_argument->range_end); else if (_argument->arg_type == EXTCAP_ARG_UNSIGNED) { - guint tmp = extcap_complex_get_uint(_argument->range_end); - if (tmp > G_MAXINT) + unsigned tmp = extcap_complex_get_uint(_argument->range_end); + if (tmp > INT_MAX) { ws_log(LOG_DOMAIN_CAPTURE, LOG_LEVEL_DEBUG, "Defined value for range_end of %s exceeds valid integer range", _argument->call); - val = G_MAXINT; + val = INT_MAX; } else - val = (gint)tmp; + val = (int)tmp; } textValidator->setTop(val); @@ -807,7 +813,7 @@ ExtcapValueList ExtcapArgument::loadValues(QString parent) QString call = QString().fromUtf8(v->call); ExtcapValue element = ExtcapValue(display, call, - v->enabled == (gboolean)TRUE, v->is_default == (gboolean)TRUE); + v->enabled == true, v->is_default == true); if (!call.isEmpty()) element.setChildren(this->loadValues(call)); @@ -839,6 +845,7 @@ bool ExtcapArgument::reloadValues() } ExtcapArgument::~ExtcapArgument() { + extcap_free_arg(_argument); } QWidget * ExtcapArgument::createLabel(QWidget * parent) @@ -907,9 +914,9 @@ QString ExtcapArgument::defaultValue() { if (_argument != 0 && _argument->default_complex != 0) { - gchar * str = extcap_get_complex_as_string(_argument->default_complex); - if (str != 0) - return QString(str); + char * str = extcap_get_complex_as_string(_argument->default_complex); + if (str != nullptr) + return gchar_free_to_qstring(str); } return QString(); } @@ -946,7 +953,7 @@ bool ExtcapArgument::isRequired() if (_argument != NULL) return _argument->is_required; - return FALSE; + return false; } bool ExtcapArgument::reload() @@ -962,7 +969,7 @@ bool ExtcapArgument::fileExists() if (_argument != NULL) return _argument->fileexists; - return FALSE; + return false; } bool ExtcapArgument::isDefault() @@ -1027,7 +1034,7 @@ void ExtcapArgument::onBoolChanged(bool) bool ExtcapArgument::isSetDefaultValueSupported() { - return FALSE; + return false; } void ExtcapArgument::setDefaultValue() diff --git a/ui/qt/extcap_argument.h b/ui/qt/extcap_argument.h index 2efa4e42..d9e852d7 100644 --- a/ui/qt/extcap_argument.h +++ b/ui/qt/extcap_argument.h @@ -211,6 +211,7 @@ class ExtArgRadio : public ExtcapArgument public: ExtArgRadio(extcap_arg * argument, QObject *parent = Q_NULLPTR); + virtual ~ExtArgRadio(); virtual QWidget * createEditor(QWidget * parent); virtual QString value(); diff --git a/ui/qt/extcap_argument_multiselect.cpp b/ui/qt/extcap_argument_multiselect.cpp index 6f816b98..4eb2e4d5 100644 --- a/ui/qt/extcap_argument_multiselect.cpp +++ b/ui/qt/extcap_argument_multiselect.cpp @@ -212,7 +212,7 @@ QString ExtArgMultiSelect::defaultValue() bool ExtArgMultiSelect::isSetDefaultValueSupported() { - return TRUE; + return true; } void ExtArgMultiSelect::setDefaultValue() diff --git a/ui/qt/extcap_options_dialog.cpp b/ui/qt/extcap_options_dialog.cpp index 52c360c0..014a949a 100644 --- a/ui/qt/extcap_options_dialog.cpp +++ b/ui/qt/extcap_options_dialog.cpp @@ -9,8 +9,6 @@ #include -#include - #include #include @@ -59,8 +57,7 @@ ExtcapOptionsDialog::ExtcapOptionsDialog(bool startCaptureOnClose, QWidget *pare ui(new Ui::ExtcapOptionsDialog), device_name(""), device_idx(0), - defaultValueIcon_(StockIcon("x-reset")), - start_capture_on_close_(startCaptureOnClose) + defaultValueIcon_(StockIcon("x-reset")) { ui->setupUi(this); @@ -68,10 +65,11 @@ ExtcapOptionsDialog::ExtcapOptionsDialog(bool startCaptureOnClose, QWidget *pare ui->checkSaveOnStart->setCheckState(prefs.extcap_save_on_start ? Qt::Checked : Qt::Unchecked); + ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Start")); if (startCaptureOnClose) { - ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Start")); - } else { - ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Save")); + // This dialog was spawned because the user wanted to start a capture + // immediately but a mandatory parameter was not configured. + ui->buttonBox->button(QDialogButtonBox::Save)->hide(); } } @@ -80,7 +78,7 @@ ExtcapOptionsDialog * ExtcapOptionsDialog::createForDevice(QString &dev_name, bo interface_t *device; ExtcapOptionsDialog * resultDialog = NULL; bool dev_found = false; - guint if_idx; + unsigned if_idx; if (dev_name.length() == 0) return NULL; @@ -118,26 +116,6 @@ ExtcapOptionsDialog::~ExtcapOptionsDialog() delete ui; } -void ExtcapOptionsDialog::on_buttonBox_accepted() -{ - if (saveOptionToCaptureInfo()) { - /* Starting a new capture with those values */ - prefs.extcap_save_on_start = ui->checkSaveOnStart->checkState() == Qt::Checked; - - /* If the button says "Save" instead of "Start", unconditionally - * save. XXX - Why not have both buttons? (#19199) - * - * XXX - If extcap_save_on_start is the only preference that has - * changed, or if it changed from true to false, we should write - * out a new preference file with its new value, but don't. - */ - if (prefs.extcap_save_on_start || !start_capture_on_close_) - storeValues(); - - accept(); - } -} - void ExtcapOptionsDialog::anyValueChanged() { bool allowStart = true; @@ -241,7 +219,7 @@ void ExtcapOptionsDialog::loadArguments() extcapArguments << optional; /* argument items are now owned by ExtcapArgument. Only free the lists */ - extcap_free_if_configuration(arguments, FALSE); + extcap_free_if_configuration(arguments, false); } void ExtcapOptionsDialog::updateWidgets() @@ -403,12 +381,6 @@ void ExtcapOptionsDialog::updateWidgets() } } -// Not sure why we have to do this manually. -void ExtcapOptionsDialog::on_buttonBox_rejected() -{ - reject(); -} - void ExtcapOptionsDialog::on_buttonBox_helpRequested() { interface_t *device; @@ -474,8 +446,8 @@ bool ExtcapOptionsDialog::saveOptionToCaptureInfo() continue; } - gchar * call_string = qstring_strdup(call); - gchar * value_string = NULL; + char * call_string = qstring_strdup(call); + char * value_string = NULL; if (value.length() > 0) value_string = qstring_strdup(value); @@ -491,8 +463,41 @@ bool ExtcapOptionsDialog::saveOptionToCaptureInfo() void ExtcapOptionsDialog::on_buttonBox_clicked(QAbstractButton *button) { /* Only the save button has the ActionRole */ - if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole) + switch (ui->buttonBox->buttonRole(button)) { + case QDialogButtonBox::ResetRole: resetValues(); + break; + case QDialogButtonBox::RejectRole: + case QDialogButtonBox::DestructiveRole: + /* entries are only saved if saveOptionToCaptureInfo() is called, + * so do nothing. */ + reject(); + break; + case QDialogButtonBox::AcceptRole: + if (saveOptionToCaptureInfo()) { + /* Starting a new capture with those values */ + prefs.extcap_save_on_start = ui->checkSaveOnStart->checkState() == Qt::Checked; + + /* XXX - If extcap_save_on_start is the only preference that has + * changed, or if it changed from true to false, we should write + * out a new preference file with its new value, but don't. + */ + if (ui->buttonBox->standardButton(button) == QDialogButtonBox::Save) { + storeValues(); + /* Reject the dialog, because we don't want to start a capture. */ + reject(); + } else { + /* Start */ + if (prefs.extcap_save_on_start) { + storeValues(); + } + accept(); + } + } + break; + default: + break; + } } void ExtcapOptionsDialog::resetValues() @@ -549,14 +554,14 @@ void ExtcapOptionsDialog::resetValues() } - /* Values are stored when dialog is commited, just check validity*/ + /* Values are stored when dialog is committed, just check validity */ anyValueChanged(); } } GHashTable *ExtcapOptionsDialog::getArgumentSettings(bool useCallsAsKey, bool includeEmptyValues) { - GHashTable * entries = g_hash_table_new(g_str_hash, g_str_equal); + GHashTable * entries = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); ExtcapArgumentList::const_iterator iter; QString value; @@ -615,7 +620,7 @@ GHashTable *ExtcapOptionsDialog::getArgumentSettings(bool useCallsAsKey, bool in if ((key.length() > 0) && (includeEmptyValues || isBoolflag || value.length() > 0) ) { - gchar * val = qstring_strdup(value); + char * val = qstring_strdup(value); g_hash_table_insert(entries, qstring_strdup(key), val); } @@ -634,6 +639,8 @@ void ExtcapOptionsDialog::storeValues() mainApp->emitAppSignal(MainApplication::PreferencesChanged); } + + g_hash_table_unref(entries); } ExtcapValueList ExtcapOptionsDialog::loadValuesFor(int argNum, QString argumentName, QString parent) @@ -673,7 +680,7 @@ ExtcapValueList ExtcapOptionsDialog::loadValuesFor(int argNum, QString argumentN QString call = QString().fromUtf8(v->call); ExtcapValue element = ExtcapValue(display, call, - v->enabled == (gboolean)TRUE, v->is_default == (gboolean)TRUE); + v->enabled == true, v->is_default == true); #if 0 /* TODO: Disabled due to wrong parent handling. It leads to an infinite loop for now. To implement this properly, other things diff --git a/ui/qt/extcap_options_dialog.h b/ui/qt/extcap_options_dialog.h index bb1d8e89..ddf82165 100644 --- a/ui/qt/extcap_options_dialog.h +++ b/ui/qt/extcap_options_dialog.h @@ -40,8 +40,6 @@ public: ExtcapValueList loadValuesFor(int argNum, QString call, QString parent = ""); private Q_SLOTS: - void on_buttonBox_accepted(); - void on_buttonBox_rejected(); void on_buttonBox_clicked(QAbstractButton *button); void on_buttonBox_helpRequested(); void updateWidgets(); @@ -52,9 +50,8 @@ private: Ui::ExtcapOptionsDialog *ui; QString device_name; - guint device_idx; + unsigned device_idx; QIcon defaultValueIcon_; - bool start_capture_on_close_; ExtcapArgumentList extcapArguments; diff --git a/ui/qt/extcap_options_dialog.ui b/ui/qt/extcap_options_dialog.ui index 337a0c9d..1c6f0d7b 100644 --- a/ui/qt/extcap_options_dialog.ui +++ b/ui/qt/extcap_options_dialog.ui @@ -40,7 +40,7 @@ - QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults + QDialogButtonBox::Discard|QDialogButtonBox::Help|QDialogButtonBox::Ok|QDialogButtonBox::Save|QDialogButtonBox::RestoreDefaults diff --git a/ui/qt/file_set_dialog.cpp b/ui/qt/file_set_dialog.cpp index 70f38914..0cb2d232 100644 --- a/ui/qt/file_set_dialog.cpp +++ b/ui/qt/file_set_dialog.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include "file.h" #include "fileset.h" diff --git a/ui/qt/file_set_dialog.h b/ui/qt/file_set_dialog.h index d4158898..defdeda6 100644 --- a/ui/qt/file_set_dialog.h +++ b/ui/qt/file_set_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include "file.h" #include "fileset.h" diff --git a/ui/qt/filter_action.cpp b/ui/qt/filter_action.cpp index f8b7732f..3a54cf67 100644 --- a/ui/qt/filter_action.cpp +++ b/ui/qt/filter_action.cpp @@ -66,25 +66,18 @@ const QString FilterAction::actionName(Action action) { switch (action) { case ActionApply: return QObject::tr("Apply as Filter"); - break; case ActionPrepare: return QObject::tr("Prepare as Filter"); - break; case ActionFind: return QObject::tr("Find"); - break; case ActionColorize: return QObject::tr("Colorize"); - break; case ActionWebLookup: return QObject::tr("Look Up"); - break; case ActionCopy: return QObject::tr("Copy"); - break; default: return QObject::tr("UNKNOWN"); - break; } } @@ -118,25 +111,18 @@ const QString FilterAction::actionTypeName(ActionType type) { switch (type) { case ActionTypePlain: return QObject::tr("Selected"); - break; case ActionTypeNot: return QObject::tr("Not Selected"); - break; case ActionTypeAnd: return QObject::tr("…and Selected"); - break; case ActionTypeOr: return QObject::tr("…or Selected"); - break; case ActionTypeAndNot: return QObject::tr("…and not Selected"); - break; case ActionTypeOrNot: return QObject::tr("…or not Selected"); - break; default: return QObject::tr("UNKNOWN"); - break; } } @@ -160,34 +146,24 @@ const QString FilterAction::actionDirectionName(ActionDirection direction) { switch (direction) { case ActionDirectionAToFromB: return QObject::tr("A " UTF8_LEFT_RIGHT_ARROW " B"); - break; case ActionDirectionAToB: return QObject::tr("A " UTF8_RIGHTWARDS_ARROW " B"); - break; case ActionDirectionAFromB: return QObject::tr("B " UTF8_RIGHTWARDS_ARROW " A"); - break; case ActionDirectionAToFromAny: return QObject::tr("A " UTF8_LEFT_RIGHT_ARROW " Any"); - break; case ActionDirectionAToAny: return QObject::tr("A " UTF8_RIGHTWARDS_ARROW " Any"); - break; case ActionDirectionAFromAny: return QObject::tr("Any " UTF8_RIGHTWARDS_ARROW " A"); - break; case ActionDirectionAnyToFromB: return QObject::tr("Any " UTF8_LEFT_RIGHT_ARROW " B"); - break; case ActionDirectionAnyToB: return QObject::tr("Any " UTF8_RIGHTWARDS_ARROW " B"); - break; case ActionDirectionAnyFromB: return QObject::tr("B " UTF8_RIGHTWARDS_ARROW " Any"); - break; default: return QObject::tr("UNKNOWN"); - break; } } diff --git a/ui/qt/filter_dialog.cpp b/ui/qt/filter_dialog.cpp index 1ed86b87..e1617611 100644 --- a/ui/qt/filter_dialog.cpp +++ b/ui/qt/filter_dialog.cpp @@ -9,8 +9,6 @@ #include -#include - #include #include @@ -59,18 +57,29 @@ FilterDialog::FilterDialog(QWidget *parent, FilterType filter_type, QString new_ ui->filterTreeView->setAcceptDrops(true); ui->filterTreeView->setDropIndicatorShown(true); - const gchar * filename = NULL; + const char * filename = NULL; QString newFilterText; - if (filter_type == CaptureFilter) { - setWindowTitle(mainApp->windowTitleString(tr("Capture Filters"))); - filename = CFILTER_FILE_NAME; - newFilterText = tr("New capture filter"); - model_ = new FilterListModel(FilterListModel::Capture, this); - } else { - setWindowTitle(mainApp->windowTitleString(tr("Display Filters"))); - filename = DFILTER_FILE_NAME; - newFilterText = tr("New display filter"); - model_ = new FilterListModel(FilterListModel::Display, this); + switch (filter_type) { + case CaptureFilter: + setWindowTitle(mainApp->windowTitleString(tr("Capture Filters"))); + filename = CFILTER_FILE_NAME; + newFilterText = tr("New capture filter"); + model_ = new FilterListModel(FilterListModel::Capture, this); + break; + case DisplayFilter: + setWindowTitle(mainApp->windowTitleString(tr("Display Filters"))); + filename = DFILTER_FILE_NAME; + newFilterText = tr("New display filter"); + model_ = new FilterListModel(FilterListModel::Display, this); + break; + case DisplayMacro: + setWindowTitle(mainApp->windowTitleString(tr("Display Filter Macros"))); + filename = DMACROS_FILE_NAME; + newFilterText = tr("New macro"); + model_ = new FilterListModel(FilterListModel::DisplayMacro, this); + break; + default: + ws_assert_not_reached(); } if (new_filter_.length() > 0) @@ -84,7 +93,7 @@ FilterDialog::FilterDialog(QWidget *parent, FilterType filter_type, QString new_ connect(ui->filterTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &FilterDialog::selectionChanged); - QString abs_path = gchar_free_to_qstring(get_persconffile_path(filename, TRUE)); + QString abs_path = gchar_free_to_qstring(get_persconffile_path(filename, true)); if (file_exists(abs_path.toUtf8().constData())) { ui->pathLabel->setText(abs_path); ui->pathLabel->setUrl(QUrl::fromLocalFile(abs_path).toString()); @@ -129,14 +138,24 @@ void FilterDialog::on_newToolButton_clicked() QString name; QString filter; - if (filter_type_ == CaptureFilter) { - //: This text is automatically filled in when a new filter is created - name = tr("New capture filter"); - filter = "ip host host.example.com"; - } else { - //: This text is automatically filled in when a new filter is created - name = tr("New display filter"); - filter = "ip.host == host.example.com"; + switch (filter_type_) { + case CaptureFilter: + //: This text is automatically filled in when a new filter is created + name = tr("New capture filter"); + filter = "ip host host.example.com"; + break; + case DisplayFilter: + //: This text is automatically filled in when a new filter is created + name = tr("New display filter"); + filter = "ip.host == host.example.com"; + break; + case DisplayMacro: + //: This text is automatically filled in when a new filter is created + name = "eq_example_com"; + filter = "$1 == host.example.com"; + break; + default: + ws_assert_not_reached(); } addFilter(name, filter, true); @@ -172,19 +191,43 @@ void FilterDialog::on_buttonBox_accepted() { model_->saveList(); - if (filter_type_ == CaptureFilter) { - mainApp->emitAppSignal(MainApplication::CaptureFilterListChanged); - } else { - mainApp->emitAppSignal(MainApplication::DisplayFilterListChanged); + switch (filter_type_) { + case CaptureFilter: + mainApp->emitAppSignal(MainApplication::CaptureFilterListChanged); + break; + case DisplayFilter: + mainApp->emitAppSignal(MainApplication::DisplayFilterListChanged); + break; + case DisplayMacro: + mainApp->reloadDisplayFilterMacros(); + // The function above emits MainApplication::FieldsChanged, which + // takes care of invalidating the current display filter text if + // it no longer compiles. + // XXX - What if the current display filter means something + // different now? Should we force a refilter (not redissection, + // the dissection shouldn't have changed) with the current display + // filter, or wait for the user to refilter? + // The UAT based display macro system did not refilter. + break; + default: + ws_assert_not_reached(); } } void FilterDialog::on_buttonBox_helpRequested() { - if (filter_type_ == CaptureFilter) { - mainApp->helpTopicAction(HELP_CAPTURE_FILTERS_DIALOG); - } else { - mainApp->helpTopicAction(HELP_DISPLAY_FILTERS_DIALOG); + switch (filter_type_) { + case CaptureFilter: + mainApp->helpTopicAction(HELP_CAPTURE_FILTERS_DIALOG); + break; + case DisplayFilter: + mainApp->helpTopicAction(HELP_DISPLAY_FILTERS_DIALOG); + break; + case DisplayMacro: + mainApp->helpTopicAction(HELP_DISPLAY_MACRO_DIALOG); + break; + default: + ws_assert_not_reached(); } } @@ -204,17 +247,26 @@ QWidget *FilterTreeDelegate::createEditor(QWidget *parent, const QStyleOptionVie if (index.column() != FilterListModel::ColumnExpression) { w = QStyledItemDelegate::createEditor(parent, option, index); } - else - { - if (filter_type_ == FilterDialog::CaptureFilter) { - w = new CaptureFilterEdit(parent, true); - } else { - w = new DisplayFilterEdit(parent, DisplayFilterToEnter); - } + else if (filter_type_ == FilterDialog::CaptureFilter) { + w = new CaptureFilterEdit(parent, true); + } + else if (filter_type_ == FilterDialog::DisplayFilter) { + w = new DisplayFilterEdit(parent, DisplayFilterToEnter); + } + else { + w = QStyledItemDelegate::createEditor(parent, option, index); } - if (qobject_cast(w) && index.column() == FilterListModel::ColumnName) - qobject_cast(w)->setValidator(new FilterValidator()); + if (qobject_cast(w)) { + if (index.column() == FilterListModel::ColumnName) { + if (filter_type_ == FilterDialog::DisplayMacro) { + qobject_cast(w)->setValidator(new MacroNameValidator()); + } + else { + qobject_cast(w)->setValidator(new FilterValidator()); + } + } + } return w; } @@ -244,3 +296,17 @@ QValidator::State FilterValidator::validate(QString & input, int & /*pos*/) cons return QValidator::Acceptable; } + +QValidator::State MacroNameValidator::validate(QString &input, int & /*pos*/) const +{ + if (input.length() <= 0) + return QValidator::Intermediate; + + for (QChar ch: input) { + if (!ch.isLetterOrNumber() && ch != '_') { + return QValidator::Invalid; + } + } + + return QValidator::Acceptable; +} diff --git a/ui/qt/filter_dialog.h b/ui/qt/filter_dialog.h index 34b3a156..90d2f1b2 100644 --- a/ui/qt/filter_dialog.h +++ b/ui/qt/filter_dialog.h @@ -29,7 +29,7 @@ class FilterDialog : public GeometryStateDialog Q_OBJECT public: - enum FilterType { CaptureFilter, DisplayFilter }; + enum FilterType { CaptureFilter, DisplayFilter, DisplayMacro }; explicit FilterDialog(QWidget *parent = 0, FilterType filter_type = CaptureFilter, const QString new_filter = QString()); ~FilterDialog(); @@ -81,4 +81,10 @@ public: virtual QValidator::State validate(QString & input, int & pos) const override; }; +class MacroNameValidator : public QValidator +{ +public: + virtual QValidator::State validate(QString & input, int & pos) const override; +}; + #endif // FILTER_DIALOG_H diff --git a/ui/qt/filter_expression_frame.cpp b/ui/qt/filter_expression_frame.cpp index 38975977..dd40b3fa 100644 --- a/ui/qt/filter_expression_frame.cpp +++ b/ui/qt/filter_expression_frame.cpp @@ -144,7 +144,7 @@ void FilterExpressionFrame::on_buttonBox_accepted() } else { - filter_expression_new(label_ba.constData(), expr_ba.constData(), comment_ba.constData(), TRUE); + filter_expression_new(label_ba.constData(), expr_ba.constData(), comment_ba.constData(), true); } save_migrated_uat("Display expressions", &prefs.filter_expressions_old); diff --git a/ui/qt/firewall_rules_dialog.cpp b/ui/qt/firewall_rules_dialog.cpp index a74355e1..e36e4235 100644 --- a/ui/qt/firewall_rules_dialog.cpp +++ b/ui/qt/firewall_rules_dialog.cpp @@ -127,15 +127,15 @@ void FirewallRulesDialog::updateWidgets() } #define ADDR_BUF_LEN 200 -void FirewallRulesDialog::addRule(QString description, syntax_func rule_func, address *addr, guint32 port) +void FirewallRulesDialog::addRule(QString description, syntax_func rule_func, address *addr, uint32_t port) { if (!rule_func) return; char addr_buf[ADDR_BUF_LEN]; QString comment_pfx = firewall_product_comment_prefix(prod_); GString *rule_str = g_string_new(""); - gboolean inbound = ui->inboundCheckBox->isChecked(); - gboolean deny = ui->denyCheckBox->isChecked(); + bool inbound = ui->inboundCheckBox->isChecked(); + bool deny = ui->denyCheckBox->isChecked(); address_to_str_buf(addr, addr_buf, ADDR_BUF_LEN); rule_func(rule_str, addr_buf, port, ptype_, inbound, deny); diff --git a/ui/qt/firewall_rules_dialog.h b/ui/qt/firewall_rules_dialog.h index e14456f4..9d298048 100644 --- a/ui/qt/firewall_rules_dialog.h +++ b/ui/qt/firewall_rules_dialog.h @@ -20,7 +20,7 @@ class FirewallRulesDialog; class QAbstractButton; -typedef void (*syntax_func)(GString *rtxt, gchar *addr, guint32 port, port_type ptype, gboolean inbound, gboolean deny); +typedef void (*syntax_func)(GString *rtxt, char *addr, uint32_t port, port_type ptype, bool inbound, bool deny); class FirewallRulesDialog : public WiresharkDialog { @@ -50,11 +50,11 @@ private: address net_src_; address net_dst_; port_type ptype_; - guint32 src_port_; - guint32 dst_port_; + uint32_t src_port_; + uint32_t dst_port_; void updateWidgets(); - void addRule(QString description, syntax_func rule_func, address *addr, guint32 port); + void addRule(QString description, syntax_func rule_func, address *addr, uint32_t port); }; #endif // FIREWALL_RULES_DIALOG_H diff --git a/ui/qt/follow_stream_action.cpp b/ui/qt/follow_stream_action.cpp index c9a946a1..0be2d561 100644 --- a/ui/qt/follow_stream_action.cpp +++ b/ui/qt/follow_stream_action.cpp @@ -9,7 +9,6 @@ #include -#include #include #include #include diff --git a/ui/qt/follow_stream_action.h b/ui/qt/follow_stream_action.h index 8c7c58e3..5357bae4 100644 --- a/ui/qt/follow_stream_action.h +++ b/ui/qt/follow_stream_action.h @@ -12,7 +12,6 @@ #include "config.h" -#include #include #include diff --git a/ui/qt/follow_stream_dialog.cpp b/ui/qt/follow_stream_dialog.cpp index dbae1604..532d37f5 100644 --- a/ui/qt/follow_stream_dialog.cpp +++ b/ui/qt/follow_stream_dialog.cpp @@ -29,6 +29,7 @@ #include "wsutil/file_util.h" #include "wsutil/str_util.h" +#include "wsutil/filesystem.h" #include "ws_symbol_export.h" @@ -53,8 +54,6 @@ // - Instead of calling QMessageBox, display the error message in the text // box and disable the appropriate controls. // - Add a progress bar and connect captureCaptureUpdateContinue to it -// - User's Guide documents the "Raw" type as "same as ASCII, but saving binary -// data". However it currently displays hex-encoded data. // Matches SplashOverlay. static int info_update_freq_ = 100; @@ -63,7 +62,7 @@ static int info_update_freq_ = 100; static QMutex loop_break_mutex; // Indicates that a Follow Stream is currently running -static gboolean isReadRunning; +static bool isReadRunning; Q_DECLARE_METATYPE(bytes_show_type) @@ -72,7 +71,6 @@ FollowStreamDialog::FollowStreamDialog(QWidget &parent, CaptureFile &cf, int pro ui(new Ui::FollowStreamDialog), b_find_(NULL), follower_(NULL), - truncated_(false), client_buffer_count_(0), server_buffer_count_(0), client_packet_count_(0), @@ -101,6 +99,8 @@ FollowStreamDialog::FollowStreamDialog(QWidget &parent, CaptureFile &cf, int pro follow_info_.show_stream = BOTH_HOSTS; follow_info_.substream_id = SUBSTREAM_UNUSED; + nstime_set_zero(&last_ts_); + ui->teStreamContent->installEventFilter(this); connect(ui->leFind, SIGNAL(useRegexFind(bool)), this, SLOT(useRegexFind(bool))); @@ -118,27 +118,46 @@ FollowStreamDialog::FollowStreamDialog(QWidget &parent, CaptureFile &cf, int pro cbcs->setCurrentIndex(cbcs->findData(recent.gui_follow_show)); cbcs->blockSignals(false); + ui->deltaComboBox->setCurrentIndex(recent.gui_follow_delta); + b_filter_out_ = ui->buttonBox->addButton(tr("Filter Out This Stream"), QDialogButtonBox::ActionRole); - connect(b_filter_out_, SIGNAL(clicked()), this, SLOT(filterOut())); + connect(b_filter_out_, &QPushButton::clicked, this, &FollowStreamDialog::filterOut); b_print_ = ui->buttonBox->addButton(tr("Print"), QDialogButtonBox::ActionRole); - connect(b_print_, SIGNAL(clicked()), this, SLOT(printStream())); + connect(b_print_, &QPushButton::clicked, this, &FollowStreamDialog::printStream); b_save_ = ui->buttonBox->addButton(tr("Save as…"), QDialogButtonBox::ActionRole); - connect(b_save_, SIGNAL(clicked()), this, SLOT(saveAs())); + connect(b_save_, &QPushButton::clicked, this, &FollowStreamDialog::saveAs); b_back_ = ui->buttonBox->addButton(tr("Back"), QDialogButtonBox::ActionRole); - connect(b_back_, SIGNAL(clicked()), this, SLOT(backButton())); + connect(b_back_, &QPushButton::clicked, this, &FollowStreamDialog::backButton); ProgressFrame::addToButtonBox(ui->buttonBox, &parent); - connect(ui->buttonBox, SIGNAL(helpRequested()), this, SLOT(helpButton())); - connect(ui->teStreamContent, SIGNAL(mouseMovedToTextCursorPosition(int)), - this, SLOT(fillHintLabel(int))); - connect(ui->teStreamContent, SIGNAL(mouseClickedOnTextCursorPosition(int)), - this, SLOT(goToPacketForTextPos(int))); + connect(ui->cbDirections, static_cast(&QComboBox::currentIndexChanged), + this, &FollowStreamDialog::cbDirectionsCurrentIndexChanged); + connect(ui->cbCharset, static_cast(&QComboBox::currentIndexChanged), + this, &FollowStreamDialog::cbCharsetCurrentIndexChanged); + connect(ui->deltaComboBox, static_cast(&QComboBox::currentIndexChanged), + this, &FollowStreamDialog::deltaComboBoxCurrentIndexChanged); + + connect(ui->streamNumberSpinBox, static_cast(&QSpinBox::valueChanged), + this, &FollowStreamDialog::streamNumberSpinBoxValueChanged); + connect(ui->subStreamNumberSpinBox, static_cast(&QSpinBox::valueChanged), + this, &FollowStreamDialog::subStreamNumberSpinBoxValueChanged); + + connect(ui->buttonBox, &QDialogButtonBox::helpRequested, this, &FollowStreamDialog::helpButton); + connect(ui->teStreamContent, &FollowStreamText::mouseMovedToPacket, + this, &FollowStreamDialog::fillHintLabel); + connect(ui->teStreamContent, &FollowStreamText::mouseClickedOnPacket, + this, &FollowStreamDialog::goToPacketForTextPos); + + connect(ui->bFind, &QPushButton::clicked, this, &FollowStreamDialog::bFindClicked); + connect(ui->leFind, &FindLineEdit::returnPressed, this, &FollowStreamDialog::leFindReturnPressed); + + connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &FollowStreamDialog::buttonBoxRejected); - fillHintLabel(-1); + fillHintLabel(); } FollowStreamDialog::~FollowStreamDialog() @@ -169,29 +188,37 @@ void FollowStreamDialog::printStream() #endif } -void FollowStreamDialog::fillHintLabel(int text_pos) +void FollowStreamDialog::fillHintLabel(int pkt) { QString hint; - int pkt = -1; - if (text_pos >= 0) { - QMap::iterator it = text_pos_to_packet_.upperBound(text_pos); - if (it != text_pos_to_packet_.end()) { - pkt = it.value(); + bool is_logray = strcmp(get_configuration_namespace(), "Logray") == 0; + + if (is_logray) { + if (pkt > 0) { + hint = QString(tr("Event %1. ")).arg(pkt); } - } - if (pkt > 0) { - hint = QString(tr("Packet %1. ")).arg(pkt); - } + hint += tr("%Ln reads, ", "", client_packet_count_) + .arg(ColorUtils::fromColorT(prefs.st_client_fg).name(), + ColorUtils::fromColorT(prefs.st_client_bg).name()) + + tr("%Ln writes, ", "", server_packet_count_) + .arg(ColorUtils::fromColorT(prefs.st_server_fg).name(), + ColorUtils::fromColorT(prefs.st_server_bg).name()) + + tr("%Ln turn(s).", "", turns_); + } else { + if (pkt > 0) { + hint = QString(tr("Packet %1. ")).arg(pkt); + } - hint += tr("%Ln client pkt(s), ", "", client_packet_count_) - .arg(ColorUtils::fromColorT(prefs.st_client_fg).name()) - .arg(ColorUtils::fromColorT(prefs.st_client_bg).name()) - + tr("%Ln server pkt(s), ", "", server_packet_count_) - .arg(ColorUtils::fromColorT(prefs.st_server_fg).name()) - .arg(ColorUtils::fromColorT(prefs.st_server_bg).name()) - + tr("%Ln turn(s).", "", turns_); + hint += tr("%Ln client pkt(s), ", "", client_packet_count_) + .arg(ColorUtils::fromColorT(prefs.st_client_fg).name(), + ColorUtils::fromColorT(prefs.st_client_bg).name()) + + tr("%Ln server pkt(s), ", "", server_packet_count_) + .arg(ColorUtils::fromColorT(prefs.st_server_fg).name(), + ColorUtils::fromColorT(prefs.st_server_bg).name()) + + tr("%Ln turn(s).", "", turns_); + } if (pkt > 0) { hint.append(QString(tr(" Click to select."))); @@ -202,20 +229,12 @@ void FollowStreamDialog::fillHintLabel(int text_pos) ui->hintLabel->setText(hint); } -void FollowStreamDialog::goToPacketForTextPos(int text_pos) +void FollowStreamDialog::goToPacketForTextPos(int pkt) { - int pkt = -1; if (file_closed_) { return; } - if (text_pos >= 0) { - QMap::iterator it = text_pos_to_packet_.upperBound(text_pos); - if (it != text_pos_to_packet_.end()) { - pkt = it.value(); - } - } - if (pkt > 0) { emit goToPacket(pkt); } @@ -255,20 +274,40 @@ void FollowStreamDialog::useRegexFind(bool use_regex) ui->lFind->setText(tr("Find:")); } +// This only calls itself with go_back false, so never recurses more than once. +// NOLINTNEXTLINE(misc-no-recursion) void FollowStreamDialog::findText(bool go_back) { if (ui->leFind->text().isEmpty()) return; bool found; + + QTextDocument::FindFlags options; + if (ui->caseCheckBox->isChecked()) { + options |= QTextDocument::FindCaseSensitively; + } if (use_regex_find_) { #if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)) + // https://bugreports.qt.io/browse/QTBUG-88721 + // QPlainTextEdit::find() searches case-insensitively unless + // QTextDocument::FindCaseSensitively is explicitly given. + // This *does* apply to QRegularExpression (overriding + // CaseInsensitiveOption), but not QRegExp. + // + // QRegularExpression and QRegExp do not support Perl's /i, but + // the former at least does support the mode modifiers (?i) and + // (?-i), which can override QTextDocument::FindCaseSensitively. + // + // To make matters worse, while the QTextDocument::find() documentation + // is correct, QPlainTextEdit::find() claims that QRegularExpression + // works like QRegExp, which is incorrect. QRegularExpression regex(ui->leFind->text(), QRegularExpression::UseUnicodePropertiesOption); #else - QRegExp regex(ui->leFind->text()); + QRegExp regex(ui->leFind->text(), (options & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive); #endif - found = ui->teStreamContent->find(regex); + found = ui->teStreamContent->find(regex, options); } else { - found = ui->teStreamContent->find(ui->leFind->text()); + found = ui->teStreamContent->find(ui->leFind->text(), options); } if (found) { @@ -288,15 +327,17 @@ void FollowStreamDialog::saveAs() QFile file(file_name); if (!file.open(QIODevice::WriteOnly)) { - open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE); + open_failure_alert_box(file_name.toUtf8().constData(), errno, true); return; } + // XXX: What if truncated_ is true? We should save the entire stream. // Unconditionally save data as UTF-8 (even if data is decoded otherwise). QByteArray bytes = ui->teStreamContent->toPlainText().toUtf8(); if (recent.gui_follow_show == SHOW_RAW) { // The "Raw" format is currently displayed as hex data and needs to be - // converted to binary data. + // converted to binary data. fromHex() skips over non hex characters + // including line breaks, which is what we want. bytes = QByteArray::fromHex(bytes); } @@ -337,12 +378,12 @@ void FollowStreamDialog::close() // previous_filter if 'Close' (passed in follow() method) // filter_out_filter_ if 'Filter Out This Stream' (built by appending !current_stream to previous_filter) // leave filter alone if window closed. (current stream) - emit updateFilter(output_filter_, TRUE); + emit updateFilter(output_filter_, true); WiresharkDialog::close(); } -void FollowStreamDialog::on_cbDirections_currentIndexChanged(int idx) +void FollowStreamDialog::cbDirectionsCurrentIndexChanged(int idx) { switch(idx) { @@ -362,24 +403,43 @@ void FollowStreamDialog::on_cbDirections_currentIndexChanged(int idx) readStream(); } -void FollowStreamDialog::on_cbCharset_currentIndexChanged(int idx) +void FollowStreamDialog::cbCharsetCurrentIndexChanged(int idx) { if (idx < 0) return; recent.gui_follow_show = ui->cbCharset->currentData().value(); + + switch (recent.gui_follow_show) { + case SHOW_EBCDIC: + case SHOW_ASCII: + case SHOW_CODEC: + ui->deltaComboBox->setEnabled(true); + break; + default: + ui->deltaComboBox->setEnabled(false); + } + + readStream(); +} + +void FollowStreamDialog::deltaComboBoxCurrentIndexChanged(int idx) +{ + if (idx < 0) return; + recent.gui_follow_delta = static_cast(ui->deltaComboBox->currentIndex()); + readStream(); } -void FollowStreamDialog::on_bFind_clicked() +void FollowStreamDialog::bFindClicked() { findText(); } -void FollowStreamDialog::on_leFind_returnPressed() +void FollowStreamDialog::leFindReturnPressed() { findText(); } -void FollowStreamDialog::on_streamNumberSpinBox_valueChanged(int stream_num) +void FollowStreamDialog::streamNumberSpinBoxValueChanged(int stream_num) { if (file_closed_) return; @@ -388,7 +448,7 @@ void FollowStreamDialog::on_streamNumberSpinBox_valueChanged(int stream_num) sub_stream_num = ui->subStreamNumberSpinBox->value(); ui->subStreamNumberSpinBox->blockSignals(false); - gboolean ok; + bool ok; if (ui->subStreamNumberSpinBox->isVisible()) { /* We need to find a suitable sub stream for the new stream */ follow_sub_stream_id_func sub_stream_func; @@ -399,7 +459,7 @@ void FollowStreamDialog::on_streamNumberSpinBox_valueChanged(int stream_num) return; } - guint sub_stream_num_new = static_cast(sub_stream_num); + unsigned sub_stream_num_new = static_cast(sub_stream_num); if (sub_stream_num < 0) { // Stream ID 0 should always exist as it is used for control messages. // XXX: That is only guaranteed for HTTP2. For example, in QUIC, @@ -411,14 +471,14 @@ void FollowStreamDialog::on_streamNumberSpinBox_valueChanged(int stream_num) // follow? Right now the substream spinbox is left active and // the user can change the value to no effect. sub_stream_num_new = 0; - ok = TRUE; + ok = true; } else { - ok = sub_stream_func(static_cast(stream_num), sub_stream_num_new, FALSE, &sub_stream_num_new); + ok = sub_stream_func(static_cast(stream_num), sub_stream_num_new, false, &sub_stream_num_new); if (!ok) { - ok = sub_stream_func(static_cast(stream_num), sub_stream_num_new, TRUE, &sub_stream_num_new); + ok = sub_stream_func(static_cast(stream_num), sub_stream_num_new, true, &sub_stream_num_new); } } - sub_stream_num = static_cast(sub_stream_num_new); + sub_stream_num = static_cast(sub_stream_num_new); } else { /* XXX: For HTTP and TLS, we use the TCP stream index, and really should * return false if the TCP stream doesn't have HTTP or TLS. (Or we could @@ -434,7 +494,7 @@ void FollowStreamDialog::on_streamNumberSpinBox_valueChanged(int stream_num) } -void FollowStreamDialog::on_subStreamNumberSpinBox_valueChanged(int sub_stream_num) +void FollowStreamDialog::subStreamNumberSpinBoxValueChanged(int sub_stream_num) { if (file_closed_) return; @@ -451,20 +511,20 @@ void FollowStreamDialog::on_subStreamNumberSpinBox_valueChanged(int sub_stream_n return; } - guint sub_stream_num_new = static_cast(sub_stream_num); - gboolean ok; + unsigned sub_stream_num_new = static_cast(sub_stream_num); + bool ok; /* previous_sub_stream_num_ is a hack to track which buttons was pressed without event handling */ if (sub_stream_num < 0) { // Stream ID 0 should always exist as it is used for control messages. // XXX: That is only guaranteed for HTTP2, see above. sub_stream_num_new = 0; - ok = TRUE; + ok = true; } else if (previous_sub_stream_num_ < sub_stream_num) { - ok = sub_stream_func(static_cast(stream_num), sub_stream_num_new, FALSE, &sub_stream_num_new); + ok = sub_stream_func(static_cast(stream_num), sub_stream_num_new, false, &sub_stream_num_new); } else { - ok = sub_stream_func(static_cast(stream_num), sub_stream_num_new, TRUE, &sub_stream_num_new); + ok = sub_stream_func(static_cast(stream_num), sub_stream_num_new, true, &sub_stream_num_new); } - sub_stream_num = static_cast(sub_stream_num_new); + sub_stream_num = static_cast(sub_stream_num_new); if (ok) { follow(previous_filter_, true, stream_num, sub_stream_num); @@ -472,7 +532,7 @@ void FollowStreamDialog::on_subStreamNumberSpinBox_valueChanged(int sub_stream_n } } -void FollowStreamDialog::on_buttonBox_rejected() +void FollowStreamDialog::buttonBoxRejected() { // Ignore the close button if FollowStreamDialog::close() is running. if (terminating_) @@ -490,60 +550,34 @@ void FollowStreamDialog::removeStreamControls() ui->subStreamNumberSpinBox->setVisible(false); } -void FollowStreamDialog::resetStream() +void FollowStreamDialog::resetStream(void *tap_data) { - GList *cur; - follow_record_t *follow_record; - - filter_out_filter_.clear(); - text_pos_to_packet_.clear(); - if (!data_out_filename_.isEmpty()) { - ws_unlink(data_out_filename_.toUtf8().constData()); - } - for (cur = follow_info_.payload; cur; cur = gxx_list_next(cur)) { - follow_record = gxx_list_data(follow_record_t *, cur); - if (follow_record->data) { - g_byte_array_free(follow_record->data, TRUE); - } - g_free(follow_record); - } - g_list_free(follow_info_.payload); - - //Only TCP stream uses fragments - for (cur = follow_info_.fragments[0]; cur; cur = gxx_list_next(cur)) { - follow_record = gxx_list_data(follow_record_t *, cur); - if (follow_record->data) { - g_byte_array_free(follow_record->data, TRUE); - } - g_free(follow_record); - } - follow_info_.fragments[0] = Q_NULLPTR; - for (cur = follow_info_.fragments[1]; cur; cur = gxx_list_next(cur)) { - follow_record = gxx_list_data(follow_record_t *, cur); - if (follow_record->data) { - g_byte_array_free(follow_record->data, TRUE); - } - g_free(follow_record); - } - follow_info_.fragments[1] = Q_NULLPTR; + follow_info_t *follow_info = static_cast(tap_data); + follow_reset_stream(follow_info); + // If we ever draw the text while tapping (instead of only after + // the tap finishes), reset the GUI here too. +} - free_address(&follow_info_.client_ip); - free_address(&follow_info_.server_ip); - follow_info_.payload = Q_NULLPTR; - follow_info_.client_port = 0; +void FollowStreamDialog::resetStream() +{ + FollowStreamDialog::resetStream(&follow_info_); } -frs_return_t -FollowStreamDialog::readStream() +void FollowStreamDialog::readStream() { // interrupt any reading already running loop_break_mutex.lock(); - isReadRunning = FALSE; + isReadRunning = false; loop_break_mutex.unlock(); + double scroll_ratio = 0.0; + int doc_length = ui->teStreamContent->verticalScrollBar()->maximum() + ui->teStreamContent->verticalScrollBar()->pageStep(); + if (doc_length > 0) { + scroll_ratio = static_cast(ui->teStreamContent->verticalScrollBar()->value()) / doc_length; + } + ui->teStreamContent->clear(); - text_pos_to_packet_.clear(); switch (recent.gui_follow_show) { case SHOW_CARRAY: @@ -561,9 +595,6 @@ FollowStreamDialog::readStream() ui->teStreamContent->setWordWrapMode(QTextOption::WrapAnywhere); } - truncated_ = false; - frs_return_t ret; - client_buffer_count_ = 0; server_buffer_count_ = 0; client_packet_count_ = 0; @@ -571,16 +602,16 @@ FollowStreamDialog::readStream() last_packet_ = 0; turns_ = 0; - if (follower_) { - ret = readFollowStream(); - } else { - ret = (frs_return_t)0; + if (!follower_) { ws_assert_not_reached(); } + readFollowStream(); + ui->teStreamContent->moveCursor(QTextCursor::Start); - return ret; + doc_length = ui->teStreamContent->verticalScrollBar()->maximum() + ui->teStreamContent->verticalScrollBar()->pageStep(); + ui->teStreamContent->verticalScrollBar()->setValue(doc_length * scroll_ratio); } void @@ -589,49 +620,9 @@ FollowStreamDialog::followStream() readStream(); } -const int FollowStreamDialog::max_document_length_ = 500 * 1000 * 1000; // Just a guess -void FollowStreamDialog::addText(QString text, gboolean is_from_server, guint32 packet_num, gboolean colorize) +void FollowStreamDialog::addText(QString text, bool is_from_server, uint32_t packet_num, bool colorize) { - if (truncated_) { - return; - } - - int char_count = ui->teStreamContent->document()->characterCount(); - if (char_count + text.length() > max_document_length_) { - text.truncate(max_document_length_ - char_count); - truncated_ = true; - } - - setUpdatesEnabled(false); - int cur_pos = ui->teStreamContent->verticalScrollBar()->value(); - ui->teStreamContent->moveCursor(QTextCursor::End); - - QTextCharFormat tcf = ui->teStreamContent->currentCharFormat(); - if (!colorize) { - tcf.setBackground(palette().window().color()); - tcf.setForeground(palette().windowText().color()); - } else if (is_from_server) { - tcf.setForeground(ColorUtils::fromColorT(prefs.st_server_fg)); - tcf.setBackground(ColorUtils::fromColorT(prefs.st_server_bg)); - } else { - tcf.setForeground(ColorUtils::fromColorT(prefs.st_client_fg)); - tcf.setBackground(ColorUtils::fromColorT(prefs.st_client_bg)); - } - ui->teStreamContent->setCurrentCharFormat(tcf); - - ui->teStreamContent->insertPlainText(text); - text_pos_to_packet_[ui->teStreamContent->textCursor().anchor()] = packet_num; - - if (truncated_) { - tcf = ui->teStreamContent->currentCharFormat(); - tcf.setBackground(palette().window().color()); - tcf.setForeground(palette().windowText().color()); - ui->teStreamContent->insertPlainText("\n" + tr("[Stream output truncated]")); - ui->teStreamContent->moveCursor(QTextCursor::End); - } else { - ui->teStreamContent->verticalScrollBar()->setValue(cur_pos); - } - setUpdatesEnabled(true); + ui->teStreamContent->addText(std::move(text), is_from_server, packet_num, colorize); } // The following keyboard shortcuts should work (although @@ -682,33 +673,64 @@ void FollowStreamDialog::keyPressEvent(QKeyEvent *event) QDialog::keyPressEvent(event); } -static inline void sanitize_buffer(char *buffer, size_t nchars) { - for (size_t i = 0; i < nchars; i++) { - if (buffer[i] == '\n' || buffer[i] == '\r' || buffer[i] == '\t') +// Replaces non printable ASCII characters in the QByteArray with . +// Causes buffer to detach/deep copy *only* if a character has to be +// replaced. +static inline void sanitize_buffer(QByteArray &buffer, size_t nchars) { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + for (int i = 0; i < (int)nchars; i++) { +#else + for (qsizetype i = 0; i < (qsizetype)nchars; i++) { +#endif + if (buffer.at(i) == '\n' || buffer.at(i) == '\r' || buffer.at(i) == '\t') continue; - if (! g_ascii_isprint((guchar)buffer[i])) { + if (! g_ascii_isprint((unsigned char)buffer.at(i))) { buffer[i] = '.'; } } } -frs_return_t -FollowStreamDialog::showBuffer(char *buffer, size_t nchars, gboolean is_from_server, guint32 packet_num, - nstime_t abs_ts, guint32 *global_pos) +void FollowStreamDialog::showBuffer(QByteArray &buffer, size_t nchars, bool is_from_server, uint32_t packet_num, + nstime_t abs_ts, uint32_t *global_pos) { - gchar initbuf[256]; - guint32 current_pos; - static const gchar hexchars[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + char initbuf[256]; + uint32_t current_pos; + static const char hexchars[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + bool show_delta = false; + + if (last_packet_ == 0) { + last_from_server_ = is_from_server; + } else { + if (recent.gui_follow_delta == FOLLOW_DELTA_ALL || + (recent.gui_follow_delta == FOLLOW_DELTA_TURN && last_from_server_ != is_from_server)) { + show_delta = true; + } + } + + double delta = 0.0; + if (!nstime_is_zero(&abs_ts)) { + // packet-tcp.c and possibly other dissectors can return a zero abs_ts when + // a fragment is missing. + nstime_t delta_ts; + nstime_delta(&delta_ts, &abs_ts, &last_ts_); + delta = nstime_to_sec(&delta_ts); + last_ts_ = abs_ts; + } switch (recent.gui_follow_show) { case SHOW_EBCDIC: { /* If our native arch is ASCII, call: */ - EBCDIC_to_ASCII((guint8*)buffer, (guint) nchars); + EBCDIC_to_ASCII((uint8_t*)buffer.data(), (unsigned) nchars); + if (show_delta) { + ui->teStreamContent->addDeltaTime(delta); + } + if (show_delta || last_from_server_ != is_from_server) { + addText("\n", is_from_server, packet_num); + } sanitize_buffer(buffer, nchars); - QByteArray ba = QByteArray(buffer, (int)nchars); - addText(ba, is_from_server, packet_num); + addText(buffer, is_from_server, packet_num); break; } @@ -717,32 +739,41 @@ FollowStreamDialog::showBuffer(char *buffer, size_t nchars, gboolean is_from_ser /* If our native arch is EBCDIC, call: * ASCII_TO_EBCDIC(buffer, nchars); */ + if (show_delta) { + ui->teStreamContent->addDeltaTime(delta); + } + if (show_delta || last_from_server_ != is_from_server) { + addText("\n", is_from_server, packet_num); + } sanitize_buffer(buffer, nchars); - QByteArray ba = QByteArray(buffer, (int)nchars); - addText(ba, is_from_server, packet_num); + addText(buffer, is_from_server, packet_num); break; } case SHOW_CODEC: { + if (show_delta) { + ui->teStreamContent->addDeltaTime(delta); + } + if (show_delta || last_from_server_ != is_from_server) { + addText("\n", is_from_server, packet_num); + } // This assumes that multibyte characters don't span packets in the // stream. To handle that case properly (which might occur with fixed // block sizes, e.g. transferring over TFTP, we would need to create // two stateful QTextDecoders, one for each direction, presumably in // on_cbCharset_currentIndexChanged() QTextCodec *codec = QTextCodec::codecForName(ui->cbCharset->currentText().toUtf8()); - QByteArray ba = QByteArray(buffer, (int)nchars); - QString decoded = codec->toUnicode(ba); - addText(decoded, is_from_server, packet_num); + addText(codec->toUnicode(buffer), is_from_server, packet_num); break; } case SHOW_HEXDUMP: current_pos = 0; while (current_pos < nchars) { - gchar hexbuf[256]; + char hexbuf[256]; int i; - gchar *cur = hexbuf, *ascii_start; + char *cur = hexbuf, *ascii_start; /* is_from_server indentation : put 4 spaces at the * beginning of the string */ @@ -756,9 +787,9 @@ FollowStreamDialog::showBuffer(char *buffer, size_t nchars, gboolean is_from_ser ascii_start = cur + 49 + 2; for (i = 0; i < 16 && current_pos + i < nchars; i++) { *cur++ = - hexchars[(buffer[current_pos + i] & 0xf0) >> 4]; + hexchars[(buffer.at(current_pos + i) & 0xf0) >> 4]; *cur++ = - hexchars[buffer[current_pos + i] & 0x0f]; + hexchars[buffer.at(current_pos + i) & 0x0f]; *cur++ = ' '; if (i == 7) *cur++ = ' '; @@ -770,8 +801,8 @@ FollowStreamDialog::showBuffer(char *buffer, size_t nchars, gboolean is_from_ser /* Now dump bytes as text */ for (i = 0; i < 16 && current_pos + i < nchars; i++) { *cur++ = - (g_ascii_isprint((guchar)buffer[current_pos + i]) ? - buffer[current_pos + i] : '.'); + (g_ascii_isprint((unsigned char)buffer.at(current_pos + i)) ? + buffer.at(current_pos + i) : '.'); if (i == 7) { *cur++ = ' '; } @@ -794,7 +825,7 @@ FollowStreamDialog::showBuffer(char *buffer, size_t nchars, gboolean is_from_ser addText(initbuf, is_from_server, packet_num); while (current_pos < nchars) { - gchar hexbuf[256]; + char hexbuf[256]; int i, cur; cur = 0; @@ -803,9 +834,9 @@ FollowStreamDialog::showBuffer(char *buffer, size_t nchars, gboolean is_from_ser hexbuf[cur++] = '0'; hexbuf[cur++] = 'x'; hexbuf[cur++] = - hexchars[(buffer[current_pos + i] & 0xf0) >> 4]; + hexchars[(buffer.at(current_pos + i) & 0xf0) >> 4]; hexbuf[cur++] = - hexchars[buffer[current_pos + i] & 0x0f]; + hexchars[buffer.at(current_pos + i) & 0x0f]; /* Delimit array entries with a comma */ if (current_pos + i + 1 < nchars) @@ -849,15 +880,13 @@ FollowStreamDialog::showBuffer(char *buffer, size_t nchars, gboolean is_from_ser " - peer: 0\n" " host: %1\n" " port: %2\n") - .arg(hostname0) - .arg(port0), false, 0); + .arg(hostname0, port0), false, 0); addText(QString( " - peer: 1\n" " host: %1\n" " port: %2\n") - .arg(hostname1) - .arg(port1), true, 0); + .arg(hostname1, port1), true, 0); wmem_free(NULL, port0); wmem_free(NULL, port1); @@ -879,7 +908,7 @@ FollowStreamDialog::showBuffer(char *buffer, size_t nchars, gboolean is_from_ser } while (current_pos < nchars) { int len = current_pos + base64_raw_len < nchars ? base64_raw_len : (int) nchars - current_pos; - QByteArray base64_data(&buffer[current_pos], len); + QByteArray base64_data(&buffer.constData()[current_pos], len); /* XXX: GCC 12.1 has a bogus stringop-overread warning using the Qt * conversions from QByteArray to QString at -O2 and higher due to @@ -896,15 +925,13 @@ DIAG_ON(stringop-overread) current_pos += len; (*global_pos) += len; } - addText(yaml_text, is_from_server, packet_num); + addText(std::move(yaml_text), is_from_server, packet_num); break; } case SHOW_RAW: { - QByteArray ba = QByteArray(buffer, (int)nchars).toHex(); - ba += '\n'; - addText(ba, is_from_server, packet_num); + addText(buffer.toHex() + '\n', is_from_server, packet_num); break; } @@ -915,10 +942,6 @@ DIAG_ON(stringop-overread) ws_assert_not_reached(); } - if (last_packet_ == 0) { - last_from_server_ = is_from_server; - } - if (packet_num != last_packet_) { last_packet_ = packet_num; if (is_from_server) { @@ -931,11 +954,9 @@ DIAG_ON(stringop-overread) turns_++; } } - - return FRS_OK; } -bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index, guint stream_num, guint sub_stream_num) +bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index, unsigned stream_num, unsigned sub_stream_num) { QString follow_filter; const char *hostname0 = NULL, *hostname1 = NULL; @@ -943,12 +964,10 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index, QString server_to_client_string; QString client_to_server_string; QString both_directions_string; - gboolean is_follower = FALSE; + bool is_follower = false; int stream_count; follow_stream_count_func stream_count_func = NULL; - resetStream(); - if (file_closed_) { QMessageBox::warning(this, tr("No capture file."), tr("Please make sure you have a capture file opened.")); @@ -969,8 +988,6 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index, } } - follow_reset_stream(&follow_info_); - /* Create a new filter that matches all packets in the TCP stream, and set the display filter entry accordingly */ if (use_stream_index) { @@ -993,7 +1010,7 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index, /* append the negation */ if (!previous_filter.isEmpty()) { filter_out_filter_ = QString("%1 and !(%2)") - .arg(previous_filter).arg(follow_filter); + .arg(previous_filter, follow_filter); } else { @@ -1005,7 +1022,8 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index, /* data will be passed via tap callback*/ if (!registerTapListener(get_follow_tap_string(follower_), &follow_info_, follow_filter.toUtf8().constData(), - 0, NULL, get_follow_tap_handler(follower_), NULL)) { + 0, FollowStreamDialog::resetStream, + get_follow_tap_handler(follower_), NULL)) { return false; } @@ -1026,9 +1044,9 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index, follow_sub_stream_id_func sub_stream_func; sub_stream_func = get_follow_sub_stream_id_func(follower_); if (sub_stream_func != NULL) { - guint substream_max_id = 0; - sub_stream_func(static_cast(stream_num), G_MAXINT32, TRUE, &substream_max_id); - stream_count = static_cast(substream_max_id); + unsigned substream_max_id = 0; + sub_stream_func(static_cast(stream_num), INT32_MAX, true, &substream_max_id); + stream_count = static_cast(substream_max_id); ui->subStreamNumberSpinBox->blockSignals(true); ui->subStreamNumberSpinBox->setEnabled(true); ui->subStreamNumberSpinBox->setMaximum(stream_count); @@ -1054,43 +1072,83 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index, /* Run the display filter so it goes in effect - even if it's the same as the previous display filter. */ - emit updateFilter(follow_filter, TRUE); + /* XXX: This forces a cf_filter_packets() - but if a rescan (or something else + * that sets cf->read_lock) is in progress, this will queue the filter + * and return immediately. It will also cause a rescan in progress to + * stop and restart with the new filter. That also applies to this rescan; + * changing the main display filter (from the main window, or from, e.g. + * another FollowStreamDialog) will cause this to restart and reset the + * tap. + * + * Other tapping dialogs call cf_retap_packets (which retaps but doesn't + * set the main display filter, freeze the packet list, etc.), which + * has somewhat different behavior when another dialog tries to retap, + * but also results in the taps being reset mid tap. + * + * Either way, we should be event driven and listening for CaptureEvents + * instead of drawing after this returns. (Or like other taps, draw + * periodically in a callback, provided that can be done without causing + * issues with changing the Decode As type.) + */ + emit updateFilter(follow_filter, true); removeTapListeners(); - hostname0 = address_to_name(&follow_info_.client_ip); - hostname1 = address_to_name(&follow_info_.server_ip); - - port0 = get_follow_port_to_display(follower_)(NULL, follow_info_.client_port); - port1 = get_follow_port_to_display(follower_)(NULL, follow_info_.server_port); - - server_to_client_string = - QString("%1:%2 %3 %4:%5 (%6)") - .arg(hostname0).arg(port0) - .arg(UTF8_RIGHTWARDS_ARROW) - .arg(hostname1).arg(port1) - .arg(gchar_free_to_qstring(format_size( - follow_info_.bytes_written[0], - FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI))); - - client_to_server_string = - QString("%1:%2 %3 %4:%5 (%6)") - .arg(hostname1).arg(port1) - .arg(UTF8_RIGHTWARDS_ARROW) - .arg(hostname0).arg(port0) - .arg(gchar_free_to_qstring(format_size( - follow_info_.bytes_written[1], - FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI))); - - wmem_free(NULL, port0); - wmem_free(NULL, port1); - - both_directions_string = tr("Entire conversation (%1)") - .arg(gchar_free_to_qstring(format_size( - follow_info_.bytes_written[0] + follow_info_.bytes_written[1], - FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI))); - setWindowSubtitle(tr("Follow %1 Stream (%2)").arg(proto_get_protocol_short_name(find_protocol_by_id(get_follow_proto_id(follower_)))) - .arg(follow_filter)); + bool is_logray = strcmp(get_configuration_namespace(), "Logray") == 0; + + if (is_logray) { + server_to_client_string = + tr("Read activity(%6)") + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[0], + FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI))); + + client_to_server_string = + tr("Write activity(%6)") + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[1], + FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI))); + + both_directions_string = tr("Entire I/O activity (%1)") + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[0] + follow_info_.bytes_written[1], + FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI))); + } else { + hostname0 = address_to_name(&follow_info_.client_ip); + hostname1 = address_to_name(&follow_info_.server_ip); + + port0 = get_follow_port_to_display(follower_)(NULL, follow_info_.client_port); + port1 = get_follow_port_to_display(follower_)(NULL, follow_info_.server_port); + + server_to_client_string = + QString("%1:%2 %3 %4:%5 (%6)") + .arg(hostname0, port0) + .arg(UTF8_RIGHTWARDS_ARROW) + .arg(hostname1, port1) + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[0], + FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI))); + + client_to_server_string = + QString("%1:%2 %3 %4:%5 (%6)") + .arg(hostname1, port1) + .arg(UTF8_RIGHTWARDS_ARROW) + .arg(hostname0, port0) + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[1], + FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI))); + + wmem_free(NULL, port0); + wmem_free(NULL, port1); + + both_directions_string = tr("Entire conversation (%1)") + .arg(gchar_free_to_qstring(format_size( + follow_info_.bytes_written[0] + follow_info_.bytes_written[1], + FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI))); + } + + setWindowSubtitle(tr("Follow %1 Stream (%2)").arg(proto_get_protocol_short_name(find_protocol_by_id(get_follow_proto_id(follower_))), + follow_filter)); ui->cbDirections->blockSignals(true); ui->cbDirections->clear(); @@ -1100,13 +1158,13 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index, ui->cbDirections->blockSignals(false); followStream(); - fillHintLabel(-1); + fillHintLabel(); updateWidgets(false); endRetapPackets(); if (prefs.restore_filter_after_following_stream) { - emit updateFilter(previous_filter_, TRUE); + emit updateFilter(previous_filter_, true); } return true; @@ -1120,74 +1178,53 @@ void FollowStreamDialog::captureFileClosed() WiresharkDialog::captureFileClosed(); } -/* - * XXX - the routine pointed to by "print_line_fcn_p" doesn't get handed lines, - * it gets handed bufferfuls. That's fine for "follow_write_raw()" - * and "follow_add_to_gtk_text()", but, as "follow_print_text()" calls - * the "print_line()" routine from "print.c", and as that routine might - * genuinely expect to be handed a line (if, for example, it's using - * some OS or desktop environment's printing API, and that API expects - * to be handed lines), "follow_print_text()" should probably accumulate - * lines in a buffer and hand them "print_line()". (If there's a - * complete line in a buffer - i.e., there's nothing of the line in - * the previous buffer or the next buffer - it can just hand that to - * "print_line()" after filtering out non-printables, as an - * optimization.) - * - * This might or might not be the reason why C arrays display - * correctly but get extra blank lines very other line when printed. - */ -frs_return_t -FollowStreamDialog::readFollowStream() +void FollowStreamDialog::readFollowStream() { - guint32 global_client_pos = 0, global_server_pos = 0; - guint32 *global_pos; - gboolean skip; + uint32_t global_client_pos = 0, global_server_pos = 0; + uint32_t *global_pos; + bool skip; GList* cur; - frs_return_t frs_return; follow_record_t *follow_record; QElapsedTimer elapsed_timer; + QByteArray buffer; elapsed_timer.start(); loop_break_mutex.lock(); - isReadRunning = TRUE; + isReadRunning = true; loop_break_mutex.unlock(); for (cur = g_list_last(follow_info_.payload); cur; cur = g_list_previous(cur)) { if (dialogClosed() || !isReadRunning) break; follow_record = (follow_record_t *)cur->data; - skip = FALSE; + skip = false; if (!follow_record->is_server) { global_pos = &global_client_pos; if (follow_info_.show_stream == FROM_SERVER) { - skip = TRUE; + skip = true; } } else { global_pos = &global_server_pos; if (follow_info_.show_stream == FROM_CLIENT) { - skip = TRUE; + skip = true; } } - QByteArray buffer; if (!skip) { - // We want a deep copy. - buffer.clear(); - buffer.append((const char *) follow_record->data->data, - follow_record->data->len); - frs_return = showBuffer( - buffer.data(), - follow_record->data->len, - follow_record->is_server, - follow_record->packet_num, - follow_record->abs_ts, - global_pos); - if (frs_return == FRS_PRINT_ERROR) - return frs_return; + // This will only detach / deep copy if the buffer data is + // modified. Try to avoid doing that as much as possible + // (and avoid new memory allocations that have to be freed). + buffer.setRawData((char*)follow_record->data->data, follow_record->data->len); + showBuffer( + buffer, + follow_record->data->len, + follow_record->is_server, + follow_record->packet_num, + follow_record->abs_ts, + global_pos); if (elapsed_timer.elapsed() > info_update_freq_) { - fillHintLabel(ui->teStreamContent->textCursor().position()); + fillHintLabel(ui->teStreamContent->currentPacket()); mainApp->processEvents(); elapsed_timer.start(); } @@ -1195,8 +1232,7 @@ FollowStreamDialog::readFollowStream() } loop_break_mutex.lock(); - isReadRunning = FALSE; + isReadRunning = false; loop_break_mutex.unlock(); - - return FRS_OK; } + diff --git a/ui/qt/follow_stream_dialog.h b/ui/qt/follow_stream_dialog.h index e56023de..859c0534 100644 --- a/ui/qt/follow_stream_dialog.h +++ b/ui/qt/follow_stream_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include #ifdef HAVE_UNISTD_H @@ -44,7 +42,7 @@ public: ~FollowStreamDialog(); void addCodecs(const QMap &codecMap); - bool follow(QString previous_filter = QString(), bool use_stream_index = false, guint stream_num = 0, guint sub_stream_num = 0); + bool follow(QString previous_filter = QString(), bool use_stream_index = false, unsigned stream_num = 0, unsigned sub_stream_num = 0); protected: bool eventFilter(QObject *obj, QEvent *event); @@ -52,10 +50,11 @@ protected: void captureFileClosed(); private slots: - void on_cbCharset_currentIndexChanged(int idx); - void on_cbDirections_currentIndexChanged(int idx); - void on_bFind_clicked(); - void on_leFind_returnPressed(); + void cbCharsetCurrentIndexChanged(int idx); + void deltaComboBoxCurrentIndexChanged(int idx); + void cbDirectionsCurrentIndexChanged(int idx); + void bFindClicked(); + void leFindReturnPressed(); void helpButton(); void backButton(); @@ -65,33 +64,33 @@ private slots: void findText(bool go_back = true); void saveAs(); void printStream(); - void fillHintLabel(int text_pos); - void goToPacketForTextPos(int text_pos); + void fillHintLabel(int pkt = 0); + void goToPacketForTextPos(int pkt = 0); - void on_streamNumberSpinBox_valueChanged(int stream_num); - void on_subStreamNumberSpinBox_valueChanged(int sub_stream_num); + void streamNumberSpinBoxValueChanged(int stream_num); + void subStreamNumberSpinBoxValueChanged(int sub_stream_num); - void on_buttonBox_rejected(); + void buttonBoxRejected(); signals: void updateFilter(QString filter, bool force); void goToPacket(int packet_num); private: + // Callback for register_tap_listener + static void resetStream(void *tapData); + void removeStreamControls(); void resetStream(void); void updateWidgets(bool follow_in_progress); void updateWidgets() { updateWidgets(false); } // Needed for WiresharkDialog? - frs_return_t - showBuffer(char *buffer, size_t nchars, gboolean is_from_server, - guint32 packet_num, nstime_t abs_ts, guint32 *global_pos); - - frs_return_t readStream(); - frs_return_t readFollowStream(); - frs_return_t readSslStream(); + void showBuffer(QByteArray &buffer, size_t nchars, bool is_from_server, + uint32_t packet_num, nstime_t abs_ts, uint32_t *global_pos); + void readStream(); + void readFollowStream(); void followStream(); - void addText(QString text, gboolean is_from_server, guint32 packet_num, gboolean colorize = true); + void addText(QString text, bool is_from_server, uint32_t packet_num, bool colorize = true); Ui::FollowStreamDialog *ui; @@ -103,9 +102,6 @@ private: follow_info_t follow_info_; register_follow_t* follower_; - QString data_out_filename_; - static const int max_document_length_; - bool truncated_; QString previous_filter_; QString filter_out_filter_; QString output_filter_; @@ -113,10 +109,10 @@ private: int server_buffer_count_; int client_packet_count_; int server_packet_count_; - guint32 last_packet_; - gboolean last_from_server_; + uint32_t last_packet_; + bool last_from_server_; + nstime_t last_ts_; int turns_; - QMap text_pos_to_packet_; bool use_regex_find_; diff --git a/ui/qt/follow_stream_dialog.ui b/ui/qt/follow_stream_dialog.ui index 3b4a76a4..dc77586e 100644 --- a/ui/qt/follow_stream_dialog.ui +++ b/ui/qt/follow_stream_dialog.ui @@ -6,7 +6,7 @@ 0 0 - 609 + 750 600 @@ -41,7 +41,7 @@ - + @@ -50,7 +50,7 @@ - + Qt::Horizontal @@ -65,7 +65,7 @@ - Show data as + Show as @@ -76,6 +76,38 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + No delta times + + + + + Turn delta times + + + + + All delta times + + + + @@ -123,6 +155,13 @@ + + + + Case sensitive + + + diff --git a/ui/qt/font_color_preferences_frame.cpp b/ui/qt/font_color_preferences_frame.cpp index 0a09e0f4..ceb94c31 100644 --- a/ui/qt/font_color_preferences_frame.cpp +++ b/ui/qt/font_color_preferences_frame.cpp @@ -15,6 +15,7 @@ #include #include #include "main_application.h" +#include "wsutil/array.h" #include #include @@ -28,7 +29,7 @@ static const char *font_pangrams_[] = { QT_TRANSLATE_NOOP("FontColorPreferencesFrame", "Example GIF query packets have jumbo window sizes"), QT_TRANSLATE_NOOP("FontColorPreferencesFrame", "Lazy badgers move unique waxy jellyfish packets") }; -const int num_font_pangrams_ = (sizeof font_pangrams_ / sizeof font_pangrams_[0]); +const int num_font_pangrams_ = array_length(font_pangrams_); FontColorPreferencesFrame::FontColorPreferencesFrame(QWidget *parent) : QFrame(parent), @@ -78,7 +79,7 @@ void FontColorPreferencesFrame::showEvent(QShowEvent *) void FontColorPreferencesFrame::updateWidgets() { - gint colorstyle; + int colorstyle; QColor foreground; QColor background1; QColor background2; diff --git a/ui/qt/funnel_statistics.cpp b/ui/qt/funnel_statistics.cpp index f5ed6745..943c354b 100644 --- a/ui/qt/funnel_statistics.cpp +++ b/ui/qt/funnel_statistics.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include "epan/color_filters.h" #include "file.h" @@ -43,23 +41,23 @@ extern "C" { static struct _funnel_text_window_t* text_window_new(funnel_ops_id_t *ops_id, const char* title); -static void string_dialog_new(funnel_ops_id_t *ops_id, const gchar* title, const gchar** field_names, const gchar** field_values, funnel_dlg_cb_t dialog_cb, void* dialog_cb_data, funnel_dlg_cb_data_free_t dialog_cb_data_free); +static void string_dialog_new(funnel_ops_id_t *ops_id, const char* title, const char** field_names, const char** field_values, funnel_dlg_cb_t dialog_cb, void* dialog_cb_data, funnel_dlg_cb_data_free_t dialog_cb_data_free); static void funnel_statistics_retap_packets(funnel_ops_id_t *ops_id); static void funnel_statistics_copy_to_clipboard(GString *text); -static const gchar *funnel_statistics_get_filter(funnel_ops_id_t *ops_id); +static const char *funnel_statistics_get_filter(funnel_ops_id_t *ops_id); static void funnel_statistics_set_filter(funnel_ops_id_t *ops_id, const char* filter_string); -static gchar* funnel_statistics_get_color_filter_slot(guint8 filter_num); -static void funnel_statistics_set_color_filter_slot(guint8 filter_num, const gchar* filter_string); -static gboolean funnel_statistics_open_file(funnel_ops_id_t *ops_id, const char* fname, const char* filter, char**); +static char* funnel_statistics_get_color_filter_slot(uint8_t filter_num); +static void funnel_statistics_set_color_filter_slot(uint8_t filter_num, const char* filter_string); +static bool funnel_statistics_open_file(funnel_ops_id_t *ops_id, const char* fname, const char* filter, char**); static void funnel_statistics_reload_packets(funnel_ops_id_t *ops_id); static void funnel_statistics_redissect_packets(funnel_ops_id_t *ops_id); static void funnel_statistics_reload_lua_plugins(funnel_ops_id_t *ops_id); static void funnel_statistics_apply_filter(funnel_ops_id_t *ops_id); -static gboolean browser_open_url(const gchar *url); -static void browser_open_data_file(const gchar *filename); -static struct progdlg *progress_window_new(funnel_ops_id_t *ops_id, const gchar* title, const gchar* task, gboolean terminate_is_stop, gboolean *stop_flag); -static void progress_window_update(struct progdlg *progress_dialog, float percentage, const gchar* status); +static bool browser_open_url(const char *url); +static void browser_open_data_file(const char *filename); +static struct progdlg *progress_window_new(funnel_ops_id_t *ops_id, const char* title, const char* task, bool terminate_is_stop, bool *stop_flag); +static void progress_window_update(struct progdlg *progress_dialog, float percentage, const char* status); static void progress_window_destroy(struct progdlg *progress_dialog); } @@ -67,14 +65,14 @@ FunnelAction::FunnelAction(QObject *parent) : QAction(parent), callback_(nullptr), callback_data_(NULL), - retap_(FALSE), + retap_(false), packetCallback_(nullptr), packetData_(NULL) { } -FunnelAction::FunnelAction(QString title, funnel_menu_callback callback, gpointer callback_data, gboolean retap, QObject *parent = nullptr) : +FunnelAction::FunnelAction(QString title, funnel_menu_callback callback, void *callback_data, bool retap, QObject *parent = nullptr) : QAction(parent), title_(title), callback_(callback), @@ -89,7 +87,7 @@ FunnelAction::FunnelAction(QString title, funnel_menu_callback callback, gpointe packetRequiredFields_ = QSet(); } -FunnelAction::FunnelAction(QString title, funnel_packet_menu_callback callback, gpointer callback_data, gboolean retap, const char *packet_required_fields, QObject *parent = nullptr) : +FunnelAction::FunnelAction(QString title, funnel_packet_menu_callback callback, void *callback_data, bool retap, const char *packet_required_fields, QObject *parent = nullptr) : QAction(parent), title_(title), callback_data_(callback_data), @@ -248,7 +246,7 @@ void FunnelConsoleAction::triggerCallback() { static QHash > funnel_actions_; const QString FunnelStatistics::action_name_ = "FunnelStatisticsAction"; -static gboolean menus_registered = FALSE; +static bool menus_registered; struct _funnel_ops_id_t { FunnelStatistics *funnel_statistics; @@ -313,7 +311,7 @@ void FunnelStatistics::retapPackets() capture_file_.retapPackets(); } -struct progdlg *FunnelStatistics::progressDialogNew(const gchar *task_title, const gchar *item_title, gboolean terminate_is_stop, gboolean *stop_flag) +struct progdlg *FunnelStatistics::progressDialogNew(const char *task_title, const char *item_title, bool terminate_is_stop, bool *stop_flag) { return create_progress_dlg(parent(), task_title, item_title, terminate_is_stop, stop_flag); } @@ -373,7 +371,7 @@ struct _funnel_text_window_t* text_window_new(funnel_ops_id_t *ops_id, const cha return FunnelTextDialog::textWindowNew(qobject_cast(ops_id->funnel_statistics->parent()), title); } -void string_dialog_new(funnel_ops_id_t *ops_id, const gchar* title, const gchar** field_names, const gchar** field_values, funnel_dlg_cb_t dialog_cb, void* dialog_cb_data, funnel_dlg_cb_data_free_t dialog_cb_data_free) +void string_dialog_new(funnel_ops_id_t *ops_id, const char* title, const char** field_names, const char** field_values, funnel_dlg_cb_t dialog_cb, void* dialog_cb_data, funnel_dlg_cb_data_free_t dialog_cb_data_free) { QList> field_list; for (int i = 0; field_names[i]; i++) { @@ -398,7 +396,7 @@ void funnel_statistics_copy_to_clipboard(GString *text) { mainApp->clipboard()->setText(text->str); } -const gchar *funnel_statistics_get_filter(funnel_ops_id_t *ops_id) { +const char *funnel_statistics_get_filter(funnel_ops_id_t *ops_id) { if (!ops_id || !ops_id->funnel_statistics) return nullptr; return ops_id->funnel_statistics->displayFilter(); @@ -410,28 +408,28 @@ void funnel_statistics_set_filter(funnel_ops_id_t *ops_id, const char* filter_st ops_id->funnel_statistics->emitSetDisplayFilter(filter_string); } -gchar* funnel_statistics_get_color_filter_slot(guint8 filter_num) { +char* funnel_statistics_get_color_filter_slot(uint8_t filter_num) { return color_filters_get_tmp(filter_num); } -void funnel_statistics_set_color_filter_slot(guint8 filter_num, const gchar* filter_string) { - gchar *err_msg = nullptr; - if (!color_filters_set_tmp(filter_num, filter_string, FALSE, &err_msg)) { +void funnel_statistics_set_color_filter_slot(uint8_t filter_num, const char* filter_string) { + char *err_msg = nullptr; + if (!color_filters_set_tmp(filter_num, filter_string, false, &err_msg)) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); g_free(err_msg); } } -gboolean funnel_statistics_open_file(funnel_ops_id_t *ops_id, const char* fname, const char* filter, char**) { +bool funnel_statistics_open_file(funnel_ops_id_t *ops_id, const char* fname, const char* filter, char**) { // XXX We need to return a proper error value. We should probably move // MainWindow::openCaptureFile to CaptureFile and add error handling // there. - if (!ops_id || !ops_id->funnel_statistics) return FALSE; + if (!ops_id || !ops_id->funnel_statistics) return false; QString cf_name(fname); QString cf_filter(filter); ops_id->funnel_statistics->emitOpenCaptureFile(cf_name, cf_filter); - return TRUE; + return true; } void funnel_statistics_reload_packets(funnel_ops_id_t *ops_id) { @@ -458,21 +456,21 @@ void funnel_statistics_apply_filter(funnel_ops_id_t *ops_id) { ops_id->funnel_statistics->emitApplyDisplayFilter(); } -gboolean browser_open_url(const gchar *url) { - return QDesktopServices::openUrl(QUrl(url)) ? TRUE : FALSE; +bool browser_open_url(const char *url) { + return QDesktopServices::openUrl(QUrl(url)) ? true : false; } -void browser_open_data_file(const gchar *filename) { +void browser_open_data_file(const char *filename) { QDesktopServices::openUrl(QUrl::fromLocalFile(filename)); } -struct progdlg *progress_window_new(funnel_ops_id_t *ops_id, const gchar* task_title, const gchar* item_title, gboolean terminate_is_stop, gboolean *stop_flag) { +struct progdlg *progress_window_new(funnel_ops_id_t *ops_id, const char* task_title, const char* item_title, bool terminate_is_stop, bool *stop_flag) { if (!ops_id || !ops_id->funnel_statistics) return nullptr; return ops_id->funnel_statistics->progressDialogNew(task_title, item_title, terminate_is_stop, stop_flag); } -void progress_window_update(struct progdlg *progress_dialog, float percentage, const gchar* status) { +void progress_window_update(struct progdlg *progress_dialog, float percentage, const char* status) { update_progress_dlg(progress_dialog, percentage, status); } @@ -487,8 +485,8 @@ void register_tap_listener_qt_funnel(void); static void register_menu_cb(const char *name, register_stat_group_t group, funnel_menu_callback callback, - gpointer callback_data, - gboolean retap) + void *callback_data, + bool retap) { FunnelAction *funnel_action = new FunnelAction(name, callback, callback_data, retap, mainApp); if (menus_registered) { @@ -519,8 +517,8 @@ static void register_menu_cb(const char *name, static void register_packet_menu_cb(const char *name, const char *required_fields, funnel_packet_menu_callback callback, - gpointer callback_data, - gboolean retap) + void *callback_data, + bool retap) { FunnelAction *funnel_action = new FunnelAction(name, callback, callback_data, retap, required_fields, mainApp); MainWindow * mainwindow = qobject_cast(mainApp->mainWindow()); @@ -552,7 +550,7 @@ register_tap_listener_qt_funnel(void) { funnel_register_all_menus(register_menu_cb); funnel_statistics_load_console_menus(); - menus_registered = TRUE; + menus_registered = true; } void @@ -566,9 +564,9 @@ funnel_statistics_reload_menus(void) /** * Returns whether the packet menus have been modified since they were last registered * - * @return TRUE if the packet menus were modified since the last registration + * @return true if the packet menus were modified since the last registration */ -gboolean +bool funnel_statistics_packet_menus_modified(void) { return funnel_packet_menus_modified(); diff --git a/ui/qt/funnel_statistics.h b/ui/qt/funnel_statistics.h index 65b36ab8..b6ed12f7 100644 --- a/ui/qt/funnel_statistics.h +++ b/ui/qt/funnel_statistics.h @@ -26,7 +26,7 @@ struct progdlg; /** * Signature of function that can be called from a custom packet menu entry */ -typedef void (* funnel_packet_menu_callback)(gpointer, GPtrArray*); +typedef void (* funnel_packet_menu_callback)(void *, GPtrArray*); class FunnelStatistics : public QObject { @@ -35,7 +35,7 @@ public: explicit FunnelStatistics(QObject *parent, CaptureFile &cf); ~FunnelStatistics(); void retapPackets(); - struct progdlg *progressDialogNew(const gchar *task_title, const gchar *item_title, gboolean terminate_is_stop, gboolean *stop_flag); + struct progdlg *progressDialogNew(const char *task_title, const char *item_title, bool terminate_is_stop, bool *stop_flag); const char *displayFilter(); void emitSetDisplayFilter(const QString filter); void reloadPackets(); @@ -68,8 +68,8 @@ class FunnelAction : public QAction Q_OBJECT public: FunnelAction(QObject *parent = nullptr); - FunnelAction(QString title, funnel_menu_callback callback, gpointer callback_data, gboolean retap, QObject *parent); - FunnelAction(QString title, funnel_packet_menu_callback callback, gpointer callback_data, gboolean retap, const char *packet_required_fields, QObject *parent); + FunnelAction(QString title, funnel_menu_callback callback, void *callback_data, bool retap, QObject *parent); + FunnelAction(QString title, funnel_packet_menu_callback callback, void *callback_data, bool retap, const char *packet_required_fields, QObject *parent); ~FunnelAction(); funnel_menu_callback callback() const; QString title() const; @@ -89,8 +89,8 @@ private: QString title_; QString packetSubmenu_; funnel_menu_callback callback_; - gpointer callback_data_; - gboolean retap_; + void *callback_data_; + bool retap_; funnel_packet_menu_callback packetCallback_; GPtrArray* packetData_; QSet packetRequiredFields_; @@ -120,7 +120,7 @@ extern "C" { void funnel_statistics_reload_menus(void); void funnel_statistics_load_packet_menus(void); void funnel_statistics_load_console_menus(void); - gboolean funnel_statistics_packet_menus_modified(void); + bool funnel_statistics_packet_menus_modified(void); } // extern "C" #endif // FUNNELSTATISTICS_H diff --git a/ui/qt/funnel_string_dialog.cpp b/ui/qt/funnel_string_dialog.cpp index de52e73f..c8cffe09 100644 --- a/ui/qt/funnel_string_dialog.cpp +++ b/ui/qt/funnel_string_dialog.cpp @@ -81,7 +81,7 @@ void FunnelStringDialog::on_buttonBox_accepted() } g_ptr_array_add(returns, NULL); - gchar **user_input = (gchar **)g_ptr_array_free(returns, FALSE); + char **user_input = (char **)g_ptr_array_free(returns, false); dialog_cb_(user_input, dialog_cb_data_); } diff --git a/ui/qt/funnel_string_dialog.h b/ui/qt/funnel_string_dialog.h index bd4f3d35..2ac277aa 100644 --- a/ui/qt/funnel_string_dialog.h +++ b/ui/qt/funnel_string_dialog.h @@ -10,8 +10,6 @@ #ifndef FUNNEL_STRING_DIALOG_H #define FUNNEL_STRING_DIALOG_H -#include - #include "epan/funnel.h" #include diff --git a/ui/qt/funnel_text_dialog.cpp b/ui/qt/funnel_text_dialog.cpp index ad18cf76..15043926 100644 --- a/ui/qt/funnel_text_dialog.cpp +++ b/ui/qt/funnel_text_dialog.cpp @@ -113,7 +113,7 @@ void FunnelTextDialog::setCloseCallback(text_win_close_cb_t close_cb, void *clos close_cb_data_ = close_cb_data; } -void FunnelTextDialog::setTextEditable(gboolean editable) +void FunnelTextDialog::setTextEditable(bool editable) { ui->textEdit->setReadOnly(!editable); } @@ -214,7 +214,7 @@ void text_window_set_close_cb(funnel_text_window_t *ftw, text_win_close_cb_t clo } } -void text_window_set_editable(funnel_text_window_t *ftw, gboolean editable) +void text_window_set_editable(funnel_text_window_t *ftw, bool editable) { if (ftw) { ftw->funnel_text_dialog->setTextEditable(editable); diff --git a/ui/qt/funnel_text_dialog.h b/ui/qt/funnel_text_dialog.h index 84a313c9..19476dd3 100644 --- a/ui/qt/funnel_text_dialog.h +++ b/ui/qt/funnel_text_dialog.h @@ -10,8 +10,6 @@ #ifndef FUNNEL_TEXT_DIALOG_H #define FUNNEL_TEXT_DIALOG_H -#include - #include "epan/funnel.h" #include "geometry_state_dialog.h" @@ -44,7 +42,7 @@ public: void clearText(); const char *getText(); void setCloseCallback(text_win_close_cb_t close_cb, void* close_cb_data); - void setTextEditable(gboolean editable); + void setTextEditable(bool editable); void addButton(funnel_bt_t *button_cb, QString label); private slots: @@ -66,7 +64,7 @@ void text_window_prepend(funnel_text_window_t* ftw, const char* text); void text_window_clear(funnel_text_window_t *ftw); const char *text_window_get_text(funnel_text_window_t* ftw); void text_window_set_close_cb(funnel_text_window_t *ftw, text_win_close_cb_t close_cb, void* close_cb_data); -void text_window_set_editable(funnel_text_window_t* ftw, gboolean editable); +void text_window_set_editable(funnel_text_window_t* ftw, bool editable); void text_window_destroy(funnel_text_window_t* ftw); void text_window_add_button(funnel_text_window_t* ftw, funnel_bt_t* funnel_button, const char* label); } diff --git a/ui/qt/geometry_state_dialog.cpp b/ui/qt/geometry_state_dialog.cpp index ca6d3980..28a746ee 100644 --- a/ui/qt/geometry_state_dialog.cpp +++ b/ui/qt/geometry_state_dialog.cpp @@ -14,7 +14,8 @@ GeometryStateDialog::~GeometryStateDialog() { - saveGeometry(); + saveWindowGeometry(); + saveSplitterState(); } void GeometryStateDialog::loadGeometry(int width, int height, const QString &dialog_name) @@ -23,24 +24,30 @@ void GeometryStateDialog::loadGeometry(int width, int height, const QString &dia dialog_name_ = dialog_name.isEmpty() ? objectName() : dialog_name; if (!dialog_name_.isEmpty() && window_geom_load(dialog_name_.toUtf8().constData(), &geom)) { - QRect recent_geom(geom.x, geom.y, geom.width, geom.height); + if (geom.qt_geom == nullptr || !restoreGeometry(QByteArray::fromHex(geom.qt_geom))) { + // restoreGeometry didn't work, fallback to older (but other + // toolkit compatible?) less-accurate method. (restoreGeometry + // is supposed to take care of things like making sure the window + // is on screen, setting the non-maximized size if maximized, etc.) + QRect recent_geom(geom.x, geom.y, geom.width, geom.height); - // Check if the dialog is visible on any screen - if (rect_on_screen(recent_geom)) { - move(recent_geom.topLeft()); - resize(recent_geom.size()); - } else { - // Not visible, move within a reasonable area and try size only - recent_geom.moveTopLeft(QPoint(50, 50)); + // Check if the dialog is visible on any screen if (rect_on_screen(recent_geom)) { + move(recent_geom.topLeft()); resize(recent_geom.size()); - } else if (width > 0 && height > 0) { - // We're not visible on any screens, use defaults - resize(width, height); + } else { + // Not visible, move within a reasonable area and try size only + recent_geom.moveTopLeft(QPoint(50, 50)); + if (rect_on_screen(recent_geom)) { + resize(recent_geom.size()); + } else if (width > 0 && height > 0) { + // We're not visible on any screens, use defaults + resize(width, height); + } + } + if (geom.maximized) { + showFullScreen(); } - } - if (geom.maximized) { - showFullScreen(); } } else if (width > 0 && height > 0) { // No saved geometry found, use defaults @@ -48,7 +55,34 @@ void GeometryStateDialog::loadGeometry(int width, int height, const QString &dia } } -void GeometryStateDialog::saveGeometry() +#ifndef Q_OS_MAC +void GeometryStateDialog::setWindowModality(Qt::WindowModality modality) +{ + if (modality != windowModality()) { + if (modality == Qt::NonModal) { + setParent(nullptr, windowFlags()); + } else { + setParent(parent_, windowFlags()); + } + } + QDialog::setWindowModality(modality); +} +#endif + +void GeometryStateDialog::loadSplitterState(QSplitter *splitter) +{ + if (splitter == nullptr) { + splitter = findChild(); + } + if (splitter != nullptr) { + const char* splitter_state = window_splitter_load(dialog_name_.toUtf8().constData()); + if (splitter_state != nullptr) { + splitter->restoreState(QByteArray::fromHex(splitter_state)); + } + } +} + +void GeometryStateDialog::saveWindowGeometry() { if (dialog_name_.isEmpty()) return; @@ -56,14 +90,27 @@ void GeometryStateDialog::saveGeometry() window_geometry_t geom; geom.key = NULL; - geom.set_pos = TRUE; + geom.set_pos = true; geom.x = pos().x(); geom.y = pos().y(); - geom.set_size = TRUE; + geom.set_size = true; geom.width = size().width(); geom.height = size().height(); - geom.set_maximized = TRUE; + geom.set_maximized = true; + // XXX: maximized and fullScreen are different window states; we've been + // using the maximized key for fullScreen ever since this was added. geom.maximized = isFullScreen(); + geom.qt_geom = g_strdup(saveGeometry().toHex().constData()); window_geom_save(dialog_name_.toUtf8().constData(), &geom); } + +void GeometryStateDialog::saveSplitterState(const QSplitter *splitter) +{ + if (splitter == nullptr) { + splitter = findChild(); + } + if (splitter != nullptr) { + window_splitter_save(dialog_name_.toUtf8().constData(), splitter->saveState().toHex().constData()); + } +} diff --git a/ui/qt/geometry_state_dialog.h b/ui/qt/geometry_state_dialog.h index 613fad8a..15f0af63 100644 --- a/ui/qt/geometry_state_dialog.h +++ b/ui/qt/geometry_state_dialog.h @@ -11,6 +11,7 @@ #define GEOMETRY_STATE_DIALOG_H #include +#include class GeometryStateDialog : public QDialog { @@ -44,24 +45,51 @@ public: // // Additionally, maximized, parent-less dialogs can close to a black screen // on macOS: https://gitlab.com/wireshark/wireshark/-/issues/12544 +// (aka https://bugreports.qt.io/browse/QTBUG-46701 ), which claims to +// be fixed in Qt 6.2.0 // // Pass in the parent on macOS and NULL elsewhere so that we have an // independent window that un-maximizes correctly. +// +// Pass Qt::Window as the flags that we have minimize and maximize buttons, as +// this class is for dialogs where we want to remember user-set geometry. +// (We're still at the mercy of the platform and Qt, e.g. recent GNOME defaults +// to not having min or max buttons, instead requiring right-clicking on the +// menu title bar to perform the minimize or maximize actions. We can't do +// anything about that, though users can.) +// +// However, we want modal dialogs to always be on top of their parent. +// On Linux with Mutter (and maybe some other window managers), an orphan +// ApplicationModal dialog is not always on top, and it's confusing if a +// modal dialog is behind other windows it blocks (Issue #19099). On Windows, +// a modal orphan dialog is always on top, but setting the parent adds effects +// like causing the modal dialog to shake if the blocked parent is clicked. +// So when setting the dialog modal, set the parent if we haven't yet. #ifdef Q_OS_MAC - explicit GeometryStateDialog(QWidget *parent, Qt::WindowFlags f = Qt::WindowFlags()) : QDialog(parent, f) {} + explicit GeometryStateDialog(QWidget *parent, Qt::WindowFlags f = Qt::Window) : QDialog(parent, f) {} #else - explicit GeometryStateDialog(QWidget *, Qt::WindowFlags f = Qt::WindowFlags()) : QDialog(NULL, f) {} + explicit GeometryStateDialog(QWidget *parent, Qt::WindowFlags f = Qt::Window) : QDialog(NULL, f), parent_(parent) {} #endif ~GeometryStateDialog(); +#ifndef Q_OS_MAC +public: + void setWindowModality(Qt::WindowModality windowModality); +#endif + protected: void loadGeometry(int width = 0, int height = 0, const QString &dialog_name = QString()); + void loadSplitterState(QSplitter *splitter = nullptr); private: - void saveGeometry(); + void saveWindowGeometry(); + void saveSplitterState(const QSplitter *splitter = nullptr); QString dialog_name_; +#ifndef Q_OS_MAC + QWidget *parent_; +#endif }; #endif // GEOMETRY_STATE_DIALOG_H diff --git a/ui/qt/glib_mainloop_on_qeventloop.cpp b/ui/qt/glib_mainloop_on_qeventloop.cpp index f715bbc7..c92901b5 100644 --- a/ui/qt/glib_mainloop_on_qeventloop.cpp +++ b/ui/qt/glib_mainloop_on_qeventloop.cpp @@ -5,6 +5,8 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ +#include + #include #include "glib_mainloop_on_qeventloop.h" @@ -24,7 +26,7 @@ GLibPoller::~GLibPoller() void GLibPoller::run() { - gint timeout; + int timeout; mutex_.lock(); while (!isInterruptionRequested()) diff --git a/ui/qt/glib_mainloop_on_qeventloop.h b/ui/qt/glib_mainloop_on_qeventloop.h index 9f66c681..9a641e04 100644 --- a/ui/qt/glib_mainloop_on_qeventloop.h +++ b/ui/qt/glib_mainloop_on_qeventloop.h @@ -11,7 +11,6 @@ #include #include #include -#include class GLibPoller : public QThread { @@ -26,9 +25,9 @@ protected: QMutex mutex_; QWaitCondition dispatched_; GMainContext *ctx_; - gint priority_; + int priority_; GPollFD *fds_; - gint allocated_fds_, nfds_; + int allocated_fds_, nfds_; signals: void polled(void); diff --git a/ui/qt/gsm_map_summary_dialog.cpp b/ui/qt/gsm_map_summary_dialog.cpp index 3652c7c7..acdcd48b 100644 --- a/ui/qt/gsm_map_summary_dialog.cpp +++ b/ui/qt/gsm_map_summary_dialog.cpp @@ -16,8 +16,6 @@ #include "config.h" -#include - #include "ui/summary.h" #include diff --git a/ui/qt/iax2_analysis_dialog.cpp b/ui/qt/iax2_analysis_dialog.cpp index 7e3fb82e..dfac2ee7 100644 --- a/ui/qt/iax2_analysis_dialog.cpp +++ b/ui/qt/iax2_analysis_dialog.cpp @@ -134,7 +134,7 @@ public: } } - guint32 frameNum() { return frame_num_; } + uint32_t frameNum() { return frame_num_; } bool frameStatus() { return ok_; } QList rowData() { @@ -153,19 +153,14 @@ public: switch (treeWidget()->sortColumn()) { case (packet_col_): return frame_num_ < other_row->frame_num_; - break; case (delta_col_): return delta_ < other_row->delta_; - break; case (jitter_col_): return jitter_ < other_row->jitter_; - break; case (bandwidth_col_): return bandwidth_ < other_row->bandwidth_; - break; case (length_col_): return pkt_len_ < other_row->pkt_len_; - break; default: break; } @@ -174,9 +169,9 @@ public: return QTreeWidgetItem::operator <(other); } private: - guint32 frame_num_; - guint32 pkt_len_; - guint32 flags_; + uint32_t frame_num_; + uint32_t pkt_len_; + uint32_t flags_; double delta_; double jitter_; double bandwidth_; @@ -228,6 +223,9 @@ Iax2AnalysisDialog::Iax2AnalysisDialog(QWidget &parent, CaptureFile &cf) : this, SLOT(graphClicked(QMouseEvent*))); graph_ctx_menu_.addAction(ui->actionSaveGraph); + ui->streamGraph->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->streamGraph, &QCustomPlot::customContextMenuRequested, this, + &Iax2AnalysisDialog::showGraphMenu); QStringList header_labels; for (int i = 0; i < ui->forwardTreeWidget->columnCount(); i++) { @@ -289,9 +287,9 @@ Iax2AnalysisDialog::Iax2AnalysisDialog(QWidget &parent, CaptureFile &cf) : #if 0 /* Only accept Voice or MiniPacket packets */ - const gchar filter_text[] = "iax2.call && (ip || ipv6)"; + const char filter_text[] = "iax2.call && (ip || ipv6)"; #else - const gchar filter_text[] = "iax2 && (ip || ipv6)"; + const char filter_text[] = "iax2 && (ip || ipv6)"; #endif dfilter_t *sfcode; df_error_t *df_err; @@ -318,7 +316,7 @@ Iax2AnalysisDialog::Iax2AnalysisDialog(QWidget &parent, CaptureFile &cf) : epan_dissect_t edt; - epan_dissect_init(&edt, cap_file_.capFile()->epan, TRUE, FALSE); + epan_dissect_init(&edt, cap_file_.capFile()->epan, true, false); epan_dissect_prime_with_dfilter(&edt, sfcode); epan_dissect_run(&edt, cap_file_.capFile()->cd_t, &cap_file_.capFile()->rec, frame_tvbuff_new_buffer(&cap_file_.capFile()->provider, fdata, &cap_file_.capFile()->buf), @@ -337,10 +335,10 @@ Iax2AnalysisDialog::Iax2AnalysisDialog(QWidget &parent, CaptureFile &cf) : dfilter_free(sfcode); /* ok, it is a IAX2 frame, so let's get the ip and port values */ - rtpstream_id_copy_pinfo(&(edt.pi),&(fwd_id_),FALSE); + rtpstream_id_copy_pinfo(&(edt.pi),&(fwd_id_),false); /* assume the inverse ip/port combination for the reverse direction */ - rtpstream_id_copy_pinfo(&(edt.pi),&(rev_id_),TRUE); + rtpstream_id_copy_pinfo(&(edt.pi),&(rev_id_),true); epan_dissect_cleanup(&edt); @@ -652,8 +650,8 @@ void Iax2AnalysisDialog::resetStatistics() memset(&fwd_statinfo_, 0, sizeof(fwd_statinfo_)); memset(&rev_statinfo_, 0, sizeof(rev_statinfo_)); - fwd_statinfo_.first_packet = TRUE; - rev_statinfo_.first_packet = TRUE; + fwd_statinfo_.first_packet = true; + rev_statinfo_.first_packet = true; fwd_statinfo_.reg_pt = PT_UNDEFINED; rev_statinfo_.reg_pt = PT_UNDEFINED; @@ -703,17 +701,17 @@ void Iax2AnalysisDialog::addPacket(bool forward, packet_info *pinfo, const struc } // iax2_analysis.c:rtp_packet_save_payload -const guint8 silence_pcmu_ = 0xff; -const guint8 silence_pcma_ = 0x55; +const uint8_t silence_pcmu_ = 0xff; +const uint8_t silence_pcma_ = 0x55; void Iax2AnalysisDialog::savePayload(QTemporaryFile *tmpfile, packet_info *pinfo, const struct _iax2_info_t *iax2info) { /* Is this the first packet we got in this direction? */ // if (statinfo->flags & STAT_FLAG_FIRST) { // if (saveinfo->fp == NULL) { -// saveinfo->saved = FALSE; +// saveinfo->saved = false; // saveinfo->error_type = TAP_RTP_FILE_OPEN_ERROR; // } else { -// saveinfo->saved = TRUE; +// saveinfo->saved = true; // } // } @@ -896,9 +894,9 @@ void Iax2AnalysisDialog::saveAudio(Iax2AnalysisDialog::StreamDirection direction } QFile save_file(file_path); - gint16 sample; - guint8 pd[4]; - gboolean stop_flag = FALSE; + int16_t sample; + uint8_t pd[4]; + bool stop_flag = false; qint64 nchars; save_file.open(QIODevice::WriteOnly); @@ -1009,16 +1007,16 @@ void Iax2AnalysisDialog::saveAudio(Iax2AnalysisDialog::StreamDirection direction case dir_both_: { char f_rawvalue, r_rawvalue; - guint32 f_write_silence = 0; - guint32 r_write_silence = 0; + uint32_t f_write_silence = 0; + uint32_t r_write_silence = 0; /* since conversation in one way can start later than in the other one, * we have to write some silence information for one channel */ if (fwd_statinfo_.start_time > rev_statinfo_.start_time) { - f_write_silence = (guint32) + f_write_silence = (uint32_t) ((fwd_statinfo_.start_time - rev_statinfo_.start_time) * (8000/1000)); } else if (fwd_statinfo_.start_time < rev_statinfo_.start_time) { - r_write_silence = (guint32) + r_write_silence = (uint32_t) ((rev_statinfo_.start_time - fwd_statinfo_.start_time) * (8000/1000)); } @@ -1222,16 +1220,14 @@ bool Iax2AnalysisDialog::eventFilter(QObject *, QEvent *event) return false; } -void Iax2AnalysisDialog::graphClicked(QMouseEvent *event) +void Iax2AnalysisDialog::showGraphMenu(const QPoint &pos) +{ + graph_ctx_menu_.popup(ui->streamGraph->mapToGlobal(pos)); +} + +void Iax2AnalysisDialog::graphClicked(QMouseEvent *) { updateWidgets(); - if (event->button() == Qt::RightButton) { -#if QT_VERSION >= QT_VERSION_CHECK(6, 0 ,0) - graph_ctx_menu_.popup(event->globalPosition().toPoint()); -#else - graph_ctx_menu_.popup(event->globalPos()); -#endif - } } void Iax2AnalysisDialog::showStreamMenu(QPoint pos) diff --git a/ui/qt/iax2_analysis_dialog.h b/ui/qt/iax2_analysis_dialog.h index c6daedd0..b1d40331 100644 --- a/ui/qt/iax2_analysis_dialog.h +++ b/ui/qt/iax2_analysis_dialog.h @@ -17,8 +17,6 @@ #include -#include - #include #include "ui/tap-iax2-analysis.h" @@ -74,6 +72,7 @@ private slots: void on_actionSaveGraph_triggered(); void on_buttonBox_helpRequested(); void showStreamMenu(QPoint pos); + void showGraphMenu(const QPoint &pos); void graphClicked(QMouseEvent *event); private: @@ -120,8 +119,8 @@ private: void saveCsv(StreamDirection direction); #if 0 - guint32 processNode(proto_node *ptree_node, header_field_info *hfinformation, const gchar* proto_field, bool *ok); - guint32 getIntFromProtoTree(proto_tree *protocol_tree, const gchar *proto_name, const gchar *proto_field, bool *ok); + uint32_t processNode(proto_node *ptree_node, header_field_info *hfinformation, const char* proto_field, bool *ok); + uint32_t getIntFromProtoTree(proto_tree *protocol_tree, const char *proto_name, const char *proto_field, bool *ok); #endif bool eventFilter(QObject*, QEvent* event); diff --git a/ui/qt/import_text_dialog.cpp b/ui/qt/import_text_dialog.cpp index 0916c417..17c1734d 100644 --- a/ui/qt/import_text_dialog.cpp +++ b/ui/qt/import_text_dialog.cpp @@ -14,8 +14,6 @@ #include "wiretap/wtap.h" #include "wiretap/pcap-encap.h" -#include - #include "ui/text_import_scanner.h" #include "ui/util.h" #include "ui/alert_box.h" @@ -26,8 +24,8 @@ #include "wsutil/file_util.h" #include "wsutil/inet_addr.h" #include "wsutil/time_util.h" -#include "wsutil/tempfile.h" #include "wsutil/filesystem.h" +#include #include #include "main_application.h" @@ -127,7 +125,7 @@ ImportTextDialog::ImportTextDialog(QWidget *parent) : {"Plain bin", ENCODING_PLAIN_BIN}, {"Base 64", ENCODING_BASE64} }; - for (i = 0; i < (int) (sizeof(encodings) / sizeof(encodings[0])); ++i) { + for (i = 0; i < (int)array_length(encodings); ++i) { ti_ui_->dataEncodingComboBox->addItem(encodings[i].name, QVariant(encodings[i].id)); } @@ -185,7 +183,7 @@ ImportTextDialog::~ImportTextDialog() void ImportTextDialog::loadSettingsFile() { - QFileInfo fileInfo(gchar_free_to_qstring(get_profile_dir(get_profile_name(), FALSE)), QString(SETTINGS_FILE)); + QFileInfo fileInfo(gchar_free_to_qstring(get_profile_dir(get_profile_name(), false)), QString(SETTINGS_FILE)); QFile loadFile(fileInfo.filePath()); if (!fileInfo.exists() || !fileInfo.isFile()) { @@ -202,7 +200,7 @@ void ImportTextDialog::loadSettingsFile() void ImportTextDialog::saveSettingsFile() { - QFileInfo fileInfo(gchar_free_to_qstring(get_profile_dir(get_profile_name(), FALSE)), QString(SETTINGS_FILE)); + QFileInfo fileInfo(gchar_free_to_qstring(get_profile_dir(get_profile_name(), false)), QString(SETTINGS_FILE)); QFile saveFile(fileInfo.filePath()); if (fileInfo.exists() && !fileInfo.isFile()) { @@ -407,7 +405,7 @@ int ImportTextDialog::exec() { char* tmp; GError* gerror = NULL; int err; - gchar *err_info; + char *err_info; wtap_dump_params params; int file_type_subtype; QString interface_name; @@ -427,10 +425,12 @@ int ImportTextDialog::exec() { import_info_.import_text_filename = qstring_strdup(ti_ui_->textFileLineEdit->text()); import_info_.timestamp_format = qstring_strdup(ti_ui_->timestampFormatLineEdit->text()); if (strlen(import_info_.timestamp_format) == 0) { - g_free((gpointer) import_info_.timestamp_format); + g_free((void *) import_info_.timestamp_format); import_info_.timestamp_format = NULL; } + mainApp->setLastOpenDirFromFilename(QString(import_info_.import_text_filename)); + switch (import_info_.mode) { default: /* should never happen */ setResult(QDialog::Rejected); @@ -438,7 +438,7 @@ int ImportTextDialog::exec() { case TEXT_IMPORT_HEXDUMP: import_info_.hexdump.import_text_FILE = ws_fopen(import_info_.import_text_filename, "rb"); if (!import_info_.hexdump.import_text_FILE) { - open_failure_alert_box(import_info_.import_text_filename, errno, FALSE); + open_failure_alert_box(import_info_.import_text_filename, errno, false); setResult(QDialog::Rejected); goto cleanup_mode; } @@ -452,7 +452,7 @@ int ImportTextDialog::exec() { case TEXT_IMPORT_REGEX: import_info_.regex.import_text_GMappedFile = g_mapped_file_new(import_info_.import_text_filename, true, &gerror); if (gerror) { - open_failure_alert_box(import_info_.import_text_filename, gerror->code, FALSE); + open_failure_alert_box(import_info_.import_text_filename, gerror->code, false); g_error_free(gerror); setResult(QDialog::Rejected); goto cleanup_mode; @@ -539,7 +539,7 @@ int ImportTextDialog::exec() { wtap_free_idb_info(params.idb_inf); wtap_dump_params_cleanup(¶ms); g_free(tmp); - g_free((gpointer) import_info_.payload); + g_free((void *) import_info_.payload); switch (import_info_.mode) { case TEXT_IMPORT_HEXDUMP: fclose(import_info_.hexdump.import_text_FILE); @@ -547,13 +547,13 @@ int ImportTextDialog::exec() { case TEXT_IMPORT_REGEX: g_mapped_file_unref(import_info_.regex.import_text_GMappedFile); g_regex_unref((GRegex*) import_info_.regex.format); - g_free((gpointer) import_info_.regex.in_indication); - g_free((gpointer) import_info_.regex.out_indication); + g_free((void *) import_info_.regex.in_indication); + g_free((void *) import_info_.regex.out_indication); break; } cleanup_mode: - g_free((gpointer) import_info_.import_text_filename); - g_free((gpointer) import_info_.timestamp_format); + g_free((void *) import_info_.import_text_filename); + g_free((void *) import_info_.timestamp_format); return result(); } @@ -606,26 +606,7 @@ void ImportTextDialog::on_textFileBrowseButton_clicked() if (ti_ui_->textFileLineEdit->text().length() > 0) { open_dir = ti_ui_->textFileLineEdit->text(); } else { - switch (prefs.gui_fileopen_style) { - - case FO_STYLE_LAST_OPENED: - /* The user has specified that we should start out in the last directory - we looked in. If we've already opened a file, use its containing - directory, if we could determine it, as the directory, otherwise - use the "last opened" directory saved in the preferences file if - there was one. */ - /* This is now the default behaviour in file_selection_new() */ - open_dir = get_open_dialog_initial_dir(); - break; - - case FO_STYLE_SPECIFIED: - /* The user has specified that we should always start out in a - specified directory; if they've specified that directory, - start out by showing the files in that dir. */ - if (prefs.gui_fileopen_dir[0] != '\0') - open_dir = prefs.gui_fileopen_dir; - break; - } + open_dir = get_open_dialog_initial_dir(); } QString file_name = WiresharkFileDialog::getOpenFileName(this, mainApp->windowTitleString(tr("Import Text File")), open_dir); @@ -637,7 +618,7 @@ bool ImportTextDialog::checkDateTimeFormat(const QString &time_format) /* nonstandard is f for fractions of seconds */ const QString valid_code = "aAbBcdDFfHIjmMpsSTUwWxXyYzZ%"; int idx = 0; - int ret = false; + bool ret = false; /* XXX: Temporary(?) hack to allow ISO format time, a checkbox is * probably better */ @@ -742,7 +723,7 @@ void ImportTextDialog::on_asciiIdentificationCheckBox_toggled(bool checked) void ImportTextDialog::on_regexTextEdit_textChanged() { - gchar* regex_gchar_p = qstring_strdup(ti_ui_->regexTextEdit->toPlainText());; + char* regex_gchar_p = qstring_strdup(ti_ui_->regexTextEdit->toPlainText()); GError* gerror = NULL; /* TODO: Use GLib's c++ interface or enable C++ int to enum casting * because the flags are declared as enum, so we can't pass 0 like @@ -953,7 +934,7 @@ void ImportTextDialog::on_ipVersionComboBox_currentIndexChanged(int index) on_destinationAddressLineEdit_textChanged(ti_ui_->destinationAddressLineEdit->text()); } -void ImportTextDialog::check_line_edit(SyntaxLineEdit *le, bool &ok_enabled, const QString &num_str, int base, guint max_val, bool is_short, guint *val_ptr) { +void ImportTextDialog::check_line_edit(SyntaxLineEdit *le, bool &ok_enabled, const QString &num_str, int base, unsigned max_val, bool is_short, unsigned *val_ptr) { bool conv_ok; SyntaxLineEdit::SyntaxState syntax_state = SyntaxLineEdit::Empty; @@ -967,7 +948,7 @@ void ImportTextDialog::check_line_edit(SyntaxLineEdit *le, bool &ok_enabled, con if (is_short) { *val_ptr = num_str.toUShort(&conv_ok, base); } else { - *val_ptr = (guint)num_str.toULong(&conv_ok, base); + *val_ptr = (unsigned)num_str.toULong(&conv_ok, base); } if (conv_ok && *val_ptr <= max_val) { syntax_state = SyntaxLineEdit::Valid; diff --git a/ui/qt/import_text_dialog.h b/ui/qt/import_text_dialog.h index ac9537d9..d2fe13cb 100644 --- a/ui/qt/import_text_dialog.h +++ b/ui/qt/import_text_dialog.h @@ -14,8 +14,6 @@ #include -#include - #include "ui/text_import.h" #include @@ -44,7 +42,7 @@ private: /* regex fields */ void enableFieldWidgets(bool enable_direction_input = true, bool enable_time_input = true); - void check_line_edit(SyntaxLineEdit *le, bool &ok_enable, const QString &num_str, int base, guint max_val, bool is_short, guint *val_ptr); + void check_line_edit(SyntaxLineEdit *le, bool &ok_enable, const QString &num_str, int base, unsigned max_val, bool is_short, unsigned *val_ptr); void checkAddress(SyntaxLineEdit *le, bool &ok_enable, const QString &addr_str, ws_in4_addr *val_ptr); void checkIPv6Address(SyntaxLineEdit *le, bool &ok_enable, const QString &addr_str, ws_in6_addr *val_ptr); bool checkDateTimeFormat(const QString &time_format); diff --git a/ui/qt/interface_frame.cpp b/ui/qt/interface_frame.cpp index b1f34b22..ba2d42e0 100644 --- a/ui/qt/interface_frame.cpp +++ b/ui/qt/interface_frame.cpp @@ -32,6 +32,7 @@ #include #include "capture_opts.h" #include "ui/capture_globals.h" +#include #include #include @@ -41,6 +42,8 @@ #include #include #include +#include +#include #include @@ -51,6 +54,8 @@ const int stat_update_interval_ = 1000; // ms #endif const char *no_capture_link = "#no_capture"; +static QMutex scan_mutex; + InterfaceFrame::InterfaceFrame(QWidget * parent) : QFrame(parent), ui(new Ui::InterfaceFrame) @@ -205,6 +210,27 @@ void InterfaceFrame::showEvent(QShowEvent *) { #endif // HAVE_LIBPCAP } +#ifdef HAVE_LIBPCAP +void InterfaceFrame::scanLocalInterfaces(GList *filter_list) +{ + GList *if_list = NULL; + if (scan_mutex.tryLock()) { + if (isVisible()) { + source_model_.stopStatistic(); + if_stat_cache_t * stat_cache = capture_interface_stat_start(&global_capture_opts, &if_list); + source_model_.setCache(stat_cache); + } + mainApp->setInterfaceList(if_list); + free_interface_list(if_list); + scan_local_interfaces_filtered(filter_list, main_window_update); + mainApp->emitAppSignal(MainApplication::LocalInterfacesChanged); + scan_mutex.unlock(); + } else { + qDebug() << "scan mutex locked, can't scan interfaces"; + } +} +#endif // HAVE_LIBPCAP + void InterfaceFrame::actionButton_toggled(bool checked) { QVariant ifType = sender()->property(BTN_IFTYPE_PROPERTY); @@ -422,7 +448,7 @@ void InterfaceFrame::on_interfaceTree_doubleClicked(const QModelIndex &index) interfaces << device_name; /* We trust the string here. If this interface is really extcap, the string is - * being checked immediatly before the dialog is being generated */ + * being checked immediately before the dialog is being generated */ if (extcap_string.length() > 0) { /* this checks if configuration is required and not yet provided or saved via prefs */ @@ -454,7 +480,7 @@ void InterfaceFrame::on_interfaceTree_clicked(const QModelIndex &index) QString extcap_string = source_model_.getColumnContent(realIndex.row(), IFTREE_COL_EXTCAP_PATH).toString(); /* We trust the string here. If this interface is really extcap, the string is - * being checked immediatly before the dialog is being generated */ + * being checked immediately before the dialog is being generated */ if (extcap_string.length() > 0) { /* this checks if configuration is required and not yet provided or saved via prefs */ @@ -534,7 +560,7 @@ void InterfaceFrame::showContextMenu(QPoint pos) void InterfaceFrame::on_warningLabel_linkActivated(const QString &link) { if (link.compare(no_capture_link) == 0) { - recent.sys_warn_if_no_capture = FALSE; + recent.sys_warn_if_no_capture = false; resetInterfaceTreeDisplay(); } else { QDesktopServices::openUrl(QUrl(link)); diff --git a/ui/qt/interface_frame.h b/ui/qt/interface_frame.h index f36ce945..211350e7 100644 --- a/ui/qt/interface_frame.h +++ b/ui/qt/interface_frame.h @@ -15,8 +15,6 @@ #include -#include - #include #include #include @@ -52,6 +50,9 @@ Q_SIGNALS: void typeSelectionChanged(); public slots: +#ifdef HAVE_LIBPCAP + void scanLocalInterfaces(GList *filter_list = nullptr); +#endif void updateSelectedInterfaces(); void interfaceListChanged(); void toggleHiddenInterfaces(); diff --git a/ui/qt/interface_toolbar.cpp b/ui/qt/interface_toolbar.cpp index be2cde66..e4472d8c 100644 --- a/ui/qt/interface_toolbar.cpp +++ b/ui/qt/interface_toolbar.cpp @@ -79,7 +79,7 @@ InterfaceToolbar::InterfaceToolbar(QWidget *parent, const iface_toolbar *toolbar // Fill inn interfaces list and initialize default interface values for (GList *walker = toolbar->ifnames; walker; walker = walker->next) { - QString ifname((gchar *)walker->data); + QString ifname((char *)walker->data); interface_[ifname].reader_thread = NULL; interface_[ifname].out_fd = -1; } @@ -193,14 +193,14 @@ QWidget *InterfaceToolbar::createCheckbox(iface_toolbar_control *control) QWidget *InterfaceToolbar::createButton(iface_toolbar_control *control) { - QPushButton *button = new QPushButton(QString().fromUtf8((gchar *)control->display)); + QPushButton *button = new QPushButton(QString().fromUtf8((char *)control->display)); button->setMaximumHeight(27); button->setToolTip(QString().fromUtf8(control->tooltip)); switch (control->ctrl_role) { case INTERFACE_ROLE_CONTROL: - setDefaultValue(control->num, (gchar *)control->display); + setDefaultValue(control->num, (char *)control->display); connect(button, SIGNAL(clicked()), this, SLOT(onControlButtonClicked())); break; @@ -242,13 +242,13 @@ QWidget *InterfaceToolbar::createSelector(iface_toolbar_control *control) for (GList *walker = control->values; walker; walker = walker->next) { iface_toolbar_value *val = (iface_toolbar_value *)walker->data; - QString value = QString().fromUtf8((gchar *)val->value); + QString value = QString().fromUtf8((char *)val->value); if (value.isEmpty()) { // Invalid value continue; } - QString display = QString().fromUtf8((gchar *)val->display); + QString display = QString().fromUtf8((char *)val->display); QByteArray interface_value; interface_value.append(value.toUtf8()); @@ -746,7 +746,7 @@ void InterfaceToolbar::startCapture(GArray *ifaces) QString first_capturing_ifname; bool selected_found = false; - for (guint i = 0; i < ifaces->len; i++) + for (unsigned i = 0; i < ifaces->len; i++) { interface_options *interface_opts = &g_array_index(ifaces, interface_options, i); QString ifname(interface_opts->name); @@ -774,7 +774,7 @@ void InterfaceToolbar::startCapture(GArray *ifaces) // The control out pipe will close when both out_fd and extcap_control_out_h are closed. HANDLE duplicate_out_handle = INVALID_HANDLE_VALUE; if (!DuplicateHandle(GetCurrentProcess(), interface_opts->extcap_control_out_h, - GetCurrentProcess(), &duplicate_out_handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) + GetCurrentProcess(), &duplicate_out_handle, 0, true, DUPLICATE_SAME_ACCESS)) { simple_dialog_async(ESD_TYPE_ERROR, ESD_BTN_OK, "Failed to duplicate extcap control out handle: %s\n.", @@ -962,7 +962,7 @@ void InterfaceToolbar::interfaceListChanged() ui->interfacesComboBox->blockSignals(true); ui->interfacesComboBox->clear(); - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (device->hidden) diff --git a/ui/qt/interface_toolbar.h b/ui/qt/interface_toolbar.h index f9879fa2..fc20c197 100644 --- a/ui/qt/interface_toolbar.h +++ b/ui/qt/interface_toolbar.h @@ -10,8 +10,6 @@ #ifndef INTERFACE_TOOLBAR_H #define INTERFACE_TOOLBAR_H -#include - #include "ui/iface_toolbar.h" #include "funnel_text_dialog.h" #include "interface_toolbar_reader.h" diff --git a/ui/qt/interface_toolbar_reader.cpp b/ui/qt/interface_toolbar_reader.cpp index d12f7472..6b5c1f1a 100644 --- a/ui/qt/interface_toolbar_reader.cpp +++ b/ui/qt/interface_toolbar_reader.cpp @@ -34,7 +34,7 @@ int InterfaceToolbarReader::async_pipe_read(void *data, int nbyte) int bytes_read = -1; overlap.Pointer = 0; - overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + overlap.hEvent = CreateEvent(NULL, true, false, NULL); if (overlap.hEvent == NULL) { // CreateEvent failed with error code GetLastError() @@ -54,7 +54,7 @@ int InterfaceToolbarReader::async_pipe_read(void *data, int nbyte) if (WaitForSingleObject(overlap.hEvent, INFINITE) == WAIT_OBJECT_0) { // The wait operation has completed. - success = GetOverlappedResult(control_in_, &overlap, &nof_bytes_read, FALSE); + success = GetOverlappedResult(control_in_, &overlap, &nof_bytes_read, false); if (success && nof_bytes_read != 0) { diff --git a/ui/qt/io_console_dialog.cpp b/ui/qt/io_console_dialog.cpp index 92d4c542..600a544b 100644 --- a/ui/qt/io_console_dialog.cpp +++ b/ui/qt/io_console_dialog.cpp @@ -44,6 +44,7 @@ IOConsoleDialog::IOConsoleDialog(QWidget &parent, title = QString("Console"); loadGeometry(0, 0, title); + loadSplitterState(ui->splitter); setWindowTitle(mainApp->windowTitleString(title)); QPushButton *eval_button = ui->buttonBox->addButton(tr("Evaluate"), QDialogButtonBox::ActionRole); diff --git a/ui/qt/io_graph_action.cpp b/ui/qt/io_graph_action.cpp new file mode 100644 index 00000000..777f87b1 --- /dev/null +++ b/ui/qt/io_graph_action.cpp @@ -0,0 +1,134 @@ +/* @file + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "io_graph_action.h" + +#include +#include +#include +#include + +#include + +#include + +#include + +IOGraphAction::IOGraphAction(QObject *parent, io_graph_item_unit_t unit, QString field) : + QAction(parent), + unit_(unit), + field_(field) +{ + setText(unitName(unit)); + connect(this, &QAction::triggered, [&](){ emit openIOGraphDialog(unit_, field_); }); +} + +const QString IOGraphAction::unitName(io_graph_item_unit_t unit) { + switch (unit) { + case IOG_ITEM_UNIT_PACKETS: + if (is_packet_configuration_namespace()) { + return QObject::tr("PACKETS"); + } + return QObject::tr("EVENTS"); + case IOG_ITEM_UNIT_BYTES: + return QObject::tr("BYTES"); + case IOG_ITEM_UNIT_BITS: + return QObject::tr("BITS"); + case IOG_ITEM_UNIT_CALC_FRAMES: + return QObject::tr("COUNT FRAMES"); + case IOG_ITEM_UNIT_CALC_FIELDS: + return QObject::tr("COUNT FIELDS"); + case IOG_ITEM_UNIT_CALC_SUM: + return QObject::tr("SUM"); + case IOG_ITEM_UNIT_CALC_MAX: + return QObject::tr("MAX"); + case IOG_ITEM_UNIT_CALC_MIN: + return QObject::tr("MIN"); + case IOG_ITEM_UNIT_CALC_AVERAGE: + return QObject::tr("AVERAGE"); + case IOG_ITEM_UNIT_CALC_THROUGHPUT: + return QObject::tr("THROUGHPUT"); + case IOG_ITEM_UNIT_CALC_LOAD: + return QObject::tr("LOAD"); + default: + return QObject::tr("UNKNOWN"); + } +} + +QList IOGraphAction::unitTypes(const FieldInformation::HeaderInfo& headerinfo) +{ + static const QList simple_types_ = QList() + << IOG_ITEM_UNIT_CALC_FRAMES + << IOG_ITEM_UNIT_CALC_FIELDS; + + static const QList number_types_ = QList() + << IOG_ITEM_UNIT_CALC_SUM + << IOG_ITEM_UNIT_CALC_FRAMES + << IOG_ITEM_UNIT_CALC_FIELDS + << IOG_ITEM_UNIT_CALC_MAX + << IOG_ITEM_UNIT_CALC_MIN + << IOG_ITEM_UNIT_CALC_THROUGHPUT + << IOG_ITEM_UNIT_CALC_AVERAGE; + + static const QList time_types_ = QList(number_types_) + << IOG_ITEM_UNIT_CALC_LOAD; + + switch (headerinfo.type) { + case FT_UINT8: + case FT_UINT16: + case FT_UINT24: + case FT_UINT32: + case FT_UINT64: + case FT_INT8: + case FT_INT16: + case FT_INT24: + case FT_INT32: + case FT_INT64: + case FT_FLOAT: + case FT_DOUBLE: + return number_types_; + case FT_RELATIVE_TIME: + return time_types_; + default: + return simple_types_; + } +} + +QMenu * IOGraphAction::createMenu(const FieldInformation::HeaderInfo& headerinfo, QWidget * parent) +{ + MainWindow *mw(nullptr); + if (mainApp) + { + QWidget * mainWin = mainApp->mainWindow(); + if (qobject_cast(mainWin)) { + mw = qobject_cast(mainWin); + } + } + + QString title("I/O Graph"); + QMenu * submenu = new QMenu(title, parent); + + int one_em = submenu->fontMetrics().height(); + QString prep_text = QString("%1: %2").arg(title).arg(headerinfo.abbreviation); + prep_text = submenu->fontMetrics().elidedText(prep_text, Qt::ElideRight, one_em * 40); + QAction * comment = submenu->addAction(prep_text); + comment->setEnabled(false); + submenu->addSeparator(); + + IOGraphAction *graphAction; + for (const auto &unit : IOGraphAction::unitTypes(headerinfo)) { + graphAction = new IOGraphAction(submenu, unit, headerinfo.abbreviation); + if (mw) { + connect(graphAction, &IOGraphAction::openIOGraphDialog, mw, &MainWindow::showIOGraphDialog); + } + submenu->addAction(graphAction); + } + + return submenu; +} diff --git a/ui/qt/io_graph_action.h b/ui/qt/io_graph_action.h new file mode 100644 index 00000000..290f1880 --- /dev/null +++ b/ui/qt/io_graph_action.h @@ -0,0 +1,47 @@ +/** @file + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef IO_GRAPH_ACTION_H +#define IO_GRAPH_ACTION_H + +#include +#include + +#include + +class IOGraphAction : public QAction +{ + Q_OBJECT +public: + explicit IOGraphAction(QObject *parent, io_graph_item_unit_t unit = IOG_ITEM_UNIT_PACKETS, QString field = QString()); + explicit IOGraphAction(QObject *parent); + + io_graph_item_unit_t unit() const { return unit_; } + + QString valueField() const { return field_; } + + static const QString unitName(io_graph_item_unit_t unit); + + static QList unitTypes(const FieldInformation::HeaderInfo& headerinfo); + static QMenu * createMenu(const FieldInformation::HeaderInfo& headerinfo, QWidget * parent); + +signals: + void openIOGraphDialog(io_graph_item_unit_t, QString); + +public slots: + +private: + io_graph_item_unit_t unit_; + QString field_; + +private slots: + +}; + +#endif // IO_GRAPH_ACTION_H diff --git a/ui/qt/io_graph_dialog.cpp b/ui/qt/io_graph_dialog.cpp index 002b98f9..8e7821a4 100644 --- a/ui/qt/io_graph_dialog.cpp +++ b/ui/qt/io_graph_dialog.cpp @@ -7,13 +7,14 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ +#define WS_LOG_DOMAIN LOG_DOMAIN_QTUI #include "io_graph_dialog.h" #include #include "file.h" +#include "locale.h" #include -#include "epan/stats_tree_priv.h" #include "epan/uat-int.h" #include @@ -25,11 +26,16 @@ #include #include +#include +#include #include "progress_frame.h" #include "main_application.h" +#include #include #include +#include +#include #include //provides some default colors #include @@ -47,6 +53,8 @@ #include #include +#include // std::bad_alloc + // Bugs and uncertainties: // - Regular (non-stacked) bar graphs are drawn on top of each other on the Z axis. // The QCP forum suggests drawing them side by side: @@ -54,15 +62,30 @@ // - We retap and redraw more than we should. // - Smoothing doesn't seem to match GTK+ // - Closing the color picker on macOS sends the dialog to the background. -// - The color picker triggers https://bugreports.qt.io/browse/QTBUG-58699. +// - X-axis time buckets are based on the file relative time, even in +// Time of Day / absolute time mode. (See io_graph_item.c/get_io_graph_index) +// Changing this would mean retapping when switching to ToD mode, though. // To do: // - Use scroll bars? -// - Scroll during live captures +// https://www.qcustomplot.com/index.php/tutorials/specialcases/scrollbar +// - Scroll during live captures (currently the graph auto rescales instead) // - Set ticks per pixel (e.g. pressing "2" sets 2 tpp). // - Explicitly handle missing values, e.g. via NAN. // - Add a "show missing" or "show zero" option to the UAT? // It would add yet another graph configuration column. +// - Increase max number of items (or make configurable) +// - Dark Mode support, e.g. +// https://www.qcustomplot.com/index.php/demos/barchartdemo +// - Multiple y-axes? +// https://www.qcustomplot.com/index.php/demos/multiaxisdemo +// https://www.qcustomplot.com/index.php/tutorials/specialcases/axistags + +// Scale factor to convert the units the interval is stored in to seconds. +// Must match what get_io_graph_index() in io_graph_item expects. +// Increase this in order to make smaller intervals possible. +const int SCALE = 1000000; +const double SCALE_F = (double)SCALE; const qreal graph_line_width_ = 1.0; @@ -77,15 +100,15 @@ const int stat_update_interval_ = 200; // ms // Saved graph settings typedef struct _io_graph_settings_t { - gboolean enabled; + bool enabled; char* name; char* dfilter; - guint color; - guint32 style; - guint32 yaxis; + unsigned color; + uint32_t style; + uint32_t yaxis; char* yfield; - guint32 sma_period; - guint32 y_axis_factor; + uint32_t sma_period; + uint32_t y_axis_factor; } io_graph_settings_t; static const value_string graph_style_vs[] = { @@ -105,7 +128,7 @@ static const value_string graph_style_vs[] = { { 0, NULL } }; -static const value_string y_axis_vs[] = { +static const value_string y_axis_packet_vs[] = { { IOG_ITEM_UNIT_PACKETS, "Packets" }, { IOG_ITEM_UNIT_BYTES, "Bytes" }, { IOG_ITEM_UNIT_BITS, "Bits" }, @@ -115,10 +138,25 @@ static const value_string y_axis_vs[] = { { IOG_ITEM_UNIT_CALC_MAX, "MAX(Y Field)" }, { IOG_ITEM_UNIT_CALC_MIN, "MIN(Y Field)" }, { IOG_ITEM_UNIT_CALC_AVERAGE, "AVG(Y Field)" }, + { IOG_ITEM_UNIT_CALC_THROUGHPUT, "THROUGHPUT(Y Field)" }, { IOG_ITEM_UNIT_CALC_LOAD, "LOAD(Y Field)" }, { 0, NULL } }; +static const value_string y_axis_event_vs[] = { + { IOG_ITEM_UNIT_PACKETS, "Events" }, + y_axis_packet_vs[1], + y_axis_packet_vs[2], + y_axis_packet_vs[3], + y_axis_packet_vs[4], + y_axis_packet_vs[5], + y_axis_packet_vs[6], + y_axis_packet_vs[7], + y_axis_packet_vs[8], + y_axis_packet_vs[9], + { 0, NULL } +}; + static const value_string moving_avg_vs[] = { { 0, "None" }, { 10, "10 interval SMA" }, @@ -131,24 +169,31 @@ static const value_string moving_avg_vs[] = { { 0, NULL } }; -static io_graph_settings_t *iog_settings_ = NULL; -static guint num_io_graphs_ = 0; -static uat_t *iog_uat_ = NULL; +static io_graph_settings_t *iog_settings_; +static unsigned num_io_graphs_; +static uat_t *iog_uat_; +// XXX - Multiple UatModels with the same uat can crash if one is +// edited, because the underlying uat_t* data changes but the +// record_errors and dirty_records lists do not. +static QPointer static_uat_model_; // y_axis_factor was added in 3.6. Provide backward compatibility. static const char *iog_uat_defaults_[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "1" }; +static char *decimal_point; + extern "C" { -//Allow the enable/disable field to be a checkbox, but for backwards compatibility, -//the strings have to be "Enabled"/"Disabled", not "TRUE"/"FALSE" +//Allow the enable/disable field to be a checkbox, but for backwards +//compatibility with pre-2.6 versions, the strings are "Enabled"/"Disabled", +//not "true"/"false". (Pre-4.4 versions require "true" to be all-caps.) #define UAT_BOOL_ENABLE_CB_DEF(basename,field_name,rec_t) \ -static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ +static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ char* tmp_str = g_strndup(buf,len); \ - if ((g_strcmp0(tmp_str, "Enabled") == 0) || \ - (g_strcmp0(tmp_str, "TRUE") == 0)) \ + if (tmp_str && ((g_strcmp0(tmp_str, "Enabled") == 0) || \ + (g_ascii_strcasecmp(tmp_str, "true") == 0))) \ ((rec_t*)rec)->field_name = 1; \ else \ ((rec_t*)rec)->field_name = 0; \ @@ -157,32 +202,33 @@ static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, *out_ptr = ws_strdup_printf("%s",((rec_t*)rec)->field_name ? "Enabled" : "Disabled"); \ *out_len = (unsigned)strlen(*out_ptr); } -static bool uat_fld_chk_enable(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) +static bool uat_fld_chk_enable(void* u1 _U_, const char* strptr, unsigned len, const void* u2 _U_, const void* u3 _U_, char** err) { char* str = g_strndup(strptr,len); - if ((g_strcmp0(str, "Enabled") == 0) || + if (str && + ((g_strcmp0(str, "Enabled") == 0) || (g_strcmp0(str, "Disabled") == 0) || - (g_strcmp0(str, "TRUE") == 0) || //just for UAT functionality - (g_strcmp0(str, "FALSE") == 0)) { + (g_ascii_strcasecmp(str, "true") == 0) || //just for UAT functionality + (g_ascii_strcasecmp(str, "false") == 0))) { *err = NULL; g_free(str); - return TRUE; + return true; } //User should never see this unless they are manually modifying UAT *err = ws_strdup_printf("invalid value: %s (must be Enabled or Disabled)", str); g_free(str); - return FALSE; + return false; } #define UAT_FLD_BOOL_ENABLE(basename,field_name,title,desc) \ {#field_name, title, PT_TXTMOD_BOOL,{uat_fld_chk_enable,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} //"Custom" handler for sma_period enumeration for backwards compatibility -static void io_graph_sma_period_set_cb(void* rec, const char* buf, guint len, const void* vs, const void* u2 _U_) +static void io_graph_sma_period_set_cb(void* rec, const char* buf, unsigned len, const void* vs, const void* u2 _U_) { - guint i; + unsigned i; char* str = g_strndup(buf,len); const char* cstr; ((io_graph_settings_t*)rec)->sma_period = 0; @@ -202,7 +248,7 @@ static void io_graph_sma_period_set_cb(void* rec, const char* buf, guint len, co for (i=0; (cstr = ((const value_string*)vs)[i].strptr) ;i++) { if (g_str_equal(cstr,str)) { - ((io_graph_settings_t*)rec)->sma_period = (guint32)((const value_string*)vs)[i].value; + ((io_graph_settings_t*)rec)->sma_period = (uint32_t)((const value_string*)vs)[i].value; g_free(str); return; } @@ -212,7 +258,7 @@ static void io_graph_sma_period_set_cb(void* rec, const char* buf, guint len, co //Duplicated because macro covers both functions static void io_graph_sma_period_tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* vs, const void* u2 _U_) { - guint i; + unsigned i; for (i=0;((const value_string*)vs)[i].strptr;i++) { if (((const value_string*)vs)[i].value == ((io_graph_settings_t*)rec)->sma_period) { *out_ptr = g_strdup(((const value_string*)vs)[i].strptr); @@ -224,9 +270,9 @@ static void io_graph_sma_period_tostr_cb(void* rec, char** out_ptr, unsigned* ou *out_len = (unsigned)strlen("None"); } -static bool sma_period_chk_enum(void* u1 _U_, const char* strptr, guint len, const void* v, const void* u3 _U_, char** err) { +static bool sma_period_chk_enum(void* u1 _U_, const char* strptr, unsigned len, const void* v, const void* u3 _U_, char** err) { char *str = g_strndup(strptr,len); - guint i; + unsigned i; const value_string* vs = (const value_string *)v; //Original UAT had just raw numbers and not enumerated values with "interval SMA" @@ -246,13 +292,13 @@ static bool sma_period_chk_enum(void* u1 _U_, const char* strptr, guint len, con if (g_strcmp0(vs[i].strptr,str) == 0) { *err = NULL; g_free(str); - return TRUE; + return true; } } *err = ws_strdup_printf("invalid value: %s",str); g_free(str); - return FALSE; + return false; } #define UAT_FLD_SMA_PERIOD(basename,field_name,title,enum,desc) \ @@ -263,18 +309,33 @@ UAT_BOOL_ENABLE_CB_DEF(io_graph, enabled, io_graph_settings_t) UAT_CSTRING_CB_DEF(io_graph, name, io_graph_settings_t) UAT_DISPLAY_FILTER_CB_DEF(io_graph, dfilter, io_graph_settings_t) UAT_COLOR_CB_DEF(io_graph, color, io_graph_settings_t) -UAT_VS_DEF(io_graph, style, io_graph_settings_t, guint32, 0, "Line") -UAT_VS_DEF(io_graph, yaxis, io_graph_settings_t, guint32, 0, "Packets") +UAT_VS_DEF(io_graph, style, io_graph_settings_t, uint32_t, 0, "Line") +// XXX Need to use "Events" where appropriate. +UAT_VS_DEF(io_graph, yaxis, io_graph_settings_t, uint32_t, 0, "Packets") UAT_PROTO_FIELD_CB_DEF(io_graph, yfield, io_graph_settings_t) UAT_DEC_CB_DEF(io_graph, y_axis_factor, io_graph_settings_t) -static uat_field_t io_graph_fields[] = { +static uat_field_t io_graph_packet_fields[] = { + UAT_FLD_BOOL_ENABLE(io_graph, enabled, "Enabled", "Graph visibility"), + UAT_FLD_CSTRING(io_graph, name, "Graph Name", "The name of the graph"), + UAT_FLD_DISPLAY_FILTER(io_graph, dfilter, "Display Filter", "Graph packets matching this display filter"), + UAT_FLD_COLOR(io_graph, color, "Color", "Graph color (#RRGGBB)"), + UAT_FLD_VS(io_graph, style, "Style", graph_style_vs, "Graph style (Line, Bars, etc.)"), + UAT_FLD_VS(io_graph, yaxis, "Y Axis", y_axis_packet_vs, "Y Axis units"), + UAT_FLD_PROTO_FIELD(io_graph, yfield, "Y Field", "Apply calculations to this field"), + UAT_FLD_SMA_PERIOD(io_graph, sma_period, "SMA Period", moving_avg_vs, "Simple moving average period"), + UAT_FLD_DEC(io_graph, y_axis_factor, "Y Axis Factor", "Y Axis Factor"), + + UAT_END_FIELDS +}; + +static uat_field_t io_graph_event_fields[] = { UAT_FLD_BOOL_ENABLE(io_graph, enabled, "Enabled", "Graph visibility"), UAT_FLD_CSTRING(io_graph, name, "Graph Name", "The name of the graph"), UAT_FLD_DISPLAY_FILTER(io_graph, dfilter, "Display Filter", "Graph packets matching this display filter"), UAT_FLD_COLOR(io_graph, color, "Color", "Graph color (#RRGGBB)"), UAT_FLD_VS(io_graph, style, "Style", graph_style_vs, "Graph style (Line, Bars, etc.)"), - UAT_FLD_VS(io_graph, yaxis, "Y Axis", y_axis_vs, "Y Axis units"), + UAT_FLD_VS(io_graph, yaxis, "Y Axis", y_axis_event_vs, "Y Axis units"), UAT_FLD_PROTO_FIELD(io_graph, yfield, "Y Field", "Apply calculations to this field"), UAT_FLD_SMA_PERIOD(io_graph, sma_period, "SMA Period", moving_avg_vs, "Simple moving average period"), UAT_FLD_DEC(io_graph, y_axis_factor, "Y Axis Factor", "Y Axis Factor"), @@ -306,16 +367,25 @@ static void io_graph_free_cb(void* p) { g_free(iogs->yfield); } +// If the uat changes outside the model, e.g. when changing profiles, +// we need to tell the UatModel. +static void io_graph_post_update_cb() { + if (static_uat_model_) { + static_uat_model_->reloadUat(); + } +} + } // extern "C" -IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf, QString displayFilter) : +IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf, QString displayFilter, + io_graph_item_unit_t value_units, QString yfield) : WiresharkDialog(parent, cf), ui(new Ui::IOGraphDialog), uat_model_(nullptr), uat_delegate_(nullptr), base_graph_(nullptr), tracer_(nullptr), - start_time_(0.0), + start_time_(NSTIME_INIT_ZERO), mouse_drags_(true), rubber_band_(nullptr), stat_timer_(nullptr), @@ -355,15 +425,17 @@ IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf, QString displayFi QPushButton *copy_bt = ui->buttonBox->addButton(tr("Copy"), QDialogButtonBox::ActionRole); connect (copy_bt, SIGNAL(clicked()), this, SLOT(copyAsCsvClicked())); - CopyFromProfileButton * copy_button = new CopyFromProfileButton(this, "io_graphs", tr("Copy graphs from another profile.")); - ui->buttonBox->addButton(copy_button, QDialogButtonBox::ActionRole); - connect(copy_button, &CopyFromProfileButton::copyProfile, this, &IOGraphDialog::copyFromProfile); + copy_profile_bt_ = new CopyFromProfileButton(this, "io_graphs", tr("Copy graphs from another profile.")); + ui->buttonBox->addButton(copy_profile_bt_, QDialogButtonBox::ActionRole); + connect(copy_profile_bt_, &CopyFromProfileButton::copyProfile, this, &IOGraphDialog::copyFromProfile); QPushButton *close_bt = ui->buttonBox->button(QDialogButtonBox::Close); if (close_bt) { close_bt->setDefault(true); } + connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &IOGraphDialog::buttonBoxClicked); + ui->automaticUpdateCheckBox->setChecked(prefs.gui_io_graph_automatic_update ? true : false); ui->enableLegendCheckBox->setChecked(prefs.gui_io_graph_enable_legend ? true : false); @@ -373,22 +445,38 @@ IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf, QString displayFi stat_timer_->start(stat_update_interval_); // Intervals (ms) - ui->intervalComboBox->addItem(tr("1 ms"), 1); - ui->intervalComboBox->addItem(tr("2 ms"), 2); - ui->intervalComboBox->addItem(tr("5 ms"), 5); - ui->intervalComboBox->addItem(tr("10 ms"), 10); - ui->intervalComboBox->addItem(tr("20 ms"), 20); - ui->intervalComboBox->addItem(tr("50 ms"), 50); - ui->intervalComboBox->addItem(tr("100 ms"), 100); - ui->intervalComboBox->addItem(tr("200 ms"), 200); - ui->intervalComboBox->addItem(tr("500 ms"), 500); - ui->intervalComboBox->addItem(tr("1 sec"), 1000); - ui->intervalComboBox->addItem(tr("2 sec"), 2000); - ui->intervalComboBox->addItem(tr("5 sec"), 5000); - ui->intervalComboBox->addItem(tr("10 sec"), 10000); - ui->intervalComboBox->addItem(tr("1 min"), 60000); - ui->intervalComboBox->addItem(tr("10 min"), 600000); - ui->intervalComboBox->setCurrentIndex(9); + // #6441 asks for arbitrary values. We could probably do that with + // a QSpinBox, e.g. using QAbstractSpinBox::AdaptiveDecimalStepType + // or similar (it only exists starting in Qt 5.12) and suffix(), + // or something fancier with valueFromText() and textFromValue() to + // convert to and from SI prefixes. + ui->intervalComboBox->addItem(tr("1 μs"), SCALE / 1000000); + ui->intervalComboBox->addItem(tr("2 μs"), SCALE / 500000); + ui->intervalComboBox->addItem(tr("5 μs"), SCALE / 200000); + ui->intervalComboBox->addItem(tr("10 μs"), SCALE / 100000); + ui->intervalComboBox->addItem(tr("20 μs"), SCALE / 50000); + ui->intervalComboBox->addItem(tr("50 μs"), SCALE / 20000); + ui->intervalComboBox->addItem(tr("100 μs"), SCALE / 10000); + ui->intervalComboBox->addItem(tr("200 μs"), SCALE / 5000); + ui->intervalComboBox->addItem(tr("500 μs"), SCALE / 2000); + ui->intervalComboBox->addItem(tr("1 ms"), SCALE / 1000); + ui->intervalComboBox->addItem(tr("2 ms"), SCALE / 500); + ui->intervalComboBox->addItem(tr("5 ms"), SCALE / 200); + ui->intervalComboBox->addItem(tr("10 ms"), SCALE / 100); + ui->intervalComboBox->addItem(tr("20 ms"), SCALE / 50); + ui->intervalComboBox->addItem(tr("50 ms"), SCALE / 20); + ui->intervalComboBox->addItem(tr("100 ms"), SCALE / 10); + ui->intervalComboBox->addItem(tr("200 ms"), SCALE / 5); + ui->intervalComboBox->addItem(tr("500 ms"), SCALE / 2); + ui->intervalComboBox->addItem(tr("1 sec"), SCALE); + ui->intervalComboBox->addItem(tr("2 sec"), SCALE * 2); + ui->intervalComboBox->addItem(tr("5 sec"), SCALE * 5); + ui->intervalComboBox->addItem(tr("10 sec"), SCALE * 10); + ui->intervalComboBox->addItem(tr("1 min"), SCALE * 60); + ui->intervalComboBox->addItem(tr("2 min"), SCALE * 120); + ui->intervalComboBox->addItem(tr("5 min"), SCALE * 300); + ui->intervalComboBox->addItem(tr("10 min"), SCALE * 600); + ui->intervalComboBox->setCurrentIndex(18); ui->todCheckBox->setChecked(false); iop->xAxis->setTicker(number_ticker_); @@ -419,6 +507,9 @@ IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf, QString displayFi ctx_menu_.addAction(ui->actionCrosshairs); set_action_shortcuts_visible_in_context_menu(ctx_menu_.actions()); + iop->setContextMenuPolicy(Qt::CustomContextMenu); + connect(iop, &QCustomPlot::customContextMenuRequested, this, &IOGraphDialog::showContextMenu); + iop->xAxis->setLabel(tr("Time (s)")); iop->setMouseTracking(true); @@ -433,22 +524,23 @@ IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf, QString displayFi loadProfileGraphs(); bool filterExists = false; - QString graph_name = is_packet_configuration_namespace() ? tr("Filtered packets") : tr("Filtered events"); if (uat_model_->rowCount() > 0) { for (int i = 0; i < uat_model_->rowCount(); i++) { createIOGraph(i); - if (ioGraphs_.at(i)->filter().compare(displayFilter) == 0) + IOGraph *iog = ioGraphs_.at(i); + if (iog->filter().compare(displayFilter) == 0 && + iog->valueUnitField().compare(yfield) == 0 && + iog->valueUnits() == value_units) { filterExists = true; + } } - if (! filterExists && displayFilter.length() > 0) - addGraph(true, graph_name, displayFilter, ColorUtils::graphColor(uat_model_->rowCount()), - IOGraph::psLine, IOG_ITEM_UNIT_PACKETS, QString(), DEFAULT_MOVING_AVERAGE, DEFAULT_Y_AXIS_FACTOR); } else { addDefaultGraph(true, 0); addDefaultGraph(true, 1); - if (displayFilter.length() > 0) - addGraph(true, graph_name, displayFilter, ColorUtils::graphColor(uat_model_->rowCount()), - IOGraph::psLine, IOG_ITEM_UNIT_PACKETS, QString(), DEFAULT_MOVING_AVERAGE, DEFAULT_Y_AXIS_FACTOR); + } + + if (! filterExists && (!displayFilter.isEmpty() || !yfield.isEmpty())) { + addGraph(true, displayFilter, value_units, yfield); } toggleTracerStyle(true); @@ -460,14 +552,23 @@ IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf, QString displayFi ui->splitter->setStretchFactor(0, 95); ui->splitter->setStretchFactor(1, 5); + loadSplitterState(ui->splitter); //XXX - resize columns? + //ui->graphUat->header()->resizeSections(QHeaderView::ResizeToContents); ProgressFrame::addToButtonBox(ui->buttonBox, &parent); connect(iop, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(graphClicked(QMouseEvent*))); connect(iop, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoved(QMouseEvent*))); connect(iop, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(mouseReleased(QMouseEvent*))); + + connect(iop, &QCustomPlot::beforeReplot, this, &IOGraphDialog::updateLegend); + + MainWindow *main_window = qobject_cast(mainApp->mainWindow()); + if (main_window != nullptr) { + connect(main_window, &MainWindow::framesSelected, this, &IOGraphDialog::selectedFrameChanged); + } } IOGraphDialog::~IOGraphDialog() @@ -482,15 +583,18 @@ IOGraphDialog::~IOGraphDialog() void IOGraphDialog::copyFromProfile(QString filename) { - guint orig_data_len = iog_uat_->raw_data->len; + if (uat_model_ == nullptr) + return; - gchar *err = NULL; + char *err = NULL; + // uat_load appends rows to the current UAT, using filename. + // We should let the UatModel handle it, and have the UatModel + // call beginInsertRows() and endInsertRows(), so that we can + // just add the new rows instead of resetting the information. if (uat_load(iog_uat_, filename.toUtf8().constData(), &err)) { - iog_uat_->changed = TRUE; - uat_model_->reloadUat(); - for (guint i = orig_data_len; i < iog_uat_->raw_data->len; i++) { - createIOGraph(i); - } + iog_uat_->changed = true; + // uat_load calls the post update cb, which reloads the Uat. + //uat_model_->reloadUat(); } else { report_failure("Error while loading %s: %s", iog_uat_->name, err); g_free(err); @@ -499,6 +603,8 @@ void IOGraphDialog::copyFromProfile(QString filename) void IOGraphDialog::addGraph(bool checked, QString name, QString dfilter, QRgb color_idx, IOGraph::PlotStyles style, io_graph_item_unit_t value_units, QString yfield, int moving_average, int y_axis_factor) { + if (uat_model_ == nullptr) + return; QVariantList newRowData; newRowData.append(checked ? Qt::Checked : Qt::Unchecked); @@ -507,12 +613,12 @@ void IOGraphDialog::addGraph(bool checked, QString name, QString dfilter, QRgb c newRowData.append(QColor(color_idx)); newRowData.append(val_to_str_const(style, graph_style_vs, "None")); if (is_packet_configuration_namespace()) { - newRowData.append(val_to_str_const(value_units, y_axis_vs, "Packets")); + newRowData.append(val_to_str_const(value_units, y_axis_packet_vs, "Packets")); } else { - newRowData.append(val_to_str_const(value_units, y_axis_vs, "Events")); + newRowData.append(val_to_str_const(value_units, y_axis_event_vs, "Events")); } newRowData.append(yfield); - newRowData.append(val_to_str_const((guint32) moving_average, moving_avg_vs, "None")); + newRowData.append(val_to_str_const((uint32_t) moving_average, moving_avg_vs, "None")); newRowData.append(y_axis_factor); QModelIndex newIndex = uat_model_->appendEntry(newRowData); @@ -522,11 +628,36 @@ void IOGraphDialog::addGraph(bool checked, QString name, QString dfilter, QRgb c return; } ui->graphUat->setCurrentIndex(newIndex); - createIOGraph(newIndex.row()); +} + +void IOGraphDialog::addGraph(bool checked, QString dfilter, io_graph_item_unit_t value_units, QString yfield) +{ + if (uat_model_ == nullptr) + return; + + QString graph_name; + if (yfield.isEmpty()) { + if (!dfilter.isEmpty()) { + graph_name = is_packet_configuration_namespace() ? tr("Filtered packets") : tr("Filtered events"); + } else { + graph_name = is_packet_configuration_namespace() ? tr("All packets") : tr("All events"); + } + } else { + if (is_packet_configuration_namespace()) { + graph_name = QString(val_to_str_const(value_units, y_axis_packet_vs, "Unknown")).replace("Y Field", yfield); + } else { + graph_name = QString(val_to_str_const(value_units, y_axis_event_vs, "Unknown")).replace("Y Field", yfield); + } + } + addGraph(checked, std::move(graph_name), dfilter, ColorUtils::graphColor(uat_model_->rowCount()), + IOGraph::psLine, value_units, yfield, DEFAULT_MOVING_AVERAGE, DEFAULT_Y_AXIS_FACTOR); } void IOGraphDialog::addGraph(bool copy_from_current) { + if (uat_model_ == nullptr) + return; + const QModelIndex ¤t = ui->graphUat->currentIndex(); if (copy_from_current && !current.isValid()) return; @@ -540,8 +671,6 @@ void IOGraphDialog::addGraph(bool copy_from_current) qDebug() << "Failed to add a new record"; return; } - createIOGraph(copyIdx.row()); - ui->graphUat->setCurrentIndex(copyIdx); } else { addDefaultGraph(false); @@ -553,22 +682,19 @@ void IOGraphDialog::addGraph(bool copy_from_current) void IOGraphDialog::createIOGraph(int currentRow) { - // XXX - Should IOGraph have it's own list that has to sync with UAT? - ioGraphs_.append(new IOGraph(ui->ioPlot)); + // XXX - Should IOGraph have its own list that has to sync with UAT? + ioGraphs_.insert(currentRow, new IOGraph(ui->ioPlot)); IOGraph* iog = ioGraphs_[currentRow]; - connect(this, SIGNAL(recalcGraphData(capture_file *, bool)), iog, SLOT(recalcGraphData(capture_file *, bool))); - connect(this, SIGNAL(reloadValueUnitFields()), iog, SLOT(reloadValueUnitField())); - connect(&cap_file_, SIGNAL(captureEvent(CaptureEvent)), - iog, SLOT(captureEvent(CaptureEvent))); - connect(iog, SIGNAL(requestRetap()), this, SLOT(scheduleRetap())); - connect(iog, SIGNAL(requestRecalc()), this, SLOT(scheduleRecalc())); - connect(iog, SIGNAL(requestReplot()), this, SLOT(scheduleReplot())); + connect(this, &IOGraphDialog::recalcGraphData, iog, &IOGraph::recalcGraphData); + connect(this, &IOGraphDialog::reloadValueUnitFields, iog, &IOGraph::reloadValueUnitField); + connect(&cap_file_, &CaptureFile::captureEvent, iog, &IOGraph::captureEvent); + connect(iog, &IOGraph::requestRetap, this, [=]() { scheduleRetap(); }); + connect(iog, &IOGraph::requestRecalc, this, [=]() { scheduleRecalc(); }); + connect(iog, &IOGraph::requestReplot, this, [=]() { scheduleReplot(); }); syncGraphSettings(currentRow); - if (iog->visible()) { - scheduleRetap(); - } + iog->setNeedRetap(true); } void IOGraphDialog::addDefaultGraph(bool enabled, int idx) @@ -591,7 +717,7 @@ void IOGraphDialog::addDefaultGraph(bool enabled, int idx) IOGraph::psLine, IOG_ITEM_UNIT_PACKETS, QString(), DEFAULT_MOVING_AVERAGE, DEFAULT_Y_AXIS_FACTOR); break; default: - addGraph(enabled, tr("Access Denied"), "ct.error == \"AccessDenied\"", ColorUtils::graphColor(4), // 4 = red + addGraph(enabled, tr("All Execs"), "evt.type == \"execve\"", ColorUtils::graphColor(4), // 4 = red IOGraph::psDot, IOG_ITEM_UNIT_PACKETS, QString(), DEFAULT_MOVING_AVERAGE, DEFAULT_Y_AXIS_FACTOR); break; } @@ -613,11 +739,10 @@ void IOGraphDialog::syncGraphSettings(int row) { IOGraph *iog = ioGraphs_.value(row, Q_NULLPTR); - if (!uat_model_->index(row, colEnabled).isValid() || !iog) + if (!uat_model_ || !uat_model_->index(row, colEnabled).isValid() || !iog) return; bool visible = graphIsEnabled(row); - bool retap = !iog->visible() && visible; QString data_str; iog->setName(uat_model_->data(uat_model_->index(row, colName)).toString()); @@ -625,7 +750,11 @@ void IOGraphDialog::syncGraphSettings(int row) /* plot style depend on the value unit, so set it first. */ data_str = uat_model_->data(uat_model_->index(row, colYAxis)).toString(); - iog->setValueUnits((int) str_to_val(qUtf8Printable(data_str), y_axis_vs, IOG_ITEM_UNIT_PACKETS)); + if (is_packet_configuration_namespace()) { + iog->setValueUnits((int) str_to_val(qUtf8Printable(data_str), y_axis_packet_vs, IOG_ITEM_UNIT_PACKETS)); + } else { + iog->setValueUnits((int) str_to_val(qUtf8Printable(data_str), y_axis_event_vs, IOG_ITEM_UNIT_PACKETS)); + } iog->setValueUnitField(uat_model_->data(uat_model_->index(row, colYField)).toString()); iog->setColor(uat_model_->data(uat_model_->index(row, colColor), Qt::DecorationRole).value().rgb()); @@ -642,7 +771,6 @@ void IOGraphDialog::syncGraphSettings(int row) if (!iog->configError().isEmpty()) { hint_err_ = iog->configError(); visible = false; - retap = false; } else { hint_err_.clear(); } @@ -650,18 +778,18 @@ void IOGraphDialog::syncGraphSettings(int row) iog->setVisible(visible); getGraphInfo(); - mouseMoved(NULL); // Update hint - updateLegend(); + updateHint(); if (visible) { - if (retap) { - scheduleRetap(); - } else { - scheduleReplot(); - } + scheduleReplot(); } } +qsizetype IOGraphDialog::graphCount() const +{ + return uat_model_ ? uat_model_->rowCount() : ioGraphs_.size(); +} + void IOGraphDialog::updateWidgets() { WiresharkDialog::updateWidgets(); @@ -671,9 +799,6 @@ void IOGraphDialog::scheduleReplot(bool now) { need_replot_ = true; if (now) updateStatistics(); - // A plot finished, force an update of the legend now in case a time unit - // was involved (which might append "(ms)" to the label). - updateLegend(); } void IOGraphDialog::scheduleRecalc(bool now) @@ -693,6 +818,27 @@ void IOGraphDialog::reloadFields() emit reloadValueUnitFields(); } +void IOGraphDialog::captureFileClosing() +{ + // The other buttons will be disabled when the model is set to null. + ui->newToolButton->setEnabled(false); + ui->intervalComboBox->setEnabled(false); + copy_profile_bt_->setEnabled(false); + if (uat_model_) { + applyChanges(); + disconnect(uat_model_, nullptr, this, nullptr); + } + // It would be nice to keep the information in the UAT about the graphs + // visible in a read-only state after closing, but if the view is just + // disabled, updating the model from elsewhere (e.g., other dialogs) + // will still change it, so we'd need to copy the information into + // a new model. + uat_model_ = nullptr; + ui->graphUat->setModel(nullptr); + ui->graphUat->setVisible(false); + WiresharkDialog::captureFileClosing(); +} + void IOGraphDialog::keyPressEvent(QKeyEvent *event) { int pan_pixels = event->modifiers() & Qt::ShiftModifier ? 1 : 10; @@ -764,19 +910,25 @@ void IOGraphDialog::keyPressEvent(QKeyEvent *event) QDialog::keyPressEvent(event); } -void IOGraphDialog::reject() +void IOGraphDialog::applyChanges() { - if (!uat_model_) + if (!static_uat_model_) return; // Changes to the I/O Graphs settings are always saved, // there is no possibility for "rejection". QString error; - if (uat_model_->applyChanges(error)) { + if (static_uat_model_->applyChanges(error)) { if (!error.isEmpty()) { report_failure("%s", qPrintable(error)); } } +} + +void IOGraphDialog::reject() +{ + if (uat_model_) + applyChanges(); QDialog::reject(); } @@ -881,12 +1033,12 @@ void IOGraphDialog::toggleTracerStyle(bool force_default) IOGraph *IOGraphDialog::currentActiveGraph() const { QModelIndex index = ui->graphUat->currentIndex(); - if (index.isValid()) { + if (index.isValid() && graphIsEnabled(index.row())) { return ioGraphs_.value(index.row(), NULL); } //if no currently selected item, go with first item enabled - for (int row = 0; row < uat_model_->rowCount(); row++) + for (int row = 0; row < graphCount(); row++) { if (graphIsEnabled(row)) { return ioGraphs_.value(row, NULL); @@ -898,8 +1050,13 @@ IOGraph *IOGraphDialog::currentActiveGraph() const bool IOGraphDialog::graphIsEnabled(int row) const { - Qt::CheckState state = static_cast(uat_model_->data(uat_model_->index(row, colEnabled), Qt::CheckStateRole).toInt()); - return state == Qt::Checked; + if (uat_model_) { + Qt::CheckState state = static_cast(uat_model_->data(uat_model_->index(row, colEnabled), Qt::CheckStateRole).toInt()); + return state == Qt::Checked; + } else { + IOGraph* iog = ioGraphs_.value(row, nullptr); + return (iog && iog->visible()); + } } // Scan through our graphs and gather information. @@ -909,7 +1066,7 @@ void IOGraphDialog::getGraphInfo() { base_graph_ = NULL; QCPBars *prev_bars = NULL; - start_time_ = 0.0; + nstime_set_zero(&start_time_); tracer_->setGraph(NULL); IOGraph *selectedGraph = currentActiveGraph(); @@ -931,9 +1088,9 @@ void IOGraphDialog::getGraphInfo() prev_bars = bars; } if (iog->visible() && iog->maxInterval() >= 0) { - double iog_start = iog->startOffset(); - if (start_time_ == 0.0 || iog_start < start_time_) { - start_time_ = iog_start; + nstime_t iog_start = iog->startTime(); + if (nstime_is_zero(&start_time_) || nstime_cmp(&iog_start, &start_time_) < 0) { + nstime_copy(&start_time_, &iog_start); } } @@ -946,9 +1103,78 @@ void IOGraphDialog::getGraphInfo() } } +void IOGraphDialog::updateHint() +{ + QCustomPlot *iop = ui->ioPlot; + QString hint; + + // XXX: ElidedLabel doesn't support rich text / HTML, we + // used to bold this error + if (!hint_err_.isEmpty()) { + hint += QString("%1 ").arg(hint_err_); + } + if (mouse_drags_) { + double ts = 0; + packet_num_ = 0; + int interval_packet = -1; + + if (tracer_->graph()) { + ts = tracer_->position->key(); + if (IOGraph *iog = currentActiveGraph()) { + interval_packet = iog->packetFromTime(ts - nstime_to_sec(&start_time_)); + } + } + + if (interval_packet < 0) { + hint += tr("Hover over the graph for details."); + } else { + QString msg = is_packet_configuration_namespace() ? tr("No packets in interval") : tr("No events in interval"); + QString val; + if (interval_packet > 0) { + packet_num_ = (uint32_t) interval_packet; + if (is_packet_configuration_namespace()) { + msg = QString("%1 %2") + .arg(!file_closed_ ? tr("Click to select packet") : tr("Packet")) + .arg(packet_num_); + } else { + msg = QString("%1 %2") + .arg(!file_closed_ ? tr("Click to select event") : tr("Event")) + .arg(packet_num_); + } + val = " = " + QString::number(tracer_->position->value(), 'g', 4); + } + // XXX - If Time of Day is selected, should we use ISO 8601 + // timestamps or something similar here instead of epoch time? + hint += tr("%1 (%2s%3).") + .arg(msg) + .arg(QString::number(ts, 'f', precision_)) + .arg(val); + } + iop->replot(QCustomPlot::rpQueuedReplot); + } else { + if (rubber_band_ && rubber_band_->isVisible()) { + QRectF zoom_ranges = getZoomRanges(rubber_band_->geometry()); + if (zoom_ranges.width() > 0.0 && zoom_ranges.height() > 0.0) { + hint += tr("Release to zoom, x = %1 to %2, y = %3 to %4") + .arg(zoom_ranges.x()) + .arg(zoom_ranges.x() + zoom_ranges.width()) + .arg(zoom_ranges.y()) + .arg(zoom_ranges.y() + zoom_ranges.height()); + } else { + hint += tr("Unable to select range."); + } + } else { + hint += tr("Click to select a portion of the graph."); + } + } + + ui->hintLabel->setText(hint); +} + void IOGraphDialog::updateLegend() { QCustomPlot *iop = ui->ioPlot; + QSet format_units_set; QSet vu_label_set; QString intervalText = ui->intervalComboBox->itemText(ui->intervalComboBox->currentIndex()); @@ -956,49 +1182,60 @@ void IOGraphDialog::updateLegend() iop->yAxis->setLabel(QString()); // Find unique labels - if (uat_model_ != NULL) { - for (int row = 0; row < uat_model_->rowCount(); row++) { - IOGraph *iog = ioGraphs_.value(row, Q_NULLPTR); - if (graphIsEnabled(row) && iog) { - QString label(iog->valueUnitLabel()); - if (!iog->scaledValueUnit().isEmpty()) { - label += " (" + iog->scaledValueUnit() + ")"; - } - vu_label_set.insert(label); - } + for (int row = 0; row < graphCount(); row++) { + IOGraph *iog = ioGraphs_.value(row, Q_NULLPTR); + if (graphIsEnabled(row) && iog) { + QString label(iog->valueUnitLabel()); + vu_label_set.insert(label); + format_units_set.insert(iog->formatUnits()); } } // Nothing. if (vu_label_set.size() < 1) { + iop->legend->layer()->replot(); return; } + format_size_units_e format_units = FORMAT_SIZE_UNIT_NONE; + if (format_units_set.size() == 1) { + format_units = format_units_set.values().constFirst(); + } + + QSharedPointer si_ticker = qSharedPointerDynamicCast(iop->yAxis->ticker()); + if (format_units != FORMAT_SIZE_UNIT_NONE) { + if (si_ticker) { + si_ticker->setUnit(format_units); + } else { + iop->yAxis->setTicker(QSharedPointer(new QCPAxisTickerSi(format_units, QString(), ui->logCheckBox->isChecked()))); + } + } else { + if (si_ticker) { + if (ui->logCheckBox->isChecked()) { + iop->yAxis->setTicker(QSharedPointer(new QCPAxisTickerLog)); + } else { + iop->yAxis->setTicker(QSharedPointer(new QCPAxisTicker)); + } + } + } + // All the same. Use the Y Axis label. if (vu_label_set.size() == 1) { - iop->yAxis->setLabel(vu_label_set.values()[0] + "/" + intervalText); - return; + iop->yAxis->setLabel(vu_label_set.values().constFirst() + "/" + intervalText); } - // Differing labels. Create a legend with a Title label at top. + // Create a legend with a Title label at top. // Legend Title thanks to: https://www.qcustomplot.com/index.php/support/forum/443 - QCPTextElement* legendTitle = qobject_cast(iop->legend->elementAt(0)); - if (legendTitle == NULL) { - legendTitle = new QCPTextElement(iop, QString("")); - iop->legend->insertRow(0); - iop->legend->addElement(0, 0, legendTitle); - } - legendTitle->setText(QString(intervalText + " Intervals ")); - - if (uat_model_ != NULL) { - for (int row = 0; row < uat_model_->rowCount(); row++) { - IOGraph *iog = ioGraphs_.value(row, Q_NULLPTR); - if (iog) { - if (graphIsEnabled(row)) { - iog->addToLegend(); - } else { - iog->removeFromLegend(); - } + iop->legend->clearItems(); + QCPStringLegendItem *legendTitle = new QCPStringLegendItem(iop->legend, QString(tr("%1 Intervals ").arg(intervalText))); + iop->legend->insertRow(0); + iop->legend->addElement(0, 0, legendTitle); + + for (int row = 0; row < graphCount(); row++) { + IOGraph *iog = ioGraphs_.value(row, Q_NULLPTR); + if (iog) { + if (graphIsEnabled(row)) { + iog->addToLegend(); } } } @@ -1037,19 +1274,37 @@ QRectF IOGraphDialog::getZoomRanges(QRect zoom_rect) return zoom_ranges; } +void IOGraphDialog::showContextMenu(const QPoint &pos) +{ + if (ui->ioPlot->legend->selectTest(pos, false) >= 0) { + QMenu *menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) + menu->addAction(tr("Move to top left"), this, &IOGraphDialog::moveLegend)->setData((Qt::AlignTop|Qt::AlignLeft).toInt()); + menu->addAction(tr("Move to top center"), this, &IOGraphDialog::moveLegend)->setData((Qt::AlignTop|Qt::AlignHCenter).toInt()); + menu->addAction(tr("Move to top right"), this, &IOGraphDialog::moveLegend)->setData((Qt::AlignTop|Qt::AlignRight).toInt()); + menu->addAction(tr("Move to bottom left"), this, &IOGraphDialog::moveLegend)->setData((Qt::AlignBottom|Qt::AlignLeft).toInt()); + menu->addAction(tr("Move to bottom center"), this, &IOGraphDialog::moveLegend)->setData((Qt::AlignBottom|Qt::AlignHCenter).toInt()); + menu->addAction(tr("Move to bottom right"), this, &IOGraphDialog::moveLegend)->setData((Qt::AlignBottom|Qt::AlignRight).toInt()); +#else + menu->addAction(tr("Move to top left"), this, &IOGraphDialog::moveLegend)->setData(static_cast(Qt::AlignTop|Qt::AlignLeft)); + menu->addAction(tr("Move to top center"), this, &IOGraphDialog::moveLegend)->setData(static_cast(Qt::AlignTop|Qt::AlignHCenter)); + menu->addAction(tr("Move to top right"), this, &IOGraphDialog::moveLegend)->setData(static_cast(Qt::AlignTop|Qt::AlignRight)); + menu->addAction(tr("Move to bottom left"), this, &IOGraphDialog::moveLegend)->setData(static_cast(Qt::AlignBottom|Qt::AlignLeft)); + menu->addAction(tr("Move to bottom center"), this, &IOGraphDialog::moveLegend)->setData(static_cast(Qt::AlignBottom|Qt::AlignHCenter)); + menu->addAction(tr("Move to bottom right"), this, &IOGraphDialog::moveLegend)->setData(static_cast(Qt::AlignBottom|Qt::AlignRight)); +#endif + menu->popup(ui->ioPlot->mapToGlobal(pos)); + } else { + ctx_menu_.popup(ui->ioPlot->mapToGlobal(pos)); + } +} + void IOGraphDialog::graphClicked(QMouseEvent *event) { QCustomPlot *iop = ui->ioPlot; - if (event->button() == Qt::RightButton) { - // XXX We should find some way to get ioPlot to handle a - // contextMenuEvent instead. -#if QT_VERSION >= QT_VERSION_CHECK(6, 0 ,0) - ctx_menu_.popup(event->globalPosition().toPoint()); -#else - ctx_menu_.popup(event->globalPos()); -#endif - } else if (mouse_drags_) { + if (mouse_drags_) { if (iop->axisRect()->rect().contains(event->pos())) { iop->setCursor(QCursor(Qt::ClosedHandCursor)); } @@ -1068,87 +1323,35 @@ void IOGraphDialog::graphClicked(QMouseEvent *event) void IOGraphDialog::mouseMoved(QMouseEvent *event) { QCustomPlot *iop = ui->ioPlot; - QString hint; Qt::CursorShape shape = Qt::ArrowCursor; - // XXX: ElidedLabel doesn't support rich text / HTML, we - // used to bold this error - if (!hint_err_.isEmpty()) { - hint += QString("%1 ").arg(hint_err_); - } - if (event) { - if (event->buttons().testFlag(Qt::LeftButton)) { - if (mouse_drags_) { - shape = Qt::ClosedHandCursor; - } else { - shape = Qt::CrossCursor; - } - } else if (iop->axisRect()->rect().contains(event->pos())) { - if (mouse_drags_) { - shape = Qt::OpenHandCursor; - } else { - shape = Qt::CrossCursor; - } + if (event->buttons().testFlag(Qt::LeftButton)) { + if (mouse_drags_) { + shape = Qt::ClosedHandCursor; + } else { + shape = Qt::CrossCursor; + } + } else if (iop->axisRect()->rect().contains(event->pos())) { + if (mouse_drags_) { + shape = Qt::OpenHandCursor; + } else { + shape = Qt::CrossCursor; } - iop->setCursor(QCursor(shape)); } + iop->setCursor(QCursor(shape)); if (mouse_drags_) { - double ts = 0; - packet_num_ = 0; - int interval_packet = -1; - - if (event && tracer_->graph()) { + if (tracer_->graph()) { tracer_->setGraphKey(iop->xAxis->pixelToCoord(event->pos().x())); - ts = tracer_->position->key(); - if (IOGraph *iog = currentActiveGraph()) { - interval_packet = iog->packetFromTime(ts - start_time_); - } } - if (interval_packet < 0) { - hint += tr("Hover over the graph for details."); - } else { - QString msg = is_packet_configuration_namespace() ? tr("No packets in interval") : tr("No events in interval"); - QString val; - if (interval_packet > 0) { - packet_num_ = (guint32) interval_packet; - if (is_packet_configuration_namespace()) { - msg = QString("%1 %2") - .arg(!file_closed_ ? tr("Click to select packet") : tr("Packet")) - .arg(packet_num_); - } else { - msg = QString("%1 %2") - .arg(!file_closed_ ? tr("Click to select event") : tr("Event")) - .arg(packet_num_); - } - val = " = " + QString::number(tracer_->position->value(), 'g', 4); - } - hint += tr("%1 (%2s%3).") - .arg(msg) - .arg(QString::number(ts, 'g', 4)) - .arg(val); - } - iop->replot(); } else { - if (event && rubber_band_ && rubber_band_->isVisible()) { + if (rubber_band_ && rubber_band_->isVisible()) { rubber_band_->setGeometry(QRect(rb_origin_, event->pos()).normalized()); - QRectF zoom_ranges = getZoomRanges(QRect(rb_origin_, event->pos())); - if (zoom_ranges.width() > 0.0 && zoom_ranges.height() > 0.0) { - hint += tr("Release to zoom, x = %1 to %2, y = %3 to %4") - .arg(zoom_ranges.x()) - .arg(zoom_ranges.x() + zoom_ranges.width()) - .arg(zoom_ranges.y()) - .arg(zoom_ranges.y() + zoom_ranges.height()); - } else { - hint += tr("Unable to select range."); - } - } else { - hint += tr("Click to select a portion of the graph."); } } - ui->hintLabel->setText(hint); + updateHint(); } void IOGraphDialog::mouseReleased(QMouseEvent *event) @@ -1172,51 +1375,99 @@ void IOGraphDialog::mouseReleased(QMouseEvent *event) } } +void IOGraphDialog::moveLegend() +{ + if (QAction *contextAction = qobject_cast(sender())) { + if (contextAction->data().canConvert()) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) + ui->ioPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::Alignment::fromInt(contextAction->data().value())); +#else + ui->ioPlot->axisRect()->insetLayout()->setInsetAlignment(0, static_cast(contextAction->data().value())); +#endif + ui->ioPlot->replot(); + } + } +} + void IOGraphDialog::resetAxes() { QCustomPlot *iop = ui->ioPlot; - QCPRange x_range = iop->xAxis->scaleType() == QCPAxis::stLogarithmic ? - iop->xAxis->range().sanitizedForLogScale() : iop->xAxis->range(); - double pixel_pad = 10.0; // per side iop->rescaleAxes(true); + QCPRange x_range = iop->xAxis->scaleType() == QCPAxis::stLogarithmic ? + iop->xAxis->range().sanitizedForLogScale() : iop->xAxis->range(); double axis_pixels = iop->xAxis->axisRect()->width(); iop->xAxis->scaleRange((axis_pixels + (pixel_pad * 2)) / axis_pixels, x_range.center()); + QCPRange y_range = iop->yAxis->scaleType() == QCPAxis::stLogarithmic ? + iop->yAxis->range().sanitizedForLogScale() : iop->yAxis->range(); axis_pixels = iop->yAxis->axisRect()->height(); - iop->yAxis->scaleRange((axis_pixels + (pixel_pad * 2)) / axis_pixels, iop->yAxis->range().center()); + iop->yAxis->scaleRange((axis_pixels + (pixel_pad * 2)) / axis_pixels, y_range.center()); auto_axes_ = true; iop->replot(); } +void IOGraphDialog::selectedFrameChanged(QList frames) +{ + if (frames.count() == 1 && cap_file_.isValid() && !file_closed_ && tracer_->graph() && cap_file_.packetInfo() != nullptr) { + packet_info *pinfo = cap_file_.packetInfo(); + if (pinfo->num != packet_num_) { + // This prevents being triggered by the IOG's own GoToPacketAction, + // although that is mostly harmless. + int interval = ui->intervalComboBox->itemData(ui->intervalComboBox->currentIndex()).toInt(); + + /* + * setGraphKey (with Interpolation false, as it is by default) + * finds the nearest point to the key. Our buckets are derived + * from rounding down (XXX - which is appropriate for relative + * time but less so when absolute time of day is selected.) + * We could call get_io_graph_index() and then multiply to get + * the exact ts for the bucket, but it's fewer math operations + * operations simply to subtract half the interval. + * XXX - Getting the exact value would be superior if we wished + * to avoid doing anything in the case that the tracer is + * already pointing at the correct bucket. (Is the hint always + * correct in that case?) + */ +#if 0 + int64_t idx = get_io_graph_index(pinfo, interval); + double ts = (double)idx * interval / SCALE_F + nstime_to_sec(&start_time); +#endif + double key = nstime_to_sec(&pinfo->rel_ts) - (interval / (2 * SCALE_F)) + nstime_to_sec(&start_time_); + tracer_->setGraphKey(key); + ui->ioPlot->replot(); + updateHint(); + } + } +} + void IOGraphDialog::updateStatistics() { if (!isVisible()) return; - if (need_retap_ && !file_closed_ && prefs.gui_io_graph_automatic_update) { + /* XXX - If we're currently retapping, what we really want to do is + * abort the current tap and start over. process_specified_records() + * in file.c doesn't let us do that, because it doesn't know whether + * it's holding cf->read_lock for something that could be restarted + * (like tapping or dissection) or something that needs to run to + * completion (saving, printing.) + * + * So we wait and see if we're no longer tapping the next check. + */ + if (need_retap_ && !file_closed_ && !retapDepth() && prefs.gui_io_graph_automatic_update) { need_retap_ = false; - cap_file_.retapPackets(); + QTimer::singleShot(0, &cap_file_, &CaptureFile::retapPackets); // The user might have closed the window while tapping, which means // we might no longer exist. } else { if (need_recalc_ && !file_closed_ && prefs.gui_io_graph_automatic_update) { need_recalc_ = false; need_replot_ = true; - int enabled_graphs = 0; - if (uat_model_ != NULL) { - for (int row = 0; row < uat_model_->rowCount(); row++) { - if (graphIsEnabled(row)) { - ++enabled_graphs; - } - } - } - // With multiple visible graphs, disable Y scaling to avoid - // multiple, distinct units. - emit recalcGraphData(cap_file_.capFile(), enabled_graphs == 1); + emit recalcGraphData(cap_file_.capFile()); if (!tracer_->graph()) { if (base_graph_ && base_graph_->data()->size() > 0) { tracer_->setGraph(base_graph_); @@ -1239,11 +1490,15 @@ void IOGraphDialog::updateStatistics() void IOGraphDialog::loadProfileGraphs() { if (iog_uat_ == NULL) { + uat_field_t *io_graph_fields = io_graph_packet_fields; + if (!is_packet_configuration_namespace()) { + io_graph_fields = io_graph_event_fields; + } iog_uat_ = uat_new("I/O Graphs", sizeof(io_graph_settings_t), "io_graphs", - TRUE, + true, &iog_settings_, &num_io_graphs_, 0, /* doesn't affect anything that requires a GUI update */ @@ -1251,7 +1506,7 @@ void IOGraphDialog::loadProfileGraphs() io_graph_copy_cb, NULL, io_graph_free_cb, - NULL, + io_graph_post_update_cb, NULL, io_graph_fields); @@ -1263,16 +1518,26 @@ void IOGraphDialog::loadProfileGraphs() g_free(err); uat_clear(iog_uat_); } + + static_uat_model_ = new UatModel(mainApp, iog_uat_); + connect(mainApp, &MainApplication::profileChanging, IOGraphDialog::applyChanges); } - uat_model_ = new UatModel(NULL, iog_uat_); - uat_delegate_ = new UatDelegate; + uat_model_ = static_uat_model_; + uat_delegate_ = new UatDelegate(ui->graphUat); ui->graphUat->setModel(uat_model_); ui->graphUat->setItemDelegate(uat_delegate_); + ui->graphUat->setSelectionMode(QAbstractItemView::ContiguousSelection); + + ui->graphUat->setHeader(new ResizeHeaderView(Qt::Horizontal, ui->graphUat)); - connect(uat_model_, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(modelDataChanged(QModelIndex))); - connect(uat_model_, SIGNAL(modelReset()), this, SLOT(modelRowsReset())); + connect(uat_model_, &UatModel::dataChanged, this, &IOGraphDialog::modelDataChanged); + connect(uat_model_, &UatModel::modelReset, this, &IOGraphDialog::modelRowsReset); + connect(uat_model_, &UatModel::rowsInserted, this, &IOGraphDialog::modelRowsInserted); + connect(uat_model_, &UatModel::rowsRemoved, this, &IOGraphDialog::modelRowsRemoved); + connect(uat_model_, &UatModel::rowsMoved, this, &IOGraphDialog::modelRowsMoved); + + connect(ui->graphUat->selectionModel(), &QItemSelectionModel::selectionChanged, this, &IOGraphDialog::graphUatSelectionChanged); } // Slots @@ -1282,6 +1547,22 @@ void IOGraphDialog::on_intervalComboBox_currentIndexChanged(int) int interval = ui->intervalComboBox->itemData(ui->intervalComboBox->currentIndex()).toInt(); bool need_retap = false; + precision_ = ceil(log10(SCALE_F / interval)); + if (precision_ < 0) { + precision_ = 0; + } + + // XXX - This is the default QCP date time format, but adding fractional + // seconds when our interval is small. Should we make it something else, + // like ISO 8601 (but still with a line break between time and date)? + // Note this is local time, with no time zone offset displayed. Should + // it be in UTC? (call setDateTimeSpec()) + if (precision_) { + datetime_ticker_->setDateTimeFormat("hh:mm:ss.z\ndd.MM.yy"); + } else { + datetime_ticker_->setDateTimeFormat("hh:mm:ss\ndd.MM.yy"); + } + if (uat_model_ != NULL) { for (int row = 0; row < uat_model_->rowCount(); row++) { IOGraph *iog = ioGraphs_.value(row, NULL); @@ -1289,6 +1570,8 @@ void IOGraphDialog::on_intervalComboBox_currentIndexChanged(int) iog->setInterval(interval); if (iog->visible()) { need_retap = true; + } else { + iog->setNeedRetap(true); } } } @@ -1297,13 +1580,12 @@ void IOGraphDialog::on_intervalComboBox_currentIndexChanged(int) if (need_retap) { scheduleRetap(true); } - - updateLegend(); } void IOGraphDialog::on_todCheckBox_toggled(bool checked) { - double orig_start = start_time_; + nstime_t orig_start; + nstime_copy(&orig_start, &start_time_); bool orig_auto = auto_axes_; if (checked) { @@ -1315,46 +1597,135 @@ void IOGraphDialog::on_todCheckBox_toggled(bool checked) scheduleRecalc(true); auto_axes_ = orig_auto; getGraphInfo(); - ui->ioPlot->xAxis->moveRange(start_time_ - orig_start); - mouseMoved(NULL); // Update hint + nstime_delta(&orig_start, &start_time_, &orig_start); + ui->ioPlot->xAxis->moveRange(nstime_to_sec(&orig_start)); + updateHint(); } void IOGraphDialog::modelRowsReset() { + foreach(IOGraph* iog, ioGraphs_) { + delete iog; + } + ioGraphs_.clear(); + + for (int i = 0; i < uat_model_->rowCount(); i++) { + createIOGraph(i); + } ui->deleteToolButton->setEnabled(false); ui->copyToolButton->setEnabled(false); ui->clearToolButton->setEnabled(uat_model_->rowCount() != 0); } -void IOGraphDialog::on_graphUat_currentItemChanged(const QModelIndex ¤t, const QModelIndex&) +void IOGraphDialog::modelRowsInserted(const QModelIndex &, int first, int last) { - if (current.isValid()) { + // first to last is inclusive + for (int i = first; i <= last; i++) { + createIOGraph(i); + } +} + +void IOGraphDialog::modelRowsRemoved(const QModelIndex &, int first, int last) +{ + // first to last is inclusive + for (int i = last; i >= first; i--) { + IOGraph *iog = ioGraphs_.takeAt(i); + delete iog; + } +} + +void IOGraphDialog::modelRowsMoved(const QModelIndex &source, int sourceStart, int sourceEnd, const QModelIndex &dest, int destinationRow) +{ + // The source and destination parent are always the same for UatModel. + ws_assert(source == dest); + // Either destinationRow < sourceStart, or destinationRow > sourceEnd. + // When moving rows down the same parent, the rows are placed _before_ + // destinationRow, otherwise it's the row to which items are moved. + if (destinationRow < sourceStart) { + for (int i = 0; i <= sourceEnd - sourceStart; i++) { + // When moving up the same parent, moving an earlier + // item doesn't change the row. + ioGraphs_.move(sourceStart + i, destinationRow + i); + } + } else { + for (int i = 0; i <= sourceEnd - sourceStart; i++) { + // When moving down the same parent, moving an earlier + // item means the next items move up (so all the moved + // rows are always at sourceStart.) + ioGraphs_.move(sourceStart, destinationRow - 1); + } + } + + // setting a QCPLayerable to its current layer moves it to the end + // as though it were the last added. Do that for all the plottables + // starting with the first one that changed, so that the graphs appear + // as though they were added in the current order. + // (moveToLayer() is the same thing but with a parameter to prepend + // instead, which would be faster if we're in the top half of the + // list, except that's a protected function. There's no function + // to swap layerables in a layer.) + IOGraph *iog; + for (int row = qMin(sourceStart, destinationRow); row < uat_model_->rowCount(); row++) { + iog = ioGraphs_.at(row); + if (iog->graph()) { + iog->graph()->setLayer(iog->graph()->layer()); + } else if (iog->bars()) { + iog->bars()->setLayer(iog->bars()->layer()); + } + } + ui->ioPlot->replot(); +} + +void IOGraphDialog::graphUatSelectionChanged(const QItemSelection&, const QItemSelection&) +{ + QModelIndexList selectedRows = ui->graphUat->selectionModel()->selectedRows(); + qsizetype num_selected = selectedRows.size(); + if (num_selected > 0) { + std::sort(selectedRows.begin(), selectedRows.end()); ui->deleteToolButton->setEnabled(true); ui->copyToolButton->setEnabled(true); - ui->clearToolButton->setEnabled(true); - ui->moveUpwardsToolButton->setEnabled(true); - ui->moveDownwardsToolButton->setEnabled(true); + ui->moveUpwardsToolButton->setEnabled(selectedRows.first().row() > 0); + ui->moveDownwardsToolButton->setEnabled(selectedRows.last().row() < uat_model_->rowCount() - 1); } else { ui->deleteToolButton->setEnabled(false); ui->copyToolButton->setEnabled(false); - ui->clearToolButton->setEnabled(false); ui->moveUpwardsToolButton->setEnabled(false); ui->moveDownwardsToolButton->setEnabled(false); } } -void IOGraphDialog::modelDataChanged(const QModelIndex &index) +void IOGraphDialog::on_graphUat_currentItemChanged(const QModelIndex ¤t, const QModelIndex&) +{ + if (current.isValid()) { + ui->clearToolButton->setEnabled(true); + if (graphIsEnabled(current.row())) { + // Try to set the tracer to the new current graph. + // If it's not enabled, don't try to switch from the + // old graph to the one in the first row. + getGraphInfo(); + } + } else { + ui->clearToolButton->setEnabled(false); + } +} + +void IOGraphDialog::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &) { bool recalc = false; - switch (index.column()) - { - case colYAxis: - case colSMAPeriod: - recalc = true; + for (int col = topLeft.column(); col <= bottomRight.column(); col++) { + switch (col) + { + case colYAxis: + case colSMAPeriod: + case colYAxisFactor: + recalc = true; + } } - syncGraphSettings(index.row()); + for (int row = topLeft.row(); row <= bottomRight.row(); row++) { + syncGraphSettings(row); + } if (recalc) { scheduleRecalc(true); @@ -1363,11 +1734,6 @@ void IOGraphDialog::modelDataChanged(const QModelIndex &index) } } -void IOGraphDialog::on_resetButton_clicked() -{ - resetAxes(); -} - void IOGraphDialog::on_newToolButton_clicked() { addGraph(); @@ -1375,70 +1741,95 @@ void IOGraphDialog::on_newToolButton_clicked() void IOGraphDialog::on_deleteToolButton_clicked() { - const QModelIndex ¤t = ui->graphUat->currentIndex(); - if (uat_model_ && current.isValid()) { - delete ioGraphs_[current.row()]; - ioGraphs_.remove(current.row()); + if (uat_model_ == nullptr) { + return; + } - if (!uat_model_->removeRows(current.row(), 1)) { - qDebug() << "Failed to remove row"; + for (const auto &range : ui->graphUat->selectionModel()->selection()) { + // Each QItemSelectionRange is contiguous + if (!range.isEmpty()) { + if (!uat_model_->removeRows(range.top(), range.bottom() - range.top() + 1)) { + qDebug() << "Failed to remove rows" << range.top() << "to" << range.bottom(); + } } } // We should probably be smarter about this. hint_err_.clear(); - mouseMoved(NULL); + updateHint(); } void IOGraphDialog::on_copyToolButton_clicked() { - addGraph(true); + if (uat_model_ == nullptr) { + return; + } + + QModelIndexList selectedRows = ui->graphUat->selectionModel()->selectedRows(); + if (selectedRows.size() > 0) { + std::sort(selectedRows.begin(), selectedRows.end()); + + QModelIndex copyIdx; + + for (const auto &idx : selectedRows) { + copyIdx = uat_model_->copyRow(idx); + if (!copyIdx.isValid()) + { + qDebug() << "Failed to copy row" << idx.row(); + } + } + ui->graphUat->setCurrentIndex(copyIdx); + } } void IOGraphDialog::on_clearToolButton_clicked() { if (uat_model_) { - foreach(IOGraph* iog, ioGraphs_) { - delete iog; - } - ioGraphs_.clear(); uat_model_->clearAll(); } hint_err_.clear(); - mouseMoved(NULL); + updateHint(); } void IOGraphDialog::on_moveUpwardsToolButton_clicked() { - const QModelIndex& current = ui->graphUat->currentIndex(); - if (uat_model_ && current.isValid()) { - - int current_row = current.row(); - if (current_row > 0){ - // Swap current row with the one above - IOGraph* temp = ioGraphs_[current_row - 1]; - ioGraphs_[current_row - 1] = ioGraphs_[current_row]; - ioGraphs_[current_row] = temp; + if (uat_model_ == nullptr) { + return; + } - uat_model_->moveRow(current_row, current_row - 1); + for (const auto &range : ui->graphUat->selectionModel()->selection()) { + // Each QItemSelectionRange is contiguous + if (!range.isEmpty() && range.top() > 0) { + // Swap range of rows with the row above the top + if (! uat_model_->moveRows(QModelIndex(), range.top(), range.bottom() - range.top() + 1, QModelIndex(), range.top() - 1)) { + qDebug() << "Failed to move up rows" << range.top() << "to" << range.bottom(); + } + // Our moveRows implementation calls begin/endMoveRows(), so + // range.top() already has the new row number. + ui->moveUpwardsToolButton->setEnabled(range.top() > 0); + ui->moveDownwardsToolButton->setEnabled(true); } } } void IOGraphDialog::on_moveDownwardsToolButton_clicked() { - const QModelIndex& current = ui->graphUat->currentIndex(); - if (uat_model_ && current.isValid()) { - - int current_row = current.row(); - if (current_row < uat_model_->rowCount() - 1) { - // Swap current row with the one below - IOGraph* temp = ioGraphs_[current_row + 1]; - ioGraphs_[current_row + 1] = ioGraphs_[current_row]; - ioGraphs_[current_row] = temp; + if (uat_model_ == nullptr) { + return; + } - uat_model_->moveRow(current_row, current_row + 1); + for (const auto &range : ui->graphUat->selectionModel()->selection()) { + // Each QItemSelectionRange is contiguous + if (!range.isEmpty() && range.bottom() + 1 < uat_model_->rowCount()) { + // Swap range of rows with the row below the top + if (! uat_model_->moveRows(QModelIndex(), range.top(), range.bottom() - range.top() + 1, QModelIndex(), range.bottom() + 1)) { + qDebug() << "Failed to move down rows" << range.top() << "to" << range.bottom(); + } + // Our moveRows implementation calls begin/endMoveRows, so + // range.bottom() already has the new row number. + ui->moveUpwardsToolButton->setEnabled(true); + ui->moveDownwardsToolButton->setEnabled(range.bottom() < uat_model_->rowCount() - 1); } } } @@ -1461,14 +1852,28 @@ void IOGraphDialog::on_zoomRadioButton_toggled(bool checked) void IOGraphDialog::on_logCheckBox_toggled(bool checked) { QCustomPlot *iop = ui->ioPlot; + QSharedPointer si_ticker = qSharedPointerDynamicCast(iop->yAxis->ticker()); + if (si_ticker != nullptr) { + si_ticker->setLog(checked); + } - iop->yAxis->setScaleType(checked ? QCPAxis::stLogarithmic : QCPAxis::stLinear); + if (checked) { + iop->yAxis->setScaleType(QCPAxis::stLogarithmic); + if (si_ticker == nullptr) { + iop->yAxis->setTicker(QSharedPointer(new QCPAxisTickerLog)); + } + } else { + iop->yAxis->setScaleType(QCPAxis::stLinear); + if (si_ticker == nullptr) { + iop->yAxis->setTicker(QSharedPointer(new QCPAxisTicker)); + } + } iop->replot(); } void IOGraphDialog::on_automaticUpdateCheckBox_toggled(bool checked) { - prefs.gui_io_graph_automatic_update = checked ? TRUE : FALSE; + prefs.gui_io_graph_automatic_update = checked ? true : false; prefs_main_write(); @@ -1480,16 +1885,16 @@ void IOGraphDialog::on_automaticUpdateCheckBox_toggled(bool checked) void IOGraphDialog::on_enableLegendCheckBox_toggled(bool checked) { - prefs.gui_io_graph_enable_legend = checked ? TRUE : FALSE; + prefs.gui_io_graph_enable_legend = checked ? true : false; prefs_main_write(); - updateLegend(); + ui->ioPlot->legend->layer()->replot(); } void IOGraphDialog::on_actionReset_triggered() { - on_resetButton_clicked(); + resetAxes(); } void IOGraphDialog::on_actionZoomIn_triggered() @@ -1585,7 +1990,7 @@ void IOGraphDialog::on_actionToggleTimeOrigin_triggered() void IOGraphDialog::on_actionCrosshairs_triggered() { - + toggleTracerStyle(); } void IOGraphDialog::on_buttonBox_helpRequested() @@ -1638,6 +2043,17 @@ void IOGraphDialog::on_buttonBox_accepted() } } +void IOGraphDialog::buttonBoxClicked(QAbstractButton *button) +{ + switch (ui->buttonBox->buttonRole(button)) { + case QDialogButtonBox::ResetRole: + resetAxes(); + break; + default: + break; + } +} + void IOGraphDialog::makeCsv(QTextStream &stream) const { QList activeGraphs; @@ -1646,25 +2062,47 @@ void IOGraphDialog::makeCsv(QTextStream &stream) const int max_interval = 0; stream << "\"Interval start\""; - if (uat_model_ != NULL) { - for (int row = 0; row < uat_model_->rowCount(); row++) { - if (graphIsEnabled(row) && ioGraphs_[row] != NULL) { - activeGraphs.append(ioGraphs_[row]); - if (max_interval < ioGraphs_[row]->maxInterval()) { - max_interval = ioGraphs_[row]->maxInterval(); - } - QString name = ioGraphs_[row]->name().toUtf8(); - name = QString("\"%1\"").arg(name.replace("\"", "\"\"")); // RFC 4180 - stream << "," << name; + for (int row = 0; row < graphCount(); row++) { + if (graphIsEnabled(row) && ioGraphs_[row] != NULL) { + activeGraphs.append(ioGraphs_[row]); + if (max_interval < ioGraphs_[row]->maxInterval()) { + max_interval = ioGraphs_[row]->maxInterval(); } + QString name = ioGraphs_[row]->name().toUtf8(); + name = QString("\"%1\"").arg(name.replace("\"", "\"\"")); // RFC 4180 + stream << "," << name; } } stream << '\n'; for (int interval = 0; interval <= max_interval; interval++) { - double interval_start = (double)interval * ((double)ui_interval / 1000.0); - stream << interval_start; + int64_t interval_start = (int64_t)interval * ui_interval; + if (qSharedPointerDynamicCast(ui->ioPlot->xAxis->ticker()) != nullptr) { + nstime_t interval_time = NSTIME_INIT_SECS_USECS((time_t)(interval_start / SCALE), (int)(interval_start % SCALE)); + + nstime_add(&interval_time, &start_time_); + + static char time_string_buf[39]; + + if (decimal_point == nullptr) { + decimal_point = g_strdup(localeconv()->decimal_point); + } + // Should we convert to UTC for output, even if the graph axis has + // local time? + // The question of what precision to use is somewhat tricky. + // The buckets are aligned to the relative time start, not to + // absolute time, so the timestamp precision should be used instead + // of the bucket precision. We can save the precision of the + // start time timestamp for each graph, but we don't necessarily + // have a guarantee that all timestamps in the file have the same + // precision. Possibly nstime_t should store precision, cf. #15579 + format_nstime_as_iso8601(time_string_buf, sizeof time_string_buf, &interval_time, decimal_point, true, 9); // precision_); + + stream << time_string_buf; + } else { + stream << (double)interval_start / SCALE_F; + } foreach (IOGraph *iog, activeGraphs) { double value = 0.0; if (interval <= iog->maxInterval()) { @@ -1698,11 +2136,14 @@ bool IOGraphDialog::saveCsv(const QString &file_name) const IOGraph::IOGraph(QCustomPlot *parent) : parent_(parent), + tap_registered_(true), visible_(false), graph_(NULL), bars_(NULL), val_units_(IOG_ITEM_UNIT_FIRST), hf_index_(-1), + interval_(0), + start_time_(NSTIME_INIT_ZERO), cur_idx_(-1) { Q_ASSERT(parent_ != NULL); @@ -1723,11 +2164,12 @@ IOGraph::IOGraph(QCustomPlot *parent) : // error_string->str); // config_err_ = error_string->str; g_string_free(error_string, TRUE); + tap_registered_ = false; } } IOGraph::~IOGraph() { - remove_tap_listener(this); + removeTapListener(); if (graph_) { parent_->removeGraph(graph_); } @@ -1736,9 +2178,17 @@ IOGraph::~IOGraph() { } } +void IOGraph::removeTapListener() +{ + if (tap_registered_) { + remove_tap_listener(this); + tap_registered_ = false; + } +} + // Construct a full filter string from the display filter and value unit / Y axis. -// Check for errors and sets config_err_ if any are found. -void IOGraph::setFilter(const QString &filter) +// Check for errors and sets config_err_ and returns false if any are found. +bool IOGraph::setFilter(const QString &filter) { GString *error_string; QString full_filter(filter.trimmed()); @@ -1756,7 +2206,7 @@ void IOGraph::setFilter(const QString &filter) config_err_ = QString::fromUtf8(df_err->msg); df_error_free(&df_err); filter_ = full_filter; - return; + return false; } } @@ -1765,7 +2215,7 @@ void IOGraph::setFilter(const QString &filter) if (error_string) { config_err_ = error_string->str; g_string_free(error_string, TRUE); - return; + return false; } // Make sure vu_field_ survives edt tree pruning by adding it to our filter @@ -1778,17 +2228,36 @@ void IOGraph::setFilter(const QString &filter) } } - error_string = set_tap_dfilter(this, full_filter.toUtf8().constData()); - if (error_string) { - config_err_ = error_string->str; - g_string_free(error_string, TRUE); - return; - } else { - if (filter_.compare(filter) && visible_) { - emit requestRetap(); + if (full_filter_.compare(full_filter)) { + error_string = set_tap_dfilter(this, full_filter.toUtf8().constData()); + if (error_string) { + config_err_ = error_string->str; + g_string_free(error_string, TRUE); + return false; } + filter_ = filter; + full_filter_ = full_filter; + /* If we changed the tap filter the graph is visible, we need to + * retap. + * Note that setting the tap dfilter will mark the tap as needing a + * redraw, which will cause a recalculation (via tapDraw) via the + * (fairly long) main application timer. + */ + /* XXX - When changing from an advanced graph to one that doesn't + * use the field, we don't actually need to retap if filter and + * full_filter produce the same results. (We do have to retap + * regardless if changing _to_ an advanced graph, because the + * extra fields in the io_graph_item_t aren't filled in from the + * edt for the basic graph.) + * Checking that in full generality would require more optimization + * in the dfilter engine plus functions to compare filters, but + * we could test the simple case where filter and vu_field are + * the same string. + */ + setNeedRetap(true); } + return true; } void IOGraph::applyCurrentColor() @@ -1796,7 +2265,15 @@ void IOGraph::applyCurrentColor() if (graph_) { graph_->setPen(QPen(color_, graph_line_width_)); } else if (bars_) { - bars_->setPen(QPen(QBrush(ColorUtils::graphColor(0)), graph_line_width_)); // ...or omit it altogether? + bars_->setPen(QPen(color_.color().darker(110), graph_line_width_)); + // ...or omit it altogether? + // bars_->setPen(QPen(color_); + // XXX - We should do something like + // bars_->setPen(QPen(ColorUtils::alphaBlend(color_, palette().windowText(), 0.65)); + // to get a darker outline in light mode and a lighter outline in dark + // mode, but we don't yet respect dark mode in IOGraph (or anything + // that uses QCustomPlot) - see link below for how to set QCP colors: + // https://www.qcustomplot.com/index.php/demos/barchartdemo bars_->setBrush(color_); } } @@ -1812,7 +2289,28 @@ void IOGraph::setVisible(bool visible) bars_->setVisible(visible_); } if (old_visibility != visible_) { - emit requestReplot(); + if (visible_ && need_retap_) { + need_retap_ = false; + emit requestRetap(); + } else { + // XXX - If the number of enabled graphs changed to or from 1, we + // need to recalculate to possibly change the rescaling. (This is + // why QCP recommends doing scaling in the axis ticker instead.) + // If we can't determine the number of enabled graphs here, always + // request a recalculation instead of a replot. (At least until we + // change the scaling to be done in the ticker.) + //emit requestReplot(); + emit requestRecalc(); + } + } +} + +void IOGraph::setNeedRetap(bool retap) +{ + if (visible_ && retap) { + emit requestRetap(); + } else { + need_retap_ = retap; } } @@ -1827,7 +2325,7 @@ void IOGraph::setName(const QString &name) } } -QRgb IOGraph::color() +QRgb IOGraph::color() const { return color_.color().rgb(); } @@ -1840,14 +2338,24 @@ void IOGraph::setColor(const QRgb color) void IOGraph::setPlotStyle(int style) { + bool recalc = false; + bool shows_zero = showsZero(); + // Switch plottable if needed switch (style) { case psBar: case psStackedBar: if (graph_) { bars_ = new QCPBars(parent_->xAxis, parent_->yAxis); + // default widthType is wtPlotCoords. Scale with the interval + // size to prevent overlap. (Multiply this by a factor to have + // a gap between bars; the QCustomPlot default is 0.75.) + if (interval_) { + bars_->setWidth(interval_ / SCALE_F); + } parent_->removeGraph(graph_); graph_ = NULL; + recalc = true; } break; default: @@ -1855,6 +2363,7 @@ void IOGraph::setPlotStyle(int style) graph_ = parent_->addGraph(parent_->xAxis, parent_->yAxis); parent_->removePlottable(bars_); bars_ = NULL; + recalc = true; } break; } @@ -1930,13 +2439,26 @@ void IOGraph::setPlotStyle(int style) break; } + if (shows_zero != showsZero()) { + // recalculate if whether zero is added changed + recalc = true; + } + setName(name_); applyCurrentColor(); + + if (recalc) { + // switching the plottable requires recalculation to add the data + emit requestRecalc(); + } } -const QString IOGraph::valueUnitLabel() +QString IOGraph::valueUnitLabel() const { - return val_to_str_const(val_units_, y_axis_vs, "Unknown"); + if (is_packet_configuration_namespace()) { + return val_to_str_const(val_units_, y_axis_packet_vs, "Unknown"); + } + return val_to_str_const(val_units_, y_axis_event_vs, "Unknown"); } void IOGraph::setValueUnits(int val_units) @@ -1946,9 +2468,21 @@ void IOGraph::setValueUnits(int val_units) val_units_ = (io_graph_item_unit_t)val_units; if (old_val_units != val_units) { - setFilter(filter_); // Check config & prime vu field - if (val_units < IOG_ITEM_UNIT_CALC_SUM) { - emit requestRecalc(); + // If val_units changed, switching between a type that doesn't + // use the vu_field/hfi/edt to one of the advanced graphs that + // does requires a retap. setFilter will handle that, because + // the full filter strings will be different. + if (setFilter(filter_)) { // Check config & prime vu field + if (val_units == IOG_ITEM_UNIT_CALC_LOAD || + old_val_units == IOG_ITEM_UNIT_CALC_LOAD) { + // LOAD graphs fill in the io_graph_item_t differently + // than other advanced graphs, so we have to retap even + // if the filter is the same. (update_io_graph_item could + // instead calculate and store LOAD information for any + // advanced graph type, but the tradeoff might not be + // worth it.) + setNeedRetap(true); + } } } } @@ -1967,6 +2501,8 @@ void IOGraph::setValueUnitField(const QString &vu_field) } if (old_hf_index != hf_index_) { + // If the field changed, and val_units is a type that uses it, + // we need to retap. setFilter will handle that. setFilter(filter_); // Check config & prime vu field } } @@ -1993,25 +2529,44 @@ bool IOGraph::removeFromLegend() return false; } -double IOGraph::startOffset() +// This returns what graph key offset corresponds with relative time 0.0, +// i.e. when absolute times are used the difference between abs_ts and +// rel_ts of the first tapped packet. Generally the same for all graphs +// that are displayed and have some data, unless they're on the opposite +// sides of time references. +// XXX - If the graph spans a time reference, it's not clear how we want +// to switch from relative to absolute times. +double IOGraph::startOffset() const { - if (graph_ && qSharedPointerDynamicCast(graph_->keyAxis()->ticker()) && graph_->data()->size() > 0) { - return graph_->data()->at(0)->key; + if (graph_ && qSharedPointerDynamicCast(graph_->keyAxis()->ticker())) { + return nstime_to_sec(&start_time_); } - if (bars_ && qSharedPointerDynamicCast(bars_->keyAxis()->ticker()) && bars_->data()->size() > 0) { - return bars_->data()->at(0)->key; + if (bars_ && qSharedPointerDynamicCast(bars_->keyAxis()->ticker())) { + return nstime_to_sec(&start_time_); } return 0.0; } -int IOGraph::packetFromTime(double ts) +nstime_t IOGraph::startTime() const { - int idx = ts * 1000 / interval_; - if (idx >= 0 && idx < (int) cur_idx_) { + if (graph_ && qSharedPointerDynamicCast(graph_->keyAxis()->ticker())) { + return start_time_; + } + if (bars_ && qSharedPointerDynamicCast(bars_->keyAxis()->ticker())) { + return start_time_; + } + return nstime_t(NSTIME_INIT_ZERO); +} + +int IOGraph::packetFromTime(double ts) const +{ + int idx = ts * SCALE_F / interval_; + if (idx >= 0 && idx <= cur_idx_) { switch (val_units_) { case IOG_ITEM_UNIT_CALC_MAX: + return items_[idx].max_frame_in_invl; case IOG_ITEM_UNIT_CALC_MIN: - return items_[idx].extreme_frame_in_invl; + return items_[idx].min_frame_in_invl; default: return items_[idx].last_frame_in_invl; } @@ -2022,31 +2577,30 @@ int IOGraph::packetFromTime(double ts) void IOGraph::clearAllData() { cur_idx_ = -1; - reset_io_graph_items(items_, max_io_items_); + if (items_.size()) { + reset_io_graph_items(&items_[0], items_.size(), hf_index_); + } if (graph_) { graph_->data()->clear(); } if (bars_) { bars_->data()->clear(); } - start_time_ = 0.0; + nstime_set_zero(&start_time_); } -void IOGraph::recalcGraphData(capture_file *cap_file, bool enable_scaling) +void IOGraph::recalcGraphData(capture_file *cap_file) { /* Moving average variables */ unsigned int mavg_in_average_count = 0, mavg_left = 0; unsigned int mavg_to_remove = 0, mavg_to_add = 0; double mavg_cumulated = 0; - QCPAxis *x_axis = nullptr; if (graph_) { graph_->data()->clear(); - x_axis = graph_->keyAxis(); } if (bars_) { bars_->data()->clear(); - x_axis = bars_->keyAxis(); } if (moving_avg_period_ > 0 && cur_idx_ >= 0) { @@ -2054,7 +2608,7 @@ void IOGraph::recalcGraphData(capture_file *cap_file, bool enable_scaling) * just to make sure average on leftmost and rightmost displayed * values is as reliable as possible */ - guint64 warmup_interval = 0; + uint64_t warmup_interval = 0; // for (; warmup_interval < first_interval; warmup_interval += interval_) { // mavg_cumulated += get_it_value(io, i, (int)warmup_interval/interval_); @@ -2064,8 +2618,8 @@ void IOGraph::recalcGraphData(capture_file *cap_file, bool enable_scaling) mavg_cumulated += getItemValue((int)warmup_interval/interval_, cap_file); mavg_in_average_count++; for (warmup_interval = interval_; - ((warmup_interval < (0 + (moving_avg_period_ / 2) * (guint64)interval_)) && - (warmup_interval <= (cur_idx_ * (guint64)interval_))); + ((warmup_interval < (0 + (moving_avg_period_ / 2) * (uint64_t)interval_)) && + (warmup_interval <= (cur_idx_ * (uint64_t)interval_))); warmup_interval += interval_) { mavg_cumulated += getItemValue((int)warmup_interval / interval_, cap_file); @@ -2074,11 +2628,9 @@ void IOGraph::recalcGraphData(capture_file *cap_file, bool enable_scaling) mavg_to_add = (unsigned int)warmup_interval; } + double ts_offset = startOffset(); for (int i = 0; i <= cur_idx_; i++) { - double ts = (double) i * interval_ / 1000; - if (x_axis && qSharedPointerDynamicCast(x_axis->ticker())) { - ts += start_time_; - } + double ts = (double) i * interval_ / SCALE_F + ts_offset; double val = getItemValue(i, cap_file); if (moving_avg_period_ > 0) { @@ -2112,73 +2664,46 @@ void IOGraph::recalcGraphData(capture_file *cap_file, bool enable_scaling) bars_->addData(ts, val); } } -// qDebug() << "=rgd i" << i << ts << val; - } - - // attempt to rescale time values to specific units - if (enable_scaling) { - calculateScaledValueUnit(); - } else { - scaled_value_unit_.clear(); } emit requestReplot(); } -void IOGraph::calculateScaledValueUnit() +format_size_units_e IOGraph::formatUnits() const { - // Reset unit and recalculate if needed. - scaled_value_unit_.clear(); - - // If there is no field, scaling is not possible. - if (hf_index_ < 0) { - return; - } - switch (val_units_) { + case IOG_ITEM_UNIT_PACKETS: + case IOG_ITEM_UNIT_CALC_FRAMES: + if (is_packet_configuration_namespace()) { + return FORMAT_SIZE_UNIT_PACKETS; + } + return FORMAT_SIZE_UNIT_EVENTS; + case IOG_ITEM_UNIT_BYTES: + return FORMAT_SIZE_UNIT_BYTES; + case IOG_ITEM_UNIT_BITS: + return FORMAT_SIZE_UNIT_BITS; + case IOG_ITEM_UNIT_CALC_LOAD: + return FORMAT_SIZE_UNIT_ERLANGS; + case IOG_ITEM_UNIT_CALC_FIELDS: + return FORMAT_SIZE_UNIT_FIELDS; case IOG_ITEM_UNIT_CALC_SUM: case IOG_ITEM_UNIT_CALC_MAX: case IOG_ITEM_UNIT_CALC_MIN: case IOG_ITEM_UNIT_CALC_AVERAGE: // Unit is not yet known, continue detecting it. - break; - default: - // Unit is Packets, Bytes, Bits, etc. - return; - } - - if (proto_registrar_get_ftype(hf_index_) == FT_RELATIVE_TIME) { - // find maximum absolute value and scale accordingly - double maxValue = 0; - if (graph_) { - maxValue = maxValueFromGraphData(*graph_->data()); - } else if (bars_) { - maxValue = maxValueFromGraphData(*bars_->data()); - } - // If the maximum value is zero, then either we have no data or - // everything is zero, do not scale the unit in this case. - if (maxValue == 0) { - return; - } - - // XXX GTK+ always uses "ms" for log scale, should we do that too? - int value_multiplier; - if (maxValue >= 1.0) { - scaled_value_unit_ = "s"; - value_multiplier = 1; - } else if (maxValue >= 0.001) { - scaled_value_unit_ = "ms"; - value_multiplier = 1000; - } else { - scaled_value_unit_ = "us"; - value_multiplier = 1000000; - } - - if (graph_) { - scaleGraphData(*graph_->data(), value_multiplier); - } else if (bars_) { - scaleGraphData(*bars_->data(), value_multiplier); + if (hf_index_ > 0) { + if (proto_registrar_get_ftype(hf_index_) == FT_RELATIVE_TIME) { + return FORMAT_SIZE_UNIT_SECONDS; + } + // Could we look if it's BASE_UNIT_STRING and use that? + // One complication is that prefixes shouldn't be combined, + // and some unit strings are already prefixed units. } + return FORMAT_SIZE_UNIT_NONE; + case IOG_ITEM_UNIT_CALC_THROUGHPUT: + return FORMAT_SIZE_UNIT_BITS_S; + default: + return FORMAT_SIZE_UNIT_NONE; } } @@ -2211,7 +2736,7 @@ void IOGraph::captureEvent(CaptureEvent e) if ((e.captureContext() == CaptureEvent::File) && (e.eventType() == CaptureEvent::Closing)) { - remove_tap_listener(this); + removeTapListener(); } } @@ -2222,6 +2747,38 @@ void IOGraph::reloadValueUnitField() } } +// returns true if the current plot style shows zero values, +// false if null values are omitted. +bool IOGraph::showsZero() const +{ + switch (val_units_) { + case IOG_ITEM_UNIT_PACKETS: + case IOG_ITEM_UNIT_BYTES: + case IOG_ITEM_UNIT_BITS: + case IOG_ITEM_UNIT_CALC_FRAMES: + case IOG_ITEM_UNIT_CALC_FIELDS: + if (graph_ && graph_->lineStyle() == QCPGraph::lsNone) { + return false; + } + else { + return true; + } + case IOG_ITEM_UNIT_CALC_SUM: + case IOG_ITEM_UNIT_CALC_MAX: + case IOG_ITEM_UNIT_CALC_MIN: + case IOG_ITEM_UNIT_CALC_AVERAGE: + case IOG_ITEM_UNIT_CALC_LOAD: + case IOG_ITEM_UNIT_CALC_THROUGHPUT: + // These are not the same sort of "omitted zeros" as above, + // but changing val_units_ always results in a recalculation + // so it doesn't matter (see modelDataChanged) + return false; + + default: + return true; + } +} + // Check if a packet is available at the given interval (idx). bool IOGraph::hasItemToShow(int idx, double value) const { @@ -2237,7 +2794,7 @@ bool IOGraph::hasItemToShow(int idx, double value) const case IOG_ITEM_UNIT_BITS: case IOG_ITEM_UNIT_CALC_FRAMES: case IOG_ITEM_UNIT_CALC_FIELDS: - if(value == 0.0 && (graph_ && graph_->scatterStyle().shape() != QCPScatterStyle::ssNone)) { + if (value == 0.0 && (graph_ && graph_->lineStyle() == QCPGraph::lsNone)) { result = false; } else { @@ -2250,6 +2807,7 @@ bool IOGraph::hasItemToShow(int idx, double value) const case IOG_ITEM_UNIT_CALC_MIN: case IOG_ITEM_UNIT_CALC_AVERAGE: case IOG_ITEM_UNIT_CALC_LOAD: + case IOG_ITEM_UNIT_CALC_THROUGHPUT: if (item->fields) { result = true; } @@ -2266,6 +2824,9 @@ bool IOGraph::hasItemToShow(int idx, double value) const void IOGraph::setInterval(int interval) { interval_ = interval; + if (bars_) { + bars_->setWidth(interval_ / SCALE_F); + } } // Get the value at the given interval (idx) for the current value unit. @@ -2273,7 +2834,7 @@ double IOGraph::getItemValue(int idx, const capture_file *cap_file) const { ws_assert(idx < max_io_items_); - return get_io_graph_item(items_, val_units_, idx, hf_index_, cap_file, interval_, cur_idx_); + return get_io_graph_item(&items_[0], val_units_, idx, hf_index_, cap_file, interval_, cur_idx_); } // "tap_reset" callback for register_tap_listener @@ -2294,27 +2855,60 @@ tap_packet_status IOGraph::tapPacket(void *iog_ptr, packet_info *pinfo, epan_dis return TAP_PACKET_DONT_REDRAW; } - int idx = get_io_graph_index(pinfo, iog->interval_); + int64_t tmp_idx = get_io_graph_index(pinfo, iog->interval_); bool recalc = false; /* some sanity checks */ - if ((idx < 0) || (idx >= max_io_items_)) { - iog->cur_idx_ = max_io_items_ - 1; + if ((tmp_idx < 0) || (tmp_idx >= max_io_items_)) { + iog->cur_idx_ = (int)iog->items_.size() - 1; return TAP_PACKET_DONT_REDRAW; } + int idx = (int)tmp_idx; + /* If the graph isn't visible, don't do the work or redraw, but mark + * the graph in need of a retap if it is ever enabled. The alternative + * is to do the work, but clear pending retaps when the taps are reset + * (which indicates something else triggered a retap.) The tradeoff would + * be more calculation and memory usage when a graph is disabled in + * exchange for fewer scenarios that involve retaps when toggling the + * enabled/disabled taps. + */ + if (!iog->visible()) { + if (idx > iog->cur_idx_) { + iog->need_retap_ = true; + } + return TAP_PACKET_DONT_REDRAW; + } + + if ((size_t)idx >= iog->items_.size()) { + const size_t old_size = iog->items_.size(); + size_t new_size; + if (old_size == 0) { + new_size = 1024; + } else { + new_size = MIN((old_size * 3) / 2, max_io_items_); + } + new_size = MAX(new_size, (size_t)idx + 1); + try { + iog->items_.resize(new_size); + } catch (std::bad_alloc&) { + // std::vector.resize() has strong exception safety + ws_warning("Failed memory allocation!"); + return TAP_PACKET_DONT_REDRAW; + } + // resize zero-initializes new items, which is what we want + //reset_io_graph_items(&iog->items_[old_size], new_size - old_size); + } + /* update num_items */ if (idx > iog->cur_idx_) { - iog->cur_idx_ = (guint32) idx; + iog->cur_idx_ = idx; recalc = true; } /* set start time */ - if (iog->start_time_ == 0.0) { - nstime_t start_nstime; - nstime_set_zero(&start_nstime); - nstime_delta(&start_nstime, &pinfo->abs_ts, &pinfo->rel_ts); - iog->start_time_ = nstime_to_sec(&start_nstime); + if (nstime_is_zero(&iog->start_time_)) { + nstime_delta(&iog->start_time_, &pinfo->abs_ts, &pinfo->rel_ts); } epan_dissect_t *adv_edt = NULL; @@ -2323,7 +2917,7 @@ tap_packet_status IOGraph::tapPacket(void *iog_ptr, packet_info *pinfo, epan_dis adv_edt = edt; } - if (!update_io_graph_item(iog->items_, idx, pinfo, adv_edt, iog->hf_index_, iog->val_units_, iog->interval_)) { + if (!update_io_graph_item(&iog->items_[0], idx, pinfo, adv_edt, iog->hf_index_, iog->val_units_, iog->interval_)) { return TAP_PACKET_DONT_REDRAW; } diff --git a/ui/qt/io_graph_dialog.h b/ui/qt/io_graph_dialog.h index f0bd4cdf..736ec93d 100644 --- a/ui/qt/io_graph_dialog.h +++ b/ui/qt/io_graph_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include "epan/epan_dissect.h" #include "epan/prefs.h" #include "ui/preference_utils.h" @@ -25,12 +23,20 @@ #include #include +#include + +#include #include #include #include +#include + +#include class QRubberBand; class QTimer; +class QAbstractButton; +class CopyFromProfileButton; class QCPBars; class QCPGraph; @@ -39,8 +45,16 @@ class QCustomPlot; class QCPAxisTicker; class QCPAxisTickerDateTime; -// GTK+ sets this to 100000 (NUM_IO_ITEMS) -const int max_io_items_ = 250000; +// GTK+ set this to 100000 (NUM_IO_ITEMS) before raising it to unlimited +// in commit 524583298beb671f43e972476693866754d38a38. +// This is the maximum index returned from get_io_graph_index that will +// be added to the graph. Thus, for a minimum interval size of 1 μs no +// more than 33.55 s. +// Each io_graph_item_t is 88 bytes on a system with 64 bit time_t, so +// the max size we'll attempt to allocate for the array of items is 2.75 GiB +// (plus a tiny amount extra for the std::vector bookkeeping.) +// 2^25 = 16777216 +const int max_io_items_ = 1 << 25; // XXX - Move to its own file? class IOGraph : public QObject { @@ -51,33 +65,37 @@ public: explicit IOGraph(QCustomPlot *parent); ~IOGraph(); - const QString configError() { return config_err_; } - const QString name() { return name_; } + QString configError() const { return config_err_; } + QString name() const { return name_; } void setName(const QString &name); - const QString filter() { return filter_; } - void setFilter(const QString &filter); + QString filter() const { return filter_; } + bool setFilter(const QString &filter); void applyCurrentColor(); - bool visible() { return visible_; } + bool visible() const { return visible_; } void setVisible(bool visible); - QRgb color(); + bool needRetap() const { return need_retap_; } + void setNeedRetap(bool retap); + QRgb color() const; void setColor(const QRgb color); void setPlotStyle(int style); - const QString valueUnitLabel(); + QString valueUnitLabel() const; + format_size_units_e formatUnits() const; + io_graph_item_unit_t valueUnits() const { return val_units_; } void setValueUnits(int val_units); - const QString valueUnitField() { return vu_field_; } + QString valueUnitField() const { return vu_field_; } void setValueUnitField(const QString &vu_field); - unsigned int movingAveragePeriod() { return moving_avg_period_; } + unsigned int movingAveragePeriod() const { return moving_avg_period_; } void setInterval(int interval); bool addToLegend(); bool removeFromLegend(); - QCPGraph *graph() { return graph_; } - QCPBars *bars() { return bars_; } - double startOffset(); - int packetFromTime(double ts); + QCPGraph *graph() const { return graph_; } + QCPBars *bars() const { return bars_; } + double startOffset() const; + nstime_t startTime() const; + int packetFromTime(double ts) const; bool hasItemToShow(int idx, double value) const; double getItemValue(int idx, const capture_file *cap_file) const; int maxInterval () const { return cur_idx_; } - QString scaledValueUnit() const { return scaled_value_unit_; } void clearAllData(); @@ -85,7 +103,7 @@ public: unsigned int y_axis_factor_; public slots: - void recalcGraphData(capture_file *cap_file, bool enable_scaling); + void recalcGraphData(capture_file *cap_file); void captureEvent(CaptureEvent e); void reloadValueUnitField(); @@ -100,28 +118,33 @@ private: static tap_packet_status tapPacket(void *iog_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *data, tap_flags_t flags); static void tapDraw(void *iog_ptr); - void calculateScaledValueUnit(); + void removeTapListener(); + + bool showsZero() const; + template double maxValueFromGraphData(const DataMap &map); template void scaleGraphData(DataMap &map, int scalar); QCustomPlot *parent_; QString config_err_; QString name_; + bool tap_registered_; bool visible_; + bool need_retap_; QCPGraph *graph_; QCPBars *bars_; QString filter_; + QString full_filter_; // Includes vu_field_ if used QBrush color_; io_graph_item_unit_t val_units_; QString vu_field_; int hf_index_; int interval_; - double start_time_; - QString scaled_value_unit_; + nstime_t start_time_; // Cached data. We should be able to change the Y axis without retapping as // much as is feasible. - io_graph_item_t items_[max_io_items_]; + std::vector items_; int cur_idx_; }; @@ -134,40 +157,50 @@ class IOGraphDialog : public WiresharkDialog Q_OBJECT public: - explicit IOGraphDialog(QWidget &parent, CaptureFile &cf, QString displayFilter = QString()); + explicit IOGraphDialog(QWidget &parent, CaptureFile &cf, QString displayFilter = QString(), io_graph_item_unit_t value_units = IOG_ITEM_UNIT_PACKETS, QString yfield = QString()); ~IOGraphDialog(); enum UatColumns { colEnabled = 0, colName, colDFilter, colColor, colStyle, colYAxis, colYField, colSMAPeriod, colYAxisFactor, colMaxNum}; void addGraph(bool checked, QString name, QString dfilter, QRgb color_idx, IOGraph::PlotStyles style, io_graph_item_unit_t value_units, QString yfield, int moving_average, int yaxisfactor); + void addGraph(bool checked, QString dfilter, io_graph_item_unit_t value_units, QString yfield); void addGraph(bool copy_from_current = false); void addDefaultGraph(bool enabled, int idx = 0); void syncGraphSettings(int row); + qsizetype graphCount() const; public slots: void scheduleReplot(bool now = false); void scheduleRecalc(bool now = false); void scheduleRetap(bool now = false); - void modelRowsReset(); void reloadFields(); protected: + void captureFileClosing(); void keyPressEvent(QKeyEvent *event); void reject(); +protected slots: + void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles); + void modelRowsReset(); + void modelRowsInserted(const QModelIndex &parent, int first, int last); + void modelRowsRemoved(const QModelIndex &parent, int first, int last); + void modelRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow); + signals: void goToPacket(int packet_num); - void recalcGraphData(capture_file *cap_file, bool enable_scaling); + void recalcGraphData(capture_file *cap_file); void intervalChanged(int interval); void reloadValueUnitFields(); private: Ui::IOGraphDialog *ui; + CopyFromProfileButton *copy_profile_bt_; //Model and delegate were chosen over UatFrame because add/remove/copy //buttons would need realignment (UatFrame has its own) - UatModel *uat_model_; + QPointer uat_model_; UatDelegate *uat_delegate_; // XXX - This needs to stay synced with UAT index @@ -176,8 +209,8 @@ private: QString hint_err_; QCPGraph *base_graph_; QCPItemTracer *tracer_; - guint32 packet_num_; - double start_time_; + uint32_t packet_num_; + nstime_t start_time_; bool mouse_drags_; QRubberBand *rubber_band_; QPoint rb_origin_; @@ -187,6 +220,7 @@ private: bool need_recalc_; // Medium weight: recalculate values, then replot bool need_retap_; // Heavy weight: re-read packet data bool auto_axes_; + int precision_; QSharedPointer number_ticker_; QSharedPointer datetime_ticker_; @@ -199,6 +233,7 @@ private: void panAxes(int x_pixels, int y_pixels); void toggleTracerStyle(bool force_default = false); void getGraphInfo(); + void updateHint(); void updateLegend(); QRectF getZoomRanges(QRect zoom_rect); void createIOGraph(int currentRow); @@ -209,22 +244,26 @@ private: bool graphIsEnabled(int row) const; private slots: + static void applyChanges(); + void copyFromProfile(QString filename); void updateWidgets(); + void showContextMenu(const QPoint &pos); void graphClicked(QMouseEvent *event); void mouseMoved(QMouseEvent *event); void mouseReleased(QMouseEvent *event); + void selectedFrameChanged(QList frames); + void moveLegend(); void resetAxes(); void updateStatistics(void); void copyAsCsvClicked(); + void graphUatSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void on_intervalComboBox_currentIndexChanged(int index); void on_todCheckBox_toggled(bool checked); - void modelDataChanged(const QModelIndex &index); void on_graphUat_currentItemChanged(const QModelIndex ¤t, const QModelIndex &previous); - void on_resetButton_clicked(); void on_logCheckBox_toggled(bool checked); void on_automaticUpdateCheckBox_toggled(bool checked); void on_enableLegendCheckBox_toggled(bool checked); @@ -257,6 +296,7 @@ private slots: void on_actionCrosshairs_triggered(); void on_buttonBox_helpRequested(); void on_buttonBox_accepted(); + void buttonBoxClicked(QAbstractButton *button); }; #endif // IO_GRAPH_DIALOG_H diff --git a/ui/qt/io_graph_dialog.ui b/ui/qt/io_graph_dialog.ui index 91f071ee..25cc41c7 100644 --- a/ui/qt/io_graph_dialog.ui +++ b/ui/qt/io_graph_dialog.ui @@ -72,7 +72,7 @@ - + 0 @@ -97,14 +97,14 @@ - Remove this graph. + Remove the selected graph(s). - Duplicate this graph. + Duplicate the selected graph(s). @@ -112,32 +112,32 @@ - + false - Clear all graphs. + Move the selected graph(s) upwards. - + false - Move this graph upwards. + Move the selected graph(s) downwards. - + false - Move this graph downwards. + Clear all graphs. @@ -290,26 +290,6 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Reset - - - @@ -318,7 +298,7 @@ Qt::Horizontal - QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Save + QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Save|QDialogButtonBox::Reset @@ -540,9 +520,14 @@

widgets/elided_label.h
- TabnavTreeView + RowMoveTreeView QTreeView -
widgets/tabnav_tree_view.h
+
widgets/rowmove_tree_view.h
+
+ + ResizeHeaderView + QHeaderView +
widgets/resize_header_view.h
StockIconToolButton @@ -555,6 +540,11 @@
widgets/qcustomplot.h
1
+ + QCPStringLegendItem + QCPAbstractLegendItem +
widgets/qcp_string_legend_item.h
+
diff --git a/ui/qt/layout_preferences_frame.cpp b/ui/qt/layout_preferences_frame.cpp index 07b97c57..693ef228 100644 --- a/ui/qt/layout_preferences_frame.cpp +++ b/ui/qt/layout_preferences_frame.cpp @@ -358,22 +358,22 @@ void LayoutPreferencesFrame::on_restoreButtonBox_clicked(QAbstractButton *) void LayoutPreferencesFrame::on_packetListSeparatorCheckBox_toggled(bool checked) { - prefs_set_bool_value(pref_packet_list_separator_, (gboolean) checked, pref_stashed); + prefs_set_bool_value(pref_packet_list_separator_, (bool) checked, pref_stashed); } void LayoutPreferencesFrame::on_packetListHeaderShowColumnDefinition_toggled(bool checked) { - prefs_set_bool_value(pref_packet_header_column_definition_, (gboolean) checked, pref_stashed); + prefs_set_bool_value(pref_packet_header_column_definition_, (bool) checked, pref_stashed); } void LayoutPreferencesFrame::on_packetListHoverStyleCheckbox_toggled(bool checked) { - prefs_set_bool_value(pref_packet_list_hover_style_, (gboolean) checked, pref_stashed); + prefs_set_bool_value(pref_packet_list_hover_style_, (bool) checked, pref_stashed); } void LayoutPreferencesFrame::on_packetListAllowSorting_toggled(bool checked) { - prefs_set_bool_value(pref_packet_list_sorting_, (gboolean) checked, pref_stashed); + prefs_set_bool_value(pref_packet_list_sorting_, (bool) checked, pref_stashed); } void LayoutPreferencesFrame::on_packetListCachedRowsLineEdit_textEdited(const QString &new_str) @@ -387,10 +387,10 @@ void LayoutPreferencesFrame::on_packetListCachedRowsLineEdit_textEdited(const QS void LayoutPreferencesFrame::on_statusBarShowSelectedPacketCheckBox_toggled(bool checked) { - prefs_set_bool_value(pref_show_selected_packet_, (gboolean) checked, pref_stashed); + prefs_set_bool_value(pref_show_selected_packet_, (bool) checked, pref_stashed); } void LayoutPreferencesFrame::on_statusBarShowFileLoadTimeCheckBox_toggled(bool checked) { - prefs_set_bool_value(pref_show_file_load_time_, (gboolean) checked, pref_stashed); + prefs_set_bool_value(pref_show_file_load_time_, (bool) checked, pref_stashed); } diff --git a/ui/qt/lbm_lbtrm_transport_dialog.cpp b/ui/qt/lbm_lbtrm_transport_dialog.cpp index 9391183e..9f8b9301 100644 --- a/ui/qt/lbm_lbtrm_transport_dialog.cpp +++ b/ui/qt/lbm_lbtrm_transport_dialog.cpp @@ -69,7 +69,7 @@ namespace static const double OneGigabit = OneMegabit * OneKilobit; } -static QString format_rate(const nstime_t & elapsed, guint64 bytes) +static QString format_rate(const nstime_t & elapsed, uint64_t bytes) { QString result; double elapsed_sec; @@ -143,15 +143,15 @@ static QString format_rate(const nstime_t & elapsed, guint64 bytes) class LBMLBTRMFrameEntry : public QTreeWidgetItem { public: - LBMLBTRMFrameEntry(guint32 frame); + LBMLBTRMFrameEntry(uint32_t frame); virtual ~LBMLBTRMFrameEntry(void) { } - guint32 getFrame(void) { return (m_frame); } + uint32_t getFrame(void) { return (m_frame); } private: - guint32 m_frame; + uint32_t m_frame; }; -LBMLBTRMFrameEntry::LBMLBTRMFrameEntry(guint32 frame) : +LBMLBTRMFrameEntry::LBMLBTRMFrameEntry(uint32_t frame) : QTreeWidgetItem(), m_frame(frame) { @@ -160,25 +160,25 @@ LBMLBTRMFrameEntry::LBMLBTRMFrameEntry(guint32 frame) : setText(Detail_Frame_Column, QString("%1").arg(m_frame)); } -typedef QMap LBMLBTRMFrameMap; -typedef QMap::iterator LBMLBTRMFrameMapIterator; +typedef QMap LBMLBTRMFrameMap; +typedef QMap::iterator LBMLBTRMFrameMapIterator; // A SQN (SeQuence Number) entry class LBMLBTRMSQNEntry : public QTreeWidgetItem { public: - LBMLBTRMSQNEntry(guint32 sqn); + LBMLBTRMSQNEntry(uint32_t sqn); virtual ~LBMLBTRMSQNEntry(void); - void processFrame(guint32 frame); + void processFrame(uint32_t frame); private: LBMLBTRMSQNEntry(void); - guint32 m_sqn; - guint32 m_count; + uint32_t m_sqn; + uint32_t m_count; LBMLBTRMFrameMap m_frames; }; -LBMLBTRMSQNEntry::LBMLBTRMSQNEntry(guint32 sqn) : +LBMLBTRMSQNEntry::LBMLBTRMSQNEntry(uint32_t sqn) : QTreeWidgetItem(), m_sqn(sqn), m_count(0), @@ -200,7 +200,7 @@ LBMLBTRMSQNEntry::~LBMLBTRMSQNEntry(void) m_frames.clear(); } -void LBMLBTRMSQNEntry::processFrame(guint32 frame) +void LBMLBTRMSQNEntry::processFrame(uint32_t frame) { LBMLBTRMFrameMapIterator it; @@ -221,19 +221,19 @@ void LBMLBTRMSQNEntry::processFrame(guint32 frame) class LBMLBTRMNCFReasonEntry : public QTreeWidgetItem { public: - LBMLBTRMNCFReasonEntry(guint8 reason); + LBMLBTRMNCFReasonEntry(uint8_t reason); virtual ~LBMLBTRMNCFReasonEntry(void); - void processFrame(guint32 frame); + void processFrame(uint32_t frame); private: LBMLBTRMNCFReasonEntry(void); - guint8 m_reason; + uint8_t m_reason; QString m_reason_string; - guint32 m_count; + uint32_t m_count; LBMLBTRMFrameMap m_frames; }; -LBMLBTRMNCFReasonEntry::LBMLBTRMNCFReasonEntry(guint8 reason) : +LBMLBTRMNCFReasonEntry::LBMLBTRMNCFReasonEntry(uint8_t reason) : QTreeWidgetItem(), m_reason(reason), m_reason_string(), @@ -273,7 +273,7 @@ LBMLBTRMNCFReasonEntry::~LBMLBTRMNCFReasonEntry(void) m_frames.clear(); } -void LBMLBTRMNCFReasonEntry::processFrame(guint32 frame) +void LBMLBTRMNCFReasonEntry::processFrame(uint32_t frame) { LBMLBTRMFrameMapIterator it; @@ -290,25 +290,25 @@ void LBMLBTRMNCFReasonEntry::processFrame(guint32 frame) setTextAlignment(Detail_Count_Column, Qt::AlignRight); } -typedef QMap LBMLBTRMNCFReasonMap; -typedef QMap::iterator LBMLBTRMNCFReasonMapIterator; +typedef QMap LBMLBTRMNCFReasonMap; +typedef QMap::iterator LBMLBTRMNCFReasonMapIterator; // An NCF SQN entry class LBMLBTRMNCFSQNEntry : public QTreeWidgetItem { public: - LBMLBTRMNCFSQNEntry(guint32 sqn); + LBMLBTRMNCFSQNEntry(uint32_t sqn); virtual ~LBMLBTRMNCFSQNEntry(void); - void processFrame(guint8 reason, guint32 frame); + void processFrame(uint8_t reason, uint32_t frame); private: LBMLBTRMNCFSQNEntry(void); - guint32 m_sqn; - guint32 m_count; + uint32_t m_sqn; + uint32_t m_count; LBMLBTRMNCFReasonMap m_reasons; }; -LBMLBTRMNCFSQNEntry::LBMLBTRMNCFSQNEntry(guint32 sqn) : +LBMLBTRMNCFSQNEntry::LBMLBTRMNCFSQNEntry(uint32_t sqn) : QTreeWidgetItem(), m_sqn(sqn), m_count(0), @@ -330,7 +330,7 @@ LBMLBTRMNCFSQNEntry::~LBMLBTRMNCFSQNEntry(void) m_reasons.clear(); } -void LBMLBTRMNCFSQNEntry::processFrame(guint8 reason, guint32 frame) +void LBMLBTRMNCFSQNEntry::processFrame(uint8_t reason, uint32_t frame) { LBMLBTRMNCFReasonMapIterator it; LBMLBTRMNCFReasonEntry * entry = NULL; @@ -353,10 +353,10 @@ void LBMLBTRMNCFSQNEntry::processFrame(guint8 reason, guint32 frame) entry->processFrame(frame); } -typedef QMap LBMLBTRMSQNMap; -typedef QMap::iterator LBMLBTRMSQNMapIterator; -typedef QMap LBMLBTRMNCFSQNMap; -typedef QMap::iterator LBMLBTRMNCFSQNMapIterator; +typedef QMap LBMLBTRMSQNMap; +typedef QMap::iterator LBMLBTRMSQNMapIterator; +typedef QMap LBMLBTRMNCFSQNMap; +typedef QMap::iterator LBMLBTRMNCFSQNMapIterator; // A source transport entry class LBMLBTRMSourceTransportEntry : public QTreeWidgetItem @@ -373,15 +373,15 @@ class LBMLBTRMSourceTransportEntry : public QTreeWidgetItem private: void fillItem(void); - guint64 m_data_frames; - guint64 m_data_bytes; - guint64 m_rx_data_frames; - guint64 m_rx_data_bytes; - guint64 m_ncf_frames; - guint64 m_ncf_count; - guint64 m_ncf_bytes; - guint64 m_sm_frames; - guint64 m_sm_bytes; + uint64_t m_data_frames; + uint64_t m_data_bytes; + uint64_t m_rx_data_frames; + uint64_t m_rx_data_bytes; + uint64_t m_ncf_frames; + uint64_t m_ncf_count; + uint64_t m_ncf_bytes; + uint64_t m_sm_frames; + uint64_t m_sm_bytes; nstime_t m_first_frame_timestamp; bool m_first_frame_timestamp_valid; nstime_t m_last_frame_timestamp; @@ -502,13 +502,13 @@ void LBMLBTRMSourceTransportEntry::processPacket(const packet_info * pinfo, cons } else if (tap_info->type == LBTRM_PACKET_TYPE_NCF) { - guint16 idx; + uint16_t idx; LBMLBTRMNCFSQNMapIterator it; LBMLBTRMNCFSQNEntry * sqn = NULL; m_ncf_frames++; m_ncf_bytes += pinfo->fd->pkt_len; - m_ncf_count += (guint64)tap_info->num_sqns; + m_ncf_count += (uint64_t)tap_info->num_sqns; for (idx = 0; idx < tap_info->num_sqns; idx++) { it = m_ncf_sqns.find(tap_info->sqns[idx]); @@ -612,15 +612,15 @@ class LBMLBTRMSourceEntry : public QTreeWidgetItem void fillItem(void); QString m_address; QString m_transport; - guint64 m_data_frames; - guint64 m_data_bytes; - guint64 m_rx_data_frames; - guint64 m_rx_data_bytes; - guint64 m_ncf_frames; - guint64 m_ncf_count; - guint64 m_ncf_bytes; - guint64 m_sm_frames; - guint64 m_sm_bytes; + uint64_t m_data_frames; + uint64_t m_data_bytes; + uint64_t m_rx_data_frames; + uint64_t m_rx_data_bytes; + uint64_t m_ncf_frames; + uint64_t m_ncf_count; + uint64_t m_ncf_bytes; + uint64_t m_sm_frames; + uint64_t m_sm_bytes; nstime_t m_first_frame_timestamp; bool m_first_frame_timestamp_valid; nstime_t m_last_frame_timestamp; @@ -783,9 +783,9 @@ class LBMLBTRMReceiverTransportEntry : public QTreeWidgetItem private: void fillItem(void); QString m_transport; - guint64 m_nak_frames; - guint64 m_nak_count; - guint64 m_nak_bytes; + uint64_t m_nak_frames; + uint64_t m_nak_count; + uint64_t m_nak_bytes; nstime_t m_first_frame_timestamp; bool m_first_frame_timestamp_valid; nstime_t m_last_frame_timestamp; @@ -839,7 +839,7 @@ void LBMLBTRMReceiverTransportEntry::processPacket(const packet_info * pinfo, co } if (tap_info->type == LBTRM_PACKET_TYPE_NAK) { - guint16 idx; + uint16_t idx; LBMLBTRMSQNEntry * sqn = NULL; LBMLBTRMSQNMapIterator it; @@ -899,9 +899,9 @@ class LBMLBTRMReceiverEntry : public QTreeWidgetItem void fillItem(void); QString m_address; QString m_transport; - guint64 m_nak_frames; - guint64 m_nak_count; - guint64 m_nak_bytes; + uint64_t m_nak_frames; + uint64_t m_nak_count; + uint64_t m_nak_bytes; nstime_t m_first_frame_timestamp; bool m_first_frame_timestamp_valid; nstime_t m_last_frame_timestamp; diff --git a/ui/qt/lbm_lbtrm_transport_dialog.h b/ui/qt/lbm_lbtrm_transport_dialog.h index 2e31dc50..5e6b66be 100644 --- a/ui/qt/lbm_lbtrm_transport_dialog.h +++ b/ui/qt/lbm_lbtrm_transport_dialog.h @@ -14,8 +14,6 @@ #include -#include - #include "cfile.h" #include #include diff --git a/ui/qt/lbm_lbtru_transport_dialog.cpp b/ui/qt/lbm_lbtru_transport_dialog.cpp index 529d7776..cc98c3d5 100644 --- a/ui/qt/lbm_lbtru_transport_dialog.cpp +++ b/ui/qt/lbm_lbtru_transport_dialog.cpp @@ -87,7 +87,7 @@ namespace static const double OneGigabit = OneMegabit * OneKilobit; } -static QString format_rate(const nstime_t & elapsed, guint64 bytes) +static QString format_rate(const nstime_t & elapsed, uint64_t bytes) { QString result; double elapsed_sec; @@ -161,15 +161,15 @@ static QString format_rate(const nstime_t & elapsed, guint64 bytes) class LBMLBTRUFrameEntry : public QTreeWidgetItem { public: - LBMLBTRUFrameEntry(guint32 frame); + LBMLBTRUFrameEntry(uint32_t frame); virtual ~LBMLBTRUFrameEntry(void) { } - guint32 getFrame(void) { return (m_frame); } + uint32_t getFrame(void) { return (m_frame); } private: - guint32 m_frame; + uint32_t m_frame; }; -LBMLBTRUFrameEntry::LBMLBTRUFrameEntry(guint32 frame) : +LBMLBTRUFrameEntry::LBMLBTRUFrameEntry(uint32_t frame) : QTreeWidgetItem(), m_frame(frame) { @@ -178,25 +178,25 @@ LBMLBTRUFrameEntry::LBMLBTRUFrameEntry(guint32 frame) : setText(Detail_Frame_Column, QString("%1").arg(m_frame)); } -typedef QMap LBMLBTRUFrameMap; -typedef QMap::iterator LBMLBTRUFrameMapIterator; +typedef QMap LBMLBTRUFrameMap; +typedef QMap::iterator LBMLBTRUFrameMapIterator; // An SQN (SeQuence Number) entry class LBMLBTRUSQNEntry : public QTreeWidgetItem { public: - LBMLBTRUSQNEntry(guint32 sqn); + LBMLBTRUSQNEntry(uint32_t sqn); virtual ~LBMLBTRUSQNEntry(void); - void processFrame(guint32 frame); + void processFrame(uint32_t frame); private: LBMLBTRUSQNEntry(void); - guint32 m_sqn; - guint32 m_count; + uint32_t m_sqn; + uint32_t m_count; LBMLBTRUFrameMap m_frames; }; -LBMLBTRUSQNEntry::LBMLBTRUSQNEntry(guint32 sqn) : +LBMLBTRUSQNEntry::LBMLBTRUSQNEntry(uint32_t sqn) : QTreeWidgetItem(), m_sqn(sqn), m_count(0), @@ -218,7 +218,7 @@ LBMLBTRUSQNEntry::~LBMLBTRUSQNEntry(void) m_frames.clear(); } -void LBMLBTRUSQNEntry::processFrame(guint32 frame) +void LBMLBTRUSQNEntry::processFrame(uint32_t frame) { LBMLBTRUFrameMapIterator it; @@ -239,18 +239,18 @@ void LBMLBTRUSQNEntry::processFrame(guint32 frame) class LBMLBTRUNCFReasonEntry : public QTreeWidgetItem { public: - LBMLBTRUNCFReasonEntry(guint8 reason); + LBMLBTRUNCFReasonEntry(uint8_t reason); virtual ~LBMLBTRUNCFReasonEntry(void); - void processFrame(guint32 frame); + void processFrame(uint32_t frame); private: LBMLBTRUNCFReasonEntry(void); - guint8 m_reason; - guint32 m_count; + uint8_t m_reason; + uint32_t m_count; LBMLBTRUFrameMap m_frames; }; -LBMLBTRUNCFReasonEntry::LBMLBTRUNCFReasonEntry(guint8 reason) : +LBMLBTRUNCFReasonEntry::LBMLBTRUNCFReasonEntry(uint8_t reason) : QTreeWidgetItem(), m_reason(reason), m_count(0), @@ -288,7 +288,7 @@ LBMLBTRUNCFReasonEntry::~LBMLBTRUNCFReasonEntry(void) m_frames.clear(); } -void LBMLBTRUNCFReasonEntry::processFrame(guint32 frame) +void LBMLBTRUNCFReasonEntry::processFrame(uint32_t frame) { LBMLBTRUFrameMapIterator it; @@ -305,25 +305,25 @@ void LBMLBTRUNCFReasonEntry::processFrame(guint32 frame) setTextAlignment(Detail_Count_Column, Qt::AlignRight); } -typedef QMap LBMLBTRUNCFReasonMap; -typedef QMap::iterator LBMLBTRUNCFReasonMapIterator; +typedef QMap LBMLBTRUNCFReasonMap; +typedef QMap::iterator LBMLBTRUNCFReasonMapIterator; // An NCF SQN entry class LBMLBTRUNCFSQNEntry : public QTreeWidgetItem { public: - LBMLBTRUNCFSQNEntry(guint32 sqn); + LBMLBTRUNCFSQNEntry(uint32_t sqn); virtual ~LBMLBTRUNCFSQNEntry(void); - void processFrame(guint8 reason, guint32 frame); + void processFrame(uint8_t reason, uint32_t frame); private: LBMLBTRUNCFSQNEntry(void); - guint32 m_sqn; - guint32 m_count; + uint32_t m_sqn; + uint32_t m_count; LBMLBTRUNCFReasonMap m_reasons; }; -LBMLBTRUNCFSQNEntry::LBMLBTRUNCFSQNEntry(guint32 sqn) : +LBMLBTRUNCFSQNEntry::LBMLBTRUNCFSQNEntry(uint32_t sqn) : QTreeWidgetItem(), m_sqn(sqn), m_count(0), @@ -345,7 +345,7 @@ LBMLBTRUNCFSQNEntry::~LBMLBTRUNCFSQNEntry(void) m_reasons.clear(); } -void LBMLBTRUNCFSQNEntry::processFrame(guint8 reason, guint32 frame) +void LBMLBTRUNCFSQNEntry::processFrame(uint8_t reason, uint32_t frame) { LBMLBTRUNCFReasonMapIterator it; LBMLBTRUNCFReasonEntry * entry = NULL; @@ -372,19 +372,19 @@ void LBMLBTRUNCFSQNEntry::processFrame(guint8 reason, guint32 frame) class LBMLBTRURSTReasonEntry : public QTreeWidgetItem { public: - LBMLBTRURSTReasonEntry(guint32 reason); + LBMLBTRURSTReasonEntry(uint32_t reason); virtual ~LBMLBTRURSTReasonEntry(void); - void processFrame(guint32 frame); + void processFrame(uint32_t frame); private: LBMLBTRURSTReasonEntry(void); - guint32 m_reason; + uint32_t m_reason; QString m_reason_string; - guint32 m_count; + uint32_t m_count; LBMLBTRUFrameMap m_frames; }; -LBMLBTRURSTReasonEntry::LBMLBTRURSTReasonEntry(guint32 reason) : +LBMLBTRURSTReasonEntry::LBMLBTRURSTReasonEntry(uint32_t reason) : QTreeWidgetItem(), m_reason(reason), m_reason_string(), @@ -416,7 +416,7 @@ LBMLBTRURSTReasonEntry::~LBMLBTRURSTReasonEntry(void) m_frames.clear(); } -void LBMLBTRURSTReasonEntry::processFrame(guint32 frame) +void LBMLBTRURSTReasonEntry::processFrame(uint32_t frame) { LBMLBTRUFrameMapIterator it; @@ -437,19 +437,19 @@ void LBMLBTRURSTReasonEntry::processFrame(guint32 frame) class LBMLBTRUCREQRequestEntry : public QTreeWidgetItem { public: - LBMLBTRUCREQRequestEntry(guint32 request); + LBMLBTRUCREQRequestEntry(uint32_t request); virtual ~LBMLBTRUCREQRequestEntry(void); - void processFrame(guint32 frame); + void processFrame(uint32_t frame); private: LBMLBTRUCREQRequestEntry(void); - guint32 m_request; + uint32_t m_request; QString m_request_string; - guint32 m_count; + uint32_t m_count; LBMLBTRUFrameMap m_frames; }; -LBMLBTRUCREQRequestEntry::LBMLBTRUCREQRequestEntry(guint32 request) : +LBMLBTRUCREQRequestEntry::LBMLBTRUCREQRequestEntry(uint32_t request) : QTreeWidgetItem(), m_request(request), m_request_string(), @@ -481,7 +481,7 @@ LBMLBTRUCREQRequestEntry::~LBMLBTRUCREQRequestEntry(void) m_frames.clear(); } -void LBMLBTRUCREQRequestEntry::processFrame(guint32 frame) +void LBMLBTRUCREQRequestEntry::processFrame(uint32_t frame) { LBMLBTRUFrameMapIterator it; @@ -498,14 +498,14 @@ void LBMLBTRUCREQRequestEntry::processFrame(guint32 frame) setTextAlignment(Detail_Count_Column, Qt::AlignRight); } -typedef QMap LBMLBTRUSQNMap; -typedef QMap::iterator LBMLBTRUSQNMapIterator; -typedef QMap LBMLBTRUNCFSQNMap; -typedef QMap::iterator LBMLBTRUNCFSQNMapIterator; -typedef QMap LBMLBTRURSTReasonMap; -typedef QMap::iterator LBMLBTRURSTReasonMapIterator; -typedef QMap LBMLBTRUCREQRequestMap; -typedef QMap::iterator LBMLBTRUCREQRequestMapIterator; +typedef QMap LBMLBTRUSQNMap; +typedef QMap::iterator LBMLBTRUSQNMapIterator; +typedef QMap LBMLBTRUNCFSQNMap; +typedef QMap::iterator LBMLBTRUNCFSQNMapIterator; +typedef QMap LBMLBTRURSTReasonMap; +typedef QMap::iterator LBMLBTRURSTReasonMapIterator; +typedef QMap LBMLBTRUCREQRequestMap; +typedef QMap::iterator LBMLBTRUCREQRequestMapIterator; // A source transport entry class LBMLBTRUSourceTransportEntry : public QTreeWidgetItem @@ -522,17 +522,17 @@ class LBMLBTRUSourceTransportEntry : public QTreeWidgetItem private: void fillItem(void); - guint64 m_data_frames; - guint64 m_data_bytes; - guint64 m_rx_data_frames; - guint64 m_rx_data_bytes; - guint64 m_ncf_frames; - guint64 m_ncf_count; - guint64 m_ncf_bytes; - guint64 m_sm_frames; - guint64 m_sm_bytes; - guint64 m_rst_frames; - guint64 m_rst_bytes; + uint64_t m_data_frames; + uint64_t m_data_bytes; + uint64_t m_rx_data_frames; + uint64_t m_rx_data_bytes; + uint64_t m_ncf_frames; + uint64_t m_ncf_count; + uint64_t m_ncf_bytes; + uint64_t m_sm_frames; + uint64_t m_sm_bytes; + uint64_t m_rst_frames; + uint64_t m_rst_bytes; nstime_t m_first_frame_timestamp; bool m_first_frame_timestamp_valid; nstime_t m_last_frame_timestamp; @@ -664,13 +664,13 @@ void LBMLBTRUSourceTransportEntry::processPacket(const packet_info * pinfo, cons } else if (tap_info->type == LBTRU_PACKET_TYPE_NCF) { - guint16 idx; + uint16_t idx; LBMLBTRUNCFSQNMapIterator it; LBMLBTRUNCFSQNEntry * sqn = NULL; m_ncf_frames++; m_ncf_bytes += pinfo->fd->pkt_len; - m_ncf_count += (guint64)tap_info->num_sqns; + m_ncf_count += (uint64_t)tap_info->num_sqns; for (idx = 0; idx < tap_info->num_sqns; idx++) { it = m_ncf_sqns.find(tap_info->sqns[idx]); @@ -801,17 +801,17 @@ class LBMLBTRUSourceEntry : public QTreeWidgetItem void fillItem(void); QString m_address; QString m_transport; - guint64 m_data_frames; - guint64 m_data_bytes; - guint64 m_rx_data_frames; - guint64 m_rx_data_bytes; - guint64 m_ncf_frames; - guint64 m_ncf_count; - guint64 m_ncf_bytes; - guint64 m_sm_frames; - guint64 m_sm_bytes; - guint64 m_rst_frames; - guint64 m_rst_bytes; + uint64_t m_data_frames; + uint64_t m_data_bytes; + uint64_t m_rx_data_frames; + uint64_t m_rx_data_bytes; + uint64_t m_ncf_frames; + uint64_t m_ncf_count; + uint64_t m_ncf_bytes; + uint64_t m_sm_frames; + uint64_t m_sm_bytes; + uint64_t m_rst_frames; + uint64_t m_rst_bytes; nstime_t m_first_frame_timestamp; bool m_first_frame_timestamp_valid; nstime_t m_last_frame_timestamp; @@ -988,13 +988,13 @@ class LBMLBTRUReceiverTransportEntry : public QTreeWidgetItem private: void fillItem(void); QString m_transport; - guint64 m_nak_frames; - guint64 m_nak_count; - guint64 m_nak_bytes; - guint64 m_ack_frames; - guint64 m_ack_bytes; - guint64 m_creq_frames; - guint64 m_creq_bytes; + uint64_t m_nak_frames; + uint64_t m_nak_count; + uint64_t m_nak_bytes; + uint64_t m_ack_frames; + uint64_t m_ack_bytes; + uint64_t m_creq_frames; + uint64_t m_creq_bytes; nstime_t m_first_frame_timestamp; bool m_first_frame_timestamp_valid; nstime_t m_last_frame_timestamp; @@ -1070,7 +1070,7 @@ void LBMLBTRUReceiverTransportEntry::processPacket(const packet_info * pinfo, co { case LBTRU_PACKET_TYPE_NAK: { - guint16 idx; + uint16_t idx; LBMLBTRUSQNEntry * sqn = NULL; LBMLBTRUSQNMapIterator it; @@ -1135,7 +1135,6 @@ void LBMLBTRUReceiverTransportEntry::processPacket(const packet_info * pinfo, co break; default: return; - break; } fillItem(); } @@ -1194,13 +1193,13 @@ class LBMLBTRUReceiverEntry : public QTreeWidgetItem void fillItem(void); QString m_address; QString m_transport; - guint64 m_nak_frames; - guint64 m_nak_count; - guint64 m_nak_bytes; - guint64 m_ack_frames; - guint64 m_ack_bytes; - guint64 m_creq_frames; - guint64 m_creq_bytes; + uint64_t m_nak_frames; + uint64_t m_nak_count; + uint64_t m_nak_bytes; + uint64_t m_ack_frames; + uint64_t m_ack_bytes; + uint64_t m_creq_frames; + uint64_t m_creq_bytes; nstime_t m_first_frame_timestamp; bool m_first_frame_timestamp_valid; nstime_t m_last_frame_timestamp; diff --git a/ui/qt/lbm_lbtru_transport_dialog.h b/ui/qt/lbm_lbtru_transport_dialog.h index 56590102..b606fe84 100644 --- a/ui/qt/lbm_lbtru_transport_dialog.h +++ b/ui/qt/lbm_lbtru_transport_dialog.h @@ -14,8 +14,6 @@ #include -#include - #include "cfile.h" #include #include diff --git a/ui/qt/lbm_stream_dialog.cpp b/ui/qt/lbm_stream_dialog.cpp index 65ddcc47..8988240b 100644 --- a/ui/qt/lbm_stream_dialog.cpp +++ b/ui/qt/lbm_stream_dialog.cpp @@ -44,9 +44,9 @@ namespace class LBMSubstreamEntry { public: - LBMSubstreamEntry(guint64 channel, guint32 substream_id, const address * source_address, guint16 source_port, const address * destination_address, guint16 destination_port); + LBMSubstreamEntry(uint64_t channel, uint32_t substream_id, const address * source_address, uint16_t source_port, const address * destination_address, uint16_t destination_port); ~LBMSubstreamEntry(void); - void processPacket(guint32 frame, guint32 bytes); + void processPacket(uint32_t frame, uint32_t bytes); void setItem(QTreeWidgetItem * item); QTreeWidgetItem * getItem(void) { @@ -54,22 +54,22 @@ class LBMSubstreamEntry } private: - void fillItem(gboolean update_only = TRUE); - guint64 m_channel; - guint32 m_substream_id; + void fillItem(bool update_only = true); + uint64_t m_channel; + uint32_t m_substream_id; QString m_endpoint_a; QString m_endpoint_b; - guint32 m_first_frame; - guint32 m_flast_frame; - guint32 m_messages; - guint32 m_bytes; + uint32_t m_first_frame; + uint32_t m_flast_frame; + uint32_t m_messages; + uint32_t m_bytes; QTreeWidgetItem * m_item; }; -LBMSubstreamEntry::LBMSubstreamEntry(guint64 channel, guint32 substream_id, const address * source_address, guint16 source_port, const address * destination_address, guint16 destination_port) : +LBMSubstreamEntry::LBMSubstreamEntry(uint64_t channel, uint32_t substream_id, const address * source_address, uint16_t source_port, const address * destination_address, uint16_t destination_port) : m_channel(channel), m_substream_id(substream_id), - m_first_frame((guint32)(~0)), + m_first_frame((uint32_t)(~0)), m_flast_frame(0), m_messages(0), m_bytes(0), @@ -87,7 +87,7 @@ LBMSubstreamEntry::~LBMSubstreamEntry(void) { } -void LBMSubstreamEntry::processPacket(guint32 frame, guint32 bytes) +void LBMSubstreamEntry::processPacket(uint32_t frame, uint32_t bytes) { if (m_first_frame > frame) { @@ -105,12 +105,12 @@ void LBMSubstreamEntry::processPacket(guint32 frame, guint32 bytes) void LBMSubstreamEntry::setItem(QTreeWidgetItem * item) { m_item = item; - fillItem(FALSE); + fillItem(false); } -void LBMSubstreamEntry::fillItem(gboolean update_only) +void LBMSubstreamEntry::fillItem(bool update_only) { - if (update_only == FALSE) + if (update_only == false) { m_item->setText(Stream_Column, QString("%1.%2").arg(m_channel).arg(m_substream_id)); m_item->setText(EndpointA_Column, m_endpoint_a); @@ -122,13 +122,13 @@ void LBMSubstreamEntry::fillItem(gboolean update_only) m_item->setText(LastFrame_Column, QString("%1").arg(m_flast_frame)); } -typedef QMap LBMSubstreamMap; -typedef QMap::iterator LBMSubstreamMapIterator; +typedef QMap LBMSubstreamMap; +typedef QMap::iterator LBMSubstreamMapIterator; class LBMStreamEntry { public: - LBMStreamEntry(const packet_info * pinfo, guint64 channel, const lbm_uim_stream_endpoint_t * endpoint_a, const lbm_uim_stream_endpoint_t * endpoint_b); + LBMStreamEntry(const packet_info * pinfo, uint64_t channel, const lbm_uim_stream_endpoint_t * endpoint_a, const lbm_uim_stream_endpoint_t * endpoint_b); ~LBMStreamEntry(void); void processPacket(const packet_info * pinfo, const lbm_uim_stream_tap_info_t * stream_info); void setItem(QTreeWidgetItem * item); @@ -138,22 +138,22 @@ class LBMStreamEntry } private: - void fillItem(gboolean update_only = TRUE); + void fillItem(bool update_only = true); QString formatEndpoint(const packet_info * pinfo, const lbm_uim_stream_endpoint_t * endpoint); - guint64 m_channel; + uint64_t m_channel; QString m_endpoint_a; QString m_endpoint_b; - guint32 m_first_frame; - guint32 m_flast_frame; - guint32 m_messages; - guint32 m_bytes; + uint32_t m_first_frame; + uint32_t m_flast_frame; + uint32_t m_messages; + uint32_t m_bytes; QTreeWidgetItem * m_item; LBMSubstreamMap m_substreams; }; -LBMStreamEntry::LBMStreamEntry(const packet_info * pinfo, guint64 channel, const lbm_uim_stream_endpoint_t * endpoint_a, const lbm_uim_stream_endpoint_t * endpoint_b) : +LBMStreamEntry::LBMStreamEntry(const packet_info * pinfo, uint64_t channel, const lbm_uim_stream_endpoint_t * endpoint_a, const lbm_uim_stream_endpoint_t * endpoint_b) : m_channel(channel), - m_first_frame((guint32)(~0)), + m_first_frame((uint32_t)(~0)), m_flast_frame(0), m_messages(0), m_bytes(0), @@ -228,12 +228,12 @@ void LBMStreamEntry::processPacket(const packet_info * pinfo, const lbm_uim_stre void LBMStreamEntry::setItem(QTreeWidgetItem * item) { m_item = item; - fillItem(FALSE); + fillItem(false); } -void LBMStreamEntry::fillItem(gboolean update_only) +void LBMStreamEntry::fillItem(bool update_only) { - if (update_only == FALSE) + if (update_only == false) { m_item->setData(Stream_Column, Qt::DisplayRole, QVariant((qulonglong)m_channel)); m_item->setText(EndpointA_Column, m_endpoint_a); @@ -245,8 +245,8 @@ void LBMStreamEntry::fillItem(gboolean update_only) m_item->setText(LastFrame_Column, QString("%1").arg(m_flast_frame)); } -typedef QMap LBMStreamMap; -typedef QMap::iterator LBMStreamMapIterator; +typedef QMap LBMStreamMap; +typedef QMap::iterator LBMStreamMapIterator; class LBMStreamDialogInfo { diff --git a/ui/qt/lbm_stream_dialog.h b/ui/qt/lbm_stream_dialog.h index 0bc75d29..0efc141d 100644 --- a/ui/qt/lbm_stream_dialog.h +++ b/ui/qt/lbm_stream_dialog.h @@ -14,8 +14,6 @@ #include -#include - #include "cfile.h" #include #include diff --git a/ui/qt/lte_mac_statistics_dialog.cpp b/ui/qt/lte_mac_statistics_dialog.cpp index 691128ea..7646caf3 100644 --- a/ui/qt/lte_mac_statistics_dialog.cpp +++ b/ui/qt/lte_mac_statistics_dialog.cpp @@ -25,6 +25,7 @@ // Whole-UE headings. enum { + col_rat_, col_rnti_, col_type_, col_ueid_, @@ -56,7 +57,7 @@ enum { // Calculate and return a bandwidth figure, in Mbs static double calculate_bw(const nstime_t *start_time, const nstime_t *stop_time, - guint32 bytes) + uint32_t bytes) { // Can only calculate bandwidth if have time delta if (memcmp(start_time, stop_time, sizeof(nstime_t)) != 0) { @@ -83,13 +84,14 @@ static double calculate_bw(const nstime_t *start_time, const nstime_t *stop_time class MacULDLTreeWidgetItem : public QTreeWidgetItem { public: - MacULDLTreeWidgetItem(QTreeWidgetItem *parent, unsigned ueid, unsigned rnti, int row_type) : + MacULDLTreeWidgetItem(QTreeWidgetItem *parent, unsigned ueid, unsigned rnti, unsigned rat, int row_type) : QTreeWidgetItem (parent, row_type), ueid_(ueid), - rnti_(rnti) + rnti_(rnti), + rat_(rat) { // Init values held for all lcids to 0. - for (int n=0; n < MAC_LTE_DATA_LCID_COUNT_MAX; n++) { + for (int n=0; n < MAC_3GPP_DATA_LCID_COUNT_MAX; n++) { lcids[n] = 0; } @@ -124,43 +126,62 @@ public: // Show current value of counter for each LCID. // N.B. fields that are set as % using percent_bar_delegate.h // for UE headings don't display here... - for (int n=0; n < MAC_LTE_DATA_LCID_COUNT_MAX; n++) { + for (int n=0; n < MAC_3GPP_DATA_LCID_COUNT_MAX; n++) { setText(col_type_+n, QString::number((uint)lcids[n])); } } // Increase value held for lcid by given value. - void updateLCID(guint8 lcid, guint value) + void updateLCID(uint8_t lcid, unsigned value) { lcids[lcid] += value; } // Generate expression for this UE and direction, also filter for SRs and RACH if indicated. - const QString filterExpression(bool showSR, bool showRACH) { + const QString filterExpression(bool showSR, bool showRACH) + { int direction = (type() == mac_dlsch_packet_count_row_type) || (type() == mac_dlsch_byte_count_row_type); QString filter_expr; if (showSR) { - filter_expr = QString("(mac-lte.sr-req and mac-lte.ueid == %1) or (").arg(ueid_); + // Only applies to LTE. + if (rat_ == MAC_RAT_LTE) { + filter_expr = QString("(mac-lte.sr-req and mac-lte.ueid == %1) or (").arg(ueid_); + } } if (showRACH) { - filter_expr += QString("(mac-lte.rar or (mac-lte.preamble-sent and mac-lte.ueid == %1)) or (").arg(ueid_); + if (rat_ == MAC_RAT_LTE) { + filter_expr += QString("(mac-lte.rar or (mac-lte.preamble-sent and mac-lte.ueid == %1)) or (").arg(ueid_); + } + else { + filter_expr += QString("mac-nr.rar or "); + } } // Main expression matching this UE and direction - filter_expr += QString("mac-lte.ueid==%1 && mac-lte.rnti==%2 && mac-lte.direction==%3"). - arg(ueid_).arg(rnti_).arg(direction); + if (rat_ == MAC_RAT_LTE) { + filter_expr += QString("mac-lte.ueid==%1 && mac-lte.rnti==%2 && mac-lte.direction==%3"). + arg(ueid_).arg(rnti_).arg(direction); + } + else { + filter_expr += QString("mac-nr.ueid==%1 && mac-nr.rnti==%2 && mac-nr.direction==%3"). + arg(ueid_).arg(rnti_).arg(direction); + } // Close () if open because of SR if (showSR) { - filter_expr += QString(")"); + if (rat_ == MAC_RAT_LTE) { + filter_expr += QString(")"); + } } // Close () if open because of RACH if (showRACH) { - filter_expr += QString(")"); + if (rat_ == MAC_RAT_LTE) { + filter_expr += QString(")"); + } } return filter_expr; @@ -176,7 +197,8 @@ public: private: unsigned ueid_; unsigned rnti_; - int lcids[MAC_LTE_DATA_LCID_COUNT_MAX]; /* 0 to 10 and 32 to 38 */ + unsigned rat_; + int lcids[MAC_3GPP_DATA_LCID_COUNT_MAX]; /* For LTE, mapped to 0 to 10 and 32 to 38 */ }; @@ -185,7 +207,7 @@ private: class MacUETreeWidgetItem : public QTreeWidgetItem { public: - MacUETreeWidgetItem(QTreeWidget *parent, const mac_lte_tap_info *mlt_info) : + MacUETreeWidgetItem(QTreeWidget *parent, const mac_3gpp_tap_info *mlt_info) : QTreeWidgetItem (parent, mac_whole_ue_row_type_), rnti_(0), type_(0), @@ -203,9 +225,13 @@ public: dl_retx_(0) { // Set fixed fields. - rnti_ = mlt_info->rnti; - type_ = mlt_info->rntiType; - ueid_ = mlt_info->ueid; + rnti_ = mlt_info->rnti; + type_ = mlt_info->rntiType; + ueid_ = mlt_info->ueid; + rat_ = mlt_info->rat; + setText(col_rat_, (mlt_info->rat == MAC_RAT_LTE) ? + QObject::tr("LTE") : + QObject::tr("NR")); setText(col_rnti_, QString::number(rnti_)); setText(col_type_, type_ == C_RNTI ? QObject::tr("C-RNTI") : QObject::tr("SPS-RNTI")); setText(col_ueid_, QString::number(ueid_)); @@ -215,14 +241,15 @@ public: } // Does this tap-info match this existing UE item? - bool isMatch(const mac_lte_tap_info *mlt_info) { + bool isMatch(const mac_3gpp_tap_info *mlt_info) { return ((rnti_ == mlt_info->rnti) && (type_ == mlt_info->rntiType) && - (ueid_ == mlt_info->ueid)); + (ueid_ == mlt_info->ueid) && + (rat_ == mlt_info->rat)); } // Update this UE according to the tap info - void update(const mac_lte_tap_info *mlt_info) { + void update(const mac_3gpp_tap_info *mlt_info) { // Uplink. if (mlt_info->direction == DIRECTION_UPLINK) { @@ -239,9 +266,9 @@ public: // Update time range if (ul_frames_ == 0) { - ul_time_start_ = mlt_info->mac_lte_time; + ul_time_start_ = mlt_info->mac_time; } - ul_time_stop_ = mlt_info->mac_lte_time; + ul_time_stop_ = mlt_info->mac_time; ul_frames_++; @@ -251,7 +278,7 @@ public: // N.B. Not going to support predefined data in Qt version.. if (!mlt_info->isPredefinedData) { - for (int n=0; n < MAC_LTE_DATA_LCID_COUNT_MAX; n++) { + for (int n=0; n < MAC_3GPP_DATA_LCID_COUNT_MAX; n++) { // Update UL child items ul_frames_item_->updateLCID(n, mlt_info->sdus_for_lcid[n]); ul_bytes_item_->updateLCID(n, mlt_info->bytes_for_lcid[n]); @@ -283,9 +310,9 @@ public: // Update time range if (dl_frames_ == 0) { - dl_time_start_ = mlt_info->mac_lte_time; + dl_time_start_ = mlt_info->mac_time; } - dl_time_stop_ = mlt_info->mac_lte_time; + dl_time_stop_ = mlt_info->mac_time; dl_frames_++; @@ -295,7 +322,7 @@ public: // N.B. Not going to support predefined data in Qt version.. if (!mlt_info->isPredefinedData) { - for (int n=0; n < MAC_LTE_DATA_LCID_COUNT_MAX; n++) { + for (int n=0; n < MAC_3GPP_DATA_LCID_COUNT_MAX; n++) { // Update DL child items dl_frames_item_->updateLCID(n, mlt_info->sdus_for_lcid[n]); dl_bytes_item_->updateLCID(n, mlt_info->bytes_for_lcid[n]); @@ -308,10 +335,10 @@ public: void addDetails() { // Add UL/DL packet and byte counts. - ul_frames_item_ = new MacULDLTreeWidgetItem(this, ueid_, rnti_, mac_ulsch_packet_count_row_type); - ul_bytes_item_ = new MacULDLTreeWidgetItem(this, ueid_, rnti_, mac_ulsch_byte_count_row_type); - dl_frames_item_ = new MacULDLTreeWidgetItem(this, ueid_, rnti_, mac_dlsch_packet_count_row_type); - dl_bytes_item_ = new MacULDLTreeWidgetItem(this, ueid_, rnti_, mac_dlsch_byte_count_row_type); + ul_frames_item_ = new MacULDLTreeWidgetItem(this, ueid_, rnti_, rat_, mac_ulsch_packet_count_row_type); + ul_bytes_item_ = new MacULDLTreeWidgetItem(this, ueid_, rnti_, rat_, mac_ulsch_byte_count_row_type); + dl_frames_item_ = new MacULDLTreeWidgetItem(this, ueid_, rnti_, rat_, mac_dlsch_packet_count_row_type); + dl_bytes_item_ = new MacULDLTreeWidgetItem(this, ueid_, rnti_, rat_, mac_dlsch_byte_count_row_type); setExpanded(false); } @@ -382,23 +409,39 @@ public: QString filter_expr; if (showSR) { - filter_expr = QString("(mac-lte.sr-req and mac-lte.ueid == %1) or (").arg(ueid_); + if (rat_ == MAC_RAT_LTE) { + filter_expr = QString("(mac-lte.sr-req and mac-lte.ueid == %1) or (").arg(ueid_); + } } if (showRACH) { - filter_expr += QString("(mac-lte.rar or (mac-lte.preamble-sent and mac-lte.ueid == %1)) or (").arg(ueid_); + if (rat_ == MAC_RAT_LTE) { + filter_expr += QString("(mac-lte.rar or (mac-lte.preamble-sent and mac-lte.ueid == %1)) or (").arg(ueid_); + } + else { + filter_expr += QString("mac-nr.rar or "); + } } // Main expression matching this UE - filter_expr += QString("mac-lte.ueid==%1 && mac-lte.rnti==%2").arg(ueid_).arg(rnti_); + if (rat_ == MAC_RAT_LTE) { + filter_expr += QString("mac-lte.ueid==%1 && mac-lte.rnti==%2").arg(ueid_).arg(rnti_); + } + else { + filter_expr += QString("mac-nr.ueid==%1 && mac-nr.rnti==%2").arg(ueid_).arg(rnti_); + } // Close () if open because of SR if (showSR) { - filter_expr += QString(")"); + if (rat_ == MAC_RAT_LTE) { + filter_expr += QString(")"); + } } // Close () if open because of RACH if (showRACH) { - filter_expr += QString(")"); + if (rat_ == MAC_RAT_LTE) { + filter_expr += QString(")"); + } } return filter_expr; @@ -432,6 +475,7 @@ public: private: // Unchanging (key) fields. + uint8_t rat_; unsigned rnti_; unsigned type_; unsigned ueid_; @@ -467,7 +511,7 @@ private: // Label headings. Show according to which type of tree item is currently selected. static const QStringList mac_whole_ue_row_labels = QStringList() - << QObject::tr("RNTI") << QObject::tr("Type") << QObject::tr("UEId") + << QObject::tr("RAT") << QObject::tr("RNTI") << QObject::tr("Type") << QObject::tr("UEId") << QObject::tr("UL Frames") << QObject::tr("UL Bytes") << QObject::tr("UL MB/s") << QObject::tr("UL Padding %") << QObject::tr("UL Re TX") << QObject::tr("DL Frames") << QObject::tr("DL Bytes") << QObject::tr("DL MB/s") @@ -477,7 +521,7 @@ static const QStringList mac_whole_ue_row_labels = QStringList() << QObject::tr("") << QObject::tr("") << QObject::tr("") << QObject::tr("") << QObject::tr(""); static const QStringList mac_channel_counts_labels = QStringList() - << QObject::tr("") << QObject::tr("CCCH") + << QObject::tr("") << QObject::tr("") << QObject::tr("CCCH") << QObject::tr("LCID 1") << QObject::tr("LCID 2") << QObject::tr("LCID 3") << QObject::tr("LCID 4") << QObject::tr("LCID 5") << QObject::tr("LCID 6") << QObject::tr("LCID 7") << QObject::tr("LCID 8") << QObject::tr("LCID 9") @@ -495,7 +539,7 @@ LteMacStatisticsDialog::LteMacStatisticsDialog(QWidget &parent, CaptureFile &cf, TapParameterDialog(parent, cf, HELP_STATS_LTE_MAC_TRAFFIC_DIALOG), commonStatsCurrent_(false) { - setWindowSubtitle(tr("LTE Mac Statistics")); + setWindowSubtitle(tr("LTE/NR Mac Statistics")); loadGeometry(parent.width() * 1, parent.height() * 3 / 4, "LTEMacStatisticsDialog"); clearCommonStats(); @@ -617,7 +661,7 @@ LteMacStatisticsDialog::~LteMacStatisticsDialog() } // Update system/common counters, and redraw if changed. -void LteMacStatisticsDialog::updateCommonStats(const mac_lte_tap_info *tap_info) +void LteMacStatisticsDialog::updateCommonStats(const mac_3gpp_tap_info *tap_info) { commonStats_.all_frames++; @@ -719,11 +763,11 @@ void LteMacStatisticsDialog::tapReset(void *ws_dlg_ptr) //--------------------------------------------------------------------------------------- // Process tap info from a new packet. // Returns TAP_PACKET_REDRAW if a redraw is needed, TAP_PACKET_DONT_REDRAW otherwise. -tap_packet_status LteMacStatisticsDialog::tapPacket(void *ws_dlg_ptr, struct _packet_info *, epan_dissect *, const void *mac_lte_tap_info_ptr, tap_flags_t) +tap_packet_status LteMacStatisticsDialog::tapPacket(void *ws_dlg_ptr, struct _packet_info *, epan_dissect *, const void *mac_3gpp_tap_info_ptr, tap_flags_t) { // Look up dialog and tap info. LteMacStatisticsDialog *ws_dlg = static_cast(ws_dlg_ptr); - const mac_lte_tap_info *mlt_info = (const mac_lte_tap_info *) mac_lte_tap_info_ptr; + const mac_3gpp_tap_info *mlt_info = (const mac_3gpp_tap_info *)mac_3gpp_tap_info_ptr; if (!ws_dlg || !mlt_info) { return TAP_PACKET_DONT_REDRAW; } @@ -799,7 +843,7 @@ void LteMacStatisticsDialog::tapDraw(void *ws_dlg_ptr) ws_dlg->drawCommonStats(); // Update title - ws_dlg->setWindowSubtitle(QString("LTE Mac Statistics (%1 UEs, %2 frames)"). + ws_dlg->setWindowSubtitle(QString("3GPP Mac Statistics (%1 UEs, %2 frames)"). arg(ws_dlg->statsTreeWidget()->topLevelItemCount()).arg(ws_dlg->getFrameCount())); } @@ -825,7 +869,7 @@ const QString LteMacStatisticsDialog::filterExpression() void LteMacStatisticsDialog::fillTree() { - if (!registerTapListener("mac-lte", + if (!registerTapListener("mac-3gpp", this, displayFilter_.toLatin1().data(), TL_REQUIRES_NOTHING, @@ -910,12 +954,12 @@ lte_mac_statistics_init(const char *args, void*) { } static stat_tap_ui lte_mac_statistics_ui = { - REGISTER_STAT_GROUP_TELEPHONY_LTE, + REGISTER_TELEPHONY_GROUP_3GPP_UU, QT_TRANSLATE_NOOP("LteMacStatisticsDialog", "MAC Statistics"), - "mac-lte,stat", + "mac-3gpp,stat", // cli_string lte_mac_statistics_init, - 0, - NULL + 0, // nparams + NULL // params }; extern "C" { diff --git a/ui/qt/lte_mac_statistics_dialog.h b/ui/qt/lte_mac_statistics_dialog.h index 411d0614..c3ea692d 100644 --- a/ui/qt/lte_mac_statistics_dialog.h +++ b/ui/qt/lte_mac_statistics_dialog.h @@ -18,20 +18,20 @@ #include // Common channel stats -typedef struct mac_lte_common_stats { - guint32 all_frames; - guint32 mib_frames; - guint32 sib_frames; - guint32 sib_bytes; - guint32 pch_frames; - guint32 pch_bytes; - guint32 pch_paging_ids; - guint32 rar_frames; - guint32 rar_entries; - - guint16 max_ul_ues_in_tti; - guint16 max_dl_ues_in_tti; -} mac_lte_common_stats; +typedef struct mac_3gpp_common_stats { + uint32_t all_frames; + uint32_t mib_frames; + uint32_t sib_frames; + uint32_t sib_bytes; + uint32_t pch_frames; + uint32_t pch_bytes; + uint32_t pch_paging_ids; + uint32_t rar_frames; + uint32_t rar_entries; + + uint16_t max_ul_ues_in_tti; + uint16_t max_dl_ues_in_tti; +} mac_3gpp_common_stats; class LteMacStatisticsDialog : public TapParameterDialog @@ -55,15 +55,15 @@ private: // Callbacks for register_tap_listener static void tapReset(void *ws_dlg_ptr); - static tap_packet_status tapPacket(void *ws_dlg_ptr, struct _packet_info *, struct epan_dissect *, const void *mac_lte_tap_info_ptr, tap_flags_t flags); + static tap_packet_status tapPacket(void *ws_dlg_ptr, struct _packet_info *, struct epan_dissect *, const void *mac_3gpp_tap_info_ptr, tap_flags_t flags); static void tapDraw(void *ws_dlg_ptr); virtual const QString filterExpression(); // Common stats. - mac_lte_common_stats commonStats_; + mac_3gpp_common_stats commonStats_; bool commonStatsCurrent_; // Set when changes have not yet been drawn - void updateCommonStats(const struct mac_lte_tap_info *mlt_info); + void updateCommonStats(const struct mac_3gpp_tap_info *mlt_info); void drawCommonStats(); void clearCommonStats(); diff --git a/ui/qt/lte_rlc_graph_dialog.cpp b/ui/qt/lte_rlc_graph_dialog.cpp index f1ac2b46..6158c21b 100644 --- a/ui/qt/lte_rlc_graph_dialog.cpp +++ b/ui/qt/lte_rlc_graph_dialog.cpp @@ -31,6 +31,8 @@ #include "ui/qt/widgets/wireshark_file_dialog.h" #include +#include + #include @@ -62,7 +64,7 @@ LteRlcGraphDialog::LteRlcGraphDialog(QWidget &parent, CaptureFile &cf, bool chan rp->xAxis->setLabel(tr("Time")); rp->yAxis->setLabel(tr("Sequence Number")); - // TODO: couldn't work out how to tell rp->xAxis not to label fractions of a SN... + // TODO: couldn't work out how to tell rp->yAxis not to label fractions of a SN... ui->dragRadioButton->setChecked(mouse_drags_); @@ -95,6 +97,9 @@ LteRlcGraphDialog::LteRlcGraphDialog(QWidget &parent, CaptureFile &cf, bool chan ctx_menu_->addAction(ui->actionSwitchDirection); set_action_shortcuts_visible_in_context_menu(ctx_menu_->actions()); + rp->setContextMenuPolicy(Qt::CustomContextMenu); + connect(rp, &QCustomPlot::customContextMenuRequested, this, &LteRlcGraphDialog::showContextMenu); + // Zero out this struct. memset(&graph_, 0, sizeof(graph_)); @@ -111,15 +116,16 @@ LteRlcGraphDialog::~LteRlcGraphDialog() } // Set the channel information that this graph should show. -void LteRlcGraphDialog::setChannelInfo(guint16 ueid, guint8 rlcMode, - guint16 channelType, guint16 channelId, guint8 direction, +void LteRlcGraphDialog::setChannelInfo(uint8_t rat, uint16_t ueid, uint8_t rlcMode, + uint16_t channelType, uint16_t channelId, uint8_t direction, bool maybe_empty) { + graph_.rat = rat; graph_.ueid = ueid; graph_.rlcMode = rlcMode; graph_.channelType = channelType; graph_.channelId = channelId; - graph_.channelSet = TRUE; + graph_.channelSet = true; graph_.direction = direction; completeGraph(maybe_empty); @@ -135,7 +141,8 @@ void LteRlcGraphDialog::completeGraph(bool may_be_empty) // Set window title here. if (graph_.channelSet) { - QString dlg_title = tr("LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5)") + QString dlg_title = tr("%1 RLC Graph (UE=%2 chan=%3%4 %5 - %6)") + .arg((graph_.rat == RLC_RAT_LTE) ? "LTE" : "NR") .arg(graph_.ueid) .arg((graph_.channelType == CHANNEL_TYPE_SRB) ? "SRB" : "DRB") .arg(graph_.channelId) @@ -144,7 +151,7 @@ void LteRlcGraphDialog::completeGraph(bool may_be_empty) setWindowTitle(dlg_title); } else { - setWindowTitle(tr("LTE RLC Graph - no channel selected")); + setWindowTitle(tr("3GPP RLC Graph - no channel selected")); } // Set colours/styles for each of the traces on the graph. @@ -186,7 +193,8 @@ void LteRlcGraphDialog::completeGraph(bool may_be_empty) // See if the given segment matches the channel this graph is plotting. bool LteRlcGraphDialog::compareHeaders(rlc_segment *seg) { - return compare_rlc_headers(graph_.ueid, graph_.channelType, + return compare_rlc_headers(graph_.rat, seg->rat, + graph_.ueid, graph_.channelType, graph_.channelId, graph_.rlcMode, graph_.direction, seg->ueid, seg->channelType, seg->channelId, seg->rlcMode, seg->direction, @@ -230,13 +238,13 @@ void LteRlcGraphDialog::fillGraph() return; } - tracer_->setGraph(NULL); - base_graph_->setLineStyle(QCPGraph::lsNone); // dot reseg_graph_->setLineStyle(QCPGraph::lsNone); // dot acks_graph_->setLineStyle(QCPGraph::lsStepLeft); // to get step effect... nacks_graph_->setLineStyle(QCPGraph::lsNone); // dot, but bigger. + tracer_->setGraph(NULL); + // Will show all graphs with data we find. for (int i = 0; i < sp->graphCount(); i++) { sp->graph(i)->data()->clear(); @@ -252,14 +260,13 @@ void LteRlcGraphDialog::fillGraph() // NACKs are shown bigger than others. nacks_graph_->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, pkt_point_size_*2)); - // Map timestamps -> segments in first pass. + // Map timestamps -> segments (time_stamp_map_) in first pass. time_stamp_map_.clear(); for (struct rlc_segment *seg = graph_.segments; seg != NULL; seg = seg->next) { if (!compareHeaders(seg)) { continue; } double ts = seg->rel_secs + seg->rel_usecs / 1000000.0; - time_stamp_map_.insert(ts, seg); } @@ -268,12 +275,23 @@ void LteRlcGraphDialog::fillGraph() reseg_seq_time, reseg_seq, acks_time, acks, nacks_time, nacks; + + uint32_t last_ackSN = uint32_t(-1); // start with invalid value + uint32_t maxSN = 0; + + // Note the max possible SN + if (graph_.segments) { + maxSN = (1 << graph_.segments->sequenceNumberLength); + } + + // Run through the segments to get data for (struct rlc_segment *seg = graph_.segments; seg != NULL; seg = seg->next) { double ts = seg->rel_secs + (seg->rel_usecs / 1000000.0); if (compareHeaders(seg)) { if (!seg->isControlPDU) { - // Data + // Data PDUs if (seg->isResegmented) { + // LTE only reseg_seq_time.append(ts); reseg_seq.append(seg->SN); } @@ -283,22 +301,31 @@ void LteRlcGraphDialog::fillGraph() } } else { - // Status (ACKs/NACKs) - acks_time.append(ts); - acks.append(seg->ACKNo-1); - for (int n=0; n < seg->noOfNACKs; n++) { - nacks_time.append(ts); - nacks.append(seg->NACKs[n]); + // Status PDUs + + // Filter out ACKS that are likely caused by MAC retx, so track last ACK + if (seg->ACKNo != last_ackSN) { + // Status (ACKs/NACKs) + acks_time.append(ts); + acks.append((seg->ACKNo-1) % maxSN); + last_ackSN = seg->ACKNo; + + // Any NACKs + for (int n=0; n < seg->noOfNACKs; n++) { + nacks_time.append(ts); + nacks.append(seg->NACKs[n]); + } } } } } // Add the data from the graphs. - base_graph_->setData(seq_time, seq); - reseg_graph_->setData(reseg_seq_time, reseg_seq); - acks_graph_->setData(acks_time, acks); - nacks_graph_->setData(nacks_time, nacks); + // N.B. passing true to assume the timestamps are already sorted.. + base_graph_->setData(seq_time, seq, true); + reseg_graph_->setData(reseg_seq_time, reseg_seq, true); + acks_graph_->setData(acks_time, acks, true); + nacks_graph_->setData(nacks_time, nacks, true); sp->setEnabled(true); @@ -533,19 +560,16 @@ QRectF LteRlcGraphDialog::getZoomRanges(QRect zoom_rect) return zoom_ranges; } +void LteRlcGraphDialog::showContextMenu(const QPoint &pos) +{ + ctx_menu_->popup(ui->rlcPlot->mapToGlobal(pos)); +} + void LteRlcGraphDialog::graphClicked(QMouseEvent *event) { QCustomPlot *rp = ui->rlcPlot; - if (event->button() == Qt::RightButton) { - // XXX We should find some way to get rlcPlot to handle a - // contextMenuEvent instead. -#if QT_VERSION >= QT_VERSION_CHECK(6, 0 ,0) - ctx_menu_->popup(event->globalPosition().toPoint()); -#else - ctx_menu_->popup(event->globalPos()); -#endif - } else if (mouse_drags_) { + if (mouse_drags_) { if (rp->axisRect()->rect().contains(event->pos())) { rp->setCursor(QCursor(Qt::ClosedHandCursor)); } @@ -675,21 +699,21 @@ void LteRlcGraphDialog::resetAxes() { QCustomPlot *rp = ui->rlcPlot; - QCPRange x_range = rp->xAxis->scaleType() == QCPAxis::stLogarithmic ? - rp->xAxis->range().sanitizedForLogScale() : rp->xAxis->range(); - double pixel_pad = 10.0; // per side rp->rescaleAxes(true); - base_graph_->rescaleValueAxis(false, true); + + QCPRange x_range = rp->xAxis->range(); double axis_pixels = rp->xAxis->axisRect()->width(); rp->xAxis->scaleRange((axis_pixels + (pixel_pad * 2)) / axis_pixels, x_range.center()); axis_pixels = rp->yAxis->axisRect()->height(); - rp->yAxis->scaleRange((axis_pixels + (pixel_pad * 2)) / axis_pixels, rp->yAxis->range().center()); + rp->yAxis->scaleRange((axis_pixels + (pixel_pad * 2)) / axis_pixels, + rp->yAxis->range().center()); - rp->replot(QCustomPlot::rpQueuedReplot); + // N.B. TCP Stream Dialog uses default (rpRefreshHint) - was using QCustomPlot::rpQueuedReplot + rp->replot(); } void LteRlcGraphDialog::on_actionGoToPacket_triggered() @@ -800,7 +824,8 @@ void LteRlcGraphDialog::on_actionSwitchDirection_triggered() { // Channel settings exactly the same, except change direction. // N.B. do not fail and close if there are no packets in opposite direction. - setChannelInfo(graph_.ueid, + setChannelInfo(graph_.rat, + graph_.ueid, graph_.rlcMode, graph_.channelType, graph_.channelId, diff --git a/ui/qt/lte_rlc_graph_dialog.h b/ui/qt/lte_rlc_graph_dialog.h index 07661ab2..2b83f0ff 100644 --- a/ui/qt/lte_rlc_graph_dialog.h +++ b/ui/qt/lte_rlc_graph_dialog.h @@ -33,8 +33,8 @@ public: explicit LteRlcGraphDialog(QWidget &parent, CaptureFile &cf, bool channelKnown); ~LteRlcGraphDialog(); - void setChannelInfo(guint16 ueid, guint8 rlcMode, - guint16 channelType, guint16 channelId, guint8 direction, + void setChannelInfo(uint8_t rat, uint16_t ueid, uint8_t rlcMode, + uint16_t channelType, uint16_t channelId, uint8_t direction, bool maybe_empty=false); signals: @@ -51,19 +51,19 @@ private: QPoint rb_origin_; QMenu *ctx_menu_; - // Data gleaned directly from tapping packets (shared with gtk impl) + // Data gleaned directly from tapping packets struct rlc_graph graph_; // Data - QMultiMap time_stamp_map_; + QMultiMap time_stamp_map_; // used for mapping clicks back to segment/frame QMap sequence_num_map_; - QCPGraph *base_graph_; // Clickable packets + QCPGraph *base_graph_; // Data SNs - clickable packets QCPGraph *reseg_graph_; QCPGraph *acks_graph_; QCPGraph *nacks_graph_; QCPItemTracer *tracer_; - guint32 packet_num_; + uint32_t packet_num_; void completeGraph(bool may_be_empty=false); @@ -82,6 +82,7 @@ private: void toggleTracerStyle(bool force_default); private slots: + void showContextMenu(const QPoint &pos); void graphClicked(QMouseEvent *event); void mouseMoved(QMouseEvent *event); void mouseReleased(QMouseEvent *event); diff --git a/ui/qt/lte_rlc_statistics_dialog.cpp b/ui/qt/lte_rlc_statistics_dialog.cpp index 43b5c81b..77553c96 100644 --- a/ui/qt/lte_rlc_statistics_dialog.cpp +++ b/ui/qt/lte_rlc_statistics_dialog.cpp @@ -13,8 +13,6 @@ #include #include -#include - #include #include #include @@ -26,6 +24,7 @@ // TODO: have never tested in a live capture. enum { + col_rat_, col_ueid_, col_mode_, // channel only col_priority_, // channel only @@ -49,7 +48,7 @@ enum { }; /* Calculate and return a bandwidth figure, in Mbs */ -static double calculate_bw(const nstime_t *start_time, const nstime_t *stop_time, guint32 bytes) +static double calculate_bw(const nstime_t *start_time, const nstime_t *stop_time, uint32_t bytes) { /* Can only calculate bandwidth if have time delta */ if (memcmp(start_time, stop_time, sizeof(nstime_t)) != 0) { @@ -74,31 +73,31 @@ static double calculate_bw(const nstime_t *start_time, const nstime_t *stop_time // Stats kept for one channel. typedef struct rlc_channel_stats { - guint8 rlcMode; - guint8 priority; - guint16 channelType; - guint16 channelId; + uint8_t rlcMode; + uint8_t priority; + uint16_t channelType; + uint16_t channelId; - guint32 UL_frames; - guint32 UL_bytes; + uint32_t UL_frames; + uint32_t UL_bytes; nstime_t UL_time_start; nstime_t UL_time_stop; - gboolean UL_has_data; // i.e. not just ACKs for DL. + bool UL_has_data; // i.e. not just ACKs for DL. - guint32 DL_frames; - guint32 DL_bytes; + uint32_t DL_frames; + uint32_t DL_bytes; nstime_t DL_time_start; nstime_t DL_time_stop; - gboolean DL_has_data; // i.e. not just ACKs for UL. + bool DL_has_data; // i.e. not just ACKs for UL. - guint32 UL_acks; - guint32 UL_nacks; + uint32_t UL_acks; + uint32_t UL_nacks; - guint32 DL_acks; - guint32 DL_nacks; + uint32_t DL_acks; + uint32_t DL_nacks; - guint32 UL_missing; - guint32 DL_missing; + uint32_t UL_missing; + uint32_t DL_missing; } rlc_channel_stats; //------------------------------------------------------------------- @@ -108,10 +107,12 @@ class RlcChannelTreeWidgetItem : public QTreeWidgetItem { public: RlcChannelTreeWidgetItem(QTreeWidgetItem *parent, + uint8_t rat, unsigned ueid, unsigned mode, unsigned channelType, unsigned channelId) : QTreeWidgetItem(parent, rlc_channel_row_type_), + rat_(rat), ueid_(ueid), channelType_(channelType), channelId_(channelId), @@ -163,7 +164,7 @@ public: } // Update UE/channels from tap info. - void update(const rlc_lte_tap_info *tap_info) { + void update(const rlc_3gpp_tap_info *tap_info) { // Copy these fields into UE stats. if (tap_info->rlcMode != stats_.rlcMode) { @@ -183,9 +184,9 @@ public: if (tap_info->direction == DIRECTION_UPLINK) { // Update time range. if (stats_.UL_frames == 0) { - stats_.UL_time_start = tap_info->rlc_lte_time; + stats_.UL_time_start = tap_info->rlc_time; } - stats_.UL_time_stop = tap_info->rlc_lte_time; + stats_.UL_time_stop = tap_info->rlc_time; stats_.UL_frames++; stats_.UL_bytes += tap_info->pduLength; @@ -195,15 +196,15 @@ public: stats_.UL_acks++; } else { - stats_.UL_has_data = TRUE; + stats_.UL_has_data = true; } } else { // Update time range. if (stats_.DL_frames == 0) { - stats_.DL_time_start = tap_info->rlc_lte_time; + stats_.DL_time_start = tap_info->rlc_time; } - stats_.DL_time_stop = tap_info->rlc_lte_time; + stats_.DL_time_stop = tap_info->rlc_time; stats_.DL_frames++; stats_.DL_bytes += tap_info->pduLength; @@ -213,7 +214,7 @@ public: stats_.DL_acks++; } else { - stats_.DL_has_data = TRUE; + stats_.DL_has_data = true; } } } @@ -269,47 +270,81 @@ public: return QTreeWidgetItem::operator< (other); } - // Filter expression for channel. + // Filter expression for this bearer. const QString filterExpression(bool showSR, bool showRACH) { // Create an expression to match with all traffic for this UE. QString filter_expr; // Are we taking RLC PDUs from MAC, or not? if (!recent.gui_rlc_use_pdus_from_mac) { - filter_expr += QString("not mac-lte and "); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString("not mac-lte and "); + } + else { + filter_expr += QString("not mac-nr and "); + } } else { - filter_expr += QString("mac-lte and "); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString("mac-lte and "); + } + else { + filter_expr += QString("mac-nr and "); + } } if (showSR) { - filter_expr += QString("(mac-lte.sr-req and mac-lte.ueid == %1) or (").arg(ueid_); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString("(mac-lte.sr-req and mac-lte.ueid == %1) or (").arg(ueid_); + } } if (showRACH) { - filter_expr += QString("(mac-lte.rar or (mac-lte.preamble-sent and mac-lte.ueid == %1)) or (").arg(ueid_); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString("(mac-lte.rar or (mac-lte.preamble-sent and mac-lte.ueid == %1)) or (").arg(ueid_); + } + else { + filter_expr += QString("(mac-nr.rar or "); + } } // Main part of expression. - filter_expr += QString("rlc-lte.ueid==%1 and rlc-lte.channel-type == %2"). - arg(ueid_).arg(channelType_); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString("rlc-lte.ueid==%1 and rlc-lte.channel-type == %2"). + arg(ueid_).arg(channelType_); + } + else { + filter_expr += QString("rlc-nr.ueid==%1 and rlc-nr.bearer-type == %2"). + arg(ueid_).arg(channelType_); + } + // Channel/bearer Id if ((channelType_ == CHANNEL_TYPE_SRB) || (channelType_ == CHANNEL_TYPE_DRB)) { - filter_expr += QString(" and rlc-lte.channel-id == %1").arg(channelId_); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString(" and rlc-lte.channel-id == %1").arg(channelId_); + } + else { + filter_expr += QString(" and rlc-nr.bearer-id == %1").arg(channelId_); + } } // Close () if open because of SR if (showSR) { - filter_expr += QString(")"); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString(")"); + } } // Close () if open because of RACH if (showRACH) { - filter_expr += QString(")"); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString(")"); + } } return filter_expr; } // Accessors (queried for launching graph) + uint8_t get_rat() const { return rat_; } unsigned get_ueid() const { return ueid_; } unsigned get_channelType() const { return channelType_; } unsigned get_channelId() const { return channelId_; } @@ -325,10 +360,11 @@ public: } private: + uint8_t rat_; unsigned ueid_; unsigned channelType_; unsigned channelId_; - unsigned mode_; + unsigned mode_; // RLC mode for this bearer unsigned priority_; unsigned channelRank() const @@ -353,21 +389,21 @@ private: // Stats for one UE. TODO: private to class? typedef struct rlc_ue_stats { - guint32 UL_frames; - guint32 UL_total_bytes; + uint32_t UL_frames; + uint32_t UL_total_bytes; nstime_t UL_time_start; nstime_t UL_time_stop; - guint32 UL_total_acks; - guint32 UL_total_nacks; - guint32 UL_total_missing; + uint32_t UL_total_acks; + uint32_t UL_total_nacks; + uint32_t UL_total_missing; - guint32 DL_frames; - guint32 DL_total_bytes; + uint32_t DL_frames; + uint32_t DL_total_bytes; nstime_t DL_time_start; nstime_t DL_time_stop; - guint32 DL_total_acks; - guint32 DL_total_nacks; - guint32 DL_total_missing; + uint32_t DL_total_acks; + uint32_t DL_total_nacks; + uint32_t DL_total_missing; } rlc_ue_stats; @@ -377,11 +413,17 @@ typedef struct rlc_ue_stats { class RlcUeTreeWidgetItem : public QTreeWidgetItem { public: - RlcUeTreeWidgetItem(QTreeWidget *parent, const rlc_lte_tap_info *rlt_info) : + RlcUeTreeWidgetItem(QTreeWidget *parent, const rlc_3gpp_tap_info *rlt_info) : QTreeWidgetItem (parent, rlc_ue_row_type_), ueid_(0) { ueid_ = rlt_info->ueid; + rat_ = rlt_info->rat; + + // Version matches UE number + setText(col_rat_, (rat_ == RLC_RAT_LTE) ? + QObject::tr("LTE") : + QObject::tr("NR")); setText(col_ueid_, QString::number(ueid_)); // We create RlcChannelTreeWidgetItems when first data on new channel is seen. @@ -398,20 +440,14 @@ public: } // Does UE match? - bool isMatch(const rlc_lte_tap_info *rlt_info) { - return ueid_ == rlt_info->ueid; + bool isMatch(const rlc_3gpp_tap_info *rlt_info) + { + return (rat_ == rlt_info->rat) && (ueid_ == rlt_info->ueid); } // Update UE/channels from tap info. - void update(const rlc_lte_tap_info *tap_info) { - - // Are we ignoring RLC frames that were found in MAC frames, or only those - // that were logged separately? - if ((!recent.gui_rlc_use_pdus_from_mac && tap_info->loggedInMACFrame) || - (recent.gui_rlc_use_pdus_from_mac && !tap_info->loggedInMACFrame)) { - return; - } - + void update(const rlc_3gpp_tap_info *tap_info) + { // TODO: update title with number of UEs and frames like MAC does? // N.B. not really expecting to see common stats - ignoring them. @@ -430,9 +466,9 @@ public: if (tap_info->direction == DIRECTION_UPLINK) { // Update time range. if (stats_.UL_frames == 0) { - stats_.UL_time_start = tap_info->rlc_lte_time; + stats_.UL_time_start = tap_info->rlc_time; } - stats_.UL_time_stop = tap_info->rlc_lte_time; + stats_.UL_time_stop = tap_info->rlc_time; stats_.UL_frames++; stats_.UL_total_bytes += tap_info->pduLength; @@ -448,9 +484,9 @@ public: else { // Update time range. if (stats_.DL_frames == 0) { - stats_.DL_time_start = tap_info->rlc_lte_time; + stats_.DL_time_start = tap_info->rlc_time; } - stats_.DL_time_stop = tap_info->rlc_lte_time; + stats_.DL_time_stop = tap_info->rlc_time; stats_.DL_frames++; stats_.DL_total_bytes += tap_info->pduLength; @@ -472,7 +508,7 @@ public: channel_item = CCCH_stats_; if (channel_item == NULL) { channel_item = CCCH_stats_ = - new RlcChannelTreeWidgetItem(this, tap_info->ueid, RLC_TM_MODE, + new RlcChannelTreeWidgetItem(this, tap_info->rat, tap_info->ueid, RLC_TM_MODE, tap_info->channelType, tap_info->channelId); } break; @@ -481,7 +517,7 @@ public: channel_item = srb_stats_[tap_info->channelId-1]; if (channel_item == NULL) { channel_item = srb_stats_[tap_info->channelId-1] = - new RlcChannelTreeWidgetItem(this, tap_info->ueid, RLC_AM_MODE, + new RlcChannelTreeWidgetItem(this, tap_info->rat, tap_info->ueid, RLC_AM_MODE, tap_info->channelType, tap_info->channelId); } break; @@ -490,7 +526,7 @@ public: channel_item = drb_stats_[tap_info->channelId-1]; if (channel_item == NULL) { channel_item = drb_stats_[tap_info->channelId-1] = - new RlcChannelTreeWidgetItem(this, tap_info->ueid, tap_info->rlcMode, + new RlcChannelTreeWidgetItem(this, tap_info->rat, tap_info->ueid, tap_info->rlcMode, tap_info->channelType, tap_info->channelId); } break; @@ -505,7 +541,8 @@ public: } // Draw UE entry - void draw() { + void draw() + { // Fixed fields only drawn once from constructor so don't redraw here. /* Calculate bandwidths. */ @@ -516,6 +553,8 @@ public: &stats_.DL_time_stop, stats_.DL_total_bytes); + setText(col_rat_, (rat_ == RLC_RAT_LTE) ? QString("LTE") : QString("NR")); + // Uplink. setText(col_ul_frames_, QString::number(stats_.UL_frames)); setText(col_ul_bytes_, QString::number(stats_.UL_total_bytes)); @@ -564,35 +603,63 @@ public: } // Filter expression for UE. - const QString filterExpression(bool showSR, bool showRACH) { + const QString filterExpression(bool showSR, bool showRACH) + { // Create an expression to match with all traffic for this UE. QString filter_expr; // Are we taking RLC PDUs from MAC, or not? if (!recent.gui_rlc_use_pdus_from_mac) { - filter_expr += QString("not mac-lte and "); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString("not mac-lte and "); + } + else { + filter_expr += QString("not mac-nr and "); + } } else { - filter_expr += QString("mac-lte and "); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString("mac-lte and "); + } + else { + filter_expr += QString("mac-nr and "); + } } if (showSR) { - filter_expr += QString("(mac-lte.sr-req and mac-lte.ueid == %1) or (").arg(ueid_); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString("(mac-lte.sr-req and mac-lte.ueid == %1) or (").arg(ueid_); + } } if (showRACH) { - filter_expr += QString("(mac-lte.rar or (mac-lte.preamble-sent and mac-lte.ueid == %1)) or (").arg(ueid_); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString("(mac-lte.rar or (mac-lte.preamble-sent and mac-lte.ueid == %1)) or (").arg(ueid_); + } + else { + filter_expr += QString("mac-nr.rar or "); + } } - filter_expr += QString("rlc-lte.ueid==%1").arg(ueid_); + // Must match UE + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString("rlc-lte.ueid==%1").arg(ueid_); + } + else { + filter_expr += QString("rlc-nr.ueid==%1").arg(ueid_); + } // Close () if open because of SR if (showSR) { - filter_expr += QString(")"); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString(")"); + } } // Close () if open because of RACH if (showRACH) { - filter_expr += QString(")"); + if (rat_ == RLC_RAT_LTE) { + filter_expr += QString(")"); + } } return filter_expr; @@ -623,6 +690,7 @@ public: } private: + uint8_t rat_; unsigned ueid_; rlc_ue_stats stats_; @@ -633,15 +701,16 @@ private: }; -// Only the first 3 columns headings differ between UE and channel rows. - -static const QString ue_col_0_title_ = QObject::tr("UE Id"); -static const QString ue_col_1_title_ = QObject::tr(""); +// Only the first 4 columns headings differ between UE and channel rows. +static const QString ue_col_0_title_ = QObject::tr("RAT"); +static const QString ue_col_1_title_ = QObject::tr("UE Id"); static const QString ue_col_2_title_ = QObject::tr(""); +static const QString ue_col_3_title_ = QObject::tr(""); -static const QString channel_col_0_title_ = QObject::tr("Name"); -static const QString channel_col_1_title_ = QObject::tr("Mode"); -static const QString channel_col_2_title_ = QObject::tr("Priority"); +static const QString channel_col_0_title_ = QObject::tr(""); +static const QString channel_col_1_title_ = QObject::tr("Name"); +static const QString channel_col_2_title_ = QObject::tr("Mode"); +static const QString channel_col_3_title_ = QObject::tr("Priority"); @@ -650,11 +719,11 @@ static const QString channel_col_2_title_ = QObject::tr("Priority"); // Constructor. LteRlcStatisticsDialog::LteRlcStatisticsDialog(QWidget &parent, CaptureFile &cf, const char *filter) : - TapParameterDialog(parent, cf, HELP_STATS_LTE_MAC_TRAFFIC_DIALOG), + TapParameterDialog(parent, cf, HELP_STATS_LTE_RLC_TRAFFIC_DIALOG), cf_(cf), packet_count_(0) { - setWindowSubtitle(tr("LTE RLC Statistics")); + setWindowSubtitle(tr("3GPP RLC Statistics")); loadGeometry((parent.width() * 5) / 5, (parent.height() * 3) / 4, "LTERLCStatisticsDialog"); // Create a grid for filtering-related widgetsto also appear in layout. @@ -692,7 +761,7 @@ LteRlcStatisticsDialog::LteRlcStatisticsDialog(QWidget &parent, CaptureFile &cf, filter_controls_grid->addWidget(useRLCFramesFromMacCheckBox_); QStringList header_labels = QStringList() - << "" << "" << "" + << "" << "" << "" << "" << tr("UL Frames") << tr("UL Bytes") << tr("UL MB/s") << tr("UL ACKs") << tr("UL NACKs") << tr("UL Missing") << tr("DL Frames") << tr("DL Bytes") << tr("DL MB/s") @@ -705,6 +774,9 @@ LteRlcStatisticsDialog::LteRlcStatisticsDialog(QWidget &parent, CaptureFile &cf, // resizeColumnToContents doesn't work well here, so set sizes manually. for (int col = 0; col < statsTreeWidget()->columnCount() - 1; col++) { switch (col) { + case col_rat_: + statsTreeWidget()->setColumnWidth(col, one_em * 3); + break; case col_ueid_: statsTreeWidget()->setColumnWidth(col, one_em * 7); break; @@ -770,24 +842,33 @@ void LteRlcStatisticsDialog::tapReset(void *ws_dlg_ptr) // Process the tap info from a dissected RLC PDU. // Returns TAP_PACKET_REDRAW if a redraw is needed, TAP_PACKET_DONT_REDRAW otherwise. -tap_packet_status LteRlcStatisticsDialog::tapPacket(void *ws_dlg_ptr, struct _packet_info *, epan_dissect *, const void *rlc_lte_tap_info_ptr, tap_flags_t) +tap_packet_status LteRlcStatisticsDialog::tapPacket(void *ws_dlg_ptr, struct _packet_info *, epan_dissect *, const void *rlc_3gpp_tap_info_ptr, tap_flags_t) { // Look up dialog. LteRlcStatisticsDialog *ws_dlg = static_cast(ws_dlg_ptr); - const rlc_lte_tap_info *rlt_info = (const rlc_lte_tap_info *) rlc_lte_tap_info_ptr; + const rlc_3gpp_tap_info *rlt_info = (const rlc_3gpp_tap_info *) rlc_3gpp_tap_info_ptr; if (!ws_dlg || !rlt_info) { return TAP_PACKET_DONT_REDRAW; } + // Are we ignoring RLC frames that were found in MAC frames, or only those + // that were logged separately? + if ((!recent.gui_rlc_use_pdus_from_mac && rlt_info->loggedInMACFrame) || + (recent.gui_rlc_use_pdus_from_mac && !rlt_info->loggedInMACFrame)) { + return TAP_PACKET_DONT_REDRAW; + } + ws_dlg->incFrameCount(); - // Look for this UE (TODO: avoid linear search if have lots of UEs in capture...) + // Look for this UE (TODO: avoid linear search if have lots of UEs in capture?) RlcUeTreeWidgetItem *ue_ti = NULL; for (int i = 0; i < ws_dlg->statsTreeWidget()->topLevelItemCount(); i++) { QTreeWidgetItem *ti = ws_dlg->statsTreeWidget()->topLevelItem(i); if (ti->type() != rlc_ue_row_type_) continue; + // Get UE object for this entry RlcUeTreeWidgetItem *cur_ru_ti = static_cast(ti); + // Does it match this tap? if (cur_ru_ti->isMatch(rlt_info)) { ue_ti = cur_ru_ti; break; @@ -842,6 +923,7 @@ void LteRlcStatisticsDialog::useRLCFramesFromMacCheckBoxToggled(bool state) fillTree(); } +// Return a filter expression for currently selected UE or bearer row const QString LteRlcStatisticsDialog::filterExpression() { QString filter_expr; @@ -864,7 +946,7 @@ const QString LteRlcStatisticsDialog::filterExpression() void LteRlcStatisticsDialog::fillTree() { - if (!registerTapListener("rlc-lte", + if (!registerTapListener("rlc-3gpp", this, displayFilter_.toLatin1().data(), TL_REQUIRES_NOTHING, @@ -904,14 +986,16 @@ void LteRlcStatisticsDialog::updateHeaderLabels() statsTreeWidget()->selectedItems()[0]->type() == rlc_channel_row_type_) { // UE column headings. - statsTreeWidget()->headerItem()->setText(col_ueid_, channel_col_0_title_); - statsTreeWidget()->headerItem()->setText(col_mode_, channel_col_1_title_); - statsTreeWidget()->headerItem()->setText(col_priority_, channel_col_2_title_); + statsTreeWidget()->headerItem()->setText(col_rat_, channel_col_0_title_); + statsTreeWidget()->headerItem()->setText(col_ueid_, channel_col_1_title_); + statsTreeWidget()->headerItem()->setText(col_mode_, channel_col_2_title_); + statsTreeWidget()->headerItem()->setText(col_priority_, channel_col_3_title_); } else { // Channel column headings. - statsTreeWidget()->headerItem()->setText(col_ueid_, ue_col_0_title_); - statsTreeWidget()->headerItem()->setText(col_mode_, ue_col_1_title_); - statsTreeWidget()->headerItem()->setText(col_priority_, ue_col_2_title_); + statsTreeWidget()->headerItem()->setText(col_rat_, ue_col_0_title_); + statsTreeWidget()->headerItem()->setText(col_ueid_, ue_col_1_title_); + statsTreeWidget()->headerItem()->setText(col_mode_, ue_col_2_title_); + statsTreeWidget()->headerItem()->setText(col_priority_, ue_col_3_title_); } } @@ -925,11 +1009,15 @@ void LteRlcStatisticsDialog::captureFileClosing() // Launch a UL graph for the currently-selected channel. void LteRlcStatisticsDialog::launchULGraphButtonClicked() { - if (statsTreeWidget()->selectedItems().count() > 0 && statsTreeWidget()->selectedItems()[0]->type() == rlc_channel_row_type_) { + if (statsTreeWidget()->selectedItems().count() > 0 && + statsTreeWidget()->selectedItems()[0]->type() == rlc_channel_row_type_) { + // Get the channel item. QTreeWidgetItem *ti = statsTreeWidget()->selectedItems()[0]; RlcChannelTreeWidgetItem *rc_ti = static_cast(ti); + // Launch the graph. emit launchRLCGraph(true, + rc_ti->get_rat(), rc_ti->get_ueid(), rc_ti->get_mode(), rc_ti->get_channelType(), @@ -946,6 +1034,7 @@ void LteRlcStatisticsDialog::launchDLGraphButtonClicked() QTreeWidgetItem *ti = statsTreeWidget()->selectedItems()[0]; RlcChannelTreeWidgetItem *rc_ti = static_cast(ti); emit launchRLCGraph(true, + rc_ti->get_rat(), rc_ti->get_ueid(), rc_ti->get_mode(), rc_ti->get_channelType(), @@ -982,7 +1071,8 @@ QList LteRlcStatisticsDialog::treeItemData(QTreeWidgetItem *item) cons // Stat command + args static void -lte_rlc_statistics_init(const char *args, void*) { +lte_rlc_statistics_init(const char *args, void*) +{ QStringList args_l = QString(args).split(','); QByteArray filter; if (args_l.length() > 2) { @@ -992,12 +1082,12 @@ lte_rlc_statistics_init(const char *args, void*) { } static stat_tap_ui lte_rlc_statistics_ui = { - REGISTER_STAT_GROUP_TELEPHONY_LTE, + REGISTER_TELEPHONY_GROUP_3GPP_UU, QT_TRANSLATE_NOOP("LteRlcStatisticsDialog", "RLC Statistics"), - "rlc-lte,stat", + "rlc-3gpp,stat", // cli_string lte_rlc_statistics_init, - 0, - NULL + 0, // nparams + NULL // params }; extern "C" { diff --git a/ui/qt/lte_rlc_statistics_dialog.h b/ui/qt/lte_rlc_statistics_dialog.h index 50e1af92..fc97996e 100644 --- a/ui/qt/lte_rlc_statistics_dialog.h +++ b/ui/qt/lte_rlc_statistics_dialog.h @@ -12,6 +12,10 @@ #include "tap_parameter_dialog.h" +#include +#include + + #include class LteRlcStatisticsDialog : public TapParameterDialog @@ -30,9 +34,11 @@ protected: signals: void launchRLCGraph(bool channelKnown, - guint16 ueid, guint8 rlcMode, - guint16 channelType, guint16 channelId, - guint8 direction); + uint8_t version, + uint16_t ueid, + uint8_t rlcMode, + uint16_t channelType, uint16_t channelId, + uint8_t direction); private: // Extra controls needed for this dialog. diff --git a/ui/qt/main.cpp b/ui/qt/main.cpp index 582855f2..c7d459b1 100644 --- a/ui/qt/main.cpp +++ b/ui/qt/main.cpp @@ -10,8 +10,6 @@ #include #define WS_LOG_DOMAIN LOG_DOMAIN_MAIN -#include - #include #ifdef _WIN32 @@ -77,6 +75,7 @@ #include "ui/preference_utils.h" #include "ui/software_update.h" #include "ui/taps.h" +#include "ui/profile.h" #include "ui/qt/conversation_dialog.h" #include "ui/qt/utils/color_utils.h" @@ -209,11 +208,27 @@ gather_wireshark_qt_compiled_info(feature_list l) #endif gather_caplibs_compile_info(l); epan_gather_compile_info(l); +#ifdef HAVE_MINIZIPNG + with_feature(l, "Minizip-ng %s", MINIZIPNG_VERSION); +#else +#ifdef HAVE_MINIZIP + with_feature(l, "Minizip %s", MINIZIP_VERSION); +#else + without_feature(l, "Minizip"); +#endif +#endif /* HAVE_MINIZIPNG */ #ifdef QT_MULTIMEDIA_LIB with_feature(l, "QtMultimedia"); #else without_feature(l, "QtMultimedia"); #endif +#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) +#ifdef QT_DBUS_LIB + with_feature(l, "QtDBus"); +#else + without_feature(l, "QtDBus"); +#endif +#endif /* !Q_OS_WIN && !Q_OS_MAC */ const char *update_info = software_update_info(); if (update_info) { @@ -228,12 +243,6 @@ gather_wireshark_qt_compiled_info(feature_list l) without_feature(l, "AirPcap"); #endif #endif /* _WIN32 */ - -#ifdef HAVE_MINIZIP - with_feature(l, "Minizip"); -#else - without_feature(l, "Minizip"); -#endif } void @@ -339,7 +348,7 @@ qt_log_message_handler(QtMsgType type, const QMessageLogContext &context, const static void check_and_warn_user_startup() { - gchar *cur_user, *cur_group; + char *cur_user, *cur_group; /* Tell the user not to run as root. */ if (running_with_special_privs() && recent.privs_warn_if_elevated) { @@ -447,16 +456,15 @@ macos_enable_layer_backing(void) static GList * capture_opts_get_interface_list(int *err, char **err_str) { - /* - * XXX - should this pass an update callback? - * We already have a window up by the time we start parsing - * the majority of the command-line arguments, because - * we need to do a bunch of initialization work before - * parsing those arguments, and we want to let the user - * know that we're doing that initialization, given that - * it can take a while. - */ - return capture_interface_list(err, err_str, NULL); + if (mainApp) { + GList *if_list = mainApp->getInterfaceList(); + if (if_list == NULL) { + if_list = capture_interface_list(err, err_str, main_window_update); + mainApp->setInterfaceList(if_list); + } + return if_list; + } + return capture_interface_list(err, err_str, main_window_update); } #endif @@ -475,15 +483,15 @@ int main(int argc, char *qt_argv[]) char *rf_path; int rf_open_errno; #ifdef HAVE_LIBPCAP - gchar *err_str, *err_str_secondary;; + char *err_str, *err_str_secondary; #else #ifdef _WIN32 #ifdef HAVE_AIRPCAP - gchar *err_str; + char *err_str; #endif #endif #endif - gchar *err_msg = NULL; + char *err_msg = NULL; df_error_t *df_err = NULL; QString dfilter, read_filter; @@ -491,7 +499,7 @@ int main(int argc, char *qt_argv[]) int caps_queries = 0; #endif /* Start time in microseconds */ - guint64 start_time = g_get_monotonic_time(); + uint64_t start_time = g_get_monotonic_time(); static const struct report_message_routines wireshark_report_routines = { vfailure_alert_box, vwarning_alert_box, @@ -542,7 +550,7 @@ int main(int argc, char *qt_argv[]) /* Initialize log handler early so we can have proper logging during startup. */ ws_log_init("wireshark", vcmdarg_err); /* For backward compatibility with GLib logging and Wireshark 3.4. */ - ws_log_console_writer_set_use_stdout(TRUE); + ws_log_console_writer_set_use_stdout(true); qInstallMessageHandler(qt_log_message_handler); @@ -551,7 +559,7 @@ int main(int argc, char *qt_argv[]) #endif #ifdef DEBUG_STARTUP_TIME - prefs.gui_console_open = console_open_always; + ws_log_console_open = LOG_CONSOLE_OPEN_ALWAYS; #endif /* DEBUG_STARTUP_TIME */ #if defined(Q_OS_MAC) @@ -675,7 +683,7 @@ int main(int argc, char *qt_argv[]) g_free (rf_path); } - profile_store_persconffiles(TRUE); + profile_store_persconffiles(true); recent_init(); /* Read the profile independent recent file. We have to do this here so we can */ @@ -704,7 +712,7 @@ int main(int argc, char *qt_argv[]) // https://bugreports.qt.io/browse/QTBUG-53022 - The device pixel ratio is pretty much bogus on Windows. // https://bugreports.qt.io/browse/QTBUG-55510 - Windows have wrong size // - // Deprecated in Qt6. + // Deprecated in Qt6, which is Per-Monitor DPI Aware V2 by default. // warning: 'Qt::AA_EnableHighDpiScaling' is deprecated: High-DPI scaling is always enabled. // This attribute no longer has any effect. #if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -762,8 +770,10 @@ int main(int argc, char *qt_argv[]) GLibMainloopOnQEventLoop::setup(main_w); // We may not need a queued connection here but it would seem to make sense // to force the issue. - main_w->connect(&ws_app, SIGNAL(openCaptureFile(QString,QString,unsigned int)), - main_w, SLOT(openCaptureFile(QString,QString,unsigned int))); + main_w->connect(&ws_app, &WiresharkApplication::openCaptureFile, + main_w, [&](QString cf_path, QString display_filter, unsigned int type) { + main_w->openCaptureFile(cf_path, display_filter, type); + }); main_w->connect(&ws_app, &WiresharkApplication::openCaptureOptions, main_w, &WiresharkMainWindow::showCaptureOptionsDialog); @@ -793,7 +803,7 @@ int main(int argc, char *qt_argv[]) * dissection-time handlers for file-type-dependent blocks can * register using the file type/subtype value for the file type. */ - wtap_init(TRUE); + wtap_init(true); splash_update(RA_DISSECTORS, NULL, NULL); #ifdef DEBUG_STARTUP_TIME @@ -803,14 +813,14 @@ int main(int argc, char *qt_argv[]) "-G" flag, as the "-G" flag dumps information registered by the dissectors, and we must do it before we read the preferences, in case any dissectors register preferences. */ - if (!epan_init(splash_update, NULL, TRUE)) { + if (!epan_init(splash_update, NULL, true)) { SimpleDialog::displayQueuedMessages(main_w); ret_val = WS_EXIT_INIT_FAILED; goto clean_exit; } #ifdef DEBUG_STARTUP_TIME /* epan_init resets the preferences */ - prefs.gui_console_open = console_open_always; + ws_log_console_open = LOG_CONSOLE_OPEN_ALWAYS; ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "epan done, elapsed time %" PRIu64 " us \n", g_get_monotonic_time() - start_time); #endif @@ -847,11 +857,6 @@ int main(int argc, char *qt_argv[]) in_file_type = open_info_name_to_type(ex_opt_get_next("read_format")); } -#ifdef DEBUG_STARTUP_TIME - ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Calling extcap_register_preferences, elapsed time %" PRIu64 " us \n", g_get_monotonic_time() - start_time); -#endif - splash_update(RA_EXTCAP, NULL, NULL); - extcap_register_preferences(); splash_update(RA_PREFERENCES, NULL, NULL); #ifdef DEBUG_STARTUP_TIME ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Calling module preferences, elapsed time %" PRIu64 " us \n", g_get_monotonic_time() - start_time); @@ -864,7 +869,17 @@ int main(int argc, char *qt_argv[]) * line, and store them. We have to do this before applying the * preferences to the capture options. */ - commandline_override_prefs(argc, argv, TRUE); + commandline_override_prefs(argc, argv, true); + + /* Register the extcap preferences. We do this after seeing if the + * capture_no_extcap preference is set in the configuration file + * or command line. This will re-read the extcap specific preferences. + */ +#ifdef DEBUG_STARTUP_TIME + ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Calling extcap_register_preferences, elapsed time %" PRIu64 " us \n", g_get_monotonic_time() - start_time); +#endif + splash_update(RA_EXTCAP, NULL, NULL); + extcap_register_preferences(); /* Some of the preferences affect the capture options. Apply those * before getting the other command line arguments, which can also @@ -875,7 +890,21 @@ int main(int argc, char *qt_argv[]) prefs_to_capture_opts(); /* Now get our remaining args */ - commandline_other_options(argc, argv, TRUE); + + /* XXX: Processing interface options on the command line might retrieve + * interface list. We don't yet know if we will need to retrieve the + * interface capabilities as well (e.g. are we printing capabilities, + * or loading the interface list?) until we parse other options, like + * whether we have a capture file. + * + * We'd prefer to avoid firing up dumpcap twice (once for the list + * without the capabilities and once for capabilities), especially + * on Windows where that could mean two UAC prompts. However, getting + * the interface capabilities is a bit time-consuming so we don't want + * to do it if we don't need to. + */ + + commandline_other_options(argc, argv, true); /* Convert some command-line parameters to QStrings */ if (global_commandline_info.cf_name != NULL) @@ -890,17 +919,9 @@ int main(int argc, char *qt_argv[]) timestamp_set_seconds_type (recent.gui_seconds_format); #ifdef HAVE_LIBPCAP -#ifdef DEBUG_STARTUP_TIME - ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Calling fill_in_local_interfaces, elapsed time %" PRIu64 " us \n", g_get_monotonic_time() - start_time); -#endif - splash_update(RA_INTERFACES, NULL, NULL); - - if (!global_commandline_info.cf_name && !prefs.capture_no_interface_load) - fill_in_local_interfaces(main_window_update); - - if (global_commandline_info.list_link_layer_types) + if (global_commandline_info.list_link_layer_types) caps_queries |= CAPS_QUERY_LINK_TYPES; - if (global_commandline_info.list_timestamp_types) + if (global_commandline_info.list_timestamp_types) caps_queries |= CAPS_QUERY_TIMESTAMP_TYPES; if (global_commandline_info.start_capture || caps_queries) { @@ -919,27 +940,41 @@ int main(int argc, char *qt_argv[]) * and exit. */ if (caps_queries) { - guint i; + unsigned i; #ifdef _WIN32 create_console(); #endif /* _WIN32 */ /* Get the list of link-layer types for the capture devices. */ ret_val = EXIT_SUCCESS; + GList *if_cap_queries = NULL; + if_cap_query_t *if_cap_query; + GHashTable *capability_hash; for (i = 0; i < global_capture_opts.ifaces->len; i++) { interface_options *interface_opts; - if_capabilities_t *caps; - char *auth_str = NULL; interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i); + if_cap_query = g_new(if_cap_query_t, 1); + if_cap_query->name = interface_opts->name; + if_cap_query->monitor_mode = interface_opts->monitor_mode; + if_cap_query->auth_username = NULL; + if_cap_query->auth_password = NULL; #ifdef HAVE_PCAP_REMOTE if (interface_opts->auth_type == CAPTURE_AUTH_PWD) { - auth_str = ws_strdup_printf("%s:%s", interface_opts->auth_username, interface_opts->auth_password); + if_cap_query->auth_username = interface_opts->auth_username; + if_cap_query->auth_password = interface_opts->auth_password; } #endif - caps = capture_get_if_capabilities(interface_opts->name, interface_opts->monitor_mode, - auth_str, &err_str, &err_str_secondary, NULL); - g_free(auth_str); + if_cap_queries = g_list_prepend(if_cap_queries, if_cap_query); + } + if_cap_queries = g_list_reverse(if_cap_queries); + capability_hash = capture_get_if_list_capabilities(if_cap_queries, &err_str, &err_str_secondary, NULL); + g_list_free_full(if_cap_queries, g_free); + for (i = 0; i < global_capture_opts.ifaces->len; i++) { + interface_options *interface_opts; + if_capabilities_t *caps; + interface_opts = &g_array_index(global_capture_opts.ifaces, interface_options, i); + caps = static_cast(g_hash_table_lookup(capability_hash, interface_opts->name)); if (caps == NULL) { cmdarg_err("%s%s%s", err_str, err_str_secondary ? "\n" : "", err_str_secondary ? err_str_secondary : ""); g_free(err_str); @@ -949,7 +984,6 @@ int main(int argc, char *qt_argv[]) } ret_val = capture_opts_print_if_capabilities(caps, interface_opts, caps_queries); - free_if_capabilities(caps); if (ret_val != EXIT_SUCCESS) { break; } @@ -957,9 +991,19 @@ int main(int argc, char *qt_argv[]) #ifdef _WIN32 destroy_console(); #endif /* _WIN32 */ + g_hash_table_destroy(capability_hash); goto clean_exit; } +#ifdef DEBUG_STARTUP_TIME + ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Calling fill_in_local_interfaces, elapsed time %" PRIu64 " us \n", g_get_monotonic_time() - start_time); +#endif + splash_update(RA_INTERFACES, NULL, NULL); + + if (!global_commandline_info.cf_name && !prefs.capture_no_interface_load) { + wsApp->scanLocalInterfaces(nullptr); + } + capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE); capture_opts_trim_ring_num_files(&global_capture_opts); #endif /* HAVE_LIBPCAP */ @@ -972,17 +1016,18 @@ int main(int argc, char *qt_argv[]) #endif splash_update(RA_PREFERENCES_APPLY, NULL, NULL); prefs_apply_all(); + wsApp->emitAppSignal(WiresharkApplication::ColorsChanged); wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged); #ifdef HAVE_LIBPCAP if ((global_capture_opts.num_selected == 0) && (prefs.capture_device != NULL)) { - guint i; + unsigned i; interface_t *device; for (i = 0; i < global_capture_opts.all_ifaces->len; i++) { device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (!device->hidden && strcmp(device->display_name, prefs.capture_device) == 0) { - device->selected = TRUE; + device->selected = true; global_capture_opts.num_selected++; break; } @@ -999,7 +1044,7 @@ int main(int argc, char *qt_argv[]) goto clean_exit; } - build_column_format_array(&CaptureFile::globalCapFile()->cinfo, global_commandline_info.prefs_p->num_cols, TRUE); + build_column_format_array(&CaptureFile::globalCapFile()->cinfo, global_commandline_info.prefs_p->num_cols, true); wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged); // We read "recent" widths above. wsApp->emitAppSignal(WiresharkApplication::RecentPreferencesRead); // Must be emitted after PreferencesChanged. @@ -1022,7 +1067,7 @@ int main(int argc, char *qt_argv[]) * processEvents() here. */ wsApp->allSystemsGo(); - ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Wireshark is up and ready to go, elapsed time %.3fs", (float) (g_get_monotonic_time() - start_time) / 1000000); + ws_info("Wireshark is up and ready to go, elapsed time %.3fs", (float) (g_get_monotonic_time() - start_time) / 1000000); SimpleDialog::displayQueuedMessages(main_w); /* User could specify filename, or display filter, or both */ @@ -1043,7 +1088,7 @@ int main(int argc, char *qt_argv[]) if (global_commandline_info.go_to_packet != 0) { /* Jump to the specified frame number, kept for backward compatibility. */ - cf_goto_frame(CaptureFile::globalCapFile(), global_commandline_info.go_to_packet); + cf_goto_frame(CaptureFile::globalCapFile(), global_commandline_info.go_to_packet, false); } else if (global_commandline_info.jfilter != NULL) { dfilter_t *jump_to_filter = NULL; /* try to compile given filter */ @@ -1069,7 +1114,7 @@ int main(int argc, char *qt_argv[]) if (global_capture_opts.save_file != NULL) { /* Save the directory name for future file dialogs. */ /* (get_dirname overwrites filename) */ - gchar *s = g_strdup(global_capture_opts.save_file); + char *s = g_strdup(global_capture_opts.save_file); set_last_open_dir(get_dirname(s)); g_free(s); } @@ -1079,6 +1124,9 @@ int main(int argc, char *qt_argv[]) /* If no user interfaces were specified on the command line, copy the list of selected interfaces to the set of interfaces to use for this capture. */ + /* XXX: I don't think this can happen, because if start_capture is + * true then capture_opts_default_iface_if_necessary() was called + */ if (global_capture_opts.ifaces->len == 0) collect_ifaces(&global_capture_opts); CaptureFile::globalCapFile()->window = main_w; @@ -1106,8 +1154,10 @@ int main(int argc, char *qt_argv[]) // loaded when the dialog is shown. Register them here. profile_register_persconffile("io_graphs"); profile_register_persconffile("import_hexdump.json"); + profile_register_persconffile("remote_hosts.json"); - profile_store_persconffiles(FALSE); + profile_store_persconffiles(false); + init_profile_list(); // If the wsApp->exec() event loop exits cleanly, we call // WiresharkApplication::cleanup(). diff --git a/ui/qt/main_application.cpp b/ui/qt/main_application.cpp index da881127..00b65218 100644 --- a/ui/qt/main_application.cpp +++ b/ui/qt/main_application.cpp @@ -31,7 +31,9 @@ #include "epan/tap.h" #include "epan/timestamp.h" #include "epan/decode_as.h" +#include "epan/dfilter/dfilter-macro.h" +#include "ui/commandline.h" #include "ui/decode_as_utils.h" #include "ui/preference_utils.h" #include "ui/iface_lists.h" @@ -110,7 +112,7 @@ #pragma warning(pop) #endif -MainApplication *mainApp = NULL; +MainApplication *mainApp; // XXX - Copied from ui/gtk/file_dlg.c @@ -161,7 +163,7 @@ topic_action(topic_action_e action) * https://stackoverflow.com/questions/437212/how-do-you-register-a-most-recently-used-list-with-windows-in-preparation-for-win */ extern "C" void -add_menu_recent_capture_file(const gchar *cf_name) { +add_menu_recent_capture_file(const char *cf_name, bool force) { QString normalized_cf_name = QString::fromUtf8(cf_name); QDir cf_path; @@ -196,7 +198,7 @@ add_menu_recent_capture_file(const gchar *cf_name) { */ ri->filename.compare(normalized_cf_name) == 0 || #endif - cnt >= prefs.gui_recent_files_count_max) { + (!force && cnt >= prefs.gui_recent_files_count_max)) { rii.remove(); delete(ri); cnt--; @@ -212,12 +214,15 @@ extern "C" void menu_recent_file_write_all(FILE *rf) { /* we have to iterate backwards through the children's list, * so we get the latest item last in the file. */ - QListIterator rii(recent_captures_); - rii.toBack(); - while (rii.hasPrevious()) { - QString cf_name; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + int i = qMin(recent_captures_.size(), (int)(prefs.gui_recent_files_count_max)) - 1; +#else + qsizetype i = qMin(recent_captures_.size(), (qsizetype)prefs.gui_recent_files_count_max) - 1; +#endif + for (; i >= 0; i--) { + recent_item_status *ri = recent_captures_.at(i); /* get capture filename from the menu item label */ - cf_name = rii.previous()->filename; + QString cf_name = ri->filename; if (!cf_name.isNull()) { fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", qUtf8Printable(cf_name)); } @@ -279,7 +284,7 @@ void MainApplication::colorSchemeChanged() { void MainApplication::updateTaps() { - draw_tap_listeners(FALSE); + draw_tap_listeners(false); } QDir MainApplication::openDialogInitialDir() { @@ -299,7 +304,7 @@ void MainApplication::helpTopicAction(topic_action_e action) QString url = gchar_free_to_qstring(topic_action_url(action)); if (!url.isEmpty()) { - QDesktopServices::openUrl(QUrl(url)); + QDesktopServices::openUrl(QUrl(QDir::fromNativeSeparators(url))); } } @@ -397,25 +402,21 @@ void MainApplication::setMonospaceFont(const char *font_string) { int MainApplication::monospaceTextSize(const char *str) { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) return QFontMetrics(mono_font_).horizontalAdvance(str); -#else - return QFontMetrics(mono_font_).width(str); -#endif } -void MainApplication::setConfigurationProfile(const gchar *profile_name, bool write_recent_file) +void MainApplication::setConfigurationProfile(const char *profile_name, bool write_recent_file) { char *rf_path; int rf_open_errno; - gchar *err_msg = NULL; + char *err_msg = NULL; - gboolean prev_capture_no_interface_load; - gboolean prev_capture_no_extcap; + bool prev_capture_no_interface_load; + bool prev_capture_no_extcap; /* First check if profile exists */ - if (!profile_exists(profile_name, FALSE)) { - if (profile_exists(profile_name, TRUE)) { + if (!profile_exists(profile_name, false)) { + if (profile_exists(profile_name, true)) { char *pf_dir_path, *pf_dir_path2, *pf_filename; /* Copy from global profile */ if (create_persconffile_profile(profile_name, &pf_dir_path) == -1) { @@ -426,7 +427,7 @@ void MainApplication::setConfigurationProfile(const gchar *profile_name, bool wr g_free(pf_dir_path); } - if (copy_persconffile_profile(profile_name, profile_name, TRUE, &pf_filename, + if (copy_persconffile_profile(profile_name, profile_name, true, &pf_filename, &pf_dir_path, &pf_dir_path2) == -1) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.", @@ -453,7 +454,7 @@ void MainApplication::setConfigurationProfile(const gchar *profile_name, bool wr /* Get the current geometry, before writing it to disk */ emit profileChanging(); - if (write_recent_file && profile_exists(get_profile_name(), FALSE)) + if (write_recent_file && profile_exists(get_profile_name(), false)) { /* Write recent file for profile we are leaving, if it still exists */ write_profile_recent(); @@ -466,6 +467,13 @@ void MainApplication::setConfigurationProfile(const gchar *profile_name, bool wr /* Apply new preferences */ readConfigurationFiles(true); + /* Apply command-line preferences */ + commandline_options_reapply(); + extcap_register_preferences(); + + /* Switching profile requires reloading the macro list. */ + reloadDisplayFilterMacros(); + if (!recent_read_profile_static(&rf_path, &rf_open_errno)) { simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK, "Could not open common recent file\n\"%s\": %s.", @@ -494,6 +502,7 @@ void MainApplication::setConfigurationProfile(const gchar *profile_name, bool wr emit freezePacketList(true); emit columnsChanged(); + emit colorsChanged(); emit preferencesChanged(); emit recentPreferencesRead(); emit filterExpressionsChanged(); @@ -523,7 +532,7 @@ void MainApplication::setConfigurationProfile(const gchar *profile_name, bool wr void MainApplication::reloadLuaPluginsDelayed() { - QTimer::singleShot(0, this, SIGNAL(reloadLuaPlugins())); + QTimer::singleShot(0, this, &MainApplication::reloadLuaPlugins); } const QIcon &MainApplication::normalIcon() @@ -647,6 +656,9 @@ MainApplication::MainApplication(int &argc, char **argv) : is_reloading_lua_(false), if_notifier_(NULL), active_captures_(0) +#ifdef HAVE_LIBPCAP + , cached_if_list_(NULL) +#endif { mainApp = this; @@ -676,15 +688,13 @@ MainApplication::MainApplication(int &argc, char **argv) : setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); #endif -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) setAttribute(Qt::AA_DisableWindowContextHelpButton); #endif // Throw various settings at the wall with the hope that one of them will // enable context menu shortcuts QTBUG-69452, QTBUG-109590 -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) setAttribute(Qt::AA_DontShowShortcutsInContextMenus, false); -#endif #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) styleHints()->setShowShortcutsInContextMenus(true); #endif @@ -697,7 +707,7 @@ MainApplication::MainApplication(int &argc, char **argv) : // QFileSystemWatcher should allow us to watch for files being // removed or renamed. It uses kqueues and EVFILT_VNODE on FreeBSD, // NetBSD, FSEvents on macOS, inotify on Linux if available, and - // FindFirstChagneNotification() on Windows. On all other platforms, + // FindFirstChangeNotification() on Windows. On all other platforms, // it just periodically polls, as we're doing now. // // For unmounts: @@ -776,17 +786,17 @@ MainApplication::MainApplication(int &argc, char **argv) : // I'm not sure what can be done on Linux. // recent_timer_.setParent(this); - connect(&recent_timer_, SIGNAL(timeout()), this, SLOT(refreshRecentCaptures())); + connect(&recent_timer_, &QTimer::timeout, this, &MainApplication::refreshRecentCaptures); recent_timer_.start(2000); packet_data_timer_.setParent(this); - connect(&packet_data_timer_, SIGNAL(timeout()), this, SLOT(refreshPacketData())); + connect(&packet_data_timer_, &QTimer::timeout, this, &MainApplication::refreshPacketData); packet_data_timer_.start(1000); tap_update_timer_.setParent(this); tap_update_timer_.setInterval(TAP_UPDATE_DEFAULT_INTERVAL); - connect(this, SIGNAL(appInitialized()), &tap_update_timer_, SLOT(start())); - connect(&tap_update_timer_, SIGNAL(timeout()), this, SLOT(updateTaps())); + connect(this, &MainApplication::appInitialized, &tap_update_timer_, [&]() { tap_update_timer_.start(); }); + connect(&tap_update_timer_, &QTimer::timeout, this, &MainApplication::updateTaps); // Application-wide style sheet QString app_style_sheet = qApp->styleSheet(); @@ -796,7 +806,7 @@ MainApplication::MainApplication(int &argc, char **argv) : prefs_set_gui_theme_is_dark(ColorUtils::themeIsDark()); #if defined(HAVE_SOFTWARE_UPDATE) && defined(Q_OS_WIN) - connect(this, SIGNAL(softwareUpdateQuit()), this, SLOT(quit()), Qt::QueuedConnection); + connect(this, &MainApplication::softwareUpdateQuit, this, &MainApplication::quit, Qt::QueuedConnection); #endif #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) && defined(Q_OS_WIN) @@ -804,14 +814,16 @@ MainApplication::MainApplication(int &argc, char **argv) : connect(styleHints(), &QStyleHints::colorSchemeChanged, this, &MainApplication::colorSchemeChanged); #endif - connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(cleanup())); + connect(qApp, &QApplication::aboutToQuit, this, &MainApplication::cleanup); } MainApplication::~MainApplication() { mainApp = NULL; +#ifdef HAVE_LIBPCAP + free_interface_list(cached_if_list_); +#endif clearDynamicMenuGroupItems(); - free_filter_lists(); } void MainApplication::registerUpdate(register_action_e action, const char *message) @@ -858,6 +870,9 @@ void MainApplication::emitAppSignal(AppSignal signal) case FieldsChanged: emit fieldsChanged(); break; + case ColorsChanged: + emit colorsChanged(); + break; case FreezePacketList: emit freezePacketList(false); break; @@ -986,7 +1001,7 @@ static void iface_mon_event_cb(const char *iface, int added, int up) { int present = 0; - guint ifs, j; + unsigned ifs, j; interface_t *device; interface_options *interface_opts; @@ -1015,6 +1030,27 @@ iface_mon_event_cb(const char *iface, int added, int up) /* * We've been told that there's a new interface or that an old * interface is gone; reload the local interface list. + * + * XXX: We also want to reload the local interface list if [what + * we can retrieve about] the capabilities of the device have changed. + * Ideally we'd update the capabilities of just the one device in + * the cache and signal that the list has been updated, instead of + * freeing the entire cache and scanning again - but some extcaps + * depend on other interfaces being up; e.g. by default androiddump + * tries to connect to the loopback interface to look for adb running, + * so if the loopback interface changes so does the status of + * androiddump. + * + * On Linux, at least, you can't get the capabilities from a down + * interface, but it's still present in all_ifaces - dumpcap returns + * it in the list, and we show it so the user can get a status / error + * message when trying to capture on it instead of it vanishing. + * So if both present and up are true, then we still want to refresh + * to update the capabilities and restart the stats. + * + * We also store the address in all_ifaces and show them to the user, + * so we probably should monitor those events as well and update + * the interface list appropriately when those change. */ mainApp->refreshLocalInterfaces(); } @@ -1046,21 +1082,23 @@ void MainApplication::refreshLocalInterfaces() extcap_clear_interfaces(); #ifdef HAVE_LIBPCAP - /* - * Reload the local interface list. - */ - scan_local_interfaces(main_window_update); - - /* - * Now emit a signal to indicate that the list changed, so that all - * places displaying the list will get updated. - * - * XXX - only if it *did* change. - */ - emit localInterfaceListChanged(); + emit scanLocalInterfaces(nullptr); #endif } +#ifdef HAVE_LIBPCAP +GList* MainApplication::getInterfaceList() const +{ + return interface_list_copy(cached_if_list_); +} + +void MainApplication::setInterfaceList(GList *if_list) +{ + free_interface_list(cached_if_list_); + cached_if_list_ = interface_list_copy(if_list); +} +#endif + void MainApplication::allSystemsGo() { QString display_filter = NULL; @@ -1078,7 +1116,7 @@ void MainApplication::allSystemsGo() if (err == 0) { if_notifier_ = new QSocketNotifier(iface_mon_get_sock(), QSocketNotifier::Read, this); - connect(if_notifier_, SIGNAL(activated(int)), SLOT(ifChangeEventsAvailable())); + connect(if_notifier_, &QSocketNotifier::activated, this, &MainApplication::ifChangeEventsAvailable); } #endif } @@ -1100,9 +1138,6 @@ _e_prefs *MainApplication::readConfigurationFiles(bool reset) /* Load libwireshark settings from the current profile. */ prefs_p = epan_load_settings(); - /* Read the capture filter file. */ - read_filter_list(CFILTER_LIST); - return prefs_p; } @@ -1179,9 +1214,9 @@ void MainApplication::loadLanguage(const QString newLanguage) switchTranslator(mainApp->translator, QString("wireshark_%1.qm").arg(localeLanguage), QString(get_datafile_dir()) + QString("/languages")); if (QFile::exists(QString("%1/wireshark_%3.qm") - .arg(gchar_free_to_qstring(get_persconffile_path("languages", FALSE))).arg(localeLanguage))) + .arg(gchar_free_to_qstring(get_persconffile_path("languages", false))).arg(localeLanguage))) switchTranslator(mainApp->translator, - QString("wireshark_%1.qm").arg(localeLanguage), gchar_free_to_qstring(get_persconffile_path("languages", FALSE))); + QString("wireshark_%1.qm").arg(localeLanguage), gchar_free_to_qstring(get_persconffile_path("languages", false))); if (QFile::exists(QString("%1/qt_%2.qm") .arg(get_datafile_dir()).arg(localeLanguage))) { switchTranslator(mainApp->translatorQt, @@ -1382,3 +1417,11 @@ void MainApplication::gotoFrame(int frame) MainWindow * mw = qobject_cast(mainWindow()); mw->gotoFrame(frame); } + +void MainApplication::reloadDisplayFilterMacros() +{ + dfilter_macro_reload(); + // The signal is needed when the display filter grammar changes for + // any reason (not just "fields".) + mainApp->emitAppSignal(MainApplication::FieldsChanged); +} diff --git a/ui/qt/main_application.h b/ui/qt/main_application.h index dd5b0bab..de7aad0a 100644 --- a/ui/qt/main_application.h +++ b/ui/qt/main_application.h @@ -12,8 +12,6 @@ #include -#include - #include "wsutil/feature_list.h" #include "epan/register.h" @@ -56,6 +54,7 @@ public: enum AppSignal { CaptureFilterListChanged, + ColorsChanged, ColumnsChanged, DisplayFilterListChanged, FieldsChanged, @@ -89,6 +88,16 @@ public: // Emitting app signals (PacketDissectionChanged in particular) from // dialogs on macOS can be problematic. Dialogs should call queueAppSignal // instead. + // On macOS, nested event loops (e.g., calling a dialog with exec()) + // that call processEvents (e.g., from PacketDissectionChanged, or + // anything with a ProgressFrame) caused issues off and on from 5.3.0 + // until 5.7.1/5.8.0. It appears to be solved after some false starts: + // https://bugreports.qt.io/browse/QTBUG-53947 + // https://bugreports.qt.io/browse/QTBUG-56746 + // We also try to avoid exec / additional event loops as much as possible: + // e.g., commit f67eccedd9836e6ced1f57ae9889f57a5400a3d7 + // (note it can show up in unexpected places, e.g. static functions like + // WiresharkFileDialog::getOpenFileName()) void queueAppSignal(AppSignal signal) { app_signals_ << signal; } void emitStatCommandSignal(const QString &menu_path, const char *arg, void *userdata); void emitTapParameterSignal(const QString cfg_abbr, const QString arg, void *userdata); @@ -105,6 +114,13 @@ public: void emitLocalInterfaceEvent(const char *ifname, int added, int up); virtual void refreshLocalInterfaces(); +#ifdef HAVE_LIBPCAP + // This returns a deep copy of the cached interface list that must + // be freed with free_interface_list. + GList * getInterfaceList() const; + // This set the cached interface list to a deep copy of if_list. + void setInterfaceList(GList *if_list); +#endif struct _e_prefs * readConfigurationFiles(bool reset); QList recentItems() const; @@ -116,7 +132,7 @@ public: const QFont monospaceFont(bool zoomed = false) const; void setMonospaceFont(const char *font_string); int monospaceTextSize(const char *str); - void setConfigurationProfile(const gchar *profile_name, bool write_recent_file = true); + void setConfigurationProfile(const char *profile_name, bool write_recent_file = true); void reloadLuaPluginsDelayed(); bool isInitialized() { return initialized_; } void setReloadingLua(bool is_reloading) { is_reloading_lua_ = is_reloading; } @@ -160,6 +176,7 @@ private: static QString window_title_separator_; QList app_signals_; int active_captures_; + #if defined(HAVE_SOFTWARE_UPDATE) && defined(Q_OS_WIN) bool software_update_ok_; #endif @@ -173,10 +190,14 @@ protected: QIcon normal_icon_; QIcon capture_icon_; +#ifdef HAVE_LIBPCAP + GList *cached_if_list_; +#endif signals: void appInitialized(); void localInterfaceEvent(const char *ifname, int added, int up); + void scanLocalInterfaces(GList *filter_list = nullptr); void localInterfaceListChanged(); void openCaptureFile(QString cf_path, QString display_filter, unsigned int type); void openCaptureOptions(); @@ -184,7 +205,7 @@ signals: void updateRecentCaptureStatus(const QString &filename, qint64 size, bool accessible); void splashUpdate(register_action_e action, const char *message); void profileChanging(); - void profileNameChanged(const gchar *profile_name); + void profileNameChanged(const char *profile_name); void freezePacketList(bool changing_profile); void columnsChanged(); // XXX This recreates the packet list. We might want to rename it accordingly. @@ -192,6 +213,7 @@ signals: void displayFilterListChanged(); void filterExpressionsChanged(); void packetDissectionChanged(); + void colorsChanged(); void preferencesChanged(); void addressResolutionChanged(); void columnDataChanged(); @@ -223,6 +245,8 @@ public slots: // each dialog that calls queueAppSignal closes. void flushAppSignals(); + void reloadDisplayFilterMacros(); + private slots: void updateTaps(); diff --git a/ui/qt/main_status_bar.cpp b/ui/qt/main_status_bar.cpp index a504aa7a..3e5c6e9c 100644 --- a/ui/qt/main_status_bar.cpp +++ b/ui/qt/main_status_bar.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include "file.h" #include @@ -47,13 +45,13 @@ Q_DECLARE_METATYPE(ProfileDialog::ProfileAction) // If we ever add support for multiple windows this will need to be replaced. // See also: main_window.cpp -static MainStatusBar *cur_main_status_bar_ = NULL; +static MainStatusBar *cur_main_status_bar_; /* * Push a formatted temporary message onto the statusbar. */ void -statusbar_push_temporary_msg(const gchar *msg_format, ...) +statusbar_push_temporary_msg(const char *msg_format, ...) { va_list ap; QString push_msg; @@ -133,8 +131,8 @@ MainStatusBar::MainStatusBar(QWidget *parent) : comment_button_->setToolTip(tr("Open the Capture File Properties dialog")); comment_button_->setEnabled(false); - connect(expert_button_, SIGNAL(clicked(bool)), this, SIGNAL(showExpertInfo())); - connect(comment_button_, SIGNAL(clicked(bool)), this, SIGNAL(editCaptureComment())); + connect(expert_button_, &QToolButton::clicked, this, &MainStatusBar::showExpertInfo); + connect(comment_button_, &QToolButton::clicked, this, &MainStatusBar::editCaptureComment); info_progress_hb->setContentsMargins(icon_size / 2, 0, 0, 0); @@ -167,17 +165,13 @@ MainStatusBar::MainStatusBar(QWidget *parent) : progress_frame_.enableTaskbarUpdates(true); #endif - connect(mainApp, SIGNAL(appInitialized()), splitter, SLOT(show())); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(appInitialized())); - connect(&info_status_, SIGNAL(toggleTemporaryFlash(bool)), - this, SLOT(toggleBackground(bool))); - connect(mainApp, SIGNAL(profileNameChanged(const gchar *)), - this, SLOT(setProfileName())); - connect(&profile_status_, SIGNAL(clickedAt(QPoint,Qt::MouseButton)), - this, SLOT(showProfileMenu(QPoint,Qt::MouseButton))); - - connect(&progress_frame_, SIGNAL(stopLoading()), - this, SIGNAL(stopLoading())); + connect(mainApp, &MainApplication::appInitialized, splitter, &QSplitter::show); + connect(mainApp, &MainApplication::appInitialized, this, &MainStatusBar::appInitialized); + connect(&info_status_, &LabelStack::toggleTemporaryFlash, this, &MainStatusBar::toggleBackground); + connect(mainApp, &MainApplication::profileNameChanged, this, &MainStatusBar::setProfileName); + connect(&profile_status_, &ClickableLabel::clickedAt, this, &MainStatusBar::showProfileMenu); + + connect(&progress_frame_, &ProgressFrame::stopLoading, this, &MainStatusBar::stopLoading); } void MainStatusBar::showExpert() { @@ -235,8 +229,7 @@ void MainStatusBar::setFileName(CaptureFile &cf) if (cf.isValid()) { popGenericStatus(STATUS_CTX_FILE); QString msgtip = QString("%1 (%2)") - .arg(cf.capFile()->filename) - .arg(file_size_to_qstring(cf.capFile()->f_datalen)); + .arg(cf.capFile()->filename, file_size_to_qstring(cf.capFile()->f_datalen)); pushGenericStatus(STATUS_CTX_FILE, cf.fileName(), msgtip); } } @@ -264,8 +257,7 @@ void MainStatusBar::setStatusbarForCaptureFile() if (cap_file_ && cap_file_->filename && (cap_file_->state != FILE_CLOSED)) { popGenericStatus(STATUS_CTX_FILE); QString msgtip = QString("%1 (%2)") - .arg(cap_file_->filename) - .arg(file_size_to_qstring(cap_file_->f_datalen)); + .arg(cap_file_->filename, file_size_to_qstring(cap_file_->f_datalen)); pushGenericStatus(STATUS_CTX_FILE, gchar_free_to_qstring(cf_get_display_name(cap_file_)), msgtip); } @@ -298,7 +290,12 @@ void MainStatusBar::selectedFieldChanged(FieldInformation * finfo) finfo_length = finfo->position().length + finfo->appendix().length; if (finfo_length > 0) { - item_info.append(", " + tr("%Ln byte(s)", "", finfo_length)); + int finfo_bits = FI_GET_BITS_SIZE(finfo->fieldInfo()); + if (finfo_bits % 8 == 0) { + item_info.append(", " + tr("%Ln byte(s)", "", finfo_length)); + } else { + item_info.append(", " + tr("%Ln bit(s)", "", finfo_bits)); + } } } @@ -312,16 +309,14 @@ void MainStatusBar::highlightedFieldChanged(FieldInformation * finfo) if (finfo) { FieldInformation::Position pos = finfo->position(); - QString field_str; if (pos.length < 2) { - hint = QString(tr("Byte %1")).arg(pos.start); + hint = tr("Byte %1").arg(pos.start); } else { - hint = QString(tr("Bytes %1-%2")).arg(pos.start).arg(pos.start + pos.length - 1); + hint = tr("Bytes %1-%2").arg(pos.start).arg(pos.start + pos.length - 1); } hint += QString(": %1 (%2)") - .arg(finfo->headerInfo().name) - .arg(finfo->headerInfo().abbreviation); + .arg(finfo->headerInfo().name, finfo->headerInfo().abbreviation); } pushGenericStatus(STATUS_CTX_BYTE, hint); @@ -337,9 +332,7 @@ void MainStatusBar::pushGenericStatus(StatusContext status, const QString &messa if (message.isEmpty() && status != STATUS_CTX_FILE && status != STATUS_CTX_TEMPORARY && status != STATUS_CTX_PROGRESS) popGenericStatus(status); else - stack->pushText(message, status); - - stack->setToolTip(messagetip); + stack->pushText(message, status, messagetip); if (status == STATUS_CTX_FILTER || status == STATUS_CTX_FILE) expertUpdate(); @@ -352,8 +345,6 @@ void MainStatusBar::popGenericStatus(StatusContext status) if (status == STATUS_CTX_MAIN) stack = &packet_status_; - stack->setToolTip(QString()); - stack->popText(status); } @@ -365,7 +356,7 @@ void MainStatusBar::setProfileName() void MainStatusBar::appInitialized() { setProfileName(); - connect(mainApp->mainWindow(), SIGNAL(framesSelected(QList)), this, SLOT(selectedFrameChanged(QList))); + connect(qobject_cast(mainApp->mainWindow()), &MainWindow::framesSelected, this, &MainStatusBar::selectedFrameChanged); } void MainStatusBar::selectedFrameChanged(QList) @@ -390,48 +381,62 @@ void MainStatusBar::showCaptureStatistics() } if (cs_count_ > 0) { if (prefs.gui_show_selected_packet && rows.count() == 1) { - packets_str.append(QString(tr("Selected Packet: %1 %2 ")) - .arg(rows.at(0)) - .arg(UTF8_MIDDLE_DOT)); + if (is_packet_configuration_namespace()) { + packets_str.append(tr("Selected Packet: %1 %2 ") + .arg(rows.at(0)) + .arg(UTF8_MIDDLE_DOT)); + } else { + packets_str.append(tr("Selected Event: %1 %2 ") + .arg(rows.at(0)) + .arg(UTF8_MIDDLE_DOT)); + } + } + if (is_packet_configuration_namespace()) { + packets_str.append(tr("Packets: %1") + .arg(cs_count_)); + } else { + packets_str.append(tr("Events: %1") + .arg(cs_count_)); + } + if (cap_file_->dfilter) { + packets_str.append(tr(" %1 Displayed: %2 (%3%)") + .arg(UTF8_MIDDLE_DOT) + .arg(cap_file_->displayed_count) + .arg((100.0*cap_file_->displayed_count)/cs_count_, 0, 'f', 1)); } - packets_str.append(QString(tr("Packets: %1 %4 Displayed: %2 (%3%)")) - .arg(cs_count_) - .arg(cap_file_->displayed_count) - .arg((100.0*cap_file_->displayed_count)/cs_count_, 0, 'f', 1) - .arg(UTF8_MIDDLE_DOT)); if (rows.count() > 1) { - packets_str.append(QString(tr(" %1 Selected: %2 (%3%)")) + packets_str.append(tr(" %1 Selected: %2 (%3%)") .arg(UTF8_MIDDLE_DOT) .arg(rows.count()) .arg((100.0*rows.count())/cs_count_, 0, 'f', 1)); } if (cap_file_->marked_count > 0) { - packets_str.append(QString(tr(" %1 Marked: %2 (%3%)")) + packets_str.append(tr(" %1 Marked: %2 (%3%)") .arg(UTF8_MIDDLE_DOT) .arg(cap_file_->marked_count) .arg((100.0*cap_file_->marked_count)/cs_count_, 0, 'f', 1)); } if (cap_file_->drops_known) { - packets_str.append(QString(tr(" %1 Dropped: %2 (%3%)")) + packets_str.append(tr(" %1 Dropped: %2 (%3%)") .arg(UTF8_MIDDLE_DOT) .arg(cap_file_->drops) .arg((100.0*cap_file_->drops)/cs_count_, 0, 'f', 1)); } if (cap_file_->ignored_count > 0) { - packets_str.append(QString(tr(" %1 Ignored: %2 (%3%)")) + packets_str.append(tr(" %1 Ignored: %2 (%3%)") .arg(UTF8_MIDDLE_DOT) .arg(cap_file_->ignored_count) .arg((100.0*cap_file_->ignored_count)/cs_count_, 0, 'f', 1)); } if (cap_file_->packet_comment_count > 0) { - packets_str.append(QString(tr(" %1 Comments: %2")) + packets_str.append(tr(" %1 Comments: %2") .arg(UTF8_MIDDLE_DOT) .arg(cap_file_->packet_comment_count)); } if (prefs.gui_show_file_load_time && !cap_file_->is_tempfile) { /* Loading an existing file */ - gulong computed_elapsed = cf_get_computed_elapsed(cap_file_); - packets_str.append(QString(tr(" %1 Load time: %2:%3.%4")) + unsigned long computed_elapsed = cf_get_computed_elapsed(cap_file_); + packets_str.append(tr(" %1 Load time: %2:%3.%4") .arg(UTF8_MIDDLE_DOT) .arg(computed_elapsed/60000, 2, 10, QLatin1Char('0')) .arg(computed_elapsed%60000/1000, 2, 10, QLatin1Char('0')) @@ -440,18 +445,32 @@ void MainStatusBar::showCaptureStatistics() } } else if (cs_fixed_ && cs_count_ > 0) { /* There shouldn't be any rows without a cap_file_ but this is benign */ - if (prefs.gui_show_selected_packet && rows.count() == 1) { - packets_str.append(QString(tr("Selected Packet: %1 %2 ")) - .arg(rows.at(0)) - .arg(UTF8_MIDDLE_DOT)); + if (is_packet_configuration_namespace()) { + if (prefs.gui_show_selected_packet && rows.count() == 1) { + packets_str.append(tr("Selected Packet: %1 %2 ") + .arg(rows.at(0)) + .arg(UTF8_MIDDLE_DOT)); + } + packets_str.append(tr("Packets: %1") + .arg(cs_count_)); + } else { + if (prefs.gui_show_selected_packet && rows.count() == 1) { + packets_str.append(tr("Selected Event: %1 %2 ") + .arg(rows.at(0)) + .arg(UTF8_MIDDLE_DOT)); + } + packets_str.append(tr("Events: %1") + .arg(cs_count_)); } - packets_str.append(QString(tr("Packets: %1")) - .arg(cs_count_)); } #endif // HAVE_LIBPCAP if (packets_str.isEmpty()) { - packets_str = tr("No Packets"); + if (is_packet_configuration_namespace()) { + packets_str = tr("No Packets"); + } else { + packets_str = tr("No Events"); + } } popGenericStatus(STATUS_CTX_MAIN); @@ -580,7 +599,7 @@ void MainStatusBar::showProfileMenu(const QPoint &global_pos, Qt::MouseButton bu action->setEnabled(enable_edit); ctx_menu_->addSeparator(); -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) QMenu * importMenu = new QMenu(tr("Import"), ctx_menu_); action = importMenu->addAction(tr("From Zip File..."), this, SLOT(manageProfile())); action->setProperty("dialog_action_", (int)ProfileDialog::ImportZipProfile); diff --git a/ui/qt/main_status_bar.h b/ui/qt/main_status_bar.h index 611bc017..c53bc54a 100644 --- a/ui/qt/main_status_bar.h +++ b/ui/qt/main_status_bar.h @@ -65,7 +65,7 @@ private: // Capture statistics bool cs_fixed_; - guint32 cs_count_; + uint32_t cs_count_; void showCaptureStatistics(); void setStatusbarForCaptureFile(); diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 0f54995f..5c96863a 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -9,14 +9,19 @@ #include "config.h" -#include - #include "ui/preference_utils.h" #include "main_window.h" +#include "epan/dfilter/dfilter-translator.h" + +#include + #include "funnel_statistics.h" +#include "main_application.h" #include "packet_list.h" +#include "utils/profile_switcher.h" +#include "utils/qt_ui_utils.h" #include "widgets/display_filter_combo.h" // Packet Menu actions @@ -32,7 +37,8 @@ MainWindow::MainWindow(QWidget *parent) : byte_view_tab_(nullptr), packet_diagram_(nullptr), df_combo_box_(nullptr), - main_status_bar_(nullptr) + main_status_bar_(nullptr), + profile_switcher_(new ProfileSwitcher()) { } @@ -51,7 +57,7 @@ bool MainWindow::hasSelection() /* * As hasSelection() is not looking for one single packet - * selection, but at least 2, this method returns TRUE in + * selection, but at least 2, this method returns true in * this specific case. */ bool MainWindow::hasUniqueSelection() @@ -76,9 +82,9 @@ frame_data* MainWindow::frameDataForRow(int row) const return Q_NULLPTR; } -void MainWindow::insertColumn(QString name, QString abbrev, gint pos) +void MainWindow::insertColumn(QString name, QString abbrev, int pos) { - gint colnr = 0; + int colnr = 0; if (name.length() > 0 && abbrev.length() > 0) { colnr = column_prefs_add_custom(COL_CUSTOM, name.toStdString().c_str(), abbrev.toStdString().c_str(), pos); @@ -115,10 +121,10 @@ void MainWindow::setDisplayFilter(QString filter, FilterAction::Action action, F * * @param funnel_action a custom packet menu action */ -void MainWindow::appendPacketMenu(QAction* funnel_action) +void MainWindow::appendPacketMenu(FunnelAction* funnel_action) { dynamic_packet_menu_actions.append(funnel_action); - connect(funnel_action, SIGNAL(triggered(bool)), funnel_action, SLOT(triggerPacketCallback())); + connect(funnel_action, &FunnelAction::triggered, funnel_action, &FunnelAction::triggerPacketCallback); } /* @@ -177,7 +183,7 @@ bool MainWindow::addPacketMenus(QMenu * ctx_menu, GPtrArray *finfo_array) // Build a set of fields present for efficient lookups QSet fieldsPresent = QSet(); - for (guint fieldInfoIndex = 0; fieldInfoIndex < finfo_array->len; fieldInfoIndex++) { + for (unsigned fieldInfoIndex = 0; fieldInfoIndex < finfo_array->len; fieldInfoIndex++) { field_info *fi = (field_info *)g_ptr_array_index (finfo_array, fieldInfoIndex); fieldsPresent.insert(QString(fi->hfinfo->abbrev)); } @@ -203,3 +209,67 @@ bool MainWindow::addPacketMenus(QMenu * ctx_menu, GPtrArray *finfo_array) } return insertedPacketMenu; } + +const char *MainWindow::translator_ = "translator"; +const char *MainWindow::translated_filter_ = "translated filter"; + +void MainWindow::addDisplayFilterTranslationActions(QMenu *copy_menu) { + if (!copy_menu) { + return; + } + + char **df_translators = get_dfilter_translator_list(); + + if (df_translators == NULL || df_translators[0] == NULL) { + return; + } + + copy_menu->addSeparator(); + + for (size_t idx = 0; df_translators[idx]; idx++) { + QString translator = df_translators[idx]; + QString action_text; + if (idx == 0) { + action_text = tr("Display filter as %1").arg(translator); + } else { + action_text = tr(UTF8_HORIZONTAL_ELLIPSIS "as %1").arg(translator); + } + QAction *xlate_action = copy_menu->addAction(action_text); + xlate_action->setProperty(translator_, QVariant::fromValue(translator)); + xlate_action->setEnabled(false); + connect(xlate_action, &QAction::triggered, this, &MainWindow::copyDisplayFilterTranslation); + df_translate_actions_ += xlate_action; + } + + g_free(df_translators); +} + +void MainWindow::updateDisplayFilterTranslationActions(const QString &df_text) +{ + for (QAction *xlate_action : df_translate_actions_) { + bool enable = false; + QString translated_filter; + if (!df_text.isEmpty()) { + QString translator = xlate_action->property(translator_).toString(); + translated_filter = gchar_free_to_qstring((char *)translate_dfilter(qUtf8Printable(translator), + qUtf8Printable(df_text))); + if (!translated_filter.isEmpty()) { + enable = true; + } + } + xlate_action->setEnabled(enable); + xlate_action->setProperty(translated_filter_, QVariant::fromValue(translated_filter)); + } +} + +void MainWindow::copyDisplayFilterTranslation() +{ + QAction *xlate_action = qobject_cast(sender()); + if (!xlate_action) { + return; + } + + QString translated_filter = xlate_action->property(translated_filter_).toString(); + mainApp->clipboard()->setText(translated_filter); +} + diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index ac5ddcf4..2f78a261 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -19,18 +19,23 @@ #include "filter_action.h" +#include "io_graph_action.h" #include #include +class QMenu; class QSplitter; class QStackedWidget; + class ByteViewTab; class DisplayFilterCombo; class FieldInformation; +class FunnelAction; class MainStatusBar; class PacketDiagram; class PacketList; +class ProfileSwitcher; class ProtoTree; class WelcomePage; @@ -45,7 +50,7 @@ public: bool hasSelection(); bool hasUniqueSelection(); QList selectedRows(bool useFrameNum = false); - void insertColumn(QString name, QString abbrev, gint pos = -1); + void insertColumn(QString name, QString abbrev, int pos = -1); void gotoFrame(int packet_num); frame_data* frameDataForRow(int) const; @@ -53,7 +58,7 @@ public: MainStatusBar *statusBar(); // Used for managing custom packet menus - void appendPacketMenu(QAction* funnel_action); + void appendPacketMenu(FunnelAction *funnel_action); QList getPacketMenuActions(); void clearAddedPacketMenus(); bool addPacketMenus(QMenu * ctx_menu, GPtrArray *finfo_array); @@ -62,6 +67,7 @@ public slots: void setDisplayFilter(QString filter, FilterAction::Action action, FilterAction::ActionType filterType); virtual void filterPackets(QString, bool) = 0; virtual void showPreferencesDialog(QString module_name) = 0; + virtual void showIOGraphDialog(io_graph_item_unit_t, QString) = 0; void layoutPanes(); void applyRecentPaneGeometry(); @@ -96,6 +102,20 @@ protected: PacketDiagram *packet_diagram_; DisplayFilterCombo *df_combo_box_; MainStatusBar *main_status_bar_; + ProfileSwitcher *profile_switcher_; + +protected slots: + void addDisplayFilterTranslationActions(QMenu *copy_menu); + void updateDisplayFilterTranslationActions(const QString &df_text); + +private: + QVector df_translate_actions_; + + static const char *translator_; + static const char *translated_filter_; + +private slots: + void copyDisplayFilterTranslation(void); signals: void setCaptureFile(capture_file *cf); diff --git a/ui/qt/main_window_layout.cpp b/ui/qt/main_window_layout.cpp index b65b267f..9e2b5a3c 100644 --- a/ui/qt/main_window_layout.cpp +++ b/ui/qt/main_window_layout.cpp @@ -88,7 +88,9 @@ void MainWindow::layoutPanes() packet_list_->setParent(main_stack_); proto_tree_->setParent(main_stack_); byte_view_tab_->setParent(main_stack_); - packet_diagram_->setParent(main_stack_); + if (packet_diagram_) { + packet_diagram_->setParent(main_stack_); + } empty_pane_.setParent(main_stack_); extra_split_.setParent(main_stack_); @@ -163,7 +165,9 @@ void MainWindow::layoutPanes() packet_list_->setVisible(ms_children.contains(packet_list_) && recent.packet_list_show); proto_tree_->setVisible(ms_children.contains(proto_tree_) && recent.tree_view_show); byte_view_tab_->setVisible(ms_children.contains(byte_view_tab_) && recent.byte_view_show); - packet_diagram_->setVisible(ms_children.contains(packet_diagram_) && recent.packet_diagram_show); + if (packet_diagram_) { + packet_diagram_->setVisible(ms_children.contains(packet_diagram_) && recent.packet_diagram_show); + } if (frozen) { packet_list_->thaw(true); @@ -177,59 +181,65 @@ void MainWindow::layoutPanes() // - When the profile changes void MainWindow::applyRecentPaneGeometry() { - // XXX This shrinks slightly each time the application is run. For some - // reason the master_split_ geometry is two pixels shorter when - // saveWindowGeometry is invoked. - - // This is also an awful lot of trouble to go through to reuse the GTK+ - // pane settings. We might want to add gui.geometry_main_master_sizes - // and gui.geometry_main_extra_sizes and save QSplitter::saveState in - // each. - - // Force a geometry recalculation - QWidget *cur_w = main_stack_->currentWidget(); - showCapture(); - QRect geom = main_stack_->geometry(); - QList master_sizes = master_split_.sizes(); - QList extra_sizes = extra_split_.sizes(); - main_stack_->setCurrentWidget(cur_w); - - int master_last_size = master_split_.orientation() == Qt::Vertical ? geom.height() : geom.width(); - master_last_size -= master_split_.handleWidth() * (master_sizes.length() - 1); - - int extra_last_size = extra_split_.orientation() == Qt::Vertical ? geom.height() : geom.width(); - extra_last_size -= extra_split_.handleWidth(); - - if (recent.gui_geometry_main_upper_pane > 0) { - master_sizes[0] = recent.gui_geometry_main_upper_pane; - master_last_size -= recent.gui_geometry_main_upper_pane; - } else { - master_sizes[0] = master_last_size / master_sizes.length(); - master_last_size -= master_last_size / master_sizes.length(); - } - - if (recent.gui_geometry_main_lower_pane > 0) { - if (master_sizes.length() > 2) { - master_sizes[1] = recent.gui_geometry_main_lower_pane; - master_last_size -= recent.gui_geometry_main_lower_pane; - } else if (extra_sizes.length() > 0) { - extra_sizes[0] = recent.gui_geometry_main_lower_pane; - extra_last_size -= recent.gui_geometry_main_lower_pane; - extra_sizes.last() = extra_last_size; + if (recent.gui_geometry_main_master_split == nullptr || + recent.gui_geometry_main_extra_split == nullptr || + !master_split_.restoreState(QByteArray::fromHex(recent.gui_geometry_main_master_split)) || + !extra_split_.restoreState(QByteArray::fromHex(recent.gui_geometry_main_extra_split))) { + // Restoring the splitter states via the savedState didn't work, + // so let's fall back to the older method. + // + // XXX This shrinks slightly each time the application is run. For some + // reason the master_split_ geometry is two pixels shorter when + // saveWindowGeometry is invoked. + + // This is also an awful lot of trouble to go through to reuse the GTK+ + // pane settings. + + // Force a geometry recalculation + QWidget *cur_w = main_stack_->currentWidget(); + showCapture(); + QRect geom = main_stack_->geometry(); + QList master_sizes = master_split_.sizes(); + QList extra_sizes = extra_split_.sizes(); + main_stack_->setCurrentWidget(cur_w); + + int master_last_size = master_split_.orientation() == Qt::Vertical ? geom.height() : geom.width(); + master_last_size -= master_split_.handleWidth() * (master_sizes.length() - 1); + + int extra_last_size = extra_split_.orientation() == Qt::Vertical ? geom.height() : geom.width(); + extra_last_size -= extra_split_.handleWidth(); + + if (recent.gui_geometry_main_upper_pane > 0) { + master_sizes[0] = recent.gui_geometry_main_upper_pane; + master_last_size -= recent.gui_geometry_main_upper_pane; + } else { + master_sizes[0] = master_last_size / master_sizes.length(); + master_last_size -= master_last_size / master_sizes.length(); } - } else { - if (master_sizes.length() > 2) { - master_sizes[1] = master_last_size / 2; - master_last_size -= master_last_size / 2; - } else if (extra_sizes.length() > 0) { - extra_sizes[0] = extra_last_size / 2; - extra_last_size -= extra_last_size / 2; - extra_sizes.last() = extra_last_size; + + if (recent.gui_geometry_main_lower_pane > 0) { + if (master_sizes.length() > 2) { + master_sizes[1] = recent.gui_geometry_main_lower_pane; + master_last_size -= recent.gui_geometry_main_lower_pane; + } else if (extra_sizes.length() > 0) { + extra_sizes[0] = recent.gui_geometry_main_lower_pane; + extra_last_size -= recent.gui_geometry_main_lower_pane; + extra_sizes.last() = extra_last_size; + } + } else { + if (master_sizes.length() > 2) { + master_sizes[1] = master_last_size / 2; + master_last_size -= master_last_size / 2; + } else if (extra_sizes.length() > 0) { + extra_sizes[0] = extra_last_size / 2; + extra_last_size -= extra_last_size / 2; + extra_sizes.last() = extra_last_size; + } } - } - master_sizes.last() = master_last_size; + master_sizes.last() = master_last_size; - master_split_.setSizes(master_sizes); - extra_split_.setSizes(extra_sizes); + master_split_.setSizes(master_sizes); + extra_split_.setSizes(extra_sizes); + } } diff --git a/ui/qt/main_window_preferences_frame.cpp b/ui/qt/main_window_preferences_frame.cpp index 9659c928..447540f7 100644 --- a/ui/qt/main_window_preferences_frame.cpp +++ b/ui/qt/main_window_preferences_frame.cpp @@ -48,6 +48,7 @@ MainWindowPreferencesFrame::MainWindowPreferencesFrame(QWidget *parent) : ).arg(ui->geometryCheckBox->style()->subElementRect(QStyle::SE_CheckBoxContents, &style_opt).left()); ui->foStyleLastOpenedRadioButton->setStyleSheet(indent_ss); ui->foStyleSpecifiedRadioButton->setStyleSheet(indent_ss); + ui->foStyleCWDRadioButton->setStyleSheet(indent_ss); ui->maxFilterLineEdit->setStyleSheet(indent_ss); ui->maxRecentLineEdit->setStyleSheet(indent_ss); @@ -66,7 +67,7 @@ MainWindowPreferencesFrame::MainWindowPreferencesFrame(QWidget *parent) : ui->languageComboBox->setItemIcon(0, language_icon); QString globalLanguagesPath(QString(get_datafile_dir()) + "/languages/"); - QString userLanguagesPath(gchar_free_to_qstring(get_persconffile_path("languages/", FALSE))); + QString userLanguagesPath(gchar_free_to_qstring(get_persconffile_path("languages/", false))); QStringList filenames = QDir(":/i18n/").entryList(QStringList("wireshark_*.qm")); filenames += QDir(globalLanguagesPath).entryList(QStringList("wireshark_*.qm")); @@ -114,10 +115,18 @@ void MainWindowPreferencesFrame::updateWidgets() ui->geometryCheckBox->setChecked(false); } - if (prefs_get_enum_value(pref_fileopen_style_, pref_stashed) == FO_STYLE_LAST_OPENED) { + switch (prefs_get_enum_value(pref_fileopen_style_, pref_stashed)) { + + case FO_STYLE_LAST_OPENED: ui->foStyleLastOpenedRadioButton->setChecked(true); - } else { + break; + case FO_STYLE_CWD: + ui->foStyleCWDRadioButton->setChecked(true); + break; + case FO_STYLE_SPECIFIED: + default: ui->foStyleSpecifiedRadioButton->setChecked(true); + break; } ui->foStyleSpecifiedLineEdit->setText(prefs_get_string_value(pref_fileopen_dir_, pref_stashed)); @@ -148,6 +157,13 @@ void MainWindowPreferencesFrame::on_geometryCheckBox_toggled(bool checked) prefs_set_bool_value(pref_geometry_save_maximized_, checked, pref_stashed); } +void MainWindowPreferencesFrame::on_foStyleCWDRadioButton_toggled(bool checked) +{ + if (checked) { + prefs_set_enum_value(pref_fileopen_style_, FO_STYLE_CWD, pref_stashed); + } +} + void MainWindowPreferencesFrame::on_foStyleLastOpenedRadioButton_toggled(bool checked) { if (checked) { diff --git a/ui/qt/main_window_preferences_frame.h b/ui/qt/main_window_preferences_frame.h index 52d01049..2ba1064d 100644 --- a/ui/qt/main_window_preferences_frame.h +++ b/ui/qt/main_window_preferences_frame.h @@ -48,6 +48,7 @@ private: private slots: void on_geometryCheckBox_toggled(bool checked); + void on_foStyleCWDRadioButton_toggled(bool checked); void on_foStyleLastOpenedRadioButton_toggled(bool checked); void on_foStyleSpecifiedRadioButton_toggled(bool checked); void on_foStyleSpecifiedLineEdit_textEdited(const QString &new_dir); diff --git a/ui/qt/main_window_preferences_frame.ui b/ui/qt/main_window_preferences_frame.ui index 745e78b3..6ed803c3 100644 --- a/ui/qt/main_window_preferences_frame.ui +++ b/ui/qt/main_window_preferences_frame.ui @@ -84,6 +84,16 @@ + + + + The current working directory + + + openInButtonGroup + + + diff --git a/ui/qt/manage_interfaces_dialog.cpp b/ui/qt/manage_interfaces_dialog.cpp index a8529e26..ca7a1d9a 100644 --- a/ui/qt/manage_interfaces_dialog.cpp +++ b/ui/qt/manage_interfaces_dialog.cpp @@ -23,6 +23,10 @@ #include "ui/qt/remote_settings_dialog.h" #include "capture/capture-pcap-util.h" #include "ui/recent.h" +#include "wsutil/filesystem.h" +#include +#include +#include #endif #include "ui/iface_lists.h" #include "ui/preference_utils.h" @@ -72,53 +76,89 @@ enum { }; #ifdef HAVE_PCAP_REMOTE -static void populateExistingRemotes(gpointer key, gpointer value, gpointer user_data) +#define REMOTE_HOSTS_FILE "remote_hosts.json" + +void ManageInterfacesDialog::addRemote(const QVariantMap&& remoteHostMap) { - ManageInterfacesDialog *dialog = (ManageInterfacesDialog*)user_data; - const gchar *host = (const gchar *)key; - struct remote_host *remote_host = (struct remote_host *)value; remote_options global_remote_opts; int err; - gchar *err_str; + char* err_str; global_remote_opts.src_type = CAPTURE_IFREMOTE; - global_remote_opts.remote_host_opts.remote_host = g_strdup(host); - global_remote_opts.remote_host_opts.remote_port = g_strdup(remote_host->remote_port); - global_remote_opts.remote_host_opts.auth_type = remote_host->auth_type; - global_remote_opts.remote_host_opts.auth_username = g_strdup(remote_host->auth_username); - global_remote_opts.remote_host_opts.auth_password = g_strdup(remote_host->auth_password); - global_remote_opts.remote_host_opts.datatx_udp = FALSE; - global_remote_opts.remote_host_opts.nocap_rpcap = TRUE; - global_remote_opts.remote_host_opts.nocap_local = FALSE; + global_remote_opts.remote_host_opts.remote_host = qstring_strdup(remoteHostMap["host"].toString()); + global_remote_opts.remote_host_opts.remote_port = qstring_strdup(remoteHostMap["port"].toString()); + global_remote_opts.remote_host_opts.auth_type = static_cast(remoteHostMap["auth"].toInt()); + global_remote_opts.remote_host_opts.auth_username = qstring_strdup(remoteHostMap["username"].toString()); + global_remote_opts.remote_host_opts.auth_password = qstring_strdup(remoteHostMap["password"].toString()); + global_remote_opts.remote_host_opts.datatx_udp = false; + global_remote_opts.remote_host_opts.nocap_rpcap = true; + global_remote_opts.remote_host_opts.nocap_local = false; #ifdef HAVE_PCAP_SETSAMPLING global_remote_opts.sampling_method = CAPTURE_SAMP_NONE; - global_remote_opts.sampling_param = 0; + global_remote_opts.sampling_param = 0; #endif - GList *rlist = get_remote_interface_list(global_remote_opts.remote_host_opts.remote_host, - global_remote_opts.remote_host_opts.remote_port, - global_remote_opts.remote_host_opts.auth_type, - global_remote_opts.remote_host_opts.auth_username, - global_remote_opts.remote_host_opts.auth_password, - &err, &err_str); + + // This doesn't handle CAPTURE_AUTH_PWD because we don't store the password + // XXX: Don't these strings get leaked? I think that they're dup'ed again + // later. Same for in RemoteCaptureDialog::apply_remote() + + GList* rlist = get_remote_interface_list(global_remote_opts.remote_host_opts.remote_host, + global_remote_opts.remote_host_opts.remote_port, + global_remote_opts.remote_host_opts.auth_type, + global_remote_opts.remote_host_opts.auth_username, + global_remote_opts.remote_host_opts.auth_password, + &err, &err_str); + if (rlist == NULL) { switch (err) { case 0: - QMessageBox::warning(dialog, QObject::tr("Error"), QObject::tr("No remote interfaces found.")); + QMessageBox::warning(this, QObject::tr("Error"), QObject::tr("No remote interfaces found.")); break; case CANT_GET_INTERFACE_LIST: - QMessageBox::critical(dialog, QObject::tr("Error"), err_str); + QMessageBox::critical(this, QObject::tr("Error"), err_str); break; case DONT_HAVE_PCAP: - QMessageBox::critical(dialog, QObject::tr("Error"), QObject::tr("PCAP not found")); + QMessageBox::critical(this, QObject::tr("Error"), QObject::tr("PCAP not found")); break; default: - QMessageBox::critical(dialog, QObject::tr("Error"), QObject::tr("Unknown error")); + QMessageBox::critical(this, QObject::tr("Error"), QObject::tr("Unknown error")); break; } return; } + // XXX: If the connection fails we won't add it, so it won't get saved to + // load automatically next time (but will perhaps still be in recent.) + // That's mostly a feature not a bug, but we might want support for + // currently disabled remote hosts. + + emit remoteAdded(rlist, &global_remote_opts); +} + +void ManageInterfacesDialog::populateExistingRemotes() +{ + const char* cfile = REMOTE_HOSTS_FILE; + + /* Try personal config file first */ + QString fileName = gchar_free_to_qstring(get_persconffile_path(cfile, true)); + + if (fileName.isEmpty() || !QFileInfo::exists(fileName)) { + return; + } + + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) { + return; + } + + QJsonDocument document = QJsonDocument::fromJson(file.readAll()); + if (!document.isArray()) { + return; + } + + foreach(QJsonValue value, document.array()) { + addRemote(value.toObject().toVariantMap()); + } - emit dialog->remoteAdded(rlist, &global_remote_opts); } #endif /* HAVE_PCAP_REMOTE */ @@ -157,10 +197,13 @@ ManageInterfacesDialog::ManageInterfacesDialog(QWidget *parent) : proxyModel->setRemoteDisplay(false); #endif proxyModel->setFilterByType(false); + proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); ui->localView->setModel(proxyModel); ui->localView->resizeColumnToContents(proxyModel->mapSourceToColumn(IFTREE_COL_HIDDEN)); ui->localView->resizeColumnToContents(proxyModel->mapSourceToColumn(IFTREE_COL_NAME)); + ui->localView->header()->setSortIndicator(-1, Qt::AscendingOrder); + ui->localView->setSortingEnabled(true); pipeProxyModel = new InterfaceSortFilterModel(this); columns.clear(); @@ -176,7 +219,7 @@ ManageInterfacesDialog::ManageInterfacesDialog(QWidget *parent) : ui->pipeView->setModel(pipeProxyModel); ui->delPipe->setEnabled(pipeProxyModel->rowCount() > 0); - ui->pipeView->setItemDelegateForColumn(pipeProxyModel->mapSourceToColumn(IFTREE_COL_PIPE_PATH), new PathSelectionDelegate()); + ui->pipeView->setItemDelegateForColumn(pipeProxyModel->mapSourceToColumn(IFTREE_COL_PIPE_PATH), new PathSelectionDelegate(this)); connect(ui->pipeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [=](const QItemSelection &sel, const QItemSelection &) { ui->delPipe->setEnabled(sel.count() > 0); }); @@ -200,7 +243,7 @@ ManageInterfacesDialog::ManageInterfacesDialog(QWidget *parent) : connect(this, SIGNAL(remoteAdded(GList*, remote_options*)), this, SLOT(addRemoteInterfaces(GList*, remote_options*))); connect(this, SIGNAL(remoteSettingsChanged(interface_t *)), this, SLOT(setRemoteSettings(interface_t *))); connect(ui->remoteList, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(remoteSelectionChanged(QTreeWidgetItem*, int))); - recent_remote_host_list_foreach(populateExistingRemotes, this); + populateExistingRemotes(); #endif ui->tabWidget->setCurrentIndex(tab_local_); @@ -272,8 +315,8 @@ void ManageInterfacesDialog::on_addPipe_clicked() memset(&device, 0, sizeof(device)); device.name = qstring_strdup(tr("New Pipe")); device.display_name = g_strdup(device.name); - device.hidden = FALSE; - device.selected = TRUE; + device.hidden = false; + device.selected = true; device.pmode = global_capture_opts.default_options.promisc_mode; device.has_snaplen = global_capture_opts.default_options.has_snaplen; device.snaplen = global_capture_opts.default_options.snaplen; @@ -319,20 +362,25 @@ void ManageInterfacesDialog::updateRemoteInterfaceList(GList* rlist, remote_opti GList *if_entry, *lt_entry; if_info_t *if_info; char *if_string = NULL; - gchar *descr, *auth_str; + char *descr, *auth_str; if_capabilities_t *caps; - gint linktype_count; + int linktype_count; bool monitor_mode, found = false; GSList *curr_addr; int ips = 0; - guint i; + unsigned i; if_addr_t *addr; data_link_info_t *data_link_info; GString *ip_str; link_row *linkr = NULL; interface_t device; - guint num_interfaces; + unsigned num_interfaces; + // Add any (remote) interface in rlist to the global list of all + // interfaces. + // Most of this is copied from scan_local_interfaces_filtered, but + // some of it doesn't make sense for remote interfaces (yet?) - we + // can't, for example, control monitor mode. num_interfaces = global_capture_opts.all_ifaces->len; for (if_entry = g_list_first(rlist); if_entry != NULL; if_entry = gxx_list_next(if_entry)) { auth_str = NULL; @@ -345,12 +393,12 @@ void ManageInterfacesDialog::updateRemoteInterfaceList(GList* rlist, remote_opti if (device.hidden) continue; if (strcmp(device.name, if_info->name) == 0) { - found = TRUE; + found = true; break; } } if (found) { - found = FALSE; + found = false; continue; } ip_str = g_string_new(""); @@ -430,11 +478,15 @@ void ManageInterfacesDialog::updateRemoteInterfaceList(GList* rlist, remote_opti linktype_count = 0; device.links = NULL; if (caps != NULL) { + GList *lt_list = caps->data_link_types; #ifdef HAVE_PCAP_CREATE - device.monitor_mode_enabled = monitor_mode; + device.monitor_mode_enabled = monitor_mode && caps->can_set_rfmon; device.monitor_mode_supported = caps->can_set_rfmon; + if (device.monitor_mode_enabled) { + lt_list = caps->data_link_types_rfmon; + } #endif - for (lt_entry = caps->data_link_types; lt_entry != NULL; lt_entry = gxx_list_next(lt_entry)) { + for (lt_entry = lt_list; lt_entry != NULL; lt_entry = gxx_list_next(lt_entry)) { data_link_info = gxx_list_data(data_link_info_t *, lt_entry); linkr = new link_row; /* @@ -459,8 +511,8 @@ void ManageInterfacesDialog::updateRemoteInterfaceList(GList* rlist, remote_opti } /* for link_types */ } else { #if defined(HAVE_PCAP_CREATE) - device.monitor_mode_enabled = FALSE; - device.monitor_mode_supported = FALSE; + device.monitor_mode_enabled = false; + device.monitor_mode_supported = false; #endif device.active_dlt = -1; } @@ -468,7 +520,7 @@ void ManageInterfacesDialog::updateRemoteInterfaceList(GList* rlist, remote_opti device.no_addresses = ips; device.remote_opts.src_type= roptions->src_type; if (device.remote_opts.src_type == CAPTURE_IFREMOTE) { - device.local = FALSE; + device.local = false; } device.remote_opts.remote_host_opts.remote_host = g_strdup(roptions->remote_host_opts.remote_host); device.remote_opts.remote_host_opts.remote_port = g_strdup(roptions->remote_host_opts.remote_port); @@ -482,7 +534,7 @@ void ManageInterfacesDialog::updateRemoteInterfaceList(GList* rlist, remote_opti device.remote_opts.sampling_method = roptions->sampling_method; device.remote_opts.sampling_param = roptions->sampling_param; #endif - device.selected = TRUE; + device.selected = true; global_capture_opts.num_selected++; g_array_append_val(global_capture_opts.all_ifaces, device); g_string_free(ip_str, TRUE); @@ -500,9 +552,17 @@ void ManageInterfacesDialog::addRemoteInterfaces(GList* rlist, remote_options *r void ManageInterfacesDialog::remoteAccepted() { QTreeWidgetItemIterator it(ui->remoteList); + QJsonArray hostArray; while (*it) { - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + if ((*it)->parent() == nullptr) { + QVariant v = (*it)->data(0, Qt::UserRole); + if (v.canConvert()) { + hostArray.append(v.toJsonValue()); + } + } + + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if ((*it)->text(col_r_host_dev_).compare(device->name)) continue; @@ -510,6 +570,21 @@ void ManageInterfacesDialog::remoteAccepted() } ++it; } + + const char* cfile = REMOTE_HOSTS_FILE; + /* Try personal config file first */ + QString fileName = gchar_free_to_qstring(get_persconffile_path(cfile, true)); + + if (fileName.isEmpty()) { + return; + } + + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly)) { + return; + } + + file.write(QJsonDocument(hostArray).toJson(QJsonDocument::Compact)); } void ManageInterfacesDialog::on_remoteList_currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *) @@ -523,7 +598,7 @@ void ManageInterfacesDialog::on_remoteList_itemClicked(QTreeWidgetItem *item, in return; } - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (!device->local) { if (item->text(col_r_host_dev_).compare(device->name)) @@ -540,7 +615,7 @@ void ManageInterfacesDialog::on_delRemote_clicked() return; } - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (item->text(col_r_host_dev_).compare(device->remote_opts.remote_host_opts.remote_host)) continue; @@ -559,7 +634,7 @@ void ManageInterfacesDialog::on_addRemote_clicked() void ManageInterfacesDialog::showRemoteInterfaces() { - guint i; + unsigned i; interface_t *device; QTreeWidgetItem * item = nullptr; @@ -580,6 +655,17 @@ void ManageInterfacesDialog::showRemoteInterfaces() if (items.count() == 0) { item = new QTreeWidgetItem(ui->remoteList); item->setText(col_r_host_dev_, parentName); + QJsonObject remote_host{ + {"host", parentName}, + {"port", device->remote_opts.remote_host_opts.remote_port}, + {"auth_type", device->remote_opts.remote_host_opts.auth_type}, + {"username", device->remote_opts.remote_host_opts.auth_username}, + // {"password", device->remote_opts.remote_host_opts.auth_password}, + // We should find some way to store the password in a + // credential manager (cf. #17949 for extcap) and + // reference it + }; + item->setData(0, Qt::UserRole, remote_host); item->setExpanded(true); } else { @@ -599,7 +685,7 @@ void ManageInterfacesDialog::showRemoteInterfaces() void ManageInterfacesDialog::on_remoteSettings_clicked() { - guint i = 0; + unsigned i = 0; interface_t *device; QTreeWidgetItem* item = ui->remoteList->currentItem(); if (!item) { @@ -622,7 +708,7 @@ void ManageInterfacesDialog::on_remoteSettings_clicked() void ManageInterfacesDialog::setRemoteSettings(interface_t *iface) { - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (!device->local) { if (strcmp(iface->name, device->name)) { diff --git a/ui/qt/manage_interfaces_dialog.h b/ui/qt/manage_interfaces_dialog.h index 79e9d0d9..de8db2d4 100644 --- a/ui/qt/manage_interfaces_dialog.h +++ b/ui/qt/manage_interfaces_dialog.h @@ -12,7 +12,6 @@ #include -#include #include "capture_opts.h" #include @@ -48,6 +47,10 @@ private: InterfaceSortFilterModel * pipeProxyModel; void showRemoteInterfaces(); +#ifdef HAVE_PCAP_REMOTE + void addRemote(const QVariantMap&&); + void populateExistingRemotes(); +#endif signals: void ifsChanged(); diff --git a/ui/qt/manager/wireshark_preference.cpp b/ui/qt/manager/wireshark_preference.cpp index cca87c7b..91f8bd20 100644 --- a/ui/qt/manager/wireshark_preference.cpp +++ b/ui/qt/manager/wireshark_preference.cpp @@ -80,6 +80,7 @@ public: }; REGISTER_PREFERENCE_TYPE(PREF_STRING, StringPreference) REGISTER_PREFERENCE_TYPE(PREF_CUSTOM, StringPreference) +REGISTER_PREFERENCE_TYPE(PREF_DISSECTOR, StringPreference) class PasswordPreference : public StringPreference { @@ -101,7 +102,6 @@ public: UIntPreference(QObject * parent = Q_NULLPTR) : StringPreference(parent) {} }; REGISTER_PREFERENCE_TYPE(PREF_UINT, UIntPreference) -REGISTER_PREFERENCE_TYPE(PREF_DECODE_AS_UINT, UIntPreference) class EnumPreference : public WiresharkPreference { diff --git a/ui/qt/manuf_dialog.cpp b/ui/qt/manuf_dialog.cpp index 0c383af3..d7ed9192 100644 --- a/ui/qt/manuf_dialog.cpp +++ b/ui/qt/manuf_dialog.cpp @@ -102,9 +102,9 @@ static QByteArray convertMacAddressToByteArray(const QString &bytesString) { GByteArray *bytes = g_byte_array_new(); - if (!hex_str_to_bytes(qUtf8Printable(bytesString), bytes, FALSE) + if (!hex_str_to_bytes(qUtf8Printable(bytesString), bytes, false) || bytes->len == 0 || bytes->len > 6) { - g_byte_array_free(bytes, TRUE); + g_byte_array_free(bytes, true); return QByteArray(); } diff --git a/ui/qt/models/astringlist_list_model.cpp b/ui/qt/models/astringlist_list_model.cpp index a0b5fc38..c3b3ec05 100644 --- a/ui/qt/models/astringlist_list_model.cpp +++ b/ui/qt/models/astringlist_list_model.cpp @@ -166,7 +166,6 @@ bool AStringListListSortFilterProxyModel::filterAcceptsRow(int sourceRow, const break; case FilterNone: return true; - break; default: compareFunc = AContainsB; break; diff --git a/ui/qt/models/astringlist_list_model.h b/ui/qt/models/astringlist_list_model.h index 70acc97b..f1e396c8 100644 --- a/ui/qt/models/astringlist_list_model.h +++ b/ui/qt/models/astringlist_list_model.h @@ -21,6 +21,7 @@ class AStringListListModel : public QAbstractTableModel { + Q_OBJECT public: explicit AStringListListModel(QObject * parent = Q_NULLPTR); virtual ~AStringListListModel(); diff --git a/ui/qt/models/atap_data_model.cpp b/ui/qt/models/atap_data_model.cpp index b7ff508d..c3a2f840 100644 --- a/ui/qt/models/atap_data_model.cpp +++ b/ui/qt/models/atap_data_model.cpp @@ -7,8 +7,6 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -#include - #include #include #include @@ -90,10 +88,12 @@ bool ATapDataModel::hasGeoIPData() while (!coordsFound && row < count) { QModelIndex idx = index(row, 0); - if (_type == ATapDataModel::DATAMODEL_ENDPOINT) - coordsFound = qobject_cast(this)->data(idx, ATapDataModel::GEODATA_AVAILABLE).toBool(); - else if (_type == ATapDataModel::DATAMODEL_CONVERSATION) - coordsFound = qobject_cast(this)->data(idx, ATapDataModel::GEODATA_AVAILABLE).toBool(); + if (!data(idx, ATapDataModel::ROW_IS_FILTERED).toBool()) { + if (_type == ATapDataModel::DATAMODEL_ENDPOINT) + coordsFound = qobject_cast(this)->data(idx, ATapDataModel::GEODATA_AVAILABLE).toBool(); + else if (_type == ATapDataModel::DATAMODEL_CONVERSATION) + coordsFound = qobject_cast(this)->data(idx, ATapDataModel::GEODATA_AVAILABLE).toBool(); + } row++; } @@ -585,6 +585,9 @@ void ConversationDataModel::doDataUpdate() int ConversationDataModel::columnCount(const QModelIndex &) const { + if(tap()=="tcp") + return CONV_TCP_EXT_NUM_COLUMNS; + return CONV_NUM_COLUMNS; } @@ -630,6 +633,15 @@ QVariant ConversationDataModel::headerData(int section, Qt::Orientation orientat case CONV_COLUMN_BPS_BA: return tr("Bits/s B " UTF8_RIGHTWARDS_ARROW " A"); break; } + /* Extended conversations columns, e.g. TCP */ + if(tap()=="tcp") { + switch (section) { + case CONV_TCP_EXT_COLUMN_A: + return tr("Flows"); break; + default : + ws_assert_not_reached(); break; + } + } } else if (role == Qt::TextAlignmentRole) { if (section == CONV_COLUMN_SRC_ADDR || section == CONV_COLUMN_DST_ADDR) return Qt::AlignLeft; @@ -701,7 +713,10 @@ QVariant ConversationDataModel::data(const QModelIndex &idx, int role) const return role == Qt::DisplayRole ? formatString((qlonglong)conv_item->tx_bytes + conv_item->rx_bytes) : QVariant((qlonglong)conv_item->tx_bytes + conv_item->rx_bytes); case CONV_COLUMN_CONV_ID: - return (int) conv_item->conv_id; + if(conv_item->conv_id!=CONV_ID_UNSET) { + return (int) conv_item->conv_id; + } + break; case CONV_COLUMN_PACKETS_TOTAL: { qlonglong packets = 0; @@ -722,7 +737,7 @@ QVariant ConversationDataModel::data(const QModelIndex &idx, int role) const /* Qt guarantees that this roundtrip conversion compares equally, * so filtering with equality will work as expected. * XXX: Perhaps the UNFORMATTED_DISPLAYDATA role shoud be split - * into one used for raw data export and comparisions with each + * into one used for raw data export and comparisons with each * other, and another for comparing with filters? */ return role == Qt::DisplayRole ? rounded + "%" : QVariant(rounded.toDouble()); @@ -778,6 +793,18 @@ QVariant ConversationDataModel::data(const QModelIndex &idx, int role) const case CONV_COLUMN_BPS_BA: return bpsCalculated ? (role == Qt::DisplayRole ? gchar_free_to_qstring(format_size((int64_t)bps_ba, FORMAT_SIZE_UNIT_BITS_S, FORMAT_SIZE_PREFIX_SI)) : QVariant((qlonglong)bps_ba)): QVariant(); } + /* Extended conversations columns, e.g. TCP */ + if(tap()=="tcp") { + switch(idx.column()) { + case CONV_TCP_EXT_COLUMN_A: + { + qlonglong flows = (qlonglong)conv_item->ext_tcp.flows; + return role == Qt::DisplayRole ? QString("%L1").arg(flows) : (QVariant)flows; break; + } + default : + ws_assert_not_reached(); break; + } + } } else if (role == Qt::ToolTipRole) { if (idx.column() == CONV_COLUMN_START || idx.column() == CONV_COLUMN_DURATION) return QObject::tr("Bars show the relative timeline for each conversation."); @@ -844,7 +871,11 @@ bool ConversationDataModel::showConversationId(int row) const return false; conv_item_t *conv_item = (conv_item_t *)&g_array_index(storage_, conv_item_t, row); - if (conv_item && (conv_item->ctype == CONVERSATION_TCP || conv_item->ctype == CONVERSATION_UDP)) + if (conv_item && (conv_item->ctype == CONVERSATION_TCP || + conv_item->ctype == CONVERSATION_UDP || + conv_item->ctype == CONVERSATION_IP || + conv_item->ctype == CONVERSATION_IPV6|| + conv_item->ctype == CONVERSATION_ETH)) return true; return false; } diff --git a/ui/qt/models/atap_data_model.h b/ui/qt/models/atap_data_model.h index 38bdbd2f..6ba0b325 100644 --- a/ui/qt/models/atap_data_model.h +++ b/ui/qt/models/atap_data_model.h @@ -12,8 +12,6 @@ #include "config.h" -#include "glib.h" - #include #include #include @@ -306,6 +304,12 @@ public: CONV_INDEX_COLUMN = CONV_NUM_COLUMNS } conversation_column_type_e; + typedef enum { + CONV_TCP_EXT_COLUMN_A = CONV_INDEX_COLUMN, + CONV_TCP_EXT_NUM_COLUMNS, + CONV_TCP_EXT_INDEX_COLUMN = CONV_TCP_EXT_NUM_COLUMNS + } conversation_tcp_ext_column_type_e; + explicit ConversationDataModel(int protoId, QString filter, QObject *parent = nullptr); int columnCount(const QModelIndex &parent = QModelIndex()) const; diff --git a/ui/qt/models/coloring_rules_delegate.cpp b/ui/qt/models/coloring_rules_delegate.cpp index b86ffa97..58524be1 100644 --- a/ui/qt/models/coloring_rules_delegate.cpp +++ b/ui/qt/models/coloring_rules_delegate.cpp @@ -32,7 +32,7 @@ QWidget* ColoringRulesDelegate::createEditor(QWidget *parent, const QStyleOption return new DisplayFilterEdit(parent); default: - Q_ASSERT(FALSE); + Q_ASSERT(false); return 0; } diff --git a/ui/qt/models/coloring_rules_model.cpp b/ui/qt/models/coloring_rules_model.cpp index dced9c37..29bb7dcf 100644 --- a/ui/qt/models/coloring_rules_model.cpp +++ b/ui/qt/models/coloring_rules_model.cpp @@ -72,7 +72,7 @@ ColoringRuleItem& ColoringRuleItem::operator=(ColoringRuleItem& rhs) // Callback for color_filters_clone. void -color_filter_add_cb(color_filter_t *colorf, gpointer user_data) +color_filter_add_cb(color_filter_t *colorf, void *user_data) { ColoringRulesModel *model = (ColoringRulesModel*)user_data; @@ -149,7 +149,7 @@ void ColoringRulesModel::addColor(bool disabled, QString filter, QColor foregrou bool ColoringRulesModel::importColors(QString filename, QString& err) { bool success = true; - gchar* err_msg = NULL; + char* err_msg = NULL; if (!color_filters_import(filename.toUtf8().constData(), this, &err_msg, color_filter_add_cb)) { err = gchar_free_to_qstring(err_msg); success = false; @@ -162,8 +162,8 @@ bool ColoringRulesModel::exportColors(QString filename, QString& err) { GSList *cfl = createColorFilterList(); bool success = true; - gchar* err_msg = NULL; - if (!color_filters_export(filename.toUtf8().constData(), cfl, FALSE, &err_msg)) { + char* err_msg = NULL; + if (!color_filters_export(filename.toUtf8().constData(), cfl, false, &err_msg)) { err = gchar_free_to_qstring(err_msg); success = false; } @@ -176,7 +176,7 @@ bool ColoringRulesModel::writeColors(QString& err) { GSList *cfl = createColorFilterList(); bool success = true; - gchar* err_msg = NULL; + char* err_msg = NULL; if (!color_filters_apply(conversation_colors_, cfl, &err_msg)) { err = gchar_free_to_qstring(err_msg); success = false; diff --git a/ui/qt/models/coloring_rules_model.h b/ui/qt/models/coloring_rules_model.h index f51a1a30..0df532ef 100644 --- a/ui/qt/models/coloring_rules_model.h +++ b/ui/qt/models/coloring_rules_model.h @@ -14,7 +14,6 @@ #include -#include #include #include diff --git a/ui/qt/models/column_list_model.cpp b/ui/qt/models/column_list_model.cpp index 102ffc31..7613e487 100644 --- a/ui/qt/models/column_list_model.cpp +++ b/ui/qt/models/column_list_model.cpp @@ -13,11 +13,11 @@ #include #include -#include #include #include #include #include +#include #include #include @@ -31,6 +31,8 @@ struct ListElement int type; int originalType; int occurrence; + int width; + char xalign; bool displayed; bool resolved; }; @@ -65,6 +67,22 @@ ColumnTypeDelegate::ColumnTypeDelegate(QObject * parent) : QStyledItemDelegate(parent) {} +QString ColumnTypeDelegate::alignDesc(char xalign) +{ + switch (xalign) { + case COLUMN_XALIGN_DEFAULT: + return QObject::tr("Default"); + case COLUMN_XALIGN_LEFT: + return QObject::tr("Left"); + case COLUMN_XALIGN_CENTER: + return QObject::tr("Center"); + case COLUMN_XALIGN_RIGHT: + return QObject::tr("Right"); + default: + return QObject::tr("Unknown"); + } +} + QWidget *ColumnTypeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const @@ -92,13 +110,26 @@ QWidget *ColumnTypeDelegate::createEditor(QWidget *parent, ff_editor->setText(index.data().toString()); editor = ff_editor; } - else if (index.column() == ColumnListModel::COL_OCCURRENCE) + else if (index.column() == ColumnListModel::COL_OCCURRENCE || + index.column() == ColumnListModel::COL_WIDTH) { SyntaxLineEdit * sl_editor = new SyntaxLineEdit(parent); connect(sl_editor, &SyntaxLineEdit::textChanged, sl_editor, &SyntaxLineEdit::checkInteger); sl_editor->setText(index.data().toString()); editor = sl_editor; } + else if (index.column() == ColumnListModel::COL_XALIGN) + { + QComboBox *cb_editor = new QComboBox(parent); + + cb_editor->addItem(alignDesc(COLUMN_XALIGN_DEFAULT), QVariant(COLUMN_XALIGN_DEFAULT)); + cb_editor->addItem(alignDesc(COLUMN_XALIGN_LEFT), QVariant(COLUMN_XALIGN_LEFT)); + cb_editor->addItem(alignDesc(COLUMN_XALIGN_CENTER), QVariant(COLUMN_XALIGN_CENTER)); + cb_editor->addItem(alignDesc(COLUMN_XALIGN_RIGHT), QVariant(COLUMN_XALIGN_RIGHT)); + cb_editor->setCurrentIndex(cb_editor->findText(index.data().toString())); + cb_editor->setFrame(false); + editor = cb_editor; + } if (!editor) { editor = QStyledItemDelegate::createEditor(parent, option, index); @@ -111,7 +142,8 @@ void ColumnTypeDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QVariant data = index.model()->data(index); - if (index.column() == ColumnListModel::COL_TYPE) + if (index.column() == ColumnListModel::COL_TYPE || + index.column() == ColumnListModel::COL_XALIGN) { QComboBox *comboBox = static_cast(editor); comboBox->setCurrentText(data.toString()); @@ -121,7 +153,8 @@ void ColumnTypeDelegate::setEditorData(QWidget *editor, if (qobject_cast(editor)) qobject_cast(editor)->setText(data.toString()); } - else if (index.column() == ColumnListModel::COL_OCCURRENCE) + else if (index.column() == ColumnListModel::COL_OCCURRENCE || + index.column() == ColumnListModel::COL_WIDTH) { if (qobject_cast(editor)) qobject_cast(editor)->setText(data.toString()); @@ -136,7 +169,8 @@ void ColumnTypeDelegate::setEditorData(QWidget *editor, void ColumnTypeDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { - if (index.column() == ColumnListModel::COL_TYPE) + if (index.column() == ColumnListModel::COL_TYPE || + index.column() == ColumnListModel::COL_XALIGN) { QComboBox *comboBox = static_cast(editor); bool ok = false; @@ -197,6 +231,22 @@ void ColumnTypeDelegate::setModelData(QWidget *editor, QAbstractItemModel *model } } + else if (index.column() == ColumnListModel::COL_WIDTH) + { + SyntaxLineEdit * sle = qobject_cast(editor); + bool ok = false; + if (sle) + { + sle->checkInteger(index.data().toString()); + if (sle->syntaxState() == SyntaxLineEdit::Valid) + ok = true; + } + + if (ok) + { + model->setData(index, sle->text(), Qt::EditRole); + } + } else QStyledItemDelegate::setModelData(editor, model, index); } @@ -216,7 +266,7 @@ ColumnListModel::ColumnListModel(QObject * parent): QVariant ColumnListModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (section > ColumnListModel::COL_RESOLVED || orientation != Qt::Horizontal || + if (section > ColumnListModel::COL_XALIGN || orientation != Qt::Horizontal || role != Qt::DisplayRole) return QVariant(); @@ -230,7 +280,7 @@ int ColumnListModel::rowCount(const QModelIndex &/*parent*/) const int ColumnListModel::columnCount(const QModelIndex &/*parent*/) const { - return ColumnListModel::COL_RESOLVED + 1; + return ColumnListModel::COL_XALIGN + 1; } QString ColumnListModel::headerTitle(int section) const @@ -249,6 +299,10 @@ QString ColumnListModel::headerTitle(int section) const return tr("Field Occurrence"); case ColumnListModel::COL_RESOLVED: return tr("Resolved"); + case ColumnListModel::COL_WIDTH: + return tr("Width"); + case ColumnListModel::COL_XALIGN: + return tr("Alignment"); } return QString(); @@ -271,6 +325,9 @@ void ColumnListModel::populate() ne.occurrence = cfmt->custom_occurrence; ne.resolved = cfmt->resolved; + ne.width = recent_get_column_width(nr); + ne.xalign = recent_get_column_xalign(nr); + nr++; store_ << ne; } @@ -298,6 +355,10 @@ QVariant ColumnListModel::data(const QModelIndex &index, int role) const return ne.customFields; case ColumnListModel::COL_OCCURRENCE: return ne.customFields.length() > 0 ? QVariant::fromValue(ne.occurrence) : QVariant(); + case ColumnListModel::COL_WIDTH: + return ne.width; + case ColumnListModel::COL_XALIGN: + return ColumnTypeDelegate::alignDesc(ne.xalign); } } else if (role == Qt::CheckStateRole) @@ -452,6 +513,20 @@ bool ColumnListModel::setData(const QModelIndex &index, const QVariant &value, i { store_[index.row()].resolved = value.toInt() == Qt::Checked ? true : false; } + else if (index.column() == ColumnListModel::COL_WIDTH) + { + bool ok = false; + int val = value.toInt(&ok); + if (ok) + store_[index.row()].width = val; + } + else if (index.column() == ColumnListModel::COL_XALIGN) + { + bool ok = false; + int val = value.toInt(&ok); + if (ok) + store_[index.row()].xalign = static_cast(val); + } if (change) emit dataChanged(index, index); @@ -471,7 +546,7 @@ void ColumnListModel::saveColumns() cfmt->title = qstring_strdup(elem.title); cfmt->visible = elem.displayed; cfmt->fmt = elem.type; - cfmt->resolved = TRUE; + cfmt->resolved = true; if (cfmt->fmt == COL_CUSTOM) { cfmt->custom_fields = qstring_strdup(elem.customFields); @@ -486,6 +561,16 @@ void ColumnListModel::saveColumns() column_prefs_remove_link(prefs.col_list); prefs.col_list = new_col_list; + + recent_free_column_width_info(&recent); + for (int row = 0; row < store_.count(); row++) + { + ListElement elem = store_.at(row); + + recent_insert_column(row); + recent_set_column_width(row, elem.width); + recent_set_column_xalign(row, elem.xalign); + } } void ColumnListModel::addEntry() @@ -499,6 +584,8 @@ void ColumnListModel::addEntry() elem.occurrence = 0; elem.customFields = QString(); elem.resolved = true; + elem.width = -1; + elem.xalign = COLUMN_XALIGN_DEFAULT; store_ << elem; endInsertRows(); } diff --git a/ui/qt/models/column_list_model.h b/ui/qt/models/column_list_model.h index c4739f96..7f59b91c 100644 --- a/ui/qt/models/column_list_model.h +++ b/ui/qt/models/column_list_model.h @@ -35,6 +35,8 @@ class ColumnTypeDelegate : public QStyledItemDelegate public: ColumnTypeDelegate(QObject * parent = Q_NULLPTR); + static QString alignDesc(char xalign); + QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; @@ -59,7 +61,9 @@ public: COL_TYPE, COL_FIELDS, COL_OCCURRENCE, - COL_RESOLVED + COL_RESOLVED, + COL_WIDTH, + COL_XALIGN }; enum { diff --git a/ui/qt/models/decode_as_delegate.cpp b/ui/qt/models/decode_as_delegate.cpp index 3c300a79..c3917928 100644 --- a/ui/qt/models/decode_as_delegate.cpp +++ b/ui/qt/models/decode_as_delegate.cpp @@ -46,11 +46,11 @@ void DecodeAsDelegate::cachePacketProtocols() if (cap_file_ && cap_file_->edt) { wmem_list_frame_t * protos = wmem_list_head(cap_file_->edt->pi.layers); - guint8 curr_layer_num = 1; + uint8_t curr_layer_num = 1; while (protos != NULL) { int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos)); - const gchar * proto_name = proto_get_protocol_filter_name(proto_id); + const char * proto_name = proto_get_protocol_filter_name(proto_id); for (GList *cur = decode_as_list; cur; cur = cur->next) { decode_as_t *entry = (decode_as_t *) cur->data; if (g_strcmp0(proto_name, entry->name) == 0) { @@ -95,7 +95,7 @@ void DecodeAsDelegate::collectDAProtocols(QSet& all_protocols, QList* proto_list = (QList*)user_data; @@ -178,10 +178,10 @@ QWidget* DecodeAsDelegate::createEditor(QWidget *parentWidget, const QStyleOptio case DecodeAsModel::colSelector: { QComboBox *cb_editor = NULL; - const gchar *proto_name = NULL; + const char *proto_name = NULL; bool edt_present = cap_file_ && cap_file_->edt; - gint8 curr_layer_num_saved = edt_present ? cap_file_->edt->pi.curr_layer_num : 0; - QList proto_layers; + int8_t curr_layer_num_saved = edt_present ? cap_file_->edt->pi.curr_layer_num : 0; + QList proto_layers; foreach(packet_proto_data_t proto, packet_proto_list_) { @@ -212,7 +212,7 @@ QWidget* DecodeAsDelegate::createEditor(QWidget *parentWidget, const QStyleOptio cb_editor->addItem(current_value); //get the value(s) from the packet - foreach(guint8 current_layer, proto_layers) { + foreach(uint8_t current_layer, proto_layers) { cap_file_->edt->pi.curr_layer_num = current_layer; for (uint ni = 0; ni < entry->num_items; ni++) { if (entry->values[ni].num_values == 1) { // Skip over multi-value ("both") entries diff --git a/ui/qt/models/decode_as_delegate.h b/ui/qt/models/decode_as_delegate.h index d0457764..d793a85a 100644 --- a/ui/qt/models/decode_as_delegate.h +++ b/ui/qt/models/decode_as_delegate.h @@ -13,7 +13,6 @@ #define DECODE_AS_DELEGATE_H #include -#include #include "cfile.h" @@ -23,9 +22,9 @@ #include typedef struct _packet_proto_data_t { - const gchar* proto_name; - const gchar* table_ui_name; - guint8 curr_layer_num; + const char* proto_name; + const char* table_ui_name; + uint8_t curr_layer_num; } packet_proto_data_t; class DecodeAsDelegate : public QStyledItemDelegate @@ -51,7 +50,7 @@ private: void cachePacketProtocols(); bool isSelectorCombo(DecodeAsItem* item) const; - static void decodeAddProtocol(const gchar *table_name, const gchar *proto_name, gpointer value, gpointer user_data); + static void decodeAddProtocol(const char *table_name, const char *proto_name, void *value, void *user_data); capture_file *cap_file_; QList packet_proto_list_; diff --git a/ui/qt/models/decode_as_model.cpp b/ui/qt/models/decode_as_model.cpp index 67e98b75..73253c30 100644 --- a/ui/qt/models/decode_as_model.cpp +++ b/ui/qt/models/decode_as_model.cpp @@ -29,7 +29,7 @@ static const char *DEFAULT_TABLE = "tcp.port"; // Arbitrary static const char *DEFAULT_UI_TABLE = "TCP port"; // Arbitrary -DecodeAsItem::DecodeAsItem(const char* table_name, gconstpointer selector) : +DecodeAsItem::DecodeAsItem(const char* table_name, const void *selector) : tableName_(DEFAULT_TABLE), tableUIName_(DEFAULT_UI_TABLE), selectorUint_(0), @@ -45,7 +45,7 @@ DecodeAsItem::DecodeAsItem(const char* table_name, gconstpointer selector) : init(table_name, selector); } -DecodeAsItem::DecodeAsItem(const decode_as_t *entry, gconstpointer selector) : +DecodeAsItem::DecodeAsItem(const decode_as_t *entry, const void *selector) : tableName_(DEFAULT_TABLE), tableUIName_(DEFAULT_UI_TABLE), selectorUint_(0), @@ -65,7 +65,7 @@ DecodeAsItem::~DecodeAsItem() { } -void DecodeAsItem::init(const char* table_name, gconstpointer selector) +void DecodeAsItem::init(const char* table_name, const void *selector) { tableName_ = table_name; tableUIName_ = get_dissector_table_ui_name(tableName_); @@ -74,7 +74,7 @@ void DecodeAsItem::init(const char* table_name, gconstpointer selector) ftenum_t selector_type = get_dissector_table_selector_type(tableName_); if (FT_IS_STRING(selector_type)) { if (selector != NULL) { - default_handle = dissector_get_default_string_handle(tableName_, (const gchar*)selector); + default_handle = dissector_get_default_string_handle(tableName_, (const char*)selector); selectorString_ = QString((const char*)selector); } } else if (FT_IS_UINT(selector_type)) { @@ -241,7 +241,7 @@ QVariant DecodeAsModel::data(const QModelIndex &index, int role) const if (FT_IS_UINT(selector_type)) { return entryString(item->tableName(), GUINT_TO_POINTER(item->selectorUint())); } else if (FT_IS_STRING(selector_type)) { - return entryString(item->tableName(), (gconstpointer)item->selectorString().toUtf8().constData()); + return entryString(item->tableName(), (const void *)item->selectorString().toUtf8().constData()); } else if (selector_type == FT_GUID) { if (item->selectorDCERPC() != NULL) { return item->selectorDCERPC()->ctx_id; @@ -410,12 +410,12 @@ bool DecodeAsModel::insertRows(int row, int count, const QModelIndex &/*parent*/ // the fields for the tables not being present at all. wmem_list_frame_t * protos = wmem_list_tail(cap_file_->edt->pi.layers); - gint8 curr_layer_num_saved = cap_file_->edt->pi.curr_layer_num; - guint8 curr_layer_num = wmem_list_count(cap_file_->edt->pi.layers); + int8_t curr_layer_num_saved = cap_file_->edt->pi.curr_layer_num; + uint8_t curr_layer_num = wmem_list_count(cap_file_->edt->pi.layers); while (protos != NULL && item == nullptr) { int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos)); - const gchar * proto_name = proto_get_protocol_filter_name(proto_id); + const char * proto_name = proto_get_protocol_filter_name(proto_id); for (GList *cur = decode_as_list; cur; cur = cur->next) { decode_as_t *entry = (decode_as_t *) cur->data; if (g_strcmp0(proto_name, entry->name) == 0) { @@ -428,7 +428,7 @@ bool DecodeAsModel::insertRows(int row, int count, const QModelIndex &/*parent*/ // XXX: What if the Decode As table supports multiple // values, but the first possible one is 0/NULL? cap_file_->edt->pi.curr_layer_num = curr_layer_num; - gpointer selector = entry->values[0].build_values[0](&cap_file_->edt->pi); + void *selector = entry->values[0].build_values[0](&cap_file_->edt->pi); // FT_NONE tables don't need a value if (selector != NULL || selector_type == FT_NONE) { item = new DecodeAsItem(entry, selector); @@ -499,7 +499,7 @@ bool DecodeAsModel::copyRow(int dst_row, int src_row) return true; } -prefs_set_pref_e DecodeAsModel::readDecodeAsEntry(gchar *key, const gchar *value, void *private_data, gboolean) +prefs_set_pref_e DecodeAsModel::readDecodeAsEntry(char *key, const char *value, void *private_data, bool) { DecodeAsModel *model = (DecodeAsModel*)private_data; if (model == NULL) @@ -510,7 +510,7 @@ prefs_set_pref_e DecodeAsModel::readDecodeAsEntry(gchar *key, const gchar *value } /* Parse into table, selector, initial, current */ - gchar **values = g_strsplit_set(value, ",", 4); + char **values = g_strsplit_set(value, ",", 4); DecodeAsItem *item = nullptr; dissector_table_t dissector_table = find_dissector_table(values[0]); @@ -546,7 +546,7 @@ prefs_set_pref_e DecodeAsModel::readDecodeAsEntry(gchar *key, const gchar *value return PREFS_SET_OK; } -bool DecodeAsModel::copyFromProfile(QString filename, const gchar **err) +bool DecodeAsModel::copyFromProfile(QString filename, const char **err) { FILE *fp = ws_fopen(filename.toUtf8().constData(), "r"); @@ -564,7 +564,7 @@ bool DecodeAsModel::copyFromProfile(QString filename, const gchar **err) return true; } -QString DecodeAsModel::entryString(const gchar *table_name, gconstpointer value) +QString DecodeAsModel::entryString(const char *table_name, const void *value) { QString entry_str; ftenum_t selector_type = get_dissector_table_selector_type(table_name); @@ -654,7 +654,7 @@ void DecodeAsModel::setDissectorHandle(const QModelIndex &index, dissector_handl item->setDissectorHandle(dissector_handle); } -void DecodeAsModel::buildChangedList(const gchar *table_name, ftenum_t, gpointer key, gpointer value, gpointer user_data) +void DecodeAsModel::buildChangedList(const char *table_name, ftenum_t, void *key, void *value, void *user_data) { DecodeAsModel *model = (DecodeAsModel*)user_data; if (model == NULL) @@ -669,7 +669,7 @@ void DecodeAsModel::buildChangedList(const gchar *table_name, ftenum_t, gpointer model->decode_as_items_ << item; } -void DecodeAsModel::buildDceRpcChangedList(gpointer data, gpointer user_data) +void DecodeAsModel::buildDceRpcChangedList(void *data, void *user_data) { dissector_table_t sub_dissectors; guid_key guid_val; @@ -690,27 +690,36 @@ void DecodeAsModel::buildDceRpcChangedList(gpointer data, gpointer user_data) model->decode_as_items_ << item; } -typedef QPair UintPair; typedef QPair CharPtrPair; -void DecodeAsModel::gatherChangedEntries(const gchar *table_name, - ftenum_t selector_type, gpointer key, gpointer, gpointer user_data) +void DecodeAsModel::gatherChangedEntries(const char *table_name, + ftenum_t selector_type, void *key, void *value, void *user_data) { DecodeAsModel *model = qobject_cast((DecodeAsModel*)user_data); if (model == NULL) return; + dissector_handle_t current = dtbl_entry_get_handle((dtbl_entry_t *)value); + switch (selector_type) { case FT_UINT8: case FT_UINT16: case FT_UINT24: case FT_UINT32: - model->changed_uint_entries_ << UintPair(table_name, GPOINTER_TO_UINT(key)); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + model->changed_uint_entries_.emplaceBack(table_name, GPOINTER_TO_UINT(key), dissector_handle_get_pref_suffix(current)); +#else + model->changed_uint_entries_ << UIntEntry(table_name, GPOINTER_TO_UINT(key), dissector_handle_get_pref_suffix(current)); +#endif break; case FT_NONE: //need to reset dissector table, so this needs to be in a changed list, //might as well be the uint one. - model->changed_uint_entries_ << UintPair(table_name, 0); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + model->changed_uint_entries_.emplaceBack(table_name, 0, ""); +#else + model->changed_uint_entries_ << UIntEntry(table_name, 0, ""); +#endif break; case FT_STRING: @@ -741,20 +750,20 @@ void DecodeAsModel::applyChanges() // If dissector_all_tables_remove_changed existed we could call it // instead. dissector_all_tables_foreach_changed(gatherChangedEntries, this); - foreach (UintPair uint_entry, changed_uint_entries_) { + foreach (const auto &uint_entry, changed_uint_entries_) { /* Set "Decode As preferences" to default values */ - sub_dissectors = find_dissector_table(uint_entry.first); - handle = dissector_get_uint_handle(sub_dissectors, uint_entry.second); + sub_dissectors = find_dissector_table(uint_entry.table); + handle = dissector_get_uint_handle(sub_dissectors, uint_entry.key); if (handle != NULL) { module = prefs_find_module(proto_get_protocol_filter_name(dissector_handle_get_protocol_index(handle))); - pref_value = prefs_find_preference(module, uint_entry.first); + pref_value = prefs_find_preference(module, uint_entry.pref_name); if (pref_value != NULL) { module->prefs_changed_flags |= prefs_get_effect_flags(pref_value); reset_pref(pref_value); } } - dissector_reset_uint(uint_entry.first, uint_entry.second); + dissector_reset_uint(uint_entry.table, uint_entry.key); } changed_uint_entries_.clear(); foreach (CharPtrPair char_ptr_entry, changed_string_entries_) { @@ -775,7 +784,7 @@ void DecodeAsModel::applyChanges() if (!g_strcmp0(decode_as_entry->table_name, item->tableName())) { ftenum_t selector_type = get_dissector_table_selector_type(item->tableName()); - gconstpointer selector_value; + const void * selector_value; QByteArray byteArray; switch (selector_type) { @@ -791,7 +800,7 @@ void DecodeAsModel::applyChanges() case FT_STRINGZPAD: case FT_STRINGZTRUNC: byteArray = item->selectorString().toUtf8(); - selector_value = (gconstpointer) byteArray.constData(); + selector_value = (const void *) byteArray.constData(); break; case FT_NONE: //selector value is ignored, but dissector table needs to happen @@ -799,7 +808,7 @@ void DecodeAsModel::applyChanges() break; case FT_GUID: if (item->selectorDCERPC() != NULL) { - selector_value = (gconstpointer)item->selectorDCERPC(); + selector_value = (const void *)item->selectorDCERPC(); } else { //TODO: Support normal GUID dissector tables selector_value = NULL; @@ -820,7 +829,7 @@ void DecodeAsModel::applyChanges() pref_value = prefs_find_preference(module, decode_as_entry->table_name); if (pref_value != NULL) { module->prefs_changed_flags |= prefs_get_effect_flags(pref_value); - prefs_remove_decode_as_value(pref_value, item->selectorUint(), TRUE); + prefs_remove_decode_as_value(pref_value, item->selectorUint(), true); } } } @@ -833,10 +842,10 @@ void DecodeAsModel::applyChanges() if (item->dissectorHandle() != NULL) { if (FT_IS_UINT(dissector_table_get_type(sub_dissectors))) { module = prefs_find_module(proto_get_protocol_filter_name(dissector_handle_get_protocol_index(item->dissectorHandle()))); - pref_value = prefs_find_preference(module, decode_as_entry->table_name); + pref_value = prefs_find_preference(module, QByteArray(decode_as_entry->table_name).append(dissector_handle_get_pref_suffix(item->dissectorHandle()))); if (pref_value != NULL) { module->prefs_changed_flags |= prefs_get_effect_flags(pref_value); - prefs_add_decode_as_value(pref_value, item->selectorUint(), FALSE); + prefs_add_decode_as_value(pref_value, item->selectorUint(), false); } } } diff --git a/ui/qt/models/decode_as_model.h b/ui/qt/models/decode_as_model.h index cf280965..273827a8 100644 --- a/ui/qt/models/decode_as_model.h +++ b/ui/qt/models/decode_as_model.h @@ -13,7 +13,6 @@ #define DECODE_AS_MODEL_H #include -#include #include #include @@ -27,12 +26,12 @@ class DecodeAsItem { public: - DecodeAsItem(const char *table_name = NULL, gconstpointer selector = NULL); - DecodeAsItem(const decode_as_t *entry, gconstpointer selector = NULL); + DecodeAsItem(const char *table_name = NULL, const void *selector = NULL); + DecodeAsItem(const decode_as_t *entry, const void *selector = NULL); virtual ~DecodeAsItem(); - const gchar* tableName() const { return tableName_; } - const gchar* tableUIName() const { return tableUIName_; } + const char* tableName() const { return tableName_; } + const char* tableUIName() const { return tableUIName_; } uint selectorUint() const { return selectorUint_; } QString selectorString() const { return selectorString_; } decode_dcerpc_bind_values_t* selectorDCERPC() const { return selectorDCERPC_; } @@ -46,10 +45,10 @@ public: void updateHandles(); private: - void init(const char *table_name, gconstpointer selector = NULL); + void init(const char *table_name, const void *selector = NULL); - const gchar* tableName_; - const gchar* tableUIName_; + const char* tableName_; + const char* tableUIName_; //save our sanity and not have to worry about memory management //between (lack of) persistent data in GUI and underlying data @@ -70,6 +69,15 @@ public: DecodeAsModel(QObject *parent, capture_file *cf = NULL); virtual ~DecodeAsModel(); + struct UIntEntry { + QByteArray table; + uint32_t key; + QByteArray pref_name; + + UIntEntry(const char* t, uint32_t k, const char* pref_suffix) : + table(t), key(k), pref_name(t) { pref_name.append(pref_suffix); } + }; + enum DecodeAsColumn { colTable = 0, // aka "Field" (or dissector table like "TCP Port") colSelector, // the actual table value (e.g., port number 80) @@ -95,25 +103,25 @@ public: bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); void clearAll(); bool copyRow(int dst_row, int src_row); - bool copyFromProfile(QString filename, const gchar **err); + bool copyFromProfile(QString filename, const char **err); - static QString entryString(const gchar *table_name, gconstpointer value); + static QString entryString(const char *table_name, const void *value); void applyChanges(); protected: - static void buildChangedList(const gchar *table_name, ftenum_t selector_type, - gpointer key, gpointer value, gpointer user_data); - static void buildDceRpcChangedList(gpointer data, gpointer user_data); - static void gatherChangedEntries(const gchar *table_name, ftenum_t selector_type, - gpointer key, gpointer value, gpointer user_data); - static prefs_set_pref_e readDecodeAsEntry(gchar *key, const gchar *value, - void *user_data, gboolean return_range_errors); + static void buildChangedList(const char *table_name, ftenum_t selector_type, + void *key, void *value, void *user_data); + static void buildDceRpcChangedList(void *data, void *user_data); + static void gatherChangedEntries(const char *table_name, ftenum_t selector_type, + void *key, void *value, void *user_data); + static prefs_set_pref_e readDecodeAsEntry(char *key, const char *value, + void *user_data, bool); private: capture_file *cap_file_; QList decode_as_items_; - QList > changed_uint_entries_; + QList changed_uint_entries_; QList > changed_string_entries_; }; diff --git a/ui/qt/models/dissector_tables_model.cpp b/ui/qt/models/dissector_tables_model.cpp index 73c757ec..dcf3dc72 100644 --- a/ui/qt/models/dissector_tables_model.cpp +++ b/ui/qt/models/dissector_tables_model.cpp @@ -179,7 +179,7 @@ QVariant DissectorTablesModel::data(const QModelIndex &index, int role) const return QVariant(); } -static void gatherProtocolDecodes(const char *, ftenum_t selector_type, gpointer key, gpointer value, gpointer item_ptr) +static void gatherProtocolDecodes(const char *, ftenum_t selector_type, void *key, void *value, void *item_ptr) { DissectorTablesItem* pdl_ptr = (DissectorTablesItem*)item_ptr; if (pdl_ptr == NULL) @@ -225,7 +225,7 @@ struct tables_root DissectorTablesItem* string_table; }; -static void gatherTableNames(const char *short_name, const char *table_name, gpointer model_ptr) +static void gatherTableNames(const char *short_name, const char *table_name, void *model_ptr) { struct tables_root* tables = (struct tables_root*)model_ptr; if (model_ptr == NULL) @@ -262,7 +262,7 @@ static void gatherTableNames(const char *short_name, const char *table_name, gpo dissector_table_foreach(short_name, gatherProtocolDecodes, dt_ti); } -static void gatherHeurProtocolDecodes(const char *, struct heur_dtbl_entry *dtbl_entry, gpointer list_ptr) +static void gatherHeurProtocolDecodes(const char *, struct heur_dtbl_entry *dtbl_entry, void *list_ptr) { DissectorTablesItem* hdl_ptr = (DissectorTablesItem*)list_ptr; if (hdl_ptr == NULL) @@ -279,13 +279,18 @@ static void gatherHeurProtocolDecodes(const char *, struct heur_dtbl_entry *dtbl } } -static void gatherHeurTableNames(const char *table_name, heur_dissector_list *list, gpointer heur_tables) +static void gatherHeurTableNames(const char *table_name, heur_dissector_list *list, void *heur_tables) { DissectorTablesItem* table = (DissectorTablesItem*)heur_tables; if (table == NULL) return; - DissectorTablesItem *heur = new DissectorTablesItem(table_name, QString(""), table); + QString desc_name = table_name; + if (list) { + const char *desc = heur_dissector_list_get_description(list); + if (desc) desc_name = desc; + } + DissectorTablesItem *heur = new DissectorTablesItem(desc_name, table_name, table); table->prependChild(heur); if (list) { diff --git a/ui/qt/models/enabled_protocols_model.cpp b/ui/qt/models/enabled_protocols_model.cpp index ecbc47a9..d923d765 100644 --- a/ui/qt/models/enabled_protocols_model.cpp +++ b/ui/qt/models/enabled_protocols_model.cpp @@ -31,7 +31,7 @@ public: virtual ~ProtocolTreeItem() {} protected: - virtual void applyValuePrivate(gboolean value) + virtual void applyValuePrivate(bool value) { if (! proto_can_toggle_protocol(proto_get_id(proto_))) { return; @@ -56,7 +56,7 @@ public: virtual ~HeuristicTreeItem() {} protected: - virtual void applyValuePrivate(gboolean value) + virtual void applyValuePrivate(bool value) { heuristic_table_->enabled = value; } @@ -239,7 +239,6 @@ QVariant EnabledProtocolsModel::data(const QModelIndex &index, int role) const break; case DATA_PROTOCOL_TYPE: return QVariant::fromValue(item->type()); - break; default: break; } @@ -270,7 +269,7 @@ bool EnabledProtocolsModel::setData(const QModelIndex &index, const QVariant &va return true; } -static void addHeuristicItem(gpointer data, gpointer user_data) +static void addHeuristicItem(void *data, void *user_data) { heur_dtbl_entry_t* heur = (heur_dtbl_entry_t*)data; ProtocolTreeItem* protocol_item = (ProtocolTreeItem*)user_data; diff --git a/ui/qt/models/enabled_protocols_model.h b/ui/qt/models/enabled_protocols_model.h index 23b2c1bb..fe6caeab 100644 --- a/ui/qt/models/enabled_protocols_model.h +++ b/ui/qt/models/enabled_protocols_model.h @@ -43,7 +43,7 @@ public: bool applyValue(); protected: - virtual void applyValuePrivate(gboolean value) = 0; + virtual void applyValuePrivate(bool value) = 0; QString name_; QString description_; diff --git a/ui/qt/models/expert_info_model.cpp b/ui/qt/models/expert_info_model.cpp index 017dba3d..24204612 100644 --- a/ui/qt/models/expert_info_model.cpp +++ b/ui/qt/models/expert_info_model.cpp @@ -118,7 +118,7 @@ ExpertPacketItem* ExpertInfoModel::createRootItem() { static const char* rootName = "ROOT"; DIAG_OFF_CAST_AWAY_CONST - static expert_info_t root_expert = { 0, -1, -1, -1, rootName, (gchar*)rootName, NULL }; + static expert_info_t root_expert = { 0, -1, -1, -1, rootName, (char*)rootName, NULL }; DIAG_ON_CAST_AWAY_CONST return new ExpertPacketItem(root_expert, NULL, NULL); @@ -355,8 +355,8 @@ int ExpertInfoModel::columnCount(const QModelIndex&) const void ExpertInfoModel::addExpertInfo(const struct expert_info_s& expert_info) { - QString groupKey = ExpertPacketItem::groupKey(FALSE, expert_info.severity, expert_info.group, QString(expert_info.protocol), expert_info.hf_index); - QString summaryKey = ExpertPacketItem::groupKey(TRUE, expert_info.severity, expert_info.group, QString(expert_info.protocol), expert_info.hf_index); + QString groupKey = ExpertPacketItem::groupKey(false, expert_info.severity, expert_info.group, QString(expert_info.protocol), expert_info.hf_index); + QString summaryKey = ExpertPacketItem::groupKey(true, expert_info.severity, expert_info.group, QString(expert_info.protocol), expert_info.hf_index); ExpertPacketItem* expert_root = root_->child(groupKey); if (expert_root == NULL) { diff --git a/ui/qt/models/export_objects_model.cpp b/ui/qt/models/export_objects_model.cpp index 3cf9ec63..3546db5c 100644 --- a/ui/qt/models/export_objects_model.cpp +++ b/ui/qt/models/export_objects_model.cpp @@ -176,7 +176,7 @@ void ExportObjectModel::saveAllEntries(QString path) if (entry == NULL) continue; - guint count = 0; + unsigned count = 0; QString filename; do { diff --git a/ui/qt/models/fileset_entry_model.cpp b/ui/qt/models/fileset_entry_model.cpp index 8c9f504b..86979e38 100644 --- a/ui/qt/models/fileset_entry_model.cpp +++ b/ui/qt/models/fileset_entry_model.cpp @@ -121,14 +121,13 @@ void FilesetEntryModel::clear() } QString FilesetEntryModel::nameToDate(const char *name) const { + char *date; QString dn; - if (!fileset_filename_match_pattern(name)) + if (fileset_filename_match_pattern(name, NULL, NULL, &date) == FILESET_NO_MATCH) return NULL; - dn = name; - dn.remove(QRegularExpression(".*_")); - dn.truncate(14); + dn = gchar_free_to_qstring(date); dn.insert(4, '-'); dn.insert(7, '-'); dn.insert(10, ' '); diff --git a/ui/qt/models/fileset_entry_model.h b/ui/qt/models/fileset_entry_model.h index aa812b0c..40e6796f 100644 --- a/ui/qt/models/fileset_entry_model.h +++ b/ui/qt/models/fileset_entry_model.h @@ -12,8 +12,6 @@ #include -#include - #include #include diff --git a/ui/qt/models/filter_list_model.cpp b/ui/qt/models/filter_list_model.cpp index 3ed25839..c257d6af 100644 --- a/ui/qt/models/filter_list_model.cpp +++ b/ui/qt/models/filter_list_model.cpp @@ -8,8 +8,6 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -#include - #include #include @@ -23,11 +21,6 @@ #include #include -/* - * Old filter file name. - */ -#define FILTER_FILE_NAME "filters" - /* * Capture filter file name. */ @@ -38,6 +31,11 @@ */ #define DFILTER_FILE_NAME "dfilters" +/* + * Display filter macros file name. + */ +#define DMACROS_FILE_NAME "dmacros" + FilterListModel::FilterListModel(QObject * parent) : QAbstractListModel(parent), type_(FilterListModel::Display) @@ -56,12 +54,17 @@ void FilterListModel::reload() { storage.clear(); - const char * cfile = (type_ == FilterListModel::Capture) ? CFILTER_FILE_NAME : DFILTER_FILE_NAME; + const char *cfile; + + switch (type_) { + case FilterListModel::Capture: cfile = CFILTER_FILE_NAME; break; + case FilterListModel::Display: cfile = DFILTER_FILE_NAME; break; + case FilterListModel::DisplayMacro: cfile = DMACROS_FILE_NAME; break; + default: ws_assert_not_reached(); + } /* Try personal config file first */ - QString fileName = gchar_free_to_qstring(get_persconffile_path(cfile, TRUE)); - if (fileName.length() <= 0 || ! QFileInfo::exists(fileName)) - fileName = gchar_free_to_qstring(get_persconffile_path(FILTER_FILE_NAME, TRUE)); + QString fileName = gchar_free_to_qstring(get_persconffile_path(cfile, true)); if (fileName.length() <= 0 || ! QFileInfo::exists(fileName)) fileName = gchar_free_to_qstring(get_datafile_path(cfile)); if (fileName.length() <= 0 || ! QFileInfo::exists(fileName)) @@ -80,7 +83,7 @@ void FilterListModel::reload() /* Filter out lines that do not contain content: * - Starting with # is a comment * - Does not start with a quoted string - */ + */ if (data.startsWith("#") || ! data.trimmed().startsWith("\"")) continue; @@ -125,10 +128,16 @@ QVariant FilterListModel::headerData(int section, Qt::Orientation orientation, i { switch (section) { case ColumnName: - return tr("Filter Name"); + if (type_ == DisplayMacro) + return tr("Macro Name"); + else + return tr("Filter Name"); break; case ColumnExpression: - return tr("Filter Expression"); + if (type_ == DisplayMacro) + return tr("Macro Expression"); + else + return tr("Filter Expression"); break; } } @@ -230,9 +239,17 @@ void FilterListModel::removeFilter(QModelIndex idx) void FilterListModel::saveList() { - QString filename = (type_ == FilterListModel::Capture) ? CFILTER_FILE_NAME : DFILTER_FILE_NAME; + const char *cfile; + QString filename; + + switch (type_) { + case Capture: cfile = CFILTER_FILE_NAME; break; + case Display: cfile = DFILTER_FILE_NAME; break; + case DisplayMacro: cfile = DMACROS_FILE_NAME; break; + default: ws_assert_not_reached(); + } - filename = QString("%1%2%3").arg(ProfileModel::activeProfilePath()).arg("/").arg(filename); + filename = QString("%1%2%3").arg(ProfileModel::activeProfilePath()).arg("/").arg(cfile); QFile file(filename); if (! file.open(QIODevice::WriteOnly | QIODevice::Text)) diff --git a/ui/qt/models/filter_list_model.h b/ui/qt/models/filter_list_model.h index 4f528d2f..4611eeb9 100644 --- a/ui/qt/models/filter_list_model.h +++ b/ui/qt/models/filter_list_model.h @@ -25,7 +25,8 @@ class FilterListModel : public QAbstractListModel public: enum FilterListType { Display, - Capture + Capture, + DisplayMacro, }; explicit FilterListModel(FilterListType type = FilterListModel::Display, QObject * parent = Q_NULLPTR); diff --git a/ui/qt/models/info_proxy_model.cpp b/ui/qt/models/info_proxy_model.cpp index 7b256b9d..e07027c8 100644 --- a/ui/qt/models/info_proxy_model.cpp +++ b/ui/qt/models/info_proxy_model.cpp @@ -57,7 +57,6 @@ QVariant InfoProxyModel::data (const QModelIndex &index, int role) const { case Qt::DisplayRole: return infos_.at(ifIdx); - break; case Qt::FontRole: QFont font = QIdentityProxyModel::data(index, Qt::FontRole).value(); font.setItalic(true); diff --git a/ui/qt/models/interface_sort_filter_model.cpp b/ui/qt/models/interface_sort_filter_model.cpp index 9d9c5dc8..f5d62074 100644 --- a/ui/qt/models/interface_sort_filter_model.cpp +++ b/ui/qt/models/interface_sort_filter_model.cpp @@ -12,8 +12,6 @@ #include #include -#include - #include #include #include @@ -143,10 +141,7 @@ void InterfaceSortFilterModel::resetPreferenceData() } } -#if 0 - // Disabled until bug 13354 is fixed _filterHidden = ! prefs.gui_interfaces_show_hidden; -#endif #ifdef HAVE_PCAP_REMOTE _remoteDisplay = prefs.gui_interfaces_remote_display; #endif @@ -278,15 +273,18 @@ bool InterfaceSortFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex int type = -1; bool hidden = false; - if (dynamic_cast(sourceModel()) != 0) + InterfaceTreeCacheModel* cacheModel = qobject_cast(sourceModel()); + InterfaceTreeModel* treeModel = nullptr; + + if (cacheModel != nullptr) { - type = ((InterfaceTreeCacheModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_TYPE).toInt(); - hidden = ((InterfaceTreeCacheModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_HIDDEN, Qt::UserRole).toBool(); + type = cacheModel->getColumnContent(idx, IFTREE_COL_TYPE).toInt(); + hidden = cacheModel->getColumnContent(idx, IFTREE_COL_HIDDEN, Qt::UserRole).toBool(); } - else if (dynamic_cast(sourceModel()) != 0) + else if ((treeModel = qobject_cast(sourceModel())) != nullptr) { - type = ((InterfaceTreeModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_TYPE).toInt(); - hidden = ((InterfaceTreeModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_HIDDEN, Qt::UserRole).toBool(); + type = treeModel->getColumnContent(idx, IFTREE_COL_TYPE).toInt(); + hidden = treeModel->getColumnContent(idx, IFTREE_COL_HIDDEN, Qt::UserRole).toBool(); } else return false; @@ -294,24 +292,31 @@ bool InterfaceSortFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex if (hidden && _filterHidden) return false; +#ifdef HAVE_PCAP_REMOTE + bool isRemote = false; + if (cacheModel && cacheModel->isRemote(realIndex)) { + isRemote = true; + } else if (treeModel && treeModel->isRemote(idx)) { + isRemote = true; + } +#endif + if (_filterTypes && ! isInterfaceTypeShown(type)) { #ifdef HAVE_PCAP_REMOTE - /* Remote interfaces have the if type IF_WIRED, therefore would be filtered, if not explicitly checked here */ - if (type != IF_WIRED || ! ((InterfaceTreeModel *)sourceModel())->isRemote(idx)) + /* Remote interfaces have the if type IF_WIRED, therefore would be filtered if not explicitly checked here */ + if (type != IF_WIRED || !isRemote) #endif return false; } #ifdef HAVE_PCAP_REMOTE - if (((InterfaceTreeModel *)sourceModel())->isRemote(idx)) - { - if (! _remoteDisplay) + if (isRemote && !_remoteDisplay) { return false; } #endif -#endif +#endif /* HAVE_LIBPCAP */ return true; } diff --git a/ui/qt/models/interface_sort_filter_model.h b/ui/qt/models/interface_sort_filter_model.h index 5bf69d9d..e3609a81 100644 --- a/ui/qt/models/interface_sort_filter_model.h +++ b/ui/qt/models/interface_sort_filter_model.h @@ -16,8 +16,6 @@ #include -#include - #include class InterfaceSortFilterModel : public QSortFilterProxyModel diff --git a/ui/qt/models/interface_tree_cache_model.cpp b/ui/qt/models/interface_tree_cache_model.cpp index cad22b32..6c21d004 100644 --- a/ui/qt/models/interface_tree_cache_model.cpp +++ b/ui/qt/models/interface_tree_cache_model.cpp @@ -32,7 +32,7 @@ InterfaceTreeCacheModel::InterfaceTreeCacheModel(QObject *parent) : sourceModel = new InterfaceTreeModel(parent); QIdentityProxyModel::setSourceModel(sourceModel); - storage = new QMap *>(); + storage = new QMap > >(); checkableColumns << IFTREE_COL_HIDDEN << IFTREE_COL_PROMISCUOUSMODE; #ifdef HAVE_PCAP_CREATE @@ -67,8 +67,7 @@ void InterfaceTreeCacheModel::reset(int row) { if (row < 0) { - delete storage; - storage = new QMap *>(); + storage->clear(); } else { @@ -90,7 +89,7 @@ void InterfaceTreeCacheModel::saveNewDevices() interface_t *device = const_cast(&(*it)); bool useDevice = false; - QMap * dataField = storage->value(idx, 0); + QSharedPointer > dataField = storage->value(idx, 0); /* When devices are being added, they are added using generic values. So only devices * whose data have been changed should be used from here on out. */ if (dataField != 0) @@ -124,7 +123,6 @@ void InterfaceTreeCacheModel::saveNewDevices() /* All entries of this new devices have been considered */ storage->remove(idx); - delete dataField; } newDevices.clear(); @@ -159,7 +157,7 @@ void InterfaceTreeCacheModel::save() continue; /* Try to load a saved value row for this index */ - QMap * dataField = storage->value(idx, 0); + QSharedPointer > dataField = storage->value(idx, 0); /* Handle the storing of values for this device here */ if (dataField) @@ -177,7 +175,8 @@ void InterfaceTreeCacheModel::save() if (col == IFTREE_COL_HIDDEN) { - device->hidden = saveValue.toBool(); + /* Hidden is de-selection, therefore inverted logic here */ + device->hidden = (saveValue == Qt::Unchecked); } else if (device->if_info.type == IF_EXTCAP) { @@ -420,12 +419,12 @@ bool InterfaceTreeCacheModel::setData(const QModelIndex &index, const QVariant & { QVariant saveValue = value; - QMap * dataField = 0; + QSharedPointer > dataField = nullptr; /* obtain the list of already stored changes for this row. If none exist * create a new storage row for this entry */ - if ((dataField = storage->value(row, 0)) == 0) + if ((dataField = storage->value(row, 0)) == nullptr) { - dataField = new QMap(); + dataField = QSharedPointer >(new QMap); storage->insert(row, dataField); } @@ -452,8 +451,8 @@ QVariant InterfaceTreeCacheModel::data(const QModelIndex &index, int role) const if (((role == Qt::DisplayRole || role == Qt::EditRole) && editableColumns.contains(col)) || (role == Qt::CheckStateRole && checkableColumns.contains(col)) ) { - QMap * dataField = 0; - if ((dataField = storage->value(row, 0)) != 0) + QSharedPointer > dataField = nullptr; + if ((dataField = storage->value(row, 0)) != nullptr) { if (dataField->contains(col)) { @@ -492,8 +491,8 @@ QVariant InterfaceTreeCacheModel::data(const QModelIndex &index, int role) const col == IFTREE_COL_DESCRIPTION) { - QMap * dataField = 0; - if ((dataField = storage->value(row, 0)) != 0 && + QSharedPointer > dataField = nullptr; + if ((dataField = storage->value(row, 0)) != nullptr && dataField->contains(IFTREE_COL_PIPE_PATH)) { return dataField->value(IFTREE_COL_PIPE_PATH, QVariant()); @@ -525,6 +524,17 @@ QVariant InterfaceTreeCacheModel::data(const QModelIndex &index, int role) const return QVariant(); } +#ifdef HAVE_PCAP_REMOTE +bool InterfaceTreeCacheModel::isRemote(const QModelIndex &index) const +{ + const interface_t *device = lookup(index); + if (device != nullptr && device->remote_opts.src_type == CAPTURE_IFREMOTE) { + return true; + } + return false; +} +#endif + #ifdef HAVE_LIBPCAP QModelIndex InterfaceTreeCacheModel::index(int row, int column, const QModelIndex &parent) const { diff --git a/ui/qt/models/interface_tree_cache_model.h b/ui/qt/models/interface_tree_cache_model.h index 9b51c10b..1c33081d 100644 --- a/ui/qt/models/interface_tree_cache_model.h +++ b/ui/qt/models/interface_tree_cache_model.h @@ -20,6 +20,8 @@ class InterfaceTreeCacheModel : public QIdentityProxyModel { + Q_OBJECT + public: explicit InterfaceTreeCacheModel(QObject *parent); ~InterfaceTreeCacheModel(); @@ -42,6 +44,10 @@ public: void deleteDevice(const QModelIndex &index); #endif +#ifdef HAVE_PCAP_REMOTE + bool isRemote(const QModelIndex &index) const; +#endif + private: InterfaceTreeModel * sourceModel; @@ -50,7 +56,7 @@ private: void saveNewDevices(); #endif - QMap *> * storage; + QMap > > * storage; QList editableColumns; QList checkableColumns; diff --git a/ui/qt/models/interface_tree_model.cpp b/ui/qt/models/interface_tree_model.cpp index 547b9010..696937a2 100644 --- a/ui/qt/models/interface_tree_model.cpp +++ b/ui/qt/models/interface_tree_model.cpp @@ -136,7 +136,7 @@ QVariant InterfaceTreeModel::data(const QModelIndex &index, int role) const } else if (col == IFTREE_COL_DESCRIPTION) { - return QString(device->friendly_name); + return QString(device->if_info.friendly_name); } else if (col == IFTREE_COL_DISPLAY_NAME) { @@ -370,7 +370,7 @@ void InterfaceTreeModel::interfaceListChanged() QVariant InterfaceTreeModel::toolTipForInterface(int idx) const { #ifdef HAVE_LIBPCAP - if (! global_capture_opts.all_ifaces || global_capture_opts.all_ifaces->len <= (guint) idx) + if (! global_capture_opts.all_ifaces || global_capture_opts.all_ifaces->len <= (unsigned) idx) return QVariant(); interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, idx); @@ -415,6 +415,12 @@ QVariant InterfaceTreeModel::toolTipForInterface(int idx) const } #ifdef HAVE_LIBPCAP +void InterfaceTreeModel::setCache(if_stat_cache_t *stat_cache) +{ + stopStatistic(); + stat_cache_ = stat_cache; +} + void InterfaceTreeModel::stopStatistic() { if (stat_cache_) @@ -428,7 +434,7 @@ void InterfaceTreeModel::stopStatistic() void InterfaceTreeModel::updateStatistic(unsigned int idx) { #ifdef HAVE_LIBPCAP - if (! global_capture_opts.all_ifaces || global_capture_opts.all_ifaces->len <= (guint) idx) + if (! global_capture_opts.all_ifaces || global_capture_opts.all_ifaces->len <= (unsigned) idx) return; interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, idx); @@ -439,7 +445,11 @@ void InterfaceTreeModel::updateStatistic(unsigned int idx) if (!stat_cache_) { // Start gathering statistics using dumpcap - // We crash (on macOS at least) if we try to do this from ::showEvent. + // + // The stat cache will only properly configure if it has the list + // of interfaces in global_capture_opts->all_ifaces. + // We crash if we try to do this from InterfaceFrame::showEvent, + // because main.cpp calls mainw->show() before capture_opts_init(). stat_cache_ = capture_stat_start(&global_capture_opts); } @@ -530,12 +540,12 @@ bool InterfaceTreeModel::updateSelectedDevices(QItemSelection sourceSelection) { if (! device->selected) selectionHasChanged = true; - device->selected = TRUE; + device->selected = true; global_capture_opts.num_selected++; } else { if (device->selected) selectionHasChanged = true; - device->selected = FALSE; + device->selected = false; } } #else diff --git a/ui/qt/models/interface_tree_model.h b/ui/qt/models/interface_tree_model.h index cdf2ac89..747dc2e0 100644 --- a/ui/qt/models/interface_tree_model.h +++ b/ui/qt/models/interface_tree_model.h @@ -27,19 +27,28 @@ typedef QList PointList; +/* + * When sorting, QSortFilterProxyModel creates its own mapping instead + * of using the QModelIndex mapping with mapToSource to determine which + * column in the proxy model maps to which column in the source. Its own + * mapping is always done in order; this means that it's easier if all + * the Views of this model keep the columns in the same relative order, + * but can omit columns. (If you really need to change the order, + * QHeaderView::swapSections() can be used.) + */ enum InterfaceTreeColumns { - IFTREE_COL_EXTCAP, + IFTREE_COL_EXTCAP, // InterfaceFrame interfaceTree IFTREE_COL_EXTCAP_PATH, - IFTREE_COL_NAME, - IFTREE_COL_DESCRIPTION, - IFTREE_COL_DISPLAY_NAME, - IFTREE_COL_COMMENT, - IFTREE_COL_HIDDEN, + IFTREE_COL_HIDDEN, // ManageInterfaceDialog localView + IFTREE_COL_DISPLAY_NAME, // InterfaceFrame interfaceTree + IFTREE_COL_DESCRIPTION, // ManageInterfaceDialog localView + IFTREE_COL_NAME, // ManageInterfaceDialog localView + IFTREE_COL_COMMENT, // ManageInterfaceDialog localView + IFTREE_COL_STATS, // InterfaceFrame interfaceTree IFTREE_COL_DLT, IFTREE_COL_PROMISCUOUSMODE, IFTREE_COL_TYPE, - IFTREE_COL_STATS, IFTREE_COL_ACTIVE, IFTREE_COL_SNAPLEN, #ifdef CAN_SET_CAPTURE_BUFFER_SIZE @@ -49,7 +58,7 @@ enum InterfaceTreeColumns IFTREE_COL_MONITOR_MODE, #endif IFTREE_COL_CAPTURE_FILTER, - IFTREE_COL_PIPE_PATH, + IFTREE_COL_PIPE_PATH, // ManageInterfaceDialog pipeView IFTREE_COL_MAX /* is not being displayed, it is the definition for the maximum numbers of columns */ }; @@ -68,6 +77,7 @@ public: void updateStatistic(unsigned int row); #ifdef HAVE_LIBPCAP + void setCache(if_stat_cache_t *stat_cache); void stopStatistic(); #endif diff --git a/ui/qt/models/packet_list_model.cpp b/ui/qt/models/packet_list_model.cpp index 8cc00691..9bb81fb5 100644 --- a/ui/qt/models/packet_list_model.cpp +++ b/ui/qt/models/packet_list_model.cpp @@ -8,7 +8,6 @@ */ #include -#include #include #include @@ -55,7 +54,7 @@ class SortAbort : public std::runtime_error static PacketListModel * glbl_plist_model = Q_NULLPTR; static const int reserved_packets_ = 100000; -guint +unsigned packet_list_append(column_info *, frame_data *fdata) { if (!glbl_plist_model) @@ -143,7 +142,7 @@ int PacketListModel::packetNumberToRow(int packet_num) const return number_to_row_.value(packet_num) - 1; } -guint PacketListModel::recreateVisibleRows() +unsigned PacketListModel::recreateVisibleRows() { beginResetModel(); visible_rows_.resize(0); @@ -155,7 +154,7 @@ guint PacketListModel::recreateVisibleRows() if (fdata->passed_dfilter || fdata->ref_time) { visible_rows_ << record; - if (static_cast(number_to_row_.size()) <= fdata->num) { + if (static_cast(number_to_row_.size()) <= fdata->num) { number_to_row_.resize(fdata->num + 10000); } number_to_row_[fdata->num] = static_cast(visible_rows_.count()); @@ -166,7 +165,7 @@ guint PacketListModel::recreateVisibleRows() endInsertRows(); } idle_dissection_row_ = 0; - return static_cast(visible_rows_.count()); + return static_cast(visible_rows_.count()); } void PacketListModel::clear() { @@ -285,7 +284,7 @@ void PacketListModel::toggleFrameMark(const QModelIndexList &indeces) } } -void PacketListModel::setDisplayedFrameMark(gboolean set) +void PacketListModel::setDisplayedFrameMark(bool set) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) emit layoutAboutToBeChanged(); @@ -334,7 +333,7 @@ void PacketListModel::toggleFrameIgnore(const QModelIndexList &indeces) } } -void PacketListModel::setDisplayedFrameIgnore(gboolean set) +void PacketListModel::setDisplayedFrameIgnore(bool set) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) emit layoutAboutToBeChanged(); @@ -447,7 +446,7 @@ void PacketListModel::addFrameComment(const QModelIndexList &indices, const QByt } } -void PacketListModel::setFrameComment(const QModelIndex &index, const QByteArray &comment, guint c_number) +void PacketListModel::setFrameComment(const QModelIndex &index, const QByteArray &comment, unsigned c_number) { int sectionMax = columnCount() - 1; frame_data *fdata; @@ -492,10 +491,10 @@ void PacketListModel::deleteFrameComments(const QModelIndexList &indices) fdata = record->frameData(); wtap_block_t pkt_block = cf_get_packet_block(cap_file_, fdata); - guint n_comments = wtap_block_count_option(pkt_block, OPT_COMMENT); + unsigned n_comments = wtap_block_count_option(pkt_block, OPT_COMMENT); if (n_comments) { - for (guint i = 0; i < n_comments; i++) { + for (unsigned i = 0; i < n_comments; i++) { wtap_block_remove_nth_option_instance(pkt_block, OPT_COMMENT, 0); } if (!cf_set_modified_block(cap_file_, fdata, pkt_block)) { @@ -522,10 +521,10 @@ void PacketListModel::deleteAllFrameComments() foreach (PacketListRecord *record, physical_rows_) { frame_data *fdata = record->frameData(); wtap_block_t pkt_block = cf_get_packet_block(cap_file_, fdata); - guint n_comments = wtap_block_count_option(pkt_block, OPT_COMMENT); + unsigned n_comments = wtap_block_count_option(pkt_block, OPT_COMMENT); if (n_comments) { - for (guint i = 0; i < n_comments; i++) { + for (unsigned i = 0; i < n_comments; i++) { wtap_block_remove_nth_option_instance(pkt_block, OPT_COMMENT, 0); } cf_set_modified_block(cap_file_, fdata, pkt_block); @@ -557,7 +556,7 @@ int PacketListModel::sort_column_is_numeric_; int PacketListModel::text_sort_column_; Qt::SortOrder PacketListModel::sort_order_; capture_file *PacketListModel::sort_cap_file_; -gboolean PacketListModel::stop_flag_; +bool PacketListModel::stop_flag_; ProgressFrame *PacketListModel::progress_frame_; double PacketListModel::comps_; double PacketListModel::exp_comps_; @@ -579,7 +578,7 @@ void PacketListModel::sort(int column, Qt::SortOrder order) QString col_title = get_column_title(column); - if (text_sort_column_ >= 0 && (guint)visible_rows_.count() > prefs.gui_packet_list_cached_rows_max) { + if (text_sort_column_ >= 0 && (unsigned)visible_rows_.count() > prefs.gui_packet_list_cached_rows_max) { /* Column not based on frame data but by column text that requires * dissection, so to sort in a reasonable amount of time the column * text needs to be cached. @@ -614,7 +613,7 @@ void PacketListModel::sort(int column, Qt::SortOrder order) */ return; } - sort_cap_file_->read_lock = TRUE; + sort_cap_file_->read_lock = true; QString busy_msg; if (!col_title.isEmpty()) { @@ -622,7 +621,7 @@ void PacketListModel::sort(int column, Qt::SortOrder order) } else { busy_msg = tr("Sorting …"); } - stop_flag_ = FALSE; + stop_flag_ = false; comps_ = 0; /* XXX: The expected number of comparisons is O(N log N), but this could * be a pretty significant overestimate of the amount of time it takes, @@ -672,7 +671,7 @@ void PacketListModel::sort(int column, Qt::SortOrder order) disconnect(progress_frame_, &ProgressFrame::stopLoading, this, &PacketListModel::stopSorting); } - sort_cap_file_->read_lock = FALSE; + sort_cap_file_->read_lock = false; if (cap_file_->current_frame) { emit goToPacket(cap_file_->current_frame->num); @@ -681,11 +680,14 @@ void PacketListModel::sort(int column, Qt::SortOrder order) void PacketListModel::stopSorting() { - stop_flag_ = TRUE; + stop_flag_ = true; } bool PacketListModel::isNumericColumn(int column) { + /* XXX - Should this and ui/packet_list_utils.c right_justify_column() + * be the same list of columns? + */ if (column < 0) { return false; } @@ -720,10 +722,19 @@ bool PacketListModel::isNumericColumn(int column) return false; } - guint num_fields = g_slist_length(sort_cap_file_->cinfo.columns[column].col_custom_fields_ids); - for (guint i = 0; i < num_fields; i++) { - guint *field_idx = (guint *) g_slist_nth_data(sort_cap_file_->cinfo.columns[column].col_custom_fields_ids, i); - header_field_info *hfi = proto_registrar_get_nth(*field_idx); + unsigned num_fields = g_slist_length(sort_cap_file_->cinfo.columns[column].col_custom_fields_ids); + col_custom_t *col_custom; + for (unsigned i = 0; i < num_fields; i++) { + col_custom = (col_custom_t *) g_slist_nth_data(sort_cap_file_->cinfo.columns[column].col_custom_fields_ids, i); + if (col_custom->field_id == 0) { + /* XXX - We need some way to check the compiled dfilter's expected + * return type. Best would be to use the actual field values return + * and sort on those (we could skip expensive string conversions + * in the numeric case, see below) + */ + return false; + } + header_field_info *hfi = proto_registrar_get_nth(col_custom->field_id); /* * Reject a field when there is no numeric field type or when: @@ -824,7 +835,7 @@ double PacketListModel::parseNumericColumn(const QString &val, bool *ok) { QByteArray ba = val.toUtf8(); const char *strval = ba.constData(); - gchar *end = NULL; + char *end = NULL; double num = g_ascii_strtod(strval, &end); *ok = strval != end; return num; @@ -871,13 +882,10 @@ QVariant PacketListModel::data(const QModelIndex &d_index, int role) const switch(recent_get_column_xalign(d_index.column())) { case COLUMN_XALIGN_RIGHT: return Qt::AlignRight; - break; case COLUMN_XALIGN_CENTER: return Qt::AlignCenter; - break; case COLUMN_XALIGN_LEFT: return Qt::AlignLeft; - break; case COLUMN_XALIGN_DEFAULT: default: if (right_justify_column(d_index.column(), cap_file_)) { @@ -995,6 +1003,12 @@ void PacketListModel::dissectIdle(bool reset) idle_dissection_timer_->restart(); + if (!cap_file_ || cap_file_->read_lock) { + // File is in use (at worst, being rescanned). Try again later. + QTimer::singleShot(idle_dissection_interval_, this, [=]() { dissectIdle(); }); + return; + } + int first = idle_dissection_row_; while (idle_dissection_timer_->elapsed() < idle_dissection_interval_ && idle_dissection_row_ < physical_rows_.count()) { @@ -1015,7 +1029,7 @@ void PacketListModel::dissectIdle(bool reset) // XXX Pass in cinfo from packet_list_append so that we can fill in // line counts? -gint PacketListModel::appendPacket(frame_data *fdata) +int PacketListModel::appendPacket(frame_data *fdata) { PacketListRecord *record = new PacketListRecord(fdata); qsizetype pos = -1; @@ -1038,17 +1052,19 @@ gint PacketListModel::appendPacket(frame_data *fdata) pos = static_cast( visible_rows_.count() + new_visible_rows_.count() ) - 1; } - return static_cast(pos); + emit packetAppended(cap_file_, fdata, physical_rows_.size() - 1); + + return static_cast(pos); } -frame_data *PacketListModel::getRowFdata(QModelIndex idx) +frame_data *PacketListModel::getRowFdata(QModelIndex idx) const { if (!idx.isValid()) return Q_NULLPTR; return getRowFdata(idx.row()); } -frame_data *PacketListModel::getRowFdata(int row) { +frame_data *PacketListModel::getRowFdata(int row) const { if (row < 0 || row >= visible_rows_.count()) return NULL; PacketListRecord *record = visible_rows_[row]; @@ -1071,13 +1087,8 @@ void PacketListModel::ensureRowColorized(int row) int PacketListModel::visibleIndexOf(frame_data *fdata) const { - int row = 0; - foreach (PacketListRecord *record, visible_rows_) { - if (record->frameData() == fdata) { - return row; - } - row++; + if (fdata == nullptr) { + return -1; } - - return -1; + return packetNumberToRow(fdata->num); } diff --git a/ui/qt/models/packet_list_model.h b/ui/qt/models/packet_list_model.h index 807d8847..c4a4acf4 100644 --- a/ui/qt/models/packet_list_model.h +++ b/ui/qt/models/packet_list_model.h @@ -14,8 +14,6 @@ #include -#include - #include #include @@ -46,7 +44,7 @@ public: const QModelIndex & = QModelIndex()) const; QModelIndex parent(const QModelIndex &) const; int packetNumberToRow(int packet_num) const; - guint recreateVisibleRows(); + unsigned recreateVisibleRows(); void clear(); int rowCount(const QModelIndex &parent = QModelIndex()) const; @@ -54,9 +52,9 @@ public: QVariant data(const QModelIndex &d_index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - gint appendPacket(frame_data *fdata); - frame_data *getRowFdata(QModelIndex idx); - frame_data *getRowFdata(int row); + int appendPacket(frame_data *fdata); + frame_data *getRowFdata(QModelIndex idx) const; + frame_data *getRowFdata(int row) const; void ensureRowColorized(int row); int visibleIndexOf(frame_data *fdata) const; /** @@ -69,19 +67,20 @@ public: void resetColumns(); void resetColorized(); void toggleFrameMark(const QModelIndexList &indeces); - void setDisplayedFrameMark(gboolean set); + void setDisplayedFrameMark(bool set); void toggleFrameIgnore(const QModelIndexList &indeces); - void setDisplayedFrameIgnore(gboolean set); + void setDisplayedFrameIgnore(bool set); void toggleFrameRefTime(const QModelIndex &rt_index); void unsetAllFrameRefTime(); void addFrameComment(const QModelIndexList &indices, const QByteArray &comment); - void setFrameComment(const QModelIndex &index, const QByteArray &comment, guint c_number); + void setFrameComment(const QModelIndex &index, const QByteArray &comment, unsigned c_number); void deleteFrameComments(const QModelIndexList &indices); void deleteAllFrameComments(); void setMaximumRowHeight(int height); signals: + void packetAppended(capture_file *cap_file, frame_data *fdata, qsizetype row); void goToPacket(int); void maxLineCountChanged(const QModelIndex &ih_index) const; void itemHeightChanged(const QModelIndex &ih_index); @@ -113,7 +112,7 @@ private: static bool recordLessThan(PacketListRecord *r1, PacketListRecord *r2); static double parseNumericColumn(const QString &val, bool *ok); - static gboolean stop_flag_; + static bool stop_flag_; static ProgressFrame *progress_frame_; static double exp_comps_; static double comps_; diff --git a/ui/qt/models/packet_list_record.cpp b/ui/qt/models/packet_list_record.cpp index 9c2c66d1..3cba64d5 100644 --- a/ui/qt/models/packet_list_record.cpp +++ b/ui/qt/models/packet_list_record.cpp @@ -24,7 +24,7 @@ #include -QCache PacketListRecord::col_text_cache_(500); +QCache PacketListRecord::col_text_cache_(500); QMap PacketListRecord::cinfo_column_; unsigned PacketListRecord::rows_color_ver_ = 1; @@ -112,7 +112,7 @@ void PacketListRecord::dissect(capture_file *cap_file, bool dissect_columns, boo // packet_list_store.c:packet_list_dissect_and_cache_record epan_dissect_t edt; column_info *cinfo = NULL; - gboolean create_proto_tree; + bool create_proto_tree; wtap_rec rec; /* Record metadata */ Buffer buf; /* Record data */ @@ -144,7 +144,7 @@ void PacketListRecord::dissect(capture_file *cap_file, bool dissect_columns, boo * error message. */ if (dissect_columns) { - col_fill_in_error(cinfo, fdata_, FALSE, FALSE /* fill_fd_columns */); + col_fill_in_error(cinfo, fdata_, false, false /* fill_fd_columns */); cacheColumnStrings(cinfo); } @@ -175,7 +175,7 @@ void PacketListRecord::dissect(capture_file *cap_file, bool dissect_columns, boo epan_dissect_init(&edt, cap_file->epan, create_proto_tree, - FALSE /* proto_tree_visible */); + false /* proto_tree_visible */); /* Re-color when the coloring rules are changed via the UI. */ if (dissect_color) { @@ -195,7 +195,7 @@ void PacketListRecord::dissect(capture_file *cap_file, bool dissect_columns, boo if (dissect_columns) { /* "Stringify" non frame_data vals */ - epan_dissect_fill_in_columns(&edt, FALSE, FALSE /* fill_fd_columns */); + epan_dissect_fill_in_columns(&edt, false, false /* fill_fd_columns */); cacheColumnStrings(cinfo); } @@ -204,7 +204,8 @@ void PacketListRecord::dissect(capture_file *cap_file, bool dissect_columns, boo color_ver_ = rows_color_ver_; } - struct conversation * conv = find_conversation_pinfo(&edt.pi, 0); + struct conversation * conv = find_conversation_pinfo_ro(&edt.pi, 0); + conv_index_ = ! conv ? 0 : conv->conv_index; epan_dissect_cleanup(&edt); @@ -214,7 +215,7 @@ void PacketListRecord::dissect(capture_file *cap_file, bool dissect_columns, boo void PacketListRecord::cacheColumnStrings(column_info *cinfo) { - // packet_list_store.c:packet_list_change_record(PacketList *packet_list, PacketListRecord *record, gint col, column_info *cinfo) + // packet_list_store.c:packet_list_change_record(PacketList *packet_list, PacketListRecord *record, int col, column_info *cinfo) if (!cinfo) { return; } @@ -230,7 +231,7 @@ void PacketListRecord::cacheColumnStrings(column_info *cinfo) QString col_str; int text_col = cinfo_column_.value(column, -1); if (text_col < 0) { - col_fill_in_frame_data(fdata_, cinfo, column, FALSE); + col_fill_in_frame_data(fdata_, cinfo, column, false); } col_str = QString(get_column_text(cinfo, column)); diff --git a/ui/qt/models/packet_list_record.h b/ui/qt/models/packet_list_record.h index 47aa5621..7bb582fa 100644 --- a/ui/qt/models/packet_list_record.h +++ b/ui/qt/models/packet_list_record.h @@ -12,8 +12,6 @@ #include -#include - #include "cfile.h" #include @@ -60,7 +58,7 @@ public: private: /** The column text for some columns */ - static QCache col_text_cache_; + static QCache col_text_cache_; frame_data *fdata_; int lines_; diff --git a/ui/qt/models/pref_delegate.cpp b/ui/qt/models/pref_delegate.cpp index e33bb13f..313c17dc 100644 --- a/ui/qt/models/pref_delegate.cpp +++ b/ui/qt/models/pref_delegate.cpp @@ -66,7 +66,7 @@ void AdvancedPrefDelegate::setEditorData(QWidget *editor, const QModelIndex &ind return; } - Q_ASSERT(FALSE); + Q_ASSERT(false); } void AdvancedPrefDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, @@ -81,5 +81,5 @@ void AdvancedPrefDelegate::setModelData(QWidget *editor, QAbstractItemModel *mod return; } - Q_ASSERT(FALSE); + Q_ASSERT(false); } diff --git a/ui/qt/models/pref_models.cpp b/ui/qt/models/pref_models.cpp index b86230f0..3480a8db 100644 --- a/ui/qt/models/pref_models.cpp +++ b/ui/qt/models/pref_models.cpp @@ -23,10 +23,10 @@ #include // XXX Should we move this to ui/preference_utils? -static GHashTable * pref_ptr_to_pref_ = NULL; +static GHashTable * pref_ptr_to_pref_; pref_t *prefFromPrefPtr(void *pref_ptr) { - return (pref_t *)g_hash_table_lookup(pref_ptr_to_pref_, (gpointer) pref_ptr); + return (pref_t *)g_hash_table_lookup(pref_ptr_to_pref_, (void *) pref_ptr); } static void prefInsertPrefPtr(void * pref_ptr, pref_t * pref) @@ -34,8 +34,8 @@ static void prefInsertPrefPtr(void * pref_ptr, pref_t * pref) if (! pref_ptr_to_pref_) pref_ptr_to_pref_ = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); - gpointer key = (gpointer) pref_ptr; - gpointer val = (gpointer) pref; + void *key = (void *) pref_ptr; + void *val = (void *) pref; /* Already existing entries will be ignored */ if ((void *)g_hash_table_lookup(pref_ptr_to_pref_, key) == NULL) @@ -47,6 +47,7 @@ PrefsItem::PrefsItem(module_t *module, pref_t *pref, PrefsItem* parent) pref_(pref), module_(module), name_(module->name ? module->name : module->parent->name), + help_(QString()), changed_(false) { if (pref_ != NULL) { @@ -59,9 +60,19 @@ PrefsItem::PrefsItem(const QString name, PrefsItem* parent) pref_(NULL), module_(NULL), name_(name), + help_(QString()), changed_(false) { +} +PrefsItem::PrefsItem(PrefsModel::PrefsModelType type, PrefsItem* parent) + : ModelHelperTreeItem(parent), + pref_(NULL), + module_(NULL), + name_(PrefsModel::typeToString(type)), + help_(PrefsModel::typeToHelp(type)), + changed_(false) +{ } PrefsItem::~PrefsItem() @@ -113,6 +124,20 @@ QString PrefsItem::getModuleTitle() const return QString(module_->title); } +QString PrefsItem::getModuleHelp() const +{ + if (module_ == nullptr) + return help_; + + module_t *pref_module = module_; + + while (pref_module->help == nullptr && pref_module->parent) { + pref_module = pref_module->parent; + } + + return pref_module->help; +} + void PrefsItem::setChanged(bool changed) { changed_ = changed; @@ -232,8 +257,8 @@ QVariant PrefsModel::data(const QModelIndex &index, int role) const return QVariant(); } -static guint -fill_prefs(module_t *module, gpointer root_ptr) +static unsigned +fill_prefs(module_t *module, void *root_ptr) { PrefsItem* root_item = static_cast(root_ptr); @@ -275,32 +300,32 @@ fill_prefs(module_t *module, gpointer root_ptr) void PrefsModel::populate() { - prefs_modules_foreach_submodules(NULL, fill_prefs, (gpointer)root_); + prefs_modules_foreach_submodules(NULL, fill_prefs, (void *)root_); //Add the "specially handled" preferences PrefsItem *appearance_item, *appearance_subitem, *special_item; - appearance_item = new PrefsItem(typeToString(PrefsModel::Appearance), root_); + appearance_item = new PrefsItem(PrefsModel::Appearance, root_); root_->prependChild(appearance_item); - appearance_subitem = new PrefsItem(typeToString(PrefsModel::Layout), appearance_item); + appearance_subitem = new PrefsItem(PrefsModel::Layout, appearance_item); appearance_item->prependChild(appearance_subitem); - appearance_subitem = new PrefsItem(typeToString(PrefsModel::Columns), appearance_item); + appearance_subitem = new PrefsItem(PrefsModel::Columns, appearance_item); appearance_item->prependChild(appearance_subitem); - appearance_subitem = new PrefsItem(typeToString(PrefsModel::FontAndColors), appearance_item); + appearance_subitem = new PrefsItem(PrefsModel::FontAndColors, appearance_item); appearance_item->prependChild(appearance_subitem); - special_item = new PrefsItem(typeToString(PrefsModel::Capture), root_); + special_item = new PrefsItem(PrefsModel::Capture, root_); root_->prependChild(special_item); - special_item = new PrefsItem(typeToString(PrefsModel::Expert), root_); + special_item = new PrefsItem(PrefsModel::Expert, root_); root_->prependChild(special_item); - special_item = new PrefsItem(typeToString(PrefsModel::FilterButtons), root_); + special_item = new PrefsItem(PrefsModel::FilterButtons, root_); root_->prependChild(special_item); #ifdef HAVE_LIBGNUTLS - special_item = new PrefsItem(typeToString(PrefsModel::RSAKeys), root_); + special_item = new PrefsItem(PrefsModel::RSAKeys, root_); root_->prependChild(special_item); #endif - special_item = new PrefsItem(typeToString(PrefsModel::Advanced), root_); + special_item = new PrefsItem(PrefsModel::Advanced, root_); root_->prependChild(special_item); } @@ -324,6 +349,44 @@ QString PrefsModel::typeToString(int type) return typeStr; } +QString PrefsModel::typeToHelp(int type) +{ + QString helpStr; + + switch(type) + { + case Appearance: + helpStr = QString("ChCustPreferencesSection.html#_appearance"); + break; + case Columns: + helpStr = QString("ChCustPreferencesSection.html#_columns"); + break; + case FontAndColors: + helpStr = QString("ChCustPreferencesSection.html#_font_and_colors"); + break; + case Layout: + helpStr = QString("ChCustPreferencesSection.html#_layout"); + break; + case Capture: + helpStr = QString("ChCustPreferencesSection.html#_capture"); + break; + case Expert: + helpStr = QString("ChCustPreferencesSection.html#ChCustPrefsExpertSection"); + break; + case FilterButtons: + helpStr = QString("ChCustPreferencesSection.html#ChCustFilterButtons"); + break; + case RSAKeys: + helpStr = QString("ChCustPreferencesSection.html#ChCustPrefsRSASection"); + break; + case Advanced: + helpStr = QString("ChCustPreferencesSection.html#_advanced"); + break; + } + + return helpStr; +} + AdvancedPrefsModel::AdvancedPrefsModel(QObject * parent) : QSortFilterProxyModel(parent), filter_(), @@ -470,11 +533,10 @@ bool AdvancedPrefsModel::setData(const QModelIndex &dataindex, const QVariant &v item->setChanged(true); switch (item->getPrefType()) { - case PREF_DECODE_AS_UINT: case PREF_UINT: { bool ok; - guint new_val = value.toString().toUInt(&ok, prefs_get_uint_base(item->getPref())); + unsigned new_val = value.toString().toUInt(&ok, prefs_get_uint_base(item->getPref())); if (ok) prefs_set_uint_value(item->getPref(), new_val, pref_stashed); @@ -487,6 +549,7 @@ bool AdvancedPrefsModel::setData(const QModelIndex &dataindex, const QVariant &v prefs_set_enum_value(item->getPref(), value.toInt(), pref_stashed); break; case PREF_STRING: + case PREF_DISSECTOR: prefs_set_string_value(item->getPref(), value.toString().toStdString().c_str(), pref_stashed); break; case PREF_PASSWORD: @@ -543,7 +606,7 @@ Qt::ItemFlags AdvancedPrefsModel::flags(const QModelIndex &index) const Qt::ItemFlags flags = QAbstractItemModel::flags(index); if (item->getPref() == NULL) { - /* Base modules aren't changable */ + /* Base modules aren't changeable */ flags &= ~(Qt::ItemIsEnabled | Qt::ItemIsSelectable); } else { flags |= Qt::ItemIsEditable; @@ -683,6 +746,8 @@ QVariant ModulePrefsModel::data(const QModelIndex &dataindex, int role) const return sourceModel()->data(modelIndex, role); case ModuleName: return item->getModuleName(); + case ModuleHelp: + return item->getModuleHelp(); default: break; } diff --git a/ui/qt/models/pref_models.h b/ui/qt/models/pref_models.h index 775da0d0..601c7623 100644 --- a/ui/qt/models/pref_models.h +++ b/ui/qt/models/pref_models.h @@ -19,32 +19,7 @@ #include #include -class PrefsItem : public ModelHelperTreeItem -{ -public: - PrefsItem(module_t *module, pref_t *pref, PrefsItem* parent); - PrefsItem(const QString name, PrefsItem* parent); - virtual ~PrefsItem(); - - QString getName() const {return name_;} - pref_t* getPref() const {return pref_;} - int getPrefType() const; - bool isPrefDefault() const; - QString getPrefTypeName() const; - module_t* getModule() const {return module_;} - QString getModuleName() const; - QString getModuleTitle() const; - void setChanged(bool changed = true); - -private: - pref_t *pref_; - module_t *module_; - QString name_; - //set to true if changed during module manipulation - //Used to determine proper "default" for comparison - bool changed_; -}; - +class PrefsItem; class PrefsModel : public QAbstractItemModel { @@ -83,6 +58,7 @@ public: int columnCount(const QModelIndex &parent = QModelIndex()) const; static QString typeToString(int type); + static QString typeToHelp(int type); private: void populate(); @@ -90,6 +66,35 @@ private: PrefsItem* root_; }; +class PrefsItem : public ModelHelperTreeItem +{ +public: + PrefsItem(module_t *module, pref_t *pref, PrefsItem* parent); + PrefsItem(const QString name, PrefsItem* parent); + PrefsItem(PrefsModel::PrefsModelType type, PrefsItem* parent); + virtual ~PrefsItem(); + + QString getName() const {return name_;} + pref_t* getPref() const {return pref_;} + int getPrefType() const; + bool isPrefDefault() const; + QString getPrefTypeName() const; + module_t* getModule() const {return module_;} + QString getModuleName() const; + QString getModuleTitle() const; + QString getModuleHelp() const; + void setChanged(bool changed = true); + +private: + pref_t *pref_; + module_t *module_; + QString name_; + QString help_; + //set to true if changed during module manipulation + //Used to determine proper "default" for comparison + bool changed_; +}; + class AdvancedPrefsModel : public QSortFilterProxyModel { Q_OBJECT @@ -143,7 +148,8 @@ public: }; enum ModulePrefsRoles { - ModuleName = Qt::UserRole + 1 + ModuleName = Qt::UserRole + 1, + ModuleHelp = Qt::UserRole + 2 }; QVariant data(const QModelIndex &index, int role) const; diff --git a/ui/qt/models/profile_model.cpp b/ui/qt/models/profile_model.cpp index 206ef389..ecbcef6b 100644 --- a/ui/qt/models/profile_model.cpp +++ b/ui/qt/models/profile_model.cpp @@ -11,12 +11,13 @@ #include -#include "glib.h" #include "ui/profile.h" #include "ui/recent.h" -#include "wsutil/filesystem.h" #include "epan/prefs.h" +#include "wsutil/filesystem.h" +#include "wsutil/utf8_entities.h" + #include #include @@ -276,6 +277,14 @@ QVariant ProfileModel::dataDisplay(const QModelIndex &index) const return tr("Global"); else return tr("Personal"); + case COL_AUTO_SWITCH_FILTER: + { + if (prof->is_global) { + return QString(UTF8_EM_DASH); + } + return (QString(prof->auto_switch_filter)); + } + default: break; } @@ -426,7 +435,7 @@ QVariant ProfileModel::dataBackgroundRole(const QModelIndex &index) const if (prof->status != PROF_STAT_DEFAULT && ! prof->is_global) { - /* Highlights errorneous line */ + /* Highlights erroneous line */ if (checkInvalid(index) || checkIfDeleted(index) || checkDuplicate(index) || ! checkNameValidity(prof->name)) return ColorUtils::fromColorT(&prefs.gui_text_invalid); @@ -438,6 +447,23 @@ QVariant ProfileModel::dataBackgroundRole(const QModelIndex &index) const return QVariant(); } +QVariant ProfileModel::dataForegroundRole(const QModelIndex &index) const +{ + if (! index.isValid() || profiles_.count() <= index.row()) + return QVariant(); + + profile_def * prof = guard(index.row()); + if (! prof) { + return QVariant(); + } + + if (prof->is_global && index.column() == COL_AUTO_SWITCH_FILTER) { + return ColorUtils::disabledForeground(); + } + + return QVariant(); +} + QVariant ProfileModel::dataToolTipRole(const QModelIndex &idx) const { if (! idx.isValid() || profiles_.count() <= idx.row()) @@ -492,7 +518,7 @@ QVariant ProfileModel::dataPath(const QModelIndex &index) const { case PROF_STAT_DEFAULT: if (!reset_default_) - return gchar_free_to_qstring(get_persconffile_path("", FALSE)); + return gchar_free_to_qstring(get_persconffile_path("", false)); else return tr("Resetting to default"); case PROF_STAT_EXISTS: @@ -537,7 +563,7 @@ QVariant ProfileModel::dataPath(const QModelIndex &index) const QString appendix; /* A global profile is neither deleted or removed, only system provided is allowed as appendix */ - if (profile_exists(prof->reference, TRUE) && prof->from_global) + if (profile_exists(prof->reference, true) && prof->from_global) appendix = tr("system provided"); /* A default model as reference can neither be deleted or renamed, so skip if the reference was one */ else if (! index.data(ProfileModel::DATA_IS_DEFAULT).toBool()) @@ -588,6 +614,8 @@ QVariant ProfileModel::data(const QModelIndex &index, int role) const return dataFontRole(index); case Qt::BackgroundRole: return dataBackgroundRole(index); + case Qt::ForegroundRole: + return dataForegroundRole(index); case Qt::ToolTipRole: return dataToolTipRole(index); case ProfileModel::DATA_STATUS: @@ -612,10 +640,6 @@ QVariant ProfileModel::data(const QModelIndex &index, int role) const } case ProfileModel::DATA_PATH: return dataPath(index); - case ProfileModel::DATA_INDEX_VALUE_IS_URL: - if (index.column() <= ProfileModel::COL_TYPE) - return QVariant::fromValue(false); - return QVariant::fromValue(true); case ProfileModel::DATA_PATH_IS_NOT_DESCRIPTION: if (prof->status == PROF_STAT_NEW || prof->status == PROF_STAT_COPY || (prof->status == PROF_STAT_DEFAULT && reset_default_) @@ -641,6 +665,8 @@ QVariant ProfileModel::headerData(int section, Qt::Orientation orientation, int return tr("Profile"); case COL_TYPE: return tr("Type"); + case COL_AUTO_SWITCH_FILTER: + return tr("Auto Switch Filter"); default: break; } @@ -654,11 +680,18 @@ Qt::ItemFlags ProfileModel::flags(const QModelIndex &index) const Qt::ItemFlags fl = QAbstractTableModel::flags(index); profile_def * prof = guard(index); - if (! prof) + if (! prof) { return fl; + } - if (index.column() == ProfileModel::COL_NAME && prof->status != PROF_STAT_DEFAULT && ! prof->is_global) + if (prof->is_global) { + return fl; + } + + if ((index.column() == ProfileModel::COL_NAME && prof->status != PROF_STAT_DEFAULT) + || (index.column() == ProfileModel::COL_AUTO_SWITCH_FILTER)) { fl |= Qt::ItemIsEditable; + } return fl; } @@ -722,7 +755,7 @@ QModelIndex ProfileModel::addNewProfile(QString name) cnt++; } - add_to_profile_list(newName.toUtf8().constData(), newName.toUtf8().constData(), PROF_STAT_NEW, FALSE, FALSE, FALSE); + add_to_profile_list(newName.toUtf8().constData(), newName.toUtf8().constData(), PROF_STAT_NEW, false, false, false); loadProfiles(); return index(findByName(newName), COL_NAME); @@ -794,7 +827,7 @@ QModelIndex ProfileModel::duplicateEntry(QModelIndex idx, int new_status) new_status = PROF_STAT_NEW; /* add element */ - add_to_profile_list(new_name.toUtf8().constData(), parent.toUtf8().constData(), new_status, FALSE, prof->from_global ? prof->from_global : prof->is_global, FALSE); + add_to_profile_list(new_name.toUtf8().constData(), parent.toUtf8().constData(), new_status, false, prof->from_global ? prof->from_global : prof->is_global, false); /* reload profile list in model */ loadProfiles(); @@ -901,27 +934,41 @@ bool ProfileModel::setData(const QModelIndex &idx, const QVariant &value, int ro { last_set_row_ = -1; - if (role != Qt::EditRole || ! value.isValid() || value.toString().isEmpty()) + if (role != Qt::EditRole || !value.isValid()) { return false; + } + + if (idx.column() == COL_NAME && value.toString().isEmpty()) { + return false; + } QString newValue = value.toString(); profile_def * prof = guard(idx); - if (! prof || prof->status == PROF_STAT_DEFAULT) + + if (!prof) { return false; + } last_set_row_ = idx.row(); - QString current(prof->name); - if (current.compare(newValue) != 0) - { - g_free(prof->name); - prof->name = qstring_strdup(newValue); + if (idx.column() == COL_NAME && prof->status != PROF_STAT_DEFAULT) { + QString current(prof->name); + if (current.compare(newValue) != 0) + { + g_free(prof->name); + prof->name = qstring_strdup(newValue); - if (prof->reference && g_strcmp0(prof->name, prof->reference) == 0 && ! (prof->status == PROF_STAT_NEW || prof->status == PROF_STAT_COPY)) { - prof->status = PROF_STAT_EXISTS; - } else if (prof->status == PROF_STAT_EXISTS) { - prof->status = PROF_STAT_CHANGED; + if (prof->reference && g_strcmp0(prof->name, prof->reference) == 0 && ! (prof->status == PROF_STAT_NEW || prof->status == PROF_STAT_COPY)) { + prof->status = PROF_STAT_EXISTS; + } else if (prof->status == PROF_STAT_EXISTS) { + prof->status = PROF_STAT_CHANGED; + } + emit itemChanged(idx); } + } else if (idx.column() == COL_AUTO_SWITCH_FILTER) { + g_free(prof->auto_switch_filter); + prof->auto_switch_filter = qstring_strdup(newValue); + prof->prefs_changed = true; emit itemChanged(idx); } @@ -1033,7 +1080,7 @@ QFileInfoList ProfileModel::filterProfilePath(QString path, QFileInfoList ent, b return result; } -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) QStringList ProfileModel::exportFileList(QModelIndexList items) { QStringList result; @@ -1163,7 +1210,7 @@ int ProfileModel::importProfilesFromDir(QString dirname, int * skippedCnt, bool if (success) { count++; - add_to_profile_list(fentry.fileName().toUtf8().constData(), fentry.fileName().toUtf8().constData(), PROF_STAT_NEW, FALSE, FALSE, TRUE); + add_to_profile_list(fentry.fileName().toUtf8().constData(), fentry.fileName().toUtf8().constData(), PROF_STAT_NEW, false, false, true); } else if (! wasEmpty && QFile::exists(profilePath)) { diff --git a/ui/qt/models/profile_model.h b/ui/qt/models/profile_model.h index 16febd70..ff054752 100644 --- a/ui/qt/models/profile_model.h +++ b/ui/qt/models/profile_model.h @@ -11,7 +11,6 @@ #define PROFILE_MODEL_H #include "config.h" -#include "glib.h" #include @@ -59,6 +58,7 @@ public: enum { COL_NAME, COL_TYPE, + COL_AUTO_SWITCH_FILTER, _LAST_ENTRY } columns_; @@ -69,7 +69,6 @@ public: DATA_IS_SELECTED, DATA_PATH, DATA_PATH_IS_NOT_DESCRIPTION, - DATA_INDEX_VALUE_IS_URL } data_values_; // QAbstractItemModel interface @@ -101,7 +100,7 @@ public: bool userProfilesExist() const; -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) bool exportProfiles(QString filename, QModelIndexList items, QString * err = Q_NULLPTR); int importProfilesFromZip(QString filename, int *skippedCnt = Q_NULLPTR, QStringList *result = Q_NULLPTR); #endif @@ -142,7 +141,7 @@ private: int findByNameAndVisibility(QString name, bool isGlobal = false, bool searchReference = false) const; int findAsReference(QString reference) const; -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) static bool acceptFile(QString fileName, int fileSize); static QString cleanName(QString fileName); #endif @@ -150,10 +149,11 @@ private: QVariant dataDisplay(const QModelIndex & idx) const; QVariant dataFontRole(const QModelIndex & idx) const; QVariant dataBackgroundRole(const QModelIndex & idx) const; + QVariant dataForegroundRole(const QModelIndex & idx) const; QVariant dataToolTipRole(const QModelIndex & idx) const; QVariant dataPath(const QModelIndex & idx) const; -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) QStringList exportFileList(QModelIndexList items); #endif bool copyTempToProfile(QString tempPath, QString profilePath, bool *wasEmpty = Q_NULLPTR); diff --git a/ui/qt/models/proto_tree_model.cpp b/ui/qt/models/proto_tree_model.cpp index 3ededffd..fe6f7f95 100644 --- a/ui/qt/models/proto_tree_model.cpp +++ b/ui/qt/models/proto_tree_model.cpp @@ -188,7 +188,8 @@ struct find_hfid_ { ProtoNode *node; }; -bool ProtoTreeModel::foreachFindHfid(ProtoNode *node, gpointer find_hfid_ptr) +// NOLINTNEXTLINE(misc-no-recursion) +bool ProtoTreeModel::foreachFindHfid(ProtoNode *node, void *find_hfid_ptr) { struct find_hfid_ *find_hfid = (struct find_hfid_ *) find_hfid_ptr; if (PNODE_FINFO(node->protoNode()) && PNODE_FINFO(node->protoNode())->hfinfo->id == find_hfid->hfid) { @@ -196,6 +197,7 @@ bool ProtoTreeModel::foreachFindHfid(ProtoNode *node, gpointer find_hfid_ptr) return true; } for (int i = 0; i < node->childrenCount(); i++) { + // We recurse here, but we're limited by tree depth checks in epan if (foreachFindHfid(node->child(i), find_hfid)) { return true; } @@ -221,7 +223,8 @@ struct find_field_info_ { ProtoNode *node; }; -bool ProtoTreeModel::foreachFindField(ProtoNode *node, gpointer find_finfo_ptr) +// NOLINTNEXTLINE(misc-no-recursion) +bool ProtoTreeModel::foreachFindField(ProtoNode *node, void *find_finfo_ptr) { struct find_field_info_ *find_finfo = (struct find_field_info_ *) find_finfo_ptr; if (PNODE_FINFO(node->protoNode()) == find_finfo->fi) { @@ -229,6 +232,7 @@ bool ProtoTreeModel::foreachFindField(ProtoNode *node, gpointer find_finfo_ptr) return true; } for (int i = 0; i < node->childrenCount(); i++) { + // We recurse here, but we're limited by tree depth checks in epan if (foreachFindField(node->child(i), find_finfo)) { return true; } diff --git a/ui/qt/models/proto_tree_model.h b/ui/qt/models/proto_tree_model.h index df7cbba8..12d08fc0 100644 --- a/ui/qt/models/proto_tree_model.h +++ b/ui/qt/models/proto_tree_model.h @@ -41,8 +41,8 @@ public: private: ProtoNode *root_node_; - static bool foreachFindHfid(ProtoNode *node, gpointer find_hfid_ptr); - static bool foreachFindField(ProtoNode *node, gpointer find_finfo_ptr); + static bool foreachFindHfid(ProtoNode *node, void *find_hfid_ptr); + static bool foreachFindField(ProtoNode *node, void *find_finfo_ptr); }; #endif // PROTO_TREE_MODEL_H diff --git a/ui/qt/models/related_packet_delegate.cpp b/ui/qt/models/related_packet_delegate.cpp index 885160f4..bb001adc 100644 --- a/ui/qt/models/related_packet_delegate.cpp +++ b/ui/qt/models/related_packet_delegate.cpp @@ -73,7 +73,7 @@ void RelatedPacketDelegate::paint(QPainter *painter, const QStyleOptionViewItem option_vi.decorationSize.setWidth(em_w); QStyledItemDelegate::paint(painter, option_vi, index); - guint32 setup_frame = 0, last_frame = 0; + uint32_t setup_frame = 0, last_frame = 0; if (conv_) { setup_frame = (int) conv_->setup_frame; last_frame = (int) conv_->last_frame; @@ -339,7 +339,7 @@ void RelatedPacketDelegate::clear() conv_ = NULL; } -void RelatedPacketDelegate::setCurrentFrame(guint32 current_frame) +void RelatedPacketDelegate::setCurrentFrame(uint32_t current_frame) { current_frame_ = current_frame; foreach (ft_framenum_type_t framenum_type, related_frames_) { diff --git a/ui/qt/models/related_packet_delegate.h b/ui/qt/models/related_packet_delegate.h index 927129a0..68250119 100644 --- a/ui/qt/models/related_packet_delegate.h +++ b/ui/qt/models/related_packet_delegate.h @@ -26,7 +26,7 @@ class RelatedPacketDelegate : public QStyledItemDelegate public: RelatedPacketDelegate(QWidget *parent = 0); void clear(); - void setCurrentFrame(guint32 current_frame); + void setCurrentFrame(uint32_t current_frame); void setConversation(struct conversation *conv); public slots: @@ -41,7 +41,7 @@ protected: private: QHash related_frames_; struct conversation *conv_; - guint32 current_frame_; + uint32_t current_frame_; void drawArrow(QPainter *painter, const QPoint tail, const QPoint head, int head_size) const; void drawChevrons(QPainter *painter, const QPoint tail, const QPoint head, int head_size) const; diff --git a/ui/qt/models/resolved_addresses_models.cpp b/ui/qt/models/resolved_addresses_models.cpp index 48dd2f09..25557771 100644 --- a/ui/qt/models/resolved_addresses_models.cpp +++ b/ui/qt/models/resolved_addresses_models.cpp @@ -9,8 +9,6 @@ #include -#include - #include "file.h" #include "epan/addr_resolv.h" @@ -20,11 +18,11 @@ extern "C" { static void -serv_port_hash_to_qstringlist(gpointer key, gpointer value, gpointer member_ptr) +serv_port_hash_to_qstringlist(void *key, void *value, void *member_ptr) { PortsModel *model = static_cast(member_ptr); serv_port_t *serv_port = (serv_port_t *)value; - guint port = GPOINTER_TO_UINT(key); + unsigned port = GPOINTER_TO_UINT(key); if (serv_port->tcp_name) { QStringList entries; @@ -61,69 +59,73 @@ serv_port_hash_to_qstringlist(gpointer key, gpointer value, gpointer member_ptr) } static void -ipv4_hash_table_resolved_to_list(gpointer, gpointer value, gpointer sl_ptr) +ipv4_hash_table_resolved_to_list(void *, void *value, void *sl_ptr) { QList *hosts = (QList *) sl_ptr; hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *) value; - if ((ipv4_hash_table_entry->flags & NAME_RESOLVED)) { + if ((ipv4_hash_table_entry->flags & (USED_AND_RESOLVED_MASK)) == USED_AND_RESOLVED_MASK) { *hosts << (QStringList() << QString(ipv4_hash_table_entry->ip) << QString(ipv4_hash_table_entry->name)); } } static void -ipv6_hash_table_resolved_to_list(gpointer, gpointer value, gpointer sl_ptr) +ipv6_hash_table_resolved_to_list(void *, void *value, void *sl_ptr) { QList *hosts = (QList *) sl_ptr; hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *) value; - if ((ipv6_hash_table_entry->flags & NAME_RESOLVED)) { + if ((ipv6_hash_table_entry->flags & USED_AND_RESOLVED_MASK) == USED_AND_RESOLVED_MASK) { *hosts << (QStringList() << QString(ipv6_hash_table_entry->ip6) << QString(ipv6_hash_table_entry->name)); } } static void -eth_hash_to_qstringlist(gpointer, gpointer value, gpointer sl_ptr) +eth_hash_to_qstringlist(void *, void *value, void *sl_ptr) { QList *values = (QList *) sl_ptr; hashether_t* tp = (hashether_t*)value; - *values << (QStringList() << QString(get_hash_ether_hexaddr(tp)) << QString(get_hash_ether_resolved_name(tp))); + if (get_hash_ether_used(tp)) { + *values << (QStringList() << QString(get_hash_ether_hexaddr(tp)) << QString(get_hash_ether_resolved_name(tp))); + } } static void -manuf_hash_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr) +manuf_hash_to_qstringlist(void *key, void *value, void *sl_ptr) { QList *values = (QList *) sl_ptr; hashmanuf_t *manuf = (hashmanuf_t*)value; - guint eth_as_guint = GPOINTER_TO_UINT(key); + unsigned eth_as_uint = GPOINTER_TO_UINT(key); - QString entry = QString("%1:%2:%3") - .arg((eth_as_guint >> 16 & 0xff), 2, 16, QChar('0')) - .arg((eth_as_guint >> 8 & 0xff), 2, 16, QChar('0')) - .arg((eth_as_guint & 0xff), 2, 16, QChar('0')); + if (get_hash_manuf_used(manuf)) { + QString entry = QString("%1:%2:%3") + .arg((eth_as_uint >> 16 & 0xff), 2, 16, QChar('0')) + .arg((eth_as_uint >> 8 & 0xff), 2, 16, QChar('0')) + .arg((eth_as_uint & 0xff), 2, 16, QChar('0')); - *values << (QStringList() << entry << QString(get_hash_manuf_resolved_name(manuf))); + *values << (QStringList() << entry << QString(get_hash_manuf_resolved_name(manuf))); + } } static void -wka_hash_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr) +wka_hash_to_qstringlist(void *key, void *value, void *sl_ptr) { QList *values = (QList *) sl_ptr; - gchar *name = (gchar *)value; - guint8 *eth_addr = (guint8*)key; - - QString entry = QString("%1:%2:%3:%4:%5:%6") - .arg(eth_addr[0], 2, 16, QChar('0')) - .arg(eth_addr[1], 2, 16, QChar('0')) - .arg(eth_addr[2], 2, 16, QChar('0')) - .arg(eth_addr[3], 2, 16, QChar('0')) - .arg(eth_addr[4], 2, 16, QChar('0')) - .arg(eth_addr[5], 2, 16, QChar('0')); - - // We should filter on only those actually resolved, not display - // everything in wka - *values << (QStringList() << entry << QString(name)); + hashwka_t *wkahash = (hashwka_t *)value; + uint8_t *eth_addr = (uint8_t*)key; + + if (get_hash_wka_used(wkahash)) { + QString entry = QString("%1:%2:%3:%4:%5:%6") + .arg(eth_addr[0], 2, 16, QChar('0')) + .arg(eth_addr[1], 2, 16, QChar('0')) + .arg(eth_addr[2], 2, 16, QChar('0')) + .arg(eth_addr[3], 2, 16, QChar('0')) + .arg(eth_addr[4], 2, 16, QChar('0')) + .arg(eth_addr[5], 2, 16, QChar('0')); + + *values << (QStringList() << entry << QString(get_hash_wka_resolved_name(wkahash))); + } } } diff --git a/ui/qt/models/resolved_addresses_models.h b/ui/qt/models/resolved_addresses_models.h index 32ca1b15..9a26eb6d 100644 --- a/ui/qt/models/resolved_addresses_models.h +++ b/ui/qt/models/resolved_addresses_models.h @@ -30,6 +30,13 @@ protected: }; +enum PortsModelColumns +{ + PORTS_COL_NAME, + PORTS_COL_PORT, + PORTS_COL_PROTOCOL +}; + class PortsModel : public AStringListListModel { Q_OBJECT diff --git a/ui/qt/models/sparkline_delegate.cpp b/ui/qt/models/sparkline_delegate.cpp index 457c8295..121d8226 100644 --- a/ui/qt/models/sparkline_delegate.cpp +++ b/ui/qt/models/sparkline_delegate.cpp @@ -20,7 +20,7 @@ void SparkLineDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opt QList points = qvariant_cast >(index.data(Qt::UserRole)); int max = 1; // We typically draw a sparkline alongside some text. Size our - // drawing area based on an Em width. and a bit of eyballing on + // drawing area based on an Em width. and a bit of eyeballing on // Linux, macOS, and Windows. int em_w = option.fontMetrics.height(); int content_w = option.rect.width() - (em_w / 4); diff --git a/ui/qt/models/uat_delegate.h b/ui/qt/models/uat_delegate.h index e57e533d..f9cfa92d 100644 --- a/ui/qt/models/uat_delegate.h +++ b/ui/qt/models/uat_delegate.h @@ -15,7 +15,6 @@ #define UAT_DELEGATE_H #include -#include #include #include diff --git a/ui/qt/models/uat_model.cpp b/ui/qt/models/uat_model.cpp index a841ca8c..24b4423c 100644 --- a/ui/qt/models/uat_model.cpp +++ b/ui/qt/models/uat_model.cpp @@ -12,12 +12,23 @@ #include "uat_model.h" #include +#include +#include #include #include +// XXX - The model accesses the uat_t raw data, but if the raw data +// is changed outside the model, e.g. by another model on the same UAT +// or by changing configuration profiles, record_errors and dirty_records +// don't have the proper length, which leads to accessing an illegal list +// index. The preference dialog and configuration profile dialogs are modal, +// which reduces the chance of this, but the I/O Graphs using a UAT invites +// issues. + UatModel::UatModel(QObject *parent, epan_uat *uat) : QAbstractTableModel(parent), - uat_(0) + uat_(0), + applying_(false) { loadUat(uat); } @@ -46,7 +57,14 @@ void UatModel::loadUat(epan_uat * uat) void UatModel::reloadUat() { + // Avoid unnecessarily resetting the model if we're just making + // what's on disk match what we have. + if (applying_) + return; + beginResetModel(); + record_errors.clear(); + dirty_records.clear(); loadUat(uat_); endResetModel(); } @@ -54,16 +72,22 @@ void UatModel::reloadUat() bool UatModel::applyChanges(QString &error) { if (uat_->changed) { - gchar *err = NULL; + char *err = NULL; if (!uat_save(uat_, &err)) { error = QString("Error while saving %1: %2").arg(uat_->name).arg(err); g_free(err); } + applying_ = true; + // XXX - Why does this need to call post_update_cb? post_update_cb + // is for when the uat_t is updated, e.g. after loading a file. + // Saving makes the information on disk match the table records in + // memory, but it shouldn't change the uat_t. if (uat_->post_update_cb) { uat_->post_update_cb(); } + applying_ = false; return true; } @@ -76,7 +100,7 @@ bool UatModel::revertChanges(QString &error) // to avoid calling post_update_cb. Calling uat_clear + uat_load is a lazy // option and might fail (e.g. when the UAT file is removed). if (uat_->changed) { - gchar *err = NULL; + char *err = NULL; uat_clear(uat_); if (!uat_load(uat_, NULL, &err)) { error = QString("Error while loading %1: %2").arg(uat_->name).arg(err); @@ -90,17 +114,19 @@ bool UatModel::revertChanges(QString &error) Qt::ItemFlags UatModel::flags(const QModelIndex &index) const { + Qt::ItemFlags flags = QAbstractTableModel::flags(index); + flags |= Qt::ItemIsDropEnabled; + if (!index.isValid()) - return Qt::ItemFlags(); + return flags; uat_field_t *field = &uat_->fields[index.column()]; - Qt::ItemFlags flags = QAbstractTableModel::flags(index); if (field->mode == PT_TXTMOD_BOOL) { flags |= Qt::ItemIsUserCheckable; } - flags |= Qt::ItemIsEditable; + flags |= Qt::ItemIsEditable | Qt::ItemIsDragEnabled; return flags; } @@ -114,13 +140,13 @@ QVariant UatModel::data(const QModelIndex &index, int role) const uat_field_t *field = &uat_->fields[index.column()]; if (role == Qt::DisplayRole || role == Qt::EditRole) { char *str = NULL; - guint length = 0; + unsigned length = 0; field->cb.tostr(rec, &str, &length, field->cbdata.tostr, field->fld_data); switch (field->mode) { case PT_TXTMOD_HEXBYTES: { - char* temp_str = bytes_to_str(NULL, (const guint8 *) str, length); + char* temp_str = bytes_to_str(NULL, (const uint8_t *) str, length); g_free(str); QString qstr(temp_str); wmem_free(NULL, temp_str); @@ -128,24 +154,24 @@ QVariant UatModel::data(const QModelIndex &index, int role) const } case PT_TXTMOD_BOOL: case PT_TXTMOD_COLOR: + g_free(str); return QVariant(); default: - { - QString qstr(str); - g_free(str); - return qstr; - } + return gchar_free_to_qstring(str); } } if ((role == Qt::CheckStateRole) && (field->mode == PT_TXTMOD_BOOL)) { char *str = NULL; - guint length = 0; + unsigned length = 0; enum Qt::CheckState state = Qt::Unchecked; field->cb.tostr(rec, &str, &length, field->cbdata.tostr, field->fld_data); - if ((g_strcmp0(str, "TRUE") == 0) || - (g_strcmp0(str, "Enabled") == 0)) + // "Enabled" is for backwards compatibility with pre-UAT IO Graphs: + // (Commit 5b3e3ee58748ac1fd9201d2d3facbed1b9b1e800) + if (str && + ((g_ascii_strcasecmp(str, "true") == 0) || + (g_strcmp0(str, "Enabled") == 0))) state = Qt::Checked; g_free(str); @@ -166,12 +192,21 @@ QVariant UatModel::data(const QModelIndex &index, int role) const return QVariant(); } + if (role == Qt::FontRole) { + if (!g_array_index(uat_->valid_data, bool, index.row())) { + QFont font; + font.setItalic(!font.italic()); + return font; + } + return QVariant(); + } + if ((role == Qt::DecorationRole) && (field->mode == PT_TXTMOD_COLOR)) { char *str = NULL; - guint length = 0; + unsigned length = 0; field->cb.tostr(rec, &str, &length, field->cbdata.tostr, field->fld_data); - return QColor(QString(str)); + return QColor(gchar_free_to_qstring(str)); } // expose error message if any. @@ -259,9 +294,9 @@ QModelIndex UatModel::appendEntry(QVariantList rowData) data = rowData[col].toString(); } else { if (rowData[col].toInt() == Qt::Checked) { - data = QString("TRUE"); + data = QString("true"); } else { - data = QString("FALSE"); + data = QString("false"); } } } @@ -281,7 +316,7 @@ QModelIndex UatModel::appendEntry(QVariantList rowData) // postponed until the row (in the view) is not selected anymore checkRow(row); dirty_records.insert(row, true); - uat_->changed = TRUE; + uat_->changed = true; emit endInsertRows(); @@ -316,9 +351,9 @@ bool UatModel::setData(const QModelIndex &index, const QVariant &value, int role field->cb.set(rec, bytes.constData(), (unsigned) bytes.size(), field->cbdata.set, field->fld_data); } else { if (value.toInt() == Qt::Checked) { - field->cb.set(rec, "TRUE", 4, field->cbdata.set, field->fld_data); + field->cb.set(rec, "true", 4, field->cbdata.set, field->fld_data); } else { - field->cb.set(rec, "FALSE", 5, field->cbdata.set, field->fld_data); + field->cb.set(rec, "false", 5, field->cbdata.set, field->fld_data); } } @@ -348,7 +383,7 @@ bool UatModel::setData(const QModelIndex &index, const QVariant &value, int role } uat_update_record(uat_, rec, record_errors[row].isEmpty()); dirty_records[row] = true; - uat_->changed = TRUE; + uat_->changed = true; if (updated_cols.size() > updated_cols.count(index.column())) { // The validation status for other columns were also affected by @@ -388,21 +423,24 @@ bool UatModel::insertRows(int row, int count, const QModelIndex &/*parent*/) // postponed until the row (in the view) is not selected anymore checkRow(row); dirty_records.insert(row, true); - uat_->changed = TRUE; + uat_->changed = true; endInsertRows(); return true; } bool UatModel::removeRows(int row, int count, const QModelIndex &/*parent*/) { - if (count != 1 || row < 0 || row >= rowCount()) + if (row < 0 || count < 0 || row + count > rowCount()) return false; - beginRemoveRows(QModelIndex(), row, row); - uat_remove_record_idx(uat_, row); - record_errors.removeAt(row); - dirty_records.removeAt(row); - uat_->changed = TRUE; + if (count == 0) + return true; + + beginRemoveRows(QModelIndex(), row, row + count - 1); + uat_remove_record_range(uat_, row, count); + record_errors.remove(row, count); + dirty_records.remove(row, count); + uat_->changed = true; endRemoveRows(); return true; } @@ -416,7 +454,7 @@ void UatModel::clearAll() uat_clear(uat_); record_errors.clear(); dirty_records.clear(); - uat_->changed = TRUE; + uat_->changed = true; endResetModel(); } @@ -448,7 +486,7 @@ QModelIndex UatModel::copyRow(QModelIndex original) checkRow(newRow); dirty_records.insert(newRow, true); - // the UAT record has been created, now it is filled with the infromation + // the UAT record has been created, now it is filled with the information const void *src_record = UAT_INDEX_PTR(uat_, original.row()); void *dst_record = UAT_INDEX_PTR(uat_, newRow); // insertRows always initializes the record with empty value. Before copying @@ -462,35 +500,67 @@ QModelIndex UatModel::copyRow(QModelIndex original) /* According to documentation of uat_copy_cb_t memcpy should be used if uat_->copy_cb is NULL */ memcpy(dst_record, src_record, uat_->record_size); } - gboolean src_valid = g_array_index(uat_->valid_data, gboolean, original.row()); + bool src_valid = g_array_index(uat_->valid_data, bool, original.row()); uat_update_record(uat_, dst_record, src_valid); record_errors[newRow] = record_errors[original.row()]; dirty_records[newRow] = true; - uat_->changed = TRUE; + uat_->changed = true; endInsertRows(); return index(newRow, 0, QModelIndex()); } -bool UatModel::moveRow(int src_row, int dst_row) +bool UatModel::moveRowPrivate(int src_row, int dst_row) { - if (src_row < 0 || src_row >= rowCount() || dst_row < 0 || dst_row >= rowCount()) - return false; - - int dst = src_row < dst_row ? dst_row + 1 : dst_row; + if (src_row == dst_row) + return true; - beginMoveRows(QModelIndex(), src_row, src_row, QModelIndex(), dst); uat_move_index(uat_, src_row, dst_row); record_errors.move(src_row, dst_row); dirty_records.move(src_row, dst_row); - uat_->changed = TRUE; - endMoveRows(); + uat_->changed = true; return true; } +bool UatModel::moveRow(int src_row, int dst_row) +{ + return moveRows(QModelIndex(), src_row, 1, QModelIndex(), dst_row); +} + +bool UatModel::moveRows(const QModelIndex &, int sourceRow, int count, const QModelIndex &, int destinationChild) +{ + if (sourceRow < 0 || sourceRow >= rowCount() || destinationChild < 0 || destinationChild >= rowCount() || count < 0) + return false; + + if (count == 0) + return true; + + // beginMoveRows checks this + if (sourceRow <= destinationChild && destinationChild <= sourceRow + count - 1) + return false; + + if (destinationChild < sourceRow) { + if (!beginMoveRows(QModelIndex(), sourceRow, sourceRow + count - 1, QModelIndex(), destinationChild)) { + return false; + } + for (int i = 0; i < count; i++) { + moveRowPrivate(sourceRow + i, destinationChild + i); + } + } else { + if (!beginMoveRows(QModelIndex(), sourceRow, sourceRow + count - 1, QModelIndex(), destinationChild + 1)) { + return false; + } + for (int i = 0; i < count; i++) { + moveRowPrivate(sourceRow, destinationChild); + } + } + endMoveRows(); + return true; +} + bool UatModel::hasErrors() const { for (int i = 0; i < rowCount(); i++) { @@ -513,7 +583,7 @@ bool UatModel::checkField(int row, int col, char **error) const } char *str = NULL; - guint length; + unsigned length; field->cb.tostr(rec, &str, &length, field->cbdata.tostr, field->fld_data); bool ok = field->cb.chk(rec, str, length, field->cbdata.chk, field->fld_data, error); @@ -543,3 +613,20 @@ QList UatModel::checkRow(int row) } return changed; } + +Qt::DropActions UatModel::supportedDropActions() const +{ + return Qt::MoveAction; +} + +bool UatModel::dropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex &) +{ + // We could implement MimeData using uat_fld_tostr (or a new function + // that just gives the entire string) although it would be nice for + // uat_load_str to be able to load at a specified index, or else have + // a function to produce a UAT record from a string. Or we could use + // something else. However, for now we really just want internal moves. + // Supporting drop actions and rejecting drops still allows our row + // moving view's InternalMove to work. + return false; +} diff --git a/ui/qt/models/uat_model.h b/ui/qt/models/uat_model.h index 5da647a5..a24c938a 100644 --- a/ui/qt/models/uat_model.h +++ b/ui/qt/models/uat_model.h @@ -15,7 +15,6 @@ #define UAT_MODEL_H #include -#include #include #include @@ -24,6 +23,7 @@ class UatModel : public QAbstractTableModel { + Q_OBJECT public: UatModel(QObject *parent, uat_t *uat = 0); UatModel(QObject *parent, QString tableName); @@ -43,9 +43,13 @@ public: QModelIndex appendEntry(QVariantList row); QModelIndex copyRow(QModelIndex original); + bool moveRow(int src_row, int dst_row); + bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild); - bool moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild); + //Drag & drop functionality + Qt::DropActions supportedDropActions() const; + bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); void reloadUat(); bool hasErrors() const; @@ -74,9 +78,11 @@ private: bool checkField(int row, int col, char **error) const; QList checkRow(int row); void loadUat(uat_t * uat = 0); + bool moveRowPrivate(int src_row, int dst_row); epan_uat *uat_; - QList dirty_records; - QList > record_errors; + bool applying_; + QVector dirty_records; + QVector > record_errors; }; #endif // UAT_MODEL_H diff --git a/ui/qt/models/voip_calls_info_model.cpp b/ui/qt/models/voip_calls_info_model.cpp index 23ba46f1..2f6d4f18 100644 --- a/ui/qt/models/voip_calls_info_model.cpp +++ b/ui/qt/models/voip_calls_info_model.cpp @@ -58,7 +58,7 @@ QVariant VoipCallsInfoModel::data(const QModelIndex &index, int role) const call_info->protocol_name : voip_protocol_name[call_info->protocol]; case Duration: { - guint callDuration = nstime_to_sec(&(call_info->stop_fd->abs_ts)) - nstime_to_sec(&(call_info->start_fd->abs_ts)); + unsigned callDuration = nstime_to_sec(&(call_info->stop_fd->abs_ts)) - nstime_to_sec(&(call_info->start_fd->abs_ts)); return QString("%1:%2:%3").arg(callDuration / 3600, 2, 10, QChar('0')).arg((callDuration % 3600) / 60, 2, 10, QChar('0')).arg(callDuration % 60, 2, 10, QChar('0')); } case Packets: @@ -82,14 +82,14 @@ QVariant VoipCallsInfoModel::data(const QModelIndex &index, int role) const case VOIP_H323: { h323_calls_info_t *h323_info = (h323_calls_info_t *)call_info->prot_info; - gboolean flag = FALSE; + bool flag = false; static const QString on_str = tr("On"); static const QString off_str = tr("Off"); if (call_info->call_state == VOIP_CALL_SETUP) { flag = h323_info->is_faststart_Setup; } else { if ((h323_info->is_faststart_Setup) && (h323_info->is_faststart_Proc)) { - flag = TRUE; + flag = true; } } return tr("Tunneling: %1 Fast Start: %2") @@ -202,7 +202,7 @@ void VoipCallsInfoModel::updateCalls(GQueue *callsinfos) // Add new rows cur_call = g_queue_peek_nth_link(callsinfos, rowCount()); - guint extra = g_list_length(cur_call); + unsigned extra = g_list_length(cur_call); if (extra > 0) { beginInsertRows(QModelIndex(), rowCount(), rowCount() + extra - 1); while (cur_call && cur_call->data) { diff --git a/ui/qt/models/voip_calls_info_model.h b/ui/qt/models/voip_calls_info_model.h index 2f8d4007..afb7ebe3 100644 --- a/ui/qt/models/voip_calls_info_model.h +++ b/ui/qt/models/voip_calls_info_model.h @@ -11,7 +11,6 @@ #define VOIP_CALLS_INFO_MODEL_H #include -#include #include "ui/voip_calls.h" #include diff --git a/ui/qt/module_preferences_scroll_area.cpp b/ui/qt/module_preferences_scroll_area.cpp index 56503e0a..d6f4718d 100644 --- a/ui/qt/module_preferences_scroll_area.cpp +++ b/ui/qt/module_preferences_scroll_area.cpp @@ -10,6 +10,7 @@ #include "module_preferences_scroll_area.h" #include #include +#include #include "ui/qt/widgets/wireshark_file_dialog.h" #include #include "uat_dialog.h" @@ -56,8 +57,8 @@ extern "C" { // Callbacks prefs routines /* Add a single preference to the QVBoxLayout of a preference page */ -static guint -pref_show(pref_t *pref, gpointer user_data) +static unsigned +pref_show(pref_t *pref, void *user_data) { prefSearchData * data = static_cast(user_data); @@ -73,7 +74,6 @@ pref_show(pref_t *pref, gpointer user_data) switch (prefs_get_type(pref)) { case PREF_UINT: - case PREF_DECODE_AS_UINT: { QHBoxLayout *hb = new QHBoxLayout(); QLabel *label = new QLabel(prefs_get_title(pref)); @@ -171,6 +171,21 @@ pref_show(pref_t *pref, gpointer user_data) vb->addLayout(hb); break; } + case PREF_DISSECTOR: + { + QHBoxLayout *hb = new QHBoxLayout(); + QLabel *label = new QLabel(prefs_get_title(pref)); + label->setToolTip(tooltip); + hb->addWidget(label); + QLineEdit *string_le = new DissectorSyntaxLineEdit(); + string_le->setToolTip(tooltip); + string_le->setProperty(pref_prop_, VariantPointer::asQVariant(pref)); + string_le->setMinimumWidth(string_le->fontMetrics().height() * 20); + hb->addWidget(string_le); + hb->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum)); + vb->addLayout(hb); + break; + } case PREF_DECODE_AS_RANGE: case PREF_RANGE: { @@ -305,7 +320,7 @@ ModulePreferencesScrollArea::ModulePreferencesScrollArea(module_t *module, QWidg /* Show the preference's description at the top of the page */ QFont font; - font.setBold(TRUE); + font.setBold(true); QLabel *label = new QLabel(module->description); label->setFont(font); ui->verticalLayout->addWidget(label); @@ -322,9 +337,6 @@ ModulePreferencesScrollArea::ModulePreferencesScrollArea(module_t *module, QWidg if (!pref) continue; switch (prefs_get_type(pref)) { - case PREF_DECODE_AS_UINT: - connect(le, &QLineEdit::textEdited, this, &ModulePreferencesScrollArea::uintLineEditTextEdited); - break; case PREF_UINT: connect(le, &QLineEdit::textEdited, this, &ModulePreferencesScrollArea::uintLineEditTextEdited); break; @@ -333,6 +345,7 @@ ModulePreferencesScrollArea::ModulePreferencesScrollArea(module_t *module, QWidg case PREF_OPEN_FILENAME: case PREF_DIRNAME: case PREF_PASSWORD: + case PREF_DISSECTOR: connect(le, &QLineEdit::textEdited, this, &ModulePreferencesScrollArea::stringLineEditTextEdited); break; case PREF_RANGE: @@ -471,11 +484,27 @@ void ModulePreferencesScrollArea::updateWidgets() } if (prefs_get_type(pref) == PREF_PROTO_TCP_SNDAMB_ENUM && !prefs_get_enum_radiobuttons(pref)) { - MainWindow* topWidget = dynamic_cast (mainApp->mainWindow()); - /* Ensure there is one unique or multiple selections. See issue 18642 */ - if (topWidget->hasSelection() || topWidget->hasUniqueSelection()) { - frame_data * fdata = topWidget->frameDataForRow((topWidget->selectedRows()).at(0)); - enum_cb->setCurrentIndex(fdata->tcp_snd_manual_analysis); + if (prefs_get_list_value(pref, pref_stashed) == NULL) { + /* We haven't added a list of frames that could have their + * analysis changed. Set the current value to whatever the + * first selected frame has for its its TCP Sequence Analysis + * override. + */ + MainWindow* topWidget = qobject_cast(mainApp->mainWindow()); + /* Ensure there is one unique or multiple selections. See issue 18642 */ + if (topWidget->hasSelection() || topWidget->hasUniqueSelection()) { + frame_data * fdata = topWidget->frameDataForRow((topWidget->selectedRows()).at(0)); + enum_cb->setCurrentIndex(enum_cb->findData(fdata->tcp_snd_manual_analysis)); + QList rows = topWidget->selectedRows(); + foreach (int row, rows) { + frame_data * fdata = topWidget->frameDataForRow(row); + prefs_add_list_value(pref, fdata, pref_stashed); + } + } + } else { + /* The initial value was already set from the selected frames, + * use the current value from when the CB was changed. */ + enum_cb->setCurrentIndex(enum_cb->findData(prefs_get_enum_value(pref, pref_current))); } } } @@ -640,20 +669,8 @@ void ModulePreferencesScrollArea::enumComboBoxCurrentIndexChanged_PROTO_TCP(int pref_t *pref = VariantPointer::asPtr(enum_cb->property(pref_prop_)); if (!pref) return; - MainWindow* topWidget = dynamic_cast (mainApp->mainWindow()); - - // method 1 : apply to one single packet - /* frame_data * fdata = topWidget->frameDataForRow((topWidget->selectedRows()).at(0)); - fdata->tcp_snd_manual_analysis = enum_cb->itemData(index).toInt();*/ - - // method 2 : we can leverage the functionality by allowing multiple selections - QList rows = topWidget->selectedRows(); - foreach (int row, rows) { - frame_data * fdata = topWidget->frameDataForRow(row); - fdata->tcp_snd_manual_analysis = enum_cb->itemData(index).toInt(); - } - + // Store the index value in the current value, not the stashed value. + // We use the stashed value to store the frame data pointers. prefs_set_enum_value(pref, enum_cb->itemData(index).toInt(), pref_current); //prefs_set_enum_value(pref, enum_cb->itemData(index).toInt(), pref_stashed); - updateWidgets(); } diff --git a/ui/qt/module_preferences_scroll_area.h b/ui/qt/module_preferences_scroll_area.h index f3da516b..8123564d 100644 --- a/ui/qt/module_preferences_scroll_area.h +++ b/ui/qt/module_preferences_scroll_area.h @@ -12,8 +12,6 @@ #include -#include - #include #include diff --git a/ui/qt/mtp3_summary_dialog.cpp b/ui/qt/mtp3_summary_dialog.cpp index e5460fd9..37fb50dc 100644 --- a/ui/qt/mtp3_summary_dialog.cpp +++ b/ui/qt/mtp3_summary_dialog.cpp @@ -16,8 +16,6 @@ #include "config.h" -#include - #include #include diff --git a/ui/qt/multicast_statistics_dialog.cpp b/ui/qt/multicast_statistics_dialog.cpp index cca74783..30801647 100644 --- a/ui/qt/multicast_statistics_dialog.cpp +++ b/ui/qt/multicast_statistics_dialog.cpp @@ -153,9 +153,9 @@ public: private: address src_addr_; - guint16 src_port_; + uint16_t src_port_; address dst_addr_; - guint16 dst_port_; + uint16_t dst_port_; unsigned num_packets_; double avg_pps_; double avg_bw_; @@ -414,7 +414,7 @@ void MulticastStatisticsDialog::updateMulticastParameters() param = burst_measurement_interval_le_->text().toUInt(&ok); if (ok && param > 0 && param <= 1000) { - mcast_stream_burstint = (guint16) param; + mcast_stream_burstint = (uint16_t) param; } param = burst_alarm_threshold_le_->text().toInt(&ok); @@ -456,7 +456,7 @@ void MulticastStatisticsDialog::fillTree() void MulticastStatisticsDialog::rescan() { - gboolean was_registered = tapinfo_->is_registered; + bool was_registered = tapinfo_->is_registered; if (!tapinfo_->is_registered) register_tap_listener_mcast_stream(tapinfo_); diff --git a/ui/qt/packet_comment_dialog.h b/ui/qt/packet_comment_dialog.h index 114e8345..e380953d 100644 --- a/ui/qt/packet_comment_dialog.h +++ b/ui/qt/packet_comment_dialog.h @@ -10,8 +10,6 @@ #ifndef PACKET_COMMENT_DIALOG_H #define PACKET_COMMENT_DIALOG_H -#include - #include "geometry_state_dialog.h" namespace Ui { diff --git a/ui/qt/packet_diagram.cpp b/ui/qt/packet_diagram.cpp index a5bbc106..4d83deb2 100644 --- a/ui/qt/packet_diagram.cpp +++ b/ui/qt/packet_diagram.cpp @@ -322,19 +322,11 @@ private: QFontMetrics fm = QFontMetrics(layout_->regularFont()); painter->setFont(layout_->regularFont()); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) int label_w = fm.horizontalAdvance(label); -#else - int label_w = fm.width(label); -#endif if (label_w > label_rect.width()) { painter->setFont(layout_->smallFont()); fm = QFontMetrics(layout_->smallFont()); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) label_w = fm.horizontalAdvance(label); -#else - label_w = fm.width(label); -#endif if (label_w > label_rect.width()) { // XXX Use parent+ItemClipsChildrenToShape or setScale instead? label = fm.elidedText(label, Qt::ElideRight, label_rect.width()); @@ -379,6 +371,8 @@ void PacketDiagram::setRootNode(proto_node *root_node) // useful in our case because it gives us a cheap way to retain our // scroll position between packets. scene()->clear(); + viewport()->update(); + selected_field_ = nullptr; y_pos_ = 0; @@ -399,7 +393,7 @@ void PacketDiagram::setRootNode(proto_node *root_node) kids.next(); // Exclude all ("Frame") and nothing - if (tl_node->finfo->start == 0 && tl_node->finfo->length == (int) tvb_captured_length(cap_file_->edt->tvb)) { + if (tl_node == root_node->first_child) { continue; } if (tl_node->finfo->length < 1) { @@ -475,6 +469,9 @@ void PacketDiagram::contextMenuEvent(QContextMenuEvent *event) action->setChecked(layout_->showFields()); connect(action, &QAction::toggled, this, &PacketDiagram::showFieldsToggled); + action = ctx_menu->addAction(tr("Refresh")); + connect(action, &QAction::triggered, this, &PacketDiagram::resetScene); + ctx_menu->addSeparator(); action = ctx_menu->addAction(tr("Save Diagram As…")); @@ -564,11 +561,7 @@ void PacketDiagram::addDiagram(proto_node *tl_node) qreal y_bottom = y_pos_ + bit_width; QGraphicsItem *tl_item = scene()->addLine(x, y_bottom, x + diag_w, y_bottom); QFontMetrics sfm = QFontMetrics(layout_->smallFont()); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) int space_w = sfm.horizontalAdvance(' '); -#else - int space_w = sfm.width(' '); -#endif #ifdef Q_OS_WIN // t_item->boundingRect() has a pixel of space on the left on my (gcc) // Windows VM. diff --git a/ui/qt/packet_dialog.cpp b/ui/qt/packet_dialog.cpp index 8bf7a3bf..8c2d0010 100644 --- a/ui/qt/packet_dialog.cpp +++ b/ui/qt/packet_dialog.cpp @@ -15,6 +15,7 @@ #include "epan/column.h" #include "epan/ftypes/ftypes.h" #include "epan/prefs.h" +#include "epan/prefs-int.h" #include "ui/preference_utils.h" #include "frame_tvbuff.h" @@ -28,6 +29,8 @@ #include #include +Q_DECLARE_METATYPE(splitter_layout_e) + // To do: // - Copy over experimental packet editing code. // - Fix ElidedText width. @@ -41,6 +44,8 @@ PacketDialog::PacketDialog(QWidget &parent, CaptureFile &cf, frame_data *fdata) ui->setupUi(this); loadGeometry(parent.width() * 4 / 5, parent.height() * 4 / 5); ui->hintLabel->setSmallText(); + ui->prefsLayout->insertSpacing(1, 20); + ui->prefsLayout->addStretch(); wtap_rec_init(&rec_); ws_buffer_init(&buf_, 1514); @@ -59,13 +64,13 @@ PacketDialog::PacketDialog(QWidget &parent, CaptureFile &cf, frame_data *fdata) } /* proto tree, visible. We need a proto tree if there are custom columns */ - epan_dissect_init(&edt_, cap_file_.capFile()->epan, TRUE, TRUE); + epan_dissect_init(&edt_, cap_file_.capFile()->epan, true, true); col_custom_prime_edt(&edt_, &(cap_file_.capFile()->cinfo)); epan_dissect_run(&edt_, cap_file_.capFile()->cd_t, &rec_, frame_tvbuff_new_buffer(&cap_file_.capFile()->provider, fdata, &buf_), fdata, &(cap_file_.capFile()->cinfo)); - epan_dissect_fill_in_columns(&edt_, TRUE, TRUE); + epan_dissect_fill_in_columns(&edt_, true, true); proto_tree_ = new ProtoTree(ui->packetSplitter, &edt_); // Do not call proto_tree_->setCaptureFile, ProtoTree only needs the @@ -76,7 +81,40 @@ PacketDialog::PacketDialog(QWidget &parent, CaptureFile &cf, frame_data *fdata) byte_view_tab_->setCaptureFile(cap_file_.capFile()); byte_view_tab_->selectedFrameChanged(QList() << 0); - ui->packetSplitter->setStretchFactor(1, 0); + // We have to load the splitter state after adding the proto tree + // and byte view. + loadSplitterState(ui->packetSplitter); + + module_t *gui_module = prefs_find_module("gui"); + if (gui_module != nullptr) { + pref_packet_dialog_layout_ = prefs_find_preference(gui_module, "packet_dialog_layout"); + if (pref_packet_dialog_layout_ != nullptr) { + for (const enum_val_t *ev = prefs_get_enumvals(pref_packet_dialog_layout_); ev && ev->description; ev++) { + ui->layoutComboBox->addItem(ev->description, QVariant(ev->value)); + } + } + } + ui->layoutComboBox->setCurrentIndex(ui->layoutComboBox->findData(QVariant(prefs.gui_packet_dialog_layout))); + Qt::Orientation pref_orientation = Qt::Vertical; + switch(prefs.gui_packet_dialog_layout) { + case(layout_vertical): + pref_orientation = Qt::Vertical; + break; + case(layout_horizontal): + pref_orientation = Qt::Horizontal; + break; + } + + if (ui->packetSplitter->orientation() != pref_orientation) { + ui->packetSplitter->setOrientation(pref_orientation); + // If the orientation is different than the restore one, + // reset the sizes to 50-50. + QList sizes = ui->packetSplitter->sizes(); + int totalsize = sizes.at(0) + sizes.at(1); + sizes[0] = totalsize / 2; + sizes[1] = totalsize / 2; + ui->packetSplitter->setSizes(sizes); + } QStringList col_parts; for (int i = 0; i < cap_file_.capFile()->cinfo.num_cols; ++i) { @@ -96,6 +134,7 @@ PacketDialog::PacketDialog(QWidget &parent, CaptureFile &cf, frame_data *fdata) byte_view_tab_->setVisible(false); } ui->chkShowByteView->setCheckState(state); + ui->layoutComboBox->setEnabled(state); connect(mainApp, SIGNAL(zoomMonospaceFont(QFont)), proto_tree_, SLOT(setMonospaceFont(QFont))); @@ -117,6 +156,11 @@ PacketDialog::PacketDialog(QWidget &parent, CaptureFile &cf, frame_data *fdata) connect(proto_tree_, SIGNAL(editProtocolPreference(preference*,pref_module*)), this, SIGNAL(editProtocolPreference(preference*,pref_module*))); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + connect(ui->layoutComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &PacketDialog::layoutChanged); +#else + connect(ui->layoutComboBox, &QComboBox::currentIndexChanged, this, &PacketDialog::layoutChanged, Qt::AutoConnection); +#endif connect(ui->chkShowByteView, &QCheckBox::stateChanged, this, &PacketDialog::viewVisibilityStateChanged); } @@ -192,7 +236,12 @@ void PacketDialog::setHintTextSelected(FieldInformation* finfo) finfo_length = finfo->position().length + finfo->appendix().length; if (finfo_length > 0) { - hint.append(", " + tr("%Ln byte(s)", "", finfo_length)); + int finfo_bits = FI_GET_BITS_SIZE(finfo->fieldInfo()); + if (finfo_bits % 8 == 0) { + hint.append(", " + tr("%Ln byte(s)", "", finfo_length)); + } else { + hint.append(", " + tr("%Ln bit(s)", "", finfo_bits)); + } } } } @@ -205,7 +254,22 @@ void PacketDialog::setHintTextSelected(FieldInformation* finfo) void PacketDialog::viewVisibilityStateChanged(int state) { byte_view_tab_->setVisible(state == Qt::Checked); + ui->layoutComboBox->setEnabled(state == Qt::Checked); - prefs.gui_packet_details_show_byteview = (state == Qt::Checked ? TRUE : FALSE); + prefs.gui_packet_details_show_byteview = (state == Qt::Checked ? true : false); prefs_main_write(); } + +void PacketDialog::layoutChanged(int index _U_) +{ + splitter_layout_e layout = ui->layoutComboBox->currentData().value(); + switch(layout) { + case(layout_vertical): + ui->packetSplitter->setOrientation(Qt::Vertical); + break; + case(layout_horizontal): + ui->packetSplitter->setOrientation(Qt::Horizontal); + break; + } + prefs_set_enum_value(pref_packet_dialog_layout_, layout, pref_current); +} diff --git a/ui/qt/packet_dialog.h b/ui/qt/packet_dialog.h index c2119b74..927784f1 100644 --- a/ui/qt/packet_dialog.h +++ b/ui/qt/packet_dialog.h @@ -43,6 +43,7 @@ signals: private slots: void on_buttonBox_helpRequested(); void viewVisibilityStateChanged(int); + void layoutChanged(int); void setHintText(FieldInformation *); void setHintTextSelected(FieldInformation*); @@ -50,6 +51,7 @@ private slots: private: Ui::PacketDialog *ui; + pref_t *pref_packet_dialog_layout_; QString col_info_; ProtoTree *proto_tree_; ByteViewTab *byte_view_tab_; diff --git a/ui/qt/packet_dialog.ui b/ui/qt/packet_dialog.ui index 0473fa12..83442828 100644 --- a/ui/qt/packet_dialog.ui +++ b/ui/qt/packet_dialog.ui @@ -35,14 +35,29 @@ - - - Show packet bytes - - - true - - + + + + + Show packet bytes + + + true + + + + + + + Layout: + + + + + + + + diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp index ae6f0f51..896c66fe 100644 --- a/ui/qt/packet_list.cpp +++ b/ui/qt/packet_list.cpp @@ -11,8 +11,6 @@ #include "config.h" -#include - #include "file.h" #include @@ -36,6 +34,7 @@ #include "ui/util.h" #include "wiretap/wtap_opttypes.h" +#include "wsutil/filesystem.h" #include "wsutil/str_util.h" #include @@ -49,6 +48,7 @@ #include "main_application.h" #include #include +#include #include #include #include @@ -93,7 +93,7 @@ // If we ever add the ability to open multiple capture files we might be // able to use something like QMap to match // capture files against packet lists and models. -static PacketList *gbl_cur_packet_list = NULL; +static PacketList *gbl_cur_packet_list; const int max_comments_to_fetch_ = 20000000; // Arbitrary const int overlay_update_interval_ = 100; // 250; // Milliseconds. @@ -102,18 +102,18 @@ const int overlay_update_interval_ = 100; // 250; // Milliseconds. /* * Given a frame_data structure, scroll to and select the row in the * packet list corresponding to that frame. If there is no such - * row, return FALSE, otherwise return TRUE. + * row, return false, otherwise return true. */ -gboolean +bool packet_list_select_row_from_data(frame_data *fdata_needle) { if (! gbl_cur_packet_list || ! gbl_cur_packet_list->model()) - return FALSE; + return false; PacketListModel * model = qobject_cast(gbl_cur_packet_list->model()); if (! model) - return FALSE; + return false; model->flushVisibleRows(); int row = -1; @@ -132,10 +132,32 @@ packet_list_select_row_from_data(frame_data *fdata_needle) gbl_cur_packet_list->selectionModel()->clearSelection(); gbl_cur_packet_list->selectionModel()->setCurrentIndex(model->index(row, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); gbl_cur_packet_list->scrollTo(gbl_cur_packet_list->currentIndex(), PacketList::PositionAtCenter); - return TRUE; + return true; } - return FALSE; + return false; +} + +/* + * Given a field_info, select the field (which will scroll to it in + * the main ProtoTree, etc.) This is kind of an odd place for it, + * but we call this when performing Find Packet in lieu of changing the + * selected frame (the function above), because we found a match in the + * same frame as the currently selected one. + */ +bool +packet_list_select_finfo(field_info *fi) +{ + if (! gbl_cur_packet_list || ! gbl_cur_packet_list->model()) + return false; + + if (fi) { + FieldInformation finfo(fi, gbl_cur_packet_list); + emit gbl_cur_packet_list->fieldSelected(&finfo); + } else { + emit gbl_cur_packet_list->fieldSelected(0); + } + return true; } void @@ -180,21 +202,21 @@ packet_list_recent_write_all(FILE *rf) { gbl_cur_packet_list->writeRecent(rf); } -gboolean +bool packet_list_multi_select_active(void) { if (gbl_cur_packet_list) { return gbl_cur_packet_list->multiSelectActive(); } - return FALSE; + return false; } #define MIN_COL_WIDTH_STR "MMMMMM" PacketList::PacketList(QWidget *parent) : QTreeView(parent), - proto_tree_(NULL), - cap_file_(NULL), + proto_tree_(nullptr), + cap_file_(nullptr), ctx_column_(-1), overlay_timer_id_(0), create_near_overlay_(true), @@ -209,7 +231,8 @@ PacketList::PacketList(QWidget *parent) : frozen_selected_rows_(QModelIndexList()), cur_history_(-1), in_history_(false), - finfo_array(NULL) + finfo_array(nullptr), + profile_switcher_(nullptr) { setItemsExpandable(false); setRootIsDecorated(false); @@ -227,9 +250,7 @@ PacketList::PacketList(QWidget *parent) : connect(packet_list_header_, &PacketListHeader::columnsChanged, this, &PacketList::columnsChanged); setHeader(packet_list_header_); -#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) header()->setFirstSectionMovable(true); -#endif setSelectionMode(QAbstractItemView::ExtendedSelection); @@ -276,10 +297,23 @@ PacketList::~PacketList() { if (finfo_array) { - g_ptr_array_free(finfo_array, TRUE); + g_ptr_array_free(finfo_array, true); } } +void PacketList::scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint hint) +{ + /* QAbstractItemView doesn't have a way to indicate "auto scroll, but + * only vertically." So just restore the horizontal scroll value whenever + * it scrolls. + */ + setUpdatesEnabled(false); + int horizVal = horizontalScrollBar()->value(); + QTreeView::scrollTo(index, hint); + horizontalScrollBar()->setValue(horizVal); + setUpdatesEnabled(true); +} + void PacketList::colorsChanged() { const QString c_active = "active"; @@ -550,7 +584,6 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS selection_history_.resize(cur_history_); selection_history_.append(cap_file_->current_frame->num); } - in_history_ = false; related_packet_delegate_.clear(); @@ -567,7 +600,7 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS if (cap_file_->edt->tree) { packet_info *pi = &cap_file_->edt->pi; related_packet_delegate_.setCurrentFrame(pi->num); - conversation_t *conv = find_conversation_pinfo(pi, 0); + conversation_t *conv = find_conversation_pinfo_ro(pi, 0); if (conv) { related_packet_delegate_.setConversation(conv); } @@ -581,9 +614,17 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS // The tree where the target string matched one of the labels was discarded in // match_protocol_tree() so we have to search again in the latest tree. fi = cf_find_string_protocol_tree(cap_file_, cap_file_->edt->tree); - } else if (cap_file_->search_pos != 0) { + } else if (cap_file_->search_len != 0) { // Find the finfo that corresponds to our byte. - fi = proto_find_field_from_offset(cap_file_->edt->tree, cap_file_->search_pos, + // The match can span multiple fields (and a single byte can + // match more than one field.) Our behavior is to find the last + // field in the tree (so hopefully spanning fewer bytes) that + // matches the last byte in the search match. + // (regex search can find a zero length match not at the + // start of the frame if lookbehind is used, but + // proto_find_field_from_offset doesn't match such a field + // and it's not clear which field we would want to match.) + fi = proto_find_field_from_offset(cap_file_->edt->tree, cap_file_->search_pos + cap_file_->search_len - 1, cap_file_->edt->tvb); } @@ -606,16 +647,16 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) if (finfo_array) { - g_ptr_array_free(finfo_array, TRUE); + g_ptr_array_free(finfo_array, true); finfo_array = NULL; } if (cap_file_ && cap_file_->edt && cap_file_->edt->tree) { finfo_array = proto_all_finfos(cap_file_->edt->tree); QList added_proto_prefs; - for (guint i = 0; i < finfo_array->len; i++) { + for (unsigned i = 0; i < finfo_array->len; i++) { field_info *fi = (field_info *)g_ptr_array_index (finfo_array, i); - header_field_info *hfinfo = fi->hfinfo; + const header_field_info *hfinfo = fi->hfinfo; if (prefs_is_registered_protocol(hfinfo->abbrev)) { if (hfinfo->parent == -1) { @@ -654,8 +695,8 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) ctx_menu->setAttribute(Qt::WA_DeleteOnClose); // XXX We might want to reimplement setParent() and fill in the context // menu there. - ctx_menu->addAction(window()->findChild("actionEditMarkPacket")); - ctx_menu->addAction(window()->findChild("actionEditIgnorePacket")); + ctx_menu->addAction(window()->findChild("actionEditMarkSelected")); + ctx_menu->addAction(window()->findChild("actionEditIgnoreSelected")); ctx_menu->addAction(window()->findChild("actionEditSetTimeReference")); ctx_menu->addAction(window()->findChild("actionEditTimeShift")); ctx_menu->addMenu(window()->findChild("menuPacketComment")); @@ -728,6 +769,7 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) main_menu_item = window()->findChild("menuEditCopy"); submenu = new QMenu(main_menu_item->title(), ctx_menu); + submenu->setToolTipsVisible(true); ctx_menu->addMenu(submenu); QAction * action = submenu->addAction(tr("Summary as Text")); @@ -749,15 +791,16 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) copyEntries->setParent(submenu); frameData->setParent(submenu); - ctx_menu->addSeparator(); - ctx_menu->addMenu(&proto_prefs_menus_); - action = ctx_menu->addAction(tr("Decode As…")); - action->setProperty("create_new", QVariant(true)); - connect(action, &QAction::triggered, this, &PacketList::ctxDecodeAsDialog); - // "Print" not ported intentionally - action = window()->findChild("actionViewShowPacketInNewWindow"); - ctx_menu->addAction(action); - + if (is_packet_configuration_namespace()) { + ctx_menu->addSeparator(); + ctx_menu->addMenu(&proto_prefs_menus_); + action = ctx_menu->addAction(tr("Decode As…")); + action->setProperty("create_new", QVariant(true)); + connect(action, &QAction::triggered, this, &PacketList::ctxDecodeAsDialog); + // "Print" not ported intentionally + action = window()->findChild("actionViewShowPacketInNewWindow"); + ctx_menu->addAction(action); + } // Set menu sensitivity for the current column and set action data. if (frameData) @@ -805,9 +848,7 @@ void PacketList::paintEvent(QPaintEvent *event) void PacketList::mousePressEvent (QMouseEvent *event) { - setAutoScroll(false); QTreeView::mousePressEvent(event); - setAutoScroll(true); QModelIndex curIndex = indexAt(event->pos()); mouse_pressed_at_ = curIndex; @@ -918,23 +959,7 @@ void PacketList::mouseMoveEvent (QMouseEvent *event) void PacketList::keyPressEvent(QKeyEvent *event) { - bool handled = false; - // If scrolling up/down, want to preserve horizontal scroll extent. - if (event->key() == Qt::Key_Down || event->key() == Qt::Key_Up || - event->key() == Qt::Key_PageDown || event->key() == Qt::Key_PageUp || - event->key() == Qt::Key_End || event->key() == Qt::Key_Home ) - { - // XXX: Why allow jumping to the left if the first column is current? - if (currentIndex().isValid() && currentIndex().column() > 0) { - int pos = horizontalScrollBar()->value(); - QTreeView::keyPressEvent(event); - horizontalScrollBar()->setValue(pos); - handled = true; - } - } - - if (!handled) - QTreeView::keyPressEvent(event); + QTreeView::keyPressEvent(event); if (event->matches(QKeySequence::Copy)) { @@ -1008,19 +1033,11 @@ void PacketList::setRecentColumnWidth(int col) const char *long_str = get_column_width_string(fmt, col); QFontMetrics fm = QFontMetrics(mainApp->monospaceFont()); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) if (long_str) { col_width = fm.horizontalAdvance(long_str); } else { col_width = fm.horizontalAdvance(MIN_COL_WIDTH_STR); } -#else - if (long_str) { - col_width = fm.width(long_str); - } else { - col_width = fm.width(MIN_COL_WIDTH_STR); - } -#endif // Custom delegate padding if (itemDelegateForColumn(col)) { QStyleOptionViewItem option; @@ -1102,6 +1119,14 @@ bool PacketList::havePreviousHistory(bool update_cur) return false; } +void PacketList::setProfileSwitcher(ProfileSwitcher *profile_switcher) +{ + profile_switcher_ = profile_switcher; + if (profile_switcher) { + connect(packet_list_model_, &PacketListModel::packetAppended, profile_switcher_, &ProfileSwitcher::checkPacket); + } +} + frame_data *PacketList::getFDataForRow(int row) const { return packet_list_model_->getRowFdata(row); @@ -1120,7 +1145,7 @@ void PacketList::columnsChanged() prefs.num_cols = g_list_length(prefs.col_list); col_cleanup(&cap_file_->cinfo); - build_column_format_array(&cap_file_->cinfo, prefs.num_cols, FALSE); + build_column_format_array(&cap_file_->cinfo, prefs.num_cols, false); create_far_overlay_ = true; resetColumns(); applyRecentColumnWidths(); @@ -1133,7 +1158,7 @@ void PacketList::fieldsChanged(capture_file *cf) { prefs.num_cols = g_list_length(prefs.col_list); col_cleanup(&cf->cinfo); - build_column_format_array(&cf->cinfo, prefs.num_cols, FALSE); + build_column_format_array(&cf->cinfo, prefs.num_cols, false); resetColumns(); } @@ -1163,9 +1188,6 @@ void PacketList::applyRecentColumnWidths() void PacketList::preferencesChanged() { - // Update color style changes - colorsChanged(); - // Related packet delegate if (prefs.gui_packet_list_show_related) { setItemDelegateForColumn(0, &related_packet_delegate_); @@ -1329,8 +1351,8 @@ void PacketList::clear() { } void PacketList::writeRecent(FILE *rf) { - gint col, width, col_fmt; - gchar xalign; + int col, width, col_fmt; + char xalign; fprintf (rf, "%s:\n", RECENT_KEY_COL_WIDTH); for (col = 0; col < prefs.num_cols; col++) { @@ -1387,7 +1409,7 @@ QString PacketList::getFilterFromRowAndColumn(QModelIndex idx) return filter; /* error reading the record */ } /* proto tree, visible. We need a proto tree if there's custom columns */ - epan_dissect_init(&edt, cap_file_->epan, have_custom_cols(&cap_file_->cinfo), FALSE); + epan_dissect_init(&edt, cap_file_->epan, have_custom_cols(&cap_file_->cinfo), false); col_custom_prime_edt(&edt, &cap_file_->cinfo); epan_dissect_run(&edt, cap_file_->cd_t, &rec, @@ -1400,14 +1422,14 @@ QString PacketList::getFilterFromRowAndColumn(QModelIndex idx) /* We don't need to fill in the custom columns, as we get their * filters above. */ - col_fill_in(&edt.pi, TRUE, TRUE); + col_fill_in(&edt.pi, true, true); if (strlen(cap_file_->cinfo.col_expr.col_expr[column]) != 0 && strlen(cap_file_->cinfo.col_expr.col_expr_val[column]) != 0) { - gboolean is_string_value = FALSE; + bool is_string_value = false; header_field_info *hfi = proto_registrar_get_byname(cap_file_->cinfo.col_expr.col_expr[column]); - if (hfi && hfi->type == FT_STRING) { + if (hfi && FT_IS_STRING(hfi->type)) { /* Could be an address type such as usb.src which must be quoted. */ - is_string_value = TRUE; + is_string_value = true; } if (filter.isEmpty()) { @@ -1438,7 +1460,7 @@ void PacketList::resetColorized() update(); } -QString PacketList::getPacketComment(guint c_number) +QString PacketList::getPacketComment(unsigned c_number) { int row = currentIndex().row(); const frame_data *fdata; @@ -1487,7 +1509,7 @@ void PacketList::addPacketComment(QString new_comment) } } -void PacketList::setPacketComment(guint c_number, QString new_comment) +void PacketList::setPacketComment(unsigned c_number, QString new_comment) { QModelIndex curIndex = currentIndex(); @@ -1513,7 +1535,7 @@ void PacketList::setPacketComment(guint c_number, QString new_comment) QString PacketList::allPacketComments() { - guint32 framenum; + uint32_t framenum; frame_data *fdata; QString buf_str; @@ -1525,8 +1547,8 @@ QString PacketList::allPacketComments() wtap_block_t pkt_block = cf_get_packet_block(cap_file_, fdata); if (pkt_block) { - guint n_comments = wtap_block_count_option(pkt_block, OPT_COMMENT); - for (guint i = 0; i < n_comments; i++) { + unsigned n_comments = wtap_block_count_option(pkt_block, OPT_COMMENT); + for (unsigned i = 0; i < n_comments; i++) { char *comment_text; if (WTAP_OPTTYPE_SUCCESS == wtap_block_get_nth_string_option_value(pkt_block, OPT_COMMENT, i, &comment_text)) { buf_str.append(QString(tr("Frame %1: %2\n\n")).arg(framenum).arg(comment_text)); @@ -1584,7 +1606,12 @@ void PacketList::setCaptureFile(capture_file *cf) void PacketList::setMonospaceFont(const QFont &mono_font) { setFont(mono_font); - header()->setFont(mainApp->font()); +} + +void PacketList::setRegularFont(const QFont ®ular_font) +{ + header()->setFont(regular_font); + header()->viewport()->setFont(regular_font); } void PacketList::goNextPacket(void) @@ -1644,16 +1671,14 @@ void PacketList::goLastPacket(void) { scrollViewChanged(false); } -// XXX We can jump to the wrong packet if a display filter is applied void PacketList::goToPacket(int packet, int hf_id) { - if (!cf_goto_frame(cap_file_, packet)) + if (!cf_goto_frame(cap_file_, packet, false)) return; - int row = packet_list_model_->packetNumberToRow(packet); - if (row >= 0) { - selectionModel()->setCurrentIndex(packet_list_model_->index(row, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); - scrollTo(currentIndex(), PositionAtCenter); + // cf_goto_frame only returns true if packet_list_select_row_from_data + // succeeds, the latter has already selected and scrolled to the frame. + if (hf_id > 0) { proto_tree_->goToHfid(hf_id); } @@ -1810,7 +1835,7 @@ void PacketList::sectionResized(int col, int, int new_width) // visible. // // Don't set column width when columns changed or setting column - // visibility because we may get a sectionReized() from QTreeView + // visibility because we may get a sectionResized() from QTreeView // with values from a old columns layout. // // Don't set column width when hiding a column. @@ -1825,6 +1850,7 @@ void PacketList::sectionResized(int col, int, int new_width) void PacketList::sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) { GList *new_col_list = NULL; + GList *new_recent_col_list = NULL; QList saved_sizes; int sort_idx; @@ -1849,9 +1875,14 @@ void PacketList::sectionMoved(int logicalIndex, int oldVisualIndex, int newVisua saved_sizes << header()->sectionSize(log_idx); void *pref_data = g_list_nth_data(prefs.col_list, log_idx); - if (!pref_data) continue; + if (pref_data) { + new_col_list = g_list_append(new_col_list, pref_data); + } - new_col_list = g_list_append(new_col_list, pref_data); + pref_data = g_list_nth_data(recent.col_width_list, log_idx); + if (pref_data) { + new_recent_col_list = g_list_append(new_recent_col_list, pref_data); + } } // Undo move to ensure that the logical indices map to the visual indices, @@ -1869,6 +1900,8 @@ void PacketList::sectionMoved(int logicalIndex, int oldVisualIndex, int newVisua g_list_free(prefs.col_list); prefs.col_list = new_col_list; + g_list_free(recent.col_width_list); + recent.col_width_list = new_recent_col_list; thaw(true); @@ -1988,7 +2021,7 @@ void PacketList::scrollViewChanged(bool at_end) // out colors. // Try 3: One packet per vertical scroll bar pixel. This seems to work best // but has the smallest window. -// Try 4: Use a multiple of the scroll bar heigh and scale the image down +// Try 4: Use a multiple of the scroll bar height and scale the image down // using Qt::SmoothTransformation. This gives us more packets per raster // line. diff --git a/ui/qt/packet_list.h b/ui/qt/packet_list.h index 2b025e25..8667bf5e 100644 --- a/ui/qt/packet_list.h +++ b/ui/qt/packet_list.h @@ -24,6 +24,7 @@ class PacketListHeader; class OverlayScrollBar; +class ProfileSwitcher; class QAction; class QTimerEvent; @@ -49,6 +50,7 @@ public: }; Q_ENUM(SummaryCopyType) + virtual void scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint hint = EnsureVisible) override; QMenu *conversationMenu() { return &conv_menu_; } QMenu *colorizeMenu() { return &colorize_menu_; } void setProtoTree(ProtoTree *proto_tree); @@ -73,9 +75,9 @@ public: bool contextMenuActive(); QString getFilterFromRowAndColumn(QModelIndex idx); void resetColorized(); - QString getPacketComment(guint c_number); + QString getPacketComment(unsigned c_number); void addPacketComment(QString new_comment); - void setPacketComment(guint c_number, QString new_comment); + void setPacketComment(unsigned c_number, QString new_comment); QString allPacketComments(); void deleteCommentsFromPackets(); void deleteAllPacketComments(); @@ -85,6 +87,7 @@ public: void resetColumns(); bool haveNextHistory(bool update_cur = false); bool havePreviousHistory(bool update_cur = false); + void setProfileSwitcher(ProfileSwitcher *profile_switcher); frame_data * getFDataForRow(int row) const; @@ -147,15 +150,15 @@ private: int cur_history_; bool in_history_; GPtrArray *finfo_array; // Packet data from the last selected packet entry + ProfileSwitcher *profile_switcher_; - void setFrameReftime(gboolean set, frame_data *fdata); + void setFrameReftime(bool set, frame_data *fdata); void setColumnVisibility(); int sizeHintForColumn(int column) const override; void setRecentColumnWidth(int column); void drawCurrentPacket(); void applyRecentColumnWidths(); void scrollViewChanged(bool at_end); - void colorsChanged(); QString joinSummaryRow(QStringList col_parts, int row, SummaryCopyType type); signals: @@ -172,6 +175,7 @@ signals: public slots: void setCaptureFile(capture_file *cf); void setMonospaceFont(const QFont &mono_font); + void setRegularFont(const QFont ®ular_font); void goNextPacket(); void goPreviousPacket(); void goFirstPacket(); @@ -189,6 +193,7 @@ public slots: void recolorPackets(); void redrawVisiblePackets(); void redrawVisiblePacketsDontSelectCurrent(); + void colorsChanged(); void columnsChanged(); void fieldsChanged(capture_file *cf); void preferencesChanged(); diff --git a/ui/qt/packet_range_group_box.cpp b/ui/qt/packet_range_group_box.cpp index dab44333..068f36a7 100644 --- a/ui/qt/packet_range_group_box.cpp +++ b/ui/qt/packet_range_group_box.cpp @@ -407,7 +407,7 @@ void PacketRangeGroupBox::on_rangeButton_toggled(bool checked) void PacketRangeGroupBox::on_capturedButton_toggled(bool checked) { if (checked) { - if (range_) range_->process_filtered = FALSE; + if (range_) range_->process_filtered = false; updateCounts(); } } @@ -415,21 +415,21 @@ void PacketRangeGroupBox::on_capturedButton_toggled(bool checked) void PacketRangeGroupBox::on_displayedButton_toggled(bool checked) { if (checked) { - if (range_) range_->process_filtered = TRUE; + if (range_) range_->process_filtered = true; updateCounts(); } } void PacketRangeGroupBox::on_ignoredCheckBox_toggled(bool checked) { - if (range_) range_->remove_ignored = checked ? TRUE : FALSE; + if (range_) range_->remove_ignored = checked ? true : false; updateCounts(); } void PacketRangeGroupBox::on_dependedCheckBox_toggled(bool checked) { if (range_) { - range_->include_dependents = checked ? TRUE : FALSE; + range_->include_dependents = checked ? true : false; updateCounts(); } } diff --git a/ui/qt/packet_range_group_box.h b/ui/qt/packet_range_group_box.h index 1912d71d..44fb1790 100644 --- a/ui/qt/packet_range_group_box.h +++ b/ui/qt/packet_range_group_box.h @@ -12,8 +12,6 @@ #include -#include - #include #include diff --git a/ui/qt/preference_editor_frame.cpp b/ui/qt/preference_editor_frame.cpp index 4ebce5c9..eec2571a 100644 --- a/ui/qt/preference_editor_frame.cpp +++ b/ui/qt/preference_editor_frame.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include #include #include @@ -49,6 +47,9 @@ PreferenceEditorFrame::PreferenceEditorFrame(QWidget *parent) : #endif connect(ui->preferenceBrowseButton, &QPushButton::clicked, this, &PreferenceEditorFrame::browsePushButtonClicked); + + // Disconnect textChanged signal for DissectorSyntaxLineEdit. + disconnect(ui->preferenceLineEdit, &DissectorSyntaxLineEdit::textChanged, NULL, NULL); } PreferenceEditorFrame::~PreferenceEditorFrame() @@ -80,14 +81,15 @@ void PreferenceEditorFrame::editPreference(preference *pref, pref_module *module ui->preferenceLineEdit->clear(); ui->preferenceLineEdit->setSyntaxState(SyntaxLineEdit::Empty); - disconnect(ui->preferenceLineEdit, 0, 0, 0); + + // Disconnect previous textChanged signal. + disconnect(ui->preferenceLineEdit, &SyntaxLineEdit::textChanged, this, NULL); bool show = false; bool browse_button = false; switch (prefs_get_type(pref_)) { case PREF_UINT: - case PREF_DECODE_AS_UINT: connect(ui->preferenceLineEdit, &SyntaxLineEdit::textChanged, this, &PreferenceEditorFrame::uintLineEditTextEdited); show = true; @@ -99,6 +101,7 @@ void PreferenceEditorFrame::editPreference(preference *pref, pref_module *module // Fallthrough case PREF_STRING: case PREF_PASSWORD: + case PREF_DISSECTOR: connect(ui->preferenceLineEdit, &SyntaxLineEdit::textChanged, this, &PreferenceEditorFrame::stringLineEditTextEdited); show = true; @@ -114,6 +117,16 @@ void PreferenceEditorFrame::editPreference(preference *pref, pref_module *module } if (show) { + // Enable completion only for display filter search. + if (prefs_get_type(pref_) == PREF_DISSECTOR) { + ui->preferenceLineEdit->allowCompletion(true); + ui->preferenceLineEdit->updateDissectorNames(); + ui->preferenceLineEdit->setDefaultPlaceholderText(); + } else { + ui->preferenceLineEdit->allowCompletion(false); + ui->preferenceLineEdit->setPlaceholderText(""); + } + ui->preferenceLineEdit->setText(gchar_free_to_qstring(prefs_pref_to_str(pref_, pref_stashed)).remove(QRegularExpression("\n\t"))); ui->preferenceBrowseButton->setHidden(!browse_button); animatedShow(); @@ -143,8 +156,15 @@ void PreferenceEditorFrame::uintLineEditTextEdited(const QString &new_str) void PreferenceEditorFrame::stringLineEditTextEdited(const QString &new_str) { + bool ok = true; new_str_ = new_str; - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + + if (prefs_get_type(pref_) == PREF_DISSECTOR) { + ui->preferenceLineEdit->checkDissectorName(new_str_); + ok = (ui->preferenceLineEdit->syntaxState() != SyntaxLineEdit::Invalid); + } + + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); } void PreferenceEditorFrame::browsePushButtonClicked() @@ -220,13 +240,13 @@ void PreferenceEditorFrame::on_buttonBox_accepted() unsigned int apply = 0; switch(prefs_get_type(pref_)) { case PREF_UINT: - case PREF_DECODE_AS_UINT: apply = prefs_set_uint_value(pref_, new_uint_, pref_stashed); break; case PREF_STRING: case PREF_SAVE_FILENAME: case PREF_OPEN_FILENAME: case PREF_DIRNAME: + case PREF_DISSECTOR: apply = prefs_set_string_value(pref_, new_str_.toStdString().c_str(), pref_stashed); break; case PREF_PASSWORD: @@ -245,13 +265,13 @@ void PreferenceEditorFrame::on_buttonBox_accepted() pref_unstash_data_t unstashed_data; unstashed_data.module = module_; - unstashed_data.handle_decode_as = TRUE; + unstashed_data.handle_decode_as = true; pref_unstash(pref_, &unstashed_data); prefs_apply(module_); prefs_main_write(); - gchar* err = NULL; + char* err = NULL; if (save_decode_as_entries(&err) < 0) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err); @@ -280,7 +300,7 @@ void PreferenceEditorFrame::on_buttonBox_rejected() void PreferenceEditorFrame::keyPressEvent(QKeyEvent *event) { - if (event->modifiers() == Qt::NoModifier) { + if (pref_ && module_ && (event->modifiers() == Qt::NoModifier)) { if (event->key() == Qt::Key_Escape) { on_buttonBox_rejected(); } else if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { diff --git a/ui/qt/preference_editor_frame.ui b/ui/qt/preference_editor_frame.ui index 6b8900e2..52b11dca 100644 --- a/ui/qt/preference_editor_frame.ui +++ b/ui/qt/preference_editor_frame.ui @@ -54,7 +54,7 @@ - + 1 @@ -106,9 +106,9 @@ 1 - SyntaxLineEdit - QLineEdit -
widgets/syntax_line_edit.h
+ DissectorSyntaxLineEdit + SyntaxLineEdit +
widgets/dissector_syntax_line_edit.h
diff --git a/ui/qt/preferences_dialog.cpp b/ui/qt/preferences_dialog.cpp index 7f78350c..76a880e2 100644 --- a/ui/qt/preferences_dialog.cpp +++ b/ui/qt/preferences_dialog.cpp @@ -22,21 +22,25 @@ #include #include #include +#include #include #include "main_application.h" +#include +#include + extern "C" { // Callbacks prefs routines -static guint -module_prefs_unstash(module_t *module, gpointer data) +static unsigned +module_prefs_unstash(module_t *module, void *data) { - gboolean *must_redissect_p = static_cast(data); + unsigned int *must_redissect_p = static_cast(data); pref_unstash_data_t unstashed_data; - unstashed_data.handle_decode_as = TRUE; + unstashed_data.handle_decode_as = true; module->prefs_changed_flags = 0; /* assume none of them changed */ for (GList *pref_l = module->prefs; pref_l && pref_l->data; pref_l = gxx_list_next(pref_l)) { @@ -60,8 +64,8 @@ module_prefs_unstash(module_t *module, gpointer data) return 0; /* Keep unstashing. */ } -static guint -module_prefs_clean_stash(module_t *module, gpointer) +static unsigned +module_prefs_clean_stash(module_t *module, void *) { for (GList *pref_l = module->prefs; pref_l && pref_l->data; pref_l = gxx_list_next(pref_l)) { pref_t *pref = gxx_list_data(pref_t *, pref_l); @@ -112,6 +116,13 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) : pd_ui_->splitter->setStretchFactor(0, 1); pd_ui_->splitter->setStretchFactor(1, 5); + + // The calculations done in showEvent to set the minimum size of the + // protocol column mean that if we load the splitter state it will become + // impossible to shrink the splitter below the width of the widest protocol + // that initially fits, so don't do this unless we change showEvent. + //loadSplitterState(pd_ui_->splitter); + pd_ui_->prefsView->sortByColumn(ModulePrefsModel::colName, Qt::AscendingOrder); //Set the Appearance leaf to expanded @@ -225,7 +236,7 @@ void PreferencesDialog::on_advancedSearchLineEdit_textEdited(const QString &text * the countdown. */ searchLineEditText = text; - guint gui_debounce_timer = prefs_get_uint_value("gui", "debounce.timer"); + unsigned gui_debounce_timer = prefs_get_uint_value("gui", "debounce.timer"); searchLineEditTimer->start(gui_debounce_timer); } @@ -237,19 +248,25 @@ void PreferencesDialog::on_showChangedValuesCheckBox_toggled(bool checked) pd_ui_->advancedView->expandAll(); } -void PreferencesDialog::on_buttonBox_accepted() +void PreferencesDialog::apply() { - gchar* err = NULL; + char* err = NULL; unsigned int redissect_flags = 0; // XXX - We should validate preferences as the user changes them, not here. // XXX - We're also too enthusiastic about setting must_redissect. - prefs_modules_foreach_submodules(NULL, module_prefs_unstash, (gpointer)&redissect_flags); + prefs_modules_foreach_submodules(NULL, module_prefs_unstash, (void *)&redissect_flags); + + extcap_register_preferences(); if (redissect_flags & PREF_EFFECT_GUI_LAYOUT) { // Layout type changed, reset sizes recent.gui_geometry_main_upper_pane = 0; recent.gui_geometry_main_lower_pane = 0; + g_free(recent.gui_geometry_main_master_split); + g_free(recent.gui_geometry_main_extra_split); + recent.gui_geometry_main_master_split = NULL; + recent.gui_geometry_main_extra_split = NULL; } pd_ui_->columnFrame->unstash(); @@ -299,28 +316,41 @@ void PreferencesDialog::on_buttonBox_accepted() mainApp->setMonospaceFont(prefs.gui_font_name); + if (redissect_flags & (PREF_EFFECT_GUI_COLOR)) { + mainApp->emitAppSignal(MainApplication::ColorsChanged); + } + if (redissect_flags & PREF_EFFECT_FIELDS) { - mainApp->queueAppSignal(MainApplication::FieldsChanged); + mainApp->emitAppSignal(MainApplication::FieldsChanged); } if (redissect_flags & PREF_EFFECT_DISSECTION) { // Freeze the packet list early to avoid updating column data before doing a // full redissection. The packet list will be thawed when redissection is done. - mainApp->queueAppSignal(MainApplication::FreezePacketList); + mainApp->emitAppSignal(MainApplication::FreezePacketList); /* Redissect all the packets, and re-evaluate the display filter. */ - mainApp->queueAppSignal(MainApplication::PacketDissectionChanged); + mainApp->emitAppSignal(MainApplication::PacketDissectionChanged); + } + + if (redissect_flags) { + mainApp->emitAppSignal(MainApplication::PreferencesChanged); } - mainApp->queueAppSignal(MainApplication::PreferencesChanged); if (redissect_flags & PREF_EFFECT_GUI_LAYOUT) { - mainApp->queueAppSignal(MainApplication::RecentPreferencesRead); + mainApp->emitAppSignal(MainApplication::RecentPreferencesRead); } if (prefs.capture_no_extcap != saved_capture_no_extcap_) mainApp->refreshLocalInterfaces(); } +void PreferencesDialog::on_buttonBox_accepted() +{ + apply(); + accept(); +} + void PreferencesDialog::on_buttonBox_rejected() { //handle frames that don't have their own OK/Cancel "buttons" @@ -329,9 +359,24 @@ void PreferencesDialog::on_buttonBox_rejected() #ifdef HAVE_LIBGNUTLS pd_ui_->rsaKeysFrame->rejectChanges(); #endif + reject(); +} + +void PreferencesDialog::on_buttonBox_clicked(QAbstractButton *button) +{ + if (pd_ui_->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) { + apply(); + } } void PreferencesDialog::on_buttonBox_helpRequested() { - mainApp->helpTopicAction(HELP_PREFERENCES_DIALOG); + QString help_page = modulePrefsModel_.data(pd_ui_->prefsView->currentIndex(), ModulePrefsModel::ModuleHelp).toString(); + if (!help_page.isEmpty()) { + QString url = gchar_free_to_qstring(user_guide_url(help_page.toUtf8().constData())); + QDesktopServices::openUrl(QUrl(url)); + } else { + // Generic help + mainApp->helpTopicAction(HELP_PREFERENCES_DIALOG); + } } diff --git a/ui/qt/preferences_dialog.h b/ui/qt/preferences_dialog.h index 51760699..b295aeaa 100644 --- a/ui/qt/preferences_dialog.h +++ b/ui/qt/preferences_dialog.h @@ -20,6 +20,7 @@ #include "geometry_state_dialog.h" class QComboBox; +class QAbstractButton; namespace Ui { class PreferencesDialog; @@ -44,6 +45,8 @@ protected: void showEvent(QShowEvent *evt); private: + void apply(); + Ui::PreferencesDialog *pd_ui_; QHash prefs_pane_to_item_; @@ -52,7 +55,7 @@ private: AdvancedPrefsModel advancedPrefsModel_; AdvancedPrefDelegate advancedPrefsDelegate_; ModulePrefsModel modulePrefsModel_; - gboolean saved_capture_no_extcap_; + bool saved_capture_no_extcap_; QTimer *searchLineEditTimer; QString searchLineEditText; @@ -65,6 +68,7 @@ private slots: void on_buttonBox_accepted(); void on_buttonBox_rejected(); void on_buttonBox_helpRequested(); + void on_buttonBox_clicked(QAbstractButton *button); /** * Update search results from the advancedSearchLineEdit field diff --git a/ui/qt/preferences_dialog.ui b/ui/qt/preferences_dialog.ui index e6c625bb..dc016ae0 100644 --- a/ui/qt/preferences_dialog.ui +++ b/ui/qt/preferences_dialog.ui @@ -111,7 +111,7 @@ Qt::Horizontal
- QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok + QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok|QDialogButtonBox::Apply
@@ -168,38 +168,4 @@ - - - buttonBox - accepted() - PreferencesDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - PreferencesDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - -
diff --git a/ui/qt/print_dialog.cpp b/ui/qt/print_dialog.cpp index 84c2d906..413510b4 100644 --- a/ui/qt/print_dialog.cpp +++ b/ui/qt/print_dialog.cpp @@ -32,32 +32,32 @@ extern "C" { // Page element callbacks -static gboolean -print_preamble_pd(print_stream_t *self, gchar *, const char *) +static bool +print_preamble_pd(print_stream_t *self, char *, const char *) { - if (!self) return FALSE; + if (!self) return false; PrintDialog *print_dlg = static_cast(self->data); - if (!print_dlg) return FALSE; + if (!print_dlg) return false; return print_dlg->printHeader(); } -static gboolean +static bool print_line_pd(print_stream_t *self, int indent, const char *line) { - if (!self) return FALSE; + if (!self) return false; PrintDialog *print_dlg = static_cast(self->data); - if (!print_dlg) return FALSE; + if (!print_dlg) return false; return print_dlg->printLine(indent, line); } -static gboolean +static bool new_page_pd(print_stream_t *self) { - if (!self) return FALSE; + if (!self) return false; PrintDialog *print_dlg = static_cast(self->data); - if (!print_dlg) return FALSE; + if (!print_dlg) return false; return print_dlg->printHeader(); } @@ -73,7 +73,7 @@ PrintDialog::PrintDialog(QWidget *parent, capture_file *cf, QString selRange) : print_bt_(new QPushButton(tr("&Print…"))), cap_file_(cf), page_pos_(0), - in_preview_(FALSE) + in_preview_(false) { Q_ASSERT(cf); @@ -97,7 +97,7 @@ PrintDialog::PrintDialog(QWidget *parent, capture_file *cf, QString selRange) : /* Init the export range */ packet_range_init(&print_args_.range, cap_file_); /* Default to displayed packets */ - print_args_.range.process_filtered = TRUE; + print_args_.range.process_filtered = true; stream_ops_.print_preamble = print_preamble_pd; stream_ops_.print_line = print_line_pd; @@ -107,7 +107,7 @@ PrintDialog::PrintDialog(QWidget *parent, capture_file *cf, QString selRange) : stream_.ops = &stream_ops_; print_args_.stream = &stream_; - gchar *display_basename = g_filename_display_basename(cap_file_->filename); + char *display_basename = g_filename_display_basename(cap_file_->filename); printer_.setDocName(display_basename); g_free(display_basename); @@ -136,9 +136,9 @@ PrintDialog::~PrintDialog() delete pd_ui_; } -gboolean PrintDialog::printHeader() +bool PrintDialog::printHeader() { - if (!cap_file_ || !cap_file_->filename || !cur_printer_ || !cur_painter_) return FALSE; + if (!cap_file_ || !cap_file_->filename || !cur_printer_ || !cur_painter_) return false; #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) int page_top = cur_printer_->pageLayout().paintRectPixels(cur_printer_->resolution()).top(); #else @@ -149,7 +149,7 @@ gboolean PrintDialog::printHeader() if (in_preview_) { // When generating a preview, only generate the first page; // if we're past the first page, stop the printing process. - return FALSE; + return false; } // Second and subsequent pages only cur_printer_->newPage(); @@ -160,21 +160,21 @@ gboolean PrintDialog::printHeader() QString banner = QString(tr("%1 %2 total packets, %3 shown")) .arg(cap_file_->filename) .arg(cap_file_->count) - .arg(cap_file_->displayed_count); + .arg(packet_range_count(&print_args_.range)); cur_painter_->setFont(header_font_); cur_painter_->drawText(0, page_top, banner); } page_pos_ += cur_painter_->fontMetrics().height(); cur_painter_->setFont(packet_font_); - return TRUE; + return true; } -gboolean PrintDialog::printLine(int indent, const char *line) +bool PrintDialog::printLine(int indent, const char *line) { QRect out_rect, page_rect; QString out_line; - if (!line || !cur_printer_ || !cur_painter_) return FALSE; + if (!line || !cur_printer_ || !cur_painter_) return false; /* Prepare the tabs for printing, depending on tree level */ out_line.fill(' ', indent * 4); @@ -196,13 +196,13 @@ gboolean PrintDialog::printLine(int indent, const char *line) if (in_preview_) { // When generating a preview, only generate the first page; // if we're past the first page, stop the printing process. - return FALSE; + return false; } if (*line == '\0') { // This is an empty line, so it's a separator; no need to // waste space printing it at the top of a page, as the // page break suffices as a separator. - return TRUE; + return true; } printHeader(); } @@ -210,7 +210,7 @@ gboolean PrintDialog::printLine(int indent, const char *line) out_rect.translate(0, page_pos_); cur_painter_->drawText(out_rect, Qt::TextWordWrap, out_line); page_pos_ += out_rect.height(); - return TRUE; + return true; } // Protected @@ -287,7 +287,7 @@ void PrintDialog::printPackets(QPrinter *printer, bool in_preview) // Don't show a progress bar if we're previewing; if it takes a // significant amount of time to generate a preview of the first // page, We Have A Real Problem - cf_print_packets(cap_file_, &print_args_, in_preview ? FALSE : TRUE); + cf_print_packets(cap_file_, &print_args_, in_preview ? false : true); cur_printer_ = NULL; cur_painter_ = NULL; painter.end(); diff --git a/ui/qt/print_dialog.h b/ui/qt/print_dialog.h index 88bda81e..eabb0b08 100644 --- a/ui/qt/print_dialog.h +++ b/ui/qt/print_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include "file.h" #include @@ -33,8 +31,8 @@ public: explicit PrintDialog(QWidget *parent = 0, capture_file *cf = NULL, QString selRange = QString()); ~PrintDialog(); - gboolean printHeader(); - gboolean printLine(int indent, const char *line); + bool printHeader(); + bool printLine(int indent, const char *line); protected: virtual void keyPressEvent(QKeyEvent *event) override; diff --git a/ui/qt/profile_dialog.cpp b/ui/qt/profile_dialog.cpp index 5b53a2cf..9de24054 100644 --- a/ui/qt/profile_dialog.cpp +++ b/ui/qt/profile_dialog.cpp @@ -8,11 +8,8 @@ */ #include "config.h" -#include #include "wsutil/filesystem.h" -#include "wsutil/utf8_entities.h" -#include "epan/prefs.h" #include @@ -27,6 +24,7 @@ #include "main_application.h" #include #include +#include #include #include @@ -37,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -74,9 +71,16 @@ ProfileDialog::ProfileDialog(QWidget *parent) : pd_ui_->hintLabel->setAttribute(Qt::WA_MacSmallSize, true); #endif + QString as_tooltip = pd_ui_->autoSwitchLimitLabel->toolTip(); + pd_ui_->autoSwitchSpinBox->setToolTip(as_tooltip); + if (!is_packet_configuration_namespace()) { + pd_ui_->autoSwitchLimitLabel->setText(tr("Auto switch event limit")); + } + pd_ui_->autoSwitchSpinBox->setValue(recent.gui_profile_switch_check_count); + import_button_ = pd_ui_->buttonBox->addButton(tr("Import", "noun"), QDialogButtonBox::ActionRole); -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) export_button_ = pd_ui_->buttonBox->addButton(tr("Export", "noun"), QDialogButtonBox::ActionRole); QMenu * importMenu = new QMenu(import_button_); @@ -112,13 +116,23 @@ ProfileDialog::ProfileDialog(QWidget *parent) : currentItemChanged(); + connect(pd_ui_->newToolButton, &StockIconToolButton::clicked, this, &ProfileDialog::newToolButtonClicked); + connect(pd_ui_->deleteToolButton, &StockIconToolButton::clicked, this, &ProfileDialog::deleteToolButtonClicked); + connect(pd_ui_->copyToolButton, &StockIconToolButton::clicked, this, &ProfileDialog::copyToolButtonClicked); + connect(pd_ui_->buttonBox, &QDialogButtonBox::accepted, this, &ProfileDialog::buttonBoxAccepted); + connect(pd_ui_->buttonBox, &QDialogButtonBox::rejected, this, &ProfileDialog::buttonBoxRejected); + connect(pd_ui_->buttonBox, &QDialogButtonBox::helpRequested, this, &ProfileDialog::buttonBoxHelpRequested); + + pd_ui_->profileTreeView->resizeColumnToContents(ProfileModel::COL_NAME); + pd_ui_->profileTreeView->resizeColumnToContents(ProfileModel::COL_TYPE); + pd_ui_->profileTreeView->setFocus(); } ProfileDialog::~ProfileDialog() { delete pd_ui_; - empty_profile_list (TRUE); + empty_profile_list (true); } void ProfileDialog::keyPressEvent(QKeyEvent *evt) @@ -149,11 +163,11 @@ int ProfileDialog::execAction(ProfileDialog::ProfileAction profile_action) ret = exec(); break; case NewProfile: - on_newToolButton_clicked(); + newToolButtonClicked(); ret = exec(); break; case ImportZipProfile: -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) importFromZip(); #endif break; @@ -161,12 +175,12 @@ int ProfileDialog::execAction(ProfileDialog::ProfileAction profile_action) importFromDirectory(); break; case ExportSingleProfile: -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) exportProfiles(); #endif break; case ExportAllProfiles: -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) exportProfiles(true); #endif break; @@ -249,7 +263,7 @@ void ProfileDialog::updateWidgets() import_button_->setToolTip(msg); import_button_->setEnabled(enable_import); -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) bool contains_user = false; bool enable_export = false; @@ -294,7 +308,7 @@ void ProfileDialog::updateWidgets() msg = tr("%Ln Selected Personal Profile(s)...", "", user_profiles); pd_ui_->hintLabel->setText(msg); -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) export_selected_entry_->setText(msg); #endif } @@ -314,7 +328,7 @@ void ProfileDialog::updateWidgets() } pd_ui_->copyToolButton->setEnabled(true); -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) export_selected_entry_->setText(msg); #endif } @@ -365,9 +379,6 @@ void ProfileDialog::updateWidgets() pd_ui_->hintLabel->setUrl(hintUrl); - /* ensure the name column is resized to it's content */ - pd_ui_->profileTreeView->resizeColumnToContents(ProfileModel::COL_NAME); - pd_ui_->deleteToolButton->setEnabled(enable_del); ok_button_->setEnabled(enable_ok); } @@ -377,7 +388,7 @@ void ProfileDialog::currentItemChanged(const QModelIndex &, const QModelIndex &) updateWidgets(); } -void ProfileDialog::on_newToolButton_clicked() +void ProfileDialog::newToolButtonClicked() { pd_ui_->lineProfileFilter->setText(""); pd_ui_->cmbProfileTypes->setCurrentIndex(ProfileSortModel::AllProfiles); @@ -395,7 +406,7 @@ void ProfileDialog::on_newToolButton_clicked() updateWidgets(); } -void ProfileDialog::on_deleteToolButton_clicked() +void ProfileDialog::deleteToolButtonClicked() { QModelIndexList profiles = selectedProfiles(); if (profiles.count() <= 0) @@ -417,7 +428,7 @@ void ProfileDialog::on_deleteToolButton_clicked() updateWidgets(); } -void ProfileDialog::on_copyToolButton_clicked() +void ProfileDialog::copyToolButtonClicked() { QModelIndexList profiles = selectedProfiles(); if (profiles.count() > 1) @@ -444,11 +455,13 @@ void ProfileDialog::on_copyToolButton_clicked() updateWidgets(); } -void ProfileDialog::on_buttonBox_accepted() +void ProfileDialog::buttonBoxAccepted() { bool write_recent = true; bool item_data_removed = false; + recent.gui_profile_switch_check_count = pd_ui_->autoSwitchSpinBox->value(); + QModelIndex index = sort_model_->mapToSource(pd_ui_->profileTreeView->currentIndex()); pd_ui_->buttonBox->setFocus(); @@ -483,7 +496,7 @@ void ProfileDialog::on_buttonBox_accepted() write_profile_recent(); } - gchar * err_msg = Q_NULLPTR; + char * err_msg = Q_NULLPTR; if ((err_msg = apply_profile_changes()) != Q_NULLPTR) { QMessageBox::critical(this, tr("Profile Error"), err_msg, @@ -512,22 +525,22 @@ void ProfileDialog::on_buttonBox_accepted() if (profileName.length() > 0 && model_->findByName(profileName) >= 0) { // The new profile exists, change. - mainApp->setConfigurationProfile (profileName.toUtf8().constData(), FALSE); + mainApp->setConfigurationProfile (profileName.toUtf8().constData(), false); } else if (!model_->activeProfile().isValid()) { // The new profile does not exist, and the previous profile has // been deleted. Change to the default profile. - mainApp->setConfigurationProfile (Q_NULLPTR, FALSE); + mainApp->setConfigurationProfile (Q_NULLPTR, false); } } -void ProfileDialog::on_buttonBox_rejected() +void ProfileDialog::buttonBoxRejected() { QString msg; if (! model_->clearImported(&msg)) QMessageBox::critical(this, tr("Error"), msg); } -void ProfileDialog::on_buttonBox_helpRequested() +void ProfileDialog::buttonBoxHelpRequested() { mainApp->helpTopicAction(HELP_CONFIG_PROFILES_DIALOG); } @@ -558,14 +571,12 @@ void ProfileDialog::filterChanged(const QString &text) else if (qobject_cast(sender())) sort_model_->setFilterString(text); - pd_ui_->profileTreeView->resizeColumnToContents(ProfileModel::COL_NAME); - QModelIndex active = sort_model_->mapFromSource(model_->activeProfile()); if (active.isValid()) pd_ui_->profileTreeView->setCurrentIndex(active); } -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) void ProfileDialog::exportProfiles(bool exportAllPersonalProfiles) { QAction * action = qobject_cast(sender()); @@ -604,7 +615,7 @@ void ProfileDialog::exportProfiles(bool exportAllPersonalProfiles) return; } - QString zipFile = QFileDialog::getSaveFileName(this, tr("Select zip file for export"), openDialogInitialDir(), tr("Zip File (*.zip)")); + QString zipFile = WiresharkFileDialog::getSaveFileName(this, tr("Select zip file for export"), openDialogInitialDir(), tr("Zip File (*.zip)")); if (zipFile.length() > 0) { @@ -627,7 +638,7 @@ void ProfileDialog::exportProfiles(bool exportAllPersonalProfiles) { QString msg = tr("An error has occurred while exporting profiles"); if (err.length() > 0) - msg.append(QString("\n\n%1: %3").arg(tr("Error")).arg(err)); + msg.append(QString("\n\n%1: %2").arg(tr("Error"), err)); QMessageBox::critical(this, tr("Exporting profiles"), msg); } } @@ -635,7 +646,7 @@ void ProfileDialog::exportProfiles(bool exportAllPersonalProfiles) void ProfileDialog::importFromZip() { - QString zipFile = QFileDialog::getOpenFileName(this, tr("Select zip file for import"), openDialogInitialDir(), tr("Zip File (*.zip)")); + QString zipFile = WiresharkFileDialog::getOpenFileName(this, tr("Select zip file for import"), openDialogInitialDir(), tr("Zip File (*.zip)")); QFileInfo fi(zipFile); if (! fi.exists()) @@ -651,7 +662,7 @@ void ProfileDialog::importFromZip() void ProfileDialog::importFromDirectory() { - QString importDir = QFileDialog::getExistingDirectory(this, tr("Select directory for import"), openDialogInitialDir()); + QString importDir = WiresharkFileDialog::getExistingDirectory(this, tr("Select directory for import"), openDialogInitialDir()); QFileInfo fi(importDir); if (! fi.isDir()) @@ -726,11 +737,8 @@ void ProfileDialog::resetTreeView() selectionChanged(); - if (sort_model_->columnCount() <= 1) + if (sort_model_->columnCount() <= 1) { pd_ui_->profileTreeView->header()->hide(); - else - { - pd_ui_->profileTreeView->header()->setStretchLastSection(false); - pd_ui_->profileTreeView->header()->setSectionResizeMode(ProfileModel::COL_NAME, QHeaderView::Stretch); } } + diff --git a/ui/qt/profile_dialog.h b/ui/qt/profile_dialog.h index d42594f0..5ffc69f7 100644 --- a/ui/qt/profile_dialog.h +++ b/ui/qt/profile_dialog.h @@ -40,8 +40,8 @@ public: /** * @brief Select the profile with the given name. * - * If the profile name is empty, the currently selected profile will be choosen instead. - * If the choosen profile is invalid, the first row will be choosen. + * If the profile name is empty, the currently selected profile will be chosen instead. + * If the chosen profile is invalid, the first row will be chosen. * * @param profile the name of the profile to be selected */ @@ -54,7 +54,7 @@ private: Ui::ProfileDialog *pd_ui_; QPushButton *ok_button_; QPushButton *import_button_; -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) QPushButton *export_button_; QAction *export_selected_entry_; #endif @@ -68,18 +68,18 @@ private: private slots: void currentItemChanged(const QModelIndex & c = QModelIndex(), const QModelIndex & p = QModelIndex()); -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) void exportProfiles(bool exportAllPersonalProfiles = false); void importFromZip(); #endif void importFromDirectory(); - void on_newToolButton_clicked(); - void on_deleteToolButton_clicked(); - void on_copyToolButton_clicked(); - void on_buttonBox_accepted(); - void on_buttonBox_rejected(); - void on_buttonBox_helpRequested(); + void newToolButtonClicked(); + void deleteToolButtonClicked(); + void copyToolButtonClicked(); + void buttonBoxAccepted(); + void buttonBoxRejected(); + void buttonBoxHelpRequested(); void dataChanged(const QModelIndex &); void filterChanged(const QString &); diff --git a/ui/qt/profile_dialog.ui b/ui/qt/profile_dialog.ui index fcc7591f..5f5bdf38 100644 --- a/ui/qt/profile_dialog.ui +++ b/ui/qt/profile_dialog.ui @@ -6,7 +6,7 @@ 0 0 - 570 + 600 400
@@ -54,7 +54,7 @@ - + @@ -94,6 +94,42 @@ + + + + Qt::Horizontal + + + + 5 + 20 + + + + + + + + The number of packets or events to check for automatic profile switching. + + + Auto switch packet limit + + + + + + + QAbstractSpinBox::NoButtons + + + 10000000 + + + 1000 + + + diff --git a/ui/qt/progress_frame.cpp b/ui/qt/progress_frame.cpp index 2e40ac80..33306ebc 100644 --- a/ui/qt/progress_frame.cpp +++ b/ui/qt/progress_frame.cpp @@ -28,8 +28,8 @@ // - Don't complain so loudly when the user stops a capture. progdlg_t * -create_progress_dlg(gpointer top_level_window, const gchar *task_title, const gchar *item_title, - gboolean terminate_is_stop, gboolean *stop_flag) { +create_progress_dlg(void *top_level_window, const char *task_title, const char *item_title, + bool terminate_is_stop, bool *stop_flag) { ProgressFrame *pf; QWidget *main_window; @@ -57,9 +57,9 @@ create_progress_dlg(gpointer top_level_window, const gchar *task_title, const gc } progdlg_t * -delayed_create_progress_dlg(gpointer top_level_window, const gchar *task_title, const gchar *item_title, - gboolean terminate_is_stop, gboolean *stop_flag, - gfloat progress) +delayed_create_progress_dlg(void *top_level_window, const char *task_title, const char *item_title, + bool terminate_is_stop, bool *stop_flag, + float progress) { progdlg_t *progress_dialog = create_progress_dlg(top_level_window, task_title, item_title, terminate_is_stop, stop_flag); update_progress_dlg(progress_dialog, progress, item_title); @@ -70,7 +70,7 @@ delayed_create_progress_dlg(gpointer top_level_window, const gchar *task_title, * Update the progress information of the progress bar box. */ void -update_progress_dlg(progdlg_t *dlg, gfloat percentage, const gchar *) +update_progress_dlg(progdlg_t *dlg, float percentage, const char *) { if (!dlg) return; @@ -145,8 +145,8 @@ ProgressFrame::ProgressFrame(QWidget *parent) : effect_ = new QGraphicsOpacityEffect(this); animation_ = new QPropertyAnimation(effect_, "opacity", this); - connect(this, SIGNAL(showRequested(bool,bool,gboolean*)), - this, SLOT(show(bool,bool,gboolean*))); + connect(this, SIGNAL(showRequested(bool,bool,bool*)), + this, SLOT(show(bool,bool,bool*))); hide(); } @@ -155,17 +155,13 @@ ProgressFrame::~ProgressFrame() delete ui; } -struct progdlg *ProgressFrame::showProgress(const QString &title, bool animate, bool terminate_is_stop, gboolean *stop_flag, int value) +struct progdlg *ProgressFrame::showProgress(const QString &title, bool animate, bool terminate_is_stop, bool *stop_flag, int value) { setMaximumValue(100); ui->progressBar->setValue(value); QString elided_title = title; int max_w = fontMetrics().height() * 20; // em-widths, arbitrary -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) int title_w = fontMetrics().horizontalAdvance(title); -#else - int title_w = fontMetrics().width(title); -#endif if (title_w > max_w) { elided_title = fontMetrics().elidedText(title, Qt::ElideRight, max_w); } @@ -175,7 +171,7 @@ struct progdlg *ProgressFrame::showProgress(const QString &title, bool animate, return &progress_dialog_; } -progdlg *ProgressFrame::showBusy(bool animate, bool terminate_is_stop, gboolean *stop_flag) +progdlg *ProgressFrame::showBusy(bool animate, bool terminate_is_stop, bool *stop_flag) { setMaximumValue(0); emit showRequested(animate, terminate_is_stop, stop_flag); @@ -209,8 +205,8 @@ void ProgressFrame::addToButtonBox(QDialogButtonBox *button_box, QObject *main_w int one_em = progress_frame->fontMetrics().height(); progress_frame->setMaximumWidth(one_em * 8); - connect(main_progress_frame, SIGNAL(showRequested(bool,bool,gboolean*)), - progress_frame, SLOT(show(bool,bool,gboolean*))); + connect(main_progress_frame, SIGNAL(showRequested(bool,bool,bool*)), + progress_frame, SLOT(show(bool,bool,bool*))); connect(main_progress_frame, SIGNAL(maximumValueChanged(int)), progress_frame, SLOT(setMaximumValue(int))); connect(main_progress_frame, SIGNAL(valueChanged(int)), @@ -226,12 +222,12 @@ void ProgressFrame::captureFileClosing() { // Hide any paired ProgressFrames and disconnect from them. emit setHidden(); - disconnect(SIGNAL(showRequested(bool,bool,gboolean*))); + disconnect(SIGNAL(showRequested(bool,bool,bool*))); disconnect(SIGNAL(maximumValueChanged(int))); disconnect(SIGNAL(valueChanged(int))); - connect(this, SIGNAL(showRequested(bool,bool,gboolean*)), - this, SLOT(show(bool,bool,gboolean*))); + connect(this, SIGNAL(showRequested(bool,bool,bool*)), + this, SLOT(show(bool,bool,bool*))); } void ProgressFrame::setValue(int value) @@ -281,7 +277,7 @@ void ProgressFrame::on_stopButton_clicked() const int show_delay_ = 150; // ms -void ProgressFrame::show(bool animate, bool terminate_is_stop, gboolean *stop_flag) +void ProgressFrame::show(bool animate, bool terminate_is_stop, bool *stop_flag) { terminate_is_stop_ = terminate_is_stop; stop_flag_ = stop_flag; diff --git a/ui/qt/progress_frame.h b/ui/qt/progress_frame.h index 241afab8..368e519a 100644 --- a/ui/qt/progress_frame.h +++ b/ui/qt/progress_frame.h @@ -10,8 +10,6 @@ #ifndef PROGRESS_FRAME_H #define PROGRESS_FRAME_H -#include - #include namespace Ui { @@ -50,13 +48,13 @@ public: void captureFileClosing(); public slots: - struct progdlg *showProgress(const QString &title, bool animate, bool terminate_is_stop, gboolean *stop_flag, int value = 0); - struct progdlg *showBusy(bool animate, bool terminate_is_stop, gboolean *stop_flag); + struct progdlg *showProgress(const QString &title, bool animate, bool terminate_is_stop, bool *stop_flag, int value = 0); + struct progdlg *showBusy(bool animate, bool terminate_is_stop, bool *stop_flag); void setValue(int value); void hide(); signals: - void showRequested(bool animate, bool terminate_is_stop, gboolean *stop_flag); + void showRequested(bool animate, bool terminate_is_stop, bool *stop_flag); void valueChanged(int value); void maximumValueChanged(int value); void setHidden(); @@ -72,7 +70,7 @@ private: QString message_; QString status_; bool terminate_is_stop_; - gboolean *stop_flag_; + bool *stop_flag_; int show_timer_; QGraphicsOpacityEffect *effect_; QPropertyAnimation *animation_; @@ -84,7 +82,7 @@ private: private slots: void on_stopButton_clicked(); - void show(bool animate, bool terminate_is_stop, gboolean *stop_flag); + void show(bool animate, bool terminate_is_stop, bool *stop_flag); void setMaximumValue(int value); }; diff --git a/ui/qt/proto_tree.cpp b/ui/qt/proto_tree.cpp index 77af8d22..0db9eaa5 100644 --- a/ui/qt/proto_tree.cpp +++ b/ui/qt/proto_tree.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -174,7 +175,7 @@ void ProtoTree::ctxCopySelectedInfo() case ProtoTree::Value: { epan_dissect_t *edt = cap_file_ ? cap_file_->edt : edt_; - gchar* field_str = get_node_field_value(finfo.fieldInfo(), edt); + char* field_str = get_node_field_value(finfo.fieldInfo(), edt); clip.append(field_str); g_free(field_str); } @@ -216,7 +217,7 @@ void ProtoTree::ctxOpenUrlWiki() if (ret != QMessageBox::Yes) return; - url = QString(WS_WIKI_URL("%1")).arg(proto_abbrev); + url = QString(WS_WIKI_URL("Protocols/%1")).arg(proto_abbrev); } else { @@ -334,7 +335,10 @@ void ProtoTree::contextMenuEvent(QContextMenuEvent *event) ctx_menu->addSeparator(); } + ctx_menu->addMenu(IOGraphAction::createMenu(finfo->headerInfo(), ctx_menu)); + submenu = ctx_menu->addMenu(tr("Copy")); + submenu->setToolTipsVisible(true); submenu->addAction(tr("All Visible Items"), this, SLOT(ctxCopyVisibleItems())); action = submenu->addAction(tr("All Visible Selected Tree Items"), this, SLOT(ctxCopyVisibleItems())); action->setProperty("selected_tree", QVariant::fromValue(true)); @@ -356,7 +360,9 @@ void ProtoTree::contextMenuEvent(QContextMenuEvent *event) action = window()->findChild("actionAnalyzeShowPacketBytes"); ctx_menu->addAction(action); action = window()->findChild("actionFileExportPacketBytes"); - ctx_menu->addAction(action); + if (action) { + ctx_menu->addAction(action); + } ctx_menu->addSeparator(); } @@ -395,12 +401,14 @@ void ProtoTree::contextMenuEvent(QContextMenuEvent *event) if (! buildForDialog) { - QAction *decode_as_ = window()->findChild("actionAnalyzeDecodeAs"); - ctx_menu->addAction(decode_as_); - decode_as_->setProperty("create_new", QVariant::fromValue(true)); + QAction *decode_as = window()->findChild("actionAnalyzeDecodeAs"); + if (decode_as) { + ctx_menu->addAction(decode_as); + decode_as->setProperty("create_new", QVariant::fromValue(true)); - ctx_menu->addAction(window()->findChild("actionGoGoToLinkedPacket")); - ctx_menu->addAction(window()->findChild("actionContextShowLinkedPacketInNewWindow")); + ctx_menu->addAction(window()->findChild("actionGoGoToLinkedPacket")); + ctx_menu->addAction(window()->findChild("actionContextShowLinkedPacketInNewWindow")); + } } // The "text only" header field will not give preferences for the selected protocol. @@ -460,7 +468,7 @@ void ProtoTree::setMonospaceFont(const QFont &mono_font) update(); } -void ProtoTree::foreachTreeNode(proto_node *node, gpointer proto_tree_ptr) +void ProtoTree::foreachTreeNode(proto_node *node, void *proto_tree_ptr) { ProtoTree *tree_view = static_cast(proto_tree_ptr); ProtoTreeModel *model = qobject_cast(tree_view->model()); @@ -478,6 +486,7 @@ void ProtoTree::foreachTreeNode(proto_node *node, gpointer proto_tree_ptr) proto_tree_children_foreach(node, foreachTreeNode, proto_tree_ptr); } +// NOLINTNEXTLINE(misc-no-recursion) void ProtoTree::foreachExpand(const QModelIndex &index = QModelIndex()) { // Restore expanded state. (Note QModelIndex() refers to the root node) @@ -490,6 +499,7 @@ void ProtoTree::foreachExpand(const QModelIndex &index = QModelIndex()) { if (node && node->isValid() && tree_expanded(node->protoNode()->finfo->tree_type)) { expand(childIndex); } + // We recurse here, but we're limited by tree depth checks in epan foreachExpand(childIndex); } } @@ -571,7 +581,7 @@ void ProtoTree::syncExpanded(const QModelIndex &index) { * are thus presumably leaf nodes and cannot be expanded. */ if (finfo.treeType() != -1) { - tree_expanded_set(finfo.treeType(), TRUE); + tree_expanded_set(finfo.treeType(), true); } } @@ -584,7 +594,7 @@ void ProtoTree::syncCollapsed(const QModelIndex &index) { * are thus presumably leaf nodes and cannot be collapsed. */ if (finfo.treeType() != -1) { - tree_expanded_set(finfo.treeType(), FALSE); + tree_expanded_set(finfo.treeType(), false); } } @@ -635,7 +645,7 @@ void ProtoTree::collapseSubtrees() void ProtoTree::expandAll() { for (int i = 0; i < num_tree_types; i++) { - tree_expanded_set(i, TRUE); + tree_expanded_set(i, true); } QTreeView::expandAll(); updateContentWidth(); @@ -644,7 +654,7 @@ void ProtoTree::expandAll() void ProtoTree::collapseAll() { for (int i = 0; i < num_tree_types; i++) { - tree_expanded_set(i, FALSE); + tree_expanded_set(i, false); } QTreeView::collapseAll(); updateContentWidth(); @@ -776,6 +786,7 @@ void ProtoTree::restoreSelectedField() autoScrollTo(cur_index); } +// NOLINTNEXTLINE(misc-no-recursion) QString ProtoTree::traverseTree(const QModelIndex & travTree, int identLevel) const { QString result = ""; @@ -792,6 +803,7 @@ QString ProtoTree::traverseTree(const QModelIndex & travTree, int identLevel) co int children = proto_tree_model_->rowCount(travTree); identLevel++; for (int child = 0; child < children; child++) + // We recurse here, but we're limited by tree depth checks in epan result += traverseTree(proto_tree_model_->index(child, 0, travTree), identLevel); } } diff --git a/ui/qt/proto_tree.h b/ui/qt/proto_tree.h index 511063e9..ca08668b 100644 --- a/ui/qt/proto_tree.h +++ b/ui/qt/proto_tree.h @@ -70,7 +70,7 @@ private: epan_dissect_t *edt_; void saveSelectedField(QModelIndex &index); - static void foreachTreeNode(proto_node *node, gpointer proto_tree_ptr); + static void foreachTreeNode(proto_node *node, void *proto_tree_ptr); void foreachExpand(const QModelIndex &index); signals: diff --git a/ui/qt/protocol_hierarchy_dialog.cpp b/ui/qt/protocol_hierarchy_dialog.cpp index a97f37b7..fefb0b5c 100644 --- a/ui/qt/protocol_hierarchy_dialog.cpp +++ b/ui/qt/protocol_hierarchy_dialog.cpp @@ -305,7 +305,7 @@ void ProtocolHierarchyDialog::filterActionTriggered() emit filterAction(filter_name, fa->action(), fa->actionType()); } -void ProtocolHierarchyDialog::addTreeNode(GNode *node, gpointer data) +void ProtocolHierarchyDialog::addTreeNode(GNode *node, void *data) { ph_stats_node_t *stats = (ph_stats_node_t *)node->data; if (!stats) return; diff --git a/ui/qt/protocol_hierarchy_dialog.h b/ui/qt/protocol_hierarchy_dialog.h index 08f3dfd2..33191d1e 100644 --- a/ui/qt/protocol_hierarchy_dialog.h +++ b/ui/qt/protocol_hierarchy_dialog.h @@ -55,7 +55,7 @@ private: QSet used_protos_; // Callback for g_node_children_foreach - static void addTreeNode(GNode *node, gpointer data); + static void addTreeNode(GNode *node, void *data); void updateWidgets(); QList protoHierRowData(QTreeWidgetItem *item) const; }; diff --git a/ui/qt/protocol_preferences_menu.cpp b/ui/qt/protocol_preferences_menu.cpp index 75c3515c..4beff2fd 100644 --- a/ui/qt/protocol_preferences_menu.cpp +++ b/ui/qt/protocol_preferences_menu.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include #include #include @@ -118,7 +116,7 @@ public: } void showUatDialog() { - UatDialog *uat_dlg = new UatDialog(qobject_cast(parent()), prefs_get_uat_value(pref_)); + UatDialog *uat_dlg = new UatDialog(mainApp->mainWindow(), prefs_get_uat_value(pref_)); connect(uat_dlg, SIGNAL(destroyed(QObject*)), mainApp, SLOT(flushAppSignals())); uat_dlg->setWindowModality(Qt::ApplicationModal); uat_dlg->setAttribute(Qt::WA_DeleteOnClose); @@ -154,8 +152,8 @@ private: extern "C" { // Preference callback -static guint -add_prefs_menu_item(pref_t *pref, gpointer menu_ptr) +static unsigned +add_prefs_menu_item(pref_t *pref, void *menu_ptr) { ProtocolPreferencesMenu *pp_menu = static_cast(menu_ptr); if (!pp_menu) return 1; @@ -267,9 +265,9 @@ void ProtocolPreferencesMenu::addMenuItem(preference *pref) case PREF_OPEN_FILENAME: case PREF_DIRNAME: case PREF_RANGE: - case PREF_DECODE_AS_UINT: case PREF_DECODE_AS_RANGE: case PREF_PASSWORD: + case PREF_DISSECTOR: { EditorPreferenceAction *epa = new EditorPreferenceAction(pref, this); addAction(epa); diff --git a/ui/qt/remote_capture_dialog.cpp b/ui/qt/remote_capture_dialog.cpp index dff16527..f9a183b2 100644 --- a/ui/qt/remote_capture_dialog.cpp +++ b/ui/qt/remote_capture_dialog.cpp @@ -11,8 +11,8 @@ #include "config.h" #ifdef HAVE_PCAP_REMOTE -#include #include +#include #include "ui/capture_globals.h" #include "remote_capture_dialog.h" #include @@ -49,7 +49,11 @@ void RemoteCaptureDialog::hostChanged(const QString host) recent_free_remote_host_list(); ui->hostCombo->clear(); } else { - struct remote_host *rh = recent_get_remote_host(host.toUtf8().constData()); + const struct remote_host *rh = nullptr; + int index = ui->hostCombo->findText(host); + if (index != -1) { + rh = VariantPointer::asPtr(ui->hostCombo->itemData(index)); + } if (rh) { ui->portText->setText(QString(rh->remote_port)); if (rh->auth_type == CAPTURE_AUTH_NULL) { @@ -62,10 +66,11 @@ void RemoteCaptureDialog::hostChanged(const QString host) } -static void fillBox(gpointer key, gpointer, gpointer user_data) +static void fillBox(void *value, void *user_data) { QComboBox *cb = (QComboBox *)user_data; - cb->addItem(QString((gchar*)key)); + struct remote_host* rh = (struct remote_host*)value; + cb->addItem(QString((char*)rh->r_host), VariantPointer::asQVariant(rh)); } void RemoteCaptureDialog::fillComboBox() @@ -84,10 +89,13 @@ void RemoteCaptureDialog::fillComboBox() void RemoteCaptureDialog::apply_remote() { int err; - gchar *err_str; + char *err_str; remote_options global_remote_opts; QString host = ui->hostCombo->currentText(); + if (host.isEmpty()) { + return; + } global_remote_opts.src_type = CAPTURE_IFREMOTE; global_remote_opts.remote_host_opts.remote_host = qstring_strdup(host); QString port = ui->portText->text(); @@ -101,9 +109,9 @@ void RemoteCaptureDialog::apply_remote() global_remote_opts.remote_host_opts.auth_username = qstring_strdup(user); QString pw = ui->pwText->text(); global_remote_opts.remote_host_opts.auth_password = qstring_strdup(pw); - global_remote_opts.remote_host_opts.datatx_udp = FALSE; - global_remote_opts.remote_host_opts.nocap_rpcap = TRUE; - global_remote_opts.remote_host_opts.nocap_local = FALSE; + global_remote_opts.remote_host_opts.datatx_udp = false; + global_remote_opts.remote_host_opts.nocap_rpcap = true; + global_remote_opts.remote_host_opts.nocap_local = false; #ifdef HAVE_PCAP_SETSAMPLING global_remote_opts.sampling_method = CAPTURE_SAMP_NONE; global_remote_opts.sampling_param = 0; @@ -126,24 +134,28 @@ void RemoteCaptureDialog::apply_remote() QMessageBox::critical(this, tr("Error"), "Unknown error"); return; } - if (ui->hostCombo->count() == 0) { - ui->hostCombo->addItem(""); - ui->hostCombo->addItem(host); - ui->hostCombo->insertSeparator(2); - ui->hostCombo->addItem(QString(tr("Clear list"))); - } else { - ui->hostCombo->insertItem(0, host); - } - struct remote_host *rh = recent_get_remote_host(host.toUtf8().constData()); - if (!rh) { - rh = (struct remote_host *)g_malloc (sizeof (*rh)); - rh->r_host = qstring_strdup(host); - rh->remote_port = qstring_strdup(port); - rh->auth_type = global_remote_opts.remote_host_opts.auth_type; - rh->auth_password = g_strdup(""); - rh->auth_username = g_strdup(""); - recent_add_remote_host(global_remote_opts.remote_host_opts.remote_host, rh); - } + + // Add the remote host even if it already exists, to update the port and + // auth type and move it to the front. + struct remote_host* rh; + rh = (struct remote_host *)g_malloc (sizeof (*rh)); + rh->r_host = qstring_strdup(host); + rh->remote_port = qstring_strdup(port); + rh->auth_type = global_remote_opts.remote_host_opts.auth_type; + rh->auth_password = g_strdup(""); + rh->auth_username = g_strdup(""); + recent_add_remote_host(global_remote_opts.remote_host_opts.remote_host, rh); + + // We don't need to add the new entry to hostCombo since we only call + // this when accepting the dialog. + + // Tell the parent ManageInterfacesDialog we added this. + // XXX: If the remote hostname already exists in ManageInterfacesDialog, + // this doesn't remove it. Most of the time it won't, but there is the + // corner case of a host existing with empty (hence default, 2002) port, + // and then adding it a second time explicitly starting port 2002. + // Someone could bind rpcapd to multiple ports on the same host for + // some reason too, I suppose. emit remoteAdded(rlist, &global_remote_opts); } diff --git a/ui/qt/remote_capture_dialog.h b/ui/qt/remote_capture_dialog.h index 86ef0740..fee75d89 100644 --- a/ui/qt/remote_capture_dialog.h +++ b/ui/qt/remote_capture_dialog.h @@ -14,10 +14,8 @@ #ifdef HAVE_PCAP_REMOTE #include -#include #include "capture_opts.h" - namespace Ui { class RemoteCaptureDialog; } diff --git a/ui/qt/resolved_addresses_dialog.cpp b/ui/qt/resolved_addresses_dialog.cpp index dfe51c84..e4507294 100644 --- a/ui/qt/resolved_addresses_dialog.cpp +++ b/ui/qt/resolved_addresses_dialog.cpp @@ -12,8 +12,6 @@ #include "config.h" -#include - #include "file.h" #include "epan/addr_resolv.h" @@ -43,6 +41,11 @@ ResolvedAddressesDialog::ResolvedAddressesDialog(QWidget *parent, QString captur QStringList title_parts = QStringList() << tr("Resolved Addresses"); + copy_bt_ = ui->buttonBox->addButton(tr("Copy"), QDialogButtonBox::ActionRole); + + save_bt_ = ui->buttonBox->addButton(tr("Save as…"), QDialogButtonBox::ActionRole); + connect(save_bt_, &QPushButton::clicked, this, &ResolvedAddressesDialog::saveAs); + if (!captureFile.isEmpty()) { file_name_ = captureFile; title_parts << file_name_; @@ -86,7 +89,6 @@ ResolvedAddressesDialog::ResolvedAddressesDialog(QWidget *parent, QString captur ethTypeModel->setColumnToHide(0); ui->tblAddresses->setModel(ethTypeModel); ui->tblAddresses->resizeColumnsToContents(); - ui->tblAddresses->horizontalHeader()->setStretchLastSection(true); ui->tblAddresses->sortByColumn(1, Qt::AscendingOrder); ui->cmbDataType->addItems(ethModel->filterValues()); @@ -94,17 +96,19 @@ ResolvedAddressesDialog::ResolvedAddressesDialog(QWidget *parent, QString captur portTypeModel = new AStringListListSortFilterProxyModel(this); PortsModel * portModel = new PortsModel(this); portSortModel->setSourceModel(portModel); - portSortModel->setColumnAsNumeric(1); - portSortModel->setColumnsToFilter(QList() << 0 << 1); + portSortModel->setColumnAsNumeric(PORTS_COL_PORT); + portSortModel->setColumnsToFilter(QList() << PORTS_COL_NAME << PORTS_COL_PROTOCOL); portSortModel->setFilterCaseSensitivity(Qt::CaseInsensitive); portTypeModel->setSourceModel(portSortModel); - portTypeModel->setColumnToFilter(2); - portTypeModel->setColumnAsNumeric(1); + portTypeModel->setColumnToFilter(PORTS_COL_PROTOCOL); + portTypeModel->setColumnAsNumeric(PORTS_COL_PORT); ui->tblPorts->setModel(portTypeModel); ui->tblPorts->resizeColumnsToContents(); - ui->tblPorts->horizontalHeader()->setStretchLastSection(true); - ui->tblPorts->sortByColumn(1, Qt::AscendingOrder); + ui->tblPorts->sortByColumn(PORTS_COL_PORT, Qt::AscendingOrder); ui->cmbPortFilterType->addItems(portModel->filterValues()); + + tabChanged(ui->tabWidget->currentIndex()); + connect(ui->tabWidget, &QTabWidget::currentChanged, this, &ResolvedAddressesDialog::tabChanged); } ResolvedAddressesDialog::~ResolvedAddressesDialog() @@ -112,6 +116,27 @@ ResolvedAddressesDialog::~ResolvedAddressesDialog() delete ui; } +void ResolvedAddressesDialog::tabChanged(int index) +{ + QWidget *currentTab = ui->tabWidget->widget(index); + ResolvedAddressesView *addressView = nullptr; + if (currentTab != nullptr) { + addressView = currentTab->findChild(); + if (addressView != nullptr) { + QMenu* oldMenu = copy_bt_->menu(); + copy_bt_->setMenu(addressView->createCopyMenu(false, copy_bt_)); + if (oldMenu != nullptr) { + delete oldMenu; + } + } + } + foreach (QAbstractButton *button, ui->buttonBox->buttons()) { + if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ActionRole) { + button->setEnabled(addressView != nullptr); + } + } +} + void ResolvedAddressesDialog::on_cmbDataType_currentIndexChanged(int index) { if (! ethSortModel) @@ -146,10 +171,10 @@ void ResolvedAddressesDialog::on_cmbPortFilterType_currentIndexChanged(int index if (index == 0) { filter.clear(); - portTypeModel->setFilterType(AStringListListSortFilterProxyModel::FilterNone, 2); + portTypeModel->setFilterType(AStringListListSortFilterProxyModel::FilterNone, PORTS_COL_PROTOCOL); } else - portTypeModel->setFilterType(AStringListListSortFilterProxyModel::FilterByEquivalent, 2); + portTypeModel->setFilterType(AStringListListSortFilterProxyModel::FilterByEquivalent, PORTS_COL_PROTOCOL); portTypeModel->setFilter(filter); } @@ -202,3 +227,18 @@ void ResolvedAddressesDialog::fillBlocks() ui->plainTextEdit->moveCursor(QTextCursor::Start); setUpdatesEnabled(true); } + +void ResolvedAddressesDialog::saveAs() +{ + QWidget *currentTab = ui->tabWidget->currentWidget(); + if (currentTab == nullptr) { + return; + } + + ResolvedAddressesView *addressView = currentTab->findChild(); + if (addressView == nullptr) { + return; + } + + addressView->saveAs(); +} diff --git a/ui/qt/resolved_addresses_dialog.h b/ui/qt/resolved_addresses_dialog.h index dc6a9b64..3ce4698e 100644 --- a/ui/qt/resolved_addresses_dialog.h +++ b/ui/qt/resolved_addresses_dialog.h @@ -12,6 +12,8 @@ #include "geometry_state_dialog.h" +#include + #include class CaptureFile; @@ -41,6 +43,8 @@ private: Ui::ResolvedAddressesDialog *ui; QString file_name_; QString comment_; + QPushButton *copy_bt_; + QPushButton *save_bt_; AStringListListSortFilterProxyModel * ethSortModel; AStringListListSortFilterProxyModel * ethTypeModel; @@ -48,6 +52,10 @@ private: AStringListListSortFilterProxyModel * portTypeModel; void fillBlocks(); + +private slots: + void tabChanged(int index); + void saveAs(); }; #endif // RESOLVED_ADDRESSES_DIALOG_H diff --git a/ui/qt/resolved_addresses_dialog.ui b/ui/qt/resolved_addresses_dialog.ui index c77c5cc1..8cbbdc7f 100644 --- a/ui/qt/resolved_addresses_dialog.ui +++ b/ui/qt/resolved_addresses_dialog.ui @@ -39,19 +39,7 @@ - - - QAbstractItemView::NoEditTriggers - - - true - - - true - - - false - + @@ -76,13 +64,7 @@ - - - true - - - false - + @@ -233,6 +215,13 @@ + + + ResolvedAddressesView + QTableVew +
ui/qt/widgets/resolved_addresses_view.h
+
+
diff --git a/ui/qt/response_time_delay_dialog.cpp b/ui/qt/response_time_delay_dialog.cpp index f656525e..8943d579 100644 --- a/ui/qt/response_time_delay_dialog.cpp +++ b/ui/qt/response_time_delay_dialog.cpp @@ -50,7 +50,7 @@ bool register_response_time_delay_tables(const void *, void *value, void*) rtd_init, ResponseTimeDelayDialog::createRtdDialog); g_free(cfg_abbr); - return FALSE; + return false; } enum { diff --git a/ui/qt/rpc_service_response_time_dialog.cpp b/ui/qt/rpc_service_response_time_dialog.cpp index 7c7f70b3..fa5caf30 100644 --- a/ui/qt/rpc_service_response_time_dialog.cpp +++ b/ui/qt/rpc_service_response_time_dialog.cpp @@ -44,7 +44,7 @@ extern "C" { static void -dce_rpc_add_program(gpointer key_ptr, gpointer value_ptr, gpointer rsrtd_ptr) +dce_rpc_add_program(void *key_ptr, void *value_ptr, void *rsrtd_ptr) { RpcServiceResponseTimeDialog *rsrt_dlg = dynamic_cast((RpcServiceResponseTimeDialog *)rsrtd_ptr); if (!rsrt_dlg) return; @@ -56,7 +56,7 @@ dce_rpc_add_program(gpointer key_ptr, gpointer value_ptr, gpointer rsrtd_ptr) } static void -dce_rpc_find_versions(gpointer key_ptr, gpointer, gpointer rsrtd_ptr) +dce_rpc_find_versions(void *key_ptr, void *, void *rsrtd_ptr) { RpcServiceResponseTimeDialog *rsrt_dlg = dynamic_cast((RpcServiceResponseTimeDialog *)rsrtd_ptr); if (!rsrt_dlg) return; @@ -66,19 +66,19 @@ dce_rpc_find_versions(gpointer key_ptr, gpointer, gpointer rsrtd_ptr) } static void -onc_rpc_add_program(gpointer prog_ptr, gpointer value_ptr, gpointer rsrtd_ptr) +onc_rpc_add_program(void *prog_ptr, void *value_ptr, void *rsrtd_ptr) { RpcServiceResponseTimeDialog *rsrt_dlg = dynamic_cast((RpcServiceResponseTimeDialog *)rsrtd_ptr); if (!rsrt_dlg) return; - guint32 program = GPOINTER_TO_UINT(prog_ptr); + uint32_t program = GPOINTER_TO_UINT(prog_ptr); rpc_prog_info_value *value = (rpc_prog_info_value *) value_ptr; rsrt_dlg->addOncRpcProgram(program, value); } static void -onc_rpc_find_versions(const gchar *, ftenum_t , gpointer rpik_ptr, gpointer, gpointer rsrtd_ptr) +onc_rpc_find_versions(const char *, ftenum_t , void *rpik_ptr, void *, void *rsrtd_ptr) { RpcServiceResponseTimeDialog *rsrt_dlg = dynamic_cast((RpcServiceResponseTimeDialog *)rsrtd_ptr); if (!rsrt_dlg) return; @@ -89,7 +89,7 @@ onc_rpc_find_versions(const gchar *, ftenum_t , gpointer rpik_ptr, gpointer, gpo } static void -onc_rpc_count_procedures(const gchar *, ftenum_t , gpointer rpik_ptr, gpointer, gpointer rsrtd_ptr) +onc_rpc_count_procedures(const char *, ftenum_t , void *rpik_ptr, void *, void *rsrtd_ptr) { RpcServiceResponseTimeDialog *rsrt_dlg = dynamic_cast((RpcServiceResponseTimeDialog *)rsrtd_ptr); if (!rsrt_dlg) return; @@ -241,12 +241,12 @@ void RpcServiceResponseTimeDialog::addDceRpcProgramVersion(_guid_key *key) std::sort(versions_.begin(), versions_.end()); } -void RpcServiceResponseTimeDialog::addOncRpcProgram(guint32 program, _rpc_prog_info_value *value) +void RpcServiceResponseTimeDialog::addOncRpcProgram(uint32_t program, _rpc_prog_info_value *value) { onc_name_to_program_.insert(value->progname, program); } -void RpcServiceResponseTimeDialog::addOncRpcProgramVersion(guint32 program, guint32 version) +void RpcServiceResponseTimeDialog::addOncRpcProgramVersion(uint32_t program, uint32_t version) { if (onc_name_to_program_[program_combo_->currentText()] != program) return; @@ -262,7 +262,7 @@ void RpcServiceResponseTimeDialog::addOncRpcProgramVersion(guint32 program, guin } } -void RpcServiceResponseTimeDialog::updateOncRpcProcedureCount(guint32 program, guint32 version, int procedure) +void RpcServiceResponseTimeDialog::updateOncRpcProcedureCount(uint32_t program, uint32_t version, int procedure) { if (onc_name_to_program_[program_combo_->currentText()] != program) return; if (version_combo_->itemData(version_combo_->currentIndex()).toUInt() != version) return; @@ -374,7 +374,7 @@ void RpcServiceResponseTimeDialog::provideParameterData() { void *tap_data = NULL; const QString program_name = program_combo_->currentText(); - guint32 max_procs = 0; + uint32_t max_procs = 0; switch (dlg_type_) { case DceRpc: @@ -382,8 +382,8 @@ void RpcServiceResponseTimeDialog::provideParameterData() if (!dce_name_to_uuid_key_.contains(program_name)) return; guid_key *dkey = dce_name_to_uuid_key_[program_name]; - guint16 version = (guint16) version_combo_->itemData(version_combo_->currentIndex()).toUInt(); - dcerpc_sub_dissector *procs = dcerpc_get_proto_sub_dissector(&(dkey->guid), version); + uint16_t version = (uint16_t) version_combo_->itemData(version_combo_->currentIndex()).toUInt(); + const dcerpc_sub_dissector *procs = dcerpc_get_proto_sub_dissector(&(dkey->guid), version); if (!procs) return; dcerpcstat_tap_data_t *dtap_data = g_new0(dcerpcstat_tap_data_t, 1); @@ -406,7 +406,7 @@ void RpcServiceResponseTimeDialog::provideParameterData() rpcstat_tap_data_t *otap_data = g_new0(rpcstat_tap_data_t, 1); otap_data->program = onc_name_to_program_[program_name]; otap_data->prog = rpc_prog_name(otap_data->program); - otap_data->version = (guint32) version_combo_->itemData(version_combo_->currentIndex()).toUInt(); + otap_data->version = (uint32_t) version_combo_->itemData(version_combo_->currentIndex()).toUInt(); onc_rpc_num_procedures_ = -1; dissector_table_foreach ("rpc.call", onc_rpc_count_procedures, this); diff --git a/ui/qt/rpc_service_response_time_dialog.h b/ui/qt/rpc_service_response_time_dialog.h index d8f2ca53..4fa7306a 100644 --- a/ui/qt/rpc_service_response_time_dialog.h +++ b/ui/qt/rpc_service_response_time_dialog.h @@ -35,9 +35,9 @@ public: void addDceRpcProgram(_guid_key *key, struct _dcerpc_uuid_value *value); void addDceRpcProgramVersion(_guid_key *key); - void addOncRpcProgram(guint32 program, struct _rpc_prog_info_value *value); - void addOncRpcProgramVersion(guint32 program, guint32 version); - void updateOncRpcProcedureCount(guint32 program, guint32 version, int procedure); + void addOncRpcProgram(uint32_t program, struct _rpc_prog_info_value *value); + void addOncRpcProgramVersion(uint32_t program, uint32_t version); + void updateOncRpcProcedureCount(uint32_t program, uint32_t version, int procedure); void setDceRpcUuidAndVersion(struct _e_guid_t *uuid, int version); void setOncRpcProgramAndVersion(int program, int version); @@ -60,7 +60,7 @@ private: QMap dce_name_to_uuid_key_; // ONC-RPC - QMap onc_name_to_program_; + QMap onc_name_to_program_; int onc_rpc_num_procedures_; void clearVersionCombo(); diff --git a/ui/qt/rsa_keys_frame.cpp b/ui/qt/rsa_keys_frame.cpp index c784ab9c..429b3aaa 100644 --- a/ui/qt/rsa_keys_frame.cpp +++ b/ui/qt/rsa_keys_frame.cpp @@ -63,10 +63,10 @@ RsaKeysFrame::~RsaKeysFrame() delete ui; } -gboolean RsaKeysFrame::verifyKey(const char *uri, const char *password, gboolean *need_password, QString &error) +bool RsaKeysFrame::verifyKey(const char *uri, const char *password, bool *need_password, QString &error) { char *error_c = NULL; - gboolean key_ok = secrets_verify_key(qPrintable(uri), qPrintable(password), need_password, &error_c); + bool key_ok = secrets_verify_key(qPrintable(uri), qPrintable(password), need_password, &error_c); error = error_c ? error_c : ""; g_free(error_c); return key_ok; @@ -120,7 +120,7 @@ void RsaKeysFrame::on_addItemButton_clicked() } // Validate the token, is a PIN needed? - gboolean key_ok = false, needs_pin = true; + bool key_ok = false, needs_pin = true; QString error; if (!item.startsWith("pkcs11:")) { // For keys other than pkcs11, try to verify the key without password. @@ -168,7 +168,7 @@ void RsaKeysFrame::on_addFileButton_clicked() // Try to load the key as unencrypted key file. If any errors occur, assume // an encrypted key file and prompt for a password. QString password, error; - gboolean key_ok = secrets_verify_key(qPrintable(file), NULL, NULL, NULL); + bool key_ok = secrets_verify_key(qPrintable(file), NULL, NULL, NULL); while (!key_ok) { QString msg; if (!error.isEmpty()) { diff --git a/ui/qt/rsa_keys_frame.h b/ui/qt/rsa_keys_frame.h index fae40e2f..c2dbccd2 100644 --- a/ui/qt/rsa_keys_frame.h +++ b/ui/qt/rsa_keys_frame.h @@ -40,7 +40,7 @@ private: UatModel *rsa_keys_model_; UatModel *pkcs11_libs_model_; - gboolean verifyKey(const char *uri, const char *password, gboolean *need_password, QString &error); + bool verifyKey(const char *uri, const char *password, bool *need_password, QString &error); void addKey(const QString &uri, const QString &password); private slots: diff --git a/ui/qt/rtp_analysis_dialog.cpp b/ui/qt/rtp_analysis_dialog.cpp index d4eafd6c..9dcb910c 100644 --- a/ui/qt/rtp_analysis_dialog.cpp +++ b/ui/qt/rtp_analysis_dialog.cpp @@ -193,22 +193,16 @@ public: switch (treeWidget()->sortColumn()) { case (packet_col_): return frame_num_ < other_row->frame_num_; - break; case (sequence_col_): return sequence_num_ < other_row->sequence_num_; - break; case (delta_col_): return delta_ < other_row->delta_; - break; case (jitter_col_): return jitter_ < other_row->jitter_; - break; case (skew_col_): return skew_ < other_row->skew_; - break; case (bandwidth_col_): return bandwidth_ < other_row->bandwidth_; - break; default: break; } @@ -278,6 +272,10 @@ RtpAnalysisDialog::RtpAnalysisDialog(QWidget &parent, CaptureFile &cf) : graph_ctx_menu_.addAction(ui->actionSaveGraph); + ui->streamGraph->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->streamGraph, &QCustomPlot::customContextMenuRequested, this, + &RtpAnalysisDialog::showGraphMenu); + ui->streamGraph->xAxis->setLabel("Arrival Time"); ui->streamGraph->yAxis->setLabel("Value (ms)"); @@ -967,16 +965,14 @@ bool RtpAnalysisDialog::eventFilter(QObject *, QEvent *event) return false; } -void RtpAnalysisDialog::graphClicked(QMouseEvent *event) +void RtpAnalysisDialog::showGraphMenu(const QPoint &pos) +{ + graph_ctx_menu_.popup(ui->streamGraph->mapToGlobal(pos)); +} + +void RtpAnalysisDialog::graphClicked(QMouseEvent*) { updateWidgets(); - if (event->button() == Qt::RightButton) { -#if QT_VERSION >= QT_VERSION_CHECK(6, 0 ,0) - graph_ctx_menu_.popup(event->globalPosition().toPoint()); -#else - graph_ctx_menu_.popup(event->globalPos()); -#endif - } } void RtpAnalysisDialog::clearLayout(QLayout *layout) diff --git a/ui/qt/rtp_analysis_dialog.h b/ui/qt/rtp_analysis_dialog.h index a7fcfced..b16eccd3 100644 --- a/ui/qt/rtp_analysis_dialog.h +++ b/ui/qt/rtp_analysis_dialog.h @@ -12,7 +12,6 @@ #include -#include #include #include "epan/address.h" @@ -118,6 +117,7 @@ private slots: void on_actionSaveGraph_triggered(); void on_buttonBox_helpRequested(); void showStreamMenu(QPoint pos); + void showGraphMenu(const QPoint &pos); void graphClicked(QMouseEvent *event); void closeTab(int index); void rowCheckboxChanged(int checked); @@ -135,7 +135,7 @@ private: int tab_seq; QVector tabs_; - QMultiHash tab_hash_; + QMultiHash tab_hash_; QToolButton *player_button_; diff --git a/ui/qt/rtp_audio_stream.cpp b/ui/qt/rtp_audio_stream.cpp index 5ceb809f..8950c8df 100644 --- a/ui/qt/rtp_audio_stream.cpp +++ b/ui/qt/rtp_audio_stream.cpp @@ -128,7 +128,7 @@ void RtpAudioStream::addRtpPacket(const struct _packet_info *pinfo, const struct rtp_packet_t *rtp_packet = g_new0(rtp_packet_t, 1); rtp_packet->info = (struct _rtp_info *) g_memdup2(rtp_info, sizeof(struct _rtp_info)); if (rtp_info->info_all_data_present && (rtp_info->info_payload_len != 0)) { - rtp_packet->payload_data = (guint8 *) g_memdup2(&(rtp_info->info_data[rtp_info->info_payload_offset]), + rtp_packet->payload_data = (uint8_t *) g_memdup2(&(rtp_info->info_data[rtp_info->info_payload_offset]), rtp_info->info_payload_len); } @@ -258,21 +258,21 @@ void RtpAudioStream::decodeAudio(QAudioDeviceInfo out_device) { // XXX This is more messy than it should be. - gint32 resample_buff_bytes = 0x1000; + int32_t resample_buff_bytes = 0x1000; SAMPLE *resample_buff = (SAMPLE *) g_malloc(resample_buff_bytes); char *write_buff = NULL; qint64 write_bytes = 0; unsigned int channels = 0; unsigned int sample_rate = 0; - guint32 last_sequence = 0; - guint32 last_sequence_w = 0; // Last sequence number we wrote data + uint32_t last_sequence = 0; + uint32_t last_sequence_w = 0; // Last sequence number we wrote data double rtp_time_prev = 0.0; double arrive_time_prev = 0.0; double pack_period = 0.0; double start_time = 0.0; double start_rtp_time = 0.0; - guint64 start_timestamp = 0; + uint64_t start_timestamp = 0; size_t decoded_bytes_prev = 0; unsigned int audio_resampler_input_rate = 0; @@ -430,7 +430,7 @@ void RtpAudioStream::decodeAudio(QAudioDeviceInfo out_device) // Buffer is in SAMPLEs spx_uint32_t in_len = (spx_uint32_t) (write_bytes / SAMPLE_BYTES); // Output is audio_out_rate_/sample_rate bigger than input - spx_uint32_t out_len = (spx_uint32_t) ((guint64)in_len * audio_out_rate_ / sample_rate); + spx_uint32_t out_len = (spx_uint32_t) ((uint64_t)in_len * audio_out_rate_ / sample_rate); resample_buff = resizeBufferIfNeeded(resample_buff, &resample_buff_bytes, out_len * SAMPLE_BYTES); if (audio_resampler && @@ -472,13 +472,13 @@ void RtpAudioStream::decodeAudio(QAudioDeviceInfo out_device) void RtpAudioStream::decodeVisual() { spx_uint32_t read_len = 0; - gint32 read_buff_bytes = VISUAL_BUFF_BYTES; + int32_t read_buff_bytes = VISUAL_BUFF_BYTES; SAMPLE *read_buff = (SAMPLE *) g_malloc(read_buff_bytes); - gint32 resample_buff_bytes = VISUAL_BUFF_BYTES; + int32_t resample_buff_bytes = VISUAL_BUFF_BYTES; SAMPLE *resample_buff = (SAMPLE *) g_malloc(resample_buff_bytes); unsigned int sample_no = 0; spx_uint32_t out_len; - guint32 frame_num; + uint32_t frame_num; rtp_frame_type type; speex_resampler_set_rate(visual_resampler_, audio_out_rate_, visual_sample_rate_); @@ -486,7 +486,7 @@ void RtpAudioStream::decodeVisual() // Loop over every frame record // readFrameSamples() maintains size of buffer for us while (audio_file_->readFrameSamples(&read_buff_bytes, &read_buff, &read_len, &frame_num, &type)) { - out_len = (spx_uint32_t)(((guint64)read_len * visual_sample_rate_ ) / audio_out_rate_); + out_len = (spx_uint32_t)(((uint64_t)read_len * visual_sample_rate_ ) / audio_out_rate_); if (type == RTP_FRAME_AUDIO) { // We resample only audio samples @@ -538,14 +538,14 @@ const QVector RtpAudioStream::visualTimestamps(bool relative) // Scale the height of the waveform to global scale (max_sample_val_used_) // and adjust its Y offset so that they overlap slightly (stack_offset_). -static const double stack_offset_ = G_MAXINT16 / 3; +static const double stack_offset_ = INT16_MAX / 3; const QVector RtpAudioStream::visualSamples(int y_offset) { QVector adj_samples; double scaled_offset = y_offset * stack_offset_; for (int i = 0; i < visual_samples_.size(); i++) { if (SAMPLE_NaN != visual_samples_[i]) { - adj_samples.append(((double)visual_samples_[i] * G_MAXINT16 / max_sample_val_used_) + scaled_offset); + adj_samples.append(((double)visual_samples_[i] * INT16_MAX / max_sample_val_used_) + scaled_offset); } else { // Convert to break in graph line adj_samples.append(qQNaN()); @@ -701,8 +701,8 @@ const QString RtpAudioStream::formatDescription(const QAudioFormat &format) QString RtpAudioStream::getIDAsQString() { - gchar *src_addr_str = address_to_display(NULL, &id_.src_addr); - gchar *dst_addr_str = address_to_display(NULL, &id_.dst_addr); + char *src_addr_str = address_to_display(NULL, &id_.src_addr); + char *dst_addr_str = address_to_display(NULL, &id_.dst_addr); QString str = QString("%1:%2 - %3:%4 %5") .arg(src_addr_str) .arg(id_.src_port) @@ -843,7 +843,7 @@ void RtpAudioStream::stopPlaying() if (audio_output_) { if (audio_output_->state() == QAudio::StoppedState) { // Looks like "delayed" QTBUG-6548 - // It may happen that stream is stopped, but no signal emited + // It may happen that stream is stopped, but no signal emitted // Probably triggered by some issue in sound system which is not // handled by Qt correctly outputStateChanged(QAudio::StoppedState); @@ -905,7 +905,7 @@ void RtpAudioStream::delayedStopStream() audio_output_->stop(); } -SAMPLE *RtpAudioStream::resizeBufferIfNeeded(SAMPLE *buff, gint32 *buff_bytes, qint64 requested_size) +SAMPLE *RtpAudioStream::resizeBufferIfNeeded(SAMPLE *buff, int32_t *buff_bytes, qint64 requested_size) { if (requested_size > *buff_bytes) { while ((requested_size > *buff_bytes)) diff --git a/ui/qt/rtp_audio_stream.h b/ui/qt/rtp_audio_stream.h index 1ddeaacd..e7fd78d5 100644 --- a/ui/qt/rtp_audio_stream.h +++ b/ui/qt/rtp_audio_stream.h @@ -14,8 +14,6 @@ #ifdef QT_MULTIMEDIA_LIB -#include - #include #include #include @@ -154,7 +152,7 @@ public: void seekPlaying(qint64 samples); void setStereoRequired(bool stereo_required) { stereo_required_ = stereo_required; } qint16 getMaxSampleValue() { return max_sample_val_; } - void setMaxSampleValue(gint16 max_sample_val) { max_sample_val_used_ = max_sample_val; } + void setMaxSampleValue(int16_t max_sample_val) { max_sample_val_used_ = max_sample_val; } void seekSample(qint64 samples); qint64 readSample(SAMPLE *sample); qint64 getLeadSilenceSamples() { return prepend_samples_; } @@ -163,7 +161,7 @@ public: double getEndOfSilenceTime() { return (double)getEndOfSilenceSample() / (double)playRate(); } qint64 convertTimeToSamples(double time) { return (qint64)(time * playRate()); } bool savePayload(QIODevice *file); - guint getHash() { return rtpstream_id_to_hash(&(id_)); } + unsigned getHash() { return rtpstream_id_to_hash(&(id_)); } rtpstream_id_t *getID() { return &(id_); } QString getIDAsQString(); rtpstream_info_t *getStreamInfo() { return &rtpstream_; } @@ -223,7 +221,7 @@ private: quint32 calculateAudioOutRate(QAudioDeviceInfo out_device, unsigned int sample_rate, unsigned int requested_out_rate); #endif void decodeVisual(); - SAMPLE *resizeBufferIfNeeded(SAMPLE *buff, gint32 *buff_bytes, qint64 requested_size); + SAMPLE *resizeBufferIfNeeded(SAMPLE *buff, int32_t *buff_bytes, qint64 requested_size); private slots: void outputStateChanged(QAudio::State new_state); diff --git a/ui/qt/rtp_player_dialog.cpp b/ui/qt/rtp_player_dialog.cpp index 60418cc8..889dde2a 100644 --- a/ui/qt/rtp_player_dialog.cpp +++ b/ui/qt/rtp_player_dialog.cpp @@ -135,7 +135,6 @@ public: default: // Fall back to string comparison return QTreeWidgetItem::operator <(other); - break; } } }; @@ -206,7 +205,15 @@ RtpPlayerDialog::RtpPlayerDialog(QWidget &parent, CaptureFile &cf, bool capture_ graph_ctx_menu_->addAction(ui->actionGoToSetupPacketPlot); set_action_shortcuts_visible_in_context_menu(graph_ctx_menu_->actions()); + ui->audioPlot->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->audioPlot, &QCustomPlot::customContextMenuRequested, this, &RtpPlayerDialog::showGraphContextMenu); + ui->streamTreeWidget->setMouseTracking(true); + mouse_update_timer_ = new QTimer(this); + mouse_update_timer_->setSingleShot(true); + mouse_update_timer_->setInterval(10); + connect(mouse_update_timer_, &QTimer::timeout, this, &RtpPlayerDialog::mouseMoveUpdate); + connect(ui->streamTreeWidget, &QTreeWidget::itemEntered, this, &RtpPlayerDialog::itemEntered); connect(ui->audioPlot, &QCustomPlot::mouseMove, this, &RtpPlayerDialog::mouseMovePlot); @@ -533,7 +540,7 @@ void RtpPlayerDialog::createPlot(bool rescale_axes) bool legend_inserted_silences = false; bool relative_timestamps = !ui->todCheckBox->isChecked(); int row_count = ui->streamTreeWidget->topLevelItemCount(); - gint16 total_max_sample_value = 1; + int16_t total_max_sample_value = 1; ui->audioPlot->clearGraphs(); @@ -547,7 +554,7 @@ void RtpPlayerDialog::createPlot(bool rescale_axes) for (int row = 0; row < row_count; row++) { QTreeWidgetItem *ti = ui->streamTreeWidget->topLevelItem(row); RtpAudioStream *audio_stream = ti->data(stream_data_col_, Qt::UserRole).value(); - gint16 max_sample_value = audio_stream->getMaxSampleValue(); + int16_t max_sample_value = audio_stream->getMaxSampleValue(); if (max_sample_value > total_max_sample_value) { total_max_sample_value = max_sample_value; @@ -673,7 +680,7 @@ void RtpPlayerDialog::fillTappedColumns() // true just for first stream bool is_first = true; - // Get all rows, immutable list. Later changes in rows migth reorder them + // Get all rows, immutable list. Later changes in rows might reorder them QList items = ui->streamTreeWidget->findItems( QString("*"), Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive); @@ -887,6 +894,8 @@ void RtpPlayerDialog::setMarkers() void RtpPlayerDialog::showEvent(QShowEvent *) { + // We could use loadSplitterState(ui->splitter) instead of always + // resetting the plot size to 75% QList split_sizes = ui->splitter->sizes(); int tot_size = split_sizes[0] + split_sizes[1]; int plot_size = tot_size * 3 / 4; @@ -1130,22 +1139,34 @@ void RtpPlayerDialog::itemEntered(QTreeWidgetItem *item, int column _U_) void RtpPlayerDialog::mouseMovePlot(QMouseEvent *event) { + // The calculations are expensive, so just store the position and + // calculate no more than once per some interval. (On Linux the + // QMouseEvents can be sent absurdly often, every 25 microseconds!) + mouse_pos_ = event->pos(); + if (!mouse_update_timer_->isActive()) { + mouse_update_timer_->start(); + } +} + +void RtpPlayerDialog::mouseMoveUpdate() +{ + // findItemByCoords is expensive (because of calling pointDistance), + // and updateHintLabel calls it as well via getHoveredPacket. Some + // way to only perform the distance calculations once would be better. updateHintLabel(); - QTreeWidgetItem *ti = findItemByCoords(event->pos()); + QTreeWidgetItem *ti = findItemByCoords(mouse_pos_); handleItemHighlight(ti, true); } -void RtpPlayerDialog::graphClicked(QMouseEvent *event) +void RtpPlayerDialog::showGraphContextMenu(const QPoint &pos) +{ + graph_ctx_menu_->popup(ui->audioPlot->mapToGlobal(pos)); +} + +void RtpPlayerDialog::graphClicked(QMouseEvent*) { updateWidgets(); - if (event->button() == Qt::RightButton) { -#if QT_VERSION >= QT_VERSION_CHECK(6, 0 ,0) - graph_ctx_menu_->popup(event->globalPosition().toPoint()); -#else - graph_ctx_menu_->popup(event->globalPos()); -#endif - } } void RtpPlayerDialog::graphDoubleClicked(QMouseEvent *event) @@ -1429,7 +1450,7 @@ void RtpPlayerDialog::on_playButton_clicked() #endif marker_stream_->start(new AudioSilenceGenerator(marker_stream_)); // It may happen that stream play is finished before all others are started - // therefore we do not use playing_streams_ there, but separate temporarly + // therefore we do not use playing_streams_ there, but separate temporarily // list. It avoids access element/remove element race condition. streams_to_start = playing_streams_; for( int i = 0; iwrite((const char *)&data16, 2); if (nchars != 2) { return -1; } /* WAVE fmt header, BitsPerSample */ - data16 = (gint16)sizeof(SAMPLE) * 8; + data16 = (int16_t)sizeof(SAMPLE) * 8; nchars = save_file->write((const char *)&data16, 2); if (nchars != 2) { return -1; @@ -2418,12 +2439,12 @@ bool RtpPlayerDialog::writeAudioStreamsSamples(QFile *out_file, QVector> 8); - pd[1] = (guint8)(sample >> 0); + pd[0] = (uint8_t)(sample >> 8); + pd[1] = (uint8_t)(sample >> 0); } else { // just copy - pd[1] = (guint8)(sample >> 8); - pd[0] = (guint8)(sample >> 0); + pd[1] = (uint8_t)(sample >> 8); + pd[0] = (uint8_t)(sample >> 0); } read = true; } else { diff --git a/ui/qt/rtp_player_dialog.h b/ui/qt/rtp_player_dialog.h index 5fba67db..0180e78f 100644 --- a/ui/qt/rtp_player_dialog.h +++ b/ui/qt/rtp_player_dialog.h @@ -12,7 +12,6 @@ #include "config.h" -#include #include #include "ui/rtp_stream.h" @@ -146,6 +145,8 @@ private slots: void updateWidgets(); void itemEntered(QTreeWidgetItem *item, int column); void mouseMovePlot(QMouseEvent *event); + void mouseMoveUpdate(); + void showGraphContextMenu(const QPoint &pos); void graphClicked(QMouseEvent *event); void graphDoubleClicked(QMouseEvent *event); void plotClicked(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event); @@ -245,11 +246,13 @@ private: QToolButton *analyze_btn_; QPushButton *prepare_btn_; QPushButton *export_btn_; - QMultiHash stream_hash_; + QMultiHash stream_hash_; bool block_redraw_; int lock_ui_; bool read_capture_enabled_; double silence_skipped_time_; + QTimer *mouse_update_timer_; + QPoint mouse_pos_; // const QString streamKey(const rtpstream_info_t *rtpstream); // const QString streamKey(const packet_info *pinfo, const struct _rtp_info *rtpinfo); diff --git a/ui/qt/rtp_stream_dialog.cpp b/ui/qt/rtp_stream_dialog.cpp index 6b28a837..3d3a1c70 100644 --- a/ui/qt/rtp_stream_dialog.cpp +++ b/ui/qt/rtp_stream_dialog.cpp @@ -269,7 +269,6 @@ public: rtpstream_info_calc_free(&calc1); rtpstream_info_calc_free(&calc2); return ret; - break; case min_delta_col_: return stream_info_->rtp_stats.min_delta < other_rstwi.stream_info_->rtp_stats.min_delta; case mean_delta_col_: @@ -290,14 +289,14 @@ public: return QTreeWidgetItem::operator <(other); } - void setTOD(gboolean tod) + void setTOD(bool tod) { tod_ = tod; } private: rtpstream_info_t *stream_info_; - gboolean tod_; + bool tod_; }; @@ -586,9 +585,9 @@ void RtpStreamDialog::updateStreams() // string_list is reverse ordered, so we must add // just first "to_insert_count" of streams GList *cur_stream = g_list_first(tapinfo_.strinfo_list); - guint tap_len = g_list_length(tapinfo_.strinfo_list); - guint tree_len = static_cast(ui->streamTreeWidget->topLevelItemCount()); - guint to_insert_count = tap_len - tree_len; + unsigned tap_len = g_list_length(tapinfo_.strinfo_list); + unsigned tree_len = static_cast(ui->streamTreeWidget->topLevelItemCount()); + unsigned to_insert_count = tap_len - tree_len; // Add any missing items while (cur_stream && cur_stream->data && to_insert_count) { @@ -797,8 +796,8 @@ void RtpStreamDialog::on_actionExportAsRtpDump_triggered() save_file, "RTPDump Format (*.rtp)", &extension); if (file_name.length() > 0) { - gchar *dest_file = qstring_strdup(file_name); - gboolean save_ok = rtpstream_save(&tapinfo_, cap_file_.capFile(), stream_info, dest_file); + char *dest_file = qstring_strdup(file_name); + bool save_ok = rtpstream_save(&tapinfo_, cap_file_.capFile(), stream_info, dest_file); g_free(dest_file); // else error dialog? if (save_ok) { diff --git a/ui/qt/sctp_all_assocs_dialog.cpp b/ui/qt/sctp_all_assocs_dialog.cpp index c8208d66..2d04e69f 100644 --- a/ui/qt/sctp_all_assocs_dialog.cpp +++ b/ui/qt/sctp_all_assocs_dialog.cpp @@ -49,13 +49,9 @@ void SCTPAllAssocsDialog::fillTable() int numAssocs; ui->assocList->setColumnHidden(0, true); - ui->assocList->setColumnWidth(1, 85); - ui->assocList->setColumnWidth(2, 85); - ui->assocList->setColumnWidth(3, 150); - ui->assocList->setColumnWidth(4, 150); sctp_assocs = sctp_stat_get_info(); - if (sctp_assocs->is_registered == FALSE) { + if (sctp_assocs->is_registered == false) { register_tap_listener_sctp_stat(); /* (redissect all packets) */ cf_retap_packets(cap_file_); @@ -63,19 +59,43 @@ void SCTPAllAssocsDialog::fillTable() numAssocs = 0; ui->assocList->setRowCount(static_cast(g_list_length(sctp_assocs->assoc_info_list))); + /* https://doc.qt.io/qt-6/qtablewidget.html#setItem suggests turning + * off sorting before setting several items of a row in a loop. + */ + bool sorting = ui->assocList->isSortingEnabled(); + if (sorting) { + ui->assocList->setSortingEnabled(false); + } list = g_list_first(sctp_assocs->assoc_info_list); + QTableWidgetItem *item; while (list) { assinfo = gxx_list_data(const sctp_assoc_info_t*, list); - ui->assocList->setItem(numAssocs, 0, new QTableWidgetItem(QString("%1").arg(assinfo->assoc_id))); - ui->assocList->setItem(numAssocs, 1, new QTableWidgetItem(QString("%1").arg(assinfo->port1))); - ui->assocList->setItem(numAssocs, 2, new QTableWidgetItem(QString("%1").arg(assinfo->port2))); - ui->assocList->setItem(numAssocs, 3, new QTableWidgetItem(QString("%1").arg(assinfo->n_packets))); - ui->assocList->setItem(numAssocs, 4, new QTableWidgetItem(QString("%1").arg(assinfo->n_data_chunks))); - ui->assocList->setItem(numAssocs, 5, new QTableWidgetItem(QString("%1").arg(assinfo->n_data_bytes))); + item = new QTableWidgetItem(); + item->setData(Qt::DisplayRole, assinfo->assoc_id); + ui->assocList->setItem(numAssocs, 0, item); + item = new QTableWidgetItem(); + item->setData(Qt::DisplayRole, assinfo->port1); + ui->assocList->setItem(numAssocs, 1, item); + item = new QTableWidgetItem(); + item->setData(Qt::DisplayRole, assinfo->port2); + ui->assocList->setItem(numAssocs, 2, item); + item = new QTableWidgetItem(); + item->setData(Qt::DisplayRole, assinfo->n_packets); + ui->assocList->setItem(numAssocs, 3, item); + item = new QTableWidgetItem(); + item->setData(Qt::DisplayRole, assinfo->n_data_chunks); + ui->assocList->setItem(numAssocs, 4, item); + item = new QTableWidgetItem(); + item->setData(Qt::DisplayRole, assinfo->n_data_bytes); + ui->assocList->setItem(numAssocs, 5, item); list = gxx_list_next(list); numAssocs++; } + if (sorting) { + ui->assocList->setSortingEnabled(true); + } + ui->assocList->resizeColumnsToContents(); ui->analyseButton->setEnabled(false); ui->setFilterButton->setEnabled(false); connect(ui->assocList, SIGNAL(itemSelectionChanged()), this, SLOT(getSelectedItem())); diff --git a/ui/qt/sctp_all_assocs_dialog.h b/ui/qt/sctp_all_assocs_dialog.h index c29c8e9b..93ebf3f9 100644 --- a/ui/qt/sctp_all_assocs_dialog.h +++ b/ui/qt/sctp_all_assocs_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include #include @@ -48,7 +46,7 @@ private slots: private: Ui::SCTPAllAssocsDialog *ui; capture_file *cap_file_; - guint16 selected_assoc_id; + uint16_t selected_assoc_id; signals: diff --git a/ui/qt/sctp_assoc_analyse_dialog.cpp b/ui/qt/sctp_assoc_analyse_dialog.cpp index c6b4b11a..89a3d603 100644 --- a/ui/qt/sctp_assoc_analyse_dialog.cpp +++ b/ui/qt/sctp_assoc_analyse_dialog.cpp @@ -54,7 +54,7 @@ const sctp_assoc_info_t* SCTPAssocAnalyseDialog::findAssocForPacket(capture_file bool frame_found = false; fdata = cf->current_frame; - if (sctp_stat_get_info()->is_registered == FALSE) { + if (sctp_stat_get_info()->is_registered == false) { register_tap_listener_sctp_stat(); /* (redissect all packets) */ cf_retap_packets(cf); @@ -65,11 +65,11 @@ const sctp_assoc_info_t* SCTPAssocAnalyseDialog::findAssocForPacket(capture_file assoc = gxx_list_data(const sctp_assoc_info_t*, list); framelist = g_list_first(assoc->frame_numbers); - guint32 fn; + uint32_t fn; while (framelist) { fn = GPOINTER_TO_UINT(framelist->data); if (fn == fdata->num) { - frame_found = TRUE; + frame_found = true; break; } framelist = gxx_list_next(framelist); @@ -89,7 +89,7 @@ const sctp_assoc_info_t* SCTPAssocAnalyseDialog::findAssocForPacket(capture_file return Q_NULLPTR; } -const _sctp_assoc_info* SCTPAssocAnalyseDialog::findAssoc(QWidget *parent, guint16 assoc_id) +const _sctp_assoc_info* SCTPAssocAnalyseDialog::findAssoc(QWidget *parent, uint16_t assoc_id) { const sctp_assoc_info_t* result = get_sctp_assoc_info(assoc_id); if (result) return result; diff --git a/ui/qt/sctp_assoc_analyse_dialog.h b/ui/qt/sctp_assoc_analyse_dialog.h index ec361f4c..335abfbf 100644 --- a/ui/qt/sctp_assoc_analyse_dialog.h +++ b/ui/qt/sctp_assoc_analyse_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include #include @@ -44,7 +42,7 @@ public: void fillTabs(const _sctp_assoc_info* selected_assoc); static const _sctp_assoc_info* findAssocForPacket(capture_file* cf); - static const _sctp_assoc_info* findAssoc(QWidget *parent, guint16 assoc_id); + static const _sctp_assoc_info* findAssoc(QWidget *parent, uint16_t assoc_id); public slots: void setCaptureFile(capture_file *cf) { cap_file_ = cf; } @@ -63,7 +61,7 @@ private slots: private: Ui::SCTPAssocAnalyseDialog *ui; - guint16 selected_assoc_id; + uint16_t selected_assoc_id; capture_file *cap_file_; void openGraphDialog(int direction); void openGraphByteDialog(int direction); diff --git a/ui/qt/sctp_chunk_statistics_dialog.cpp b/ui/qt/sctp_chunk_statistics_dialog.cpp index f77c2edd..20098a7b 100644 --- a/ui/qt/sctp_chunk_statistics_dialog.cpp +++ b/ui/qt/sctp_chunk_statistics_dialog.cpp @@ -62,7 +62,7 @@ SCTPChunkStatisticsDialog::~SCTPChunkStatisticsDialog() void SCTPChunkStatisticsDialog::initializeChunkMap() { struct chunkTypes temp; - gchar buf[16]; + char buf[16]; for (int i = 0; i < 256; i++) { temp.id = i; @@ -94,7 +94,7 @@ void SCTPChunkStatisticsDialog::fillTable(bool all, const sctp_assoc_info_t *sel return; } uat_t *uat = prefs_get_uat_value(pref); - gchar* fname = uat_get_actual_filename(uat,TRUE); + char* fname = uat_get_actual_filename(uat,true); bool init = false; if (!fname) { @@ -220,7 +220,7 @@ void SCTPChunkStatisticsDialog::on_pushButton_clicked() uat_t *uat = prefs_get_uat_value(pref); - gchar* fname = uat_get_actual_filename(uat,TRUE); + char* fname = uat_get_actual_filename(uat,true); if (!fname) { return; @@ -228,7 +228,7 @@ void SCTPChunkStatisticsDialog::on_pushButton_clicked() fp = ws_fopen(fname,"w"); if (!fp && errno == ENOENT) { - gchar *pf_dir_path = NULL; + char *pf_dir_path = NULL; if (create_persconffile_dir(&pf_dir_path) != 0) { g_free (pf_dir_path); return; @@ -251,7 +251,7 @@ void SCTPChunkStatisticsDialog::on_pushButton_clicked() snprintf(str, sizeof str, "\"%d\",\"%s\",\"%s\"\n", tempChunk.id, tempChunk.name, tempChunk.hide==0?"Show":"Hide"); fputs(str, fp); void *rec = g_malloc0(uat->record_size); - uat_add_record(uat, rec, TRUE); + uat_add_record(uat, rec, true); if (uat->free_cb) { uat->free_cb(rec); } @@ -287,7 +287,7 @@ void SCTPChunkStatisticsDialog::on_actionHideChunkType_triggered() void SCTPChunkStatisticsDialog::on_actionChunkTypePreferences_triggered() { - gchar* err = NULL; + char* err = NULL; pref_t *pref = prefs_find_preference(prefs_find_module("sctp"),"statistics_chunk_types"); if (!pref) { diff --git a/ui/qt/sctp_chunk_statistics_dialog.h b/ui/qt/sctp_chunk_statistics_dialog.h index aa45f752..1c18dad9 100644 --- a/ui/qt/sctp_chunk_statistics_dialog.h +++ b/ui/qt/sctp_chunk_statistics_dialog.h @@ -11,7 +11,6 @@ #define SCTP_CHUNK_STATISTICS_DIALOG_H #include -#include #include #include @@ -62,7 +61,7 @@ signals: private: Ui::SCTPChunkStatisticsDialog *ui; - guint16 selected_assoc_id; + uint16_t selected_assoc_id; capture_file *cap_file_; QMenu ctx_menu_; QPoint selected_point; diff --git a/ui/qt/sctp_graph_arwnd_dialog.cpp b/ui/qt/sctp_graph_arwnd_dialog.cpp index 2734f28a..92c254fe 100644 --- a/ui/qt/sctp_graph_arwnd_dialog.cpp +++ b/ui/qt/sctp_graph_arwnd_dialog.cpp @@ -63,8 +63,8 @@ void SCTPGraphArwndDialog::drawArwndGraph(const sctp_assoc_info_t *selected_asso struct sack_chunk_header *sack_header; struct nr_sack_chunk_header *nr_sack_header; tsn_t *tsn; - guint8 type; - guint32 arwnd=0; + uint8_t type; + uint32_t arwnd=0; if (direction == 1) { listSACK = g_list_last(selected_assoc->sack1); @@ -161,7 +161,7 @@ void SCTPGraphArwndDialog::graphClicked(QCPAbstractPlottable* plottable, int, QM } } if (cap_file_ && frame_num > 0) { - cf_goto_frame(cap_file_, frame_num); + cf_goto_frame(cap_file_, frame_num, false); } ui->hintLabel->setText(QString(tr("Graph %1: a_rwnd=%2 Time=%3 secs ")) diff --git a/ui/qt/sctp_graph_arwnd_dialog.h b/ui/qt/sctp_graph_arwnd_dialog.h index c74d43d3..7c30b84d 100644 --- a/ui/qt/sctp_graph_arwnd_dialog.h +++ b/ui/qt/sctp_graph_arwnd_dialog.h @@ -11,7 +11,6 @@ #define SCTP_GRAPH_ARWND_DIALOG_H #include -#include #include "cfile.h" @@ -46,13 +45,13 @@ private slots: private: Ui::SCTPGraphArwndDialog *ui; - guint16 selected_assoc_id; + uint16_t selected_assoc_id; capture_file *cap_file_; int frame_num; int direction; - guint32 startArwnd; + uint32_t startArwnd; QVector xa, ya; - QVector fa; + QVector fa; // QVector typeStrings; void drawGraph(const _sctp_assoc_info *selected_assoc); diff --git a/ui/qt/sctp_graph_byte_dialog.cpp b/ui/qt/sctp_graph_byte_dialog.cpp index bd91c088..660a70d1 100644 --- a/ui/qt/sctp_graph_byte_dialog.cpp +++ b/ui/qt/sctp_graph_byte_dialog.cpp @@ -61,9 +61,9 @@ void SCTPGraphByteDialog::drawBytesGraph(const sctp_assoc_info_t *selected_assoc { GList *listTSN = Q_NULLPTR, *tlist = Q_NULLPTR; tsn_t *tsn = Q_NULLPTR; - guint8 type; - guint32 maxBytes; - guint64 sumBytes = 0; + uint8_t type; + uint32_t maxBytes; + uint64_t sumBytes = 0; if (direction == 1) { maxBytes = selected_assoc->n_data_bytes_ep1; @@ -77,7 +77,7 @@ void SCTPGraphByteDialog::drawBytesGraph(const sctp_assoc_info_t *selected_assoc while (listTSN) { tsn = gxx_list_data(tsn_t*, listTSN); tlist = g_list_first(tsn->tsns); - guint16 length; + uint16_t length; while (tlist) { type = gxx_list_data(struct chunk_header *, tlist)->type; @@ -164,7 +164,7 @@ void SCTPGraphByteDialog::graphClicked(QCPAbstractPlottable* plottable, int, QMo } } if (cap_file_ && frame_num > 0) { - cf_goto_frame(cap_file_, frame_num); + cf_goto_frame(cap_file_, frame_num, false); } ui->hintLabel->setText(QString(tr("Graph %1: Received bytes=%2 Time=%3 secs ")) diff --git a/ui/qt/sctp_graph_byte_dialog.h b/ui/qt/sctp_graph_byte_dialog.h index e6785da9..b331ad9f 100644 --- a/ui/qt/sctp_graph_byte_dialog.h +++ b/ui/qt/sctp_graph_byte_dialog.h @@ -11,7 +11,6 @@ #define SCTP_GRAPH_BYTE_DIALOG_H #include -#include #include "cfile.h" @@ -46,12 +45,12 @@ private slots: private: Ui::SCTPGraphByteDialog *ui; - guint16 selected_assoc_id; + uint16_t selected_assoc_id; capture_file *cap_file_; int frame_num; int direction; QVector xb, yb; - QVector fb; + QVector fb; void drawGraph(); void drawBytesGraph(const _sctp_assoc_info *selected_assoc); diff --git a/ui/qt/sctp_graph_dialog.cpp b/ui/qt/sctp_graph_dialog.cpp index a26f0d11..e0e69faf 100644 --- a/ui/qt/sctp_graph_dialog.cpp +++ b/ui/qt/sctp_graph_dialog.cpp @@ -67,13 +67,13 @@ void SCTPGraphDialog::drawNRSACKGraph(const sctp_assoc_info_t* selected_assoc) { tsn_t *sack = Q_NULLPTR; GList *list = Q_NULLPTR, *tlist = Q_NULLPTR; - guint16 gap_start=0, gap_end=0, i, numberOf_gaps, numberOf_nr_gaps; - guint8 type; - guint32 tsnumber, j = 0, min_tsn, rel = 0; + uint16_t gap_start=0, gap_end=0, i, numberOf_gaps, numberOf_nr_gaps; + uint8_t type; + uint32_t tsnumber, j = 0, min_tsn, rel = 0; struct nr_sack_chunk_header *nr_sack_header = Q_NULLPTR; struct gaps *nr_gap = Q_NULLPTR; /* This holds the sum of gap acks and nr gap acks */ - guint16 total_gaps = 0; + uint16_t total_gaps = 0; if (direction == 1) { list = g_list_last(selected_assoc->sack1); @@ -133,14 +133,14 @@ void SCTPGraphDialog::drawNRSACKGraph(const sctp_assoc_info_t* selected_assoc) void SCTPGraphDialog::drawSACKGraph(const sctp_assoc_info_t* selected_assoc) { GList *listSACK = Q_NULLPTR, *tlist = Q_NULLPTR; - guint16 gap_start=0, gap_end=0, nr, dup_nr; + uint16_t gap_start=0, gap_end=0, nr, dup_nr; struct sack_chunk_header *sack_header = Q_NULLPTR; struct gaps *gap = Q_NULLPTR; tsn_t *tsn = Q_NULLPTR; - guint8 type; - guint32 tsnumber=0, rel = 0; - guint32 minTSN; - guint32 *dup_list = Q_NULLPTR; + uint8_t type; + uint32_t tsnumber=0, rel = 0; + uint32_t minTSN; + uint32_t *dup_list = Q_NULLPTR; int i, j; if (direction == 1) { @@ -262,8 +262,8 @@ void SCTPGraphDialog::drawTSNGraph(const sctp_assoc_info_t* selected_assoc) { GList *listTSN = Q_NULLPTR,*tlist = Q_NULLPTR; tsn_t *tsn = Q_NULLPTR; - guint8 type; - guint32 tsnumber=0, rel = 0, minTSN; + uint8_t type; + uint32_t tsnumber=0, rel = 0, minTSN; if (direction == 1) { listTSN = g_list_last(selected_assoc->tsn1); @@ -321,7 +321,7 @@ void SCTPGraphDialog::drawGraph(const sctp_assoc_info_t* selected_assoc) if (!selected_assoc) return; } - guint32 maxTSN, minTSN; + uint32_t maxTSN, minTSN; if (direction == 1) { maxTSN = selected_assoc->max_tsn1; @@ -467,7 +467,7 @@ void SCTPGraphDialog::graphClicked(QCPAbstractPlottable* plottable, int, QMouseE } } if (cap_file_ && frame_num > 0) { - cf_goto_frame(cap_file_, frame_num); + cf_goto_frame(cap_file_, frame_num, false); } ui->hintLabel->setText(QString(tr("%1: %2 Time: %3 secs ")) .arg(plottable->name()) diff --git a/ui/qt/sctp_graph_dialog.h b/ui/qt/sctp_graph_dialog.h index 28aeccb0..06cfdd94 100644 --- a/ui/qt/sctp_graph_dialog.h +++ b/ui/qt/sctp_graph_dialog.h @@ -11,7 +11,6 @@ #define SCTP_GRAPH_DIALOG_H #include -#include #include "cfile.h" @@ -27,47 +26,47 @@ class QCustomPlot; struct _sctp_assoc_info; struct chunk_header { - guint8 type; - guint8 flags; - guint16 length; + uint8_t type; + uint8_t flags; + uint16_t length; }; struct data_chunk_header { - guint8 type; - guint8 flags; - guint16 length; - guint32 tsn; - guint16 sid; - guint16 ssn; - guint32 ppi; + uint8_t type; + uint8_t flags; + uint16_t length; + uint32_t tsn; + uint16_t sid; + uint16_t ssn; + uint32_t ppi; }; struct gaps { - guint16 start; - guint16 end; + uint16_t start; + uint16_t end; }; struct sack_chunk_header { - guint8 type; - guint8 flags; - guint16 length; - guint32 cum_tsn_ack; - guint32 a_rwnd; - guint16 nr_of_gaps; - guint16 nr_of_dups; + uint8_t type; + uint8_t flags; + uint16_t length; + uint32_t cum_tsn_ack; + uint32_t a_rwnd; + uint16_t nr_of_gaps; + uint16_t nr_of_dups; struct gaps gaps[1]; }; struct nr_sack_chunk_header { - guint8 type; - guint8 flags; - guint16 length; - guint32 cum_tsn_ack; - guint32 a_rwnd; - guint16 nr_of_gaps; - guint16 nr_of_nr_gaps; - guint16 nr_of_dups; - guint16 reserved; + uint8_t type; + uint8_t flags; + uint16_t length; + uint32_t cum_tsn_ack; + uint32_t a_rwnd; + uint16_t nr_of_gaps; + uint16_t nr_of_nr_gaps; + uint16_t nr_of_dups; + uint16_t reserved; struct gaps gaps[1]; }; @@ -102,12 +101,12 @@ private slots: private: Ui::SCTPGraphDialog *ui; - guint16 selected_assoc_id; + uint16_t selected_assoc_id; capture_file *cap_file_; int frame_num; int direction; QVector xt, yt, xs, ys, xg, yg, xd, yd, xn, yn; - QVector ft, fs, fg, fd, fn; + QVector ft, fs, fg, fd, fn; QVector typeStrings; bool relative; int type; diff --git a/ui/qt/search_frame.cpp b/ui/qt/search_frame.cpp index 95a5b8e8..d4a332d8 100644 --- a/ui/qt/search_frame.cpp +++ b/ui/qt/search_frame.cpp @@ -16,10 +16,13 @@ #include #include +#include #include #include #include "main_application.h" +#include "utils/qt_ui_utils.h" + #include #include @@ -56,6 +59,18 @@ SearchFrame::SearchFrame(QWidget *parent) : } #endif + if (!is_packet_configuration_namespace()) { + sf_ui_->searchInComboBox->setItemText(0, tr("Event List")); + sf_ui_->searchInComboBox->setItemText(1, tr("Event Details")); + sf_ui_->searchInComboBox->setItemText(2, tr("Event Bytes")); + sf_ui_->searchInComboBox->setToolTip(tr("" + "

Search the Info column of the event list (summary pane), " + "decoded event display labels (tree view pane) or the " + "ASCII-converted event data (hex view pane).

" + "")); + } + + applyRecentSearchSettings(); updateWidgets(); @@ -80,7 +95,7 @@ void SearchFrame::findNext() { if (!cap_file_) return; - cap_file_->dir = SD_FORWARD; + sf_ui_->dirCheckBox->setChecked(false); if (isHidden()) { animatedShow(); return; @@ -92,7 +107,7 @@ void SearchFrame::findPrevious() { if (!cap_file_) return; - cap_file_->dir = SD_BACKWARD; + sf_ui_->dirCheckBox->setChecked(true); if (isHidden()) { animatedShow(); return; @@ -104,7 +119,6 @@ void SearchFrame::setFocus() { sf_ui_->searchLineEdit->setFocus(); sf_ui_->searchLineEdit->selectAll(); - cap_file_->dir = SD_FORWARD; } void SearchFrame::setCaptureFile(capture_file *cf) @@ -145,6 +159,9 @@ bool SearchFrame::regexCompile() if (!sf_ui_->caseCheckBox->isChecked()) { flags |= WS_REGEX_CASELESS; } + if (sf_ui_->dirCheckBox->isChecked()) { + flags |= WS_REGEX_ANCHORED; + } if (regex_) { ws_regex_free(regex_); @@ -221,6 +238,8 @@ void SearchFrame::applyRecentSearchSettings() sf_ui_->charEncodingComboBox->setCurrentIndex(char_encoding_idx); sf_ui_->caseCheckBox->setChecked(recent.gui_search_case_sensitive); sf_ui_->searchTypeComboBox->setCurrentIndex(search_type_idx); + sf_ui_->dirCheckBox->setChecked(recent.gui_search_reverse_dir); + sf_ui_->multipleCheckBox->setChecked(recent.gui_search_multiple_occurs); } void SearchFrame::updateWidgets() @@ -235,7 +254,15 @@ void SearchFrame::updateWidgets() int search_type = sf_ui_->searchTypeComboBox->currentIndex(); sf_ui_->searchInComboBox->setEnabled(search_type == string_search_ || search_type == regex_search_); sf_ui_->caseCheckBox->setEnabled(search_type == string_search_ || search_type == regex_search_); - sf_ui_->charEncodingComboBox->setEnabled(search_type == string_search_); + // The encoding only is used when searching the raw Packet Bytes + // (otherwise all strings have already been converted to UTF-8) + sf_ui_->charEncodingComboBox->setEnabled(search_type == string_search_ && sf_ui_->searchInComboBox->currentIndex() == in_bytes_); + + // We can search for multiple matches in the same frame if we're doing + // a Proto Tree search or a Frame Bytes search, but not a string/regex + // search in the Packet List, or a display filter search (since those + // don't highlight what fields / offsets caused the match.) + sf_ui_->multipleCheckBox->setEnabled((sf_ui_->searchInComboBox->isEnabled() && sf_ui_->searchInComboBox->currentIndex() != in_packet_list_) || search_type == hex_search_); switch (search_type) { case df_search_: @@ -245,7 +272,7 @@ void SearchFrame::updateWidgets() if (sf_ui_->searchLineEdit->text().isEmpty()) { sf_ui_->searchLineEdit->setSyntaxState(SyntaxLineEdit::Invalid); } else { - guint8 *bytes; + uint8_t *bytes; size_t nbytes; bytes = convert_string_to_hex(sf_ui_->searchLineEdit->text().toUtf8().constData(), &nbytes); if (bytes == nullptr) @@ -297,6 +324,9 @@ void SearchFrame::on_searchInComboBox_currentIndexChanged(int idx) default: break; } + + // We only search for multiple occurrences in packet list and bytes + updateWidgets(); } void SearchFrame::on_charEncodingComboBox_currentIndexChanged(int idx) @@ -359,27 +389,39 @@ void SearchFrame::on_searchLineEdit_textChanged(const QString &) updateWidgets(); } +void SearchFrame::on_dirCheckBox_toggled(bool checked) +{ + recent.gui_search_reverse_dir = checked; +} + +void SearchFrame::on_multipleCheckBox_toggled(bool checked) +{ + recent.gui_search_multiple_occurs = checked; +} + void SearchFrame::on_findButton_clicked() { - guint8 *bytes = nullptr; + uint8_t *bytes = nullptr; size_t nbytes = 0; char *string = nullptr; dfilter_t *dfp = nullptr; - gboolean found_packet = FALSE; + bool found_packet = false; QString err_string; if (!cap_file_) { return; } - cap_file_->hex = FALSE; - cap_file_->string = FALSE; - cap_file_->case_type = FALSE; + cap_file_->hex = false; + cap_file_->string = false; + cap_file_->case_type = false; cap_file_->regex = nullptr; - cap_file_->packet_data = FALSE; - cap_file_->decode_data = FALSE; - cap_file_->summary_data = FALSE; + cap_file_->packet_data = false; + cap_file_->decode_data = false; + cap_file_->summary_data = false; cap_file_->scs_type = SCS_NARROW_AND_WIDE; + cap_file_->dir = sf_ui_->dirCheckBox->isChecked() ? SD_BACKWARD : SD_FORWARD; + bool multiple_occurrences = sf_ui_->multipleCheckBox->isChecked(); int search_type = sf_ui_->searchTypeComboBox->currentIndex(); switch (search_type) { @@ -400,7 +442,7 @@ void SearchFrame::on_findButton_clicked() err_string = tr("That's not a valid hex string."); goto search_done; } - cap_file_->hex = TRUE; + cap_file_->hex = true; break; case string_search_: case regex_search_: @@ -408,8 +450,8 @@ void SearchFrame::on_findButton_clicked() err_string = tr("You didn't specify any text for which to search."); goto search_done; } - cap_file_->string = TRUE; - cap_file_->case_type = sf_ui_->caseCheckBox->isChecked() ? FALSE : TRUE; + cap_file_->string = true; + cap_file_->case_type = sf_ui_->caseCheckBox->isChecked() ? false : true; cap_file_->regex = (search_type == regex_search_ ? regex_ : nullptr); switch (sf_ui_->charEncodingComboBox->currentIndex()) { case narrow_and_wide_chars_: @@ -434,13 +476,13 @@ void SearchFrame::on_findButton_clicked() switch (sf_ui_->searchInComboBox->currentIndex()) { case in_packet_list_: - cap_file_->summary_data = TRUE; + cap_file_->summary_data = true; break; case in_proto_tree_: - cap_file_->decode_data = TRUE; + cap_file_->decode_data = true; break; case in_bytes_: - cap_file_->packet_data = TRUE; + cap_file_->packet_data = true; break; default: err_string = tr("No valid search area selected. Please report this to the development team."); @@ -448,13 +490,13 @@ void SearchFrame::on_findButton_clicked() } g_free(cap_file_->sfilter); - cap_file_->sfilter = g_strdup(sf_ui_->searchLineEdit->text().toUtf8().constData()); + cap_file_->sfilter = qstring_strdup(sf_ui_->searchLineEdit->text()); mainApp->popStatus(MainApplication::FileStatus); mainApp->pushStatus(MainApplication::FileStatus, tr("Searching for %1…").arg(sf_ui_->searchLineEdit->text())); if (cap_file_->hex) { /* Hex value in packet data */ - found_packet = cf_find_packet_data(cap_file_, bytes, nbytes, cap_file_->dir); + found_packet = cf_find_packet_data(cap_file_, bytes, nbytes, cap_file_->dir, multiple_occurrences); g_free(bytes); if (!found_packet) { /* We didn't find a packet */ @@ -476,7 +518,7 @@ void SearchFrame::on_findButton_clicked() } } else if (cap_file_->decode_data) { /* String in the protocol tree headings */ - found_packet = cf_find_packet_protocol_tree(cap_file_, string, cap_file_->dir); + found_packet = cf_find_packet_protocol_tree(cap_file_, string, cap_file_->dir, multiple_occurrences); g_free(string); if (!found_packet) { err_string = tr("No packet contained that string in its dissected display."); @@ -484,7 +526,7 @@ void SearchFrame::on_findButton_clicked() } } else if (cap_file_->packet_data && string) { /* String in the ASCII-converted packet data */ - found_packet = cf_find_packet_data(cap_file_, (guint8 *) string, strlen(string), cap_file_->dir); + found_packet = cf_find_packet_data(cap_file_, (uint8_t *) string, strlen(string), cap_file_->dir, multiple_occurrences); g_free(string); if (!found_packet) { err_string = tr("No packet contained that string in its converted data."); diff --git a/ui/qt/search_frame.h b/ui/qt/search_frame.h index 7ea0946a..52a2a489 100644 --- a/ui/qt/search_frame.h +++ b/ui/qt/search_frame.h @@ -56,6 +56,8 @@ private slots: void on_caseCheckBox_toggled(bool checked); void on_searchTypeComboBox_currentIndexChanged(int idx); void on_searchLineEdit_textChanged(const QString &); + void on_dirCheckBox_toggled(bool checked); + void on_multipleCheckBox_toggled(bool checked); void on_findButton_clicked(); void on_cancelButton_clicked(); }; diff --git a/ui/qt/search_frame.ui b/ui/qt/search_frame.ui index c3bb9908..0229d6f9 100644 --- a/ui/qt/search_frame.ui +++ b/ui/qt/search_frame.ui @@ -19,7 +19,18 @@ QFrame::Plain - + + + 4 + + + 0 + + + 0 + + + 0 @@ -78,114 +89,179 @@ - + - <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> - Narrow & Wide + Display filter - Narrow (UTF-8 / ASCII) + Hex value - Wide (UTF-16) + String + + + + + Regular Expression - + + + + 1 + 0 + + + + + + + + + 16777215 + 27 + + - Case sensitive + Find + + + true + + + + + + + + 16777215 + 27 + + + + Cancel + + + + + + 0 + + + 0 + - + Qt::Horizontal + + QSizePolicy::Fixed + - 20 - 10 + 40 + 20 - + + + <b>Options:</b> + + + + + - <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> - Display filter - - - - - Hex value + Narrow & Wide - String + Narrow (UTF-8 / ASCII) - Regular Expression + Wide (UTF-16) - - - - 1 - 0 - + + + Case sensitive - - + + + Qt::Horizontal + + - 16777215 - 27 + 20 + 10 + + + + - Find - - - true + Backwards - - + + + Qt::Horizontal + + - 16777215 - 27 + 20 + 10 + + + + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + - Cancel + Multiple occurrences + + diff --git a/ui/qt/sequence_diagram.cpp b/ui/qt/sequence_diagram.cpp index 4628915b..fd28a1e1 100644 --- a/ui/qt/sequence_diagram.cpp +++ b/ui/qt/sequence_diagram.cpp @@ -11,9 +11,11 @@ #include "epan/addr_resolv.h" #include "epan/sequence_analysis.h" +#include "epan/column.h" #include #include +#include #include "ui/recent.h" #include @@ -66,9 +68,12 @@ SequenceDiagram::SequenceDiagram(QCPAxis *keyAxis, QCPAxis *valueAxis, QCPAxis * axis->setTicker(ticker); axis->setSubTickPen(no_pen); axis->setTickPen(no_pen); - axis->setBasePen(no_pen); + axis->setSelectedTickPen(no_pen); } + QSharedPointer ticker(new QCPAxisTickerElided(comment_axis_)); + comment_axis_->setTicker(ticker); + value_axis_->grid()->setVisible(false); key_axis_->setRangeReversed(true); @@ -82,6 +87,14 @@ SequenceDiagram::SequenceDiagram(QCPAxis *keyAxis, QCPAxis *valueAxis, QCPAxis * smooth_font_size(comment_font); comment_axis_->setTickLabelFont(comment_font); comment_axis_->setSelectedTickLabelFont(QFont(comment_font.family(), comment_font.pointSizeF(), QFont::Bold)); + + // By default QCPAxisRect auto resizes, which creates some slight but + // noticeable horizontal movement when scrolling vertically. Prevent that. + key_axis_->axisRect()->setAutoMargins(QCP::msTop | QCP::msBottom); + int time_margin = QFontMetrics(key_axis_->tickLabelFont()).horizontalAdvance(get_column_longest_string(COL_CLS_TIME)); + int comment_margin = QFontMetrics(comment_font).height() * (max_comment_em_width_ + 1); // Add 1 as using the exact elided width is slightly too narrow + key_axis_->axisRect()->setMargins(QMargins(time_margin, 0, comment_margin, 0)); + // frame_label // port_src -----------------> port_dst @@ -127,7 +140,7 @@ int SequenceDiagram::adjacentPacket(bool next) it = data_->constEnd(); --it; while (it != data_->constBegin()) { - guint32 prev_frame = it.value().value->frame_number; + uint32_t prev_frame = it.value().value->frame_number; --it; if (prev_frame == selected_packet_) { adjacent_packet = it.value().value->frame_number; @@ -149,8 +162,6 @@ void SequenceDiagram::setData(_seq_analysis_info *sainfo) double cur_key = 0.0; QVector key_ticks, val_ticks; QVector key_labels, val_labels, com_labels; - QFontMetrics com_fm(comment_axis_->tickLabelFont()); - int elide_w = com_fm.height() * max_comment_em_width_; char* addr_str; for (GList *cur = g_queue_peek_nth_link(sainfo->items, 0); cur; cur = gxx_list_next(cur)) { @@ -165,7 +176,7 @@ void SequenceDiagram::setData(_seq_analysis_info *sainfo) key_ticks.append(cur_key); key_labels.append(sai->time_str); - com_labels.append(com_fm.elidedText(sai->comment, Qt::ElideRight, elide_w)); + com_labels.append(sai->comment); cur_key++; } @@ -211,6 +222,20 @@ _seq_analysis_item *SequenceDiagram::itemForPosY(int ypos) return NULL; } +bool SequenceDiagram::inComment(QPoint pos) const +{ + return pos.x() >= (comment_axis_->axisRect()->right() + + comment_axis_->padding() + + comment_axis_->tickLabelPadding() + + comment_axis_->offset()); +} + +QString SequenceDiagram::elidedComment(const QString &text) const +{ + QSharedPointer comment_ticker = qSharedPointerCast(comment_axis_->ticker()); + return comment_ticker->elidedText(text); +} + double SequenceDiagram::selectTest(const QPointF &pos, bool, QVariant *) const { double key_pos = qRound(key_axis_->pixelToCoord(pos.y())); @@ -327,11 +352,7 @@ void SequenceDiagram::draw(QCPPainter *painter) double arrow_width = (arrow_end.x() - arrow_start.x()) * dir_mul; QString arrow_label = cfm.elidedText(sai->frame_label, Qt::ElideRight, arrow_width); int arrow_label_width = 0; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) arrow_label_width = cfm.horizontalAdvance(arrow_label); -#else - arrow_label_width = cfm.width(arrow_label); -#endif QPoint text_pt(comment_start + ((arrow_width - arrow_label_width) / 2), arrow_start.y() - (en_w / 2)); @@ -344,11 +365,7 @@ void SequenceDiagram::draw(QCPPainter *painter) QString port_left = QString::number(dir_mul > 0 ? sai->port_src : sai->port_dst); QString port_right = QString::number(dir_mul > 0 ? sai->port_dst : sai->port_src); int port_left_width = 0; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) port_left_width = cfm.horizontalAdvance(port_left); -#else - port_left_width = cfm.width(port_left); -#endif text_pt = QPoint(left_x - en_w - port_left_width, arrow_start.y() + (en_w / 2)); painter->drawText(text_pt, port_left); diff --git a/ui/qt/sequence_diagram.h b/ui/qt/sequence_diagram.h index aa9a377a..a3c1327d 100644 --- a/ui/qt/sequence_diagram.h +++ b/ui/qt/sequence_diagram.h @@ -12,8 +12,6 @@ #include -#include - #include #include @@ -53,6 +51,8 @@ public: // non-property methods: struct _seq_analysis_item *itemForPosY(int ypos); + bool inComment(QPoint pos) const; + QString elidedComment(const QString &text) const; // reimplemented virtual methods: virtual void clearData() { data_->clear(); } @@ -73,7 +73,7 @@ private: QCPAxis *comment_axis_; WSCPSeqDataMap *data_; struct _seq_analysis_info *sainfo_; - guint32 selected_packet_; + uint32_t selected_packet_; double selected_key_; }; diff --git a/ui/qt/sequence_dialog.cpp b/ui/qt/sequence_dialog.cpp index e5fb7b87..8a541979 100644 --- a/ui/qt/sequence_dialog.cpp +++ b/ui/qt/sequence_dialog.cpp @@ -35,27 +35,20 @@ #include // To do: -// - Resize or show + hide the Time and Comment axes, possibly via one of -// the following: -// - Split the time, diagram, and comment sections into three separate -// widgets inside a QSplitter. This would resemble the GTK+ UI, but we'd -// have to coordinate between the three and we'd lose time and comment -// values in PDF and PNG exports. -// - Add separate controls for the width and/or visibility of the Time and -// Comment columns. -// - Fake a splitter widget by catching mouse events in the plot area. -// Drawing a QCPItemLine or QCPItemPixmap over each Y axis might make -// this easier. +// - Resize the Time and Comment axis as well? // - For general flows, let the user show columns other than COL_INFO. +// (#12549) // - Add UTF8 to text dump // - Save to XMI? https://www.spinellis.gr/umlgraph/ -// - Time: abs vs delta +// - Save to SVG? https://www.qcustomplot.com/index.php/support/forum/1677 +// - Time: abs vs delta (XXX - This is currently achieved by changing +// View->Time Display Format before opening the dialog.) // - Hide nodes -// - Clickable time + comments? +// - Clickable time + comments? (XXX - Clicking on them selects the item for +// the row, is there anything else?) // - Incorporate packet comments? // - Change line_style to seq_type (i.e. draw ACKs dashed) // - Create WSGraph subclasses with common behavior. -// - Help button and text static const double min_top_ = -1.0; static const double min_left_ = -0.5; @@ -73,6 +66,8 @@ SequenceDialog::SequenceDialog(QWidget &parent, CaptureFile &cf, SequenceInfo *i num_items_(0), packet_num_(0), sequence_w_(1), + axis_pressed_(false), + current_rtp_sai_hovered_(nullptr), voipFeaturesEnabled(voipFeatures) { QAction *action; @@ -86,6 +81,7 @@ SequenceDialog::SequenceDialog(QWidget &parent, CaptureFile &cf, SequenceInfo *i if (!info_) { info_ = new SequenceInfo(sequence_analysis_info_new()); info_->sainfo()->name = "any"; + info_->sainfo()->any_addr = true; } else { info_->ref(); sequence_analysis_free_nodes(info_->sainfo()); @@ -99,16 +95,33 @@ SequenceDialog::SequenceDialog(QWidget &parent, CaptureFile &cf, SequenceInfo *i //sp->axisRect()->setRangeDragAxes(sp->xAxis2, sp->yAxis); //sp->setInteractions(QCP::iRangeDrag); + sp->setInteraction(QCP::iSelectAxes, true); + sp->xAxis->setSelectableParts(QCPAxis::spNone); + sp->xAxis2->setSelectableParts(QCPAxis::spNone); + sp->yAxis->setSelectableParts(QCPAxis::spNone); + sp->yAxis2->setSelectableParts(QCPAxis::spAxis); + sp->xAxis->setVisible(false); sp->xAxis->setPadding(0); sp->xAxis->setLabelPadding(0); sp->xAxis->setTickLabelPadding(0); + // Light border for the diagram QPen base_pen(ColorUtils::alphaBlend(palette().text(), palette().base(), 0.25)); base_pen.setWidthF(0.5); sp->xAxis2->setBasePen(base_pen); sp->yAxis->setBasePen(base_pen); sp->yAxis2->setBasePen(base_pen); + // Keep the border the same if/when the axis is selected, instead of blue + sp->xAxis2->setSelectedBasePen(base_pen); + sp->yAxis->setSelectedBasePen(base_pen); + sp->yAxis2->setSelectedBasePen(base_pen); + + /* QCP documentation for setTicks() says "setting show to false does not imply + * that tick labels are invisible, too." In practice it seems to make them + * invisible, though, so set the length to 0. + */ + sp->yAxis2->setTickLength(0); sp->xAxis2->setVisible(true); sp->yAxis2->setVisible(true); @@ -162,7 +175,18 @@ SequenceDialog::SequenceDialog(QWidget &parent, CaptureFile &cf, SequenceInfo *i action->setEnabled(false); set_action_shortcuts_visible_in_context_menu(ctx_menu_.actions()); - ui->addressComboBox->setCurrentIndex(0); + sp->setContextMenuPolicy(Qt::CustomContextMenu); + connect(sp, &QCustomPlot::customContextMenuRequested, this, &SequenceDialog::showContextMenu); + + ui->addressComboBox->addItem(tr("Any"), QVariant(true)); + ui->addressComboBox->addItem(tr("Network"), QVariant(false)); + ui->addressComboBox->setCurrentIndex(ui->addressComboBox->findData(QVariant(true))); + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + connect(ui->addressComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &SequenceDialog::addressChanged); +#else + connect(ui->addressComboBox, &QComboBox::currentIndexChanged, this, &SequenceDialog::addressChanged); +#endif sequence_items_t item_data; @@ -198,13 +222,20 @@ SequenceDialog::SequenceDialog(QWidget &parent, CaptureFile &cf, SequenceInfo *i loadGeometry(parent.width(), parent.height() * 4 / 5); + if (cf.isValid() && cf.displayFilter().length() > 0) { + ui->displayFilterCheckBox->setChecked(true); + } + + connect(ui->displayFilterCheckBox, &QCheckBox::toggled, this, &SequenceDialog::displayFilterCheckBoxToggled); connect(ui->horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(hScrollBarChanged(int))); connect(ui->verticalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(vScrollBarChanged(int))); connect(sp->xAxis2, SIGNAL(rangeChanged(QCPRange)), this, SLOT(xAxisChanged(QCPRange))); connect(sp->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(yAxisChanged(QCPRange))); - connect(sp, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(diagramClicked(QMouseEvent*))); - connect(sp, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoved(QMouseEvent*))); - connect(sp, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(mouseWheeled(QWheelEvent*))); + connect(sp, &QCustomPlot::mousePress, this, &SequenceDialog::diagramClicked); + connect(sp, &QCustomPlot::mouseRelease, this, &SequenceDialog::mouseReleased); + connect(sp, &QCustomPlot::mouseMove, this, &SequenceDialog::mouseMoved); + connect(sp, &QCustomPlot::mouseWheel, this, &SequenceDialog::mouseWheeled); + connect(sp, &QCustomPlot::axisDoubleClick, this, &SequenceDialog::axisDoubleClicked); connect(sp, &QCustomPlot::afterLayout, this, &SequenceDialog::layoutAxisLabels); } @@ -227,6 +258,23 @@ void SequenceDialog::updateWidgets() WiresharkDialog::updateWidgets(); } +bool SequenceDialog::event(QEvent *event) +{ + if (event->type() == QEvent::ToolTip) { + QHelpEvent *helpEvent = static_cast(event); + seq_analysis_item_t *sai = seq_diagram_->itemForPosY(helpEvent->pos().y()); + if (sai && seq_diagram_->inComment(helpEvent->pos()) && (sai->comment != seq_diagram_->elidedComment(sai->comment))) { + QToolTip::showText(helpEvent->globalPos(), sai->comment); + } else { + QToolTip::hideText(); + event->ignore(); + } + + return true; + } + return QWidget::event(event); +} + void SequenceDialog::showEvent(QShowEvent *) { QTimer::singleShot(0, this, SLOT(fillDiagram())); @@ -314,7 +362,7 @@ void SequenceDialog::hScrollBarChanged(int value) { if (qAbs(ui->sequencePlot->xAxis2->range().center()-value/100.0) > 0.01) { ui->sequencePlot->xAxis2->setRange(value/100.0, ui->sequencePlot->xAxis2->range().size(), Qt::AlignCenter); - ui->sequencePlot->replot(); + ui->sequencePlot->replot(QCustomPlot::rpQueuedReplot); } } @@ -322,7 +370,7 @@ void SequenceDialog::vScrollBarChanged(int value) { if (qAbs(ui->sequencePlot->yAxis->range().center()-value/100.0) > 0.01) { ui->sequencePlot->yAxis->setRange(value/100.0, ui->sequencePlot->yAxis->range().size(), Qt::AlignCenter); - ui->sequencePlot->replot(); + ui->sequencePlot->replot(QCustomPlot::rpQueuedReplot); } } @@ -338,10 +386,20 @@ void SequenceDialog::yAxisChanged(QCPRange range) ui->verticalScrollBar->setPageStep(qRound(qreal(range.size()*100.0))); } +void SequenceDialog::showContextMenu(const QPoint &pos) +{ + ctx_menu_.popup(ui->sequencePlot->mapToGlobal(pos)); +} + void SequenceDialog::diagramClicked(QMouseEvent *event) { current_rtp_sai_selected_ = NULL; if (event) { + QCPAxis *yAxis2 = ui->sequencePlot->yAxis2; + if (std::abs(event->pos().x() - yAxis2->axisRect()->right()) < 5) { + yAxis2->setSelectedParts(QCPAxis::spAxis); + axis_pressed_ = true; + } seq_analysis_item_t *sai = seq_diagram_->itemForPosY(event->pos().y()); if (voipFeaturesEnabled) { ui->actionSelectRtpStreams->setEnabled(false); @@ -361,13 +419,6 @@ void SequenceDialog::diagramClicked(QMouseEvent *event) case Qt::LeftButton: on_actionGoToPacket_triggered(); break; - case Qt::RightButton: -#if QT_VERSION >= QT_VERSION_CHECK(6, 0 ,0) - ctx_menu_.popup(event->globalPosition().toPoint()); -#else - ctx_menu_.popup(event->globalPos()); -#endif - break; default: break; } @@ -375,12 +426,47 @@ void SequenceDialog::diagramClicked(QMouseEvent *event) } +void SequenceDialog::axisDoubleClicked(QCPAxis *axis, QCPAxis::SelectablePart, QMouseEvent*) +{ + if (axis == ui->sequencePlot->yAxis2) { + QCP::MarginSides autoMargins = axis->axisRect()->autoMargins(); + axis->axisRect()->setAutoMargins(autoMargins | QCP::msRight); + ui->sequencePlot->replot(); + axis->axisRect()->setAutoMargins(autoMargins); + ui->sequencePlot->replot(); + } +} + +void SequenceDialog::mouseReleased(QMouseEvent*) +{ + QCustomPlot *sp = ui->sequencePlot; + sp->yAxis2->setSelectedParts(QCPAxis::spNone); + axis_pressed_ = false; + sp->replot(QCustomPlot::rpQueuedReplot); +} + void SequenceDialog::mouseMoved(QMouseEvent *event) { current_rtp_sai_hovered_ = NULL; packet_num_ = 0; QString hint; + Qt::CursorShape shape = Qt::ArrowCursor; if (event) { + QCPAxis *yAxis2 = ui->sequencePlot->yAxis2; + // For some reason we need this extra bool and can't rely just on + // yAxis2->selectedParts().testFlag(QCPAxis::spAxis) + if (axis_pressed_) { + int x = qMax(event->pos().x(), yAxis2->axisRect()->left()); + QMargins margins = yAxis2->axisRect()->margins(); + margins += QMargins(0, 0, yAxis2->axisRect()->right() - x, 0); + yAxis2->axisRect()->setMargins(margins); + shape = Qt::SplitHCursor; + ui->sequencePlot->replot(QCustomPlot::rpQueuedReplot); + } else { + if (std::abs(event->pos().x() - yAxis2->axisRect()->right()) < 5) { + shape = Qt::SplitHCursor; + } + } seq_analysis_item_t *sai = seq_diagram_->itemForPosY(event->pos().y()); if (sai) { if (GA_INFO_TYPE_RTP == sai->info_type) { @@ -393,6 +479,10 @@ void SequenceDialog::mouseMoved(QMouseEvent *event) } } + if (ui->sequencePlot->cursor().shape() != shape) { + ui->sequencePlot->setCursor(QCursor(shape)); + } + if (hint.isEmpty()) { if (!info_->sainfo()) { hint += tr("No data"); @@ -456,14 +546,55 @@ void SequenceDialog::exportDiagram() if (file_name.length() > 0) { bool save_ok = false; + // The QCustomPlot save functions take a width and a height, measured + // in pixels (for the entire viewport). + // In order to display the whole graph, we have to change the axes + // and scale up the width and height appropriately so that the text + // has the proper spacing. (Using the scale factor in some of the + // image writing functions makes the text illegible.) + // If we set the axes back to their old value without replotting, + // there's no visual effects from doing this. + QCustomPlot *sp = ui->sequencePlot; + QCPRange old_yrange = sp->yAxis->range(); + QCPRange old_xrange = sp->xAxis2->range(); + // For the horizontal aspect, we'll display all the nodes. + // Nodes can excluded by filtering (hiding nodes is in the todo list.) + // Use the current width of a node as determined by the user zooming + // with Key_Plus and Key_Minus, multiply that by the number of nodes, + // and add in the margin from the Time and Comment columns. + // MAX_NUM_NODES is 40, which results in a manageable 8802 pixel width + // at the default zoom level on my Linux box. + // (If the user has zoomed in unreasonably, that's on the user.) + int hmargin = sp->axisRect()->outerRect().width() - sp->axisRect()->width(); + double nodeSize = (sp->axisRect()->width()) / old_xrange.size(); + // For the vertical aspect, we need to put a bound on the number of + // pixels or items we'll put in an image, as it can get far too large. + // (JPEG only supports 16 bit aspect sizes, PNG supports 31 bit but + // many viewers don't.) + int vmargin = sp->axisRect()->outerRect().height() - sp->axisRect()->height(); + // 1000 items is a little over 27000 pixels in height on my machine. + // XXX - Should this pref be pixels instead of items? + //int max_pixel = 24576; + //double range_span = ((max_pixel - vmargin) / (one_em_ * 1.5)); + double range_span = prefs.flow_graph_max_export_items; + // Start at the current top item, and QCPRange::bounded does what + // we want, with margins of 1.0 on top and bottom. + QCPRange new_yrange(old_yrange.lower, old_yrange.lower + range_span); + new_yrange = new_yrange.bounded(min_top_, num_items_); + sp->yAxis->setRange(new_yrange); + // margins of 0.5 on left and right for port number, etc. + sp->xAxis2->setRange(min_left_, info_->sainfo()->num_nodes - 0.5); + // As seen in resetAxes(), we have an item take ~ 1.5*one_em_ pixels. + int ySize = new_yrange.size() * (one_em_ * 1.5) + vmargin; + int xSize = (nodeSize * info_->sainfo()->num_nodes) + hmargin; if (extension.compare(pdf_filter) == 0) { - save_ok = ui->sequencePlot->savePdf(file_name); + save_ok = ui->sequencePlot->savePdf(file_name, xSize, ySize); } else if (extension.compare(png_filter) == 0) { - save_ok = ui->sequencePlot->savePng(file_name); + save_ok = ui->sequencePlot->savePng(file_name, xSize, ySize); } else if (extension.compare(bmp_filter) == 0) { - save_ok = ui->sequencePlot->saveBmp(file_name); + save_ok = ui->sequencePlot->saveBmp(file_name, xSize, ySize); } else if (extension.compare(jpeg_filter) == 0) { - save_ok = ui->sequencePlot->saveJpg(file_name); + save_ok = ui->sequencePlot->saveJpg(file_name, xSize, ySize); } else if (extension.compare(ascii_filter) == 0 && !file_closed_ && info_->sainfo()) { FILE *outfile = ws_fopen(file_name.toUtf8().constData(), "w"); if (outfile != NULL) { @@ -474,11 +605,13 @@ void SequenceDialog::exportDiagram() save_ok = false; } } + sp->yAxis->setRange(old_yrange); + sp->xAxis2->setRange(old_xrange); // else error dialog? if (save_ok) { mainApp->setLastOpenDirFromFilename(file_name); } else { - open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE); + open_failure_alert_box(file_name.toUtf8().constData(), errno, true); } } } @@ -547,7 +680,7 @@ void SequenceDialog::panAxes(int x_pixels, int y_pixels) } if (sp->yAxis->rangeReversed()) { - // For reversed axes, lower still references the mathemathetically + // For reversed axes, lower still references the mathematically // smaller number than upper, so reverse the direction. y_pixels = -y_pixels; } @@ -560,11 +693,11 @@ void SequenceDialog::panAxes(int x_pixels, int y_pixels) if (h_pan && !(sp->xAxis2->range().contains(min_left_) && sp->xAxis2->range().contains(info_->sainfo()->num_nodes - 0.5))) { sp->xAxis2->moveRange(h_pan); - sp->replot(); + sp->replot(QCustomPlot::rpQueuedReplot); } if (v_pan && !(sp->yAxis->range().contains(min_top_) && sp->yAxis->range().contains(num_items_))) { sp->yAxis->moveRange(v_pan); - sp->replot(); + sp->replot(QCustomPlot::rpQueuedReplot); } } @@ -588,12 +721,12 @@ void SequenceDialog::resetAxes(bool keep_lower) sp->yAxis->setRange(top_pos, range_span + top_pos); double rmin = sp->xAxis2->range().size() / 2; - ui->horizontalScrollBar->setRange((rmin - 0.5) * 100, (info_->sainfo()->num_nodes - 0.5 - rmin) * 100); + ui->horizontalScrollBar->setRange((rmin + min_left_) * 100, (info_->sainfo()->num_nodes - 0.5 - rmin) * 100); xAxisChanged(sp->xAxis2->range()); ui->horizontalScrollBar->setValue(ui->horizontalScrollBar->minimum()); // Shouldn't be needed. rmin = (sp->yAxis->range().size() / 2); - ui->verticalScrollBar->setRange((rmin - 1.0) * 100, (num_items_ - 0.5 - rmin) * 100); + ui->verticalScrollBar->setRange((rmin + min_top_) * 100, (num_items_ - 0.5 - rmin) * 100); yAxisChanged(sp->yAxis->range()); sp->replot(QCustomPlot::rpQueuedReplot); @@ -634,7 +767,7 @@ void SequenceDialog::resetView() void SequenceDialog::on_actionGoToPacket_triggered() { if (!file_closed_ && packet_num_ > 0) { - cf_goto_frame(cap_file_.capFile(), packet_num_); + cf_goto_frame(cap_file_.capFile(), packet_num_, false); seq_diagram_->setSelectedPacket(packet_num_); } } @@ -685,12 +818,12 @@ void SequenceDialog::goToAdjacentPacket(bool next) } sp->yAxis->moveRange(range_offset); } - cf_goto_frame(cap_file_.capFile(), adjacent_packet); + cf_goto_frame(cap_file_.capFile(), adjacent_packet, false); seq_diagram_->setSelectedPacket(adjacent_packet); } } -void SequenceDialog::on_displayFilterCheckBox_toggled(bool) +void SequenceDialog::displayFilterCheckBoxToggled(bool) { fillDiagram(); } @@ -706,16 +839,15 @@ void SequenceDialog::on_flowComboBox_activated(int index) fillDiagram(); } -void SequenceDialog::on_addressComboBox_activated(int index) +void SequenceDialog::addressChanged(int) { if (!info_->sainfo()) return; - if (index == 0) { - info_->sainfo()->any_addr = TRUE; - } else { - info_->sainfo()->any_addr = FALSE; + QVariant data = ui->addressComboBox->currentData(); + if (data.isValid()) { + info_->sainfo()->any_addr = data.toBool(); + fillDiagram(); } - fillDiagram(); } void SequenceDialog::on_actionMoveRight10_triggered() @@ -825,7 +957,7 @@ bool SequenceDialog::addFlowSequenceItem(const void* key, void *value, void *use /* XXX - Although "voip" isn't a registered name yet, it appears to have special handling that will be done outside of registered data */ if (strcmp(name, "voip") == 0) - return FALSE; + return false; item_data->flow->addItem(sequence_analysis_get_ui_name(analysis), VariantPointer::asQVariant(analysis)); @@ -834,7 +966,7 @@ bool SequenceDialog::addFlowSequenceItem(const void* key, void *value, void *use item_data->curr_index++; - return FALSE; + return false; } QVectorSequenceDialog::getSelectedRtpIds() diff --git a/ui/qt/sequence_dialog.h b/ui/qt/sequence_dialog.h index f9935d5b..6bbc3d00 100644 --- a/ui/qt/sequence_dialog.h +++ b/ui/qt/sequence_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include "cfile.h" #include "epan/packet.h" @@ -53,6 +51,7 @@ public: ~SequenceDialog(); protected: + bool event(QEvent *event); void showEvent(QShowEvent *event); void resizeEvent(QResizeEvent *event); void keyPressEvent(QKeyEvent *event); @@ -70,7 +69,10 @@ private slots: void vScrollBarChanged(int value); void xAxisChanged(QCPRange range); void yAxisChanged(QCPRange range); + void showContextMenu(const QPoint &pos); void diagramClicked(QMouseEvent *event); + void axisDoubleClicked(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event); + void mouseReleased(QMouseEvent *event); void mouseMoved(QMouseEvent *event); void mouseWheeled(QWheelEvent *event); @@ -79,13 +81,14 @@ private slots: void exportDiagram(); void layoutAxisLabels(); + void addressChanged(int index); + void displayFilterCheckBoxToggled(bool checked); + void on_buttonBox_clicked(QAbstractButton *button); void on_actionGoToPacket_triggered(); void on_actionGoToNextPacket_triggered() { goToAdjacentPacket(true); } void on_actionGoToPreviousPacket_triggered() { goToAdjacentPacket(false); } - void on_displayFilterCheckBox_toggled(bool checked); void on_flowComboBox_activated(int index); - void on_addressComboBox_activated(int index); void on_actionMoveRight10_triggered(); void on_actionMoveLeft10_triggered(); void on_actionMoveUp10_triggered(); @@ -109,9 +112,10 @@ private: SequenceDiagram *seq_diagram_; SequenceInfo *info_; int num_items_; - guint32 packet_num_; + uint32_t packet_num_; double one_em_; int sequence_w_; + bool axis_pressed_; QPushButton *reset_button_; QToolButton *player_button_; QPushButton *export_button_; diff --git a/ui/qt/sequence_dialog.ui b/ui/qt/sequence_dialog.ui index a62e76e0..d116952e 100644 --- a/ui/qt/sequence_dialog.ui +++ b/ui/qt/sequence_dialog.ui @@ -156,16 +156,6 @@ - - - Any - - - - - Network - - diff --git a/ui/qt/service_response_time_dialog.cpp b/ui/qt/service_response_time_dialog.cpp index 95bd4801..31c86d58 100644 --- a/ui/qt/service_response_time_dialog.cpp +++ b/ui/qt/service_response_time_dialog.cpp @@ -66,7 +66,7 @@ bool register_service_response_tables(const void *, void *value, void*) srt_init, tpd_creator); g_free(cfg_abbr); - return FALSE; + return false; } enum { @@ -205,7 +205,7 @@ ServiceResponseTimeDialog::~ServiceResponseTimeDialog() { if (srt_data_.srt_array) { free_srt_table(srt_, srt_data_.srt_array); - g_array_free(srt_data_.srt_array, TRUE); + g_array_free(srt_data_.srt_array, true); } } @@ -259,7 +259,7 @@ void ServiceResponseTimeDialog::tapDraw(void *srtd_ptr) void ServiceResponseTimeDialog::endRetapPackets() { - for (guint i = 0; i < srt_data_.srt_array->len; i++) { + for (unsigned i = 0; i < srt_data_.srt_array->len; i++) { srt_stat_table *srt_table = g_array_index(srt_data_.srt_array, srt_stat_table*, i); addSrtTable(srt_table); } @@ -270,9 +270,9 @@ void ServiceResponseTimeDialog::fillTree() { if (srt_data_.srt_array) { free_srt_table(srt_, srt_data_.srt_array); - g_array_free(srt_data_.srt_array, TRUE); + g_array_free(srt_data_.srt_array, true); } - srt_data_.srt_array = g_array_new(FALSE, TRUE, sizeof(srt_stat_table*)); + srt_data_.srt_array = g_array_new(false, true, sizeof(srt_stat_table*)); srt_data_.user_data = this; provideParameterData(); diff --git a/ui/qt/show_packet_bytes_dialog.cpp b/ui/qt/show_packet_bytes_dialog.cpp index d85a1ea5..62a19649 100644 --- a/ui/qt/show_packet_bytes_dialog.cpp +++ b/ui/qt/show_packet_bytes_dialog.cpp @@ -182,10 +182,14 @@ void ShowPacketBytesDialog::updateHintLabel() if (start_ > 0 || end_ < (finfo_->length - 1)) { hint.append(" " + - tr("Displaying %Ln byte(s).", "", end_ - start_ + 1) + + tr("Using %Ln byte(s).", "", end_ - start_ + 1) + ""); } + if (!decode_as_name_.isEmpty()) { + hint.append(" " + tr("Decoded as %1.").arg(decode_as_name_)); + } + ui->hintLabel->setText("" + hint + ""); } @@ -194,7 +198,6 @@ void ShowPacketBytesDialog::on_sbStart_valueChanged(int value) start_ = value; ui->sbEnd->setMinimum(value); - updateHintLabel(); updateFieldBytes(); } @@ -203,7 +206,6 @@ void ShowPacketBytesDialog::on_sbEnd_valueChanged(int value) end_ = value; ui->sbStart->setMaximum(value); - updateHintLabel(); updateFieldBytes(); } @@ -242,20 +244,40 @@ void ShowPacketBytesDialog::useRegexFind(bool use_regex) ui->lFind->setText(tr("Find:")); } +// This only calls itself with go_back false, so never recurses more than once. +// NOLINTNEXTLINE(misc-no-recursion) void ShowPacketBytesDialog::findText(bool go_back) { if (ui->leFind->text().isEmpty()) return; bool found; + + QTextDocument::FindFlags options; + if (ui->caseCheckBox->isChecked()) { + options |= QTextDocument::FindCaseSensitively; + } if (use_regex_find_) { #if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)) + // https://bugreports.qt.io/browse/QTBUG-88721 + // QPlainTextEdit::find() searches case-insensitively unless + // QTextDocument::FindCaseSensitively is explicitly given. + // This *does* apply to QRegularExpression (overriding + // CaseInsensitiveOption), but not QRegExp. + // + // QRegularExpression and QRegExp do not support Perl's /i, but + // the former at least does support the mode modifiers (?i) and + // (?-i), which can override QTextDocument::FindCaseSensitively. + // + // To make matters worse, while the QTextDocument::find() documentation + // is correct, QPlainTextEdit::find() claims that QRegularExpression + // works like QRegExp, which is incorrect. QRegularExpression regex(ui->leFind->text(), QRegularExpression::UseUnicodePropertiesOption); #else - QRegExp regex(ui->leFind->text()); + QRegExp regex(ui->leFind->text(), (options & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive); #endif - found = ui->tePacketBytes->find(regex); + found = ui->tePacketBytes->find(regex, std::move(options)); } else { - found = ui->tePacketBytes->find(ui->leFind->text()); + found = ui->tePacketBytes->find(ui->leFind->text(), std::move(options)); } if (found) { @@ -514,7 +536,7 @@ void ShowPacketBytesDialog::symbolizeBuffer(QByteArray &ba) ba.replace((char)0x7f, symbol); // DEL } -QByteArray ShowPacketBytesDialog::decodeQuotedPrintable(const guint8 *bytes, int length) +QByteArray ShowPacketBytesDialog::decodeQuotedPrintable(const uint8_t *bytes, int length) { QByteArray ba; @@ -542,7 +564,7 @@ QByteArray ShowPacketBytesDialog::decodeQuotedPrintable(const guint8 *bytes, int void ShowPacketBytesDialog::rot13(QByteArray &ba) { for (int i = 0; i < ba.length(); i++) { - gchar upper = g_ascii_toupper(ba[i]); + char upper = g_ascii_toupper(ba[i]); if (upper >= 'A' && upper <= 'M') ba[i] = ba[i] + 13; else if (upper >= 'N' && upper <= 'Z') ba[i] = ba[i] - 13; } @@ -552,12 +574,13 @@ void ShowPacketBytesDialog::updateFieldBytes(bool initialization) { int start = finfo_->start + start_; int length = end_ - start_ + 1; - const guint8 *bytes; - gsize new_length = 0; + const uint8_t *bytes; if (!finfo_->ds_tvb) return; + decode_as_name_.clear(); + switch (recent.gui_show_bytes_decode) { case DecodeAsNone: @@ -568,22 +591,40 @@ void ShowPacketBytesDialog::updateFieldBytes(bool initialization) case DecodeAsBASE64: { bytes = tvb_get_ptr(finfo_->ds_tvb, start, -1); - field_bytes_ = QByteArray((const char *)bytes, length); - if (field_bytes_.size() > 1) { - g_base64_decode_inplace(field_bytes_.data(), &new_length); + QByteArray ba = QByteArray::fromRawData((const char *)bytes, length); + if (ba.contains('-') || ba.contains('_')) { + field_bytes_ = QByteArray::fromBase64(ba, QByteArray::Base64UrlEncoding); + decode_as_name_ = "base64url"; + } else { + field_bytes_ = QByteArray::fromBase64(ba, QByteArray::Base64Encoding); + decode_as_name_ = "base64"; } - field_bytes_.resize((int)new_length); break; } case DecodeAsCompressed: { - tvbuff *uncompr_tvb = tvb_uncompress(finfo_->ds_tvb, start, length); - if (uncompr_tvb) { - bytes = tvb_get_ptr(uncompr_tvb, 0, -1); - field_bytes_ = QByteArray((const char *)bytes, tvb_reported_length(uncompr_tvb)); - tvb_free(uncompr_tvb); - } else { + static const QList tvb_uncompress_list = { + { "lz77", tvb_uncompress_lz77 }, + { "lz77huff", tvb_uncompress_lz77huff }, + { "lznt1", tvb_uncompress_lznt1 }, + { "snappy", tvb_uncompress_snappy }, + { "zlib", tvb_uncompress_zlib }, + { "zstd", tvb_uncompress_zstd }, + }; + tvbuff_t *uncompr_tvb = NULL; + + for (auto &tvb_uncompress : tvb_uncompress_list) { + uncompr_tvb = tvb_uncompress.function(finfo_->ds_tvb, start, length); + if (uncompr_tvb && tvb_reported_length(uncompr_tvb) > 0) { + bytes = tvb_get_ptr(uncompr_tvb, 0, -1); + field_bytes_ = QByteArray((const char *)bytes, tvb_reported_length(uncompr_tvb)); + decode_as_name_ = tr("compressed %1").arg(tvb_uncompress.name); + tvb_free(uncompr_tvb); + break; + } + } + if (!uncompr_tvb) { field_bytes_.clear(); } break; @@ -600,7 +641,7 @@ void ShowPacketBytesDialog::updateFieldBytes(bool initialization) #if GLIB_CHECK_VERSION(2, 66, 0) GBytes *ba = g_uri_unescape_bytes((const char*)bytes, length, NULL, NULL); if (ba != NULL) { - gsize size; + size_t size; const char* data = (const char *)g_bytes_unref_to_data(ba, &size); field_bytes_ = QByteArray(data, (int)size); } @@ -609,7 +650,7 @@ void ShowPacketBytesDialog::updateFieldBytes(bool initialization) if (uri_to_bytes((const char*)bytes, ba, length)) { field_bytes_ = QByteArray((const char *)ba->data, ba->len); } - g_byte_array_free(ba, TRUE); + g_byte_array_free(ba, true); #endif break; } @@ -635,11 +676,12 @@ void ShowPacketBytesDialog::updateFieldBytes(bool initialization) } updatePacketBytes(); + updateHintLabel(); } void ShowPacketBytesDialog::updatePacketBytes(void) { - static const gchar hexchars[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + static const char hexchars[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; ui->tePacketBytes->clear(); ui->tePacketBytes->setCurrentFont(mainApp->monospaceFont()); @@ -670,7 +712,7 @@ void ShowPacketBytesDialog::updatePacketBytes(void) QString text("char packet_bytes[] = {\n"); while (pos < len) { - gchar hexbuf[256]; + char hexbuf[256]; char *cur = hexbuf; int i; @@ -707,7 +749,7 @@ void ShowPacketBytesDialog::updatePacketBytes(void) QString text("let packet_bytes: [u8; _] = [\n"); while (pos < len) { - gchar hexbuf[256]; + char hexbuf[256]; char *cur = hexbuf; int i; @@ -755,7 +797,7 @@ void ShowPacketBytesDialog::updatePacketBytes(void) case SHOW_EBCDIC: { QByteArray ba(field_bytes_); - EBCDIC_to_ASCII((guint8*)ba.data(), static_cast(ba.length())); + EBCDIC_to_ASCII((uint8_t*)ba.data(), static_cast(ba.length())); sanitizeBuffer(ba, false); ui->tePacketBytes->setLineWrapMode(QTextEdit::WidgetWidth); ui->tePacketBytes->setPlainText(ba); diff --git a/ui/qt/show_packet_bytes_dialog.h b/ui/qt/show_packet_bytes_dialog.h index 80201c81..1f6183fa 100644 --- a/ui/qt/show_packet_bytes_dialog.h +++ b/ui/qt/show_packet_bytes_dialog.h @@ -11,7 +11,6 @@ #define SHOW_PACKET_BYTES_DIALOG_H #include -#include #include #ifdef HAVE_UNISTD_H @@ -31,6 +30,11 @@ class ShowPacketBytesDialog; class ShowPacketBytesTextEdit; } +struct uncompress_list_t { + QString name; + tvbuff_t *(*function)(tvbuff_t *, int, int); +}; + class ShowPacketBytesDialog : public WiresharkDialog { Q_OBJECT @@ -71,7 +75,7 @@ private: void updateHintLabel(); void sanitizeBuffer(QByteArray &ba, bool handle_CR); void symbolizeBuffer(QByteArray &ba); - QByteArray decodeQuotedPrintable(const guint8 *bytes, int length); + QByteArray decodeQuotedPrintable(const uint8_t *bytes, int length); void rot13(QByteArray &ba); void updateFieldBytes(bool initialization = false); void updatePacketBytes(); @@ -81,6 +85,7 @@ private: const field_info *finfo_; QByteArray field_bytes_; QString hint_label_; + QString decode_as_name_; QPushButton *print_button_; QPushButton *copy_button_; QPushButton *save_as_button_; diff --git a/ui/qt/show_packet_bytes_dialog.ui b/ui/qt/show_packet_bytes_dialog.ui index f60e625d..dfe03757 100644 --- a/ui/qt/show_packet_bytes_dialog.ui +++ b/ui/qt/show_packet_bytes_dialog.ui @@ -116,6 +116,13 @@ + + + + Case sensitive + + + diff --git a/ui/qt/simple_dialog.cpp b/ui/qt/simple_dialog.cpp index b45c7a19..c5a57d4d 100644 --- a/ui/qt/simple_dialog.cpp +++ b/ui/qt/simple_dialog.cpp @@ -90,8 +90,8 @@ simple_dialog_format_message(const char *msg) return g_strdup(msg); } -gpointer -simple_dialog(ESD_TYPE_E type, gint btn_mask, const gchar *msg_format, ...) +void * +simple_dialog(ESD_TYPE_E type, int btn_mask, const char *msg_format, ...) { va_list ap; @@ -103,8 +103,8 @@ simple_dialog(ESD_TYPE_E type, gint btn_mask, const gchar *msg_format, ...) return NULL; } -gpointer -simple_dialog_async(ESD_TYPE_E type, gint btn_mask, const gchar *msg_format, ...) +void * +simple_dialog_async(ESD_TYPE_E type, int btn_mask, const char *msg_format, ...) { va_list ap; @@ -121,7 +121,7 @@ simple_dialog_async(ESD_TYPE_E type, gint btn_mask, const gchar *msg_format, ... * and checkbox, and optional secondary text. */ void -simple_message_box(ESD_TYPE_E type, gboolean *notagain, +simple_message_box(ESD_TYPE_E type, bool *notagain, const char *secondary_msg, const char *msg_format, ...) { if (notagain && *notagain) { @@ -202,7 +202,7 @@ SimpleDialog::SimpleDialog(QWidget *parent, ESD_TYPE_E type, int btn_mask, const check_box_(0), message_box_(0) { - gchar *vmessage; + char *vmessage; QString message; vmessage = ws_strdup_vprintf(msg_format, ap); diff --git a/ui/qt/simple_dialog.h b/ui/qt/simple_dialog.h index 2afda98d..32163e09 100644 --- a/ui/qt/simple_dialog.h +++ b/ui/qt/simple_dialog.h @@ -14,8 +14,6 @@ #include -#include - #include "ui/simple_dialog.h" #include diff --git a/ui/qt/simple_statistics_dialog.cpp b/ui/qt/simple_statistics_dialog.cpp index ae715603..c03d6bef 100644 --- a/ui/qt/simple_statistics_dialog.cpp +++ b/ui/qt/simple_statistics_dialog.cpp @@ -47,7 +47,7 @@ bool register_simple_stat_tables(const void *key, void *value, void*) { stu->group, simple_stat_init, SimpleStatisticsDialog::createSimpleStatisticsDialog); - return FALSE; + return false; } enum { @@ -188,7 +188,7 @@ void SimpleStatisticsDialog::addMissingRows(struct _stat_data_t *stat_data) // the top-level tree item text set to the column labels for that table. // Add any missing tables and rows. - for (guint table_idx = 0; table_idx < stat_data->stat_tap_data->tables->len; table_idx++) { + for (unsigned table_idx = 0; table_idx < stat_data->stat_tap_data->tables->len; table_idx++) { stat_tap_table* st_table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, table_idx); QTreeWidgetItem *ti = NULL; @@ -200,7 +200,7 @@ void SimpleStatisticsDialog::addMissingRows(struct _stat_data_t *stat_data) } else { ti = statsTreeWidget()->topLevelItem(table_idx); } - for (guint element = ti->childCount(); element < st_table->num_elements; element++) { + for (unsigned element = ti->childCount(); element < st_table->num_elements; element++) { stat_tap_table_item_type* fields = stat_tap_get_field_data(st_table, element, 0); if (stu_->nfields > 0) { SimpleStatisticsTreeWidgetItem *ss_ti = new SimpleStatisticsTreeWidgetItem(ti, st_table->num_fields, fields); diff --git a/ui/qt/stats_tree_dialog.cpp b/ui/qt/stats_tree_dialog.cpp index 1ec66b7e..f51e252a 100644 --- a/ui/qt/stats_tree_dialog.cpp +++ b/ui/qt/stats_tree_dialog.cpp @@ -97,18 +97,15 @@ void StatsTreeDialog::setupNode(stat_node* node) } else { st_dlg->statsTreeWidget()->addTopLevelItem(ti); } - st_dlg->statsTreeWidget()->resizeColumnToContents(item_col_); } void StatsTreeDialog::fillTree() { if (!st_cfg_ || file_closed_) return; - QString display_name = gchar_free_to_qstring(stats_tree_get_displayname(st_cfg_->name)); - - // The GTK+ UI appends "Stats Tree" to the window title. If we do the same + // The GTK+ UI appended "Stats Tree" to the window title. If we do the same // here we should expand the name completely, e.g. to "Statistics Tree". - setWindowSubtitle(display_name); + setWindowSubtitle(st_cfg_->title); st_cfg_->pr = &cfg_pr_; cfg_pr_.st_dlg = this; @@ -122,7 +119,7 @@ void StatsTreeDialog::fillTree() // Add number of columns for this stats_tree QStringList header_labels; for (int count = 0; countnum_columns; count++) { - header_labels.push_back(stats_tree_get_column_name(count)); + header_labels.push_back(stats_tree_get_column_name(st_cfg_, count)); } statsTreeWidget()->setColumnCount(static_cast(header_labels.count())); statsTreeWidget()->setHeaderLabels(header_labels); @@ -142,10 +139,11 @@ void StatsTreeDialog::fillTree() cap_file_.retapPackets(); drawTreeItems(st_); - statsTreeWidget()->setSortingEnabled(true); removeTapListeners(); - st_cfg_->pr = NULL; + + statsTreeWidget()->setSortingEnabled(true); + statsTreeWidget()->resizeColumnToContents(item_col_); } void StatsTreeDialog::resetTap(void *st_ptr) @@ -167,7 +165,7 @@ void StatsTreeDialog::drawTreeItems(void *st_ptr) while (*iter) { stat_node *node = VariantPointer::asPtr((*iter)->data(item_col_, Qt::UserRole)); if (node) { - gchar **valstrs = stats_tree_get_values_from_node(node); + char **valstrs = stats_tree_get_values_from_node(node); for (int count = 0; countnum_columns; count++) { (*iter)->setText(count,valstrs[count]); g_free(valstrs[count]); diff --git a/ui/qt/stats_tree_dialog.h b/ui/qt/stats_tree_dialog.h index de040811..a5f0a236 100644 --- a/ui/qt/stats_tree_dialog.h +++ b/ui/qt/stats_tree_dialog.h @@ -14,8 +14,6 @@ #include -#include - #include "epan/stats_tree_priv.h" struct _tree_cfg_pres { diff --git a/ui/qt/strip_headers_dialog.cpp b/ui/qt/strip_headers_dialog.cpp index 73775ddf..35f6fa13 100644 --- a/ui/qt/strip_headers_dialog.cpp +++ b/ui/qt/strip_headers_dialog.cpp @@ -20,6 +20,8 @@ #include "ui/export_pdu_ui_utils.h" #include "ui/capture_globals.h" +#include "main_application.h" + StripHeadersDialog::StripHeadersDialog(QWidget *parent) : QDialog(parent), ui(new Ui::StripHeadersDialog) @@ -28,12 +30,15 @@ StripHeadersDialog::StripHeadersDialog(QWidget *parent) : ui->setupUi(this); + setWindowTitle(mainApp->windowTitleString(tr("Strip Headers"))); + for (tap_name_list = get_export_pdu_tap_list(); tap_name_list; tap_name_list = g_slist_next(tap_name_list)) { if (export_pdu_tap_get_encap((const char*)tap_name_list->data) != WTAP_ENCAP_WIRESHARK_UPPER_PDU) { ui->comboBox->addItem((const char*)(tap_name_list->data)); } } } + void StripHeadersDialog::on_buttonBox_accepted() { const QByteArray& filter = ui->displayFilterLineEdit->text().toUtf8(); @@ -41,6 +46,12 @@ void StripHeadersDialog::on_buttonBox_accepted() do_export_pdu(filter.constData(), global_capture_opts.temp_dir, tap_name.constData()); } + +void StripHeadersDialog::on_buttonBox_helpRequested() +{ + mainApp->helpTopicAction(HELP_STRIP_HEADERS_DIALOG); +} + StripHeadersDialog::~StripHeadersDialog() { delete ui; diff --git a/ui/qt/strip_headers_dialog.h b/ui/qt/strip_headers_dialog.h index bce54784..d048293b 100644 --- a/ui/qt/strip_headers_dialog.h +++ b/ui/qt/strip_headers_dialog.h @@ -30,6 +30,7 @@ private: private slots: void on_buttonBox_accepted(); + void on_buttonBox_helpRequested(); }; #endif // STRIP_HEADERS_DIALOG_H diff --git a/ui/qt/strip_headers_dialog.ui b/ui/qt/strip_headers_dialog.ui index cc40162a..3ea44b4c 100644 --- a/ui/qt/strip_headers_dialog.ui +++ b/ui/qt/strip_headers_dialog.ui @@ -26,7 +26,7 @@ Qt::Horizontal - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Help @@ -75,32 +75,12 @@ accepted() StripHeadersDialog accept() - - - 248 - 254 - - - 157 - 274 - -
buttonBox rejected() StripHeadersDialog reject() - - - 316 - 260 - - - 286 - 274 - -
diff --git a/ui/qt/supported_protocols_dialog.cpp b/ui/qt/supported_protocols_dialog.cpp index eea2d738..10457f23 100644 --- a/ui/qt/supported_protocols_dialog.cpp +++ b/ui/qt/supported_protocols_dialog.cpp @@ -93,6 +93,6 @@ void SupportedProtocolsDialog::on_searchLineEdit_textChanged(const QString &sear * the countdown. */ searchLineEditText = search_re; - guint gui_debounce_timer = prefs_get_uint_value("gui", "debounce.timer"); + unsigned gui_debounce_timer = prefs_get_uint_value("gui", "debounce.timer"); searchLineEditTimer->start(gui_debounce_timer); } diff --git a/ui/qt/tap_parameter_dialog.cpp b/ui/qt/tap_parameter_dialog.cpp index 4652b672..eeb838dd 100644 --- a/ui/qt/tap_parameter_dialog.cpp +++ b/ui/qt/tap_parameter_dialog.cpp @@ -43,10 +43,11 @@ #include #include "main_application.h" +#include + #include #include #include -#include // The GTK+ counterpart uses tap_param_dlg, which we don't use. If we // need tap parameters we should probably create a TapParameterDialog @@ -97,6 +98,7 @@ TapParameterDialog::TapParameterDialog(QWidget &parent, CaptureFile &cf, int hel QString filter = ui->displayFilterLineEdit->text(); emit updateFilter(filter); } + updateWidgets(); show_timer_ = new QTimer(this); setRetapOnShow(true); } @@ -496,7 +498,7 @@ void TapParameterDialog::updateWidgets() bool edit_enable = true; bool apply_enable = true; - if (file_closed_) { + if (file_closed_ || !cap_file_.isValid()) { edit_enable = false; apply_enable = false; } else if (!ui->displayFilterLineEdit->checkFilter()) { @@ -511,9 +513,9 @@ void TapParameterDialog::updateWidgets() void TapParameterDialog::on_applyFilterButton_clicked() { - beginRetapPackets(); - if (!ui->displayFilterLineEdit->checkFilter()) + if (!ui->displayFilterLineEdit->checkFilter()) { return; + } QString filter = ui->displayFilterLineEdit->text(); emit updateFilter(filter); @@ -528,7 +530,6 @@ void TapParameterDialog::on_applyFilterButton_clicked() fillTree(); ui->applyFilterButton->setEnabled(af_enabled); ui->displayFilterLineEdit->setEnabled(df_enabled); - endRetapPackets(); } void TapParameterDialog::on_actionCopyToClipboard_triggered() @@ -548,7 +549,7 @@ void TapParameterDialog::on_actionSaveAs_triggered() #ifdef Q_OS_WIN HANDLE da_ctx = set_thread_per_monitor_v2_awareness(); #endif - QFileDialog SaveAsDialog(this, mainApp->windowTitleString(tr("Save Statistics As…")), + WiresharkFileDialog SaveAsDialog(this, mainApp->windowTitleString(tr("Save Statistics As…")), get_open_dialog_initial_dir()); SaveAsDialog.setNameFilter(tr("Plain text file (*.txt);;" "Comma separated values (*.csv);;" @@ -582,7 +583,7 @@ void TapParameterDialog::on_actionSaveAs_triggered() } // Get selected filename and add extension of necessary - QString file_name = SaveAsDialog.selectedFiles()[0]; + QString file_name = SaveAsDialog.selectedNativePath(); if (!file_name.endsWith(file_ext, Qt::CaseInsensitive)) { file_name.append(file_ext); } diff --git a/ui/qt/tap_parameter_dialog.h b/ui/qt/tap_parameter_dialog.h index 1ed9db78..84a6f69e 100644 --- a/ui/qt/tap_parameter_dialog.h +++ b/ui/qt/tap_parameter_dialog.h @@ -18,8 +18,6 @@ #include "config.h" -#include - #include #include diff --git a/ui/qt/tcp_stream_dialog.cpp b/ui/qt/tcp_stream_dialog.cpp index b8e15429..881ee455 100644 --- a/ui/qt/tcp_stream_dialog.cpp +++ b/ui/qt/tcp_stream_dialog.cpp @@ -136,8 +136,8 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty ui->streamNumberSpinBox->setStyleSheet("QSpinBox { min-width: 2em; }"); - guint32 th_stream = select_tcpip_session(cap_file_); - if (th_stream == G_MAXUINT32) { + uint32_t th_stream = select_tcpip_session(cap_file_); + if (th_stream == UINT32_MAX) { done(QDialog::Rejected); return; } @@ -184,6 +184,7 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty ctx_menu_.addAction(ui->actionToggleSequenceNumbers); ctx_menu_.addAction(ui->actionToggleTimeOrigin); ctx_menu_.addAction(ui->actionCrosshairs); + connect(ui->actionCrosshairs, &QAction::triggered, this, &TCPStreamDialog::toggleTracerStyle); ctx_menu_.addSeparator(); ctx_menu_.addAction(ui->actionRoundTripTime); ctx_menu_.addAction(ui->actionThroughput); @@ -192,6 +193,11 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty ctx_menu_.addAction(ui->actionWindowScaling); set_action_shortcuts_visible_in_context_menu(ctx_menu_.actions()); + QCustomPlot *sp = ui->streamPlot; + + sp->setContextMenuPolicy(Qt::CustomContextMenu); + connect(sp, &QCustomPlot::customContextMenuRequested, this, &TCPStreamDialog::showContextMenu); + graph_.type = graph_type; graph_.stream = th_stream; findStream(); @@ -229,7 +235,6 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty ui->showBytesOutCheckBox->setChecked(true); ui->showBytesOutCheckBox->blockSignals(false); - QCustomPlot *sp = ui->streamPlot; QCPTextElement *file_title = new QCPTextElement(sp, gchar_free_to_qstring(cf_get_display_name(cap_file_))); file_title->setFont(sp->xAxis->labelFont()); title_ = new QCPTextElement(sp); @@ -569,9 +574,13 @@ void TCPStreamDialog::fillGraph(bool reset_axes, bool set_focus) ts_offset_ = 0; seq_offset_ = 0; - bool first = true; - guint64 bytes_fwd = 0; - guint64 bytes_rev = 0; + bool ts_unset = ts_origin_conn_; + // seq_origin_zero_ defaults to true. It really means something like + // "use relative or absolute depending on the TCP dissector preferences". + // If it's false, then calculate the offset to convert to the other. + bool seq_unset = !seq_origin_zero_; + uint64_t bytes_fwd = 0; + uint64_t bytes_rev = 0; int pkts_fwd = 0; int pkts_rev = 0; @@ -591,15 +600,37 @@ void TCPStreamDialog::fillGraph(bool reset_axes, bool set_focus) pkts_fwd++; } double ts = seg->rel_secs + seg->rel_usecs / 1000000.0; - if (first) { - if (ts_origin_conn_) ts_offset_ = ts; - if (seq_origin_zero_) { - if (compareHeaders(seg)) - seq_offset_ = seg->th_seq; - else - seq_offset_ = seg->th_ack; + if (ts_unset) { + ts_offset_ = ts; + ts_unset = false; + } + if (seq_unset) { + if (compareHeaders(seg)) { + if (seg->th_seq != seg->th_rawseq) { + seq_offset_ = seg->th_seq - seg->th_rawseq; + } else { + // As with the TCP dissector, if this isn't the SYN or SYN-ACK, + // start the relative sequence numbers at 1. + if (seg->th_flags & TH_SYN) { + seq_offset_ = seg->th_seq; + } else { + seq_offset_ = seg->th_seq - 1; + } + } + seq_unset = false; + } else { + // A SYN in the reverse direction does not tell us the base + // sequence number, but for other segments (including SYN-ACK) + // start the offset at 1, like the TCP dissector. + if ((seg->th_flags & TH_SYN) != TH_SYN) { + if (seg->th_seq != seg->th_rawseq) { + seq_offset_ = seg->th_seq - seg->th_rawseq; + } else { + seq_offset_ -= seg->th_ack - 1; + } + seq_unset = false; + } } - first = false; } if (insert) { time_stamp_map_.insert(ts - ts_offset_, seg); @@ -765,7 +796,8 @@ void TCPStreamDialog::resetAxes() // } double axis_pixels = sp->xAxis->axisRect()->width(); - sp->xAxis->scaleRange((axis_pixels + (pixel_pad * 2)) / axis_pixels, sp->xAxis->range().center()); + sp->xAxis->scaleRange((axis_pixels + (pixel_pad * 2)) / axis_pixels, + sp->xAxis->range().center()); if (sp->yAxis2->visible()) { double ratio = sp->yAxis2->range().size() / sp->yAxis->range().size(); @@ -774,7 +806,8 @@ void TCPStreamDialog::resetAxes() } axis_pixels = sp->yAxis->axisRect()->height(); - sp->yAxis->scaleRange((axis_pixels + (pixel_pad * 2)) / axis_pixels, sp->yAxis->range().center()); + sp->yAxis->scaleRange((axis_pixels + (pixel_pad * 2)) / axis_pixels, + sp->yAxis->range().center()); sp->replot(); } @@ -925,7 +958,7 @@ void TCPStreamDialog::fillTcptrace() // I expect this to be _relatively_ small, so using vector to store // them. If this performs badly, it can be refactored with std::list // or std::map. -typedef std::pair sack_t; +typedef std::pair sack_t; typedef std::vector sack_list_t; static inline bool compare_sack(const sack_t& s1, const sack_t& s2) { return tcp_seq_before(s1.first, s2.first); @@ -935,8 +968,8 @@ static inline bool compare_sack(const sack_t& s1, const sack_t& s2) { // - removes previously sacked ranges from seglen (and from old_sacks), // - adds newly sacked ranges to seglen (and to old_sacks) static void -goodput_adjust_for_sacks(guint32 *seglen, guint32 last_ack, - sack_list_t& new_sacks, guint8 num_sack_ranges, +goodput_adjust_for_sacks(uint32_t *seglen, uint32_t last_ack, + sack_list_t& new_sacks, uint8_t num_sack_ranges, sack_list_t& old_sacks) { // Step 1 - For any old_sacks acked by last_ack, @@ -1205,8 +1238,8 @@ void TCPStreamDialog::fillThroughput() QVector tput_times, gput_times; QVector tputs, gputs; int oldest_seg = 0, oldest_ack = 0; - guint64 seg_sum = 0, ack_sum = 0; - guint32 seglen = 0; + uint64_t seg_sum = 0, ack_sum = 0; + uint32_t seglen = 0; #ifdef USE_SACKS_IN_GOODPUT_CALC // to incorporate SACKED segments into goodput calculation, @@ -1224,7 +1257,7 @@ void TCPStreamDialog::fillThroughput() // need first acked sequence number to jump-start // computation of acked bytes per packet - guint32 last_ack = 0; + uint32_t last_ack = 0; for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { // first reverse packet with ACK flag tells us first acked sequence # if (!compareHeaders(seg) && (seg->th_flags & TH_ACK)) { @@ -1253,7 +1286,7 @@ void TCPStreamDialog::fillThroughput() QVector& r_Xput_times = is_forward_seg ? tput_times : gput_times; QVector& r_Xputs = is_forward_seg ? tputs : gputs; int& r_oldest = is_forward_seg ? oldest_seg : oldest_ack; - guint64& r_sum = is_forward_seg ? seg_sum : ack_sum; + uint64_t& r_sum = is_forward_seg ? seg_sum : ack_sum; double ts = (seg->rel_secs + seg->rel_usecs / 1000000.0) - ts_offset_; @@ -1463,9 +1496,15 @@ void TCPStreamDialog::fillRoundTripTime() base_graph_->setLineStyle(QCPGraph::lsLine); QVector x_vals, rtt; - guint32 seq_base = 0; + uint32_t seq_base = 0; struct rtt_unack *unack_list = NULL, *u = NULL; for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { + // XXX - Should this just use seq_offset_? Our comparisons are + // wraparound now and should be fine without computing a base + // (we're not doing anything to extend sequence numbers to handle + // connections longer than 4 GiB), and that would let the user swap. + // (We should make clicking the X axis swap seq_origin_zero_ if + // bySeqNumber is checked.) if (compareHeaders(seg)) { seq_base = seg->th_seq; break; @@ -1473,7 +1512,7 @@ void TCPStreamDialog::fillRoundTripTime() } for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { if (compareHeaders(seg)) { - guint32 seqno = seg->th_seq - seq_base; + uint32_t seqno = seg->th_seq - seq_base; if (seg->th_seglen && !rtt_is_retrans(unack_list, seqno)) { double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0; rt_val -= ts_offset_; @@ -1486,7 +1525,7 @@ void TCPStreamDialog::fillRoundTripTime() rtt_put_unack_on_list(&unack_list, u); } } else { - guint32 ack_no = seg->th_ack - seq_base; + uint32_t ack_no = seg->th_ack - seq_base; double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0; rt_val -= ts_offset_; struct rtt_unack *v; @@ -1519,8 +1558,8 @@ void TCPStreamDialog::fillRoundTripTime() // If we link those back into the list between u and v, // then each subsequent SACK selectively ACKs that range. for (int i = 0; i < seg->num_sack_ranges; ++i) { - guint32 left = seg->sack_left_edge[i] - seq_base; - guint32 right = seg->sack_right_edge[i] - seq_base; + uint32_t left = seg->sack_left_edge[i] - seq_base; + uint32_t right = seg->sack_right_edge[i] - seq_base; u = rtt_selectively_ack_range(x_vals, bySeqNumber, rtt, &unack_list, u, v, left, right, rt_val); @@ -1553,7 +1592,11 @@ void TCPStreamDialog::fillWindowScale() QVector rel_time, win_size; QVector cwnd_time, cwnd_size; - guint32 last_ack = 0; + uint32_t last_ack = 0; + + /* highest expected SEQ seen so far */ + uint32_t max_next_seq = 0; + bool found_first_ack = false; for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { double ts = seg->rel_secs + seg->rel_usecs / 1000000.0; @@ -1561,16 +1604,21 @@ void TCPStreamDialog::fillWindowScale() // The receive window that applies to this flow comes // from packets in the opposite direction if (compareHeaders(seg)) { - // compute bytes_in_flight for cwnd graph - guint32 end_seq = seg->th_seq + seg->th_seglen; + /* compute bytes_in_flight for cwnd graph, + * by comparing the highest next SEQ to the latest ACK + */ + uint32_t end_seq = seg->th_seq + seg->th_seglen; + if(end_seq > max_next_seq) { + max_next_seq = end_seq; + } if (found_first_ack && tcp_seq_eq_or_after(end_seq, last_ack)) { cwnd_time.append(ts - ts_offset_); - cwnd_size.append((double)(end_seq - last_ack)); + cwnd_size.append((double)(max_next_seq - last_ack)); } } else { // packet in opposite direction - has advertised rwin - guint16 flags = seg->th_flags; + uint16_t flags = seg->th_flags; if ((flags & (TH_SYN|TH_RST)) == 0) { rel_time.append(ts - ts_offset_); @@ -1679,6 +1727,11 @@ QRectF TCPStreamDialog::getZoomRanges(QRect zoom_rect) return zoom_ranges; } +void TCPStreamDialog::showContextMenu(const QPoint& pos) +{ + ctx_menu_.popup(ui->streamPlot->mapToGlobal(pos)); +} + void TCPStreamDialog::graphClicked(QMouseEvent *event) { QCustomPlot *sp = ui->streamPlot; @@ -1686,15 +1739,7 @@ void TCPStreamDialog::graphClicked(QMouseEvent *event) // mouse press on graph should reset focus to graph sp->setFocus(); - if (event->button() == Qt::RightButton) { - // XXX We should find some way to get streamPlot to handle a - // contextMenuEvent instead. -#if QT_VERSION >= QT_VERSION_CHECK(6, 0 ,0) - ctx_menu_.popup(event->globalPosition().toPoint()); -#else - ctx_menu_.popup(event->globalPos()); -#endif - } else if (mouse_drags_) { + if (mouse_drags_) { if (sp->axisRect()->rect().contains(event->pos())) { sp->setCursor(QCursor(Qt::ClosedHandCursor)); } @@ -1802,12 +1847,16 @@ void TCPStreamDialog::mouseMoved(QMouseEvent *event) tracer_->setVisible(true); packet_num_ = packet_seg->num; + // XXX - We should probably change the sequence number displayed by + // seq_offset_ but in that case we should also store a base sequence + // number for the other direction so the th_ack can also be adjusted + // to a relative sequence number. hint += tr("%1 %2 (%3s len %4 seq %5 ack %6 win %7)") .arg(cap_file_ ? tr("Click to select packet") : tr("Packet")) .arg(packet_num_) .arg(QString::number(packet_seg->rel_secs + packet_seg->rel_usecs / 1000000.0, 'g', 4)) .arg(packet_seg->th_seglen) - .arg(packet_seg->th_seq) + .arg(packet_seg->th_seq) // - seq_offset_) .arg(packet_seg->th_ack) .arg(packet_seg->th_win); tracer_->setGraphKey(ui->streamPlot->xAxis->pixelToCoord(event->pos().x())); @@ -2130,7 +2179,7 @@ void TCPStreamDialog::on_actionPreviousStream_triggered() void TCPStreamDialog::on_actionSwitchDirection_triggered() { address tmp_addr; - guint16 tmp_port; + uint16_t tmp_port; copy_address(&tmp_addr, &graph_.src_address); tmp_port = graph_.src_port; diff --git a/ui/qt/tcp_stream_dialog.h b/ui/qt/tcp_stream_dialog.h index c5b97de0..4281538b 100644 --- a/ui/qt/tcp_stream_dialog.h +++ b/ui/qt/tcp_stream_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include #include @@ -71,7 +69,7 @@ private: double ts_offset_; bool ts_origin_conn_; QMap sequence_num_map_; - double seq_offset_; + uint32_t seq_offset_; bool seq_origin_zero_; struct tcp_graph graph_; QCPTextElement *title_; @@ -91,7 +89,7 @@ private: QCPGraph *zero_win_graph_; QCPItemTracer *tracer_; QRectF axis_bounds_; - guint32 packet_num_; + uint32_t packet_num_; QTransform y_axis_xfrm_; bool mouse_drags_; QRubberBand *rubber_band_; @@ -141,6 +139,7 @@ private: QRectF getZoomRanges(QRect zoom_rect); private slots: + void showContextMenu(const QPoint &pos); void graphClicked(QMouseEvent *event); void axisClicked(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event); void mouseMoved(QMouseEvent *event); diff --git a/ui/qt/time_shift_dialog.cpp b/ui/qt/time_shift_dialog.cpp index f1b325f0..5dab7618 100644 --- a/ui/qt/time_shift_dialog.cpp +++ b/ui/qt/time_shift_dialog.cpp @@ -116,7 +116,7 @@ void TimeShiftDialog::enableWidgets() void TimeShiftDialog::checkFrameNumber(SyntaxLineEdit &frame_le) { bool frame_valid; - guint frame_num = frame_le.text().toUInt(&frame_valid); + unsigned frame_num = frame_le.text().toUInt(&frame_valid); syntax_err_.clear(); if (frame_le.text().isEmpty()) { @@ -137,7 +137,7 @@ void TimeShiftDialog::checkDateTime(SyntaxLineEdit &time_le) { int Y, M, D, h, m; long double s; - const gchar *err_str; + const char *err_str; syntax_err_.clear(); if (time_le.text().isEmpty()) { @@ -175,8 +175,8 @@ void TimeShiftDialog::on_shiftAllTimeLineEdit_textChanged(const QString &sa_text { int h, m; long double s; - gboolean neg; - const gchar *err_str; + bool neg; + const char *err_str; syntax_err_.clear(); if (sa_text.isEmpty()) { @@ -223,7 +223,7 @@ void TimeShiftDialog::on_setTwoTimeLineEdit_textChanged(const QString &) void TimeShiftDialog::applyTimeShift() { - const gchar *err_str = NULL; + const char *err_str = NULL; if (!cap_file_ || cap_file_->state == FILE_CLOSED || cap_file_->state == FILE_READ_PENDING) return; diff --git a/ui/qt/time_shift_dialog.h b/ui/qt/time_shift_dialog.h index 65164946..4e218ba4 100644 --- a/ui/qt/time_shift_dialog.h +++ b/ui/qt/time_shift_dialog.h @@ -12,8 +12,6 @@ #include -#include - #include "cfile.h" #include diff --git a/ui/qt/uat_dialog.cpp b/ui/qt/uat_dialog.cpp index 6f9d2a7c..bf518888 100644 --- a/ui/qt/uat_dialog.cpp +++ b/ui/qt/uat_dialog.cpp @@ -70,10 +70,6 @@ UatDialog::UatDialog(QWidget *parent, epan_uat *uat) : ui->uatTreeView->setEditTriggers(ui->uatTreeView->editTriggers() | QAbstractItemView::CurrentChanged | QAbstractItemView::AnyKeyPressed); - // Need to add uat_move or uat_insert to the UAT API. - ui->uatTreeView->setDragEnabled(false); -// qDebug() << "FIX Add drag reordering to UAT dialog"; - // Do NOT start editing the first column for the first item ui->uatTreeView->setCurrentIndex(QModelIndex()); } @@ -106,7 +102,7 @@ void UatDialog::setUat(epan_uat *uat) connect(copy_button, &CopyFromProfileButton::copyProfile, this, &UatDialog::copyFromProfile); } - QString abs_path = gchar_free_to_qstring(uat_get_actual_filename(uat_, FALSE)); + QString abs_path = gchar_free_to_qstring(uat_get_actual_filename(uat_, false)); if (abs_path.length() > 0) { ui->pathLabel->setText(abs_path); ui->pathLabel->setUrl(QUrl::fromLocalFile(abs_path).toString()); @@ -120,6 +116,7 @@ void UatDialog::setUat(epan_uat *uat) uat_delegate_ = new UatDelegate; ui->uatTreeView->setModel(uat_model_); ui->uatTreeView->setItemDelegate(uat_delegate_); + ui->uatTreeView->setSelectionMode(QAbstractItemView::ContiguousSelection); resizeColumns(); ui->clearToolButton->setEnabled(uat_model_->rowCount() != 0); @@ -129,6 +126,9 @@ void UatDialog::setUat(epan_uat *uat) this, SLOT(modelRowsRemoved())); connect(uat_model_, SIGNAL(modelReset()), this, SLOT(modelRowsReset())); + connect(ui->uatTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, + this, &UatDialog::uatTreeViewSelectionChanged); + ok_button_->setEnabled(!uat_model_->hasErrors()); if (uat_->help && strlen(uat_->help) > 0) { @@ -144,9 +144,9 @@ void UatDialog::setUat(epan_uat *uat) void UatDialog::copyFromProfile(QString filename) { - gchar *err = NULL; + char *err = NULL; if (uat_load(uat_, filename.toUtf8().constData(), &err)) { - uat_->changed = TRUE; + uat_->changed = true; uat_model_->reloadUat(); } else { report_failure("Error while loading %s: %s", uat_->name, err); @@ -176,6 +176,7 @@ void UatDialog::modelRowsRemoved() ui->moveUpToolButton->setEnabled(false); ui->moveDownToolButton->setEnabled(false); } + ui->clearToolButton->setEnabled(uat_model_->rowCount() != 0); checkForErrorHint(current, QModelIndex()); ok_button_->setEnabled(!uat_model_->hasErrors()); @@ -190,23 +191,32 @@ void UatDialog::modelRowsReset() ui->moveDownToolButton->setEnabled(false); } +void UatDialog::uatTreeViewSelectionChanged(const QItemSelection&, const QItemSelection&) +{ + QModelIndexList selectedRows = ui->uatTreeView->selectionModel()->selectedRows(); + qsizetype num_selected = selectedRows.size(); + if (num_selected > 0) { + std::sort(selectedRows.begin(), selectedRows.end()); + ui->deleteToolButton->setEnabled(true); + ui->copyToolButton->setEnabled(true); + ui->moveUpToolButton->setEnabled(selectedRows.first().row() > 0); + ui->moveDownToolButton->setEnabled(selectedRows.last().row() < uat_model_->rowCount() - 1); + } else { + ui->deleteToolButton->setEnabled(false); + ui->copyToolButton->setEnabled(false); + ui->moveUpToolButton->setEnabled(false); + ui->moveDownToolButton->setEnabled(false); + } +} // Invoked when a different field is selected. Note: when selecting a different // field after editing, this event is triggered after modelDataChanged. void UatDialog::on_uatTreeView_currentItemChanged(const QModelIndex ¤t, const QModelIndex &previous) { if (current.isValid()) { - ui->deleteToolButton->setEnabled(true); ui->clearToolButton->setEnabled(true); - ui->copyToolButton->setEnabled(true); - ui->moveUpToolButton->setEnabled(current.row() != 0); - ui->moveDownToolButton->setEnabled(current.row() != (uat_model_->rowCount() - 1)); } else { - ui->deleteToolButton->setEnabled(false); ui->clearToolButton->setEnabled(false); - ui->copyToolButton->setEnabled(false); - ui->moveUpToolButton->setEnabled(false); - ui->moveDownToolButton->setEnabled(false); } checkForErrorHint(current, previous); @@ -289,46 +299,86 @@ void UatDialog::on_newToolButton_clicked() void UatDialog::on_deleteToolButton_clicked() { - const QModelIndex ¤t = ui->uatTreeView->currentIndex(); - if (uat_model_ && current.isValid()) { - if (!uat_model_->removeRows(current.row(), 1)) { - qDebug() << "Failed to remove row"; + if (uat_model_ == nullptr) { + return; + } + + for (const auto &range : ui->uatTreeView->selectionModel()->selection()) { + // Each QItemSelectionRange is contiguous + if (!range.isEmpty()) { + if (!uat_model_->removeRows(range.top(), range.bottom() - range.top() + 1)) { + qDebug() << "Failed to remove rows" << range.top() << "to" << range.bottom(); + } } } } void UatDialog::on_copyToolButton_clicked() { - addRecord(true); + if (uat_model_ == nullptr) { + return; + } + + QModelIndexList selectedRows = ui->uatTreeView->selectionModel()->selectedRows(); + if (selectedRows.size() > 0) { + std::sort(selectedRows.begin(), selectedRows.end()); + + QModelIndex copyIdx; + + for (const auto &idx : selectedRows) { + copyIdx = uat_model_->copyRow(idx); + if (!copyIdx.isValid()) + { + qDebug() << "Failed to copy row" << idx.row(); + } + // trigger updating error messages and the OK button state. + modelDataChanged(copyIdx); + } + // due to an EditTrigger, this will also start editing. + ui->uatTreeView->setCurrentIndex(copyIdx); + } + } void UatDialog::on_moveUpToolButton_clicked() { - const QModelIndex ¤t = ui->uatTreeView->currentIndex(); - int current_row = current.row(); - if (uat_model_ && current.isValid() && current_row > 0) { - if (!uat_model_->moveRow(current_row, current_row - 1)) { - qDebug() << "Failed to move row up"; - return; + if (uat_model_ == nullptr) { + return; + } + + for (const auto &range : ui->uatTreeView->selectionModel()->selection()) { + // Each QItemSelectionRange is contiguous + if (!range.isEmpty() && range.top() > 0) { + // Swap range of rows with the row above the top + if (! uat_model_->moveRows(QModelIndex(), range.top(), range.bottom() - range.top() + 1, QModelIndex(), range.top() - 1)) { + qDebug() << "Failed to move up rows" << range.top() << "to" << range.bottom(); + } + // Our moveRows implementation calls begin/endMoveRows(), so + // range.top() already has the new row number. + ui->moveUpToolButton->setEnabled(range.top() > 0); + ui->moveDownToolButton->setEnabled(true); } - current_row--; - ui->moveUpToolButton->setEnabled(current_row > 0); - ui->moveDownToolButton->setEnabled(current_row < (uat_model_->rowCount() - 1)); } } void UatDialog::on_moveDownToolButton_clicked() { - const QModelIndex ¤t = ui->uatTreeView->currentIndex(); - int current_row = current.row(); - if (uat_model_ && current.isValid() && current_row < (uat_model_->rowCount() - 1)) { - if (!uat_model_->moveRow(current_row, current_row + 1)) { - qDebug() << "Failed to move row down"; - return; + if (uat_model_ == nullptr) { + return; + } + + for (const auto &range : ui->uatTreeView->selectionModel()->selection()) { + // Each QItemSelectionRange is contiguous + if (!range.isEmpty() && range.bottom() + 1 < uat_model_->rowCount()) { + // Swap range of rows with the row below the top + if (! uat_model_->moveRows(QModelIndex(), range.top(), range.bottom() - range.top() + 1, QModelIndex(), range.bottom() + 1)) { + qDebug() << "Failed to move down rows" << range.top() << "to" << range.bottom(); + } + // Our moveRows implementation calls begin/endMoveRows, so + // range.bottom() already has the new row number. + ui->moveUpToolButton->setEnabled(true); + ui->moveDownToolButton->setEnabled(range.bottom() < uat_model_->rowCount() - 1); } - current_row++; - ui->moveUpToolButton->setEnabled(current_row > 0); - ui->moveDownToolButton->setEnabled(current_row < (uat_model_->rowCount() - 1)); } } diff --git a/ui/qt/uat_dialog.h b/ui/qt/uat_dialog.h index 92d7d21b..6316198a 100644 --- a/ui/qt/uat_dialog.h +++ b/ui/qt/uat_dialog.h @@ -12,14 +12,13 @@ #include -#include - #include "geometry_state_dialog.h" #include #include class QComboBox; class QPushButton; +class QItemSelection; struct epan_uat; @@ -42,6 +41,7 @@ private slots: void modelDataChanged(const QModelIndex &topLeft); void modelRowsRemoved(); void modelRowsReset(); + void uatTreeViewSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void on_uatTreeView_currentItemChanged(const QModelIndex ¤t, const QModelIndex &previous); void acceptChanges(); void rejectChanges(); diff --git a/ui/qt/uat_dialog.ui b/ui/qt/uat_dialog.ui index cdc8fbe6..3f373948 100644 --- a/ui/qt/uat_dialog.ui +++ b/ui/qt/uat_dialog.ui @@ -12,7 +12,7 @@ - + @@ -48,7 +48,7 @@ false - Remove this entry. + Remove the selected entry(ies). @@ -58,7 +58,7 @@ false - Copy this entry. + Copy the selected entry(ies). @@ -71,7 +71,7 @@ false - Move entry up. + Move the selected entry(ies) up. @@ -84,7 +84,7 @@ false - Move entry down. + Move the selected entry(ies) down. @@ -144,9 +144,9 @@
widgets/elided_label.h
- TabnavTreeView + RowMoveTreeView QTreeView -
widgets/tabnav_tree_view.h
+
widgets/rowmove_tree_view.h
StockIconToolButton diff --git a/ui/qt/uat_frame.cpp b/ui/qt/uat_frame.cpp index c48cf4c2..1a099feb 100644 --- a/ui/qt/uat_frame.cpp +++ b/ui/qt/uat_frame.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include #include "uat_frame.h" @@ -65,8 +63,6 @@ UatFrame::UatFrame(QWidget *parent) : // start editing as soon as the field is selected or when typing starts ui->uatTreeView->setEditTriggers(ui->uatTreeView->editTriggers() | QAbstractItemView::CurrentChanged | QAbstractItemView::AnyKeyPressed); - - // XXX - Need to add uat_move or uat_insert to the UAT API for drag/drop } UatFrame::~UatFrame() @@ -95,7 +91,7 @@ void UatFrame::setUat(epan_uat *uat) connect(ui->copyFromProfileButton, &CopyFromProfileButton::copyProfile, this, &UatFrame::copyFromProfile); } - QString abs_path = gchar_free_to_qstring(uat_get_actual_filename(uat_, FALSE)); + QString abs_path = gchar_free_to_qstring(uat_get_actual_filename(uat_, false)); if (abs_path.length() > 0) { ui->pathLabel->setText(abs_path); ui->pathLabel->setUrl(QUrl::fromLocalFile(abs_path).toString()); @@ -109,6 +105,7 @@ void UatFrame::setUat(epan_uat *uat) uat_delegate_ = new UatDelegate; ui->uatTreeView->setModel(uat_model_); ui->uatTreeView->setItemDelegate(uat_delegate_); + ui->uatTreeView->setSelectionMode(QAbstractItemView::ContiguousSelection); resizeColumns(); ui->clearToolButton->setEnabled(uat_model_->rowCount() != 0); @@ -117,6 +114,9 @@ void UatFrame::setUat(epan_uat *uat) connect(uat_model_, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(modelRowsRemoved())); connect(uat_model_, SIGNAL(modelReset()), this, SLOT(modelRowsReset())); + + connect(ui->uatTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, + this, &UatFrame::uatTreeViewSelectionChanged); } setWindowTitle(title); @@ -124,9 +124,9 @@ void UatFrame::setUat(epan_uat *uat) void UatFrame::copyFromProfile(QString filename) { - gchar *err = NULL; + char *err = NULL; if (uat_load(uat_, filename.toUtf8().constData(), &err)) { - uat_->changed = TRUE; + uat_->changed = true; uat_model_->reloadUat(); } else { report_failure("Error while loading %s: %s", uat_->name, err); @@ -205,23 +205,33 @@ void UatFrame::addRecord(bool copy_from_current) modelDataChanged(new_index); } -// Invoked when a different field is selected. Note: when selecting a different -// field after editing, this event is triggered after modelDataChanged. -void UatFrame::on_uatTreeView_currentItemChanged(const QModelIndex ¤t, const QModelIndex &previous) +void UatFrame::uatTreeViewSelectionChanged(const QItemSelection&, const QItemSelection&) { - if (current.isValid()) { + QModelIndexList selectedRows = ui->uatTreeView->selectionModel()->selectedRows(); + qsizetype num_selected = selectedRows.size(); + if (num_selected > 0) { + std::sort(selectedRows.begin(), selectedRows.end()); ui->deleteToolButton->setEnabled(true); - ui->clearToolButton->setEnabled(true); ui->copyToolButton->setEnabled(true); - ui->moveUpToolButton->setEnabled(current.row() != 0); - ui->moveDownToolButton->setEnabled(current.row() != (uat_model_->rowCount() - 1)); + ui->moveUpToolButton->setEnabled(selectedRows.first().row() > 0); + ui->moveDownToolButton->setEnabled(selectedRows.last().row() < uat_model_->rowCount() - 1); } else { ui->deleteToolButton->setEnabled(false); - ui->clearToolButton->setEnabled(false); ui->copyToolButton->setEnabled(false); ui->moveUpToolButton->setEnabled(false); ui->moveDownToolButton->setEnabled(false); } +} + +// Invoked when a different field is selected. Note: when selecting a different +// field after editing, this event is triggered after modelDataChanged. +void UatFrame::on_uatTreeView_currentItemChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + if (current.isValid()) { + ui->clearToolButton->setEnabled(true); + } else { + ui->clearToolButton->setEnabled(false); + } checkForErrorHint(current, previous); } @@ -247,6 +257,7 @@ void UatFrame::modelRowsRemoved() ui->moveUpToolButton->setEnabled(false); ui->moveDownToolButton->setEnabled(false); } + ui->clearToolButton->setEnabled(uat_model_->rowCount() != 0); checkForErrorHint(current, QModelIndex()); } @@ -311,46 +322,86 @@ void UatFrame::on_newToolButton_clicked() void UatFrame::on_deleteToolButton_clicked() { - const QModelIndex ¤t = ui->uatTreeView->currentIndex(); - if (uat_model_ && current.isValid()) { - if (!uat_model_->removeRows(current.row(), 1)) { - qDebug() << "Failed to remove row"; + if (uat_model_ == nullptr) { + return; + } + + for (const auto &range : ui->uatTreeView->selectionModel()->selection()) { + // Each QItemSelectionRange is contiguous + if (!range.isEmpty()) { + if (!uat_model_->removeRows(range.top(), range.bottom() - range.top() + 1)) { + qDebug() << "Failed to remove rows" << range.top() << "to" << range.bottom(); + } } } } void UatFrame::on_copyToolButton_clicked() { - addRecord(true); + if (uat_model_ == nullptr) { + return; + } + + QModelIndexList selectedRows = ui->uatTreeView->selectionModel()->selectedRows(); + if (selectedRows.size() > 0) { + std::sort(selectedRows.begin(), selectedRows.end()); + + QModelIndex copyIdx; + + for (const auto &idx : selectedRows) { + copyIdx = uat_model_->copyRow(idx); + if (!copyIdx.isValid()) + { + qDebug() << "Failed to copy row" << idx.row(); + } + // trigger updating error messages and the OK button state. + modelDataChanged(copyIdx); + } + // due to an EditTrigger, this will also start editing. + ui->uatTreeView->setCurrentIndex(copyIdx); + } + } void UatFrame::on_moveUpToolButton_clicked() { - const QModelIndex ¤t = ui->uatTreeView->currentIndex(); - int current_row = current.row(); - if (uat_model_ && current.isValid() && current_row > 0) { - if (!uat_model_->moveRow(current_row, current_row - 1)) { - qDebug() << "Failed to move row up"; - return; + if (uat_model_ == nullptr) { + return; + } + + for (const auto &range : ui->uatTreeView->selectionModel()->selection()) { + // Each QItemSelectionRange is contiguous + if (!range.isEmpty() && range.top() > 0) { + // Swap range of rows with the row above the top + if (! uat_model_->moveRows(QModelIndex(), range.top(), range.bottom() - range.top() + 1, QModelIndex(), range.top() - 1)) { + qDebug() << "Failed to move up rows" << range.top() << "to" << range.bottom(); + } + // Our moveRows implementation calls begin/endMoveRows(), so + // range.top() already has the new row number. + ui->moveUpToolButton->setEnabled(range.top() > 0); + ui->moveDownToolButton->setEnabled(true); } - current_row--; - ui->moveUpToolButton->setEnabled(current_row > 0); - ui->moveDownToolButton->setEnabled(current_row < (uat_model_->rowCount() - 1)); } } void UatFrame::on_moveDownToolButton_clicked() { - const QModelIndex ¤t = ui->uatTreeView->currentIndex(); - int current_row = current.row(); - if (uat_model_ && current.isValid() && current_row < (uat_model_->rowCount() - 1)) { - if (!uat_model_->moveRow(current_row, current_row + 1)) { - qDebug() << "Failed to move row down"; - return; + if (uat_model_ == nullptr) { + return; + } + + for (const auto &range : ui->uatTreeView->selectionModel()->selection()) { + // Each QItemSelectionRange is contiguous + if (!range.isEmpty() && range.bottom() + 1 < uat_model_->rowCount()) { + // Swap range of rows with the row below the top + if (! uat_model_->moveRows(QModelIndex(), range.top(), range.bottom() - range.top() + 1, QModelIndex(), range.bottom() + 1)) { + qDebug() << "Failed to move down rows" << range.top() << "to" << range.bottom(); + } + // Our moveRows implementation calls begin/endMoveRows, so + // range.bottom() already has the new row number. + ui->moveUpToolButton->setEnabled(true); + ui->moveDownToolButton->setEnabled(range.bottom() < uat_model_->rowCount() - 1); } - current_row++; - ui->moveUpToolButton->setEnabled(current_row > 0); - ui->moveDownToolButton->setEnabled(current_row < (uat_model_->rowCount() - 1)); } } diff --git a/ui/qt/uat_frame.h b/ui/qt/uat_frame.h index 870bba9c..f20c10ce 100644 --- a/ui/qt/uat_frame.h +++ b/ui/qt/uat_frame.h @@ -16,6 +16,8 @@ #include #include +class QItemSelection; + namespace Ui { class UatFrame; } @@ -54,6 +56,7 @@ private slots: void modelDataChanged(const QModelIndex &topLeft); void modelRowsRemoved(); void modelRowsReset(); + void uatTreeViewSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void on_uatTreeView_currentItemChanged(const QModelIndex ¤t, const QModelIndex &previous); void on_newToolButton_clicked(); void on_deleteToolButton_clicked(); diff --git a/ui/qt/uat_frame.ui b/ui/qt/uat_frame.ui index 452ae65d..a49fc29c 100644 --- a/ui/qt/uat_frame.ui +++ b/ui/qt/uat_frame.ui @@ -18,7 +18,7 @@
- + @@ -54,7 +54,7 @@ false - Remove this entry. + Remove the selected entry(ies). @@ -64,7 +64,7 @@ false - Copy this entry. + Copy the selected entry(ies). @@ -74,7 +74,7 @@ - Move entry up. + Move the selected entry(ies) up. @@ -84,7 +84,7 @@ - Move entry down. + Move the selected entry(ies) down. @@ -141,9 +141,9 @@
widgets/elided_label.h
- TabnavTreeView + RowMoveTreeView QTreeView -
widgets/tabnav_tree_view.h
+
widgets/rowmove_tree_view.h
StockIconToolButton diff --git a/ui/qt/utils/color_utils.cpp b/ui/qt/utils/color_utils.cpp index e7e396d0..6024fdb8 100644 --- a/ui/qt/utils/color_utils.cpp +++ b/ui/qt/utils/color_utils.cpp @@ -222,3 +222,8 @@ const QColor ColorUtils::warningBackground() } return QColor(tango_butter_2); } + +const QColor ColorUtils::disabledForeground() +{ + return alphaBlend(QApplication::palette().windowText(), QApplication::palette().window(), 0.65); +} diff --git a/ui/qt/utils/color_utils.h b/ui/qt/utils/color_utils.h index a205cccc..ac5ed02e 100644 --- a/ui/qt/utils/color_utils.h +++ b/ui/qt/utils/color_utils.h @@ -12,8 +12,6 @@ #include -#include - #include #include @@ -82,11 +80,17 @@ public: */ static const QColor warningBackground(); + /** + * Returns an appropriate foreground color for disabled text. + * @return The foreground color. + */ + static const QColor disabledForeground(); + private: static QList graph_colors_; static QList sequence_colors_; }; -void color_filter_qt_add_cb(color_filter_t *colorf, gpointer user_data); +void color_filter_qt_add_cb(color_filter_t *colorf, void *user_data); #endif // COLOR_UTILS_H diff --git a/ui/qt/utils/data_printer.cpp b/ui/qt/utils/data_printer.cpp index 3c3e910a..f3635ee4 100644 --- a/ui/qt/utils/data_printer.cpp +++ b/ui/qt/utils/data_printer.cpp @@ -34,6 +34,22 @@ void DataPrinter::toClipboard(DataPrinter::DumpType type, IDataPrintable * print switch(type) { + case DP_GoLiteral: + clipboard_text += QString("[]byte{"); + for (int i = 0; i < printData.length(); i++) { + if (i>0) clipboard_text += ", "; + clipboard_text += QString("0x%1").arg((uint8_t) printData[i], 1, 16, QChar('0')); + } + clipboard_text += QString("}"); + break; + case DP_CArray: + clipboard_text += QString("unsigned char bytes[] = {"); + for (int i = 0; i < printData.length(); i++) { + if (i>0) clipboard_text += ", "; + clipboard_text += QString("0x%1").arg((uint8_t) printData[i], 1, 16, QChar('0')); + } + clipboard_text += QString("};"); + break; case DP_CString: // Beginning quote clipboard_text += QString("\""); @@ -86,12 +102,21 @@ void DataPrinter::toClipboard(DataPrinter::DumpType type, IDataPrintable * print for (int i = 0; i < printData.length(); i++) clipboard_text += QString("%1").arg((uint8_t) printData[i], 2, 16, QChar('0')); break; - case DP_PrintableText: + case DP_UTF8Text: + // This automatically compensates for invalid UTF-8 in the input +#if WS_IS_AT_LEAST_GNUC_VERSION(12,1) +DIAG_OFF(stringop-overread) +#endif + clipboard_text += QString::fromUtf8(printData); +#if WS_IS_AT_LEAST_GNUC_VERSION(12,1) +DIAG_ON(stringop-overread) +#endif + break; + case DP_ASCIIText: + // Copy valid 7-bit printable ASCII bytes, skip the rest for (int i = 0; i < printData.length(); i++) { QChar ch(printData[i]); - // This interprets ch as Latin-1. We might want to use ASCII - // printable only. - if (ch.isSpace() || ch.isPrint()) { + if (ch.isSpace() || (ch > (char)0x20 && ch < (char)0x7F)) { clipboard_text += ch; } } @@ -261,9 +286,14 @@ QActionGroup * DataPrinter::copyActions(QObject * copyClass, QObject * data) action->setProperty("printertype", DataPrinter::DP_HexOnly); connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes); - action = new QAction(tr("…as Printable Text"), actions); - action->setToolTip(tr("Copy only the printable text in the packet.")); - action->setProperty("printertype", DataPrinter::DP_PrintableText); + action = new QAction(tr("…as UTF-8 Text"), actions); + action->setToolTip(tr("Copy packet bytes as text, treating as UTF-8.")); + action->setProperty("printertype", DataPrinter::DP_UTF8Text); + connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes); + + action = new QAction(tr("…as ASCII Text"), actions); + action->setToolTip(tr("Copy packet bytes as text, treating as ASCII.")); + action->setProperty("printertype", DataPrinter::DP_ASCIIText); connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes); action = new QAction(tr("…as a Hex Stream"), actions); @@ -286,6 +316,16 @@ QActionGroup * DataPrinter::copyActions(QObject * copyClass, QObject * data) action->setProperty("printertype", DataPrinter::DP_CString); connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes); + action = new QAction(tr("…as Go literal"), actions); + action->setToolTip(tr("Copy packet bytes as Go literal.")); + action->setProperty("printertype", DataPrinter::DP_GoLiteral); + connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes); + + action = new QAction(tr("…as C Array"), actions); + action->setToolTip(tr("Copy packet bytes as C Array.")); + action->setProperty("printertype", DataPrinter::DP_CArray); + connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes); + return actions; } diff --git a/ui/qt/utils/data_printer.h b/ui/qt/utils/data_printer.h index 882b5752..52c259f8 100644 --- a/ui/qt/utils/data_printer.h +++ b/ui/qt/utils/data_printer.h @@ -30,8 +30,11 @@ public: DP_HexDump, DP_HexOnly, DP_HexStream, - DP_PrintableText, + DP_UTF8Text, + DP_ASCIIText, DP_CString, + DP_GoLiteral, + DP_CArray, DP_MimeData, DP_Base64 }; diff --git a/ui/qt/utils/frame_information.cpp b/ui/qt/utils/frame_information.cpp index d344bc04..facd368d 100644 --- a/ui/qt/utils/frame_information.cpp +++ b/ui/qt/utils/frame_information.cpp @@ -48,13 +48,13 @@ void FrameInformation::loadFrameTree() edt_ = g_new0(epan_dissect_t, 1); /* proto tree, visible. We need a proto tree if there's custom columns */ - epan_dissect_init(edt_, cap_file_->capFile()->epan, TRUE, TRUE); + epan_dissect_init(edt_, cap_file_->capFile()->epan, true, true); col_custom_prime_edt(edt_, &(cap_file_->capFile()->cinfo)); epan_dissect_run(edt_, cap_file_->capFile()->cd_t, &rec_, frame_tvbuff_new_buffer(&cap_file_->capFile()->provider, fi_, &buf_), fi_, &(cap_file_->capFile()->cinfo)); - epan_dissect_fill_in_columns(edt_, TRUE, TRUE); + epan_dissect_fill_in_columns(edt_, true, true); } FrameInformation::~FrameInformation() diff --git a/ui/qt/utils/profile_switcher.cpp b/ui/qt/utils/profile_switcher.cpp new file mode 100644 index 00000000..ded1b1f5 --- /dev/null +++ b/ui/qt/utils/profile_switcher.cpp @@ -0,0 +1,140 @@ +/* profile_switcher.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +// #include +#include + +#include +#include + +#include +#include + +#include "profile_switcher.h" + +#include "file.h" + +#include +#include +#include +#include "frame_tvbuff.h" + +// Enable switching iff: +// - We're opening a new capture file via the UI. +// - We haven't changed our profile, either manually or automatically. + +ProfileSwitcher::ProfileSwitcher(QObject *parent) : + QObject(parent), + capture_file_changed_(true), + profile_changed_(false) +{ + if (g_list_length(current_profile_list()) == 0) { + init_profile_list(); + } + connect(mainApp, &MainApplication::profileChanging, this, &ProfileSwitcher::disableSwitching); +} + +void ProfileSwitcher::captureEventHandler(CaptureEvent ev) +{ + if (ev.captureContext() != CaptureEvent::File) { + return; + } + + CaptureFile *capture_file = qobject_cast(sender()); + if (!capture_file) { + return; + } + + // CaptureEvent doesn't have a "this is the same file" flag, so + // track that via the filename. + switch (ev.eventType()) { + case CaptureEvent::Opened: + if (previous_cap_file_ != capture_file->filePath()) { + capture_file_changed_ = true; + profile_changed_ = false; + } + break; + case CaptureEvent::Closing: + previous_cap_file_ = capture_file->filePath(); + break; + default: + break; + } +} + +void ProfileSwitcher::checkPacket(capture_file *cap_file, frame_data *fdata, qsizetype row) +{ + if (profile_changed_ || !capture_file_changed_ || row >= recent.gui_profile_switch_check_count) { + return; + } + + if (row == 0) { + clearProfileFilters(); + for (GList *cur = current_profile_list() ; cur; cur = cur->next) { + profile_def *profile = static_cast(cur->data); + if (!profile->auto_switch_filter) { + continue; + } + dfilter_t *dfcode; + if (dfilter_compile(profile->auto_switch_filter, &dfcode, NULL) && dfcode) { + profile_filters_.append({profile->name, dfcode}); + } + } + } + + if (profile_filters_.empty()) { + return; + } + + QString new_profile; + wtap_rec rec; + Buffer buf; + wtap_rec_init(&rec); + ws_buffer_init(&buf, 1514); + epan_dissect_t edt; + + for (auto &cur_filter : profile_filters_) { + if (!cf_read_record(cap_file, fdata, &rec, &buf)) { + continue; + } + epan_dissect_init(&edt, cap_file->epan, TRUE, FALSE); + epan_dissect_prime_with_dfilter(&edt, cur_filter.dfcode); + epan_dissect_run(&edt, cap_file->cd_t, &rec, + frame_tvbuff_new_buffer(&cap_file->provider, fdata, &buf), + fdata, NULL); + bool matched = dfilter_apply_edt(cur_filter.dfcode, &edt); + epan_dissect_cleanup(&edt); + if (matched) { + new_profile = cur_filter.name; + break; + } + } + + wtap_rec_cleanup(&rec); + ws_buffer_free(&buf); + + if (!new_profile.isEmpty()) { + clearProfileFilters(); + previous_cap_file_ = cap_file->filename; + mainApp->setConfigurationProfile(qUtf8Printable(new_profile), false); + } +} + +void ProfileSwitcher::clearProfileFilters() +{ + for (auto &cur_filter : profile_filters_) { + dfilter_free(cur_filter.dfcode); + } + profile_filters_.clear(); +} + +void ProfileSwitcher::disableSwitching() +{ + profile_changed_ = true; +} diff --git a/ui/qt/utils/profile_switcher.h b/ui/qt/utils/profile_switcher.h new file mode 100644 index 00000000..57dfd255 --- /dev/null +++ b/ui/qt/utils/profile_switcher.h @@ -0,0 +1,48 @@ +/** @file + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#pragma once + +#include + +#include "capture_event.h" +#include "cfile.h" + +#include +#include + +struct profile_switch_filter { + QString name; + dfilter_t *dfcode; +}; + +class PacketListModel; + +class ProfileSwitcher : public QObject +{ + Q_OBJECT +public: + explicit ProfileSwitcher(QObject *parent = nullptr); + +public slots: + void captureEventHandler(CaptureEvent ev); + void checkPacket(capture_file *cap_file, frame_data *fdata, qsizetype row); + +private: + PacketListModel *packet_list_model_; + QVector profile_filters_; + bool capture_file_changed_; + bool profile_changed_; + QString previous_cap_file_; + + void clearProfileFilters(); + +private slots: + void disableSwitching(); +}; diff --git a/ui/qt/utils/proto_node.cpp b/ui/qt/utils/proto_node.cpp index 68d1f4c7..222b2d5e 100644 --- a/ui/qt/utils/proto_node.cpp +++ b/ui/qt/utils/proto_node.cpp @@ -12,6 +12,7 @@ #include +// NOLINTNEXTLINE(misc-no-recursion) ProtoNode::ProtoNode(proto_node *node, ProtoNode *parent) : node_(node), parent_(parent) { @@ -28,6 +29,7 @@ ProtoNode::ProtoNode(proto_node *node, ProtoNode *parent) : for (proto_node *child = node_->first_child; child; child = child->next) { if (!isHidden(child)) { + // We recurse here, but we're limited by tree depth checks in epan m_children.append(new ProtoNode(child, this)); } } @@ -70,7 +72,7 @@ QString ProtoNode::labelText() const label = fi->rep->representation; } else { /* no, make a generic label */ - gchar label_str[ITEM_LABEL_LENGTH]; + char label_str[ITEM_LABEL_LENGTH]; proto_item_fill_label(fi, label_str); label = label_str; } diff --git a/ui/qt/utils/qt_ui_utils.cpp b/ui/qt/utils/qt_ui_utils.cpp index 9dad9dd9..addfe208 100644 --- a/ui/qt/utils/qt_ui_utils.cpp +++ b/ui/qt/utils/qt_ui_utils.cpp @@ -17,15 +17,13 @@ #include #include #include -#include #include #include #include "ui/ws_ui_util.h" #include - -#include +#include #include #include @@ -36,24 +34,31 @@ #include #include #include -#include #include +#if defined(Q_OS_MAC) +#include +#elif !defined(Q_OS_WIN) && defined(QT_DBUS_LIB) +#include +#include +#include +#endif + /* * We might want to create our own "wsstring" class with convenience * methods for handling g_malloc()ed strings, GStrings, and a shortcut * to .toUtf8().constData(). */ -gchar *qstring_strdup(QString q_string) { - return g_strdup(q_string.toUtf8().constData()); +char *qstring_strdup(QString q_string) { + return g_strdup(qUtf8Printable(q_string)); } -QString gchar_free_to_qstring(gchar *glib_string) { +QString gchar_free_to_qstring(char *glib_string) { return QString(gchar_free_to_qbytearray(glib_string)); } -QByteArray gchar_free_to_qbytearray(gchar *glib_string) +QByteArray gchar_free_to_qbytearray(char *glib_string) { QByteArray qt_bytearray(glib_string); g_free(glib_string); @@ -70,7 +75,7 @@ QByteArray gstring_free_to_qbytearray(GString *glib_gstring) QByteArray gbytearray_free_to_qbytearray(GByteArray *glib_array) { QByteArray qt_ba(reinterpret_cast(glib_array->data), glib_array->len); - g_byte_array_free(glib_array, TRUE); + g_byte_array_free(glib_array, true); return qt_ba; } @@ -101,7 +106,7 @@ const QString address_to_qstring(const _address *address, bool enclose) QString address_qstr = QString(); if (address) { if (enclose && address->type == AT_IPv6) address_qstr += "["; - gchar *address_gchar_p = address_to_str(NULL, address); + char *address_gchar_p = address_to_str(NULL, address); address_qstr += address_gchar_p; wmem_free(NULL, address_gchar_p); if (enclose && address->type == AT_IPv6) address_qstr += "]"; @@ -113,27 +118,27 @@ const QString address_to_display_qstring(const _address *address) { QString address_qstr = QString(); if (address) { - gchar *address_gchar_p = address_to_display(NULL, address); + char *address_gchar_p = address_to_display(NULL, address); address_qstr = address_gchar_p; wmem_free(NULL, address_gchar_p); } return address_qstr; } -const QString val_to_qstring(const guint32 val, const value_string *vs, const char *fmt) +const QString val_to_qstring(const uint32_t val, const value_string *vs, const char *fmt) { QString val_qstr; - gchar* gchar_p = val_to_str_wmem(NULL, val, vs, fmt); + char* gchar_p = val_to_str_wmem(NULL, val, vs, fmt); val_qstr = gchar_p; wmem_free(NULL, gchar_p); return val_qstr; } -const QString val_ext_to_qstring(const guint32 val, value_string_ext *vse, const char *fmt) +const QString val_ext_to_qstring(const uint32_t val, value_string_ext *vse, const char *fmt) { QString val_qstr; - gchar* gchar_p = val_to_str_ext_wmem(NULL, val, vse, fmt); + char* gchar_p = val_to_str_ext_wmem(NULL, val, vse, fmt); val_qstr = gchar_p; wmem_free(NULL, gchar_p); @@ -155,7 +160,7 @@ const QString bits_s_to_qstring(const double bits_s) format_size(bits_s, FORMAT_SIZE_UNIT_NONE, FORMAT_SIZE_PREFIX_SI)); } -const QString file_size_to_qstring(const gint64 size) +const QString file_size_to_qstring(const int64_t size) { return gchar_free_to_qstring( format_size(size, FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI)); @@ -209,28 +214,55 @@ void desktop_show_in_folder(const QString file_path) // https://stackoverflow.com/questions/3490336/how-to-reveal-in-finder-or-show-in-explorer-with-qt #if defined(Q_OS_WIN) + // + // See + // + // https://stackoverflow.com/questions/13680415/how-to-open-explorer-with-a-specific-file-selected + // + // for a way to do this using Windows Shell APIs, rather than having + // to fire up a separate instance of Windows Explorer. + // QString command = "explorer.exe"; QStringList arguments; QString path = QDir::toNativeSeparators(file_path); arguments << "/select," << path + ""; success = QProcess::startDetached(command, arguments); #elif defined(Q_OS_MAC) - QStringList script_args; - QString escaped_path = file_path; - - escaped_path.replace('"', "\\\""); - script_args << "-e" - << QString("tell application \"Finder\" to reveal POSIX file \"%1\"") - .arg(escaped_path); - if (QProcess::execute("/usr/bin/osascript", script_args) == 0) { - success = true; - script_args.clear(); - script_args << "-e" - << "tell application \"Finder\" to activate"; - QProcess::execute("/usr/bin/osascript", script_args); + CocoaBridge::showInFinder(file_path.toUtf8()); + success = true; +#elif defined(QT_DBUS_LIB) + // First, try the FileManager1 DBus interface's "ShowItems" method. + // https://www.freedesktop.org/wiki/Specifications/file-manager-interface/ + QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.FileManager1"), + QLatin1String("/org/freedesktop/FileManager1"), + QLatin1String("org.freedesktop.FileManager1"), + QLatin1String("ShowItems")); + QStringList uris(QUrl::fromLocalFile(file_path).toString()); + message << uris << QString(); + + message = QDBusConnection::sessionBus().call(message); + success = message.type() == QDBusMessage::ReplyMessage; + + // If that failed, perhaps we are sandboxed. Try using Portal Services. + // https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.OpenURI.html + if (!success) { + const int fd = ws_open(QFile::encodeName(file_path), O_CLOEXEC | O_PATH, 0000); + if (fd != -1) { + QDBusUnixFileDescriptor descriptor; + descriptor.giveFileDescriptor(fd); + QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"), + QLatin1String("/org/freedesktop/portal/desktop"), + QLatin1String("org.freedesktop.portal.OpenURI"), + QLatin1String("OpenDirectory")); + message << QString() << QVariant::fromValue(descriptor) << QVariantMap(); + + message = QDBusConnection::sessionBus().call(message); + success = message.type() == QDBusMessage::ReplyMessage; + ws_close(fd); + } } #else - // Is there a way to highlight the file using xdg-open? + // Any other possibilities to highlight the file before falling back to showing the folder? #endif if (!success) { QFileInfo file_info(file_path); @@ -251,7 +283,7 @@ bool rect_on_screen(const QRect &rect) void set_action_shortcuts_visible_in_context_menu(QList actions) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) && QT_VERSION < QT_VERSION_CHECK(5, 13, 0) +#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) // For QT_VERSION >= 5.13.0 we call styleHints()->setShowShortcutsInContextMenus(true) // in WiresharkApplication. // QTBUG-71471 @@ -310,27 +342,7 @@ QString openDialogInitialDir() { QString result; - switch (prefs.gui_fileopen_style) { - - case FO_STYLE_LAST_OPENED: - /* The user has specified that we should start out in the last directory - we looked in. If we've already opened a file, use its containing - directory, if we could determine it, as the directory, otherwise - use the "last opened" directory saved in the preferences file if - there was one. */ - /* This is now the default behaviour in file_selection_new() */ - result = QString(get_open_dialog_initial_dir()); - break; - - case FO_STYLE_SPECIFIED: - /* The user has specified that we should always start out in a - specified directory; if they've specified that directory, - start out by showing the files in that dir. */ - if (prefs.gui_fileopen_dir[0] != '\0') - result = QString(prefs.gui_fileopen_dir); - break; - } - + result = QString(get_open_dialog_initial_dir()); QDir ld(result); if (ld.exists()) return result; diff --git a/ui/qt/utils/qt_ui_utils.h b/ui/qt/utils/qt_ui_utils.h index 60ccf31d..24888b03 100644 --- a/ui/qt/utils/qt_ui_utils.h +++ b/ui/qt/utils/qt_ui_utils.h @@ -61,7 +61,7 @@ struct epan_range; * * @return A copy of the QString. UTF-8 allocated with g_malloc(). */ -gchar *qstring_strdup(QString q_string); +char *qstring_strdup(QString q_string); /** Transfer ownership of a GLib character string to a newly constructed QString * @@ -70,7 +70,7 @@ gchar *qstring_strdup(QString q_string); * * @return A QString instance created from the input string. */ -QString gchar_free_to_qstring(gchar *glib_string); +QString gchar_free_to_qstring(char *glib_string); /** Transfer ownership of a GLib character string to a newly constructed QString * @@ -79,7 +79,7 @@ QString gchar_free_to_qstring(gchar *glib_string); * * @return A QByteArray instance created from the input string. */ -QByteArray gchar_free_to_qbytearray(gchar *glib_string); +QByteArray gchar_free_to_qbytearray(char *glib_string); /** Transfer ownership of a GLib character string to a newly constructed QByteArray * @@ -133,7 +133,7 @@ const QString address_to_display_qstring(const struct _address *address); * * @return A QString representation of the value_string. */ -const QString val_to_qstring(const guint32 val, const struct _value_string *vs, const char *fmt) +const QString val_to_qstring(const uint32_t val, const struct _value_string *vs, const char *fmt) G_GNUC_PRINTF(3, 0); /** Convert a value_string_ext to a QString using val_to_str_ext_wmem(). @@ -144,7 +144,7 @@ G_GNUC_PRINTF(3, 0); * * @return A QString representation of the value_string_ext. */ -const QString val_ext_to_qstring(const guint32 val, struct _value_string_ext *vse, const char *fmt) +const QString val_ext_to_qstring(const uint32_t val, struct _value_string_ext *vse, const char *fmt) G_GNUC_PRINTF(3, 0); /** Convert a range to a QString using range_convert_range(). @@ -169,7 +169,7 @@ const QString bits_s_to_qstring(const double bits_s); * * @return A QString representation of the file size in SI units. */ -const QString file_size_to_qstring(const gint64 size); +const QString file_size_to_qstring(const int64_t size); /** Convert a time_t value to a human-readable QString using QDateTime. * diff --git a/ui/qt/utils/rtp_audio_file.cpp b/ui/qt/utils/rtp_audio_file.cpp index 591a63bb..8b349182 100644 --- a/ui/qt/utils/rtp_audio_file.cpp +++ b/ui/qt/utils/rtp_audio_file.cpp @@ -14,7 +14,7 @@ * File uses Frame as piece of information. One Frame match audio of one * decoded packet or audio silence in between them. Frame holds information * about frame type (audio/silence), its length and realtime position and - * sample possition (where decoded audio is really stored, with gaps omitted). + * sample position (where decoded audio is really stored, with gaps omitted). * * There are three stages of the object use * - writing data by frames during decoding of the stream @@ -124,7 +124,7 @@ void RtpAudioFile::frameUpdateSampleCounters(qint64 written_bytes) sample_pos_ += written_bytes; } -qint64 RtpAudioFile::frameWriteFrame(guint32 frame_num, qint64 real_pos, qint64 sample_pos, qint64 len, rtp_frame_type type) +qint64 RtpAudioFile::frameWriteFrame(uint32_t frame_num, qint64 real_pos, qint64 sample_pos, qint64 len, rtp_frame_type type) { rtp_frame_info frame_info; @@ -137,7 +137,7 @@ qint64 RtpAudioFile::frameWriteFrame(guint32 frame_num, qint64 real_pos, qint64 return sample_file_frame_->write((char *)&frame_info, sizeof(frame_info)); } -void RtpAudioFile::frameWriteSilence(guint32 frame_num, qint64 samples) +void RtpAudioFile::frameWriteSilence(uint32_t frame_num, qint64 samples) { if (samples < 1) return; @@ -147,9 +147,9 @@ void RtpAudioFile::frameWriteSilence(guint32 frame_num, qint64 samples) frameUpdateRealCounters(silence_bytes); } -qint64 RtpAudioFile::frameWriteSamples(guint32 frame_num, const char *data, qint64 max_size) +qint64 RtpAudioFile::frameWriteSamples(uint32_t frame_num, const char *data, qint64 max_size) { - gint64 written; + int64_t written; written = sample_file_->write(data, max_size); @@ -170,15 +170,15 @@ void RtpAudioFile::setFrameReadStage(qint64 prepend_samples) { sample_file_frame_->seek(0); if (prepend_samples > 0) { - // Skip first frame which contains openning silence + // Skip first frame which contains opening silence sample_file_frame_->read((char *)&cur_frame_, sizeof(cur_frame_)); } } -bool RtpAudioFile::readFrameSamples(gint32 *read_buff_bytes, SAMPLE **read_buff, spx_uint32_t *read_len, guint32 *frame_num, rtp_frame_type *type) +bool RtpAudioFile::readFrameSamples(int32_t *read_buff_bytes, SAMPLE **read_buff, spx_uint32_t *read_len, uint32_t *frame_num, rtp_frame_type *type) { rtp_frame_info frame_info; - guint64 read_bytes = 0; + uint64_t read_bytes = 0; if (!sample_file_frame_->read((char *)&frame_info, sizeof(frame_info))) { // Can't read frame, some error occurred diff --git a/ui/qt/utils/rtp_audio_file.h b/ui/qt/utils/rtp_audio_file.h index addc3015..b8c53b30 100644 --- a/ui/qt/utils/rtp_audio_file.h +++ b/ui/qt/utils/rtp_audio_file.h @@ -33,7 +33,7 @@ typedef struct { qint64 real_pos; qint64 sample_pos; qint64 len; - guint32 frame_num; + uint32_t frame_num; rtp_frame_type type; } rtp_frame_info; @@ -46,12 +46,12 @@ public: // Functions for writing Frames void setFrameWriteStage(); - void frameWriteSilence(guint32 frame_num, qint64 samples); - qint64 frameWriteSamples(guint32 frame_num, const char *data, qint64 max_size); + void frameWriteSilence(uint32_t frame_num, qint64 samples); + qint64 frameWriteSamples(uint32_t frame_num, const char *data, qint64 max_size); // Functions for reading Frames void setFrameReadStage(qint64 prepend_samples); - bool readFrameSamples(gint32 *read_buff_bytes, SAMPLE **read_buff, spx_uint32_t *read_len, guint32 *frame_num, rtp_frame_type *type); + bool readFrameSamples(int32_t *read_buff_bytes, SAMPLE **read_buff, spx_uint32_t *read_len, uint32_t *frame_num, rtp_frame_type *type); // Functions for reading data during play void setDataReadStage(); @@ -80,7 +80,7 @@ private: rtp_frame_info cur_frame_; // Functions for writing Frames - qint64 frameWriteFrame(guint32 frame_num, qint64 real_pos, qint64 sample_pos, qint64 len, rtp_frame_type type); + qint64 frameWriteFrame(uint32_t frame_num, qint64 real_pos, qint64 sample_pos, qint64 len, rtp_frame_type type); void frameUpdateRealCounters(qint64 written_bytes); void frameUpdateSampleCounters(qint64 written_bytes); diff --git a/ui/qt/utils/rtp_audio_routing_filter.cpp b/ui/qt/utils/rtp_audio_routing_filter.cpp index 8362d3f9..fd2b48d7 100644 --- a/ui/qt/utils/rtp_audio_routing_filter.cpp +++ b/ui/qt/utils/rtp_audio_routing_filter.cpp @@ -64,7 +64,7 @@ qint64 AudioRoutingFilter::readData(char *data, qint64 maxSize) return input_->read(data, maxSize); } else { // For stereo - gint64 silence = 0; + int64_t silence = 0; // Read half of data qint64 readBytes = input_->read(data, maxSize/SAMPLE_BYTES); diff --git a/ui/qt/utils/wireshark_zip_helper.cpp b/ui/qt/utils/wireshark_zip_helper.cpp index 7bfa0101..bcf670ad 100644 --- a/ui/qt/utils/wireshark_zip_helper.cpp +++ b/ui/qt/utils/wireshark_zip_helper.cpp @@ -11,17 +11,18 @@ #include -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) #include "config.h" -#include "glib.h" - #include #include #include // For Z_DEFLATED, etc. +#ifdef HAVE_MINIZIP #include #include - +#else +#include +#endif #include "epan/prefs.h" #include "wsutil/file_util.h" diff --git a/ui/qt/utils/wireshark_zip_helper.h b/ui/qt/utils/wireshark_zip_helper.h index 2f8e39f8..7845f70a 100644 --- a/ui/qt/utils/wireshark_zip_helper.h +++ b/ui/qt/utils/wireshark_zip_helper.h @@ -16,9 +16,13 @@ #include -#ifdef HAVE_MINIZIP +#if defined(HAVE_MINIZIP) || defined(HAVE_MINIZIPNG) +#ifdef HAVE_MINIZIP #include "minizip/zip.h" +#else +#include "minizip-ng/mz_compat.h" +#endif class WiresharkZipHelper { diff --git a/ui/qt/voip_calls_dialog.cpp b/ui/qt/voip_calls_dialog.cpp index dd5910f8..a76b8222 100644 --- a/ui/qt/voip_calls_dialog.cpp +++ b/ui/qt/voip_calls_dialog.cpp @@ -378,7 +378,7 @@ void VoipCallsDialog::tapDraw(void *tapinfo_ptr) } } -gint VoipCallsDialog::compareCallNums(gconstpointer a, gconstpointer b) +int VoipCallsDialog::compareCallNums(const void *a, const void *b) { const voip_calls_info_t *call_a = (const voip_calls_info_t *)a; const voip_calls_info_t *call_b = (const voip_calls_info_t *)b; @@ -459,7 +459,7 @@ void VoipCallsDialog::prepareFilter() } QString filter_str; - QSet selected_calls; + QSet selected_calls; QString frame_numbers; QList rows; @@ -509,7 +509,7 @@ void VoipCallsDialog::prepareFilter() filter_string_fwd = g_string_new(filter_prepend); g_string_append_printf(filter_string_fwd, "("); - is_first = TRUE; + is_first = true; /* Build a new filter based on protocol fields */ lista = g_queue_peek_nth_link(voip_calls_get_info()->callsinfos, 0); while (lista) { @@ -542,10 +542,10 @@ void VoipCallsDialog::prepareFilter() g_string_append_printf(filter_string_fwd, "((h225.guid == %s || q931.call_ref == %x:%x || q931.call_ref == %x:%x)", guid_str, - (guint8) (h323info->q931_crv & 0x00ff), - (guint8)((h323info->q931_crv & 0xff00)>>8), - (guint8) (h323info->q931_crv2 & 0x00ff), - (guint8)((h323info->q931_crv2 & 0xff00)>>8)); + (uint8_t) (h323info->q931_crv & 0x00ff), + (uint8_t)((h323info->q931_crv & 0xff00)>>8), + (uint8_t) (h323info->q931_crv2 & 0x00ff), + (uint8_t)((h323info->q931_crv2 & 0xff00)>>8)); listb = g_list_first(h323info->h245_list); wmem_free(NULL, guid_str); while (listb) { @@ -569,7 +569,7 @@ void VoipCallsDialog::prepareFilter() "(frame)"); break; } - is_first = FALSE; + is_first = false; } lista = gxx_list_next(lista); } @@ -586,7 +586,7 @@ void VoipCallsDialog::showSequence() { if (file_closed_) return; - QSet selected_calls; + QSet selected_calls; foreach (QModelIndex index, ui->callTreeView->selectionModel()->selectedIndexes()) { voip_calls_info_t *call_info = VoipCallsInfoModel::indexToCallInfo(index); if (!call_info) { @@ -629,7 +629,7 @@ QVectorVoipCallsDialog::getSelectedRtpIds() //VOIP_CALLS_DEBUG("checking call %u, start frame %u == stream call %u, start frame %u, setup frame %u", // vci->call_num, vci->start_fd->num, // rsi->call_num, rsi->start_fd->num, rsi->setup_frame_number); - if (vci->call_num == static_cast(rsi->call_num)) { + if (vci->call_num == static_cast(rsi->call_num)) { //VOIP_CALLS_DEBUG("adding call number %u", vci->call_num); if (-1 == stream_ids.indexOf(&(rsi->id))) { // Add only new stream diff --git a/ui/qt/voip_calls_dialog.h b/ui/qt/voip_calls_dialog.h index 0386dfa7..542fab9d 100644 --- a/ui/qt/voip_calls_dialog.h +++ b/ui/qt/voip_calls_dialog.h @@ -12,7 +12,6 @@ #include -#include #include #include "cfile.h" @@ -110,7 +109,7 @@ private: static void tapReset(void *tapinfo_ptr); static tap_packet_status tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *data, tap_flags_t flags); static void tapDraw(void *tapinfo_ptr); - static gint compareCallNums(gconstpointer a, gconstpointer b); + static int compareCallNums(const void *a, const void *b); void updateCalls(); void prepareFilter(); diff --git a/ui/qt/welcome_page.cpp b/ui/qt/welcome_page.cpp index ac37a6d9..1297944c 100644 --- a/ui/qt/welcome_page.cpp +++ b/ui/qt/welcome_page.cpp @@ -9,13 +9,12 @@ #include "config.h" -#include - #include #include "ui/capture_globals.h" #include "ui/urls.h" +#include "wsutil/filesystem.h" #include "wsutil/version_info.h" #include "welcome_page.h" @@ -72,24 +71,28 @@ WelcomePage::WelcomePage(QWidget *parent) : recent_files_->setTextElideMode(Qt::ElideLeft); welcome_ui_->recentList->setContextMenuPolicy(Qt::CustomContextMenu); - connect(recent_files_, SIGNAL(customContextMenuRequested(QPoint)), - this, SLOT(showRecentContextMenu(QPoint))); - - connect(mainApp, SIGNAL(updateRecentCaptureStatus(const QString &, qint64, bool)), this, SLOT(updateRecentCaptures())); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(appInitialized())); - connect(mainApp, SIGNAL(localInterfaceListChanged()), this, SLOT(interfaceListChanged())); - connect(welcome_ui_->interfaceFrame, SIGNAL(itemSelectionChanged()), - welcome_ui_->captureFilterComboBox, SIGNAL(interfacesChanged())); - connect(welcome_ui_->interfaceFrame, SIGNAL(typeSelectionChanged()), - this, SLOT(interfaceListChanged())); - connect(welcome_ui_->interfaceFrame, SIGNAL(itemSelectionChanged()), this, SLOT(interfaceSelected())); - connect(welcome_ui_->captureFilterComboBox->lineEdit(), SIGNAL(textEdited(QString)), - this, SLOT(captureFilterTextEdited(QString))); - connect(welcome_ui_->captureFilterComboBox, SIGNAL(captureFilterSyntaxChanged(bool)), - this, SIGNAL(captureFilterSyntaxChanged(bool))); - connect(welcome_ui_->captureFilterComboBox, SIGNAL(startCapture()), - this, SLOT(captureStarting())); - connect(recent_files_, SIGNAL(itemActivated(QListWidgetItem *)), this, SLOT(openRecentItem(QListWidgetItem *))); + connect(recent_files_, &QListWidget::customContextMenuRequested, this, &WelcomePage::showRecentContextMenu); + + connect(mainApp, &MainApplication::updateRecentCaptureStatus, this, &WelcomePage::updateRecentCaptures); + connect(mainApp, &MainApplication::preferencesChanged, this, &WelcomePage::updateRecentCaptures); + connect(mainApp, &MainApplication::appInitialized, this, &WelcomePage::appInitialized); + connect(mainApp, &MainApplication::localInterfaceListChanged, this, &WelcomePage::interfaceListChanged); +#ifdef HAVE_LIBPCAP + connect(mainApp, &MainApplication::scanLocalInterfaces, + welcome_ui_->interfaceFrame, &InterfaceFrame::scanLocalInterfaces); +#endif + connect(welcome_ui_->interfaceFrame, &InterfaceFrame::itemSelectionChanged, + welcome_ui_->captureFilterComboBox, &CaptureFilterCombo::interfacesChanged); + connect(welcome_ui_->interfaceFrame, &InterfaceFrame::typeSelectionChanged, + this, &WelcomePage::interfaceListChanged); + connect(welcome_ui_->interfaceFrame, &InterfaceFrame::itemSelectionChanged, this, &WelcomePage::interfaceSelected); + connect(welcome_ui_->captureFilterComboBox->lineEdit(), &QLineEdit::textEdited, + this, &WelcomePage::captureFilterTextEdited); + connect(welcome_ui_->captureFilterComboBox, &CaptureFilterCombo::captureFilterSyntaxChanged, + this, &WelcomePage::captureFilterSyntaxChanged); + connect(welcome_ui_->captureFilterComboBox, &CaptureFilterCombo::startCapture, + this, &WelcomePage::captureStarting); + connect(recent_files_, &QListWidget::itemActivated, this, &WelcomePage::openRecentItem); updateRecentCaptures(); splash_overlay_ = new SplashOverlay(this); @@ -136,11 +139,19 @@ void WelcomePage::setReleaseLabel() QString full_release; QDate today = QDate::currentDate(); if ((today.month() == 4 && today.day() == 1) || (today.month() == 7 && today.day() == 14)) { - full_release = tr("You are sniffing the glue that holds the Internet together using Wireshark "); + if (is_packet_configuration_namespace()) { + full_release = tr("You are sniffing the glue that holds the Internet together using Wireshark "); + } else { + full_release = tr("You are sniffing the glue that holds your system together using Logray "); + } } else { - full_release = tr("You are running Wireshark "); + if (is_packet_configuration_namespace()) { + full_release = tr("You are running Wireshark "); + } else { + full_release = tr("You are running Logray "); + } } - full_release += get_ws_vcs_version_info(); + full_release += is_packet_configuration_namespace() ? get_ws_vcs_version_info() : get_lr_vcs_version_info(); full_release += "."; #ifdef HAVE_SOFTWARE_UPDATE if (prefs.gui_update_enabled) { @@ -184,7 +195,7 @@ void WelcomePage::captureFilterTextEdited(const QString capture_filter) if (global_capture_opts.num_selected > 0) { interface_t *device; - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (!device->selected) { continue; @@ -272,7 +283,7 @@ void WelcomePage::updateRecentCaptures() { selectedFilename = rfItem->data(Qt::UserRole).toString(); } - if (mainApp->recentItems().count() == 0) { + if (mainApp->recentItems().count() == 0 || prefs.gui_welcome_page_show_recent) { // Recent menu has been cleared, remove all recent files. while (recent_files_->count()) { delete recent_files_->item(0); @@ -280,39 +291,41 @@ void WelcomePage::updateRecentCaptures() { } int rfRow = 0; - foreach (recent_item_status *ri, mainApp->recentItems()) { - itemLabel = ri->filename; + if(prefs.gui_welcome_page_show_recent) { + foreach (recent_item_status *ri, mainApp->recentItems()) { + itemLabel = ri->filename; - if (rfRow >= recent_files_->count()) { - recent_files_->addItem(itemLabel); - } + if (rfRow >= recent_files_->count()) { + recent_files_->addItem(itemLabel); + } - itemLabel.append(" ("); - if (ri->accessible) { - if (ri->size/1024/1024/1024 > 10) { - itemLabel.append(QString("%1 GB").arg(ri->size/1024/1024/1024)); - } else if (ri->size/1024/1024 > 10) { - itemLabel.append(QString("%1 MB").arg(ri->size/1024/1024)); - } else if (ri->size/1024 > 10) { - itemLabel.append(QString("%1 KB").arg(ri->size/1024)); + itemLabel.append(" ("); + if (ri->accessible) { + if (ri->size/1024/1024/1024 > 10) { + itemLabel.append(QString("%1 GB").arg(ri->size/1024/1024/1024)); + } else if (ri->size/1024/1024 > 10) { + itemLabel.append(QString("%1 MB").arg(ri->size/1024/1024)); + } else if (ri->size/1024 > 10) { + itemLabel.append(QString("%1 KB").arg(ri->size/1024)); + } else { + itemLabel.append(QString("%1 Bytes").arg(ri->size)); + } } else { - itemLabel.append(QString("%1 Bytes").arg(ri->size)); + itemLabel.append(tr("not found")); } - } else { - itemLabel.append(tr("not found")); - } - itemLabel.append(")"); - rfFont.setItalic(!ri->accessible); - rfItem = recent_files_->item(rfRow); - rfItem->setText(itemLabel); - rfItem->setData(Qt::AccessibleTextRole, itemLabel); - rfItem->setData(Qt::UserRole, ri->filename); - rfItem->setFlags(ri->accessible ? Qt::ItemIsSelectable | Qt::ItemIsEnabled : Qt::NoItemFlags); - rfItem->setFont(rfFont); - if (ri->filename == selectedFilename) { - rfItem->setSelected(true); + itemLabel.append(")"); + rfFont.setItalic(!ri->accessible); + rfItem = recent_files_->item(rfRow); + rfItem->setText(itemLabel); + rfItem->setData(Qt::AccessibleTextRole, itemLabel); + rfItem->setData(Qt::UserRole, ri->filename); + rfItem->setFlags(ri->accessible ? Qt::ItemIsSelectable | Qt::ItemIsEnabled : Qt::NoItemFlags); + rfItem->setFont(rfFont); + if (ri->filename == selectedFilename) { + rfItem->setSelected(true); + } + rfRow++; } - rfRow++; } int row = recent_files_->count(); @@ -378,17 +391,17 @@ void WelcomePage::showRecentContextMenu(QPoint pos) QAction *show_action = recent_ctx_menu->addAction(show_in_str_); show_action->setData(cf_path); - connect(show_action, SIGNAL(triggered(bool)), this, SLOT(showRecentFolder())); + connect(show_action, &QAction::triggered, this, &WelcomePage::showRecentFolder); QAction *copy_action = recent_ctx_menu->addAction(tr("Copy file path")); copy_action->setData(cf_path); - connect(copy_action, SIGNAL(triggered(bool)), this, SLOT(copyRecentPath())); + connect(copy_action, &QAction::triggered, this, &WelcomePage::copyRecentPath); recent_ctx_menu->addSeparator(); QAction *remove_action = recent_ctx_menu->addAction(tr("Remove from list")); remove_action->setData(cf_path); - connect(remove_action, SIGNAL(triggered(bool)), this, SLOT(removeRecentPath())); + connect(remove_action, &QAction::triggered, this, &WelcomePage::removeRecentPath); recent_ctx_menu->popup(recent_files_->mapToGlobal(pos)); } diff --git a/ui/qt/welcome_page.h b/ui/qt/welcome_page.h index d6243d1a..382d4aa4 100644 --- a/ui/qt/welcome_page.h +++ b/ui/qt/welcome_page.h @@ -58,7 +58,7 @@ private: QListWidget *recent_files_; signals: - void startCapture(QStringList); + void startCapture(QStringList ifaces); void recentFileActivated(QString cfile); void captureFilterSyntaxChanged(bool valid); void showExtcapOptions(QString &device_name, bool startCaptureOnClose); diff --git a/ui/qt/widgets/additional_toolbar.cpp b/ui/qt/widgets/additional_toolbar.cpp index c023d149..43eab273 100644 --- a/ui/qt/widgets/additional_toolbar.cpp +++ b/ui/qt/widgets/additional_toolbar.cpp @@ -9,8 +9,6 @@ #include -#include - #include #include #include @@ -159,7 +157,7 @@ QWidget * AdditionalToolbarWidgetAction::createWidget(QWidget * parent) } static void -toolbar_button_cb(gpointer item, gpointer item_data, gpointer user_data) +toolbar_button_cb(void *item, void *item_data, void *user_data) { if (! item || ! item_data || ! user_data) return; @@ -170,7 +168,7 @@ toolbar_button_cb(gpointer item, gpointer item_data, gpointer user_data) if (widget) { if (update_entry->type == EXT_TOOLBAR_UPDATE_VALUE) - widget->setText((gchar *)update_entry->user_data); + widget->setText((char *)update_entry->user_data); else if (update_entry->type == EXT_TOOLBAR_SET_ACTIVE) { bool enableState = GPOINTER_TO_INT(update_entry->user_data) == 1; @@ -195,7 +193,7 @@ QWidget * AdditionalToolbarWidgetAction::createButton(ext_toolbar_t * item, QWid } static void -toolbar_boolean_cb(gpointer item, gpointer item_data, gpointer user_data) +toolbar_boolean_cb(void *item, void *item_data, void *user_data) { if (! item || ! item_data || ! user_data) return; @@ -267,7 +265,7 @@ QWidget * AdditionalToolbarWidgetAction::createLabelFrame(ext_toolbar_t * item, } static void -toolbar_string_cb(gpointer item, gpointer item_data, gpointer user_data) +toolbar_string_cb(void *item, void *item_data, void *user_data) { if (! item || ! item_data || ! user_data) return; @@ -282,7 +280,7 @@ toolbar_string_cb(gpointer item, gpointer item_data, gpointer user_data) if (update_entry->silent) oldState = edit->blockSignals(true); - edit->setText((gchar *)update_entry->user_data); + edit->setText((char *)update_entry->user_data); if (update_entry->silent) edit->blockSignals(oldState); @@ -321,7 +319,7 @@ QWidget * AdditionalToolbarWidgetAction::createTextEditor(ext_toolbar_t * item, } static void -toolbar_selector_cb(gpointer item, gpointer item_data, gpointer user_data) +toolbar_selector_cb(void *item, void *item_data, void *user_data) { if (! item || ! item_data || ! user_data) return; @@ -346,7 +344,7 @@ toolbar_selector_cb(gpointer item, gpointer item_data, gpointer user_data) if (update_entry->type == EXT_TOOLBAR_UPDATE_VALUE) { - QString data = QString((gchar *)update_entry->user_data); + QString data = QString((char *)update_entry->user_data); for (int i = 0; i < sourceModel->rowCount(); i++) { @@ -385,8 +383,8 @@ toolbar_selector_cb(gpointer item, gpointer item_data, gpointer user_data) if (! update_entry->data_index) return; - gchar * idx = (gchar *)update_entry->data_index; - gchar * display = (gchar *)update_entry->user_data; + char * idx = (char *)update_entry->data_index; + char * display = (char *)update_entry->user_data; if (update_entry->type == EXT_TOOLBAR_UPDATE_DATABYINDEX) { @@ -522,7 +520,7 @@ void AdditionalToolbarWidgetAction::onCheckBoxChecked(int checkState) if (! item) return; - gboolean value = checkState == Qt::Checked ? true : false; + bool value = checkState == Qt::Checked ? true : false; item->callback(item, &value, item->user_data); } @@ -539,7 +537,7 @@ void AdditionalToolbarWidgetAction::sendTextToCallback() ApplyLineEdit * editor = dynamic_cast(sender()); if (! editor) { - /* Called from button, searching for acompanying line edit */ + /* Called from button, searching for accompanying line edit */ QWidget * parent = dynamic_cast(sender()->parent()); if (parent) { diff --git a/ui/qt/widgets/byte_view_text.cpp b/ui/qt/widgets/byte_view_text.cpp index a85fd91d..ee1e0195 100644 --- a/ui/qt/widgets/byte_view_text.cpp +++ b/ui/qt/widgets/byte_view_text.cpp @@ -70,6 +70,7 @@ ByteViewText::ByteViewText(const QByteArray &data, packet_char_enc encoding, QWi offset_normal_fg_ = ColorUtils::alphaBlend(palette().windowText(), palette().window(), 0.35); offset_field_fg_ = ColorUtils::alphaBlend(palette().windowText(), palette().window(), 0.65); + ctx_menu_.setToolTipsVisible(true); window()->winId(); // Required for screenChanged? https://phabricator.kde.org/D20171 connect(window()->windowHandle(), &QWindow::screenChanged, viewport(), [=](const QScreen *) { viewport()->update(); }); @@ -407,11 +408,7 @@ void ByteViewText::updateLayoutMetrics() int ByteViewText::stringWidth(const QString &line) { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) return viewport()->fontMetrics().horizontalAdvance(line); -#else - return viewport()->fontMetrics().width(line); -#endif } // Draw a line of byte view text for a given offset. diff --git a/ui/qt/widgets/capture_filter_combo.cpp b/ui/qt/widgets/capture_filter_combo.cpp index 70635cef..95766310 100644 --- a/ui/qt/widgets/capture_filter_combo.cpp +++ b/ui/qt/widgets/capture_filter_combo.cpp @@ -126,7 +126,7 @@ void CaptureFilterCombo::rebuildFilterList() QString cur_filter = currentText(); clear(); for (GList *li = g_list_first(cfilter_list); li != NULL; li = gxx_list_next(li)) { - addItem(gxx_list_data(const gchar *, li)); + addItem(gxx_list_data(const char *, li)); } lineEdit()->setText(cur_filter); lineEdit()->blockSignals(false); diff --git a/ui/qt/widgets/capture_filter_edit.cpp b/ui/qt/widgets/capture_filter_edit.cpp index 3c72fe41..50793143 100644 --- a/ui/qt/widgets/capture_filter_edit.cpp +++ b/ui/qt/widgets/capture_filter_edit.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include #include "capture_opts.h" @@ -308,7 +306,7 @@ QPair CaptureFilterEdit::getSelectedFilter() #ifdef HAVE_LIBPCAP int selected_devices = 0; - for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) { interface_t *device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (device->selected) { selected_devices++; diff --git a/ui/qt/widgets/compression_group_box.cpp b/ui/qt/widgets/compression_group_box.cpp new file mode 100644 index 00000000..08a74dae --- /dev/null +++ b/ui/qt/widgets/compression_group_box.cpp @@ -0,0 +1,69 @@ +/* @file + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "compression_group_box.h" + +#include +#include +#include + +CompressionGroupBox::CompressionGroupBox(QWidget *parent) : + QGroupBox(parent) +{ + setTitle(tr("Compression options")); + setFlat(true); + + + bg_ = new QButtonGroup(this); + QVBoxLayout *vbox = new QVBoxLayout(); + + QRadioButton *radio1 = new QRadioButton(tr("&Uncompressed")); + bg_->addButton(radio1, WTAP_UNCOMPRESSED); + vbox->addWidget(radio1); + +#if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) + QRadioButton *radio2 = new QRadioButton(tr("Compress with g&zip")); + bg_->addButton(radio2, WTAP_GZIP_COMPRESSED); + vbox->addWidget(radio2); +#endif +#ifdef HAVE_LZ4FRAME_H + QRadioButton *radio3 = new QRadioButton(tr("Compress with &LZ4")); + bg_->addButton(radio3, WTAP_LZ4_COMPRESSED); + vbox->addWidget(radio3); +#endif + + radio1->setChecked(true); + + setLayout(vbox); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + connect(bg_, &QButtonGroup::idToggled, [=] { emit stateChanged(); }); +#else + connect(bg_, QOverload::of(&QButtonGroup::buttonToggled), [=] { emit stateChanged(); }); +#endif + +} + +CompressionGroupBox::~CompressionGroupBox() +{ +} + +wtap_compression_type CompressionGroupBox::compressionType() const +{ + return static_cast(bg_->checkedId()); +} + +void CompressionGroupBox::setCompressionType(wtap_compression_type type) +{ + QAbstractButton *button = bg_->button(type); + if (button != nullptr) { + button->setChecked(true); + } +} + diff --git a/ui/qt/widgets/compression_group_box.h b/ui/qt/widgets/compression_group_box.h new file mode 100644 index 00000000..4e70ca2d --- /dev/null +++ b/ui/qt/widgets/compression_group_box.h @@ -0,0 +1,41 @@ +/** @file + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef COMPRESSION_GROUP_BOX_H +#define COMPRESSION_GROUP_BOX_H + +#include + +#include + +#include + +class QButtonGroup; + +/** + * UI element for selecting compression type from among those supported. + */ +class CompressionGroupBox : public QGroupBox +{ + Q_OBJECT + +public: + explicit CompressionGroupBox(QWidget *parent = 0); + ~CompressionGroupBox(); + wtap_compression_type compressionType() const; + void setCompressionType(wtap_compression_type type); + +signals: + void stateChanged(); + +private: + QButtonGroup *bg_; +}; + +#endif // COMPRESSION_GROUP_BOX_H diff --git a/ui/qt/widgets/copy_from_profile_button.h b/ui/qt/widgets/copy_from_profile_button.h index f074bdb8..ea6df816 100644 --- a/ui/qt/widgets/copy_from_profile_button.h +++ b/ui/qt/widgets/copy_from_profile_button.h @@ -11,7 +11,6 @@ #define COPY_FROM_PROFILE_BUTTON_H #include -#include #include #include diff --git a/ui/qt/widgets/display_filter_combo.cpp b/ui/qt/widgets/display_filter_combo.cpp index c28afb91..674da765 100644 --- a/ui/qt/widgets/display_filter_combo.cpp +++ b/ui/qt/widgets/display_filter_combo.cpp @@ -25,8 +25,31 @@ #include #include "main_application.h" -// If we ever add support for multiple windows this will need to be replaced. -static DisplayFilterCombo *cur_display_filter_combo = NULL; +static QStandardItemModel *cur_model; + +extern "C" void dfilter_recent_combo_write_all(FILE *rf) { + if (cur_model == nullptr) + return; + + for (int i = 0; i < cur_model->rowCount(); i++ ) { + const QByteArray& filter = cur_model->item(i)->text().toUtf8(); + if (!filter.isEmpty()) { + fprintf(rf, RECENT_KEY_DISPLAY_FILTER ": %s\n", filter.constData()); + } + } +} + +extern "C" bool dfilter_combo_add_recent(const char *filter) { + if (cur_model == nullptr) { + cur_model = new QStandardItemModel(); + cur_model->setSortRole(Qt::UserRole); + } + + QStandardItem *new_item = new QStandardItem(filter); + new_item->setData(QVariant(QDateTime::currentMSecsSinceEpoch()), Qt::UserRole); + cur_model->appendRow(new_item); + return true; +} DisplayFilterCombo::DisplayFilterCombo(QWidget *parent) : QComboBox(parent) @@ -46,36 +69,51 @@ DisplayFilterCombo::DisplayFilterCombo(QWidget *parent) : // Default is Preferred. setSizePolicy(QSizePolicy::MinimumExpanding, sizePolicy().verticalPolicy()); setAccessibleName(tr("Display filter selector")); - cur_display_filter_combo = this; updateStyleSheet(); setToolTip(tr("Select from previously used filters.")); - QStandardItemModel *model = qobject_cast(this->model()); - model->setSortRole(Qt::UserRole); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + // Setting the placeholderText keeps newly added items from being the + // current item. It only works for the placeholderText of the QComboBox, + // not the lineEdit (even though the lineEdit's placeholderText is shown + // instead.) This only matters for any combobox created before the recent + // display filter list is read (i.e., the main window one.) + setPlaceholderText(lineEdit()->placeholderText()); +#endif + + if (cur_model == nullptr) { + cur_model = new QStandardItemModel(); + cur_model->setSortRole(Qt::UserRole); + } + setModel(cur_model); connect(mainApp, &MainApplication::preferencesChanged, this, &DisplayFilterCombo::updateMaxCount); // Ugly cast required (?) // https://stackoverflow.com/questions/16794695/connecting-overloaded-signals-and-slots-in-qt-5 connect(this, static_cast(&DisplayFilterCombo::activated), this, &DisplayFilterCombo::onActivated); -} - -extern "C" void dfilter_recent_combo_write_all(FILE *rf) { - if (!cur_display_filter_combo) - return; - cur_display_filter_combo->writeRecent(rf); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + connect(cur_model, &QAbstractItemModel::rowsAboutToBeInserted, this, &DisplayFilterCombo::rowsAboutToBeInserted); + connect(cur_model, &QAbstractItemModel::rowsInserted, this, &DisplayFilterCombo::rowsInserted); +#endif } -void DisplayFilterCombo::writeRecent(FILE *rf) { - int i; +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) +void DisplayFilterCombo::rowsAboutToBeInserted(const QModelIndex&, int, int) +{ + // If the current text is blank but we're inserting a row, that means + // it is being added programmatically from the model, and we want to + // clear it afterwards and show the placeholder text instead. + clear_state_ = (currentText() == QString()); +} - for (i = 0; i < count(); i++) { - const QByteArray& filter = itemText(i).toUtf8(); - if (!filter.isEmpty()) { - fprintf(rf, RECENT_KEY_DISPLAY_FILTER ": %s\n", filter.constData()); - } +void DisplayFilterCombo::rowsInserted(const QModelIndex&, int, int) +{ + if (clear_state_) { + clearEditText(); } } +#endif void DisplayFilterCombo::onActivated(int row) { @@ -172,18 +210,3 @@ void DisplayFilterCombo::updateMaxCount() { setMaxCount(prefs.gui_recent_df_entries_max); } - -extern "C" gboolean dfilter_combo_add_recent(const gchar *filter) { - if (!cur_display_filter_combo) - return FALSE; - - // Adding an item to a QComboBox also sets its lineEdit. In our case - // that means we might trigger a temporary status message so we block - // the lineEdit's signals. - // Another approach would be to update QComboBox->model directly. - bool block_state = cur_display_filter_combo->lineEdit()->blockSignals(true); - cur_display_filter_combo->addItem(filter, QVariant(QDateTime::currentMSecsSinceEpoch())); - cur_display_filter_combo->clearEditText(); - cur_display_filter_combo->lineEdit()->blockSignals(block_state); - return TRUE; -} diff --git a/ui/qt/widgets/display_filter_combo.h b/ui/qt/widgets/display_filter_combo.h index 81fa11ba..d53bfca4 100644 --- a/ui/qt/widgets/display_filter_combo.h +++ b/ui/qt/widgets/display_filter_combo.h @@ -23,9 +23,16 @@ public: void updateStyleSheet(); protected: +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + void rowsAboutToBeInserted(const QModelIndex&, int, int); + void rowsInserted(const QModelIndex&, int, int); +#endif virtual bool event(QEvent *event); private: +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + bool clear_state_; +#endif public slots: bool checkDisplayFilter(); diff --git a/ui/qt/widgets/display_filter_edit.cpp b/ui/qt/widgets/display_filter_edit.cpp index 839b14fd..09113da7 100644 --- a/ui/qt/widgets/display_filter_edit.cpp +++ b/ui/qt/widgets/display_filter_edit.cpp @@ -9,9 +9,8 @@ #include "config.h" -#include - #include +#include #include @@ -58,8 +57,16 @@ #define DEFAULT_MODIFIER "Ctrl-" #endif -// proto.c:fld_abbrev_chars -static const QString fld_abbrev_chars_ = "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"; +// ':' is not a legal field character, but it appears inside literals and +// having it as a token character will keep field completion from being +// offered in a place where it is syntactically impossible. +// +// The other place ':' is used in the grammar is to separate display filter +// macros from their argument lists in the ${macro:arg;arg} format. Adding +// ':' here means that the first argument of the list won't have a completion +// pop-up. (We don't do completion for the macro names, maybe we should?) +// ${macro;arg;arg} is allowed now, though. +static const QString fld_abbrev_chars_ = ":-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"; DisplayFilterEdit::DisplayFilterEdit(QWidget *parent, DisplayFilterEditType type) : SyntaxLineEdit(parent), @@ -121,6 +128,8 @@ DisplayFilterEdit::DisplayFilterEdit(QWidget *parent, DisplayFilterEditType type connect(this, &DisplayFilterEdit::returnPressed, this, &DisplayFilterEdit::applyDisplayFilter); } + setDefaultPlaceholderText(); + connect(this, &DisplayFilterEdit::textChanged, this, static_cast(&DisplayFilterEdit::checkFilter)); @@ -578,16 +587,24 @@ void DisplayFilterEdit::buildCompletionList(const QString &field_word, const QSt void *field_cookie; const QByteArray fw_ba = field_word.toUtf8(); // or toLatin1 or toStdString? const char *fw_utf8 = fw_ba.constData(); - gsize fw_len = (gsize) strlen(fw_utf8); + size_t fw_len = (size_t) strlen(fw_utf8); for (header_field_info *hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo; hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie)) { if (hfinfo->same_name_prev_id != -1) continue; // Ignore duplicate names. if (!g_ascii_strncasecmp(fw_utf8, hfinfo->abbrev, fw_len)) { - if ((gsize) strlen(hfinfo->abbrev) != fw_len) field_list << hfinfo->abbrev; + if ((size_t) strlen(hfinfo->abbrev) != fw_len) field_list << hfinfo->abbrev; } } } } + + // Add display filter functions to the completion list + GPtrArray *func_list = df_func_name_list(); + for (unsigned i = 0; i < func_list->len; i++) { + field_list << QString::fromUtf8(static_cast(func_list->pdata[i])).append("("); + } + g_ptr_array_unref(func_list); + field_list.sort(); } @@ -614,19 +631,42 @@ void DisplayFilterEdit::clearFilter() void DisplayFilterEdit::applyDisplayFilter() { if (completer()->popup()->currentIndex().isValid()) { - // If the popup (not the QCompleter itself) has a currently - // valid QModelIndex, that means that the popup's - // QAbstractItemView::activated() signal has not yet - // been handled, which means that text() has the old value, - // not the one from the completer. - return; + // If the popup (not the QCompleter itself) has a currently valid + // QModelIndex, check to see if text() matches the text from the popup. + // If it does, then all is well, go ahead and filter (this happens + // if the popup entry is selected via mouse.) + // + // If it doesn't match, then it has the old value. There are two + // possibilities: + // 1) The user clicked away from the popup *without* selecting + // anything (making the popup disappear), and then hit Enter, in + // which case the user wants to filter with text() and doesn't care + // about what's in the popup. However, the QModelIndex for the popup + // is still valid until some time after this signal is handled. + // + // 2) The user pressed Return on an entry in the popup, in which + // case the user wants to filter with the new value in the popup, + // not the value in text(), but for some reason the popup's + // activated() signal gets handled *after* returnPressed on the + // LineEdit, unfortunately (#19323). + // + // We haven't figured out how to distinguish case 1 from case 2 yet, + // so ignore this force the user to press Enter again, and which + // point everything will have reconciled. + // + // Note that the currentCompletion() / currentIndex.data() of + // the completer() itself is "what would be the first completion + // of the text currently displayed in the line edit" and has naught + // to do with what was selected in the popup. + if (text() != completer()->popup()->currentIndex().data()) { + return; + } } if (syntaxState() == Invalid) return; - if (text().length() > 0) - last_applied_ = text(); + last_applied_ = text(); updateClearButton(); @@ -712,9 +752,7 @@ void DisplayFilterEdit::applyOrPrepareFilter() if (! pa || pa->property("display_filter").toString().isEmpty()) return; - QString filterText = pa->property("display_filter").toString(); - last_applied_ = filterText; - setText(filterText); + setText(pa->property("display_filter").toString()); // Holding down the Shift key will only prepare filter. if (!(QApplication::keyboardModifiers() & Qt::ShiftModifier)) { @@ -802,7 +840,6 @@ void DisplayFilterEdit::dropEvent(QDropEvent *event) return; } - last_applied_ = filterText; setText(filterText); // Holding down the Shift key will only prepare filter. diff --git a/ui/qt/widgets/dissector_syntax_line_edit.cpp b/ui/qt/widgets/dissector_syntax_line_edit.cpp index ae8a2247..4f228ce4 100644 --- a/ui/qt/widgets/dissector_syntax_line_edit.cpp +++ b/ui/qt/widgets/dissector_syntax_line_edit.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include #include @@ -38,6 +36,15 @@ DissectorSyntaxLineEdit::DissectorSyntaxLineEdit(QWidget *parent) : setCompleter(new QCompleter(completion_model_, this)); setCompletionTokenChars(fld_abbrev_chars_); + updateDissectorNames(); + setDefaultPlaceholderText(); + + connect(this, &DissectorSyntaxLineEdit::textChanged, this, + static_cast(&DissectorSyntaxLineEdit::checkDissectorName)); +} + +void DissectorSyntaxLineEdit::updateDissectorNames() +{ GList *dissector_names = get_dissector_names(); QStringList dissector_list; for (GList* l = dissector_names; l != NULL; l = l->next) { @@ -46,10 +53,6 @@ DissectorSyntaxLineEdit::DissectorSyntaxLineEdit(QWidget *parent) : g_list_free(dissector_names); dissector_list.sort(); completion_model_->setStringList(dissector_list); - setDefaultPlaceholderText(); - - connect(this, &DissectorSyntaxLineEdit::textChanged, this, - static_cast(&DissectorSyntaxLineEdit::checkDissectorName)); } void DissectorSyntaxLineEdit::setDefaultPlaceholderText() diff --git a/ui/qt/widgets/dissector_syntax_line_edit.h b/ui/qt/widgets/dissector_syntax_line_edit.h index adcee8c7..a99442b7 100644 --- a/ui/qt/widgets/dissector_syntax_line_edit.h +++ b/ui/qt/widgets/dissector_syntax_line_edit.h @@ -20,19 +20,22 @@ class DissectorSyntaxLineEdit : public SyntaxLineEdit Q_OBJECT public: explicit DissectorSyntaxLineEdit(QWidget *parent = 0); + void updateDissectorNames(); + void setDefaultPlaceholderText(); protected: void keyPressEvent(QKeyEvent *event) { completionKeyPressEvent(event); } void focusInEvent(QFocusEvent *event) { completionFocusInEvent(event); } -private slots: +public slots: void checkDissectorName(const QString &dissector); + +private slots: void changeEvent(QEvent* event); private: QString placeholder_text_; - void setDefaultPlaceholderText(); void buildCompletionList(const QString &field_word, const QString &preamble); }; diff --git a/ui/qt/widgets/field_filter_edit.cpp b/ui/qt/widgets/field_filter_edit.cpp index 7aebf051..b2452c30 100644 --- a/ui/qt/widgets/field_filter_edit.cpp +++ b/ui/qt/widgets/field_filter_edit.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include #include @@ -160,12 +158,12 @@ void FieldFilterEdit::buildCompletionList(const QString &field_word, const QStri void *field_cookie; const QByteArray fw_ba = field_word.toUtf8(); // or toLatin1 or toStdString? const char *fw_utf8 = fw_ba.constData(); - gsize fw_len = (gsize) strlen(fw_utf8); + size_t fw_len = (size_t) strlen(fw_utf8); for (header_field_info *hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo; hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie)) { if (hfinfo->same_name_prev_id != -1) continue; // Ignore duplicate names. if (!g_ascii_strncasecmp(fw_utf8, hfinfo->abbrev, fw_len)) { - if ((gsize) strlen(hfinfo->abbrev) != fw_len) field_list << hfinfo->abbrev; + if ((size_t) strlen(hfinfo->abbrev) != fw_len) field_list << hfinfo->abbrev; } } } diff --git a/ui/qt/widgets/filter_expression_toolbar.cpp b/ui/qt/widgets/filter_expression_toolbar.cpp index 84dabc47..c17f7aee 100644 --- a/ui/qt/widgets/filter_expression_toolbar.cpp +++ b/ui/qt/widgets/filter_expression_toolbar.cpp @@ -181,7 +181,7 @@ WiresharkMimeData * FilterExpressionToolBar::createMimeData(QString name, int po void FilterExpressionToolBar::onActionMoved(QAction* action, int oldPos, int newPos) { - gchar* err = NULL; + char* err = NULL; if (oldPos == newPos) return; @@ -237,7 +237,7 @@ void FilterExpressionToolBar::onFilterDropped(QString description, QString filte return; filter_expression_new(qUtf8Printable(description), - qUtf8Printable(filter), qUtf8Printable(description), TRUE); + qUtf8Printable(filter), qUtf8Printable(description), true); save_migrated_uat("Display expressions", &prefs.filter_expressions_old); filterExpressionsChanged(); @@ -356,16 +356,14 @@ QMenu * FilterExpressionToolBar::findParentMenu(const QStringList tree, void *fe /* Searching existing main menus */ foreach(QAction * entry, data->toolbar->actions()) { - QWidget * widget = data->toolbar->widgetForAction(entry); - QToolButton * tb = qobject_cast(widget); - if (tb && tb->menu() && tb->text().compare(tree.at(0).trimmed()) == 0) - return findParentMenu(tree.mid(1), fed_data, tb->menu()); + if (entry->text().compare(tree.at(0).trimmed()) == 0) + return findParentMenu(tree.mid(1), fed_data, entry->menu()); } } else if (parent) { QString menuName = tree.at(0).trimmed(); - /* Iterate to see, if we next have to jump into another submenu */ + /* Iterate to see if we next have to jump into another submenu */ foreach(QAction *entry, parent->actions()) { if (entry->menu() && entry->text().compare(menuName) == 0) @@ -382,16 +380,18 @@ QMenu * FilterExpressionToolBar::findParentMenu(const QStringList tree, void *fe /* No menu has been found, create one */ QString parentName = tree.at(0).trimmed(); - QToolButton * menuButton = new QToolButton(); - menuButton->setText(parentName); - menuButton->setPopupMode(QToolButton::MenuButtonPopup); - QMenu * parentMenu = new QMenu(menuButton); + QMenu * parentMenu = new QMenu(data->toolbar); parentMenu->installEventFilter(data->toolbar); parentMenu->setProperty(dfe_menu_, QVariant::fromValue(true)); - menuButton->setMenu(parentMenu); - // Required for QToolButton::MenuButtonPopup. - connect(menuButton, &QToolButton::pressed, menuButton, &QToolButton::showMenu); - data->toolbar->addWidget(menuButton); + QAction *menuAction = new QAction(data->toolbar); + menuAction->setText(parentName); + menuAction->setMenu(parentMenu); + // QToolButton::MenuButtonPopup means that pressing the button text + // itself doesn't open the menu, only pressing the downwards pointing + // triangle does. This is difficult to change for the auto created + // QToolButton inside the QToolBar. But only auto created tool buttons + // will show up in the extension menu at narrow widths (#19887.) + data->toolbar->addAction(menuAction); return findParentMenu(tree.mid(1), fed_data, parentMenu); } @@ -407,7 +407,7 @@ bool FilterExpressionToolBar::filter_expression_add_action(const void *key _U_, struct filter_expression_data* data = (filter_expression_data*)user_data; if (!fe->enabled) - return FALSE; + return false; QString label = QString(fe->label); @@ -449,7 +449,7 @@ bool FilterExpressionToolBar::filter_expression_add_action(const void *key _U_, connect(dfb_action, &QAction::triggered, data->toolbar, &FilterExpressionToolBar::filterClicked); data->actions_added = true; - return FALSE; + return false; } void FilterExpressionToolBar::filterClicked() diff --git a/ui/qt/widgets/filter_expression_toolbar.h b/ui/qt/widgets/filter_expression_toolbar.h index 80724a27..174d927b 100644 --- a/ui/qt/widgets/filter_expression_toolbar.h +++ b/ui/qt/widgets/filter_expression_toolbar.h @@ -9,8 +9,6 @@ #include -#include - #include #ifndef FILTER_EXPRESSION_TOOLBAR_H diff --git a/ui/qt/widgets/follow_stream_text.cpp b/ui/qt/widgets/follow_stream_text.cpp index a8e0f2b9..b2492c0b 100644 --- a/ui/qt/widgets/follow_stream_text.cpp +++ b/ui/qt/widgets/follow_stream_text.cpp @@ -9,10 +9,16 @@ #include +#include "epan/prefs.h" + +#include + #include +#include #include #include +#include // To do: // - Draw text by hand similar to ByteViewText. This would let us add @@ -20,17 +26,96 @@ // max_document_length_ in FollowStreamDialog. FollowStreamText::FollowStreamText(QWidget *parent) : - QPlainTextEdit(parent) + QPlainTextEdit(parent), truncated_(false) { setMouseTracking(true); // setMaximumBlockCount(1); QTextDocument *text_doc = document(); text_doc->setDefaultFont(mainApp->monospaceFont()); + + metainfo_fg_ = ColorUtils::alphaBlend(palette().windowText(), palette().window(), 0.35); +} + +const int FollowStreamText::max_document_length_ = 500 * 1000 * 1000; // Just a guess + +void FollowStreamText::addTruncated(int cur_pos) +{ + if (truncated_) { + QTextCharFormat tcf = currentCharFormat(); + tcf.setBackground(palette().base().color()); + tcf.setForeground(metainfo_fg_); + insertPlainText("\n" + tr("[Stream output truncated]")); + moveCursor(QTextCursor::End); + } else { + verticalScrollBar()->setValue(cur_pos); + } +} + +void FollowStreamText::addText(QString text, bool is_from_server, uint32_t packet_num, bool colorize) +{ + if (truncated_) { + return; + } + + int char_count = document()->characterCount(); + if (char_count + text.length() > max_document_length_) { + text.truncate(max_document_length_ - char_count); + truncated_ = true; + } + + setUpdatesEnabled(false); + int cur_pos = verticalScrollBar()->value(); + moveCursor(QTextCursor::End); + + QTextCharFormat tcf = currentCharFormat(); + if (!colorize) { + tcf.setBackground(palette().base().color()); + tcf.setForeground(palette().text().color()); + } else if (is_from_server) { + tcf.setForeground(ColorUtils::fromColorT(prefs.st_server_fg)); + tcf.setBackground(ColorUtils::fromColorT(prefs.st_server_bg)); + } else { + tcf.setForeground(ColorUtils::fromColorT(prefs.st_client_fg)); + tcf.setBackground(ColorUtils::fromColorT(prefs.st_client_bg)); + } + setCurrentCharFormat(tcf); + + insertPlainText(text); + text_pos_to_packet_[textCursor().anchor()] = packet_num; + + addTruncated(cur_pos); + setUpdatesEnabled(true); +} + +void FollowStreamText::addDeltaTime(double delta) +{ + QString delta_str = QString("\n%1s").arg(QString::number(delta, 'f', 6)); + if (truncated_) { + return; + } + + if (document()->characterCount() + delta_str.length() > max_document_length_) { + truncated_ = true; + } + + setUpdatesEnabled(false); + int cur_pos = verticalScrollBar()->value(); + moveCursor(QTextCursor::End); + + QTextCharFormat tcf = currentCharFormat(); + tcf.setBackground(palette().base().color()); + tcf.setForeground(metainfo_fg_); + setCurrentCharFormat(tcf); + + insertPlainText(delta_str); + + addTruncated(cur_pos); + setUpdatesEnabled(true); } void FollowStreamText::mouseMoveEvent(QMouseEvent *event) { - emit mouseMovedToTextCursorPosition(cursorForPosition(event->pos()).position()); + emit mouseMovedToPacket(textPosToPacket(cursorForPosition(event->pos()).position())); // Don't send the mouseMoveEvents with no buttons pushed to the base // class, effectively turning off mouse tracking for the base class. // It causes a lot of useless calculations that hurt scroll performance. @@ -41,12 +126,37 @@ void FollowStreamText::mouseMoveEvent(QMouseEvent *event) void FollowStreamText::mousePressEvent(QMouseEvent *event) { - emit mouseClickedOnTextCursorPosition(cursorForPosition(event->pos()).position()); + emit mouseClickedOnPacket(textPosToPacket(cursorForPosition(event->pos()).position())); QPlainTextEdit::mousePressEvent(event); } void FollowStreamText::leaveEvent(QEvent *event) { - emit mouseMovedToTextCursorPosition(-1); + emit mouseMovedToPacket(0); QPlainTextEdit::leaveEvent(event); } + +void FollowStreamText::clear() +{ + truncated_ = false; + text_pos_to_packet_.clear(); + QPlainTextEdit::clear(); +} + +int FollowStreamText::currentPacket() const +{ + return textPosToPacket(textCursor().position()); +} + +int FollowStreamText::textPosToPacket(int text_pos) const +{ + int pkt = 0; + if (text_pos >= 0) { + QMap::const_iterator it = text_pos_to_packet_.upperBound(text_pos); + if (it != text_pos_to_packet_.end()) { + pkt = it.value(); + } + } + + return pkt; +} diff --git a/ui/qt/widgets/follow_stream_text.h b/ui/qt/widgets/follow_stream_text.h index 0dd8dca5..0276c872 100644 --- a/ui/qt/widgets/follow_stream_text.h +++ b/ui/qt/widgets/follow_stream_text.h @@ -17,6 +17,10 @@ class FollowStreamText : public QPlainTextEdit Q_OBJECT public: explicit FollowStreamText(QWidget *parent = 0); + bool isTruncated() const { return truncated_; } + void addText(QString text, bool is_from_server, uint32_t packet_num, bool colorize); + void addDeltaTime(double delta); + int currentPacket() const; protected: void mouseMoveEvent(QMouseEvent *event); @@ -24,12 +28,20 @@ protected: void leaveEvent(QEvent *event); signals: - // Perhaps this is not descriptive enough. We should add more words. - void mouseMovedToTextCursorPosition(int); - void mouseClickedOnTextCursorPosition(int); + void mouseMovedToPacket(int); + void mouseClickedOnPacket(int); public slots: + void clear(); +private: + int textPosToPacket(int text_pos) const; + void addTruncated(int cur_pos); + + static const int max_document_length_; + bool truncated_; + QMap text_pos_to_packet_; + QColor metainfo_fg_; }; #endif // FOLLOW_STREAM_TEXT_H diff --git a/ui/qt/widgets/label_stack.cpp b/ui/qt/widgets/label_stack.cpp index 4cac15b7..8deedaec 100644 --- a/ui/qt/widgets/label_stack.cpp +++ b/ui/qt/widgets/label_stack.cpp @@ -68,9 +68,10 @@ void LabelStack::fillLabel() { setStyleSheet(style_sheet); } setText(si.text); + setToolTip(si.tooltip); } -void LabelStack::pushText(const QString &text, int ctx) { +void LabelStack::pushText(const QString &text, int ctx, const QString &tooltip) { popText(ctx); if (ctx == temporary_ctx_) { @@ -83,6 +84,7 @@ void LabelStack::pushText(const QString &text, int ctx) { StackItem si; si.text = text; + si.tooltip = tooltip; si.ctx = ctx; labels_.prepend(si); fillLabel(); diff --git a/ui/qt/widgets/label_stack.h b/ui/qt/widgets/label_stack.h index 63657b74..27e41be1 100644 --- a/ui/qt/widgets/label_stack.h +++ b/ui/qt/widgets/label_stack.h @@ -21,7 +21,7 @@ class LabelStack : public QLabel public: explicit LabelStack(QWidget *parent = 0); void setTemporaryContext(const int ctx); - void pushText(const QString &text, int ctx); + void pushText(const QString &text, int ctx, const QString &tooltip = QString()); void setShrinkable(bool shrinkable = true); protected: @@ -35,6 +35,7 @@ protected: private: typedef struct _StackItem { QString text; + QString tooltip; int ctx; } StackItem; diff --git a/ui/qt/widgets/path_selection_edit.cpp b/ui/qt/widgets/path_selection_edit.cpp index eb30f1d0..660a6f53 100644 --- a/ui/qt/widgets/path_selection_edit.cpp +++ b/ui/qt/widgets/path_selection_edit.cpp @@ -10,18 +10,18 @@ #include "config.h" -#include "epan/prefs.h" #include "ui/util.h" #include #include "ui/qt/widgets/wireshark_file_dialog.h" +#include "ui/qt/utils/qt_ui_utils.h" #include #include #include #include -PathSelectionEdit::PathSelectionEdit(QString title, QString path, bool selectFile, QWidget *parent) : +PathSelectionEdit::PathSelectionEdit(QString title, QString path, bool selectFile, QWidget *parent) : QWidget(parent) { _title = title; @@ -49,7 +49,7 @@ PathSelectionEdit::PathSelectionEdit(QString title, QString path, bool selectFil setFocusPolicy(_edit->focusPolicy()); } -PathSelectionEdit::PathSelectionEdit(QWidget *parent) : +PathSelectionEdit::PathSelectionEdit(QWidget *parent) : PathSelectionEdit(tr("Select a path"), QString(), true, parent) {} @@ -75,11 +75,7 @@ void PathSelectionEdit::browseForPath() QString openDir = _path; if (openDir.isEmpty()) { - if (prefs.gui_fileopen_style == FO_STYLE_LAST_OPENED) { - openDir = QString(get_open_dialog_initial_dir()); - } else if (prefs.gui_fileopen_style == FO_STYLE_SPECIFIED) { - openDir = QString(prefs.gui_fileopen_dir); - } + openDir = openDialogInitialDir(); } QString newPath; diff --git a/ui/qt/widgets/profile_tree_view.cpp b/ui/qt/widgets/profile_tree_view.cpp index afa86d71..ebac67c7 100644 --- a/ui/qt/widgets/profile_tree_view.cpp +++ b/ui/qt/widgets/profile_tree_view.cpp @@ -7,31 +7,28 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -#include #include #include +#include #include #include #include +#include #include #include -#include -ProfileUrlLinkDelegate::ProfileUrlLinkDelegate(QObject *parent) : UrlLinkDelegate (parent) {} +ProfileTreeEditDelegate::ProfileTreeEditDelegate(QWidget *parent) : QItemDelegate(parent), editor_(Q_NULLPTR) {} -void ProfileUrlLinkDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +QWidget *ProfileTreeEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const { - /* Only paint links for valid paths */ - if (index.data(ProfileModel::DATA_PATH_IS_NOT_DESCRIPTION).toBool()) - UrlLinkDelegate::paint(painter, option, index); - else - QStyledItemDelegate::paint(painter, option, index); - + if (index.column() == ProfileModel::COL_AUTO_SWITCH_FILTER) { + return new DisplayFilterEdit(parent); + } + return QItemDelegate::createEditor(parent, option, index); } -ProfileTreeEditDelegate::ProfileTreeEditDelegate(QWidget *parent) : QItemDelegate(parent), editor_(Q_NULLPTR) {} - void ProfileTreeEditDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { if (qobject_cast(editor)) @@ -46,8 +43,8 @@ ProfileTreeView::ProfileTreeView(QWidget *parent) : { delegate_ = new ProfileTreeEditDelegate(); setItemDelegateForColumn(ProfileModel::COL_NAME, delegate_); + setItemDelegateForColumn(ProfileModel::COL_AUTO_SWITCH_FILTER, delegate_); - connect(this, &QAbstractItemView::clicked, this, &ProfileTreeView::clicked); connect(delegate_, &ProfileTreeEditDelegate::commitData, this, &ProfileTreeView::itemUpdated); } @@ -80,19 +77,6 @@ void ProfileTreeView::selectionChanged(const QItemSelection &selected, const QIt } } -void ProfileTreeView::clicked(const QModelIndex &index) -{ - if (!index.isValid()) - return; - - /* Only paint links for valid paths */ - if (index.data(ProfileModel::DATA_INDEX_VALUE_IS_URL).toBool()) - { - QString path = QDir::toNativeSeparators(index.data().toString()); - QDesktopServices::openUrl(QUrl::fromLocalFile(path)); - } -} - void ProfileTreeView::selectRow(int row) { if (row < 0) @@ -117,3 +101,30 @@ bool ProfileTreeView::activeEdit() { return (state() == QAbstractItemView::EditingState); } + +// If our auto switch filters are shorter than the filter column title, +// stretch the name column. +void ProfileTreeView::showEvent(QShowEvent *) +{ + bool have_wide_filter = false; + int auto_switch_title_width = fontMetrics().horizontalAdvance(model()->headerData(ProfileModel::COL_AUTO_SWITCH_FILTER, Qt::Horizontal).toString()); + for (int row = 0; row < model()->rowCount(); row++) { + QString filter = model()->data(model()->index(row, ProfileModel::COL_AUTO_SWITCH_FILTER)).toString(); + if (fontMetrics().horizontalAdvance(filter) > auto_switch_title_width) { + have_wide_filter = true; + break; + } + } + + if (have_wide_filter) { + return; + } + + int col_name_size_hint = sizeHintForColumn(ProfileModel::COL_NAME); + int col_asf_size_hint = qMax(header()->sectionSizeHint(ProfileModel::COL_AUTO_SWITCH_FILTER), sizeHintForColumn(ProfileModel::COL_AUTO_SWITCH_FILTER)); + int extra = columnWidth(ProfileModel::COL_AUTO_SWITCH_FILTER) - col_asf_size_hint; + if (extra > 0) { + setColumnWidth(ProfileModel::COL_NAME, col_name_size_hint + extra); + } + +} diff --git a/ui/qt/widgets/profile_tree_view.h b/ui/qt/widgets/profile_tree_view.h index 9684811e..02492e4b 100644 --- a/ui/qt/widgets/profile_tree_view.h +++ b/ui/qt/widgets/profile_tree_view.h @@ -15,16 +15,6 @@ #include #include -class ProfileUrlLinkDelegate : public UrlLinkDelegate -{ - Q_OBJECT - -public: - explicit ProfileUrlLinkDelegate(QObject *parent = Q_NULLPTR); - - virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; -}; - class ProfileTreeEditDelegate : public QItemDelegate { Q_OBJECT @@ -32,6 +22,7 @@ public: ProfileTreeEditDelegate(QWidget *parent = Q_NULLPTR); // QAbstractItemDelegate interface + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; private: @@ -54,12 +45,12 @@ signals: // QWidget interface protected: + virtual void showEvent(QShowEvent *); virtual void mouseDoubleClickEvent(QMouseEvent *event); // QAbstractItemView interface protected slots: virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); - virtual void clicked(const QModelIndex &index); private: ProfileTreeEditDelegate *delegate_; diff --git a/ui/qt/widgets/qcp_axis_ticker_elided.cpp b/ui/qt/widgets/qcp_axis_ticker_elided.cpp new file mode 100644 index 00000000..154a750a --- /dev/null +++ b/ui/qt/widgets/qcp_axis_ticker_elided.cpp @@ -0,0 +1,74 @@ +/** @file + * + * QCustomPlot QCPAxisTickerText subclass that elides labels to the + * width of the parent QCPAxis's QCPAxisRect's margin for the appropriate + * side, for use when the margin is fixed. + * + * Copyright 2024 John Thacker + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include + +#include + +QCPAxisTickerElided::QCPAxisTickerElided(QCPAxis *parent) : + mParent(parent) +{ +} + +QCP::MarginSide QCPAxisTickerElided::axisTypeToMarginSide(const QCPAxis::AxisType axis) +{ + switch (axis) { + case QCPAxis::atLeft: + return QCP::msLeft; + case QCPAxis::atRight: + return QCP::msRight; + case QCPAxis::atTop: + return QCP::msTop; + case QCPAxis::atBottom: + return QCP::msBottom; + } + return QCP::msNone; +} + +QString QCPAxisTickerElided::elidedText(const QString& text) +{ + QCP::MarginSides autoMargins = mParent->axisRect()->autoMargins(); + if (autoMargins & axisTypeToMarginSide(mParent->axisType())) { + return text; + } + int elide_w; + QMargins margins = mParent->axisRect()->margins(); + switch (mParent->axisType()) { + case QCPAxis::atLeft: + elide_w = margins.left(); + break; + case QCPAxis::atRight: + elide_w = margins.right(); + break; + case QCPAxis::atTop: + elide_w = margins.top(); + break; + case QCPAxis::atBottom: + elide_w = margins.bottom(); + break; + default: + // ?? + elide_w = margins.left(); + } + + return QFontMetrics(mParent->tickLabelFont()).elidedText(text, + Qt::ElideRight, + elide_w); +} + +QString QCPAxisTickerElided::getTickLabel(double tick, const QLocale& , QChar , int) +{ + return elidedText(mTicks.value(tick)); +} diff --git a/ui/qt/widgets/qcp_axis_ticker_elided.h b/ui/qt/widgets/qcp_axis_ticker_elided.h new file mode 100644 index 00000000..b542d9a9 --- /dev/null +++ b/ui/qt/widgets/qcp_axis_ticker_elided.h @@ -0,0 +1,38 @@ +/** @file + * + * QCustomPlot QCPAxisTickerText subclass that elides labels to the + * width of the parent QCPAxis's QCPAxisRect's margin for the appropriate + * side, for use when the margin is fixed. + * + * Copyright 2024 John Thacker + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef QCP_AXIS_TICKER_ELIDED_H +#define QCP_AXIS_TICKER_ELIDED_H + +#include + +class QCPAxisTickerElided : public QCPAxisTickerText +{ +public: + explicit QCPAxisTickerElided(QCPAxis *parent); + + // QCP has marginSideToAxisType but not the inverse + static QCP::MarginSide axisTypeToMarginSide(const QCPAxis::AxisType); + + QString elidedText(const QString& text); + +protected: + virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) override; + +private: + QCPAxis *mParent; +}; + +#endif diff --git a/ui/qt/widgets/qcp_axis_ticker_si.cpp b/ui/qt/widgets/qcp_axis_ticker_si.cpp new file mode 100644 index 00000000..be6d35a6 --- /dev/null +++ b/ui/qt/widgets/qcp_axis_ticker_si.cpp @@ -0,0 +1,74 @@ +/** @file + * + * QCustomPlot QCPAxisTicker subclass that creates human-readable + * SI unit labels, optionally supporting log scale. + * + * Copyright 2024 John Thacker + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include + +#include +#include + +#include + +QCPAxisTickerSi::QCPAxisTickerSi(format_size_units_e unit, QString customUnit, bool log) : + mUnit(unit), mCustomUnit(customUnit), mLog(log) +{ +} + +QString QCPAxisTickerSi::getTickLabel(double tick, const QLocale& , QChar , int precision) +{ + QString label = gchar_free_to_qstring(format_units(nullptr, tick, mUnit, FORMAT_SIZE_PREFIX_SI, precision)); + + // XXX - format_units isn't consistent about whether we need to + // add a space or not + if (mUnit == FORMAT_SIZE_UNIT_NONE && !mCustomUnit.isEmpty()) { + label += mCustomUnit; + } + // XXX - "Beautiful typeset powers" for exponentials is handled by QCPAxis, + // not QCPAxisTicker and its subclasses, and its detection of exponentials + // doesn't handle having a unit or other suffix, so that won't work. + // In practical use we'll be within our prefix range, though. + return label; +} + +int QCPAxisTickerSi::getSubTickCount(double tickStep) +{ + if (mLog) { + return QCPAxisTickerLog::getSubTickCount(tickStep); + } else { + return QCPAxisTicker::getSubTickCount(tickStep); + } +} + +QVector QCPAxisTickerSi::createTickVector(double tickStep, const QCPRange &range) +{ + if (mLog) { + return QCPAxisTickerLog::createTickVector(tickStep, range); + } else { + return QCPAxisTicker::createTickVector(tickStep, range); + } +} + +void QCPAxisTickerSi::setUnit(format_size_units_e unit) +{ + mUnit = unit; +} + +void QCPAxisTickerSi::setCustomUnit(QString unit) +{ + mCustomUnit = unit; +} + +void QCPAxisTickerSi::setLog(bool log) +{ + mLog = log; +} diff --git a/ui/qt/widgets/qcp_axis_ticker_si.h b/ui/qt/widgets/qcp_axis_ticker_si.h new file mode 100644 index 00000000..a9fa51cc --- /dev/null +++ b/ui/qt/widgets/qcp_axis_ticker_si.h @@ -0,0 +1,42 @@ +/** @file + * + * QCustomPlot QCPAxisTicker subclass that creates human-readable + * SI unit labels, optionally supporting log scale. + * + * Copyright 2024 John Thacker + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef QCP_AXIS_TICKER_SI_H +#define QCP_AXIS_TICKER_SI_H + +#include + +#include + +class QCPAxisTickerSi : public QCPAxisTickerLog +{ +public: + explicit QCPAxisTickerSi(format_size_units_e unit = FORMAT_SIZE_UNIT_PACKETS, QString customUnit = QString(), bool log = false); + + format_size_units_e getUnit() const { return mUnit; } + void setUnit(format_size_units_e unit); + void setCustomUnit(QString unit); + void setLog(bool log); + +protected: + virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) override; + virtual int getSubTickCount(double tickStep) override; + virtual QVector createTickVector(double tickStep, const QCPRange &range) override; + + format_size_units_e mUnit; + QString mCustomUnit; + bool mLog; +}; + +#endif diff --git a/ui/qt/widgets/qcp_string_legend_item.cpp b/ui/qt/widgets/qcp_string_legend_item.cpp new file mode 100644 index 00000000..62596895 --- /dev/null +++ b/ui/qt/widgets/qcp_string_legend_item.cpp @@ -0,0 +1,46 @@ +/** @file + * + * QCustomPlot QCPAbstractLegendItem subclass containing a string. + * This is used to add a title to a QCPLegend. + * + * This file is from https://www.qcustomplot.com/index.php/support/forum/443 + * where the author David said "I thought I would share in case any one else + * is needing the same functionality." Accordingly, this file is in the + * public domain. + */ + +#include + +QCPStringLegendItem::QCPStringLegendItem(QCPLegend *pParent, const QString& strText) + : QCPAbstractLegendItem(pParent) + , m_strText(strText) +{ +} + +QString QCPStringLegendItem::text() const +{ + return m_strText; +} + +void QCPStringLegendItem::setText(const QString& strText) +{ + m_strText = strText; +} + +void QCPStringLegendItem::draw(QCPPainter *pPainter) +{ + pPainter->setFont(mFont); + pPainter->setPen(QPen(mTextColor)); + QRectF textRect = pPainter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip, m_strText); + pPainter->drawText(mRect.x() + mMargins.left(), mRect.y(), textRect.width(), textRect.height(), Qt::TextDontClip | Qt::AlignHCenter, m_strText); +} + +QSize QCPStringLegendItem::minimumOuterSizeHint() const +{ + QSize cSize(0, 0); + QFontMetrics fontMetrics(mFont); + QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip, m_strText); + cSize.setWidth(textRect.width() + mMargins.left() + mMargins.right()); + cSize.setHeight(textRect.height() + mMargins.top() + mMargins.bottom()); + return cSize; +} diff --git a/ui/qt/widgets/qcp_string_legend_item.h b/ui/qt/widgets/qcp_string_legend_item.h new file mode 100644 index 00000000..d32631ad --- /dev/null +++ b/ui/qt/widgets/qcp_string_legend_item.h @@ -0,0 +1,35 @@ +/** @file + * + * QCustomPlot QCPAbstractLegendItem subclass containing a string. + * This is used to add a title to a QCPLegend. + * + * This file is from https://www.qcustomplot.com/index.php/support/forum/443 + * where the author David said "I thought I would share in case any one else + * is needing the same functionality." Accordingly, this file is in the + * public domain. + */ + +#ifndef QCP_STRING_LEGEND_ITEM_H +#define QCP_STRING_LEGEND_ITEM_H + +#include + +class QCPStringLegendItem : public QCPAbstractLegendItem +{ + Q_OBJECT + +public: + explicit QCPStringLegendItem(QCPLegend *pParent, const QString& strText); + + QString text() const; + void setText(const QString& strText); + +protected: + virtual void draw(QCPPainter *painter) override; + virtual QSize minimumOuterSizeHint() const override; + +private: + QString m_strText; +}; + +#endif diff --git a/ui/qt/widgets/resize_header_view.cpp b/ui/qt/widgets/resize_header_view.cpp new file mode 100644 index 00000000..7335265f --- /dev/null +++ b/ui/qt/widgets/resize_header_view.cpp @@ -0,0 +1,45 @@ +/** @file + * + * Header view with a context menu to resize all sections to contents + * + * Copyright 2024 John Thacker + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "resize_header_view.h" + +#include +#include + +ResizeHeaderView::ResizeHeaderView(Qt::Orientation orientation, QWidget *parent) : QHeaderView(orientation, parent) +{ + setStretchLastSection(true); + setSectionsMovable(true); + // setFirstSectionMovable(true) ? +} + +/*! + \fn void ResizeHeaderView::contextMenuEvent(QContextMenuEvent *e) + + Shows a context menu which resizes all sections to their contents. + */ + +void ResizeHeaderView::contextMenuEvent(QContextMenuEvent *e) +{ + if (e == nullptr) + return; + + QMenu *ctxMenu = new QMenu(this); + ctxMenu->setAttribute(Qt::WA_DeleteOnClose); + + QString text = tr("Resize all %1 to contents").arg((orientation() == Qt::Horizontal) ? "columns" : "rows"); + QAction *act = ctxMenu->addAction(std::move(text)); + connect(act, &QAction::triggered, this, [&]() { resizeSections(QHeaderView::ResizeToContents); }); + + ctxMenu->popup(e->globalPos()); +} diff --git a/ui/qt/widgets/resize_header_view.h b/ui/qt/widgets/resize_header_view.h new file mode 100644 index 00000000..a8aa57f3 --- /dev/null +++ b/ui/qt/widgets/resize_header_view.h @@ -0,0 +1,31 @@ +/** @file + * + * Header view with a context menu to resize all sections to contents + * + * Copyright 2024 John Thacker + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef RESIZE_HEADER_VIEW_H +#define RESIZE_HEADER_VIEW_H + +#include +#include + +class ResizeHeaderView : public QHeaderView +{ + Q_OBJECT + +public: + ResizeHeaderView(Qt::Orientation orientation, QWidget *parent = nullptr); + +protected: + void contextMenuEvent(QContextMenuEvent *e) override; + +}; +#endif // RESIZE_HEADER_VIEW_H diff --git a/ui/qt/widgets/resolved_addresses_view.cpp b/ui/qt/widgets/resolved_addresses_view.cpp new file mode 100644 index 00000000..82b2a299 --- /dev/null +++ b/ui/qt/widgets/resolved_addresses_view.cpp @@ -0,0 +1,261 @@ +/** @file + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#define WS_LOG_DOMAIN LOG_DOMAIN_QTUI + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "main_application.h" + +#include + +ResolvedAddressesView::ResolvedAddressesView(QWidget *parent) : QTableView(parent) +{ + setEditTriggers(QAbstractItemView::NoEditTriggers); + setSortingEnabled(true); + setSelectionBehavior(QAbstractItemView::SelectRows); + horizontalHeader()->setStretchLastSection(true); + verticalHeader()->setVisible(false); + + // creating this action is mostly to override the default Ctrl-C handling + // (which could also be done by overriding KeyPressEvent) and to make the + // keyboard shortcut show up in the context menu. +#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0) + clip_action_ = new QAction(tr("as Plain Text"), this); + clip_action_->setShortcut(QKeySequence(QKeySequence::Copy)); + connect(clip_action_, &QAction::triggered, this, &ResolvedAddressesView::clipboardAction); + addAction(clip_action_); +#else + clip_action_ = addAction(tr("as Plain Text"), QKeySequence(QKeySequence::Copy), this, &ResolvedAddressesView::clipboardAction); +#endif + clip_action_->setProperty("copy_as", ResolvedAddressesView::EXPORT_TEXT); + clip_action_->setProperty("selected", true); +} + +QMenu* ResolvedAddressesView::createCopyMenu(bool selected, QWidget *parent) +{ + QMenu *copy_menu; + if (selected) { + copy_menu = new QMenu(tr("Copy selected rows"), parent); + } else { + copy_menu = new QMenu(tr("Copy table"), parent); + } + copy_menu->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"))); + QAction *ca; + if (selected) { + copy_menu->addAction(clip_action_); + } else { + ca = copy_menu->addAction(tr("as Plain Text"), this, &ResolvedAddressesView::clipboardAction); + ca->setProperty("copy_as", ResolvedAddressesView::EXPORT_TEXT); + ca->setProperty("selected", selected); + } + ca = copy_menu->addAction(tr("as CSV"), this, &ResolvedAddressesView::clipboardAction); + ca->setProperty("copy_as", ResolvedAddressesView::EXPORT_CSV); + ca->setProperty("selected", selected); + ca = copy_menu->addAction(tr("as JSON"), this, &ResolvedAddressesView::clipboardAction); + ca->setProperty("copy_as", ResolvedAddressesView::EXPORT_JSON); + ca->setProperty("selected", selected); + + return copy_menu; +} + +void ResolvedAddressesView::contextMenuEvent(QContextMenuEvent *e) +{ + if (!e) + return; + + QMenu *ctxMenu = new QMenu(this); + ctxMenu->setAttribute(Qt::WA_DeleteOnClose); + ctxMenu->addMenu(createCopyMenu(true, ctxMenu)); + QAction *act = ctxMenu->addAction(tr("Save selected rows as…")); + act->setIcon(QIcon::fromTheme(QStringLiteral("document-save-as"))); + act->setProperty("selected", true); + connect(act, &QAction::triggered, this, &ResolvedAddressesView::saveAs); + ctxMenu->addSeparator(); + ctxMenu->addMenu(createCopyMenu(false, ctxMenu)); + act = ctxMenu->addAction(QIcon::fromTheme(QStringLiteral("document-save-as")), tr("Save table as…"), this, &ResolvedAddressesView::saveAs); + act->setProperty("selected", false); + + ctxMenu->popup(e->globalPos()); +} + +AStringListListModel* ResolvedAddressesView::dataModel() const +{ + QSortFilterProxyModel *proxy = qobject_cast(model()); + + if (proxy) { + QAbstractItemModel *source = proxy->sourceModel(); + while (qobject_cast(source) != nullptr) { + proxy = qobject_cast(source); + source = proxy->sourceModel(); + } + return qobject_cast(source); + } + return nullptr; +} + +void ResolvedAddressesView::clipboardAction() +{ + QAction *ca = qobject_cast(sender()); + if (ca && ca->property("copy_as").isValid()) { + copyToClipboard(static_cast(ca->property("copy_as").toInt()), + ca->property("selected").toBool()); + } +} + +void ResolvedAddressesView::copyToClipboard(eResolvedAddressesExport format, bool selected) +{ + QString clipText; + QTextStream stream(&clipText, QIODevice::Text); + toTextStream(stream, format, selected); + mainApp->clipboard()->setText(stream.readAll()); +} + +void ResolvedAddressesView::saveAs() +{ + bool selected = false; + QAction *ca = qobject_cast(sender()); + if (ca && ca->property("selected").isValid()) { + selected = true; + } + QString caption(mainApp->windowTitleString(tr("Save Resolved Addresses As…"))); + QString txtFilter = tr("Plain text (*.txt)"); + QString csvFilter = tr("CSV Document (*.csv)"); + QString jsonFilter = tr("JSON Document (*.json)"); + QString selectedFilter; + QString fileName = WiresharkFileDialog::getSaveFileName(this, caption, + mainApp->openDialogInitialDir().canonicalPath(), + QString("%1;;%2;;%3").arg(txtFilter).arg(csvFilter).arg(jsonFilter), + &selectedFilter); + if (fileName.isEmpty()) { + return; + } + + eResolvedAddressesExport format(EXPORT_TEXT); + if (selectedFilter.compare(csvFilter) == 0) { + format = EXPORT_CSV; + } else if (selectedFilter.compare(jsonFilter) == 0) { + format = EXPORT_JSON; + } + + // macOS and Windows use the native file dialog, which enforces file + // extensions. UN*X dialogs generally don't. That's ok here, at + // least for the text format, because hosts and ethers and services + // files don't have an extension. + QFile saveFile(fileName); + if (saveFile.open(QFile::WriteOnly | QFile::Text)) { + QTextStream stream(&saveFile); + toTextStream(stream, format, selected); + saveFile.close(); + } else { + QMessageBox::warning(this, tr("Warning").arg(saveFile.fileName()), + tr("Unable to save %1: %2").arg(saveFile.fileName().arg(saveFile.errorString()))); + } +} + + +void ResolvedAddressesView::toTextStream(QTextStream& stream, + eResolvedAddressesExport format, bool selected) const +{ + if (model() == nullptr) { + return; + } + + // XXX: TrafficTree and TapParameterDialog have similar + // "export a QAbstractItemModel to a QTextStream in TEXT, CSV or JSON" + // functions that could be made into common code. + QStringList rowText; + if (format == EXPORT_TEXT) { + if (qobject_cast(dataModel()) != nullptr) { + // Format of services(5) + if (!selected) { + stream << "# service-name\tport/protocol\n"; + } + for (int row = 0; row < model()->rowCount(); row++) { + if (selected && !selectionModel()->isRowSelected(row, QModelIndex())) continue; + rowText.clear(); + rowText << model()->data(model()->index(row, PORTS_COL_NAME)).toString(); + rowText << QString("%1/%2") + .arg(model()->data(model()->index(row, PORTS_COL_PORT)).toString()) + .arg(model()->data(model()->index(row, PORTS_COL_PROTOCOL)).toString()); + stream << rowText.join("\t") << "\n"; + } + } else { + // Format as hosts(5) and ethers(5) + if (!selected) { + for (int col = 0; col < model()->columnCount(); col++) { + rowText << model()->headerData(col, Qt::Horizontal).toString(); + } + stream << "# " << rowText.join("\t") << "\n"; + } + for (int row = 0; row < model()->rowCount(); row++) { + if (selected && !selectionModel()->isRowSelected(row, QModelIndex())) continue; + rowText.clear(); + for (int col = 0; col < model()->columnCount(); col++) { + rowText << model()->data(model()->index(row, col)).toString(); + } + stream << rowText.join("\t") << "\n"; + } + } + } else if (format == EXPORT_CSV) { + for (int col = 0; col < model()->columnCount(); col++) { + rowText << model()->headerData(col, Qt::Horizontal).toString(); + } + if (!selected) { + stream << rowText.join(",") << "\n"; + } + for (int row = 0; row < model()->rowCount(); row++) { + if (selected && !selectionModel()->isRowSelected(row, QModelIndex())) continue; + rowText.clear(); + for (int col = 0; col < model()->columnCount(); col++) { + QVariant v = model()->data(model()->index(row, col)); + if (!v.isValid()) { + rowText << QStringLiteral("\"\""); + } else if (v.userType() == QMetaType::QString) { + rowText << QString("\"%1\"").arg(v.toString().replace('\"', "\"\"")); + } else { + rowText << v.toString(); + } + } + stream << rowText.join(",") << "\n"; + } + } else if (format == EXPORT_JSON) { + QMap headers; + for (int col = 0; col < model()->columnCount(); col++) + headers.insert(col, model()->headerData(col, Qt::Horizontal, Qt::DisplayRole).toString()); + + QJsonArray records; + + for (int row = 0; row < model()->rowCount(); row++) { + if (selected && !selectionModel()->isRowSelected(row, QModelIndex())) continue; + QJsonObject rowData; + foreach(int col, headers.keys()) { + QModelIndex idx = model()->index(row, col); + rowData.insert(headers[col], model()->data(idx).toString()); + } + records.push_back(rowData); + } + + QJsonDocument json; + json.setArray(records); + stream << json.toJson(); + } +} diff --git a/ui/qt/widgets/resolved_addresses_view.h b/ui/qt/widgets/resolved_addresses_view.h new file mode 100644 index 00000000..23fb707f --- /dev/null +++ b/ui/qt/widgets/resolved_addresses_view.h @@ -0,0 +1,50 @@ +/** @file + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef RESOLVED_ADDRESSES_VIEW_H +#define RESOLVED_ADDRESSES_VIEW_H + +#include + +#include +#include + +class ResolvedAddressesView : public QTableView +{ + Q_OBJECT + +public: + typedef enum { + EXPORT_TEXT, + EXPORT_CSV, + EXPORT_JSON + } eResolvedAddressesExport; + + ResolvedAddressesView(QWidget *parent = nullptr); + + QMenu* createCopyMenu(bool selected = false, QWidget *parent = nullptr); + +public slots: + void saveAs(); + +protected: + void contextMenuEvent(QContextMenuEvent *e) override; + +private: + QAction *clip_action_; + + AStringListListModel* dataModel() const; + void copyToClipboard(eResolvedAddressesExport format, bool selected); + +private slots: + void clipboardAction(); + void toTextStream(QTextStream &stream, eResolvedAddressesExport format, bool selected = false) const; +}; + +#endif // RESOLVED_ADDRESSES_VIEW_H diff --git a/ui/qt/widgets/rowmove_tree_view.cpp b/ui/qt/widgets/rowmove_tree_view.cpp new file mode 100644 index 00000000..fa91b28e --- /dev/null +++ b/ui/qt/widgets/rowmove_tree_view.cpp @@ -0,0 +1,98 @@ +/* @file + * Tree view that uses the model's moveRows(), if implemented, to + * support internalMoves. The model must also have Qt::MoveAction + * among the supportedDropActions, and its item flags must allow drag + * and drop. + * + * The normal Qt Drag and Drop approach for moves involves inserting a + * new row and removing the original row. That has greater generality, + * but works poorly for views like the I/O Graphs Dialog where a newly + * inserted row would require an expensive retap. + * + * Copyright 2024 John Thacker + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "rowmove_tree_view.h" + +#include + +RowMoveTreeView::RowMoveTreeView(QWidget *parent) : TabnavTreeView(parent) +{ + // QTreeViews default to row selection. + // setSelectionMode(QAbstractItemView::ContiguousSelection); + // ContiguousSelection works, but we probably want to make sure + // that the models we use this for can handle removing multiple + // rows (and that the dialogs support doing that.) + setDropIndicatorShown(true); + // We could override dragMoveEvent to have the dropIndicator cover + // the entire row. + setDragDropMode(QAbstractItemView::InternalMove); + // Classes can change this if they also support other drag and drop + // modes. +} + +void RowMoveTreeView::dropEvent(QDropEvent *event) +{ + if (event->source() == this && (event->possibleActions() & Qt::MoveAction) && !event->isAccepted()) { + + const QModelIndexList sourceIndices = selectionModel()->selectedRows(); + + if (sourceIndices.empty()) { + TabnavTreeView::dropEvent(event); + return; + } + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QModelIndex destIndex = indexAt(event->position().toPoint()); +#else + QModelIndex destIndex = indexAt(event->pos()); +#endif + if (!destIndex.isValid() || destIndex.row() == -1) { + destIndex = model()->index(model()->rowCount() - 1, 0); + } + // dropIndicatorPosition() can be used to determine if we're slightly + // above the item, slightly below the item, on top, or elsewhere in + // the viewPort. We will just use the row number, table-like. + // Note that if we setDragDropOverwriteMode(true) then there wouldn't + // be graphical hints in between rows, but that could cause issues + // if we added non internalMove handling; overriding dragMoveEvent + // could also change it. + + const auto minmaxIndex = std::minmax_element(sourceIndices.begin(), sourceIndices.end(), + [](const QModelIndex &a, const QModelIndex &b) + { return a.row() < b.row(); } + ); + + // Only allow a contiguous selection. (This check is unnecessary + // if the selectionMode is SingleSelection or ContiguousSelection.) + // We could handle multiple ranges with multiple moveRows() calls + // and QPersistentModelIndexes in place of the QModelIndexes, but + // it gets a little confusing, especially if some indices are above + // the target row and some are below (the default behavior would be + // to move all the indices above to immediately below, and vice versa.) + // Microsoft Excel doesn't allow row moves unless the selected + // rows are contiguous, and has an alert. + // + // Note that selectionModel()->selection()->size() is *not* + // guaranteed to be the minimal merged number of possible ranges + // if the selection order was unusual, so we can't just use it. + if ((minmaxIndex.second->row() - minmaxIndex.first->row() + 1) == sourceIndices.size()) { + if (model()->moveRows(QModelIndex(), minmaxIndex.first->row(), static_cast(sourceIndices.size()), QModelIndex(), destIndex.row())) { + // Prevent QAbstractItemView from removing the sourceIndices + // There's an element in the private class (dropEventMoved) + // that QTreeWidget and QTableWidget use via the d-pointer, + // but as long as the action is no longer a MoveAction when + // it returns it won't get removed. + event->setDropAction(Qt::IgnoreAction); + event->accept(); + } + } + } + TabnavTreeView::dropEvent(event); +} diff --git a/ui/qt/widgets/rowmove_tree_view.h b/ui/qt/widgets/rowmove_tree_view.h new file mode 100644 index 00000000..ac415c41 --- /dev/null +++ b/ui/qt/widgets/rowmove_tree_view.h @@ -0,0 +1,35 @@ +/** @file + * + * Tree view that uses a model's moveRows(), if implemented, to support + * internalMoves. + * + * Copyright 2024 John Thacker + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef ROWMOVE_TREE_VIEW_H +#define ROWMOVE_TREE_VIEW_H + +#include +#include + +/** + * Like QTreeView, but instead of changing to the next row (same column) when + * pressing Tab while editing, change to the next column (same row). + */ +class RowMoveTreeView : public TabnavTreeView +{ + Q_OBJECT + +public: + RowMoveTreeView(QWidget *parent = nullptr); + +protected: + void dropEvent(QDropEvent *event) override; +}; +#endif // ROWMOVE_TREE_VIEW_H diff --git a/ui/qt/widgets/rtp_audio_graph.cpp b/ui/qt/widgets/rtp_audio_graph.cpp index 1340658b..58ff2f1f 100644 --- a/ui/qt/widgets/rtp_audio_graph.cpp +++ b/ui/qt/widgets/rtp_audio_graph.cpp @@ -9,8 +9,6 @@ #include "rtp_audio_graph.h" -#include - #include #include diff --git a/ui/qt/widgets/splash_overlay.h b/ui/qt/widgets/splash_overlay.h index b15d98c4..3f5625fc 100644 --- a/ui/qt/widgets/splash_overlay.h +++ b/ui/qt/widgets/splash_overlay.h @@ -12,8 +12,6 @@ #include -#include - #include "epan/register.h" #include diff --git a/ui/qt/widgets/syntax_line_edit.cpp b/ui/qt/widgets/syntax_line_edit.cpp index f2c32142..3e1abe96 100644 --- a/ui/qt/widgets/syntax_line_edit.cpp +++ b/ui/qt/widgets/syntax_line_edit.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include #include #include @@ -86,7 +84,7 @@ void SyntaxLineEdit::setSyntaxState(SyntaxState state) { QColor deprecated_bg = ColorUtils::fromColorT(&prefs.gui_text_deprecated); QColor deprecated_fg = ColorUtils::contrastingTextColor(deprecated_bg); - // Try to matche QLineEdit's placeholder text color (which sets the + // Try to match QLineEdit's placeholder text color (which sets the // alpha channel to 50%, which doesn't work in style sheets). // Setting the foreground color lets us avoid yet another background // color preference and should hopefully make things easier to @@ -212,7 +210,7 @@ bool SyntaxLineEdit::checkDisplayFilter(QString filter) * We're being lazy and only printing the first warning. * Would it be better to print all of them? */ - syntax_error_message_ = QString(static_cast(warn->data)); + syntax_error_message_ = QString(static_cast(warn->data)); } else if (dfp != NULL && (depr = dfilter_deprecated_tokens(dfp)) != NULL) { // You keep using that word. I do not think it means what you think it means. // Possible alternatives: ::Troubled, or ::Problematic maybe? @@ -222,7 +220,7 @@ bool SyntaxLineEdit::checkDisplayFilter(QString filter) * Would it be better to print all of them? */ QString token((const char *)g_ptr_array_index(depr, 0)); - gchar *token_str = qstring_strdup(token.section('.', 0, 0)); + char *token_str = qstring_strdup(token.section('.', 0, 0)); header_field_info *hfi = proto_registrar_get_byalias(token_str); if (hfi) syntax_error_message_ = tr("\"%1\" is deprecated in favour of \"%2\". " @@ -267,10 +265,23 @@ void SyntaxLineEdit::checkCustomColumn(QString fields) return; } - gchar **splitted_fields = g_regex_split_simple(COL_CUSTOM_PRIME_REGEX, - fields.toUtf8().constData(), G_REGEX_ANCHORED, G_REGEX_MATCH_ANCHORED); - - for (guint i = 0; i < g_strv_length(splitted_fields); i++) { +#if 0 + // XXX - Eventually, if the operator we split on is something not supported + // in the filter expression syntax (so that we can distinguish multifield + // concatenation of column strings from a logical OR), we would split and + // then check each split result as a valid display filter. + // For now, any expression that is a valid display filter should work. + // + // We also, for the custom columns, want some of the extra completion + // information from DisplayFilterEdit (like the display filter functions), + // without all of its integration into the main app, but not every user + // of FieldFilterEdit wants that, so perhaps we eventually should have + // another class. + char **splitted_fields = g_regex_split_simple(COL_CUSTOM_PRIME_REGEX, + fields.toUtf8().constData(), (GRegexCompileFlags) G_REGEX_RAW, + (GRegexMatchFlags) 0); + + for (unsigned i = 0; i < g_strv_length(splitted_fields); i++) { if (splitted_fields[i] && *splitted_fields[i]) { if (proto_check_field_name(splitted_fields[i]) != 0) { setSyntaxState(SyntaxLineEdit::Invalid); @@ -280,6 +291,7 @@ void SyntaxLineEdit::checkCustomColumn(QString fields) } } g_strfreev(splitted_fields); +#endif checkDisplayFilter(fields); } diff --git a/ui/qt/widgets/traffic_tab.cpp b/ui/qt/widgets/traffic_tab.cpp index 9913acaa..6233d60d 100644 --- a/ui/qt/widgets/traffic_tab.cpp +++ b/ui/qt/widgets/traffic_tab.cpp @@ -78,7 +78,7 @@ TrafficTab::TrafficTab(QWidget * parent) : TrafficTab::~TrafficTab() {} -void TrafficTab::setProtocolInfo(QString tableName, TrafficTypesList * trafficList, GList ** recentColumnList, ATapModelCallback createModel) +void TrafficTab::setProtocolInfo(QString tableName, TrafficTypesList * trafficList, GList ** recentList, GList ** recentColumnList, ATapModelCallback createModel) { setTabBasename(tableName); @@ -86,6 +86,7 @@ void TrafficTab::setProtocolInfo(QString tableName, TrafficTypesList * trafficLi if (createModel) _createModel = createModel; + _recentList = recentList; _recentColumnList = recentColumnList; setOpenTabs(trafficList->protocols(true)); @@ -159,7 +160,7 @@ void TrafficTab::useAbsoluteTime(bool absolute) { for(int idx = 0; idx < count(); idx++) { - ATapDataModel * atdm = modelForTabIndex(idx); + ATapDataModel * atdm = dataModelForTabIndex(idx); if (atdm) atdm->useAbsoluteTime(absolute); } @@ -169,7 +170,7 @@ void TrafficTab::useNanosecondTimestamps(bool nanoseconds) { for(int idx = 0; idx < count(); idx++) { - ATapDataModel * atdm = modelForTabIndex(idx); + ATapDataModel * atdm = dataModelForTabIndex(idx); if (atdm) atdm->useNanosecondTimestamps(nanoseconds); } @@ -179,7 +180,7 @@ void TrafficTab::disableTap() { for(int idx = 0; idx < count(); idx++) { - ATapDataModel * atdm = modelForTabIndex(idx); + ATapDataModel * atdm = dataModelForTabIndex(idx); if (atdm) atdm->disableTap(); } @@ -260,6 +261,12 @@ void TrafficTab::insertProtoTab(int protoId, bool emitSignals) if (tabId >= 0) tabBar()->setTabData(tabId, storage); + // Identify the last known opened tab + int lastOpened_protoId = -1; + GList *selected_tab = g_list_first(*_recentList); + if (selected_tab != nullptr) { + lastOpened_protoId = proto_get_id_by_short_name((const char *)selected_tab->data); + } /* We reset the correct tab idxs. That operations is costly, but it is only * called during this operation and ensures, that other operations do not @@ -270,6 +277,11 @@ void TrafficTab::insertProtoTab(int protoId, bool emitSignals) _tabs.insert(tabData.protoId(), idx); } + // Restore the last known opened tab + if(lastOpened_protoId == protoId) { + setCurrentIndex(tabId); + } + if (emitSignals) { emit tabsChanged(_tabs.keys()); emit retapRequired(); @@ -329,7 +341,7 @@ QVariant TrafficTab::currentItemData(int role) * to ensure proper handling. Especially ConversationDialog depends on this * method always returning data */ if (!idx.isValid()) { - ATapDataModel * model = modelForTabIndex(currentIndex()); + TrafficDataFilterProxy * model = modelForTabIndex(currentIndex()); idx = model->index(0, 0); } return idx.data(role); @@ -365,7 +377,7 @@ void TrafficTab::modelReset() emit tabDataChanged(tabIdx); } -ATapDataModel * TrafficTab::modelForTabIndex(int tabIdx) +TrafficDataFilterProxy * TrafficTab::modelForTabIndex(int tabIdx) { if (tabIdx == -1) tabIdx = currentIndex(); @@ -373,26 +385,40 @@ ATapDataModel * TrafficTab::modelForTabIndex(int tabIdx) return modelForWidget(widget(tabIdx)); } -ATapDataModel * TrafficTab::modelForWidget(QWidget * searchWidget) +TrafficDataFilterProxy * TrafficTab::modelForWidget(QWidget * searchWidget) { if (qobject_cast(searchWidget)) { QTreeView * tree = qobject_cast(searchWidget); if (qobject_cast(tree->model())) { - TrafficDataFilterProxy * qsfpm = qobject_cast(tree->model()); - if (qsfpm && qobject_cast(qsfpm->sourceModel())) { - return qobject_cast(qsfpm->sourceModel()); - } + return qobject_cast(tree->model()); } } return nullptr; } +ATapDataModel * TrafficTab::dataModelForTabIndex(int tabIdx) +{ + if (tabIdx == -1) + tabIdx = currentIndex(); + + return dataModelForWidget(widget(tabIdx)); +} + +ATapDataModel * TrafficTab::dataModelForWidget(QWidget * searchWidget) +{ + TrafficDataFilterProxy * qsfpm = modelForWidget(searchWidget); + if (qsfpm && qobject_cast(qsfpm->sourceModel())) { + return qobject_cast(qsfpm->sourceModel()); + } + return nullptr; +} + void TrafficTab::setFilter(QString filter) { for (int idx = 0; idx < count(); idx++ ) { - ATapDataModel * atdm = modelForTabIndex(idx); + ATapDataModel * atdm = dataModelForTabIndex(idx); if (! atdm) continue; atdm->setFilter(filter); @@ -406,7 +432,7 @@ void TrafficTab::setNameResolution(bool checked) for (int idx = 0; idx < count(); idx++ ) { - ATapDataModel * atdm = modelForTabIndex(idx); + ATapDataModel * atdm = dataModelForTabIndex(idx); if (! atdm) continue; atdm->setResolveNames(checked); @@ -422,7 +448,7 @@ void TrafficTab::setNameResolution(bool checked) bool TrafficTab::hasNameResolution(int tabIdx) { int tab = tabIdx == -1 || tabIdx >= count() ? currentIndex() : tabIdx; - ATapDataModel * dataModel = modelForTabIndex(tab); + ATapDataModel * dataModel = dataModelForTabIndex(tab); if (! dataModel) return false; @@ -443,12 +469,12 @@ bool TrafficTab::hasGeoIPData(int tabIdx) { int tab = tabIdx == -1 || tabIdx >= count() ? currentIndex() : tabIdx; - ATapDataModel * dataModel = modelForTabIndex(tab); + ATapDataModel * dataModel = dataModelForTabIndex(tab); return dataModel->hasGeoIPData(); } bool -TrafficTab::writeGeoIPMapFile(QFile * fp, bool json_only, ATapDataModel * dataModel) +TrafficTab::writeGeoIPMapFile(QFile * fp, bool json_only, TrafficDataFilterProxy * model) { QTextStream out(fp); @@ -508,14 +534,15 @@ TrafficTab::writeGeoIPMapFile(QFile * fp, bool json_only, ATapDataModel * dataMo QJsonArray features; /* Append map data. */ - for(int row = 0; row < dataModel->rowCount(QModelIndex()); row++) + for(int row = 0; row < model->rowCount(QModelIndex()); row++) { - QModelIndex index = dataModel->index(row, 0); + QModelIndex index = model->mapToSource(model->index(row, 0)); + ATapDataModel *dataModel = qobject_cast(model->sourceModel()); const mmdb_lookup_t * result = VariantPointer::asPtr(dataModel->data(index, ATapDataModel::GEODATA_LOOKUPTABLE)); if (!maxmind_db_has_coords(result)) { // result could be NULL if the caller did not trigger a lookup - // before. result->found could be FALSE if no MMDB entry exists. + // before. result->found could be false if no MMDB entry exists. continue; } @@ -545,8 +572,8 @@ TrafficTab::writeGeoIPMapFile(QFile * fp, bool json_only, ATapDataModel * dataMo if (qobject_cast(dataModel)) { EndpointDataModel * endpointModel = qobject_cast(dataModel); - property["packets"] = endpointModel->data(endpointModel->index(row, EndpointDataModel::ENDP_COLUMN_PACKETS)).toString(); - property["bytes"] = endpointModel->data(endpointModel->index(row, EndpointDataModel::ENDP_COLUMN_BYTES)).toString(); + property["packets"] = endpointModel->data(index.siblingAtColumn(EndpointDataModel::ENDP_COLUMN_PACKETS)).toString(); + property["bytes"] = endpointModel->data(index.siblingAtColumn(EndpointDataModel::ENDP_COLUMN_BYTES)).toString(); } arrEntry["properties"] = property; features.append(arrEntry); @@ -568,7 +595,7 @@ TrafficTab::writeGeoIPMapFile(QFile * fp, bool json_only, ATapDataModel * dataMo QUrl TrafficTab::createGeoIPMap(bool json_only, int tabIdx) { int tab = tabIdx == -1 || tabIdx >= count() ? currentIndex() : tabIdx; - ATapDataModel * dataModel = modelForTabIndex(tab); + ATapDataModel * dataModel = dataModelForTabIndex(tab); if (! (dataModel && dataModel->hasGeoIPData())) { QMessageBox::warning(this, tr("Map file error"), tr("No endpoints available to map")); return QUrl(); @@ -581,7 +608,7 @@ QUrl TrafficTab::createGeoIPMap(bool json_only, int tabIdx) return QUrl(); } - if (!writeGeoIPMapFile(&tf, json_only, dataModel)) { + if (!writeGeoIPMapFile(&tf, json_only, modelForTabIndex(tab))) { tf.close(); return QUrl(); } @@ -592,7 +619,7 @@ QUrl TrafficTab::createGeoIPMap(bool json_only, int tabIdx) #endif void TrafficTab::detachTab(int tabIdx, QPoint pos) { - ATapDataModel * model = modelForTabIndex(tabIdx); + ATapDataModel * model = dataModelForTabIndex(tabIdx); if (!model) return; @@ -608,7 +635,7 @@ void TrafficTab::detachTab(int tabIdx, QPoint pos) { void TrafficTab::attachTab(QWidget * content, QString name) { - ATapDataModel * model = modelForWidget(content); + ATapDataModel * model = dataModelForWidget(content); if (!model) { attachTab(content, name); return; diff --git a/ui/qt/widgets/traffic_tab.h b/ui/qt/widgets/traffic_tab.h index 71c48ae5..ff0bacc5 100644 --- a/ui/qt/widgets/traffic_tab.h +++ b/ui/qt/widgets/traffic_tab.h @@ -12,10 +12,9 @@ #include "config.h" -#include - #include #include +#include #include #include @@ -94,7 +93,7 @@ public: * * @see ATapModelCallback */ - void setProtocolInfo(QString tableName, TrafficTypesList * trafficList, GList ** recentColumnList, ATapModelCallback createModel); + void setProtocolInfo(QString tableName, TrafficTypesList * trafficList, GList ** recentList, GList ** recentColumnList, ATapModelCallback createModel); /** * @brief Set the Delegate object for the tab. It will apply for all @@ -221,20 +220,23 @@ private: QMap _tabs; ATapModelCallback _createModel; ATapCreateDelegate _createDelegate; + GList ** _recentList; GList ** _recentColumnList; bool _disableTaps; bool _nameResolution; QTreeView * createTree(int protoId); - ATapDataModel * modelForTabIndex(int tabIdx = -1); - ATapDataModel * modelForWidget(QWidget * widget); + TrafficDataFilterProxy * modelForTabIndex(int tabIdx = -1); + TrafficDataFilterProxy * modelForWidget(QWidget * widget); + ATapDataModel * dataModelForTabIndex(int tabIdx = -1); + ATapDataModel * dataModelForWidget(QWidget * widget); void insertProtoTab(int protoId, bool emitSignals = true); void removeProtoTab(int protoId, bool emitSignals = true); #ifdef HAVE_MAXMINDDB - bool writeGeoIPMapFile(QFile * fp, bool json_only, ATapDataModel * dataModel); + bool writeGeoIPMapFile(QFile * fp, bool json_only, TrafficDataFilterProxy * model); #endif private slots: diff --git a/ui/qt/widgets/traffic_tree.cpp b/ui/qt/widgets/traffic_tree.cpp index be154d7d..4325e556 100644 --- a/ui/qt/widgets/traffic_tree.cpp +++ b/ui/qt/widgets/traffic_tree.cpp @@ -204,7 +204,7 @@ void TrafficTreeHeaderView::columnTriggered(bool checked) for (int col = 0; col < tree->dataModel()->columnCount(); col++) { if (proxy->columnVisible(col)) { visible << col; - gchar *nr = qstring_strdup(QString::number(col)); + char *nr = qstring_strdup(QString::number(col)); *_recentColumnList = g_list_append(*_recentColumnList, nr); } } @@ -473,7 +473,35 @@ bool TrafficDataFilterProxy::lessThan(const QModelIndex &source_left, const QMod int addressTypeA = model->data(source_left, ATapDataModel::DATA_ADDRESS_TYPE).toInt(); int addressTypeB = model->data(source_right, ATapDataModel::DATA_ADDRESS_TYPE).toInt(); if (addressTypeA != 0 && addressTypeB != 0 && addressTypeA != addressTypeB) { - result = addressTypeA < addressTypeB; + + /* Handle subnets when they are compared to IP addresses */ + if ( (addressTypeA == AT_STRINGZ) && (addressTypeB == AT_IPv4) ) { + QString subnet = datA.toString(); + qint64 lpart = subnet.indexOf("/"); + ws_in4_addr ip4addr; + + if(ws_inet_pton4(subnet.left(lpart).toUtf8().data(), &ip4addr)) { + quint32 valA = g_ntohl(ip4addr); + quint32 valB = model->data(source_right, ATapDataModel::DATA_IPV4_INTEGER).value(); + result = valA < valB; + identical = valA == valB; + } + // else: never supposed to happen + } else if ( (addressTypeA == AT_IPv4) && (addressTypeB == AT_STRINGZ) ) { + QString subnet = datB.toString(); + qint64 lpart = subnet.indexOf("/"); + ws_in4_addr ip4addr; + if(ws_inet_pton4(subnet.left(lpart).toUtf8().data(), &ip4addr)) { + quint32 valA = model->data(source_left, ATapDataModel::DATA_IPV4_INTEGER).value(); + quint32 valB = g_ntohl(ip4addr); + result = valA < valB; + identical = valA == valB; + } + // else: never supposed to happen + } else { + result = addressTypeA < addressTypeB; + } + } else if (addressTypeA != 0 && addressTypeA == addressTypeB) { if (addressTypeA == AT_IPv4) { @@ -693,8 +721,28 @@ QMenu * TrafficTree::createActionSubMenu(FilterAction::Action cur_action, QModel foreach (FilterAction::ActionType at, FilterAction::actionTypes()) { if (isConversation && conv_item) { QMenu *subsubmenu = subMenu->addMenu(FilterAction::actionTypeName(at)); - if (hasConvId && (cur_action == FilterAction::ActionApply || cur_action == FilterAction::ActionPrepare)) { - QString filter = QString("%1.stream eq %2").arg(conv_item->ctype == CONVERSATION_TCP ? "tcp" : "udp").arg(conv_item->conv_id); + + /* For IP, ensure subnets-like conversations won't enable Stream ID filters (!CONV_ID_UNSET) */ + if (hasConvId && (conv_item->conv_id!=CONV_ID_UNSET) && (cur_action == FilterAction::ActionApply || cur_action == FilterAction::ActionPrepare)) { + QString filter; + switch (conv_item->ctype) { + case CONVERSATION_TCP: + filter = QString("%1.stream eq %2").arg("tcp").arg(conv_item->conv_id); + break; + case CONVERSATION_UDP: + filter = QString("%1.stream eq %2").arg("udp").arg(conv_item->conv_id); + break; + case CONVERSATION_IP: + filter = QString("%1.stream eq %2").arg("ip").arg(conv_item->conv_id); + break; + case CONVERSATION_IPV6: + filter = QString("%1.stream eq %2").arg("ipv6").arg(conv_item->conv_id); + break; + case CONVERSATION_ETH: + default: + filter = QString("%1.stream eq %2").arg("eth").arg(conv_item->conv_id); + break; + } FilterAction * act = new FilterAction(subsubmenu, cur_action, at, tr("Filter on stream id")); act->setProperty("filter", filter); subsubmenu->addAction(act); diff --git a/ui/qt/widgets/traffic_tree.h b/ui/qt/widgets/traffic_tree.h index 5bc87e91..00d91783 100644 --- a/ui/qt/widgets/traffic_tree.h +++ b/ui/qt/widgets/traffic_tree.h @@ -12,8 +12,6 @@ #include "config.h" -#include - #include #include diff --git a/ui/qt/widgets/traffic_types_list.cpp b/ui/qt/widgets/traffic_types_list.cpp index 30126ef9..ddbe34a3 100644 --- a/ui/qt/widgets/traffic_types_list.cpp +++ b/ui/qt/widgets/traffic_types_list.cpp @@ -9,9 +9,8 @@ #include "config.h" -#include - #include +#include #include @@ -48,12 +47,12 @@ static bool iterateProtocols(const void *key, void *value, void *userdata) QList * protocols = (QList *)userdata; register_ct_t* ct = (register_ct_t*)value; - const QString title = (const gchar*)key; + const QString title = (const char*)key; int proto_id = get_conversation_proto_id(ct); TrafficTypesRowData entry(proto_id, title); protocols->append(entry); - return FALSE; + return false; } TrafficTypesModel::TrafficTypesModel(GList ** recentList, QObject *parent) : @@ -152,6 +151,26 @@ bool TrafficTypesModel::setData(const QModelIndex &idx, const QVariant &value, i if (_allTaps.count() <= idx.row()) return false; + // When updating the tabs, save the current selection, it will be restored below + GList *selected_tab = g_list_first(*_recentList); + int rct_protoId = -1; + if (selected_tab != nullptr) { + rct_protoId = proto_get_id_by_short_name((const char *)selected_tab->data); + + // Did the user just uncheck the current selection? + if (_allTaps[idx.row()].protocol() == rct_protoId && value.toInt() == Qt::Unchecked) { + // Yes. The code below will restore it. Rather than removing it, + // resetting the model, and then adding it back, just return. + // The user might want to uncheck the current selection, in which + // case the code needs to changed to handle that. + // + // Note that not allowing the current first tab to be unselected does + // have the advantage of preventing a crash from having no tabs + // selected in the Endpoint dialog (#18250). + return false; + } + } + _allTaps[idx.row()].setChecked(value.toInt() == Qt::Checked); QList selected; @@ -161,12 +180,21 @@ bool TrafficTypesModel::setData(const QModelIndex &idx, const QVariant &value, i for (int cnt = 0; cnt < _allTaps.count(); cnt++) { if (_allTaps[cnt].checked()) { int protoId = _allTaps[cnt].protocol(); - selected.append(protoId); - char *title = g_strdup(proto_get_protocol_short_name(find_protocol_by_id(protoId))); - *_recentList = g_list_append(*_recentList, title); + if(protoId != rct_protoId) { + selected.append(protoId); + char *title = g_strdup(proto_get_protocol_short_name(find_protocol_by_id(protoId))); + *_recentList = g_list_append(*_recentList, title); + } } } + if (rct_protoId != -1) { + // restore the selection by prepending it to the recent list + char *rct_title = g_strdup(proto_get_protocol_short_name(find_protocol_by_id(rct_protoId))); + selected.prepend(rct_protoId); + *_recentList = g_list_prepend(*_recentList, rct_title); + } + emit protocolsChanged(selected); emit dataChanged(idx, idx); diff --git a/ui/qt/widgets/traffic_types_list.h b/ui/qt/widgets/traffic_types_list.h index 00798c50..2666eb78 100644 --- a/ui/qt/widgets/traffic_types_list.h +++ b/ui/qt/widgets/traffic_types_list.h @@ -12,8 +12,6 @@ #include "config.h" -#include - #include #include #include @@ -122,4 +120,4 @@ private: TrafficListSortModel * _sortModel; }; -#endif // TRAFFIC_TYPES_LIST_H \ No newline at end of file +#endif // TRAFFIC_TYPES_LIST_H diff --git a/ui/qt/widgets/wireless_timeline.cpp b/ui/qt/widgets/wireless_timeline.cpp index dcdcd4f8..87eb1079 100644 --- a/ui/qt/widgets/wireless_timeline.cpp +++ b/ui/qt/widgets/wireless_timeline.cpp @@ -75,7 +75,7 @@ static void reset_rgb(float rgb[TIMELINE_HEIGHT][3]) rgb[i][0] = rgb[i][1] = rgb[i][2] = 1.0; } -static void render_pixels(QPainter &p, gint x, gint width, float rgb[TIMELINE_HEIGHT][3], float ratio) +static void render_pixels(QPainter &p, int x, int width, float rgb[TIMELINE_HEIGHT][3], float ratio) { int previous = 0, i; for (i = 1; i <= TIMELINE_HEIGHT; i++) { @@ -92,7 +92,7 @@ static void render_pixels(QPainter &p, gint x, gint width, float rgb[TIMELINE_HE reset_rgb(rgb); } -static void render_rectangle(QPainter &p, gint x, gint width, guint height, int dfilter, float r, float g, float b, float ratio) +static void render_rectangle(QPainter &p, int x, int width, unsigned height, int dfilter, float r, float g, float b, float ratio) { p.fillRect(QRectF(x/ratio, TIMELINE_HEIGHT/2-height, width/ratio, dfilter ? height * 2 : height), pcolor(r,g,b)); } @@ -157,29 +157,25 @@ void WirelessTimeline::mouseReleaseEvent(QMouseEvent *event) return; /* this was a click */ - guint num = find_packet(localPos.x()); + unsigned num = find_packet(localPos.x()); if (num == 0) return; - frame_data *fdata = frame_data_sequence_find(cfile.provider.frames, num); - if (!fdata->passed_dfilter && fdata->prev_dis_num > 0) - num = fdata->prev_dis_num; - - cf_goto_frame(&cfile, num); + cf_goto_frame(&cfile, num, false); } void WirelessTimeline::clip_tsf() { // did we go past the start of the file? - if (((gint64) start_tsf) < ((gint64) first->start_tsf)) { + if (((int64_t) start_tsf) < ((int64_t) first->start_tsf)) { // align the start of the file at the left edge - guint64 shift = first->start_tsf - start_tsf; + uint64_t shift = first->start_tsf - start_tsf; start_tsf += shift; end_tsf += shift; } if (end_tsf > last->end_tsf) { - guint64 shift = end_tsf - last->end_tsf; + uint64_t shift = end_tsf - last->end_tsf; start_tsf -= shift; end_tsf -= shift; } @@ -194,32 +190,32 @@ void WirelessTimeline::selectedFrameChanged(QList) if (cfile.current_frame) { struct wlan_radio *wr = get_wlan_radio(cfile.current_frame->num); - guint left_margin = 0.9 * start_tsf + 0.1 * end_tsf; - guint right_margin = 0.1 * start_tsf + 0.9 * end_tsf; - guint64 half_window = (end_tsf - start_tsf)/2; + unsigned left_margin = 0.9 * start_tsf + 0.1 * end_tsf; + unsigned right_margin = 0.1 * start_tsf + 0.9 * end_tsf; + uint64_t half_window = (end_tsf - start_tsf)/2; if (wr) { // are we to the left of the left margin? if (wr->start_tsf < left_margin) { // scroll the left edge back to the left margin - guint64 offset = left_margin - wr->start_tsf; + uint64_t offset = left_margin - wr->start_tsf; if (offset < half_window) { // small movement; keep packet to margin start_tsf -= offset; end_tsf -= offset; } else { // large movement; move packet to center of window - guint64 center = (wr->start_tsf + wr->end_tsf)/2; + uint64_t center = (wr->start_tsf + wr->end_tsf)/2; start_tsf = center - half_window; end_tsf = center + half_window; } } else if (wr->end_tsf > right_margin) { - guint64 offset = wr->end_tsf - right_margin; + uint64_t offset = wr->end_tsf - right_margin; if (offset < half_window) { start_tsf += offset; end_tsf += offset; } else { - guint64 center = (wr->start_tsf + wr->end_tsf)/2; + uint64_t center = (wr->start_tsf + wr->end_tsf)/2; start_tsf = center - half_window; end_tsf = center + half_window; } @@ -234,10 +230,10 @@ void WirelessTimeline::selectedFrameChanged(QList) /* given an x position find which packet that corresponds to. * if it's inter frame space the subsequent packet is returned */ -guint +unsigned WirelessTimeline::find_packet(qreal x_position) { - guint64 x_time = start_tsf + (x_position/width() * (end_tsf - start_tsf)); + uint64_t x_time = start_tsf + (x_position/width() * (end_tsf - start_tsf)); return find_packet_tsf(x_time); } @@ -267,7 +263,7 @@ void WirelessTimeline::captureFileReadFinished() */ /* TODO: update GUI to handle captures with occasional frames missing TSF data */ /* TODO: indicate error message to the user */ - for (guint32 n = 1; n < cfile.count; n++) { + for (uint32_t n = 1; n < cfile.count; n++) { struct wlan_radio *w = get_wlan_radio(n); if (w->start_tsf == 0 || w->end_tsf == 0) { QString err = tr("Packet number %1 does not include TSF timestamp, not showing timeline.").arg(n); @@ -315,11 +311,11 @@ void WirelessTimeline::resizeEvent(QResizeEvent*) // Calculate the x position on the GUI from the timestamp -int WirelessTimeline::position(guint64 tsf, float ratio) +int WirelessTimeline::position(uint64_t tsf, float ratio) { int position = -100; - if (tsf != G_MAXUINT64) { + if (tsf != UINT64_MAX) { position = ((double) tsf - start_tsf)*width()*ratio/(end_tsf-start_tsf); } return position; @@ -378,11 +374,11 @@ tap_packet_status WirelessTimeline::tap_timeline_packet(void *tapdata, packet_in const struct wlan_radio *wlan_radio_info = (const struct wlan_radio *)data; /* Save the radio information in our own (GUI) hashtable */ - g_hash_table_insert(timeline->radio_packet_list, GUINT_TO_POINTER(pinfo->num), (gpointer)wlan_radio_info); + g_hash_table_insert(timeline->radio_packet_list, GUINT_TO_POINTER(pinfo->num), (void *)wlan_radio_info); return TAP_PACKET_DONT_REDRAW; } -struct wlan_radio* WirelessTimeline::get_wlan_radio(guint32 packet_num) +struct wlan_radio* WirelessTimeline::get_wlan_radio(uint32_t packet_num) { return (struct wlan_radio*)g_hash_table_lookup(radio_packet_list, GUINT_TO_POINTER(packet_num)); } @@ -402,7 +398,7 @@ bool WirelessTimeline::event(QEvent *event) { if (event->type() == QEvent::ToolTip) { QHelpEvent *helpEvent = static_cast(event); - guint packet = find_packet(helpEvent->pos().x()); + unsigned packet = find_packet(helpEvent->pos().x()); if (packet) { doToolTip(get_wlan_radio(packet), helpEvent->globalPos(), helpEvent->x()); } else { @@ -452,16 +448,16 @@ void WirelessTimeline::bgColorizationProgress(int first, int last) void WirelessTimeline::zoom(double x_fraction) { /* adjust the zoom around the selected packet */ - guint64 file_range = last->end_tsf - first->start_tsf; - guint64 center = start_tsf + x_fraction * (end_tsf - start_tsf); - guint64 span = pow(file_range, 1.0 - zoom_level / TIMELINE_MAX_ZOOM); + uint64_t file_range = last->end_tsf - first->start_tsf; + uint64_t center = start_tsf + x_fraction * (end_tsf - start_tsf); + uint64_t span = pow(file_range, 1.0 - zoom_level / TIMELINE_MAX_ZOOM); start_tsf = center - span * x_fraction; end_tsf = center + span * (1.0 - x_fraction); clip_tsf(); update(); } -int WirelessTimeline::find_packet_tsf(guint64 tsf) +int WirelessTimeline::find_packet_tsf(uint64_t tsf) { if (cfile.count < 1) return 0; @@ -469,11 +465,11 @@ int WirelessTimeline::find_packet_tsf(guint64 tsf) if (cfile.count < 2) return 1; - guint32 min_count = 1; - guint32 max_count = cfile.count-1; + uint32_t min_count = 1; + uint32_t max_count = cfile.count-1; - guint64 min_tsf = get_wlan_radio(min_count)->end_tsf; - guint64 max_tsf = get_wlan_radio(max_count)->end_tsf; + uint64_t min_tsf = get_wlan_radio(min_count)->end_tsf; + uint64_t max_tsf = get_wlan_radio(max_count)->end_tsf; for (;;) { if (tsf >= max_tsf) @@ -482,11 +478,11 @@ int WirelessTimeline::find_packet_tsf(guint64 tsf) if (tsf < min_tsf) return min_count; - guint32 middle = (min_count + max_count)/2; + uint32_t middle = (min_count + max_count)/2; if (middle == min_count) return middle+1; - guint64 middle_tsf = get_wlan_radio(middle)->end_tsf; + uint64_t middle_tsf = get_wlan_radio(middle)->end_tsf; if (tsf >= middle_tsf) { min_count = middle; @@ -550,9 +546,9 @@ WirelessTimeline::paintEvent(QPaintEvent *qpe) if (ri == NULL) continue; - gint8 rssi = ri->aggregate ? ri->aggregate->rssi : ri->rssi; - guint height = (rssi+100)/2; - gint end_nav; + int8_t rssi = ri->aggregate ? ri->aggregate->rssi : ri->rssi; + unsigned height = (rssi+100)/2; + int end_nav; /* leave a margin above the packets so the selected packet can be seen */ if (height > TIMELINE_HEIGHT/2-6) @@ -567,7 +563,7 @@ WirelessTimeline::paintEvent(QPaintEvent *qpe) if (ri->start_tsf == 0 || ri->end_tsf == 0) continue; - x = ((gint64) (ri->start_tsf - start_tsf))*zoom; + x = ((int64_t) (ri->start_tsf - start_tsf))*zoom; /* is there a previous anti-aliased pixel to output */ if (last_x >= 0 && ((int) x) != last_x) { /* write it out now */ @@ -606,7 +602,7 @@ WirelessTimeline::paintEvent(QPaintEvent *qpe) /* record NAV field at higher magnifications */ end_nav = x + width + ri->nav*zoom; if (zoom >= 0.01 && ri->nav && end_nav > 0) { - gint y = 2*(packet % (TIMELINE_HEIGHT/2)); + int y = 2*(packet % (TIMELINE_HEIGHT/2)); qs.addLine(QLineF((x+width)/ratio, y, end_nav/ratio, y), QPen(pcolor(red,green,blue))); } diff --git a/ui/qt/widgets/wireless_timeline.h b/ui/qt/widgets/wireless_timeline.h index de43d123..cf67ff4e 100644 --- a/ui/qt/widgets/wireless_timeline.h +++ b/ui/qt/widgets/wireless_timeline.h @@ -21,8 +21,6 @@ #include -#include - #include "file.h" #include "ui/ws_ui_util.h" @@ -75,21 +73,21 @@ protected: static void tap_timeline_reset(void* tapdata); static tap_packet_status tap_timeline_packet(void *tapdata, packet_info* pinfo, epan_dissect_t* edt, const void *data, tap_flags_t flags); - struct wlan_radio* get_wlan_radio(guint32 packet_num); + struct wlan_radio* get_wlan_radio(uint32_t packet_num); void clip_tsf(); - int position(guint64 tsf, float ratio); - int find_packet_tsf(guint64 tsf); + int position(uint64_t tsf, float ratio); + int find_packet_tsf(uint64_t tsf); void doToolTip(struct wlan_radio *wr, QPoint pos, int x); void zoom(double x_fraction); double zoom_level; qreal start_x, last_x; PacketList *packet_list; - guint find_packet(qreal x); + unsigned find_packet(qreal x); float rgb[TIMELINE_HEIGHT][3]; - guint64 start_tsf; - guint64 end_tsf; + uint64_t start_tsf; + uint64_t end_tsf; int first_packet; /* first packet displayed */ struct wlan_radio *first, *last; capture_file *capfile; diff --git a/ui/qt/widgets/wireshark_file_dialog.cpp b/ui/qt/widgets/wireshark_file_dialog.cpp index acf9c7db..3c5b8d3e 100644 --- a/ui/qt/widgets/wireshark_file_dialog.cpp +++ b/ui/qt/widgets/wireshark_file_dialog.cpp @@ -43,6 +43,15 @@ WiresharkFileDialog::WiresharkFileDialog(QWidget *parent, const QString &caption #endif } +QString WiresharkFileDialog::selectedNativePath() const +{ + if (selectedFiles().isEmpty()) { + // The API implies this can't happen + return QString(); + } + return QDir::toNativeSeparators(selectedFiles().at(0)); +} + QString WiresharkFileDialog::getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, Options options) { #ifdef Q_OS_WIN @@ -52,7 +61,7 @@ QString WiresharkFileDialog::getExistingDirectory(QWidget *parent, const QString #ifdef Q_OS_WIN revert_thread_per_monitor_v2_awareness(da_ctx); #endif - return ed; + return QDir::toNativeSeparators(ed); } QString WiresharkFileDialog::getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options) @@ -64,7 +73,7 @@ QString WiresharkFileDialog::getOpenFileName(QWidget *parent, const QString &cap #ifdef Q_OS_WIN revert_thread_per_monitor_v2_awareness(da_ctx); #endif - return ofn; + return QDir::toNativeSeparators(ofn); } QString WiresharkFileDialog::getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options) @@ -76,5 +85,5 @@ QString WiresharkFileDialog::getSaveFileName(QWidget *parent, const QString &cap #ifdef Q_OS_WIN revert_thread_per_monitor_v2_awareness(da_ctx); #endif - return sfn; + return QDir::toNativeSeparators(sfn); } diff --git a/ui/qt/widgets/wireshark_file_dialog.h b/ui/qt/widgets/wireshark_file_dialog.h index 43ac67a6..7d452b3d 100644 --- a/ui/qt/widgets/wireshark_file_dialog.h +++ b/ui/qt/widgets/wireshark_file_dialog.h @@ -15,6 +15,11 @@ /** * @brief The WiresharkFileDialog class * + * Qt uses '/' as a universal path separator and converts to native path + * separators, i.e., '\' on Windows, only immediately before displaying a + * path to a user. This class can return the path with native path + * separators. + * * Qt <= 5.9 supports setting old (Windows 8.1) per-monitor DPI awareness * via Qt:AA_EnableHighDpiScaling. We do this in main.cpp. In order for * native dialogs to be rendered correctly we need to set per-monitor @@ -23,13 +28,15 @@ * we need to revert our thread context when we're done. * The class functions below are simple wrappers around their QFileDialog * equivalents that set PMv2 awareness before showing native dialogs on - * Windows and resets it afterward. + * Windows and resets it afterward. They also return the result with native + * directory separators on Windows. */ class WiresharkFileDialog : public QFileDialog { public: WiresharkFileDialog(QWidget *parent = nullptr, const QString &caption = QString(), const QString &directory = QString(), const QString &filter = QString()); + QString selectedNativePath() const; static QString getExistingDirectory(QWidget *parent = Q_NULLPTR, const QString &caption = QString(), const QString &dir = QString(), Options options = ShowDirsOnly); static QString getOpenFileName(QWidget *parent = Q_NULLPTR, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = Q_NULLPTR, Options options = Options()); static QString getSaveFileName(QWidget *parent = Q_NULLPTR, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = Q_NULLPTR, Options options = Options()); diff --git a/ui/qt/wireless_frame.cpp b/ui/qt/wireless_frame.cpp index 2247b113..4b5e14c2 100644 --- a/ui/qt/wireless_frame.cpp +++ b/ui/qt/wireless_frame.cpp @@ -12,8 +12,6 @@ #include "config.h" -#include - #include #include @@ -23,6 +21,7 @@ #include #include #include "main_application.h" +#include "utils/qt_ui_utils.h" #include #include @@ -129,7 +128,7 @@ void WirelessFrame::updateInterfaceList() ws80211_free_interfaces(interfaces_); interfaces_ = ws80211_find_interfaces(); const QString old_iface = ui->interfaceComboBox->currentText(); - guint iface_count = 0; + unsigned iface_count = 0; bool list_changed = false; // Don't interfere with user activity. @@ -148,7 +147,7 @@ void WirelessFrame::updateInterfaceList() if ((int) iface_count != ui->interfaceComboBox->count()) { list_changed = true; } else { - for (guint i = 0; i < iface_count; i++) { + for (unsigned i = 0; i < iface_count; i++) { struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i); if (ui->interfaceComboBox->itemText(i).compare(iface->ifname) != 0) { list_changed = true; @@ -159,7 +158,7 @@ void WirelessFrame::updateInterfaceList() if (list_changed) { ui->interfaceComboBox->clear(); - for (guint i = 0; i < iface_count; i++) { + for (unsigned i = 0; i < iface_count; i++) { struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i); ui->interfaceComboBox->addItem(iface->ifname); if (old_iface.compare(iface->ifname) == 0) { @@ -226,7 +225,7 @@ void WirelessFrame::getInterfaceInfo() return; } - for (guint i = 0; i < interfaces_->len; i++) { + for (unsigned i = 0; i < interfaces_->len; i++) { struct ws80211_interface *iface = g_array_index(interfaces_, struct ws80211_interface *, i); if (cur_iface.compare(iface->ifname) == 0) { struct ws80211_iface_info iface_info; @@ -234,8 +233,8 @@ void WirelessFrame::getInterfaceInfo() ws80211_get_iface_info(iface->ifname, &iface_info); - for (guint j = 0; j < iface->frequencies->len; j++) { - guint32 frequency = g_array_index(iface->frequencies, guint32, j); + for (unsigned j = 0; j < iface->frequencies->len; j++) { + uint32_t frequency = g_array_index(iface->frequencies, uint32_t, j); double ghz = frequency / 1000.0; QString chan_str = QString("%1 " UTF8_MIDDLE_DOT " %2%3") .arg(ieee80211_mhz_to_chan(frequency)) @@ -304,15 +303,15 @@ void WirelessFrame::setInterfaceInfo() int chan_type = ui->channelTypeComboBox->itemData(cur_type_idx).toInt(); int bandwidth = getBandwidthFromChanType(chan_type); int center_freq = getCenterFrequency(frequency, bandwidth); - const gchar *chan_type_s = ws80211_chan_type_to_str(chan_type); - gchar *center_freq_s = NULL; - gchar *data, *primary_msg, *secondary_msg; + const char *chan_type_s = ws80211_chan_type_to_str(chan_type); + char *center_freq_s = NULL; + char *data, *primary_msg, *secondary_msg; int ret; if (frequency < 0 || chan_type < 0) return; if (center_freq != -1) { - center_freq_s = g_strdup(QString::number(center_freq).toUtf8().constData()); + center_freq_s = qstring_strdup(QString::number(center_freq)); } ret = sync_interface_set_80211_chan(cur_iface.toUtf8().constData(), diff --git a/ui/qt/wireshark_application.cpp b/ui/qt/wireshark_application.cpp index 7b37dabc..40f9443c 100644 --- a/ui/qt/wireshark_application.cpp +++ b/ui/qt/wireshark_application.cpp @@ -9,7 +9,7 @@ #include "wireshark_application.h" -WiresharkApplication *wsApp = NULL; +WiresharkApplication *wsApp; WiresharkApplication::WiresharkApplication(int &argc, char **argv) : MainApplication(argc, argv) diff --git a/ui/qt/wireshark_de.ts b/ui/qt/wireshark_de.ts index d100b7fa..35255910 100644 --- a/ui/qt/wireshark_de.ts +++ b/ui/qt/wireshark_de.ts @@ -44,8 +44,8 @@ Ordner - Filter by path - Nach Pfad filtern + Search Folders + Ordner suchen Plugins @@ -79,6 +79,14 @@ License Lizenzen + + About Logray + Über Logray + + + Logray + Logray + The directory does not exist Das Verzeichnis existiert nicht @@ -754,6 +762,28 @@ …als EBCDIC + + CaptureCommentDialog + + Edit Capture Comments + Aufzeichnungskommentare bearbeiten + + + Add Comment + Kommentar hinzufügen + + + Section %1 + Bereich %1 + + + + CaptureCommentTabWidget + + Comment %1 + Kommentar %1 + + CaptureFile @@ -862,10 +892,6 @@ Read filter: Lesefilter: - - Compress with g&zip - Mit g&zip komprimieren - Open Capture File Wireshark: Open Capture File @@ -948,8 +974,8 @@ Details - Capture file comments - Mitschnittdateikommentare + Edit Comments + Kommentare bearbeiten Refresh @@ -959,10 +985,6 @@ Copy To Clipboard In die Zwischenablage kopieren - - Save Comments - Kommentar speichern - Capture File Properties Mitschnittdateieigenschaften @@ -1011,10 +1033,18 @@ First packet Erstes Paket + + First event + Erstes Ereignis + Last packet Letztes Paket + + Last event + Letztes Ereignis + Elapsed Zeitspanne @@ -1051,6 +1081,10 @@ Dropped packets Verworfene Pakete + + Dropped events + Verworfene Ereignisse + Capture filter Mitschnittfilter @@ -1063,6 +1097,10 @@ Packet size limit (snaplen) Paketgrößenlimit (snaplen) + + Event size limit (snaplen) + Max. Ereignisgröße (snaplen) + none keine @@ -1071,6 +1109,26 @@ %1 bytes %1 Byte + + Comments + Kommentare + + + Comment %1: + Kommentar %1: + + + Decryption Secrets + Entschlüsselungs-Secrets + + + Type + Typ + + + Size + Größe + Statistics Statistik @@ -1095,6 +1153,10 @@ Packets Pakete + + Events + Ereignisse + Time span, s Zeitspanne, s @@ -1105,7 +1167,11 @@ Average packet size, B - Durschnittliche Paketgröße, B + Durchschnittliche Paketgröße, B + + + Average event size, B + Durchschnittliche Ereignisgröße, B Bytes @@ -1113,20 +1179,20 @@ Average bytes/s - Durschnittliche Byte/s + Durchschnittliche Byte/s Average bits/s - Durschnittliche Bit/s - - - Section Comment - Kommentar Bereich + Durchschnittliche Bit/s Packet Comments Paketkommentar + + Event Comments + Ereigniskommentare + <p>Frame %1: <p>Frame %1: @@ -1137,6 +1203,14 @@ Erstellt von Wireshark %1 + + + + Created by Logray %1 + + + Erstellt von Logray %1 + @@ -1365,6 +1439,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Zur nächsten Datei wechseln wenn die Urzeit ein gerades Vielfaches des angegebenen Intervalls ist. Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angeben. + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>Normalerweise erfasst eine WLAN-Netzwerkkarte nur Verkehr, der zu oder von ihrer Netzwerkadresse gesendet wird. Zudem wird nur <em>user data</em>-Verkehr mit &quot;fake&quot; Ethernet-Headern aufgezeichnet. Wenn Sie den gesamten Datenverkehr, den die Netzwerkkarte &quot;sehen&quot; kann, aufzeichnen möchten, an 802.11 Management-/Kontrollpaketen oder Radio-Layer-Infos interessiert sind, wählen Sie diese Option an. Monitor-Mode-Verfügbarkeit hängt von der Netzwerkkarte und den Treibern ab. Schauen Sie für mehr Informationen zum Mitschneiden in WLAN-Netzwerken ins Wiki.</p></body></html> + + + Enable monitor mode on all 802.11 interfaces + Monitor Modus für alle 802.11 Schnittstellen aktivieren + compression Komprimierung @@ -1377,6 +1459,30 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe gzip gzip + + File infix pattern + Datei Infix Muster + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + <html><head/><body><p>Beim Erzeugen mehrerer Dateien werden Datum und Uhrzeit sowie die Datei-Indexnummer zwischen dem Dateinamen und Suffix eingefügt. Wählen Sie deren Sortierungsart.</p></body></html> + + + YYYYmmDDHHMMSS_NNNNN + YYYYmmDDHHMMSS_NNNNN + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + <html><head/><body><p>Datum und Uhrzeit vor der Datei-Indexnummer. Dies führt zur Sortierung nach Erstellungszeit und hält Dateien vom gleichen Stapel in der Sortierung eng zusammen.</p></body></html> + + + NNNNN_YYYYmmDDHHMMSS + NNNNN_YYYYmmDDHHMMSS + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + <html><head/><body><p>Datei-Indexnummer vor Datum und Uhrzeit. Dies ist die alte Wireshark Sortierung.</p></body></html> + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> <html><head/><body><p>Nachdem die Aufzeichnung in die nächste Datei gewechselt hat und die angegebene Anzahl an Dateien erreicht wurde, wird die älteste Datei entfernt.</p></body></html> @@ -1467,7 +1573,7 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Stop capturing after the specified number of files have been created. - + Mitschneiden beenden, nachdem die angegebene Anzahl an Dateien erstellt wurde. <html><head/><body><p>Stop capturing after the specified amount of data has been captured.</p></body></html> @@ -1530,8 +1636,8 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Fehler - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. - Dateisatz: Angeforderte Dateigröße zu groß. Die Dateigröße kann nicht größer als 2 GiB sein. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. + Dateisatz: Angeforderte Dateigröße zu groß. Die Dateigröße kann nicht größer als 2 TB sein. Multiple files: No capture file name given. You must specify a filename if you want to use multiple files. @@ -1560,6 +1666,14 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Capture packets in promiscuous mode Pakete im promiskuitiven Modus mitschneiden + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>Normalerweise erfasst eine WLAN-Netzwerkkarte nur Verkehr, der zu oder von ihrer Netzwerkadresse gesendet wird. Zudem wird nur <em>user data</em> -Verkehr mit &quot;fake&quot; Ethernet-Headern aufgezeichnet. Wenn Sie den gesamten Datenverkehr, den die Netzwerkkarte &quot;sehen&quot; kann, aufzeichnen möchten, an 802.11 Management-/Kontrollpaketen oder Radio-Layer-Infos interessiert sind, wählen Sie diese Option an. Monitor-Mode-Verfügbarkeit hängt von der Netzwerkkarte und den Treibern ab. Schauen Sie für mehr Informationen zum Mitschneiden in WLAN-Netzwerken ins Wiki.</p></body></html> + + + Capture packets in monitor mode on 802.11 devices + Pakete im Monitor Modus der 802.11 Schnittstelle mitschneiden + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>Pakete im pcapng Dateiformat aufzeichnen.</p></body></html> @@ -1787,6 +1901,14 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Resolved Aufgelöst + + Width + Breite + + + Alignment + Ausrichtung + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> <html>In Feldern menschenleserliche Zeichenketten anstatt Rohwerte anzeigen. Nur auf benutzerdefinierte Spalten mit Zeichenketten anwendbar.</html> @@ -1834,6 +1956,25 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Filter text in die Zwischenablage kopieren. + + CompressionGroupBox + + Compression options + Komprimierungsoptionen + + + &Uncompressed + &Unkomprimiert + + + Compress with g&zip + Mit g&zip komprimieren + + + Compress with &LZ4 + Mit &LZ4 komprimieren + + ConversationDataModel @@ -1900,6 +2041,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Bits/s B Bits/s B + + Flows + Flows + Total Packets Pakete gesamt @@ -2014,14 +2159,6 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Copy packet bytes as a hex dump. Paketbytes als Hex Dump kopieren - - …as Printable Text - …als druckbarer Text - - - Copy only the printable text in the packet. - Nur den druckbaren Text im Paket kopieren. - …as MIME Data ...als MIME Daten @@ -2034,10 +2171,42 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Copy packet bytes as printable ASCII characters and escape sequences. Paket-Bytes als druckbare ASCII-Zeichen und Escape-Sequenzen kopieren. + + …as Go literal + als Go Literal + + + Copy packet bytes as Go literal. + Paketbytes als Go Literal kopieren + + + …as C Array + …als C Array + + + Copy packet bytes as C Array. + Paketbytes als C Array kopieren. + …as a Hex Stream ...als Hex Stream + + …as UTF-8 Text + …als UTF-8 Text + + + Copy packet bytes as text, treating as UTF-8. + Paketbytes als Text kopieren (als UTF-8 behandeln). + + + …as ASCII Text + …als ASCII Text + + + Copy packet bytes as text, treating as ASCII. + Paketbytes als Text kopieren (als ASCII behandeln). + Copy packet bytes as a stream of hex. Paketbytes als Hexstream kopieren. @@ -2834,6 +3003,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Display filter: Anzeigefilter: + + Export PDUs + PDUs exportieren + ExtArgSelector @@ -2872,10 +3045,6 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Start Start - - Save - Speichern - Default Standard @@ -3017,6 +3186,14 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Display Filters Anzeigefilter + + Display Filter Macros + Anzeigefilter Makros + + + New macro + Neues Makro + Open Öffnen @@ -3100,10 +3277,18 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe FilterListModel + + Macro Name + Makroname + Filter Name Filtername + + Macro Expression + Makroausdruck + Filter Expression Filterausdruck @@ -3189,22 +3374,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe FolderListModel - - "File" dialogs - "Datei" Dialoge - - - capture files - Mitschnittdateien - Temp Temp - - untitled capture files - Unbenannte Mitschnittdateien - Personal configuration Benutzerspezifische Konfiguration @@ -3213,14 +3386,6 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Global configuration Globale Konfiguration - - dfilters, preferences, ethers, … - dfilters, preferences, ethers, … - - - dfilters, preferences, manuf, … - dfilters, preferences, manuf, … - System System @@ -3233,18 +3398,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Program Programm - - program files - program files - Personal Plugins Benutzerspezifische Plugins - - binary plugins - binary plugins - Global Plugins Globale Plugins @@ -3261,12 +3418,36 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Lua scripts Lua Skripte + + "File" dialog location + "Datei" Dialog Pfad + + + Capture files + Mitschnittdateien + + + Untitled capture files + Unbenannte Mitschnittdateien + + + Preferences, profiles, manuf, … + Einstellungen, Profile, manuf, … + + + Program files + Programmdateien + + + Binary plugins + Binary Plug-Ins + Personal Extcap path Benutzerspezifischer Extcap Pfad - external capture (extcap) plugins + External capture (extcap) plugins Externe Aufzeichnungs-Plug-Ins (extcap) @@ -3303,7 +3484,7 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Location - Lokation + Pfad Typical Files @@ -3403,6 +3584,24 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe %Ln Runden. + + Event %1. + Ereignis %1. + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + %Ln <span style="color: %1; background-color:%2">Lesevorgang</span>, + %Ln <span style="color: %1; background-color:%2">Lesevorgänge</span>, + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + %Ln <span style="color: %1; background-color:%2">Schreibvorgang</span>, + %Ln <span style="color: %1; background-color:%2">Schreibvorgänge</span>, + + Click to select. Zur Auswahl anklicken. @@ -3435,6 +3634,18 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe %1 stream not found on the selected packet. %1 Stream in ausgewähltem Paket nicht gefunden. + + Read activity(%6) + Leseaktivität(%6) + + + Write activity(%6) + Schreibaktivität(%6) + + + Entire I/O activity (%1) + Gesamte E/A Aktivität (%1) + Entire conversation (%1) Gesamte Verbindung (%1) @@ -3451,10 +3662,6 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Save Stream Content As… Stream Inhalt speichern als… - - [Stream output truncated] - [Streamausgabe gekürzt] - %Ln total stream(s). @@ -3482,9 +3689,20 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Hinweis. - Show data as - Show and save data as - Daten anzeigen als + Show as + Anzeigen als + + + No delta times + Keine Delta-Zeiten + + + Turn delta times + Delta-Zeiten umdrehen + + + All delta times + Alle Delta-Zeiten Stream @@ -3498,11 +3716,22 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Find: Suchen: + + Case sensitive + Groß- / Kleinschreibung beachten + Find &Next &Nächstes suchen + + FollowStreamText + + [Stream output truncated] + [Streamausgabe gekürzt] + + FontColorPreferencesFrame @@ -3838,30 +4067,29 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe </tbody></table> </body></html> - - Remove this graph. - Remove this dissection behavior. - Diesen Graph entfernen. - Add a new graph. Einen neuen Graph hinzufügen. - - Duplicate this graph. - Diesen Graph duplizieren. - Clear all graphs. Alle Graphen löschen. - Move this graph upwards. - Graphen nach oben verschieben. + Remove the selected graph(s). + Ausgewählte(n) Graphen entfernen. + + + Duplicate the selected graph(s). + Ausgewählte(n) Graphen duplizieren. + + + Move the selected graph(s) upwards. + Ausgewählte(n) Graphen nach oben verschieben. - Move this graph downwards. - Graphen nach unten verschieben. + Move the selected graph(s) downwards. + Ausgewählte(n) Graphen nach unten verschieben. Mouse @@ -3903,10 +4131,6 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Enable legend Legende einschalten - - Reset - Zurücksetzen - Reset Graph Graph zurücksetzen @@ -4120,6 +4344,42 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Copy graphs from another profile. Graph von einem anderen Profil kopieren. + + 1 μs + 1 μs + + + 2 μs + 2 μs + + + 5 μs + 5 μs + + + 10 μs + 10 μs + + + 20 μs + 20 μs + + + 50 μs + 50 μs + + + 100 μs + 100 μs + + + 200 μs + 200 μs + + + 500 μs + 500 μs + 1 ms 1 ms @@ -4164,6 +4424,14 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe 5 sec 5 Sek. + + 2 min + 2 min + + + 5 min + 5 min + Wireshark I/O Graphs: %1 Wireshark I/O Graphen: %1 @@ -4176,6 +4444,14 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Filtered events Gefilterte Ereignisse + + All packets + Alle Pakete + + + All events + Alle Ereignisse + All Packets Alle Pakete @@ -4189,8 +4465,8 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Alle Ereignisse - Access Denied - Zugriff verboten + All Execs + Alle Ausführungen Hover over the graph for details. @@ -4236,6 +4512,34 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Click to select a portion of the graph. Klicken um einen Teil des Graphen auszuwählen. + + %1 Intervals + %1 Intervalle + + + Move to top left + Nach oben links verschieben + + + Move to top center + Nach oben mittig verschieben + + + Move to top right + Nach oben rechts verschieben + + + Move to bottom left + Nach unten links verschieben + + + Move to bottom center + Nach unten mittig verschieben + + + Move to bottom right + Nach unten rechts verschieben + Portable Document Format (*.pdf) Portable Document Format (*.pdf) @@ -4988,6 +5292,13 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Änderungen anwenden + + InterfaceTreeDelegate + + default + Standard + + InterfaceTreeModel @@ -5965,8 +6276,8 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe LteMacStatisticsDialog - LTE Mac Statistics - LTE Mac Statistiken + LTE/NR Mac Statistics + LTE/NR Mac Statistiken Include SR frames in filter @@ -6270,12 +6581,12 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Sequenznummer - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) - LTE RLC Graph (UE=%1 Kanal=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) + %1 RLC Graph (UE=%2 Kanal=%3%4 %5 - %6) - LTE RLC Graph - no channel selected - LTE RLC Graph - Kein Kanal ausgewählt + 3GPP RLC Graph - no channel selected + 3GPP RLC Graph - kein Kanal ausgewählt Save As… @@ -6329,8 +6640,8 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe LteRlcStatisticsDialog - LTE RLC Statistics - LTE RLC Statistiken + 3GPP RLC Statistics + 3GPP RLC Statistiken Include SR frames in filter @@ -6415,6 +6726,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Profile: %1 Profil: %1 + + %1 Displayed: %2 (%3%) + %1 Angezeigt: %2 (%3%) + Manage Profiles… Profile verwalten… @@ -6477,6 +6792,13 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe %Ln Bytes + + %Ln bit(s) + + %Ln Bit + %Ln Bits + + Byte %1 Byte %1 @@ -6490,9 +6812,12 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Ausgewähltes Paket: %1 %2 - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 - Pakete: %1 %4 Angezeigt: %2 (%3%) + Selected Event: %1 %2 + Ausgewählte Ereignisse: %1 %2 + + + Events: %1 + Ereignisse: %1 %1 Selected: %2 (%3%) @@ -6523,6 +6848,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe No Packets Keine Pakete + + No Events + Keine Ereignisse + From Zip File... Aus ZIP Datei... @@ -6555,6 +6884,13 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe + + MainWindow + + Display filter as %1 + Filter anzeigen als %1 + + MainWindowPreferencesFrame @@ -6586,6 +6922,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe The most recently used folder Zuletzt genutztem Ordner + + The current working directory + Das aktuelle Arbeitsverzeichnis + Show up to Anzeigen von maximal @@ -7016,6 +7356,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Show Field Values Zeige Feldwerte + + Refresh + Aktualisieren + Save Diagram As… Diagramm speichern als… @@ -7063,6 +7407,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Show packet bytes Paketbytes anzeigen + + Layout: + Ansicht: + Packet %1 Paket %1 @@ -7086,6 +7434,13 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe %Ln Bytes + + %Ln bit(s) + + %Ln Bit + %Ln Bits + + PacketFormatGroupBox @@ -7544,10 +7899,22 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Copy this profile. Dieses Profil kopieren. + + The number of packets or events to check for automatic profile switching. + Die für den automatischen Profilwechsel geprüfte Anzahl von Paketen oder Ereignissen. + + + Auto switch packet limit + Autoswitch Paketlimit + Configuration Profiles Profile konfigurieren + + Auto switch event limit + Autoswitch Ereignislimit + Import noun @@ -7730,6 +8097,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe deleted gelöscht + + Auto Switch Filter + Autoswitch Filter + copy noun @@ -8091,7 +8462,7 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Unacked (Outstanding) Bytes (B) - + Nicht-ACK-bestätigte (ausstehende) Bytes (B) [no capture file] @@ -8253,6 +8624,14 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Marker missing? Marker fehlt? + + LTE + LTE + + + NR + NR + C-RNTI C-RNTI @@ -8273,6 +8652,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe UEId UEId + + RAT + RAT + UL Frames UL Frames @@ -8497,9 +8880,69 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Browse… Öffnen… + + PACKETS + PAKETE + + + EVENTS + EREIGNISSE + + + BYTES + BYTES + + + BITS + BITS + + + COUNT FRAMES + ANZAHL FRAMES + + + COUNT FIELDS + ANZAHL FELDER + + + SUM + SUMME + + + MAX + MAX + + + MIN + MIN + + + AVERAGE + DURCHSCHNITT + + + THROUGHPUT + DURCHSATZ + + + LOAD + LAST + + + Left + Links + + + Center + Zentriert + + + Right + Rechts + - QObject::QObject + QObject::QObject::QObject CCCH CCCH @@ -8599,6 +9042,13 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Millisekunden + + ResizeHeaderView + + Resize all %1 to contents + Alle %1 an Inhalt anpassen + + ResolvedAddressesDialog @@ -8714,6 +9164,14 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Resolved Addresses Aufgelöste Adressen + + Copy + Kopieren + + + Save as… + Speichern als... + # Resolved addresses found in %1 # Resolved addresses found in %1 @@ -8727,6 +9185,61 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe # + + ResolvedAddressesView + + as Plain Text + als reiner Text + + + Copy selected rows + Ausgewählte Reihen kopieren + + + Copy table + Tabelle kopieren + + + as CSV + als CSV + + + as JSON + als JSON + + + Save selected rows as… + Ausgewählte Reihen speichern... + + + Save table as… + Tabelle speichern als... + + + Save Resolved Addresses As… + Aufgelöste Adressen speichern als... + + + Plain text (*.txt) + Reiner Text (*.txt) + + + CSV Document (*.csv) + CSV Dokument (*.csv) + + + JSON Document (*.json) + JSON Dokument (*.json) + + + Warning + Warnung + + + Unable to save %1: %2 + Speichern von %1 nicht möglich: %2 + + ResponseTimeDelayDialog @@ -10401,6 +10914,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Packet bytes Paket Bytes + + <b>Options:</b> + <b>Optionen:</b> + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>Zeichenketten suchen, die schmale (UTF-8 oder ASCII) or breite (UTF-16) Zeichen enthalten.</p></body></html> @@ -10421,6 +10938,18 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Case sensitive Groß- / Kleinschreibung beachten + + Backwards + Rückwärts + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + <html><head/><body><p>Nach weiterem Vorkommen im aktuellen Paket suchen bevor mit dem nächsten Paket fortgefahren wird.</p></body></html> + + + Multiple occurrences + Mehreres Vorkommen + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10458,6 +10987,22 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Invalid filter. Ungültiger Filter. + + Event List + Ereignisliste + + + Event Details + Ereignisdetails + + + Event Bytes + Ereignis-Bytes + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + <html><head/><body><p>Durchsuchen der Informationsspalte der Ereignisliste (Übersichtsfenster), der dekodierten Ereignisanzeigebeschriftungen (Baumansicht) oder der ASCII-konvertierten Ereignisdaten (Hex-Ansicht).</p></body></html> + That filter doesn't test anything. Dieser Filter hat keine Auswirkung. @@ -10901,6 +11446,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Find: Suchen: + + Case sensitive + Groß- / Kleinschreibung beachten + Find &Next &Nächstes suchen @@ -10996,15 +11545,23 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Save as… Speichern als… + + Decoded as %1. + Dekodiert als %1. + Save Selected Packet Bytes As… Ausgewählte Paketbytes speichern als… + + compressed %1 + %1 komprimiert + - Displaying %Ln byte(s). + Using %Ln byte(s). - Zeige %Ln Byte an. - Zeige %Ln Bytes an. + Verwende %Ln Byte. + Verwende %Ln Bytes. @@ -11104,6 +11661,10 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Display filter: Anzeigefilter: + + Strip Headers + Kopfdaten entfernen + SupportedProtocolsDialog @@ -12077,22 +12638,20 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Einen neuen Eintrag erstellen. - Remove this entry. - Remove this profile. - Diesen Eintrag entfernen. + Remove the selected entry(ies). + Ausgewählte(n) Eintrag(e) entfernen. - Copy this entry. - Copy this profile. - Diesen Eintrag kopieren. + Copy the selected entry(ies). + Ausgewählte(n) Eintrag(e) kopieren. - Move entry up. - Eintrag nach oben verschieben. + Move the selected entry(ies) up. + Ausgewählte(n) Eintrag(e) nach oben verschieben. - Move entry down. - Eintrag nach unten verschieben. + Move the selected entry(ies) down. + Ausgewählte(n) Eintrag(e) nach unten verschieben. Clear all entries. @@ -12118,20 +12677,20 @@ Um zum Beispiel eine neue Datei zu jeder vollen Stunde zu haben, 1 Stunde angebe Einen neuen Eintrag erstellen. - Remove this entry. - Diesen Eintrag entfernen. + Remove the selected entry(ies). + Ausgewählte(n) Eintrag(e) entfernen. - Copy this entry. - Diesen Eintrag kopieren. + Copy the selected entry(ies). + Ausgewählte(n) Eintrag(e) kopieren. - Move entry up. - Eintrag nach oben verschieben. + Move the selected entry(ies) up. + Ausgewählte(n) Eintrag(e) nach oben verschieben. - Move entry down. - Eintrag nach unten verschieben. + Move the selected entry(ies) down. + Ausgewählte(n) Eintrag(e) nach unten verschieben. Clear all entries. @@ -12501,10 +13060,18 @@ a:hover { You are sniffing the glue that holds the Internet together using Wireshark Mit Wireshark den Kleber schnüffeln, der das Internet zusammenhält. + + You are sniffing the glue that holds your system together using Logray + Mit Logray den Kleber schnüffeln, der Ihr System zusammenhält. + You are running Wireshark Sie nutzen Wireshark + + You are running Logray + Sie nutzen Logray + You receive automatic updates. Updates werden automatisch heruntergeladen. @@ -12781,14 +13348,6 @@ a:hover { No files found Keine Dateien gefunden - - &Contents - &Inhalt - - - Wireshark Filter - Wireshark Filter - TShark TShark @@ -13054,10 +13613,6 @@ a:hover { Wireless Toolbar Wireless Toolbar - - Help contents - Hilfe Inhalt - FAQs Häufige Fragen (en) @@ -13178,11 +13733,6 @@ a:hover { Find the previous packet Vorheriges Paket finden - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - Paket &markieren - Mark All Displayed Alle angezeigte Pakete markieren @@ -13211,11 +13761,6 @@ a:hover { Go to the previous marked packet Zum vorherigen markierten Paket gehen - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - Paket &ignorieren bzw. zurücksetzen - Ignore All Displayed Alle angezeigten Pakete ignorieren @@ -13656,10 +14201,6 @@ a:hover { Reset Layout Ansicht zurücksetzen - - Reset appearance layout to default size - Anzeige auf Ausgangsgröße zurücksetzen - Seconds Since First Captured Packet Sekunden seit erstem aufgezeichneten Paket @@ -13670,19 +14211,19 @@ a:hover { Tenths of a millisecond - Zehntelmillisekunde + Zehntelmillisekunden Hundredths of a millisecond - Hundertstelmillisekunde + Hundertstelmillisekunden Tenths of a microsecond - Zehntelmikrosekunde + Zehntelmikrosekunden Hundredths of a microsecond - Hundertstelmikrosekunde + Hundertstelmikrosekunden Packet &Diagram @@ -13820,22 +14361,30 @@ a:hover { MAC Address Blocks MAC Adressblöcke - - TLS Keylog Launcher - TLS Keylog Launcher - - - Release Notes - Veröffentlichungshinweise - &Options… &Optionen... + + &3GPP Uu + &3GPP Uu + &Wireless &Wireless + + &User's Guide + Ben&utzerhandbuch (en) + + + Wireshark User's Guide + Wireshark Benutzerhandbuch (en) + + + Display Filters + Anzeigefilter + Capture &Filters… Mitschnitt&filter... @@ -13880,10 +14429,18 @@ a:hover { Find Pre&vious Vorheriges finden + + &Mark/Unmark Selected + Ausgewählte &markieren + Mark or unmark each selected packet Jedes ausgewählte Paket markieren bzw. Markierung rückgängig machen + + &Ignore/Unignore Selected + Ausgewählte &ignorieren + Ignore or unignore each selected packet Jedes ausgewählte Paket ignorieren bzw. Ignorieren zurücksetzen @@ -13924,6 +14481,18 @@ a:hover { TCP throughput TCP Durchsatz + + General + Allgemein + + + Query-Response + Query-Response + + + DNS Query-Response Statistics + DNS Query-Response Statistiken + Request Sequences Anfrage Sequenzen @@ -13932,6 +14501,14 @@ a:hover { HTTP Request Sequences HTTP Anfrage Sequenzen + + E2AP + E2AP + + + E2AP Messages + E2AP Nachrichten + Decode &As… Dekodieren &als... @@ -13992,6 +14569,10 @@ a:hover { Normal Size Normale Größe + + Reset layout to default size + Anzeige auf Standardgröße zurücksetzen + Resize Columns Spaltengröße anpassen @@ -14082,11 +14663,11 @@ a:hover { Tenths of a second - Zehntelsekunde + Zehntelsekunden Hundredths of a second - Hundertstel + Hundertstelsekunden Milliseconds @@ -14250,6 +14831,14 @@ a:hover { Go to the packet referenced by the selected field. Zum Paket gehen auf das das ausgewählte Feld referenziert. + + TLS Keylog Launcher + TLS Keylog Launcher + + + Release Notes + Release Notes + &VoIP Calls &VoIP Anrufe @@ -14282,10 +14871,6 @@ a:hover { &GSM &GSM - - &LTE - &LTE - &MTP3 &MTP3 @@ -14570,6 +15155,10 @@ a:hover { Quit without Saving &Ohne Speichern beenden + + USB CDC Data + USB CDC-Daten + There is no "rtp.ssrc" field in this version of Wireshark. In dieser Wireshark-Version ist kein "rtp.ssrc" Feld vorhanden. diff --git a/ui/qt/wireshark_dialog.cpp b/ui/qt/wireshark_dialog.cpp index 4045868f..ae8fc73c 100644 --- a/ui/qt/wireshark_dialog.cpp +++ b/ui/qt/wireshark_dialog.cpp @@ -9,8 +9,6 @@ #include "config.h" -#include - #include "cfile.h" #include @@ -95,7 +93,7 @@ void WiresharkDialog::updateWidgets() setWindowSubtitle(subtitle_); } -bool WiresharkDialog::registerTapListener(const char *tap_name, void *tap_data, const char *filter, guint flags, tap_reset_cb tap_reset, tap_packet_cb tap_packet, tap_draw_cb tap_draw) +bool WiresharkDialog::registerTapListener(const char *tap_name, void *tap_data, const char *filter, unsigned flags, tap_reset_cb tap_reset, tap_packet_cb tap_packet, tap_draw_cb tap_draw) { GString *error_string = register_tap_listener(tap_name, tap_data, filter, flags, tap_reset, tap_packet, tap_draw, NULL); diff --git a/ui/qt/wireshark_dialog.h b/ui/qt/wireshark_dialog.h index ad557ebc..20fd7113 100644 --- a/ui/qt/wireshark_dialog.h +++ b/ui/qt/wireshark_dialog.h @@ -39,6 +39,11 @@ public: // XXX Unlike the entire QWidget API, parent is mandatory here. explicit WiresharkDialog(QWidget &parent, CaptureFile &capture_file); + /** + * @brief true if the file has been closed, false otherwise. + */ + bool fileClosed() const { return file_closed_; } + protected: virtual void keyPressEvent(QKeyEvent *event) { QDialog::keyPressEvent(event); } virtual void accept(); @@ -93,7 +98,7 @@ protected: * @param tap_draw Draw callback. */ bool registerTapListener(const char *tap_name, void *tap_data, - const char *filter, guint flags, + const char *filter, unsigned flags, tap_reset_cb tap_reset, tap_packet_cb tap_packet, tap_draw_cb tap_draw); @@ -103,17 +108,21 @@ protected: */ virtual void removeTapListeners(); - /** - * @brief true if the file has been closed, false otherwise. - */ - // XXX Needs a getter? + // XXX - Move this to private, have subclasses use the getter? bool file_closed_; /** * @brief Check to see if the user has closed (and not minimized) the dialog. * @return true if the dialog has been closed, false otherwise. */ - bool dialogClosed() { return dialog_closed_; } + bool dialogClosed() const { return dialog_closed_; } + + /** + * @brief Check to see if we're currently retapping. If this is positive, + * tapping will fail in process_specified_records. + * @return The current retap depth. (In current implementation, 0 or 1.) + */ + int retapDepth() const { return retap_depth_; } /** * @brief Called when the capture file is about to close. This can be diff --git a/ui/qt/wireshark_en.ts b/ui/qt/wireshark_en.ts index ef92aa85..5f343152 100644 --- a/ui/qt/wireshark_en.ts +++ b/ui/qt/wireshark_en.ts @@ -44,7 +44,7 @@ - Filter by path + Search Folders @@ -79,6 +79,14 @@ License + + About Logray + + + + Logray + + The directory does not exist @@ -754,6 +762,28 @@ + + CaptureCommentDialog + + Edit Capture Comments + + + + Add Comment + + + + Section %1 + + + + + CaptureCommentTabWidget + + Comment %1 + + + CaptureFile @@ -862,10 +892,6 @@ Read filter: - - Compress with g&zip - - Open Capture File Wireshark: Open Capture File @@ -948,7 +974,7 @@ - Capture file comments + Edit Comments @@ -959,10 +985,6 @@ Copy To Clipboard - - Save Comments - - Capture File Properties @@ -1011,10 +1033,18 @@ First packet + + First event + + Last packet + + Last event + + Elapsed @@ -1051,6 +1081,10 @@ Dropped packets + + Dropped events + + Capture filter @@ -1063,6 +1097,10 @@ Packet size limit (snaplen) + + Event size limit (snaplen) + + none @@ -1071,6 +1109,26 @@ %1 bytes + + Comments + + + + Comment %1: + + + + Decryption Secrets + + + + Type + + + + Size + + Statistics @@ -1095,6 +1153,10 @@ Packets + + Events + + Time span, s @@ -1107,6 +1169,10 @@ Average packet size, B + + Average event size, B + + Bytes @@ -1120,11 +1186,11 @@ - Section Comment + Packet Comments - Packet Comments + Event Comments @@ -1134,6 +1200,12 @@ Created by Wireshark %1 + + + + + Created by Logray %1 + @@ -1362,6 +1434,14 @@ For example, use 1 hour to have a new file created every hour on the hour. + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + + + + Enable monitor mode on all 802.11 interfaces + + compression @@ -1374,6 +1454,30 @@ For example, use 1 hour to have a new file created every hour on the hour.gzip + + File infix pattern + + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + + + + YYYYmmDDHHMMSS_NNNNN + + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + + + + NNNNN_YYYYmmDDHHMMSS + + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> @@ -1527,7 +1631,7 @@ For example, use 1 hour to have a new file created every hour on the hour. - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. @@ -1557,6 +1661,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Capture packets in promiscuous mode + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + + + + Capture packets in monitor mode on 802.11 devices + + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> @@ -1784,6 +1896,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved + + Width + + + + Alignment + + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> @@ -1831,6 +1951,25 @@ For example, use 1 hour to have a new file created every hour on the hour. + + CompressionGroupBox + + Compression options + + + + &Uncompressed + + + + Compress with g&zip + + + + Compress with &LZ4 + + + ConversationDataModel @@ -1897,6 +2036,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Bits/s B + + Flows + + Total Packets @@ -2012,29 +2155,53 @@ For example, use 1 hour to have a new file created every hour on the hour. - …as Printable Text + …as MIME Data - Copy only the printable text in the packet. + …as C String - …as MIME Data + Copy packet bytes as printable ASCII characters and escape sequences. - …as C String + …as Go literal - Copy packet bytes as printable ASCII characters and escape sequences. + Copy packet bytes as Go literal. + + + + …as C Array + + + + Copy packet bytes as C Array. …as a Hex Stream + + …as UTF-8 Text + + + + Copy packet bytes as text, treating as UTF-8. + + + + …as ASCII Text + + + + Copy packet bytes as text, treating as ASCII. + + Copy packet bytes as a stream of hex. @@ -2829,6 +2996,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: + + Export PDUs + + ExtArgSelector @@ -2867,10 +3038,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Start - - Save - - Default @@ -3012,6 +3179,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Display Filters + + Display Filter Macros + + + + New macro + + Open @@ -3095,10 +3270,18 @@ For example, use 1 hour to have a new file created every hour on the hour. FilterListModel + + Macro Name + + Filter Name + + Macro Expression + + Filter Expression @@ -3185,75 +3368,71 @@ For example, use 1 hour to have a new file created every hour on the hour. FolderListModel - "File" dialogs - - - - capture files + Temp - Temp + Personal configuration - untitled capture files + Global configuration - Personal configuration + System - Global configuration + ethers, ipxnets - dfilters, preferences, ethers, … + Program - dfilters, preferences, manuf, … + Personal Plugins - System + Global Plugins - ethers, ipxnets + Personal Lua Plugins - Program + Global Lua Plugins - program files + Lua scripts - Personal Plugins + "File" dialog location - binary plugins + Capture files - Global Plugins + Untitled capture files - Personal Lua Plugins + Preferences, profiles, manuf, … - Global Lua Plugins + Program files - Lua scripts + Binary plugins @@ -3261,7 +3440,7 @@ For example, use 1 hour to have a new file created every hour on the hour. - external capture (extcap) plugins + External capture (extcap) plugins @@ -3398,6 +3577,24 @@ For example, use 1 hour to have a new file created every hour on the hour.%Ln turns. + + Event %1. + + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + + + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + + + + Click to select. @@ -3430,6 +3627,18 @@ For example, use 1 hour to have a new file created every hour on the hour.%1 stream not found on the selected packet. + + Read activity(%6) + + + + Write activity(%6) + + + + Entire I/O activity (%1) + + Entire conversation (%1) @@ -3446,10 +3655,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Save Stream Content As… - - [Stream output truncated] - - %Ln total stream(s). @@ -3477,8 +3682,19 @@ For example, use 1 hour to have a new file created every hour on the hour. - Show data as - Show and save data as + Show as + + + + No delta times + + + + Turn delta times + + + + All delta times @@ -3493,11 +3709,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: + + Case sensitive + + Find &Next + + FollowStreamText + + [Stream output truncated] + + + FontColorPreferencesFrame @@ -3805,28 +4032,27 @@ For example, use 1 hour to have a new file created every hour on the hour. - Remove this graph. - Remove this dissection behavior. + Add a new graph. - Add a new graph. + Clear all graphs. - Duplicate this graph. + Remove the selected graph(s). - Clear all graphs. + Duplicate the selected graph(s). - Move this graph upwards. + Move the selected graph(s) upwards. - Move this graph downwards. + Move the selected graph(s) downwards. @@ -3869,10 +4095,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Enable legend - - Reset - - Reset Graph @@ -4086,6 +4308,42 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy graphs from another profile. + + 1 μs + + + + 2 μs + + + + 5 μs + + + + 10 μs + + + + 20 μs + + + + 50 μs + + + + 100 μs + + + + 200 μs + + + + 500 μs + + 1 ms @@ -4130,6 +4388,14 @@ For example, use 1 hour to have a new file created every hour on the hour.5 sec + + 2 min + + + + 5 min + + Wireshark I/O Graphs: %1 @@ -4142,6 +4408,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Filtered events + + All packets + + + + All events + + All Packets @@ -4155,7 +4429,7 @@ For example, use 1 hour to have a new file created every hour on the hour. - Access Denied + All Execs @@ -4202,6 +4476,34 @@ For example, use 1 hour to have a new file created every hour on the hour.Click to select a portion of the graph. + + %1 Intervals + + + + Move to top left + + + + Move to top center + + + + Move to top right + + + + Move to bottom left + + + + Move to bottom center + + + + Move to bottom right + + Portable Document Format (*.pdf) @@ -4954,6 +5256,13 @@ For example, use 1 hour to have a new file created every hour on the hour. + + InterfaceTreeDelegate + + default + + + InterfaceTreeModel @@ -5931,7 +6240,7 @@ For example, use 1 hour to have a new file created every hour on the hour. LteMacStatisticsDialog - LTE Mac Statistics + LTE/NR Mac Statistics @@ -6211,11 +6520,11 @@ For example, use 1 hour to have a new file created every hour on the hour. - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) - LTE RLC Graph - no channel selected + 3GPP RLC Graph - no channel selected @@ -6270,7 +6579,7 @@ For example, use 1 hour to have a new file created every hour on the hour. LteRlcStatisticsDialog - LTE RLC Statistics + 3GPP RLC Statistics @@ -6356,6 +6665,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Profile: %1 + + %1 Displayed: %2 (%3%) + + Manage Profiles… @@ -6418,6 +6731,13 @@ For example, use 1 hour to have a new file created every hour on the hour.%Ln bytes + + %Ln bit(s) + + %Ln bit + %Ln bits + + Byte %1 @@ -6431,8 +6751,11 @@ For example, use 1 hour to have a new file created every hour on the hour. - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 + Selected Event: %1 %2 + + + + Events: %1 @@ -6464,6 +6787,10 @@ For example, use 1 hour to have a new file created every hour on the hour.No Packets + + No Events + + From Zip File... @@ -6496,6 +6823,13 @@ For example, use 1 hour to have a new file created every hour on the hour. + + MainWindow + + Display filter as %1 + + + MainWindowPreferencesFrame @@ -6527,6 +6861,10 @@ For example, use 1 hour to have a new file created every hour on the hour.The most recently used folder + + The current working directory + + Show up to @@ -6957,6 +7295,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show Field Values + + Refresh + + Save Diagram As… @@ -7004,6 +7346,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show packet bytes + + Layout: + + Packet %1 @@ -7027,6 +7373,13 @@ For example, use 1 hour to have a new file created every hour on the hour.%Ln bytes + + %Ln bit(s) + + %Ln bit + %Ln bits + + PacketFormatGroupBox @@ -7483,10 +7836,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy this profile. + + The number of packets or events to check for automatic profile switching. + + + + Auto switch packet limit + + Configuration Profiles + + Auto switch event limit + + Import noun @@ -7669,6 +8034,10 @@ For example, use 1 hour to have a new file created every hour on the hour.deleted + + Auto Switch Filter + + copy noun @@ -8192,6 +8561,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Marker missing? + + LTE + + + + NR + + C-RNTI @@ -8212,6 +8589,10 @@ For example, use 1 hour to have a new file created every hour on the hour.UEId + + RAT + + UL Frames @@ -8436,9 +8817,69 @@ For example, use 1 hour to have a new file created every hour on the hour.Browse… + + PACKETS + + + + EVENTS + + + + BYTES + + + + BITS + + + + COUNT FRAMES + + + + COUNT FIELDS + + + + SUM + + + + MAX + + + + MIN + + + + AVERAGE + + + + THROUGHPUT + + + + LOAD + + + + Left + + + + Center + + + + Right + + - QObject::QObject + QObject::QObject::QObject CCCH @@ -8538,6 +8979,13 @@ For example, use 1 hour to have a new file created every hour on the hour. + + ResizeHeaderView + + Resize all %1 to contents + + + ResolvedAddressesDialog @@ -8653,6 +9101,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved Addresses + + Copy + + + + Save as… + + # Resolved addresses found in %1 @@ -8664,6 +9120,61 @@ For example, use 1 hour to have a new file created every hour on the hour. + + ResolvedAddressesView + + as Plain Text + + + + Copy selected rows + + + + Copy table + + + + as CSV + + + + as JSON + + + + Save selected rows as… + + + + Save table as… + + + + Save Resolved Addresses As… + + + + Plain text (*.txt) + + + + CSV Document (*.csv) + + + + JSON Document (*.json) + + + + Warning + + + + Unable to save %1: %2 + + + ResponseTimeDelayDialog @@ -10334,6 +10845,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Packet bytes + + <b>Options:</b> + + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> @@ -10354,6 +10869,18 @@ For example, use 1 hour to have a new file created every hour on the hour.Case sensitive + + Backwards + + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + + + + Multiple occurrences + + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10391,6 +10918,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Invalid filter. + + Event List + + + + Event Details + + + + Event Bytes + + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + + That filter doesn't test anything. @@ -10811,6 +11354,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: + + Case sensitive + + Find &Next @@ -10906,15 +11453,23 @@ For example, use 1 hour to have a new file created every hour on the hour.Save as… + + Decoded as %1. + + Save Selected Packet Bytes As… + + compressed %1 + + - Displaying %Ln byte(s). + Using %Ln byte(s). - Displaying %Ln byte. - Displaying %Ln bytes. + Using %Ln byte. + Using %Ln bytes. @@ -11014,6 +11569,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: + + Strip Headers + + SupportedProtocolsDialog @@ -11948,21 +12507,19 @@ For example, use 1 hour to have a new file created every hour on the hour. - Remove this entry. - Remove this profile. + Remove the selected entry(ies). - Copy this entry. - Copy this profile. + Copy the selected entry(ies). - Move entry up. + Move the selected entry(ies) up. - Move entry down. + Move the selected entry(ies) down. @@ -11989,19 +12546,19 @@ For example, use 1 hour to have a new file created every hour on the hour. - Remove this entry. + Remove the selected entry(ies). - Copy this entry. + Copy the selected entry(ies). - Move entry up. + Move the selected entry(ies) up. - Move entry down. + Move the selected entry(ies) down. @@ -12330,10 +12887,18 @@ a:hover { You are sniffing the glue that holds the Internet together using Wireshark + + You are sniffing the glue that holds your system together using Logray + + You are running Wireshark + + You are running Logray + + You receive automatic updates. @@ -12610,14 +13175,6 @@ a:hover { No files found - - &Contents - - - - Wireshark Filter - - TShark @@ -12883,10 +13440,6 @@ a:hover { Wireless Toolbar - - Help contents - - FAQs @@ -13010,7 +13563,7 @@ a:hover { &Mark/Unmark Packet(s) &Mark/Unmark Packet - &Mark/Unmark Packet + &Mark/Unmark Packet Mark All Displayed @@ -13043,7 +13596,7 @@ a:hover { &Ignore/Unignore Packet(s) &Ignore/Unignore Packet - &Ignore/Unignore Packet + &Ignore/Unignore Packet Ignore All Displayed @@ -13485,10 +14038,6 @@ a:hover { Reset Layout - - Reset appearance layout to default size - - Seconds Since First Captured Packet @@ -13650,19 +14199,27 @@ a:hover { - TLS Keylog Launcher + &Options… - Release Notes + &3GPP Uu - &Options… + &Wireless - &Wireless + &User's Guide + + + + Wireshark User's Guide + + + + Display Filters @@ -13709,10 +14266,18 @@ a:hover { Find Pre&vious + + &Mark/Unmark Selected + + Mark or unmark each selected packet + + &Ignore/Unignore Selected + + Ignore or unignore each selected packet @@ -13753,6 +14318,18 @@ a:hover { TCP throughput + + General + + + + Query-Response + + + + DNS Query-Response Statistics + + Request Sequences @@ -13761,6 +14338,14 @@ a:hover { HTTP Request Sequences + + E2AP + + + + E2AP Messages + + Decode &As… @@ -13821,6 +14406,10 @@ a:hover { Normal Size + + Reset layout to default size + + Resize Columns @@ -14079,6 +14668,14 @@ a:hover { Go to the packet referenced by the selected field. + + TLS Keylog Launcher + + + + Release Notes + + &VoIP Calls @@ -14111,10 +14708,6 @@ a:hover { &GSM - - &LTE - - &MTP3 @@ -14399,6 +14992,10 @@ a:hover { Quit without Saving + + USB CDC Data + + There is no "rtp.ssrc" field in this version of Wireshark. diff --git a/ui/qt/wireshark_es.ts b/ui/qt/wireshark_es.ts index 2118a585..acd75cb1 100644 --- a/ui/qt/wireshark_es.ts +++ b/ui/qt/wireshark_es.ts @@ -44,8 +44,8 @@ Carpetas - Filter by path - Filtrar por ruta + Search Folders + Plugins @@ -79,6 +79,14 @@ License Licencia + + About Logray + + + + Logray + + The directory does not exist El directorio no existe @@ -754,6 +762,28 @@ …como EBCDIC + + CaptureCommentDialog + + Edit Capture Comments + + + + Add Comment + + + + Section %1 + + + + + CaptureCommentTabWidget + + Comment %1 + + + CaptureFile @@ -839,10 +869,6 @@ Read filter: Filtro de lectura: - - Compress with g&zip - Comprimir con g&zip - Open Capture File Wireshark: Open Capture File @@ -925,8 +951,8 @@ Detalles - Capture file comments - Comentarios de archivo de captura + Edit Comments + Refresh @@ -936,10 +962,6 @@ Copy To Clipboard Copiar al portapapeles - - Save Comments - Guardar comentarios - Capture File Properties Propiedades de archivo de captura @@ -988,10 +1010,18 @@ First packet Primer paquete + + First event + + Last packet Último paquete + + Last event + + Elapsed Transcurrido @@ -1028,6 +1058,10 @@ Dropped packets Paquetes perdidos + + Dropped events + + Capture filter Filtro de captura @@ -1040,6 +1074,10 @@ Packet size limit (snaplen) + + Event size limit (snaplen) + + none ninguno @@ -1048,6 +1086,26 @@ %1 bytes %1 bytes + + Comments + Comentarios + + + Comment %1: + + + + Decryption Secrets + + + + Type + Tipo + + + Size + Tamaño + Statistics Estadísticas @@ -1072,6 +1130,10 @@ Packets Paquetes + + Events + Eventos + Time span, s Espacio de tiempo, s @@ -1084,6 +1146,10 @@ Average packet size, B Promedio de tamaño de paquete, B + + Average event size, B + + Bytes Bytes @@ -1096,14 +1162,14 @@ Average bits/s Promedio de bits/s - - Section Comment - Sección de comentarios - Packet Comments Comentarios de paquete + + Event Comments + + <p>Frame %1: <p>Trama %1: @@ -1111,6 +1177,12 @@ Created by Wireshark %1 + + + + + Created by Logray %1 + @@ -1340,6 +1412,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Cambia al siguiente archivo cuando el (reloj de pared) tiempo es múltiplo del intervalo especificado. Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + + + + Enable monitor mode on all 802.11 interfaces + + compression compresión @@ -1352,6 +1432,30 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.gzip gzip + + File infix pattern + + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + + + + YYYYmmDDHHMMSS_NNNNN + + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + + + + NNNNN_YYYYmmDDHHMMSS + + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> <html><head/><body><p>Después de que la captura haya cambiado al siguiente archivo y el número proporcionado haya excedido, se eliminará el archivo más antiguo.</p></body></html> @@ -1505,8 +1609,8 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Error - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. - Varios archivos: El tamaño de archivo solicitado es demasiado grande. El tamaño de archivo no puede ser mayor de 2 GiB. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. + Multiple files: No capture file name given. You must specify a filename if you want to use multiple files. @@ -1535,6 +1639,14 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Capture packets in promiscuous mode Capturar paquetes en modo promiscuo + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + + + + Capture packets in monitor mode on 802.11 devices + + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>Captura paquetes en formato de archivo de captura de próxima generación.</p></body></html> @@ -1762,6 +1874,14 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Resolved + + Width + + + + Alignment + + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> @@ -1809,6 +1929,25 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Copia texto de filtro al portapapeles. + + CompressionGroupBox + + Compression options + + + + &Uncompressed + + + + Compress with g&zip + + + + Compress with &LZ4 + + + ConversationDataModel @@ -1875,6 +2014,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Bits/s B Bits/s B + + Flows + + Total Packets Paquetes totales @@ -1990,29 +2133,53 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. - …as Printable Text + …as MIME Data - Copy only the printable text in the packet. + …as C String - …as MIME Data + Copy packet bytes as printable ASCII characters and escape sequences. - …as C String + …as Go literal - Copy packet bytes as printable ASCII characters and escape sequences. + Copy packet bytes as Go literal. + + + + …as C Array + + + + Copy packet bytes as C Array. …as a Hex Stream + + …as UTF-8 Text + + + + Copy packet bytes as text, treating as UTF-8. + + + + …as ASCII Text + + + + Copy packet bytes as text, treating as ASCII. + + Copy packet bytes as a stream of hex. @@ -2809,6 +2976,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Display filter: Filtro de visualización: + + Export PDUs + + ExtArgSelector @@ -2847,10 +3018,6 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Start - - Save - - Default Predeterminado @@ -2992,6 +3159,14 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Display Filters Filtros de visualización + + Display Filter Macros + + + + New macro + + Open Abrir @@ -3075,10 +3250,18 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. FilterListModel + + Macro Name + + Filter Name Nombre de filtro + + Macro Expression + + Filter Expression Expresión de filtro @@ -3164,22 +3347,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. FolderListModel - - "File" dialogs - Diálogos de "Archivo" - - - capture files - archivos de captura - Temp Temporal - - untitled capture files - archivos de captura sin título - Personal configuration Configuración personal @@ -3188,14 +3359,6 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Global configuration Configuración global - - dfilters, preferences, ethers, … - - - - dfilters, preferences, manuf, … - - System Sistema @@ -3208,18 +3371,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Program Programa - - program files - archivos de programa - Personal Plugins Complementos personales - - binary plugins - complementos binarios - Global Plugins Complementos globales @@ -3236,12 +3391,36 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Lua scripts + + "File" dialog location + + + + Capture files + + + + Untitled capture files + + + + Preferences, profiles, manuf, … + + + + Program files + + + + Binary plugins + + Personal Extcap path Ruta personal de Extcap - external capture (extcap) plugins + External capture (extcap) plugins @@ -3364,6 +3543,24 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. + + Event %1. + + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + + + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + + + + Click to select. Clic para seleccionar. @@ -3396,6 +3593,18 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.%1 stream not found on the selected packet. + + Read activity(%6) + + + + Write activity(%6) + + + + Entire I/O activity (%1) + + Entire conversation (%1) Conversación completa (%1) @@ -3412,10 +3621,6 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Save Stream Content As… Guardar contenido de secuencia como… - - [Stream output truncated] - - %Ln total stream(s). @@ -3443,9 +3648,20 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Hint. - Show data as - Show and save data as - Mostrar datos como + Show as + Mostrar como + + + No delta times + + + + Turn delta times + + + + All delta times + Stream @@ -3459,11 +3675,22 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Find: Buscar: + + Case sensitive + Mayúsculas y minúsculas + Find &Next Buscar &siguiente + + FollowStreamText + + [Stream output truncated] + + + FontColorPreferencesFrame @@ -3799,29 +4026,28 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. - - Remove this graph. - Remove this dissection behavior. - Elimina esta gráfica. - Add a new graph. Añade una nueva gráfica. - - Duplicate this graph. - Duplica esta gráfica. - Clear all graphs. Vacía todas las gráficas. - Move this graph upwards. + Remove the selected graph(s). + + + + Duplicate the selected graph(s). + + + + Move the selected graph(s) upwards. - Move this graph downwards. + Move the selected graph(s) downwards. @@ -3864,10 +4090,6 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Enable legend - - Reset - Restablecer - Reset Graph Restablecer gráfica @@ -3971,7 +4193,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Go to packet currently under the cursor - + Va al paquete actualmente debajo del cursor G @@ -4081,6 +4303,42 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Copy graphs from another profile. Copia gráficas desde otro perfil. + + 1 μs + + + + 2 μs + + + + 5 μs + + + + 10 μs + + + + 20 μs + + + + 50 μs + + + + 100 μs + + + + 200 μs + + + + 500 μs + + 1 ms 1 ms @@ -4125,6 +4383,14 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.5 sec 5 sec + + 2 min + 10 min {2 ?} + + + 5 min + 10 min {5 ?} + Wireshark I/O Graphs: %1 Gráficas E/S de Wireshark: %1 @@ -4137,6 +4403,14 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Filtered events + + All packets + + + + All events + + All Packets Todos los paquetes @@ -4150,7 +4424,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. - Access Denied + All Execs @@ -4187,7 +4461,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Release to zoom, x = %1 to %2, y = %3 to %4 - Soltar para zoom, x = %1 a %2, y = %3 a %4 + Suelte para zoom, x = %1 a %2, y = %3 a %4 Unable to select range. @@ -4197,6 +4471,34 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Click to select a portion of the graph. Clic para seleccionar una parte de la gráfica. + + %1 Intervals + + + + Move to top left + + + + Move to top center + + + + Move to top right + + + + Move to bottom left + + + + Move to bottom center + + + + Move to bottom right + + Portable Document Format (*.pdf) Formato de documento portable (*.pdf) @@ -4949,6 +5251,13 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. + + InterfaceTreeDelegate + + default + + + InterfaceTreeModel @@ -5926,7 +6235,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. LteMacStatisticsDialog - LTE Mac Statistics + LTE/NR Mac Statistics @@ -6151,7 +6460,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Go to packet currently under the cursor - + Va al paquete actualmente debajo del cursor G @@ -6206,11 +6515,11 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) - LTE RLC Graph - no channel selected + 3GPP RLC Graph - no channel selected @@ -6231,7 +6540,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Release to zoom, x = %1 to %2, y = %3 to %4 - Soltar para zoom, x = %1 a %2, y = %3 a %4 + Suelte para zoom, x = %1 a %2, y = %3 a %4 Unable to select range. @@ -6265,7 +6574,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. LteRlcStatisticsDialog - LTE RLC Statistics + 3GPP RLC Statistics @@ -6351,6 +6660,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Profile: %1 Perfil: %1 + + %1 Displayed: %2 (%3%) + + Manage Profiles… Administrar perfiles… @@ -6413,6 +6726,13 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. + + %Ln bit(s) + + + + + Byte %1 Byte %1 @@ -6426,9 +6746,12 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Paquete seleccionado: %1 %2 - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 - Paquetes: %1 %4 Mostrado: %2 (%3%) + Selected Event: %1 %2 + + + + Events: %1 + %1 Selected: %2 (%3%) @@ -6459,6 +6782,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.No Packets No hay paquetes + + No Events + + From Zip File... @@ -6491,6 +6818,13 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. + + MainWindow + + Display filter as %1 + + + MainWindowPreferencesFrame @@ -6522,6 +6856,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.The most recently used folder La carpeta usada más recientemente + + The current working directory + + Show up to Mostrar hasta @@ -6952,6 +7290,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Show Field Values + + Refresh + Actualizar + Save Diagram As… @@ -6999,6 +7341,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Show packet bytes Mostrar bytes de paquete + + Layout: + + Packet %1 Paquete %1 @@ -7022,6 +7368,13 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. + + %Ln bit(s) + + + + + PacketFormatGroupBox @@ -7478,10 +7831,22 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Copy this profile. Copia este perfil. + + The number of packets or events to check for automatic profile switching. + + + + Auto switch packet limit + + Configuration Profiles Configuración de perfiles + + Auto switch event limit + + Import noun @@ -7650,6 +8015,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.deleted + + Auto Switch Filter + + copy noun @@ -8173,6 +8542,14 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Marker missing? + + LTE + + + + NR + + C-RNTI @@ -8193,6 +8570,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.UEId UEId + + RAT + + UL Frames Tramas UL @@ -8338,91 +8719,151 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. - Unknown + Unknown + + + + UE Id + UE Id + + + Name + Nombre + + + Mode + + + + Priority + + + + default + + + + DLT %1 + + + + Invalid Display Filter + + + + The filter expression %1 isn't a valid display filter. (%2). + + + + Error + Error + + + No remote interfaces found. + + + + PCAP not found + + + + Unknown error + + + + Default + Predeterminado + + + Changed + Modificado + + + Has this preference been changed? + ¿Se ha modificado esta preferencia? + + + Default value is empty + El valor predeterminado está vacío + + + Gap in dissection - UE Id - UE Id + Edit… + Editar… - Name - Nombre + Browse… + Explorar… - Mode + PACKETS - Priority + EVENTS - default + BYTES - DLT %1 + BITS - Invalid Display Filter + COUNT FRAMES - The filter expression %1 isn't a valid display filter. (%2). + COUNT FIELDS - Error - Error - - - No remote interfaces found. + SUM - PCAP not found + MAX - Unknown error + MIN - Default - Predeterminado - - - Changed - Modificado + AVERAGE + - Has this preference been changed? - ¿Se ha modificado esta preferencia? + THROUGHPUT + - Default value is empty - El valor predeterminado está vacío + LOAD + - Gap in dissection + Left - Edit… - Editar… + Center + - Browse… - Explorar… + Right + - QObject::QObject + QObject::QObject::QObject CCCH - CCCH + CCCH @@ -8519,6 +8960,13 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.milisegundos + + ResizeHeaderView + + Resize all %1 to contents + + + ResolvedAddressesDialog @@ -8634,6 +9082,14 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Resolved Addresses Direcciones resueltas + + Copy + Copiar + + + Save as… + Guardar como… + # Resolved addresses found in %1 # Direcciones resultas encontradas en %1 @@ -8647,6 +9103,61 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. + + ResolvedAddressesView + + as Plain Text + + + + Copy selected rows + + + + Copy table + + + + as CSV + como CSV + + + as JSON + + + + Save selected rows as… + + + + Save table as… + + + + Save Resolved Addresses As… + + + + Plain text (*.txt) + Texto plano (*.txt) + + + CSV Document (*.csv) + + + + JSON Document (*.json) + + + + Warning + Advertencia + + + Unable to save %1: %2 + + + ResponseTimeDelayDialog @@ -8985,11 +9496,11 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Prepare &Filter - + Preparar &filtro Prepare a filter matching the selected stream(s). - + Prepara un filtro que coincide con los flujo(s) seleccionado(s). &Current Tab @@ -9292,7 +9803,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Invert selection - + Invierte la selección Play/Pause @@ -9340,11 +9851,11 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Prepare &Filter - + Preparar &filtro Prepare a filter matching the selected stream(s). - + Prepara un filtro que coincide con los flujo(s) seleccionado(s). R&efresh streams @@ -9400,7 +9911,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Go to packet currently under the cursor - + Va al paquete actualmente debajo del cursor Play the stream @@ -9428,7 +9939,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Select - + Seleccionar Audio Routing @@ -9619,7 +10130,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Start Time - + Hora de inicio Duration @@ -9675,7 +10186,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Prepare &Filter - + Preparar &filtro &Export @@ -9771,7 +10282,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Invert selection - + Invierte la selección Go To Setup @@ -9787,7 +10298,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Prepare a filter matching the selected stream(s). - + Prepara un filtro que coincide con los flujo(s) seleccionado(s). P @@ -9819,7 +10330,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Copy stream list as CSV. - Copia el listado de secuencias como CSV. + Copy as YAML @@ -9827,7 +10338,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Copy stream list as YAML. - Copia el listado de secuencias como YAML. + RTP Streams @@ -9835,7 +10346,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Select - + Seleccionar as CSV @@ -10317,6 +10828,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Packet bytes Bytes de paquete + + <b>Options:</b> + + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>Busca cadenas que contienen caracteres reducidos (UTF-8 y ASCII) o ampliados (UTF-16).</p></body></html> @@ -10337,6 +10852,18 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Case sensitive Mayúsculas y minúsculas + + Backwards + + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + + + + Multiple occurrences + + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10374,6 +10901,22 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Invalid filter. Filtro no valido. + + Event List + + + + Event Details + + + + Event Bytes + + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + + That filter doesn't test anything. Este filtro no comprueba nada. @@ -10674,7 +11217,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Go to packet currently under the cursor - + Va al paquete actualmente debajo del cursor G @@ -10794,6 +11337,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Find: Buscar: + + Case sensitive + Mayúsculas y minúsculas + Find &Next Buscar &siguiente @@ -10889,12 +11436,20 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Save as… Guardar como… + + Decoded as %1. + + Save Selected Packet Bytes As… + + compressed %1 + + - Displaying %Ln byte(s). + Using %Ln byte(s). @@ -10997,6 +11552,10 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Display filter: Filtro de visualización: + + Strip Headers + + SupportedProtocolsDialog @@ -11379,7 +11938,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Go to packet currently under the cursor - + Va al paquete actualmente debajo del cursor G @@ -11575,7 +12134,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Release to zoom, x = %1 to %2, y = %3 to %4 - Soltar para zoom, x = %1 a %2, y = %3 a %4 + Suelte para zoom, x = %1 a %2, y = %3 a %4 Unable to select range. @@ -11931,22 +12490,20 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Crea una nueva entrada. - Remove this entry. - Remove this profile. - Elimina esta entrada. + Remove the selected entry(ies). + - Copy this entry. - Copy this profile. - Copia esta entrada. + Copy the selected entry(ies). + - Move entry up. - Mueve entrada hacia arriba. + Move the selected entry(ies) up. + - Move entry down. - Mueve entrada hacia abajo. + Move the selected entry(ies) down. + Clear all entries. @@ -11972,20 +12529,20 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto.Crea una nueva entrada. - Remove this entry. - Elimina esta entrada. + Remove the selected entry(ies). + - Copy this entry. - Copia esta entrada. + Copy the selected entry(ies). + - Move entry up. - Mueve entrada hacia arriba. + Move the selected entry(ies) up. + - Move entry down. - Mueve entrada hacia abajo. + Move the selected entry(ies) down. + Clear all entries. @@ -12028,19 +12585,19 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Flow &Sequence - + &Secuencia de flujo Show flow sequence for selected call(s). - + Muestra la secuencia de flujo para la(s) llamada(s) seleccionada(s). Prepare &Filter - + Preparar &filtro Prepare a filter matching the selected calls(s). - + Prepara un filtro que coincide con la(s) llamada(s) seleccionada(s). Cop&y @@ -12052,11 +12609,11 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. All - + Todo Select all - Selecciona todo + Selecciona todo None @@ -12064,11 +12621,11 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Invert - Invertir + Invertir Invert selection - + Invierte la selección Select related RTP streams @@ -12096,23 +12653,23 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Display time as time of day - + Mostrar hora como hora de día Copy as CSV - Copiar como CSV + Copiar como CSV Copy stream list as CSV. - Copia el listado de secuencias como CSV. + Copia la lista de secuencias como CSV. Copy as YAML - Copiar como YAML + Copiar como YAML Copy stream list as YAML. - Copia el listado de secuencias como YAML. + Copia la lista de secuencias como YAML. SIP Flows @@ -12120,7 +12677,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. VoIP Calls - + Llamadas VoIP as CSV @@ -12132,7 +12689,7 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Select - + Seleccionar @@ -12151,11 +12708,11 @@ Por ejemplo, use 1 hora para tener creado un nuevo archivo cada hora en punto. Start Time - + Hora de inicio Stop Time - + Hora de finalización Initial Speaker @@ -12355,10 +12912,18 @@ a:hover { You are sniffing the glue that holds the Internet together using Wireshark Está absorbiendo el pegamento que mantiene unido internet usando Wireshark + + You are sniffing the glue that holds your system together using Logray + + You are running Wireshark Está ejecutando Wireshark + + You are running Logray + + You receive automatic updates. Recibe actualizaciones automáticas. @@ -12635,14 +13200,6 @@ a:hover { No files found No se encontraron archivos - - &Contents - &Contenidos - - - Wireshark Filter - Filtro de Wireshark - TShark TShark @@ -12908,10 +13465,6 @@ a:hover { Wireless Toolbar Barra de herramientas de wireless - - Help contents - Contenidos de ayuda - FAQs FAQs @@ -13032,11 +13585,6 @@ a:hover { Find the previous packet Busca el paquete anterior - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - &Marcar/Desmarcar paquete - Mark All Displayed Marcar todos los mostrados @@ -13065,11 +13613,6 @@ a:hover { Go to the previous marked packet Va al paquete marcado anterior - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - &Ignorar/No ignorar paquete - Ignore All Displayed Ignorar todos los mostrados @@ -13220,7 +13763,7 @@ a:hover { Flow sequence diagram - Diagrama de flujo de secuencia + Diagrama de secuencia de flujo ANCP @@ -13510,10 +14053,6 @@ a:hover { Reset Layout Restablecer diseño - - Reset appearance layout to default size - Restablece el diseño de apariencia al tamaño por defecto - Seconds Since First Captured Packet Segundos desde primer paquete capturado @@ -13675,20 +14214,28 @@ a:hover { - TLS Keylog Launcher + &Options… + &Opciones… + + + &3GPP Uu - Release Notes + &Wireless + &Wireless + + + &User's Guide - &Options… - &Opciones… + Wireshark User's Guide + - &Wireless - &Wireless + Display Filters + Filtros de visualización Capture &Filters… @@ -13734,10 +14281,18 @@ a:hover { Find Pre&vious Buscar ant&erior + + &Mark/Unmark Selected + + Mark or unmark each selected packet Marca o desmarca cada paquete seleccionado + + &Ignore/Unignore Selected + + Ignore or unignore each selected packet Ignora o no ignora cada paquete seleccionado @@ -13778,6 +14333,18 @@ a:hover { TCP throughput Rendimiento TCP + + General + + + + Query-Response + + + + DNS Query-Response Statistics + + Request Sequences Secuencias de petición @@ -13786,6 +14353,14 @@ a:hover { HTTP Request Sequences Secuencias de solicitud HTTP + + E2AP + + + + E2AP Messages + + Decode &As… Decodificar &como… @@ -13846,6 +14421,10 @@ a:hover { Normal Size Tamaño normal + + Reset layout to default size + + Resize Columns Cambiar tamaño de columnas @@ -14104,6 +14683,14 @@ a:hover { Go to the packet referenced by the selected field. + + TLS Keylog Launcher + + + + Release Notes + + &VoIP Calls &Llamadas VoIP @@ -14136,10 +14723,6 @@ a:hover { &GSM &GSM - - &LTE - &LTE - &MTP3 &MTP3 @@ -14424,6 +15007,10 @@ a:hover { Quit without Saving Salir &sin guardar + + USB CDC Data + + There is no "rtp.ssrc" field in this version of Wireshark. diff --git a/ui/qt/wireshark_fr.ts b/ui/qt/wireshark_fr.ts index 13e4d4bc..b16a4c38 100644 --- a/ui/qt/wireshark_fr.ts +++ b/ui/qt/wireshark_fr.ts @@ -29,7 +29,7 @@ Copy to Clipboard - + Copier dans le Presse-papiers Authors @@ -44,8 +44,8 @@ Dossiers - Filter by path - Filtrer par chemin + Search Folders + Plugins @@ -79,6 +79,14 @@ License Licence + + About Logray + + + + Logray + + The directory does not exist Le dossier n'existe pas @@ -731,11 +739,11 @@ …as decimal - + ...en décimal …as octal - + ...en octal …as bits @@ -754,6 +762,28 @@ …comme EBCDIC + + CaptureCommentDialog + + Edit Capture Comments + + + + Add Comment + Ajouter un commentaire + + + Section %1 + Section %1 + + + + CaptureCommentTabWidget + + Comment %1 + + + CaptureFile @@ -839,10 +869,6 @@ Read filter: Filtre de lecture : - - Compress with g&zip - Compresser avec g&zip - Open Capture File Wireshark: Open Capture File @@ -925,8 +951,8 @@ Détails - Capture file comments - Commentaires du fichier de capture + Edit Comments + Refresh @@ -936,10 +962,6 @@ Copy To Clipboard Copier dans le Presse-papiers - - Save Comments - Enregister les commentaires - Capture File Properties Propriétés du fichier de capture @@ -988,10 +1010,18 @@ First packet Premier paquet + + First event + Premier événement + Last packet Dernier paquet + + Last event + Dernier événement + Elapsed Temps écoulé @@ -1028,6 +1058,10 @@ Dropped packets Paquets rejetés + + Dropped events + Événements rejetés + Capture filter Filtre de capture @@ -1040,6 +1074,10 @@ Packet size limit (snaplen) Limite de taille de paquet (snaplen) + + Event size limit (snaplen) + + none aucun @@ -1048,6 +1086,26 @@ %1 bytes %1 octets + + Comments + Commentaires + + + Comment %1: + + + + Decryption Secrets + + + + Type + Type + + + Size + Taille + Statistics Statistiques @@ -1072,6 +1130,10 @@ Packets Paquets + + Events + Événements + Time span, s Temps, s @@ -1084,6 +1146,10 @@ Average packet size, B Taille des paquets moyenne, O + + Average event size, B + + Bytes Octets @@ -1096,14 +1162,14 @@ Average bits/s Débit moyen (bits/s) - - Section Comment - Commentaire de la Section - Packet Comments Commentaires du Paquet + + Event Comments + + <p>Frame %1: <p>Trame %1 : @@ -1116,6 +1182,12 @@ + + Created by Logray %1 + + + + CaptureFilterCombo @@ -1342,6 +1414,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Passe au fichier suivant quand le temps (de l'horloge murale) est un multiple pair de l'intervale indiqué. Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les heures à l'heure. + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>Habituellement, une carte réseau sans-fil ne capture que le trafic émis vers et depuis sa propre adresse réseau, et capture seulement le trafic de <em>données utilisateur</em> avec un &quot;faux&quot; en-tête Ethernet. Si vous voulez capturer tout le trafic que la carte réseau sans-fil peut &quot;voir&quot;, ou êtes intéressés par les paquets de gestion ou de contrôle 802.11, ou les informations de niveau radio, cochez cette option. La disponibilité du mode Moniteur dépend de la carte sans-fil et de son pilote. Consultez le Wiki pour de plus amples détails concernant la capture de paquets sur un réseau WLAN.</p></body></html> + + + Enable monitor mode on all 802.11 interfaces + Activer le mode Moniteur sur toutes les interfaces 802.11 + compression compression @@ -1354,6 +1434,30 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h gzip gzip + + File infix pattern + + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + <html><head/><body><p>Dans le mode fichiers multiples, date et heure ainsi que le numéro d'index du fichier sont insérés entre le nom de fichier et le suffixe. Sélectionnez leur ordre.</p></body></html> + + + YYYYmmDDHHMMSS_NNNNN + + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + <html><head/><body><p>Date et heure avant le numéro d'index du fichier. Ceci force le tri des fichiers par ordre de leur heure de création et garde les fichiers d'un même batch proches.</p></body></html> + + + NNNNN_YYYYmmDDHHMMSS + + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + <html><head/><body><p>Numéro d'index de fichier avant la date et heure. Ceci est l'ordre utilisé historiquement par Wireshark.</p></body></html> + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> <html><head/><body><p>Après basculement de la capture vers le fichier suivant, si le nombre de fichiers indiqué est dépassé, le fichier le plus ancien sera supprimé.</p></body></html> @@ -1444,7 +1548,7 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Stop capturing after the specified number of files have been created. - + Arrête la capture après avoir créé le nombre de fichiers indiqués. <html><head/><body><p>Stop capturing after the specified amount of data has been captured.</p></body></html> @@ -1507,8 +1611,8 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Erreur - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. - Fichiers multiples : la taille demandée est trop élevée. La taille d'un fichier ne doit pas dépasser 2 Gio. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. + Fichier multiples : la taille demandée est trop élevée, elle ne doit pas être supérieure à 2 To. Multiple files: No capture file name given. You must specify a filename if you want to use multiple files. @@ -1537,6 +1641,14 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Capture packets in promiscuous mode Capture de Paquets en mode promiscuous + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>Habituellement, une carte réseau sans-fil ne capture que le trafic émis vers et depuis sa propre adresse réseau, et capture seulement le trafic de <em>données utilisateur</em> avec un &quot;faux&quot; en-tête Ethernet. Si vous voulez capturer tout le trafic que la carte réseau sans-fil peut &quot;voir&quot;, ou êtes intéressés par les paquets de gestion ou de contrôle 802.11, ou les informations de niveau radio, cochez cette option. La disponibilité du mode Moniteur dépend de la carte sans-fil et de son pilote. Consultez le Wiki pour de plus amples détails concernant la capture de paquets sur un réseau WLAN.</p></body></html> + + + Capture packets in monitor mode on 802.11 devices + + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>Paquets de capture dans le nouveau format (pcap-ng) de fichier de capture.</p></body></html> @@ -1555,15 +1667,15 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Interval between updates (ms) - + Intervalle entre les mises à jour (ms) <html><head/><body><p>How often the capture notifies the GUI of new packets. Affects how often the GUI updates and the granularity of timers.</p></body></html> - + <html><head/><body><p>A quelle fréquence la capture informe l'interface graphique pour de nouveaux paquets. Ceci affecte la fréquence de mise à jour de l'interface graphique et la granularité des chronomètres.</p></body></html> <html><head/><body><p>The interval between new packet updates. Affects how often the GUI updates and the granularity of timers.</p></body></html> - + <html><head/><body><p>L'intervalle entre les mises à jours des nouveaux paquets. Ceci affecte la fréquence de mises à jour de l'interface graphique et la granularité des chronomètres.</p></body></html> Don't load interfaces on startup @@ -1764,6 +1876,14 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Resolved Résolu + + Width + + + + Alignment + + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> <html>Afficher des chaînes lisibles par l'homme au lieu de valeurs brutes pour les champs. Applicable uniquement aux colonnes personnalisées avec des champs contenant des chaînes de valeur. @@ -1811,6 +1931,25 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Copier le texte du filtre vers le bloc-notes + + CompressionGroupBox + + Compression options + + + + &Uncompressed + + + + Compress with g&zip + + + + Compress with &LZ4 + + + ConversationDataModel @@ -1877,6 +2016,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Bits/s B Bits/s B + + Flows + + Total Packets Paquets totaux @@ -1992,29 +2135,53 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Copier les octets du paquet sous forme de vidage Hex. - …as Printable Text + …as MIME Data - Copy only the printable text in the packet. + …as C String - …as MIME Data + Copy packet bytes as printable ASCII characters and escape sequences. - …as C String + …as Go literal - Copy packet bytes as printable ASCII characters and escape sequences. + Copy packet bytes as Go literal. + + + + …as C Array + + + + Copy packet bytes as C Array. …as a Hex Stream …sous forme de flux Hex + + …as UTF-8 Text + + + + Copy packet bytes as text, treating as UTF-8. + + + + …as ASCII Text + + + + Copy packet bytes as text, treating as ASCII. + + Copy packet bytes as a stream of hex. Copier les octets du paquet sous forme de flux Hex. @@ -2230,11 +2397,11 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h By default order comparisons and contains/matches/in relations are true if any value matches. The quantifier "all" can be used to apply the test to all values in a frame. - + Par défaut, les comparaisons d'ordre et les relations contains/matches/in sont vraies si l'une des valeurs correspond. Le quantificateur "all" peut être utilisé pour appliquer le test à toutes les valeur de la trame. Quantifier - + Quantificateur Any @@ -2472,11 +2639,11 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Latitude - + Latitude Longitude - + Longitude AS Number @@ -2809,6 +2976,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Display filter: Filtre d'affichage : + + Export PDUs + + ExtArgSelector @@ -2847,10 +3018,6 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Start Démarrer - - Save - Sauvegarder - Default Défaut @@ -2992,6 +3159,14 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Display Filters Filtres d'affichage + + Display Filter Macros + + + + New macro + + Open Ouvrir @@ -3075,10 +3250,18 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h FilterListModel + + Macro Name + + Filter Name Nom du filtre + + Macro Expression + + Filter Expression Expression de filtre @@ -3164,22 +3347,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h FolderListModel - - "File" dialogs - "Fichier" dialogues - - - capture files - capturer des fichiers - Temp Temp - - untitled capture files - fichiers de capture sans titre - Personal configuration Paramétrage personnel @@ -3188,14 +3359,6 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Global configuration Configuration globale - - dfilters, preferences, ethers, … - dfiltres, préférences, éthers, … - - - dfilters, preferences, manuf, … - filtres, préférences, fabrication, … - System Système @@ -3208,18 +3371,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Program Programme - - program files - fichiers de programme - Personal Plugins Plugins personnels - - binary plugins - plugins binaires - Global Plugins Plugins globaux @@ -3236,12 +3391,36 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Lua scripts + + "File" dialog location + + + + Capture files + + + + Untitled capture files + + + + Preferences, profiles, manuf, … + + + + Program files + + + + Binary plugins + + Personal Extcap path Chemin d'accès Extcap personnel - external capture (extcap) plugins + External capture (extcap) plugins @@ -3364,6 +3543,24 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h + + Event %1. + + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + + + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + + + + Click to select. Cliquez pour sélectionner @@ -3396,6 +3593,18 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h %1 stream not found on the selected packet. + + Read activity(%6) + + + + Write activity(%6) + + + + Entire I/O activity (%1) + + Entire conversation (%1) Conversation entière (%1) @@ -3412,10 +3621,6 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Save Stream Content As… Enregistrer le contenu du flux sous… - - [Stream output truncated] - [Sortie du flux tronquée] - %Ln total stream(s). @@ -3443,9 +3648,20 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Astuce. - Show data as - Show and save data as - Afficher les données comme + Show as + Montrer comme + + + No delta times + + + + Turn delta times + + + + All delta times + Stream @@ -3459,11 +3675,22 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Find: Trouver : + + Case sensitive + Sensible à la casse + Find &Next Trouver Suiva&nt + + FollowStreamText + + [Stream output truncated] + + + FontColorPreferencesFrame @@ -3801,30 +4028,29 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h </tbody></table> </body></html> - - Remove this graph. - Remove this dissection behavior. - Enlever ce graphique. - Add a new graph. Ajouter un nouveau graphique. - - Duplicate this graph. - Dupliquer ce graphique. - Clear all graphs. Effacer tous les graphiques. - Move this graph upwards. - + Remove the selected graph(s). + Supprimer le(s) graphe(s) sélectionné(s). - Move this graph downwards. - + Duplicate the selected graph(s). + Dupliquer le(s) graphe(s) sélectionné(s). + + + Move the selected graph(s) upwards. + Déplacer le(s) graphe(s) sélectionné(s) vers le haut. + + + Move the selected graph(s) downwards. + Déplacer le(s) graphe(s) sélectionné(s) vers le bas. Mouse @@ -3860,16 +4086,12 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Automatic update - + Mise à jour automatique Enable legend - - Reset - Réinitialiser - Reset Graph Réinitialiser le Graphique @@ -4083,6 +4305,42 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Copy graphs from another profile. Copier les graphiques d'un autre profil. + + 1 μs + + + + 2 μs + + + + 5 μs + + + + 10 μs + + + + 20 μs + + + + 50 μs + + + + 100 μs + + + + 200 μs + + + + 500 μs + + 1 ms 1 ms @@ -4127,6 +4385,14 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h 5 sec 5 s + + 2 min + 10 min {2 ?} + + + 5 min + 10 min {5 ?} + Wireshark I/O Graphs: %1 Graphiques E/S Wireshark : %1 @@ -4139,6 +4405,14 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Filtered events + + All packets + + + + All events + + All Packets Tous les paquets @@ -4152,7 +4426,7 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h - Access Denied + All Execs @@ -4165,7 +4439,7 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h No events in interval - + Aucun événement dans l’intervalle Click to select packet @@ -4181,7 +4455,7 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Event - Évènement + Événement %1 (%2s%3). @@ -4199,6 +4473,34 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Click to select a portion of the graph. Cliquez pour sélectionner une partie du graphique. + + %1 Intervals + + + + Move to top left + + + + Move to top center + + + + Move to top right + + + + Move to bottom left + + + + Move to bottom center + + + + Move to bottom right + + Portable Document Format (*.pdf) Portable Document Format (*.pdf) @@ -4951,6 +5253,13 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Appliquer les modifications + + InterfaceTreeDelegate + + default + défaut + + InterfaceTreeModel @@ -5906,7 +6215,7 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h <html><head/><body><p>If more than this many rows are displayed, then sorting by columns that require packet dissection will be disabled. Increasing this number increases memory consumption by caching column values.</p></body></html> - + <html><head/><body><p>S'il y a plus de ce nombre de colonnes affichées, alors les tris par colonnes qui requièrent la dissection des paquets sera désactivée. Augmenter ce nombre augmente la mémoire utilisée par le cache de valeurs de colonnes..</body></html> Enable mouse-over colorization @@ -5928,8 +6237,8 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h LteMacStatisticsDialog - LTE Mac Statistics - Statistiques LTE Mac + LTE/NR Mac Statistics + Include SR frames in filter @@ -6232,12 +6541,12 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Numéro de Séquence - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) - Graphique LTE RLC (UE=%1 chan=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) + - LTE RLC Graph - no channel selected - Graphique LTE RLC - aucun canal sélectionné + 3GPP RLC Graph - no channel selected + Save As… @@ -6291,8 +6600,8 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h LteRlcStatisticsDialog - LTE RLC Statistics - Statistiques LTE RLC + 3GPP RLC Statistics + Include SR frames in filter @@ -6377,6 +6686,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Profile: %1 Profil : %1 + + %1 Displayed: %2 (%3%) + + Manage Profiles… Gérer les profils… @@ -6439,6 +6752,13 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h + + %Ln bit(s) + + + + + Byte %1 Octet %1 @@ -6452,9 +6772,12 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Paquet sélectionné : %1 %2 - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 - Paquets : %1 %4 Affichés : %2 (%3%) + Selected Event: %1 %2 + + + + Events: %1 + %1 Selected: %2 (%3%) @@ -6486,12 +6809,16 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Pas de paquets - From Zip File... + No Events + + From Zip File... + à partir d'un fichier Zip... + From Directory... - + à partir d'un répertoire Selected Personal Profile... @@ -6517,6 +6844,13 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h + + MainWindow + + Display filter as %1 + + + MainWindowPreferencesFrame @@ -6548,6 +6882,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h The most recently used folder Le dernier dossier utilisé + + The current working directory + Le répertoire de travail courant + Show up to Afficher @@ -6700,7 +7038,7 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h MAC Address - + Adresse MAC Search vendor name using a case-insentitive regular expression. @@ -6978,6 +7316,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Show Field Values Afficher les valeurs de champ + + Refresh + Rafraîchir + Save Diagram As… Enregistrer le diagramme sous… @@ -7025,6 +7367,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Show packet bytes Afficher les octets du paquet + + Layout: + + Packet %1 Paquet %1 @@ -7042,7 +7388,14 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Octets %1-%2 - %Ln byte(s) + %Ln byte(s) + + + + + + + %Ln bit(s) @@ -7506,10 +7859,22 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Copy this profile. Copier ce profil. + + The number of packets or events to check for automatic profile switching. + + + + Auto switch packet limit + + Configuration Profiles Profils de configuration + + Auto switch event limit + + Import noun @@ -7522,11 +7887,11 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h From Zip File... - + à partir d'un fichier Zip... From Directory... - + à partir d'un répertoire %Ln Selected Personal Profile(s)... @@ -7678,6 +8043,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h deleted supprimé + + Auto Switch Filter + + copy noun @@ -7925,7 +8294,7 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Disable unused protocols - + Désactiver les protocoles non utilisés Disable all protocols but those listed. @@ -7961,7 +8330,7 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Protocols - + Protocoles Disable unused @@ -7981,7 +8350,7 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Unused protocols have been disabled. - + Les protocoles non utilisés ont été désactivés. Protocol changes have been reverted. @@ -8201,6 +8570,14 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Marker missing? Marqueur manquant? + + LTE + + + + NR + + C-RNTI C-RNTI @@ -8221,6 +8598,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h UEId UEId + + RAT + + UL Frames UL Trames @@ -8445,12 +8826,72 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Browse… Parcourir… + + PACKETS + + + + EVENTS + + + + BYTES + + + + BITS + + + + COUNT FRAMES + + + + COUNT FIELDS + + + + SUM + + + + MAX + + + + MIN + + + + AVERAGE + + + + THROUGHPUT + + + + LOAD + + + + Left + Gauche + + + Center + + + + Right + Droite + - QObject::QObject + QObject::QObject::QObject CCCH - CCCH + CCCH @@ -8547,6 +8988,13 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h millisecondes + + ResizeHeaderView + + Resize all %1 to contents + + + ResolvedAddressesDialog @@ -8662,6 +9110,14 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Resolved Addresses Adresses résolues + + Copy + + + + Save as… + Enregistrer sous… + # Resolved addresses found in %1 # Adresses résolues trouvées dans %1 @@ -8675,6 +9131,61 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h # + + ResolvedAddressesView + + as Plain Text + + + + Copy selected rows + + + + Copy table + Copier la table + + + as CSV + + + + as JSON + comme JSON + + + Save selected rows as… + + + + Save table as… + + + + Save Resolved Addresses As… + + + + Plain text (*.txt) + Texte (*.txt) + + + CSV Document (*.csv) + + + + JSON Document (*.json) + + + + Warning + Avertissement + + + Unable to save %1: %2 + + + ResponseTimeDelayDialog @@ -10349,6 +10860,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Packet bytes Taille du paquet + + <b>Options:</b> + + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>Recherche les chaines contenant UTF-8 / ASCII ou UTF-16 caractères.</p></body></html> @@ -10369,6 +10884,18 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Case sensitive Sensible à la casse + + Backwards + + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + <html><head/><body><p>Chercher une autre occurrence dans le paquet courant avant de passer au prochain paquet.</p></body></html> + + + Multiple occurrences + + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10406,6 +10933,22 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Invalid filter. Filtre Invalide. + + Event List + + + + Event Details + + + + Event Bytes + + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + + That filter doesn't test anything. Ce filtre ne teste rien. @@ -10847,6 +11390,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Find: Trouver : + + Case sensitive + Sensible à la casse + Find &Next Rechercher le &suivant @@ -10942,12 +11489,20 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Save as… Enregistrer sous… + + Decoded as %1. + + Save Selected Packet Bytes As… Enregistrer les octets de paquet sélectionnés sous… + + compressed %1 + + - Displaying %Ln byte(s). + Using %Ln byte(s). @@ -11050,6 +11605,10 @@ Pas exemple, inquiquez 1 heure pour avoir un nouveau fichier créé toutes les h Display filter: Filtre d'affichage : + + Strip Headers + Retirer les en-têtes + SupportedProtocolsDialog @@ -11703,23 +12262,23 @@ Changer la direction de la connexion (voir le flux inverse).</p></body& TLSKeylogDialog Dialog - Dialogue + Dialogue Browse… - + Parcourir… Command line - + Ligne de commande Run an application with the SSLKEYLOGFILE environment variable set to the file specified by the TLS key log filename preference. This enables TLS decryption in Wireshark. Set the key log file and start the capture before launching the application to ensure that the initial TLS handshakes are captured. - + Exécutez une application avec la variable d'environnement SSLKEYLOGFILE définie avec le fichier spécifié dans la préférence nom de fichier journal de clé TLS. Cela permet le déchiffrement TLS dans Wireshark. Définissez le fichier d'enregistrement des clés et démarrez la capture avant de lancer l'application afin de vous assurer que les poignées de main TLS initiales sont capturées. <span style=" font-size:small;">Firefox and Chrome are known to work. If your desired browser is currently running, close it first before launching it below. Command line options are supported.</span> - + <span style=" font-size:small;">Firefox et Chrome sont connus pour fonctionner correctement. Si le navigateur de votre choix est actuellement en cours d’exécution, fermez-le d’abord avant de le lancer ci-dessous. Les options de ligne de commande sont prises en charge.</span> TLS (Pre)-Master-Secret log file path (tls.keylog_file) @@ -11727,11 +12286,11 @@ Changer la direction de la connexion (voir le flux inverse).</p></body& <span style=" font-size:small;">TLS session secrets will be logged to this file. If you change this field, hit the Save button to update the TLS protocol preferences.</span> - + <span style=" font-size:small;">Les secrets de session TLS seront enregistrés dans ce fichier. Si vous changez ce champ, cliquez sur le bouton Sauvegarder pour mettre à jour les préférences du protocole TLS.</span> Launch application with SSLKEYLOGFILE - + Démarrez l'application avec SSLKEYLOGFILE Launch @@ -11739,7 +12298,7 @@ Changer la direction de la connexion (voir le flux inverse).</p></body& Save - Sauvegarder + TLS Keylog file @@ -11747,7 +12306,7 @@ Changer la direction de la connexion (voir le flux inverse).</p></body& Program to start with SSLKEYLOGFILE - + Programme à démarrer avec SSLKEYLOGFILE @@ -11867,7 +12426,7 @@ Changer la direction de la connexion (voir le flux inverse).</p></body& Time shifting is not available while capturing packets. - + Le décalage de temps n'est pas disponible pendant la capture de paquet. @@ -12024,22 +12583,20 @@ Changer la direction de la connexion (voir le flux inverse).</p></body& Créer une nouvelle entrée - Remove this entry. - Remove this profile. - Supprimer cette entrée. + Remove the selected entry(ies). + Supprimer les entrées sélectionnées. - Copy this entry. - Copy this profile. - Copier cette entrée. + Copy the selected entry(ies). + Copier les entrées sélectionnées. - Move entry up. - Déplacer l'entrée vers le haut. + Move the selected entry(ies) up. + Déplacer les entrées sélectionnées vers le haut. - Move entry down. - Déplacer l'entrée vers le bas. + Move the selected entry(ies) down. + Déplacer les entrées sélectionnées vers le bas. Clear all entries. @@ -12065,20 +12622,20 @@ Changer la direction de la connexion (voir le flux inverse).</p></body& Créer une nouvelle entrée. - Remove this entry. - Supprimer cette entrée. + Remove the selected entry(ies). + Supprimer les entrées sélectionnées. - Copy this entry. - Copier cette entrée. + Copy the selected entry(ies). + Copier les entrées sélectionnées. - Move entry up. - Déplacer l'entrée vers le haut. + Move the selected entry(ies) up. + Déplacer les entrées sélectionnées vers le haut. - Move entry down. - Déplacer l'entrée vers le bas. + Move the selected entry(ies) down. + Déplacer les entrées sélectionnées vers le bas. Clear all entries. @@ -12406,10 +12963,18 @@ a:hover { You are sniffing the glue that holds the Internet together using Wireshark Vous reniflez la colle qui maintient Internet ensemble à l'aide de Wireshark + + You are sniffing the glue that holds your system together using Logray + + You are running Wireshark Vous exécutez Wireshark + + You are running Logray + + You receive automatic updates. Vous recevez les mises à jour automatiques. @@ -12686,14 +13251,6 @@ a:hover { No files found Pas de fichier trouvé - - &Contents - &Aide - - - Wireshark Filter - Filtre Wireshark - TShark TShark @@ -12959,10 +13516,6 @@ a:hover { Wireless Toolbar Barre d'outils Wireless - - Help contents - Contenu de l'aide - FAQs FAQ @@ -13083,11 +13636,6 @@ a:hover { Find the previous packet Trouver le paquet précédent - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - &Marquer/Démarquer le(s) paquet(s) - Mark All Displayed Marquer tout comme Affichées @@ -13116,11 +13664,6 @@ a:hover { Go to the previous marked packet Aller au paquet précédent marqué - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - &Ignorer/Annuler le(s) paquet(s) - Ignore All Displayed Ignorer tous les affichés @@ -13561,33 +14104,29 @@ a:hover { Reset Layout Réinitialiser la mise en page - - Reset appearance layout to default size - Réinitialiser la disposition de l'apparence à la taille par défaut - Seconds Since First Captured Packet Secondes depuis le premier paquet capturé Show packet times as the seconds since the first captured packet. - + Afficher les temps paquets en secondes depuis le premier paquet capturé. Tenths of a millisecond - + Dixièmes de millisecondes Hundredths of a millisecond - + Centièmes de millisecondes Tenths of a microsecond - + Dixièmes de microsecondes Hundredths of a microsecond - + Centièmes de microsecondes Packet &Diagram @@ -13726,20 +14265,28 @@ a:hover { - TLS Keylog Launcher + &Options… + &Options... + + + &3GPP Uu - Release Notes + &Wireless + &Wireless + + + &User's Guide - &Options… - &Options... + Wireshark User's Guide + Manuel utilisateur Wireshark - &Wireless - &Wireless + Display Filters + Filtres d'affichage Capture &Filters… @@ -13785,10 +14332,18 @@ a:hover { Find Pre&vious Trouver Pré&cédent + + &Mark/Unmark Selected + + Mark or unmark each selected packet Marquer ou décocher chaque paquet sélectionné + + &Ignore/Unignore Selected + + Ignore or unignore each selected packet Ignorer ou désignorer chaque paquet sélectionné @@ -13829,6 +14384,18 @@ a:hover { TCP throughput Débit TCP + + General + + + + Query-Response + + + + DNS Query-Response Statistics + + Request Sequences Séquences de requêtes @@ -13837,6 +14404,14 @@ a:hover { HTTP Request Sequences Séquences de requête HTTP + + E2AP + + + + E2AP Messages + + Decode &As… Décoder &Comme... @@ -13897,6 +14472,10 @@ a:hover { Normal Size Taille Normale + + Reset layout to default size + + Resize Columns Redimensionner les Colonnes @@ -14155,6 +14734,14 @@ a:hover { Go to the packet referenced by the selected field. Aller au paquet référencé par le champ sélectionné. + + TLS Keylog Launcher + + + + Release Notes + Notes de version + &VoIP Calls &Appels VoIP @@ -14187,10 +14774,6 @@ a:hover { &GSM &GSM - - &LTE - &LTE - &MTP3 &MTP3 @@ -14475,6 +15058,10 @@ a:hover { Quit without Saving Quitter &sans enregistrer + + USB CDC Data + + There is no "rtp.ssrc" field in this version of Wireshark. Il n'y a pas de "rtp.ssrc" champ dans cette version de Wireshark. @@ -14625,7 +15212,7 @@ a:hover { before updating - + avant de mettre à jour There are no TLS Session Keys to save. @@ -14648,11 +15235,11 @@ a:hover { There are no available secrets used to decrypt TLS traffic in the capture file. Would you like to view information about how to decrypt TLS traffic on the wiki? - + Il n’existe aucun secret disponible utilisé pour déchiffrer le trafic TLS dans le fichier de capture. Souhaitez-vous consulter des informations sur la façon de déchiffrer le trafic TLS sur le wiki ? Are you sure you want to discard all decryption secrets? - + Voulez-vous vraiment supprimer tous les secrets pour le déchiffrement ? No filter available. Try another %1. diff --git a/ui/qt/wireshark_it.ts b/ui/qt/wireshark_it.ts index 40167e06..3a84fd06 100644 --- a/ui/qt/wireshark_it.ts +++ b/ui/qt/wireshark_it.ts @@ -44,8 +44,8 @@ Cartelle - Filter by path - Filtro per percorso + Search Folders + Cerca cartelle Plugins @@ -79,6 +79,14 @@ License Licenza + + About Logray + Informazioni su Logray + + + Logray + Logray + The directory does not exist La cartella non esiste @@ -754,6 +762,28 @@ …come EBCDIC + + CaptureCommentDialog + + Edit Capture Comments + Modifica commento della cattura + + + Add Comment + Aggiungi commento + + + Section %1 + Sezione %1 + + + + CaptureCommentTabWidget + + Comment %1 + Commento %1 + + CaptureFile @@ -862,10 +892,6 @@ Read filter: Filtro di lettura: - - Compress with g&zip - Comprimi con g&zip - Open Capture File Wireshark: Open Capture File @@ -948,8 +974,8 @@ Dettagli - Capture file comments - Commenti del file di cattura + Edit Comments + Modifica commenti Refresh @@ -959,10 +985,6 @@ Copy To Clipboard Copia negli appunti - - Save Comments - Salva i commenti - Capture File Properties Proprietà del file di cattura @@ -1011,10 +1033,18 @@ First packet Primo pacchetto + + First event + Primo evento + Last packet Ultimo pacchetto + + Last event + Ultimo evento + Elapsed Trascorso @@ -1051,6 +1081,10 @@ Dropped packets Pacchetti persi + + Dropped events + Eventi scartati + Capture filter Filtro di cattura @@ -1063,6 +1097,10 @@ Packet size limit (snaplen) Dimensione limite del pacchetto (snaplen) + + Event size limit (snaplen) + Limite dimensione degli eventi (snaplen) + none nessuno @@ -1071,6 +1109,26 @@ %1 bytes %1 byte + + Comments + Commenti + + + Comment %1: + Commento %1: + + + Decryption Secrets + Segreti di decifratura + + + Type + Tipo + + + Size + Dimensione + Statistics Statistiche @@ -1095,6 +1153,10 @@ Packets Pacchetti + + Events + Eventi + Time span, s Tempo, s @@ -1107,6 +1169,10 @@ Average packet size, B Dimensione media dei pacchetti, B + + Average event size, B + Dimensione media degli eventi, B + Bytes Byte @@ -1119,14 +1185,14 @@ Average bits/s Bit/s medi - - Section Comment - Commento sezione - Packet Comments Commenti pacchetto + + Event Comments + Commenti evento + <p>Frame %1: <p>Frame %1: @@ -1137,6 +1203,14 @@ Creato da Wireshark %1 + + + + Created by Logray %1 + + + Creato da Logray %1 + @@ -1365,6 +1439,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Passa al file successivo quando l'ora (orologio a muro) è un multiplo pari dell'intervallo specificato. Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>Di solito una scheda di rete wireless catturerà solo il traffico inviato e ricevuto dal suo indirizzo di rete e catturerà solo il traffico <em>dati dell'utente</em> con intestazioni Ethernet &quot;fittizie&quot;. Se desideri catturare tutto il traffico che transita sulle schede di rete wireless o sei interessato ai pacchetti di gestione o di controllo 802.11, o alle informazioni del livello radio, seleziona questa opzione. La disponibilità della modalità di monitoraggio dipende dalla scheda di rete wireless e dal driver. Consulta il Wiki per ulteriori dettagli sulla cattura dei pacchetti nelle reti WLAN.</p></body></html> + + + Enable monitor mode on all 802.11 interfaces + Abilita la modalità monitor su tutte le interfacce 802.11 + compression compressione @@ -1377,6 +1459,30 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.gzip gzip + + File infix pattern + Modello di infisso dei file + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + <html><head/><body><p>In modalità file multipli, la data e l'ora e il numero di indice del file sono inseriti tra il modello del nome del file e qualsiasi suffisso. Seleziona il loro ordine.</p></body></html> + + + YYYYmmDDHHMMSS_NNNNN + AAAAmmGGHHMMSS_NNNNN + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + <html><head/><body><p>Data e ora prima del numero di indice del file. Ciò fa sì che i file vengano ordinati in base all'ora di creazione e mantiene i file dello stesso lotto ordinati in modo stretto.</p></body></html> + + + NNNNN_YYYYmmDDHHMMSS + NNNNN_AAAAmmGGHHMMSS + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + <html><head/><body><p>Numero di indice del file prima della data e dell'ora. Questo è l'ordinamento storico di Wireshark.</p></body></html> + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> <html><head/><body><p>Dopo che la cattura è passata al file successivo e il numero di file prescelto è stato superato, il file più vecchio sarà rimosso.</p></body></html> @@ -1459,7 +1565,7 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. Stop capturing after the specified number of packets have been captured. - Ferma la cattura dopo che un certo numero di pacchetti è stato catturato. + Ferma la cattura dopo che il numero di pacchetti specificato è stato catturato. <html><head/><body><p>Stop capturing after the specified number of files have been created.</p></body></html> @@ -1471,15 +1577,15 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. <html><head/><body><p>Stop capturing after the specified amount of data has been captured.</p></body></html> - <html><head/><body><p>Ferma la cattura dopo che una certa quantità di dati è stata catturata.</p></body></html> + <html><head/><body><p>Ferma la cattura dopo che la quantità di dati specificata è stata catturata.</p></body></html> Stop capturing after the specified amount of data has been captured. - Ferma la cattura dopo che una certa quantità di dati è stata catturata. + Ferma la cattura dopo che la quantità di dati specificata è stata catturata. Stop capturing after the specified amount of time has passed. - Ferma la cattura dopo che la quantità di tempo specificato è trascorsa. + Ferma la cattura dopo che la quantità di tempo specificata è trascorsa. <html><head/><body><p>Optionally specify a temporary directory for unnamed capture files.</p></body></html> @@ -1530,8 +1636,8 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Errore - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. - File multipli: la dimensione del file richiesta è troppo grande. La dimensione del file non può essere superiore a 2 GiB. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. + File multipli: la dimensione del file richiesta è troppo grande. La dimensione del file non può essere superiore a 2 TB. Multiple files: No capture file name given. You must specify a filename if you want to use multiple files. @@ -1560,6 +1666,14 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Capture packets in promiscuous mode Cattura i pacchetti in modalità promiscua + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>Di solito una scheda di rete wireless catturerà solo il traffico inviato e ricevuto dal suo indirizzo di rete e catturerà solo il traffico <em>dati dell'utente</em> con intestazioni Ethernet &quot;fittizie&quot;. Se desideri catturare tutto il traffico che transita sulle schede di rete wireless o sei interessato ai pacchetti di gestione o di controllo 802.11, o alle informazioni del livello radio, seleziona questa opzione. La disponibilità della modalità di monitoraggio dipende dalla scheda di rete wireless e dal driver. Consulta il Wiki per ulteriori dettagli sulla cattura dei pacchetti nelle reti WLAN.</p></body></html> + + + Capture packets in monitor mode on 802.11 devices + Cattura i pacchetti in modalità monitor sui dispositivi 802.11 + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>Cattura i pacchetti nel formato di file di nuova generazione.</p></body></html> @@ -1582,11 +1696,11 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. <html><head/><body><p>How often the capture notifies the GUI of new packets. Affects how often the GUI updates and the granularity of timers.</p></body></html> - <html><head/><body><p>La frequenza con cui l'acquisizione notifica alla GUI i nuovi pacchetti. Influisce sulla frequenza degli aggiornamenti della GUI e sulla granularità dei timer.</p></body></html> + <html><head/><body><p>La frequenza con cui l'acquisizione notifica all'interfaccia grafica i nuovi pacchetti. Influisce sulla frequenza degli aggiornamenti dell'interfaccia e sulla granularità dei timer.</p></body></html> <html><head/><body><p>The interval between new packet updates. Affects how often the GUI updates and the granularity of timers.</p></body></html> - <html><head/><body><p>L'intervallo tra gli aggiornamenti dei nuovi pacchetti. Influisce sulla frequenza degli aggiornamenti della GUI e sulla granularità dei timer.</p></body></html> + <html><head/><body><p>L'intervallo tra gli aggiornamenti dei nuovi pacchetti. Influisce sulla frequenza degli aggiornamenti dell'interfaccia grafica e sulla granularità dei timer.</p></body></html> Don't load interfaces on startup @@ -1787,6 +1901,14 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Resolved Risolto + + Width + Larghezza + + + Alignment + Allineamento + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> <html>Mostra stringhe comprensibili invece che i valori grezzi dei campi. Applicabile solo alle colonne personalizzate con campi che hanno stringhe con valori.</html> @@ -1834,6 +1956,25 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Copia il testo del filtro negli appunti. + + CompressionGroupBox + + Compression options + Opzioni di compressione + + + &Uncompressed + &Non compresso + + + Compress with g&zip + Comprimi con g&zip + + + Compress with &LZ4 + Comprimi con &LZ4 + + ConversationDataModel @@ -1900,6 +2041,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Bits/s B Bit/s B + + Flows + Flussi + Total Packets Pacchetti totali @@ -2014,14 +2159,6 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Copy packet bytes as a hex dump. Copia i byte del pacchetto come un dump esadecimale. - - …as Printable Text - ...come testo stampabile - - - Copy only the printable text in the packet. - Copia solo il testo stampabile nel pacchetto. - …as MIME Data …come dati MIME @@ -2034,10 +2171,42 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Copy packet bytes as printable ASCII characters and escape sequences. Copia i byte dei pacchetti come caratteri ASCII stampabili e sequenze di escape. + + …as Go literal + …come Go letterale + + + Copy packet bytes as Go literal. + Copia i byte del pacchetto come Go letterale. + + + …as C Array + ...come Array C + + + Copy packet bytes as C Array. + Copia i byte del pacchetto come Array C. + …as a Hex Stream ...come un flusso esadecimale + + …as UTF-8 Text + …come testo UTF-8 + + + Copy packet bytes as text, treating as UTF-8. + Copia i byte del pacchetto come testo, trattandolo come UTF-8. + + + …as ASCII Text + …come testo ASCII + + + Copy packet bytes as text, treating as ASCII. + Copia i byte del pacchetto come testo, trattandolo come ASCII. + Copy packet bytes as a stream of hex. Copia i byte del pacchetto come un flusso esadecimale. @@ -2834,6 +3003,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Display filter: Filtro di visualizzazione: + + Export PDUs + Esporta PDU + ExtArgSelector @@ -2872,10 +3045,6 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Start Avvia - - Save - Salva - Default Predefinito @@ -3017,6 +3186,14 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Display Filters Filtri di visualizzazione + + Display Filter Macros + Visualizza macro dei filtri + + + New macro + Nuova macro + Open Apri @@ -3100,10 +3277,18 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. FilterListModel + + Macro Name + Nome macro + Filter Name Nome filtro + + Macro Expression + Espressione macro + Filter Expression Espressione del filtro @@ -3189,22 +3374,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. FolderListModel - - "File" dialogs - Finestre "File" - - - capture files - file di cattura - Temp Temporanei - - untitled capture files - file di cattura senza titolo - Personal configuration Configurazione personale @@ -3213,14 +3386,6 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Global configuration Configurazione globale - - dfilters, preferences, ethers, … - dfilters, preferences, ethers, - - - dfilters, preferences, manuf, … - dfilters, preferences, manuf, - System Sistema @@ -3233,18 +3398,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Program Programma - - program files - file di programma - Personal Plugins Plugin personali - - binary plugins - plugin binari - Global Plugins Plugin globali @@ -3261,13 +3418,37 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Lua scripts Script Lua + + "File" dialog location + Posizione finestra "File" + + + Capture files + File di cattura + + + Untitled capture files + File di cattura senza titolo + + + Preferences, profiles, manuf, … + Preferenze, profili, prod, … + + + Program files + File di programma + + + Binary plugins + Plugin binari + Personal Extcap path Percorso Extcap personale - external capture (extcap) plugins - estensioni di cattura esterna (extcap) + External capture (extcap) plugins + Plugin di cattura esterna (extcap) Global Extcap path @@ -3403,6 +3584,24 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.%Ln turni. + + Event %1. + Evento %1. + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + %Ln <span style="color: %1; background-color:%2">scrittura</span>, + %Ln <span style="color: %1; background-color:%2">scritture</span>, + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + %Ln <span style="color: %1; background-color:%2">scritture</span>, + %Ln <span style="color: %1; background-color:%2">scritture</span>, + + Click to select. Fai clic per selezionare. @@ -3435,6 +3634,18 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.%1 stream not found on the selected packet. Flussi %1 non trovati nel pacchetto selezionato. + + Read activity(%6) + Attività di lettura(%6) + + + Write activity(%6) + Attività di scrittura(%6) + + + Entire I/O activity (%1) + Intera attività I/O (%1) + Entire conversation (%1) Conversazione intera (%1) @@ -3451,10 +3662,6 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Save Stream Content As… Salva il contenuto del flusso come... - - [Stream output truncated] - [Flusso di output troncato] - %Ln total stream(s). @@ -3482,9 +3689,20 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Suggerimento. - Show data as - Show and save data as - Mostra dati come + Show as + Mostra come + + + No delta times + Nessun delta dei tempi + + + Turn delta times + Attiva i delta dei tempi + + + All delta times + Tutti i delta dei tempi Stream @@ -3498,11 +3716,22 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Find: Trova: + + Case sensitive + Distingui maiuscole + Find &Next Trova &successivo + + FollowStreamText + + [Stream output truncated] + [Flusso di uscita troncato] + + FontColorPreferencesFrame @@ -3838,29 +4067,28 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. - - Remove this graph. - Remove this dissection behavior. - Rimuovi questo grafico. - Add a new graph. Aggiungi un nuovo grafico. - - Duplicate this graph. - Duplica questo grafico. - Clear all graphs. Cancella tutti i grafici. - Move this graph upwards. - Sposta questo grafico verso l'alto. + Remove the selected graph(s). + Rimuovi i grafici selezionati. + + + Duplicate the selected graph(s). + Duplica i grafici selezionati. + + + Move the selected graph(s) upwards. + Sposta i grafici selezionati in alto. - Move this graph downwards. + Move the selected graph(s) downwards. Sposta questo grafico verso il basso. @@ -3873,7 +4101,7 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. drags - trascinamenti + trascina Select using the mouse button. @@ -3881,7 +4109,7 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. zooms - zoom + ingrandisce Interval @@ -3903,10 +4131,6 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Enable legend Abilita la legenda - - Reset - Ripristina - Reset Graph Ripristina il grafico @@ -4120,6 +4344,42 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Copy graphs from another profile. Copia grafici da un altro profilo. + + 1 μs + 1 μs + + + 2 μs + 2 μs + + + 5 μs + 5 μs + + + 10 μs + 10 μs + + + 20 μs + 20 μs + + + 50 μs + 50 μs + + + 100 μs + 100 μs + + + 200 μs + 200 μs + + + 500 μs + 500 μs + 1 ms 1 ms @@ -4164,6 +4424,14 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.5 sec 5 sec + + 2 min + 2 min + + + 5 min + 5 min + Wireshark I/O Graphs: %1 Grafici di I/O di Wireshark: %1 @@ -4176,6 +4444,14 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Filtered events Eventi filtrati + + All packets + Tutti i pacchetti + + + All events + Tutti gli eventi + All Packets Tutti i pacchetti @@ -4189,8 +4465,8 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Tutti gli eventi - Access Denied - Accesso negato + All Execs + Tutti gli eseguibili Hover over the graph for details. @@ -4236,6 +4512,34 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Click to select a portion of the graph. Fai clic per selezionare una porzione del grafico. + + %1 Intervals + %1 intervalli + + + Move to top left + Sposta in alto a sinistra + + + Move to top center + Sposta in alto al centro + + + Move to top right + Sposta in alto a destra + + + Move to bottom left + Sposta in basso a sinistra + + + Move to bottom center + Sposta in basso al centro + + + Move to bottom right + Sposta in basso a destra + Portable Document Format (*.pdf) Portable Document Format (*.pdf) @@ -4988,6 +5292,13 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Applica modifiche + + InterfaceTreeDelegate + + default + predefinito + + InterfaceTreeModel @@ -5923,7 +6234,7 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. Packet List settings: - Impostazioni elenco dei pacchetti: + Impostazioni elenco pacchetti: Show packet separator @@ -5965,8 +6276,8 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. LteMacStatisticsDialog - LTE Mac Statistics - Statistiche Mac LTE + LTE/NR Mac Statistics + Statistiche Mac LTE/NR Include SR frames in filter @@ -6051,7 +6362,7 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. drags - trascinamenti + trascina Select using the mouse button. @@ -6059,7 +6370,7 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. zooms - ingrandimenti + ingrandisce <html><head/><body><p>Reset the graph to its initial state.</p></body></html> @@ -6270,12 +6581,12 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Numero di sequenza - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) - Grafico RLC LTE (UE=%1 can=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) + Grafico RLC %1 (UE=%2 can=%3%4 %5 - %6) - LTE RLC Graph - no channel selected - Grafico RLC LTE - nessun canale selezionato + 3GPP RLC Graph - no channel selected + Grafico 3GPP RLC LTE - nessun canale selezionato Save As… @@ -6329,8 +6640,8 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. LteRlcStatisticsDialog - LTE RLC Statistics - Statistiche RLC LTE + 3GPP RLC Statistics + Statistiche 3GPP RLC Include SR frames in filter @@ -6415,6 +6726,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Profile: %1 Profilo: %1 + + %1 Displayed: %2 (%3%) + %1 visualizzati: %2 (%3%) + Manage Profiles… Gestisci i profili... @@ -6477,6 +6792,13 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.%Ln byte + + %Ln bit(s) + + %Ln bit + %Ln bit + + Byte %1 Byte %1 @@ -6490,9 +6812,12 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Pacchetto selezionato: %1 %2 - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 - Pacchetti: %1 %4 visualizzati: %2 (%3%) + Selected Event: %1 %2 + Evento selezionato: %1 %2 + + + Events: %1 + Eventi: %1 %1 Selected: %2 (%3%) @@ -6523,6 +6848,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.No Packets Nessun pacchetto + + No Events + Nessun evento + From Zip File... Da file Zip... @@ -6555,6 +6884,13 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. + + MainWindow + + Display filter as %1 + Filtro di visualizzazione come %1 + + MainWindowPreferencesFrame @@ -6586,6 +6922,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.The most recently used folder La cartella usata più di recente + + The current working directory + La cartella di lavoro attuale + Show up to Mostra fino a @@ -6742,7 +7082,7 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. Search vendor name using a case-insentitive regular expression. - Cerca il nome del fornitore utilizzando un'espressione regolare senza distinzione tra maiuscole e minuscole. + Cerca il nome del produttore utilizzando un'espressione regolare senza distinzione tra maiuscole e minuscole. Vendor Name @@ -7016,6 +7356,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Show Field Values Mostra i valori dei campi + + Refresh + Aggiorna + Save Diagram As… Salva diagramma come... @@ -7063,6 +7407,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Show packet bytes Mostra byte del pacchetto + + Layout: + Disposizione: + Packet %1 Pacchetto %1 @@ -7086,6 +7434,13 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.%Ln byte + + %Ln bit(s) + + %Ln bit + %Ln bit + + PacketFormatGroupBox @@ -7295,7 +7650,7 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. Also include packets depended upon, such as those used to reassemble displayed packets - Includi anche i pacchetti di dipendenza, come quelli utilizzati per riassemblare i pacchetti visualizzati + Includi anche i pacchetti di dipendenza, come quelli utilizzati per ri-assemblare i pacchetti visualizzati First &to last marked @@ -7544,10 +7899,22 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Copy this profile. Copia questo profilo. + + The number of packets or events to check for automatic profile switching. + Il numero di pacchetti o eventi da verificare per la commutazione automatica del profilo. + + + Auto switch packet limit + Limite pacchetti per commutazione automatica + Configuration Profiles Profili di configurazione + + Auto switch event limit + Limite eventi per commutazione automatica + Import noun @@ -7730,6 +8097,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.deleted eliminato + + Auto Switch Filter + Cambio automatico del filtro + copy noun @@ -8253,6 +8624,14 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Marker missing? Marcatore mancante? + + LTE + LTE + + + NR + NR + C-RNTI C-RNTI @@ -8273,6 +8652,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.UEId UEId + + RAT + RAT + UL Frames UL Frame @@ -8497,9 +8880,69 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Browse… Sfoglia... + + PACKETS + PACCHETTI + + + EVENTS + EVENTI + + + BYTES + BYTE + + + BITS + BIT + + + COUNT FRAMES + NUMERO FRAME + + + COUNT FIELDS + NUMERO CAMPI + + + SUM + SOMMA + + + MAX + MAX + + + MIN + MIN + + + AVERAGE + MEDIA + + + THROUGHPUT + THROUGHPUT + + + LOAD + CARICO + + + Left + Sinistra + + + Center + Centro + + + Right + Destra + - QObject::QObject + QObject::QObject::QObject CCCH CCCH @@ -8599,6 +9042,13 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.millisecondi + + ResizeHeaderView + + Resize all %1 to contents + Ridimensiona tutte le %1 al contenuto + + ResolvedAddressesDialog @@ -8714,6 +9164,14 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Resolved Addresses Indirizzi risolti + + Copy + Copia + + + Save as… + Salva come... + # Resolved addresses found in %1 # Trovati indirizzi risolti in %1 @@ -8727,6 +9185,61 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. + + ResolvedAddressesView + + as Plain Text + come testo semplice + + + Copy selected rows + Copia le righe selezionate + + + Copy table + Copia la tabella + + + as CSV + come CSV + + + as JSON + come JSON + + + Save selected rows as… + Salva le righe selezionate come... + + + Save table as… + Salva la tabella come... + + + Save Resolved Addresses As… + Salva gli indirizzi risolti come... + + + Plain text (*.txt) + Testo semplice (*.txt) + + + CSV Document (*.csv) + Documento CSV (*.csv) + + + JSON Document (*.json) + Documento JSON (*.json) + + + Warning + Avviso + + + Unable to save %1: %2 + Impossibile salvare %1: %2 + + ResponseTimeDelayDialog @@ -10401,6 +10914,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Packet bytes Byte del pacchetto + + <b>Options:</b> + <b>Opzioni:</b> + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>Cerca le stringhe che contengono i caratteri ridotti (UTF-8 e ASCII) o allargati (UTF-16).</p></body></html> @@ -10421,6 +10938,18 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Case sensitive Distingui maiuscole + + Backwards + Indietro + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + <html><head/><body><p>Cerca un'occorrenza successiva nel pacchetto corrente prima di passare al pacchetto successivo.</p></body></html> + + + Multiple occurrences + Occorrenze multiple + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10458,6 +10987,22 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Invalid filter. Filtro non valido. + + Event List + Elenco eventi + + + Event Details + Dettagli evento + + + Event Bytes + Byte evento + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + <html><head/><body><p> Cerca nella colonna Info dell'elenco degli eventi (pannello di riepilogo), etichette di visualizzazione degli eventi decodificati (pannello della vista ad albero) o i dati dell'evento convertiti in ASCII (pannello della vista esadecimale).</p></body></html> + That filter doesn't test anything. Il filtro non verifica niente. @@ -10901,6 +11446,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Find: Trova: + + Case sensitive + Distingui maiuscole + Find &Next Trova &successivo @@ -10996,15 +11545,23 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Save as… Salva come... + + Decoded as %1. + Decodificato come %1. + Save Selected Packet Bytes As… Salva byte del pacchetto selezionato come... + + compressed %1 + compressi %1 + - Displaying %Ln byte(s). + Using %Ln byte(s). - Visualizzazione di %Ln byte. - Visualizzazione di %Ln byte. + Utilizzo di %Ln byte. + Utilizzo di %Ln byte. @@ -11104,6 +11661,10 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Display filter: Filtro di visualizzazione: + + Strip Headers + Rimuovi intestazioni + SupportedProtocolsDialog @@ -11328,7 +11889,7 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. drags - trascinamenti + trascina Select using the mouse button. @@ -11336,7 +11897,7 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. zooms - zoom + ingrandisce Display Round Trip Time vs Sequence Number @@ -11915,7 +12476,7 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora. Time shifting is not available while capturing packets. - Il spostamento temporale non è disponibile durante l'acquisizione dei pacchetti. + Lo spostamento temporale non è disponibile durante la cattura dei pacchetti. @@ -12072,22 +12633,20 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Crea una nuova voce. - Remove this entry. - Remove this profile. - Rimuovi questa voce. + Remove the selected entry(ies). + Rimuovi le voci selezionate. - Copy this entry. - Copy this profile. - Copia questa voce. + Copy the selected entry(ies). + Copia le voci selezionate. - Move entry up. - Sposta su la voce. + Move the selected entry(ies) up. + Sposta le voci selezionate in alto. - Move entry down. - Sposta giù la voce. + Move the selected entry(ies) down. + Sposta le voci selezionate in basso. Clear all entries. @@ -12113,20 +12672,20 @@ Ad esempio, usa 1 ora per fare in modo che un nuovo file sia creato ogni ora.Crea una nuova voce. - Remove this entry. - Rimuovi questa voce. + Remove the selected entry(ies). + Rimuovi le voci selezionate. - Copy this entry. - Copia questa voce. + Copy the selected entry(ies). + Copia le voci selezionate. - Move entry up. - Sposta su la voce. + Move the selected entry(ies) up. + Sposta le voci selezionate in alto. - Move entry down. - Sposta giù la voce. + Move the selected entry(ies) down. + Sposta le voci selezionate in basso. Clear all entries. @@ -12496,10 +13055,18 @@ a:hover { You are sniffing the glue that holds the Internet together using Wireshark Stai annusando la colla che tiene insieme Internet con Wireshark + + You are sniffing the glue that holds your system together using Logray + Questo è il collante che tiene insieme il tuo sistema usando Logray + You are running Wireshark Stai eseguendo Wireshark + + You are running Logray + Stai eseguendo Logray + You receive automatic updates. Ricevi aggiornamenti automatici. @@ -12776,14 +13343,6 @@ a:hover { No files found File non trovati - - &Contents - &Contenuti - - - Wireshark Filter - Filtro di Wireshark - TShark TShark @@ -13049,10 +13608,6 @@ a:hover { Wireless Toolbar Barra degli strumenti wireless - - Help contents - Contenuti della guida - FAQs FAQ @@ -13173,11 +13728,6 @@ a:hover { Find the previous packet Vai al pacchetto precedente - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - &Marca/Deseleziona pacchetto - Mark All Displayed Marca tutti i visualizzati @@ -13206,11 +13756,6 @@ a:hover { Go to the previous marked packet Val al prossimo pacchetto marchiato - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - &Ignora/Considera pacchetto - Ignore All Displayed Ignora tutti i visualizzati @@ -13651,10 +14196,6 @@ a:hover { Reset Layout Ripristina disposizione - - Reset appearance layout to default size - Ripristina la disposizione dell'aspetto alla dimensione predefinita - Seconds Since First Captured Packet Secondi dal primo pacchetto catturato @@ -13815,22 +14356,30 @@ a:hover { MAC Address Blocks Blocchi di indirizzi MAC - - TLS Keylog Launcher - Esecutore Keylog TLS - - - Release Notes - Note di rilascio - &Options… &Opzioni... + + &3GPP Uu + &3GPP Uu + &Wireless &Wireless + + &User's Guide + Manuale &utente + + + Wireshark User's Guide + Manuale utente di Wireshark + + + Display Filters + Filtri di visualizzazione + Capture &Filters… &Filtri di cattura... @@ -13875,10 +14424,18 @@ a:hover { Find Pre&vious Tro&va precedente + + &Mark/Unmark Selected + &Marca/Deseleziona selezionati + Mark or unmark each selected packet Marca o rimuovi ogni pacchetto selezionato + + &Ignore/Unignore Selected + &Ignora/considera selezionati + Ignore or unignore each selected packet Ignora o considera ogni pacchetto selezionato @@ -13919,6 +14476,18 @@ a:hover { TCP throughput Throughput TCP + + General + Generale + + + Query-Response + Query-Risposta + + + DNS Query-Response Statistics + Statistiche Query-Risposta DNS + Request Sequences Sequenze richiesta @@ -13927,6 +14496,14 @@ a:hover { HTTP Request Sequences Sequenze richiesta HTTP + + E2AP + E2AP + + + E2AP Messages + Messaggi E2AP + Decode &As… Decodific&a come... @@ -13987,6 +14564,10 @@ a:hover { Normal Size Dimensione normale + + Reset layout to default size + Ripristina la disposizione alla dimensione predefinita + Resize Columns Ridimensiona colonne @@ -14245,6 +14826,14 @@ a:hover { Go to the packet referenced by the selected field. Vai al pacchetto referenziato dal campo selezionato. + + TLS Keylog Launcher + Esecutore Keylog TLS + + + Release Notes + Note di rilascio + &VoIP Calls Chiamate &VoIP @@ -14277,10 +14866,6 @@ a:hover { &GSM &GSM - - &LTE - &LTE - &MTP3 &MTP3 @@ -14565,6 +15150,10 @@ a:hover { Quit without Saving Esci senza sal&vare + + USB CDC Data + Dati USB CDC + There is no "rtp.ssrc" field in this version of Wireshark. Non c'è alcun campo "rtp.ssrc" in questa versione di Wireshark. diff --git a/ui/qt/wireshark_ja_JP.ts b/ui/qt/wireshark_ja_JP.ts index 631db5c4..013ad12c 100644 --- a/ui/qt/wireshark_ja_JP.ts +++ b/ui/qt/wireshark_ja_JP.ts @@ -44,8 +44,8 @@ フォルダ - Filter by path - パスでフィルタ + Search Folders + フォルダを検索 Plugins @@ -79,6 +79,14 @@ License ライセンス + + About Logray + Lograyについて + + + Logray + Logray + The directory does not exist ディレクトリがありません @@ -753,6 +761,28 @@ EBCDIC形式として… + + CaptureCommentDialog + + Edit Capture Comments + キャプチャコメントを編集 + + + Add Comment + コメントを追加 + + + Section %1 + セクション %1 + + + + CaptureCommentTabWidget + + Comment %1 + コメント %1 + + CaptureFile @@ -858,10 +888,6 @@ Read filter: 読込フィルタ: - - Compress with g&zip - gzip形式で圧縮(&z) - Open Capture File Wireshark: Open Capture File @@ -941,8 +967,8 @@ 詳細 - Capture file comments - キャプチャファイルコメント + Edit Comments + コメントを編集 Refresh @@ -952,10 +978,6 @@ Copy To Clipboard クリップボードにコピー - - Save Comments - コメントを保存 - Capture File Properties キャプチャファイルプロパティ @@ -1004,10 +1026,18 @@ First packet 最初のパケット + + First event + 最初のイベント + Last packet 最後のパケット + + Last event + 最後のイベント + Elapsed 経過時間 @@ -1044,6 +1074,10 @@ Dropped packets 欠落したパケット + + Dropped events + 欠落したイベント + Capture filter キャプチャフィルタ @@ -1056,6 +1090,10 @@ Packet size limit (snaplen) パケットサイズ制限(snaplen) + + Event size limit (snaplen) + イベントサイズ制限(snaplen) + none なし @@ -1064,6 +1102,26 @@ %1 bytes %1 バイト + + Comments + コメント + + + Comment %1: + コメント %1: + + + Decryption Secrets + 復号化シークレット + + + Type + 種別 + + + Size + サイズ + Statistics 統計 @@ -1088,6 +1146,10 @@ Packets パケット数 + + Events + イベント + Time span, s 時間間隔,秒 @@ -1100,6 +1162,10 @@ Average packet size, B 平均パケットサイズ,バイト + + Average event size, B + 平均イベントサイズ,バイト + Bytes バイト数 @@ -1112,14 +1178,14 @@ Average bits/s 平均ビット数毎秒 - - Section Comment - セクション コメント - Packet Comments パケットコメント + + Event Comments + イベント コメント + <p>Frame %1: <p>フレーム %1: @@ -1130,6 +1196,14 @@ Wireshark %1 によって作成されました + + + + Created by Logray %1 + + + Logray %1 によって作成されました + @@ -1357,6 +1431,14 @@ For example, use 1 hour to have a new file created every hour on the hour. (時計の)時刻が特定の間隔になったら次のファイルに切り替えます。例えば、1時間に設定すると毎時1時間ごとに新しいファイルが作成されます + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>通常、無線 ネットワークカードは自身のネットワークアドレスに送受信されるトラフィックのみキャプチャして、&quot;偽の&quot; Ethernetヘッダで <em>ユーザデータ</em> トラフィックのみ取得します。もし無線ネットワークカードが&quot;見える&quot;すべてのトラフィックをキャプチャしたい、802.11管理や制御パケットや無線の物理層のヘッダ情報に興味がある場合にはこのオプションをマークしてください。モニターモードが利用できるかは無線カードとドライバに依存します。無線ネットワークに関してのパケットキャプチャのさらなる詳細についてはWikiを参照ください。</p></body></html> + + + Enable monitor mode on all 802.11 interfaces + すべての802.11インターフェースにおいてモニターモードを有効化します + compression 圧縮 @@ -1369,6 +1451,30 @@ For example, use 1 hour to have a new file created every hour on the hour.gzip gzip + + File infix pattern + ファイルinfixパターン + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + <html><head/><body><p>複数ファイルモードにおいては、日付、時間とファイルインデックス番号がファイル名テンプレートとサフィックスの間に挿入されます。順番を選択してください。</p></body></html> + + + YYYYmmDDHHMMSS_NNNNN + YYYYmmDDHHMMSS_NNNNN + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + <html><head/><body><p>ファイルインデックス番号の前に日付と時刻を示します。これによりファイルは作成時fの順序でソートされ、同じバッチのファイルが近くに配置されます。</p></body></html> + + + NNNNN_YYYYmmDDHHMMSS + NNNNN_YYYYmmDDHHMMSS + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + <html><head/><body><p>日付と時刻の前にファイルインデックスを示します。これは歴史的なWiresharkの順序です。</p></body></html> + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> <html><head/><body><p>キャプチャが次のファイルに切り替えられた後、与えられたファイル数を超過したら、最も古いファイルが消されます</p></body></html> @@ -1522,8 +1628,8 @@ For example, use 1 hour to have a new file created every hour on the hour.エラー - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. - 複数ファイル:要求されたファイルサイズが大きすぎます。ファイルサイズは2GBより大きくできません + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. + 複数ファイル:要求されたファイルサイズが大きすぎます。ファイルサイズは2テラバイトより大きくできません Multiple files: No capture file name given. You must specify a filename if you want to use multiple files. @@ -1552,6 +1658,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Capture packets in promiscuous mode プロミスキャスモードでパケットをキャプチャ + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>通常、無線 ネットワークカードは自身のネットワークアドレスに送受信されるトラフィックのみキャプチャして、&quot;偽の&quot; Ethernetヘッダで <em>ユーザデータ</em> トラフィックのみ取得します。もし無線ネットワークカードが&quot;見える&quot;すべてのトラフィックをキャプチャしたい、802.11管理や制御パケットや無線の物理層のヘッダ情報に興味がある場合にはこのオプションをマークしてください。モニターモードが利用できるかは無線カードとドライバに依存します。無線ネットワークに関してのパケットキャプチャのさらなる詳細についてはWikiを参照ください。</p></body></html> + + + Capture packets in monitor mode on 802.11 devices + 802.11デバイスにおいてモニターモードでパケットをキャプチャします + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>次世代のキャプチャファイル形式でパケットをキャプチャします</p></body></html> @@ -1779,6 +1893,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved 解決済 + + Width + + + + Alignment + 揃え + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> <html>123raw(無加工)のフィールド値の代わりに人が読むことのできる文字列を表示します。有効な文字列を含むフィールドを持つカスタム列へ適用する場合にのみ適用できます。</html> @@ -1826,6 +1948,25 @@ For example, use 1 hour to have a new file created every hour on the hour.フィルタテキストをクリップボードにコピーします + + CompressionGroupBox + + Compression options + 圧縮オプション + + + &Uncompressed + 非圧縮(&U) + + + Compress with g&zip + gzip形式で圧縮(&z) + + + Compress with &LZ4 + LZ4形式で圧縮(&L) + + ConversationDataModel @@ -1892,6 +2033,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Bits/s B ビット毎秒 B + + Flows + フロー + Total Packets 全パケット @@ -2006,14 +2151,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy packet bytes as a hex dump. 16進数ダンプとしてパケットバイト列をコピー - - …as Printable Text - 印刷可能なテキストとして… - - - Copy only the printable text in the packet. - パケット内の印刷可能なテキストだけをコピー - …as MIME Data MIMEデータとして... @@ -2026,10 +2163,42 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy packet bytes as printable ASCII characters and escape sequences. 印刷可能なASCII文字とエスケープシーケンスとしてパケットバイト列をコピー + + …as Go literal + …Go 言語のリテラルとして + + + Copy packet bytes as Go literal. + Go言語のリテラルとしてパケットバイト列をコピーします。 + + + …as C Array + …C言語配列として + + + Copy packet bytes as C Array. + C言語配列としてパケットバイト列をコピーします。 + …as a Hex Stream 16進数ストリームとして… + + …as UTF-8 Text + …UTF-8テキストとして + + + Copy packet bytes as text, treating as UTF-8. + UTF-8として扱ってパケットバイト列をテキストとしてコピーします + + + …as ASCII Text + ASCII形式テキストとして… + + + Copy packet bytes as text, treating as ASCII. + ASCII形式として扱ってパケットバイト列をテキストとしてコピーします + Copy packet bytes as a stream of hex. 16進数ストリームとしてパケットバイト列をコピー @@ -2826,6 +2995,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: 表示フィルタ: + + Export PDUs + PDUをエクスポート + ExtArgSelector @@ -2864,10 +3037,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Start 開始 - - Save - 保存 - Default デフォルト @@ -3008,6 +3177,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Display Filters 表示フィルタ + + Display Filter Macros + 表示フィルタマクロ + + + New macro + 新規マクロ + Open 開く @@ -3091,10 +3268,18 @@ For example, use 1 hour to have a new file created every hour on the hour. FilterListModel + + Macro Name + マクロ名 + Filter Name フィルタ名 + + Macro Expression + マクロ式 + Filter Expression フィルタ式 @@ -3180,22 +3365,10 @@ For example, use 1 hour to have a new file created every hour on the hour. FolderListModel - - "File" dialogs - "ファイル" ダイアログ - - - capture files - キャプチャファイル - Temp 一時的 - - untitled capture files - 名称未設定キャプチャファイル - Personal configuration 個人設定 @@ -3204,14 +3377,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Global configuration グローバル設定 - - dfilters, preferences, ethers, … - dfilters, preferences, ethers, … - - - dfilters, preferences, manuf, … - dfilters, preferences, manuf, … - System システム @@ -3224,18 +3389,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Program プログラム - - program files - プログラムファイル - Personal Plugins 個人プラグイン - - binary plugins - バイナリプラグイン - Global Plugins グローバルプラグイン @@ -3252,12 +3409,36 @@ For example, use 1 hour to have a new file created every hour on the hour.Lua scripts Luaスクリプト + + "File" dialog location + "ファイル" ダイアログの場所 + + + Capture files + キャプチャファイル + + + Untitled capture files + 名称未設定キャプチャファイル + + + Preferences, profiles, manuf, … + 設定, プロファイル, manuf, … + + + Program files + プログラムファイル + + + Binary plugins + バイナリプラグイン + Personal Extcap path 個人Extcapパス - external capture (extcap) plugins + External capture (extcap) plugins 外部キャプチャ(extcap)プラグイン @@ -3389,6 +3570,22 @@ For example, use 1 hour to have a new file created every hour on the hour.%Ln ターン + + Event %1. + イベント %1 + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + %Ln <span style="color: %1; background-color:%2">読み取り</span>, + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + %Ln <span style="color: %1; background-color:%2">書き込み</span>, + + Click to select. クリックして選択します @@ -3421,6 +3618,18 @@ For example, use 1 hour to have a new file created every hour on the hour.%1 stream not found on the selected packet. 選択したパケットに %1 ストリームは見つかりませんでした + + Read activity(%6) + 読み取りアクティビティ(%6) + + + Write activity(%6) + 書き込みアクティビティ(%6) + + + Entire I/O activity (%1) + 全体のI/Oアクティビティ(%1) + Entire conversation (%1) 全体の対話 (%1) @@ -3437,10 +3646,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Save Stream Content As… …としてストリーム内容を保存 - - [Stream output truncated] - [ストリーム出力が切り詰められました] - %Ln total stream(s). @@ -3466,9 +3671,20 @@ For example, use 1 hour to have a new file created every hour on the hour.ヒント - Show data as - Show and save data as - としてデータを表示 + Show as + として表示 + + + No delta times + デルタ時間なし + + + Turn delta times + ターンデルタ時間 + + + All delta times + 全デルタ時間 Stream @@ -3482,11 +3698,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: 検索: + + Case sensitive + 大文字小文字を区別 + Find &Next 次を検索(&N) + + FollowStreamText + + [Stream output truncated] + [ストリーム出力が切り詰められました] + + FontColorPreferencesFrame @@ -3822,30 +4049,29 @@ For example, use 1 hour to have a new file created every hour on the hour. - - Remove this graph. - Remove this dissection behavior. - このグラフを削除します - Add a new graph. 新規グラフを追加します - - Duplicate this graph. - このグラフを複製します - Clear all graphs. すべてのグラフをクリア - Move this graph upwards. - このグラフを上に移動します + Remove the selected graph(s). + 選択したグラフを削除します - Move this graph downwards. - このグラフを下に移動します + Duplicate the selected graph(s). + 選択したグラフを複製します + + + Move the selected graph(s) upwards. + 選択したグラフを上に移動します + + + Move the selected graph(s) downwards. + 選択したグラフを下に移動します Mouse @@ -3887,10 +4113,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Enable legend 凡例を有効化 - - Reset - リセット - Reset Graph グラフをリセット @@ -4104,6 +4326,42 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy graphs from another profile. 別のプロファイルからグラフをコピーします + + 1 μs + 1マイクロ秒 + + + 2 μs + 2マイクロ秒 + + + 5 μs + 5マイクロ秒 + + + 10 μs + 10マイクロ秒 + + + 20 μs + 20マイクロ秒 + + + 50 μs + 50マイクロ秒 + + + 100 μs + 100マイクロ秒 + + + 200 μs + 200マイクロ秒 + + + 500 μs + 500マイクロ秒 + 1 ms 1ミリ秒 @@ -4148,6 +4406,14 @@ For example, use 1 hour to have a new file created every hour on the hour.5 sec 5 秒 + + 2 min + 2分 + + + 5 min + 5分 + Wireshark I/O Graphs: %1 Wireshark入出力グラフ: %1 @@ -4160,6 +4426,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Filtered events フィルタされたイベント + + All packets + すべてのパケット + + + All events + すべてのイベント + All Packets すべてのパケット @@ -4173,8 +4447,8 @@ For example, use 1 hour to have a new file created every hour on the hour.すべてのイベント - Access Denied - アクセス拒否 + All Execs + 全ての Execs Hover over the graph for details. @@ -4220,6 +4494,34 @@ For example, use 1 hour to have a new file created every hour on the hour.Click to select a portion of the graph. クリックしてグラフの割合を選びます + + %1 Intervals + %1 インターバル + + + Move to top left + 左上に移動 + + + Move to top center + 中央上に移動 + + + Move to top right + 右上に移動 + + + Move to bottom left + 左下に移動 + + + Move to bottom center + 中央下に移動 + + + Move to bottom right + 右下に移動 + Portable Document Format (*.pdf) PDF形式 (*.pdf) @@ -4916,7 +5218,7 @@ For example, use 1 hour to have a new file created every hour on the hour. <p>Local interfaces are unavailable because the packet capture driver isn't loaded.</p><p>You can fix this by running <pre>net start npcap</pre> if you have Npcap installed or <pre>net start npf</pre> if you have WinPcap installed. Both commands must be run as Administrator.</p> - <p>キャプチャドライバが読み込まれていないためローカル印ーフェースは利用できません。</p><p>以下を実行することで修正することができます。 もしNpcapをインストールした場合、<pre>net start npcap</pre> もしWinPcapをインストールした場合、<pre>net start npf</pre> 両方のコマンドは管理者権限として実行する必要があります。</p> + <p>キャプチャドライバが読み込まれていないためローカルインターフェースは利用できません。</p><p>以下を実行することで修正することができます。 もしNpcapをインストールした場合、<pre>net start npcap</pre> もしWinPcapをインストールした場合、<pre>net start npf</pre> 両方のコマンドは管理者権限として実行する必要があります。</p> <p>You don't have permission to capture on local interfaces.</p><p>You can fix this by <a href="file://%1">installing ChmodBPF</a>.</p> @@ -4972,6 +5274,13 @@ For example, use 1 hour to have a new file created every hour on the hour.変更を適用 + + InterfaceTreeDelegate + + default + デフォルト + + InterfaceTreeModel @@ -5947,8 +6256,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteMacStatisticsDialog - LTE Mac Statistics - LTE MAC統計 + LTE/NR Mac Statistics + LTE/NR Mac 統計 Include SR frames in filter @@ -6256,12 +6565,12 @@ For example, use 1 hour to have a new file created every hour on the hour.シーケンス番号 - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) - LTE RLCグラフ (UE=%1 chan=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) + %1 RLC グラフ (UE=%2 chan=%3%4 %5 - %6) - LTE RLC Graph - no channel selected - LTE RLCグラフ - チャンネルが選択されていません + 3GPP RLC Graph - no channel selected + 3GPP RLC グラフ - チャンネルが選択されていません Save As… @@ -6315,8 +6624,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteRlcStatisticsDialog - LTE RLC Statistics - LTE RLC統計 + 3GPP RLC Statistics + 3GPP RLC 統計 Include SR frames in filter @@ -6401,6 +6710,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Profile: %1 プロファイル: %1 + + %1 Displayed: %2 (%3%) + %1 表示: %2 (%3%) + Manage Profiles… プロファイルの管理... @@ -6462,6 +6775,12 @@ For example, use 1 hour to have a new file created every hour on the hour.%Ln バイト + + %Ln bit(s) + + %Ln ビット + + Byte %1 %1 バイト @@ -6475,9 +6794,12 @@ For example, use 1 hour to have a new file created every hour on the hour.選択されたパケット: %1 %2 - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 - パケット数: %1 %4 表示: %2 (%3%) + Selected Event: %1 %2 + 選択したイベント: %1 %2 + + + Events: %1 + イベント: %1 %1 Selected: %2 (%3%) @@ -6508,6 +6830,10 @@ For example, use 1 hour to have a new file created every hour on the hour.No Packets パケットなし + + No Events + イベントなし + From Zip File... Zipファイルより... @@ -6539,6 +6865,13 @@ For example, use 1 hour to have a new file created every hour on the hour. + + MainWindow + + Display filter as %1 + %1 として表示フィルタ + + MainWindowPreferencesFrame @@ -6570,6 +6903,10 @@ For example, use 1 hour to have a new file created every hour on the hour.The most recently used folder 一番最近に使ったフォルダ + + The current working directory + 現在の稼働ディレクトリ + Show up to ここまで表示 @@ -7000,6 +7337,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show Field Values フィールド値を表示 + + Refresh + 更新 + Save Diagram As… …としてダイアグラムを保存 @@ -7047,6 +7388,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show packet bytes パケットバイト列を表示 + + Layout: + レイアウト: + Packet %1 パケット %1 @@ -7069,6 +7414,12 @@ For example, use 1 hour to have a new file created every hour on the hour.%Ln バイト + + %Ln bit(s) + + %Ln ビット + + PacketFormatGroupBox @@ -7527,10 +7878,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy this profile. このプロファイルをコピーします + + The number of packets or events to check for automatic profile switching. + 自動プロファイルスイッチのためのパケットやイベントの数 + + + Auto switch packet limit + 自動スイッチパケット限度 + Configuration Profiles 設定プロファイル + + Auto switch event limit + 自動スイッチイベント限度 + Import noun @@ -7706,6 +8069,10 @@ For example, use 1 hour to have a new file created every hour on the hour.deleted 削除済 + + Auto Switch Filter + 自動スイッチフィルタ + copy noun @@ -8229,6 +8596,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Marker missing? マーカー欠如? + + LTE + LTE + + + NR + NR + C-RNTI C-RNTI @@ -8249,6 +8624,10 @@ For example, use 1 hour to have a new file created every hour on the hour.UEId UEId + + RAT + RAT + UL Frames UL フレーム @@ -8473,9 +8852,69 @@ For example, use 1 hour to have a new file created every hour on the hour.Browse… 参照… + + PACKETS + パケット + + + EVENTS + イベント + + + BYTES + バイト + + + BITS + ビット + + + COUNT FRAMES + フレーム数 + + + COUNT FIELDS + フィールド数 + + + SUM + 合計 + + + MAX + 最大 + + + MIN + 最小 + + + AVERAGE + 平均 + + + THROUGHPUT + スループット + + + LOAD + 読込 + + + Left + + + + Center + 中央 + + + Right + + - QObject::QObject + QObject::QObject::QObject CCCH CCCH @@ -8575,6 +9014,13 @@ For example, use 1 hour to have a new file created every hour on the hour.ミリ秒 + + ResizeHeaderView + + Resize all %1 to contents + 全ての %1 を内容に合わせてリサイズします + + ResolvedAddressesDialog @@ -8690,6 +9136,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved Addresses 解決したアドレス + + Copy + コピー + + + Save as… + …として保存 + # Resolved addresses found in %1 # %1 に解決したアドレスが見つかりました @@ -8703,6 +9157,61 @@ For example, use 1 hour to have a new file created every hour on the hour. + + ResolvedAddressesView + + as Plain Text + プレインテキストとして + + + Copy selected rows + 選択した行をコピー + + + Copy table + 表をコピー + + + as CSV + CSVとして + + + as JSON + JSONとして + + + Save selected rows as… + 選択した行を…として保存 + + + Save table as… + …として表を保存 + + + Save Resolved Addresses As… + …として解決したアドレスを保存 + + + Plain text (*.txt) + プレインテキスト (*.txt) + + + CSV Document (*.csv) + CSV書類 (*.csv) + + + JSON Document (*.json) + JSON書類 (*.json) + + + Warning + 警告 + + + Unable to save %1: %2 + %1を保存できません: %2 + + ResponseTimeDelayDialog @@ -10377,6 +10886,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Packet bytes パケットバイト列 + + <b>Options:</b> + <b>オプション:</b> + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>ナロー文字列 (UTF-8とASCII)もしくはワイド(UTF-16)文字を検索</p></body></html> @@ -10397,6 +10910,18 @@ For example, use 1 hour to have a new file created every hour on the hour.Case sensitive 大文字小文字を区別 + + Backwards + 戻る + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + <html><head/><body><p>次のパケットへ進む前に現在のパケットの中で続いて起こるフィールド値を検索します。</p></body></html> + + + Multiple occurrences + 複数発生するフィールド値 + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10434,6 +10959,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Invalid filter. 無効なフィルタです + + Event List + イベントリスト + + + Event Details + イベント詳細 + + + Event Bytes + イベントバイト数 + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + <html><head/><body><p>イベント一覧(概要部分)やデコードされたイベント表示ラベル(ツリー表示部分)やアスキー変換されたイベントデータ(16進数表示部分)を検索します</p></body></html> + That filter doesn't test anything. そのフィルタは何も検査しません @@ -10857,7 +11398,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Decode as - としてでコード + としてデコード Show as @@ -10875,6 +11416,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: 検索: + + Case sensitive + 大文字小文字を区別 + Find &Next 次を検索 @@ -10969,14 +11514,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Save as… …として保存 + + Decoded as %1. + %1 としてデコードされました + Save Selected Packet Bytes As… …として選択したパケットバイト列を保存 + + compressed %1 + %1 を圧縮しました + - Displaying %Ln byte(s). + Using %Ln byte(s). - %Ln バイトを表示中 + %Ln バイトを利用 @@ -11076,6 +11629,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: 表示フィルタ: + + Strip Headers + ヘッダーを除去 + SupportedProtocolsDialog @@ -12049,22 +12606,20 @@ For example, use 1 hour to have a new file created every hour on the hour.新規エントリを作成します - Remove this entry. - Remove this profile. - このエントリを削除します + Remove the selected entry(ies). + 選択したエントリを削除します - Copy this entry. - Copy this profile. - このエントリをコピーします + Copy the selected entry(ies). + 選択したエントリをコピーします - Move entry up. - エントリを上に移動します + Move the selected entry(ies) up. + 選択したエントリを上に移動します - Move entry down. - エントリを下に移動します + Move the selected entry(ies) down. + 選択したエントリを下に移動します Clear all entries. @@ -12090,20 +12645,20 @@ For example, use 1 hour to have a new file created every hour on the hour.新規エントリを作成します - Remove this entry. - このエントリを削除します + Remove the selected entry(ies). + 選択したエントリを削除します - Copy this entry. - このエントリをコピーします + Copy the selected entry(ies). + 選択したエントリをコピーします - Move entry up. - エントリを上に移動します + Move the selected entry(ies) up. + 選択したエントリを上に移動します - Move entry down. - エントリを下に移動します + Move the selected entry(ies) down. + 選択したエントリを下に移動します Clear all entries. @@ -12472,10 +13027,18 @@ a:hover { You are sniffing the glue that holds the Internet together using Wireshark あなたはWiresharkを使ってインターネットを互いにつなぐ膠をキャプチャしています + + You are sniffing the glue that holds your system together using Logray + あなたはLograyを使ってシステムを互いに繋ぐ膠をキャプチャしています + You are running Wireshark Wiresharkを起動中 + + You are running Logray + Lograyを起動中です + You receive automatic updates. 自動アップデートを受信します @@ -12752,14 +13315,6 @@ a:hover { No files found ファイルが見つかりませんでした - - &Contents - 目次(&C) - - - Wireshark Filter - Wiresharkフィルタ - TShark Tshark @@ -13025,10 +13580,6 @@ a:hover { Wireless Toolbar 無線ツールバー - - Help contents - ヘルプ目次 - FAQs FAQ's @@ -13149,11 +13700,6 @@ a:hover { Find the previous packet 前のパケットを検索します - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - パケットをマーク/マーク解除(&M) - Mark All Displayed 表示されているものをすべてマークします @@ -13182,11 +13728,6 @@ a:hover { Go to the previous marked packet 前にマークされたパケットに移動します - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - パケットを無視/無視を解除(&I) - Ignore All Displayed 表示されているものすべてを無視します @@ -13627,10 +14168,6 @@ a:hover { Reset Layout レイアウトをリセット - - Reset appearance layout to default size - 外観のレイアウトをデフォルトのサイズにリセットします - Seconds Since First Captured Packet 最初にキャプチャしたパケットからの経過時間 @@ -13791,22 +14328,30 @@ a:hover { MAC Address Blocks MACアドレスブロック - - TLS Keylog Launcher - TLSキーログランチャー - - - Release Notes - リリースノート - &Options… オプション…(&O) + + &3GPP Uu + &3GPP Uu + &Wireless 無線(&W) + + &User's Guide + &ユーザーズガイド + + + Wireshark User's Guide + ワイヤーシャークユーザーズガイド + + + Display Filters + 表示フィルタ + Capture &Filters… キャプチャフィルタ…(&F) @@ -13851,10 +14396,18 @@ a:hover { Find Pre&vious 前を検索(&v) + + &Mark/Unmark Selected + 選択をマーク/マーク解除(&M) + Mark or unmark each selected packet 各々の選択されたパケットをマーク/マーク解除します + + &Ignore/Unignore Selected + 選択を無視/無視を解除(&I) + Ignore or unignore each selected packet 各々の選択されたパケットを無視/無視を解除します @@ -13895,6 +14448,18 @@ a:hover { TCP throughput TCP スループット + + General + 一般 + + + Query-Response + クエリ-応答 + + + DNS Query-Response Statistics + DNSクエリ-応答統計 + Request Sequences リクエストシーケンス @@ -13903,6 +14468,14 @@ a:hover { HTTP Request Sequences HTTPリクエストシーケンス + + E2AP + E2AP + + + E2AP Messages + E2AP メッセージ + Decode &As… …としてデコード(&A) @@ -13963,6 +14536,10 @@ a:hover { Normal Size 標準サイズ + + Reset layout to default size + デフォルトサイズにレイアウトをリセット + Resize Columns 列幅を再調整 @@ -14221,6 +14798,14 @@ a:hover { Go to the packet referenced by the selected field. 選択されたフィールドによって参照されたパケットへ移動します + + TLS Keylog Launcher + TLSキーログランチャー + + + Release Notes + リリースノート + &VoIP Calls VoIP通話(&V) @@ -14253,10 +14838,6 @@ a:hover { &GSM &GSM - - &LTE - &LTE - &MTP3 &MTP3 @@ -14541,6 +15122,10 @@ a:hover { Quit without Saving 保存しないで終了(&w) + + USB CDC Data + USB CDC データ + There is no "rtp.ssrc" field in this version of Wireshark. このバージョンのWiresharkには "rtp.ssrc" フィールドはありません diff --git a/ui/qt/wireshark_ko.ts b/ui/qt/wireshark_ko.ts index f9851df8..e95bea54 100644 --- a/ui/qt/wireshark_ko.ts +++ b/ui/qt/wireshark_ko.ts @@ -44,8 +44,8 @@ 폴더 - Filter by path - 경로로 필터 + Search Folders + 폴더 검색 Plugins @@ -79,6 +79,14 @@ License 라이선스 + + About Logray + Logray 정보 + + + Logray + Logray + The directory does not exist 디렉터리가 존재하지 않음 @@ -753,6 +761,28 @@ EBCDIC으로 표시 + + CaptureCommentDialog + + Edit Capture Comments + 캡처 주석 편집 + + + Add Comment + 주석 추가 + + + Section %1 + 부분 %1 + + + + CaptureCommentTabWidget + + Comment %1 + 주석 %1 + + CaptureFile @@ -821,7 +851,7 @@ %1, timed out at %Ln packet(s) %1, timed out at %2 packets - %1, 패킷 %Ln개 이후 시간 초과됨 + %1, 패킷 %Ln개 이후 시간 초과 @@ -858,10 +888,6 @@ Read filter: 읽기 필터: - - Compress with g&zip - gzip 형식으로 압축(&Z) - Open Capture File Wireshark: Open Capture File @@ -941,8 +967,8 @@ 자세한 정보 - Capture file comments - 캡처 파일 주석 + Edit Comments + 주석 편집 Refresh @@ -952,10 +978,6 @@ Copy To Clipboard 클립보드에 복사 - - Save Comments - 주석 저장 - Capture File Properties 캡처 파일 속성 @@ -1004,10 +1026,18 @@ First packet 처음 패킷 + + First event + 첫 이벤트 + Last packet 마지막 패킷 + + Last event + 마지막 이벤트 + Elapsed 경과 시간 @@ -1044,6 +1074,10 @@ Dropped packets 누락된 패킷 + + Dropped events + 누락된 이벤트 + Capture filter 캡처 필터 @@ -1056,6 +1090,10 @@ Packet size limit (snaplen) 패킷 크기 제한(snaplen) + + Event size limit (snaplen) + 이벤트 크기 제한(snaplen) + none 없음 @@ -1064,6 +1102,26 @@ %1 bytes %1바이트 + + Comments + 주석 + + + Comment %1: + 주석 %1 + + + Decryption Secrets + 복호화 비밀 정보 + + + Type + 유형 + + + Size + 크기 + Statistics 통계 @@ -1088,6 +1146,10 @@ Packets 패킷 수 + + Events + 이벤트 + Time span, s 시간 간격, 초 @@ -1100,6 +1162,10 @@ Average packet size, B 평균 패킷 크기, 바이트 + + Average event size, B + 평균 이벤트 크기, 바이트 + Bytes 바이트 @@ -1112,14 +1178,14 @@ Average bits/s 초당 평균 비트 수 - - Section Comment - 부분 주석 - Packet Comments 패킷 주석 + + Event Comments + 이벤트 주석 + <p>Frame %1: <p>프레임 %1: @@ -1130,6 +1196,14 @@ Wireshark %1에서 생성됨 + + + + Created by Logray %1 + + + Logray %1에서 생성됨 + @@ -1358,6 +1432,14 @@ For example, use 1 hour to have a new file created every hour on the hour.지정한 주기마다 다음 파일로 전환합니다. 예를 들어 1시간으로 설정하면 매시간마다 새로운 파일을 만듭니다. + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>일반적으로 무선 네트워크 카드는 수신이나 발신 네트워크 주소가 자기 자신인 트래픽만 캡처하며, <em>사용자 데이터</em> 트래픽에는 &quot;가짜&quot; 이더넷 헤더를 추가하여 캡처합니다. 무선 네트워크 카드가 &quot;볼 수&quot; 있는 모든 트래픽을 캡처하거나, 802.11 관리 및 제어 패킷 또는 라디오 계층 정보를 보려면 이 옵션을 선택하십시오. 무선 네트워크 카드와 드라이버에 따라서 모니터 모드 사용 가능 여부가 달라집니다. Wi-Fi 네트워크에서 패킷을 캡처하는 과정에 대한 자세한 정보를 보려면 위키 페이지를 참조하십시오.</p></body></html> + + + Enable monitor mode on all 802.11 interfaces + 모든 802.11 인터페이스에서 모니터 모드 활성화 + compression 압축 @@ -1370,6 +1452,30 @@ For example, use 1 hour to have a new file created every hour on the hour.gzip gzip + + File infix pattern + 파일 중위 표기 패턴 + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + <html><head/><body><p>여러 파일 모드에서는 파일 이름과 접두사 사이에 날짜, 시간, 파일 순서 번호가 추가됩니다. 이들의 순서를 선택하십시오.</p></body></html> + + + YYYYmmDDHHMMSS_NNNNN + YYYYmmDDHHMMSS_NNNNN + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + <html><head/><body><p>파일 순서 번호 이전에 날짜와 시간을 배치합니다. 파일을 이름 순으로 정렬했을 때 생성 시간 순서를 따르며, 같은 배치에서 생성된 파일이 인접하게 배치됩니다.</p></body></html> + + + NNNNN_YYYYmmDDHHMMSS + NNNNN_YYYYmmDDHHMMSS + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + <html><head/><body><p>날짜와 시간 이전에 파일 순서 번호를 배치합니다. Wireshark에서 역사적으로 사용했던 방식입니다..</p></body></html> + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> <html><head/><body><p>다음 파일로 캡처를 전환한 후 생성하기로 지정한 파일 개수를 초과하면 가장 오래된 파일을 지울 것입니다.</p></body></html> @@ -1444,7 +1550,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Stop capture automatically after… - 다음 이후 자동으로 캡처 정지 + 다음 이후 자동으로 캡처 정지… <html><head/><body><p>Stop capturing after the specified number of packets have been captured.</p></body></html> @@ -1460,7 +1566,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Stop capturing after the specified number of files have been created. - + 지정한 개수의 파일을 생성한 후 캡처를 정지합니다. <html><head/><body><p>Stop capturing after the specified amount of data has been captured.</p></body></html> @@ -1472,7 +1578,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Stop capturing after the specified amount of time has passed. - 지정한 시간이 지난 뒤 캡처를 정지합니다. + 지정한 시간이 지난 후 캡처를 정지합니다. <html><head/><body><p>Optionally specify a temporary directory for unnamed capture files.</p></body></html> @@ -1523,8 +1629,8 @@ For example, use 1 hour to have a new file created every hour on the hour.오류 - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. - 여러 파일: 요청한 파일 크기가 너무 큽니다. 파일 최대 크기는 2 GiB입니다. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. + 여러 파일: 요청한 파일 크기가 너무 큽니다. 파일 크기는 2 TB를 초과할 수 없습니다. Multiple files: No capture file name given. You must specify a filename if you want to use multiple files. @@ -1553,6 +1659,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Capture packets in promiscuous mode 무작위 모드로 패킷 캡처 + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>일반적으로 무선 네트워크 카드는 수신이나 발신 네트워크 주소가 자기 자신인 트래픽만 캡처하며, <em>사용자 데이터</em> 트래픽에는 &quot;가짜&quot; 이더넷 헤더를 추가하여 캡처합니다. 무선 네트워크 카드가 &quot;볼 수&quot; 있는 모든 트래픽을 캡처하거나, 802.11 관리 및 제어 패킷 또는 라디오 계층 정보를 보려면 이 옵션을 선택하십시오. 무선 네트워크 카드와 드라이버에 따라서 모니터 모드 사용 가능 여부가 달라집니다. Wi-Fi 네트워크에서 패킷을 캡처하는 과정에 대한 자세한 정보를 보려면 위키 페이지를 참조하십시오.</p></body></html> + + + Capture packets in monitor mode on 802.11 devices + 802.11 인터페이스에서 모니터 모드 활성화 + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>다음 세대(Next Generation)의 캡처 파일 형식으로 패킷을 캡처합니다.</p></body></html> @@ -1780,6 +1894,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved 해석됨 + + Width + + + + Alignment + 정렬 + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> <html>필드의 원시값 대신 사람이 읽을 수 있는 문자열로 보여 줍니다. 문자열 값을 갖는 필드를 가진 사용자 지정 칼럼에 대해서만 적용 가능합니다.</html> @@ -1827,6 +1949,25 @@ For example, use 1 hour to have a new file created every hour on the hour.필터 텍스트를 클립보드에 복사합니다. + + CompressionGroupBox + + Compression options + 압축 옵션 + + + &Uncompressed + 압축하지 않음(&U) + + + Compress with g&zip + gzip으로 압축(&Z) + + + Compress with &LZ4 + LZ4로 압축(&L) + + ConversationDataModel @@ -1893,6 +2034,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Bits/s B 비트/초 B + + Flows + 플로 + Total Packets 전체 패킷 @@ -2007,14 +2152,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy packet bytes as a hex dump. 16진수 덤프 형식으로 패킷 바이트를 복사합니다. - - …as Printable Text - 출력 가능한 문자열로 복사 - - - Copy only the printable text in the packet. - 패킷 내의 출력 가능한 문자열만 복사합니다. - …as MIME Data MIME 데이터로 복사 @@ -2027,10 +2164,42 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy packet bytes as printable ASCII characters and escape sequences. 출력 가능한 ASCII 문자와 탈출 시퀀스로 패킷 바이트를 복사합니다. + + …as Go literal + Go 리터럴로 복사 + + + Copy packet bytes as Go literal. + Go 리터럴 형식으로 패킷 바이트를 복사합니다. + + + …as C Array + C 언어 배열로 복사 + + + Copy packet bytes as C Array. + C 언어 배열 형식으로 패킷 바이트를 복사합니다. + …as a Hex Stream 16진수 스트림으로 복사 + + …as UTF-8 Text + UTF-8 텍스트로 복사 + + + Copy packet bytes as text, treating as UTF-8. + 패킷 바이트를 UTF-8 텍스트로 취급하여 복사합니다. + + + …as ASCII Text + ASCII 텍스트로 복사 + + + Copy packet bytes as text, treating as ASCII. + 패킷 바이트를 ASCII 텍스트로 취급하여 복사합니다. + Copy packet bytes as a stream of hex. 16진수 스트림으로 패킷 바이트를 복사합니다. @@ -2827,6 +2996,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: 표시 필터: + + Export PDUs + PDU 내보내기 + ExtArgSelector @@ -2865,10 +3038,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Start 시작 - - Save - 저장 - Default 기본값 @@ -3009,6 +3178,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Display Filters 표시 필터 + + Display Filter Macros + 표시 필터 매크로 + + + New macro + 새 매크로 + Open 열기: @@ -3092,10 +3269,18 @@ For example, use 1 hour to have a new file created every hour on the hour. FilterListModel + + Macro Name + 매크로 이름 + Filter Name 필터 이름 + + Macro Expression + 매크로 표현식 + Filter Expression 필터 표현식 @@ -3181,22 +3366,10 @@ For example, use 1 hour to have a new file created every hour on the hour. FolderListModel - - "File" dialogs - "파일" 대화 상자 - - - capture files - 캡처 파일 - Temp 임시 - - untitled capture files - 이름 없는 캡처 파일 - Personal configuration 개인 환경 설정 @@ -3205,14 +3378,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Global configuration 전역 설정 - - dfilters, preferences, ethers, … - dfilters, 설정, ethers, … - - - dfilters, preferences, manuf, … - dfilters, 설정, manuf, … - System 시스템 @@ -3225,18 +3390,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Program 프로그램 - - program files - 프로그램 파일 - Personal Plugins 사용자 플러그인 - - binary plugins - 바이너리 플러그인 - Global Plugins 전역 플러그인 @@ -3253,13 +3410,37 @@ For example, use 1 hour to have a new file created every hour on the hour.Lua scripts Lua 스크립트 + + "File" dialog location + "파일" 대화 상자 위치 + + + Capture files + 캡처 파일 + + + Untitled capture files + 제목 없는 캡처 파일 + + + Preferences, profiles, manuf, … + 설정, 프로필, 제조사, … + + + Program files + 프로그램 파일 + + + Binary plugins + 바이너리 플러그인 + Personal Extcap path 사용자 Extcap 경로 - external capture (extcap) plugins - 외부 캡처(Extcap) 플러그인 + External capture (extcap) plugins + 외부 캡처(extcap) 플러그인 Global Extcap path @@ -3329,7 +3510,7 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln server pkt(s), - 서버 패킷 %Ln개, + 서버 패킷 %Ln개, @@ -3390,6 +3571,22 @@ For example, use 1 hour to have a new file created every hour on the hour.턴 %Ln회. + + Event %1. + 이벤트 %1개. + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + <span style="color: %1; background-color:%2">읽기</span> %Ln개, + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + <span style="color: %1; background-color:%2">쓰기</span> %Ln개, + + Click to select. 클릭하면 선택합니다. @@ -3422,6 +3619,18 @@ For example, use 1 hour to have a new file created every hour on the hour.%1 stream not found on the selected packet. 선택한 패킷에서 %1 스트림을 찾을 수 없습니다. + + Read activity(%6) + 읽기 활동(%6) + + + Write activity(%6) + 쓰기 활동(%6) + + + Entire I/O activity (%1) + 전체 I/O 활동(%M) + Entire conversation (%1) 전체 대화(%1) @@ -3438,10 +3647,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Save Stream Content As… 다른 이름으로 스트림 내용 저장… - - [Stream output truncated] - [스트림 출력이 잘림] - %Ln total stream(s). @@ -3467,9 +3672,20 @@ For example, use 1 hour to have a new file created every hour on the hour.필터 힌트. - Show data as - Show and save data as - 다음 형식으로 표시: + Show as + 다른 형식으로 표시 + + + No delta times + 델타 시간 없음 + + + Turn delta times + 턴 델타 시간 + + + All delta times + 모든 델타 시간 Stream @@ -3483,11 +3699,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: 찾기: + + Case sensitive + 대소문자 구분 + Find &Next 다음 찾기(&N) + + FollowStreamText + + [Stream output truncated] + [스트림 출력 잘림] + + FontColorPreferencesFrame @@ -3823,30 +4050,29 @@ For example, use 1 hour to have a new file created every hour on the hour. - - Remove this graph. - Remove this dissection behavior. - 이 그래프를 삭제합니다. - Add a new graph. 새로운 그래프를 추가합니다. - - Duplicate this graph. - 이 그래프를 복제합니다. - Clear all graphs. 모든 그래프를 지웁니다. - Move this graph upwards. - 이 그래프를 위로 이동합니다. + Remove the selected graph(s). + 선택한 그래프를 삭제합니다. + + + Duplicate the selected graph(s). + 선택한 그래프를 복제합니다. + + + Move the selected graph(s) upwards. + 선택한 그래프를 위로 이동합니다. - Move this graph downwards. - 이 그래프를 아래로 이동합니다. + Move the selected graph(s) downwards. + 선택한 그래프를 아래로 이동합니다. Mouse @@ -3888,10 +4114,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Enable legend 범례 활성화 - - Reset - 초기화 - Reset Graph 그래프 초기화 @@ -4105,6 +4327,42 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy graphs from another profile. 다른 프로필에서 그래프를 복사합니다. + + 1 μs + 1 μs + + + 2 μs + 2 μs + + + 5 μs + 5 μs + + + 10 μs + 10 μs + + + 20 μs + 20 μs + + + 50 μs + 50 μs + + + 100 μs + 100 μs + + + 200 μs + 200 μs + + + 500 μs + 500 μs + 1 ms 1 ms @@ -4149,6 +4407,14 @@ For example, use 1 hour to have a new file created every hour on the hour.5 sec 5초 + + 2 min + 2분 + + + 5 min + 5분 + Wireshark I/O Graphs: %1 Wireshark I/O 그래프: %1 @@ -4161,6 +4427,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Filtered events 필터된 이벤트 + + All packets + 모든 패킷 + + + All events + 모든 이벤트 + All Packets 모든 패킷 @@ -4174,8 +4448,8 @@ For example, use 1 hour to have a new file created every hour on the hour.모든 이벤트 - Access Denied - 접근 거부됨 + All Execs + 모든 실행 Hover over the graph for details. @@ -4221,6 +4495,34 @@ For example, use 1 hour to have a new file created every hour on the hour.Click to select a portion of the graph. 클릭하여 그래프의 부분을 선택하십시오. + + %1 Intervals + 간격 %1 + + + Move to top left + 왼쪽 위로 이동 + + + Move to top center + 가운데 위로 이동 + + + Move to top right + 오른쪽 위로 이동 + + + Move to bottom left + 왼쪽 아래로 이동 + + + Move to bottom center + 가운데 아래로 이동 + + + Move to bottom right + 오른쪽 아래로 이동 + Portable Document Format (*.pdf) PDF 형식 (*.pdf) @@ -4973,6 +5275,13 @@ For example, use 1 hour to have a new file created every hour on the hour.변경 사항 적용 + + InterfaceTreeDelegate + + default + 기본값 + + InterfaceTreeModel @@ -5473,7 +5782,7 @@ For example, use 1 hour to have a new file created every hour on the hour. details for transport - 전송 상세 정보 + 전송 자세한 정보 XXXXX:XXX.XXX.XXX.XXX:XXXXX:XXXXXXXX:XXX.XXX.XXX.XXX:XXXXX @@ -5882,7 +6191,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Packet Details - 패킷 상세 정보 + 패킷 자세한 정보 Packet Bytes @@ -5948,8 +6257,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteMacStatisticsDialog - LTE Mac Statistics - LTE MAC 통계 + LTE/NR Mac Statistics + LTE/NR MAC 통계 Include SR frames in filter @@ -6253,12 +6562,12 @@ For example, use 1 hour to have a new file created every hour on the hour.시퀀스 번호 - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) - LTE RLC 그래프(UE=%1 chan=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) + %1 RLC 그래프 (UE=%2 chan=%3%4 %5 - %6) - LTE RLC Graph - no channel selected - LTE RLC 그래프 - 선택한 채널 없음 + 3GPP RLC Graph - no channel selected + 3GPP RLC 그래프 - 선택한 채널 없음 Save As… @@ -6312,8 +6621,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteRlcStatisticsDialog - LTE RLC Statistics - LTE RLC 통계 + 3GPP RLC Statistics + 3GPP RLC 통계 Include SR frames in filter @@ -6398,6 +6707,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Profile: %1 프로필: %1 + + %1 Displayed: %2 (%3%) + %1개 표시됨: %2(%3%) + Manage Profiles… 프로필 관리… @@ -6459,6 +6772,12 @@ For example, use 1 hour to have a new file created every hour on the hour.%Ln바이트 + + %Ln bit(s) + + %Ln비트 + + Byte %1 바이트 %1 @@ -6472,9 +6791,12 @@ For example, use 1 hour to have a new file created every hour on the hour.선택된 패킷: %1 %2 - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 - 패킷 수: %1 %4 표시됨: %2(%3%) + Selected Event: %1 %2 + 선택된 이벤트: %1 %2 + + + Events: %1 + 이벤트: %1 %1 Selected: %2 (%3%) @@ -6505,6 +6827,10 @@ For example, use 1 hour to have a new file created every hour on the hour.No Packets 패킷 없음 + + No Events + 이벤트 없음 + From Zip File... ZIP 파일에서... @@ -6536,6 +6862,13 @@ For example, use 1 hour to have a new file created every hour on the hour. + + MainWindow + + Display filter as %1 + %1(으)로 표시 필터 + + MainWindowPreferencesFrame @@ -6567,6 +6900,10 @@ For example, use 1 hour to have a new file created every hour on the hour.The most recently used folder 가장 최근에 사용한 폴더 + + The current working directory + 현재 작업 디렉터리 + Show up to 최대 표시 개수 @@ -6997,6 +7334,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show Field Values 필드 값 표시 + + Refresh + 새로 고침 + Save Diagram As… 다른 이름으로 다이어그램 저장… @@ -7044,6 +7385,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show packet bytes 패킷 바이트 표시 + + Layout: + 레이아웃: + Packet %1 패킷 %1 @@ -7066,6 +7411,12 @@ For example, use 1 hour to have a new file created every hour on the hour.%Ln바이트 + + %Ln bit(s) + + %Ln비트 + + PacketFormatGroupBox @@ -7524,10 +7875,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy this profile. 이 프로필을 복사합니다. + + The number of packets or events to check for automatic profile switching. + 자동 프로필 전환 시 점검할 패킷이나 이벤트 개수입니다. + + + Auto switch packet limit + 자동 전환 패킷 제한 + Configuration Profiles 설정 프로필 + + Auto switch event limit + 자동 전환 이벤트 제한 + Import noun @@ -7703,6 +8066,10 @@ For example, use 1 hour to have a new file created every hour on the hour.deleted 삭제됨 + + Auto Switch Filter + 자동 전환 필터 + copy noun @@ -8064,7 +8431,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Unacked (Outstanding) Bytes (B) - + ACK되지 않은(대기 중) 바이트(바이트) [no capture file] @@ -8226,6 +8593,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Marker missing? 마커 없음? + + LTE + LTE + + + NR + NR + C-RNTI C-RNTI @@ -8246,6 +8621,10 @@ For example, use 1 hour to have a new file created every hour on the hour.UEId UEId + + RAT + RAT + UL Frames UL 프레임 @@ -8470,9 +8849,69 @@ For example, use 1 hour to have a new file created every hour on the hour.Browse… 찾아보기... + + PACKETS + 패킷 + + + EVENTS + 이벤트 + + + BYTES + 바이트 + + + BITS + 비트 + + + COUNT FRAMES + 프레임 개수 + + + COUNT FIELDS + 필드 개수 + + + SUM + 합계 + + + MAX + 최댓값 + + + MIN + 최솟값 + + + AVERAGE + 평균 + + + THROUGHPUT + 처리량 + + + LOAD + 부하 + + + Left + 왼쪽 + + + Center + 가운데 + + + Right + 오른쪽 + - QObject::QObject + QObject::QObject::QObject CCCH CCCH @@ -8572,6 +9011,13 @@ For example, use 1 hour to have a new file created every hour on the hour.밀리초 + + ResizeHeaderView + + Resize all %1 to contents + 모든 %1을(를) 내용에 맞게 조정 + + ResolvedAddressesDialog @@ -8687,6 +9133,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved Addresses 해석된 주소 + + Copy + 복사 + + + Save as… + 다른 이름으로 저장… + # Resolved addresses found in %1 # %1에서 발견된 해석된 주소 @@ -8700,6 +9154,61 @@ For example, use 1 hour to have a new file created every hour on the hour. + + ResolvedAddressesView + + as Plain Text + 일반 텍스트로 + + + Copy selected rows + 선택한 행 복사 + + + Copy table + 표 복사 + + + as CSV + CSV로 + + + as JSON + JSON으로 + + + Save selected rows as… + 선택한 행을 다른 이름으로 저장… + + + Save table as… + 표를 다른 이름으로 저장… + + + Save Resolved Addresses As… + 해석된 주소를 다른 이름으로 저장… + + + Plain text (*.txt) + 일반 텍스트 (*.txt) + + + CSV Document (*.csv) + CSV 문서 (*.csv) + + + JSON Document (*.json) + JSON 문서 (*.json) + + + Warning + 경고 + + + Unable to save %1: %2 + %1을(를) 저장할 수 없음: %2 + + ResponseTimeDelayDialog @@ -10374,6 +10883,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Packet bytes 패킷 바이트 + + <b>Options:</b> + <b>옵션:</b> + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>좁은 문자(UTF-8과 ASCII) 또는 넓은 문자(UTF-16)를 포함하는 문자열을 검색합니다.</p></body></html> @@ -10394,6 +10907,18 @@ For example, use 1 hour to have a new file created every hour on the hour.Case sensitive 대소문자 구분 + + Backwards + 역방향 + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + <html><head/><body><p>다음 패킷으로 진행하기 전에 현재 패킷에서 일치 여부를 계속 검색합니다.</p></body></html> + + + Multiple occurrences + 여러 번 발견됨 + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10431,6 +10956,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Invalid filter. 잘못된 필터입니다. + + Event List + 이벤트 목록 + + + Event Details + 이벤트 자세한 정보 + + + Event Bytes + 이벤트 바이트 + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + <html><head/><body><p>이벤트 목록의 정보 열(요약 패널), 디코드된 이벤트 표시 이름표(트리 보기 패널), ASCII로 변환된 이벤트 데이터(16진수 보기 패널) 중에서 검색합니다.</p></body></html> + That filter doesn't test anything. 필터에서 아무것도 시험하지 않습니다. @@ -10872,6 +11413,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: 찾기: + + Case sensitive + 대소문자 구분 + Find &Next 다음 찾기(&N) @@ -10966,14 +11511,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Save as… 다른 이름으로 저장… + + Decoded as %1. + %1(으)로 디코드했습니다. + Save Selected Packet Bytes As… 선택한 패킷 바이트를 다른 이름으로 저장… + + compressed %1 + %1 압축됨 + - Displaying %Ln byte(s). + Using %Ln byte(s). - %Ln바이트를 표시하고 있습니다. + %Ln바이트를 사용합니다. @@ -11073,6 +11626,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: 표시 필터: + + Strip Headers + 헤더 잘라내기 + SupportedProtocolsDialog @@ -12046,22 +12603,20 @@ For example, use 1 hour to have a new file created every hour on the hour.새 항목을 만듭니다. - Remove this entry. - Remove this profile. - 이 항목을 삭제합니다. + Remove the selected entry(ies). + 선택한 항목을 삭제합니다. - Copy this entry. - Copy this profile. - 이 항목을 복사합니다. + Copy the selected entry(ies). + 선택한 항목을 복사합니다. - Move entry up. - 항목을 위로 이동합니다. + Move the selected entry(ies) up. + 선택한 항목을 위로 이동합니다. - Move entry down. - 항목을 아래로 이동합니다. + Move the selected entry(ies) down. + 선택한 항목을 아래로 이동합니다. Clear all entries. @@ -12087,20 +12642,20 @@ For example, use 1 hour to have a new file created every hour on the hour.새 항목을 만듭니다. - Remove this entry. - 이 항목을 삭제합니다. + Remove the selected entry(ies). + 선택한 항목을 삭제합니다. - Copy this entry. - 이 항목을 복사합니다. + Copy the selected entry(ies). + 선택한 항목을 복사합니다. - Move entry up. - 항목을 위로 이동합니다. + Move the selected entry(ies) up. + 선택한 항목을 위로 이동합니다. - Move entry down. - 항목을 아래로 이동합니다. + Move the selected entry(ies) down. + 선택한 항목을 아래로 이동합니다. Clear all entries. @@ -12469,10 +13024,18 @@ a:hover { You are sniffing the glue that holds the Internet together using Wireshark Wireshark를 사용하여 인터넷을 고정하는 접착제의 냄새를 맡고(스니핑) 있습니다 + + You are sniffing the glue that holds your system together using Logray + Logray를 사용하여 시스템을 고정하는 접착제의 냄새를 맡고(스니핑) 있습니다 + You are running Wireshark 실행 중인 Wireshark 버전: + + You are running Logray + 실행 중인 Logray 버전: + You receive automatic updates. 자동 업데이트를 받고 있습니다. @@ -12749,14 +13312,6 @@ a:hover { No files found 찾은 파일 없음 - - &Contents - 내용(&C) - - - Wireshark Filter - Wireshark 필터 - TShark TShark @@ -13022,10 +13577,6 @@ a:hover { Wireless Toolbar 무선 도구 모음 - - Help contents - 도움말 내용 - FAQs 자주 묻는 질문 @@ -13146,11 +13697,6 @@ a:hover { Find the previous packet 이전 패킷 찾기 - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - 패킷 마크/해제(&M) - Mark All Displayed 표시된 모든 패킷 마크 @@ -13179,11 +13725,6 @@ a:hover { Go to the previous marked packet 이전 마크한 패킷으로 이동 - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - 패킷 무시/해제(&I) - Ignore All Displayed 표시된 모든 패킷 무시 @@ -13624,10 +14165,6 @@ a:hover { Reset Layout 레이아웃 초기화 - - Reset appearance layout to default size - 외관 레이아웃을 기본 크기로 초기화 - Seconds Since First Captured Packet 최초로 캡처된 패킷부터 지난 초 단위 시간 @@ -13788,22 +14325,30 @@ a:hover { MAC Address Blocks MAC 주소 블록 - - TLS Keylog Launcher - TLS 키로그 실행기 - - - Release Notes - 릴리스 노트 - &Options… 옵션(&O)… + + &3GPP Uu + 3GPP Uu(&3) + &Wireless 무선(&W) + + &User's Guide + 사용자 설명서(&U) + + + Wireshark User's Guide + Wireshark 사용자 설명서 + + + Display Filters + 표시 필터 + Capture &Filters… 캡처 필터(&F)… @@ -13848,10 +14393,18 @@ a:hover { Find Pre&vious 이전 찾기(&V) + + &Mark/Unmark Selected + 선택 항목 마크/해제(&M) + Mark or unmark each selected packet 각 선택된 패킷 마크/해제 + + &Ignore/Unignore Selected + 선택 항목 무시/해제(&I) + Ignore or unignore each selected packet 각 선택된 패킷 무시/해제 @@ -13892,6 +14445,18 @@ a:hover { TCP throughput TCP 처리량 + + General + 일반 + + + Query-Response + 질의-응답 + + + DNS Query-Response Statistics + DNS 질의-응답 통계 + Request Sequences 요청 시퀀스 @@ -13900,6 +14465,14 @@ a:hover { HTTP Request Sequences HTTP 요청 시퀀스 + + E2AP + E2AP + + + E2AP Messages + E2AP 메시지 + Decode &As… 다른 형식으로 디코드(&A)… @@ -13960,6 +14533,10 @@ a:hover { Normal Size 보통 크기 + + Reset layout to default size + 레이아웃을 기본값으로 초기화 + Resize Columns 열 크기 조정 @@ -14218,6 +14795,14 @@ a:hover { Go to the packet referenced by the selected field. 선택한 필드에서 참조하는 패킷으로 이동합니다. + + TLS Keylog Launcher + TLS 키로그 실행기 + + + Release Notes + 릴리스 노트 + &VoIP Calls VoIP 호(&V) @@ -14250,10 +14835,6 @@ a:hover { &GSM GSM(&G) - - &LTE - LTE(&L) - &MTP3 MTP3(&M) @@ -14538,6 +15119,10 @@ a:hover { Quit without Saving 저장하지 않고 끝내기(&W) + + USB CDC Data + USB CDC 데이터 + There is no "rtp.ssrc" field in this version of Wireshark. 이 버전의 Wireshark에는 "rtp.ssrc" 필드가 없습니다. diff --git a/ui/qt/wireshark_main_window.cpp b/ui/qt/wireshark_main_window.cpp index 040c45ba..d1f7dcd0 100644 --- a/ui/qt/wireshark_main_window.cpp +++ b/ui/qt/wireshark_main_window.cpp @@ -12,7 +12,7 @@ /* * The generated Ui_WiresharkMainWindow::setupUi() can grow larger than our configured limit, - * so turn off -Wframe-larger-than= for ui_main_window.h. + * so turn off -Wframe-larger-than= for ui_wireshark_main_window.h. */ DIAG_OFF(frame-larger-than=) #include @@ -32,6 +32,7 @@ DIAG_ON(frame-larger-than=) #include #include "ui/iface_toolbar.h" +#include "ui/commandline.h" #ifdef HAVE_LIBPCAP #include "ui/capture.h" @@ -75,6 +76,7 @@ DIAG_ON(frame-larger-than=) #include #include +#include #include #include #include @@ -96,7 +98,7 @@ DIAG_ON(frame-larger-than=) //menu_recent_file_write_all // If we ever add support for multiple windows this will need to be replaced. -static WiresharkMainWindow *gbl_cur_main_window_ = NULL; +static WiresharkMainWindow *gbl_cur_main_window_; static void plugin_if_mainwindow_apply_filter(GHashTable * data_set) { @@ -119,9 +121,9 @@ static void plugin_if_mainwindow_preference(GHashTable * data_set) const char * pref_value; DIAG_OFF_CAST_AWAY_CONST - if (g_hash_table_lookup_extended(data_set, "pref_module", NULL, (gpointer *)&module_name) && - g_hash_table_lookup_extended(data_set, "pref_key", NULL, (gpointer *)&pref_name) && - g_hash_table_lookup_extended(data_set, "pref_value", NULL, (gpointer *)&pref_value)) + if (g_hash_table_lookup_extended(data_set, "pref_module", NULL, (void * *)&module_name) && + g_hash_table_lookup_extended(data_set, "pref_key", NULL, (void * *)&pref_name) && + g_hash_table_lookup_extended(data_set, "pref_value", NULL, (void * *)&pref_value)) { unsigned int changed_flags = prefs_store_ext(module_name, pref_name, pref_value); if (changed_flags) { @@ -137,7 +139,7 @@ static void plugin_if_mainwindow_gotoframe(GHashTable * data_set) if (!gbl_cur_main_window_ || !data_set) return; - gpointer framenr; + void *framenr; if (g_hash_table_lookup_extended(data_set, "frame_nr", NULL, &framenr)) { if (GPOINTER_TO_UINT(framenr) != 0) @@ -215,7 +217,7 @@ static void plugin_if_mainwindow_get_ws_info(GHashTable * data_set) } else { ws_info->cf_framenr = 0; - ws_info->frame_passed_dfilter = FALSE; + ws_info->frame_passed_dfilter = false; } } else @@ -223,7 +225,7 @@ static void plugin_if_mainwindow_get_ws_info(GHashTable * data_set) /* Initialise the other ws_info structure values */ ws_info->cf_count = 0; ws_info->cf_framenr = 0; - ws_info->frame_passed_dfilter = FALSE; + ws_info->frame_passed_dfilter = false; } } @@ -293,7 +295,7 @@ static void mainwindow_add_toolbar(const iface_toolbar *toolbar_entry) } } -static void mainwindow_remove_toolbar(const gchar *menu_title) +static void mainwindow_remove_toolbar(const char *menu_title) { if (gbl_cur_main_window_ && menu_title) { @@ -301,16 +303,22 @@ static void mainwindow_remove_toolbar(const gchar *menu_title) } } -QMenu* WiresharkMainWindow::findOrAddMenu(QMenu *parent_menu, QString& menu_text) { - QList actions = parent_menu->actions(); - QList::const_iterator i; - for (i = actions.constBegin(); i != actions.constEnd(); ++i) { - if ((*i)->text()==menu_text) { - return (*i)->menu(); +QMenu* WiresharkMainWindow::findOrAddMenu(QMenu *parent_menu, const QStringList& menu_parts) { + for (auto const & menu_text : menu_parts) { + bool found = false; + for (auto const & action : parent_menu->actions()) { + if (action->text() == menu_text.trimmed()) { + parent_menu = action->menu(); + found = true; + break; + } + } + if (!found) { + // If we get here the menu entry was not found, add a sub menu + parent_menu = parent_menu->addMenu(menu_text.trimmed()); } } - // If we get here there menu entry was not found, add a sub menu - return parent_menu->addMenu(menu_text); + return parent_menu; } WiresharkMainWindow::WiresharkMainWindow(QWidget *parent) : @@ -325,7 +333,8 @@ WiresharkMainWindow::WiresharkMainWindow(QWidget *parent) : freeze_focus_(NULL), was_maximized_(false), capture_stopping_(false), - capture_filter_valid_(false) + capture_filter_valid_(false), + use_capturing_title_(false) #ifdef HAVE_LIBPCAP , capture_options_dialog_(NULL) , info_data_() @@ -335,10 +344,9 @@ WiresharkMainWindow::WiresharkMainWindow(QWidget *parent) : #endif { if (!gbl_cur_main_window_) { - connect(mainApp, SIGNAL(openStatCommandDialog(QString, const char*, void*)), - this, SLOT(openStatCommandDialog(QString, const char*, void*))); - connect(mainApp, SIGNAL(openTapParameterDialog(QString, const QString, void*)), - this, SLOT(openTapParameterDialog(QString, const QString, void*))); + connect(mainApp, &MainApplication::openStatCommandDialog, this, &WiresharkMainWindow::openStatCommandDialog); + connect(mainApp, &MainApplication::openTapParameterDialog, + this, [=](const QString cfg_str, const QString arg, void *userdata) {openTapParameterDialog(cfg_str, arg, userdata);}); } gbl_cur_main_window_ = this; #ifdef HAVE_LIBPCAP @@ -363,23 +371,20 @@ WiresharkMainWindow::WiresharkMainWindow(QWidget *parent) : menu_groups_ = QList() << REGISTER_PACKET_ANALYZE_GROUP_UNSORTED - << REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER << REGISTER_PACKET_STAT_GROUP_UNSORTED << REGISTER_STAT_GROUP_GENERIC - << REGISTER_STAT_GROUP_CONVERSATION_LIST - << REGISTER_STAT_GROUP_ENDPOINT_LIST << REGISTER_STAT_GROUP_RESPONSE_TIME << REGISTER_STAT_GROUP_RSERPOOL - << REGISTER_STAT_GROUP_TELEPHONY - << REGISTER_STAT_GROUP_TELEPHONY_ANSI - << REGISTER_STAT_GROUP_TELEPHONY_GSM - << REGISTER_STAT_GROUP_TELEPHONY_LTE - << REGISTER_STAT_GROUP_TELEPHONY_MTP3 - << REGISTER_STAT_GROUP_TELEPHONY_SCTP + << REGISTER_TELEPHONY_GROUP_UNSORTED + << REGISTER_TELEPHONY_GROUP_ANSI + << REGISTER_TELEPHONY_GROUP_GSM + << REGISTER_TELEPHONY_GROUP_3GPP_UU + << REGISTER_TELEPHONY_GROUP_MTP3 + << REGISTER_TELEPHONY_GROUP_SCTP << REGISTER_TOOLS_GROUP_UNSORTED; setWindowIcon(mainApp->normalIcon()); - setTitlebarForCaptureFile(); + updateTitlebar(); setMenusForCaptureFile(); setForCapturedPackets(false); setMenusForFileSet(false); @@ -392,36 +397,37 @@ WiresharkMainWindow::WiresharkMainWindow(QWidget *parent) : qRegisterMetaType("FilterAction::Action"); qRegisterMetaType("FilterAction::ActionType"); - connect(this, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType)), - this, SLOT(queuedFilterAction(QString, FilterAction::Action, FilterAction::ActionType)), - Qt::QueuedConnection); + connect(this, &WiresharkMainWindow::filterAction, this, &WiresharkMainWindow::queuedFilterAction, Qt::QueuedConnection); //To prevent users use features before initialization complete //Otherwise unexpected problems may occur setFeaturesEnabled(false); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(setFeaturesEnabled())); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(applyGlobalCommandLineOptions())); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(zoomText())); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(initViewColorizeMenu())); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(addStatsPluginsToMenu())); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(addDynamicMenus())); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(addPluginIFStructures())); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(initConversationMenus())); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(initExportObjectsMenus())); - connect(mainApp, SIGNAL(appInitialized()), this, SLOT(initFollowStreamMenus())); - - connect(mainApp, SIGNAL(profileChanging()), this, SLOT(saveWindowGeometry())); - connect(mainApp, SIGNAL(preferencesChanged()), this, SLOT(layoutPanes())); - connect(mainApp, SIGNAL(preferencesChanged()), this, SLOT(layoutToolbars())); - connect(mainApp, SIGNAL(preferencesChanged()), this, SLOT(updatePreferenceActions())); - connect(mainApp, SIGNAL(preferencesChanged()), this, SLOT(zoomText())); - connect(mainApp, SIGNAL(preferencesChanged()), this, SLOT(setTitlebarForCaptureFile())); - - connect(mainApp, SIGNAL(updateRecentCaptureStatus(const QString &, qint64, bool)), this, SLOT(updateRecentCaptures())); + connect(mainApp, &MainApplication::appInitialized, this, [this]() { setFeaturesEnabled(); }); + connect(mainApp, &MainApplication::appInitialized, this, &WiresharkMainWindow::applyGlobalCommandLineOptions); + connect(mainApp, &MainApplication::appInitialized, this, &WiresharkMainWindow::zoomText); + connect(mainApp, &MainApplication::appInitialized, this, &WiresharkMainWindow::initViewColorizeMenu); + connect(mainApp, &MainApplication::appInitialized, this, &WiresharkMainWindow::addStatsPluginsToMenu); + connect(mainApp, &MainApplication::appInitialized, this, &WiresharkMainWindow::addDynamicMenus); + connect(mainApp, &MainApplication::appInitialized, this, &WiresharkMainWindow::addPluginIFStructures); + connect(mainApp, &MainApplication::appInitialized, this, &WiresharkMainWindow::initConversationMenus); + connect(mainApp, &MainApplication::appInitialized, this, &WiresharkMainWindow::initExportObjectsMenus); + connect(mainApp, &MainApplication::appInitialized, this, &WiresharkMainWindow::initFollowStreamMenus); + connect(mainApp, &MainApplication::appInitialized, this, + [=]() { addDisplayFilterTranslationActions(main_ui_->menuEditCopy); }); + + connect(mainApp, &MainApplication::profileChanging, this, &WiresharkMainWindow::saveWindowGeometry); + connect(mainApp, &MainApplication::preferencesChanged, this, &WiresharkMainWindow::layoutPanes); + connect(mainApp, &MainApplication::preferencesChanged, this, &WiresharkMainWindow::layoutToolbars); + connect(mainApp, &MainApplication::preferencesChanged, this, &WiresharkMainWindow::updatePreferenceActions); + connect(mainApp, &MainApplication::preferencesChanged, this, &WiresharkMainWindow::zoomText); + connect(mainApp, &MainApplication::preferencesChanged, this, &WiresharkMainWindow::updateTitlebar); + + connect(mainApp, &MainApplication::updateRecentCaptureStatus, this, &WiresharkMainWindow::updateRecentCaptures); + connect(mainApp, &MainApplication::preferencesChanged, this, &WiresharkMainWindow::updateRecentCaptures); updateRecentCaptures(); #if defined(HAVE_SOFTWARE_UPDATE) && defined(Q_OS_WIN) - connect(mainApp, SIGNAL(softwareUpdateRequested()), this, SLOT(softwareUpdateRequested()), + connect(mainApp, &MainApplication::softwareUpdateRequested, this, &WiresharkMainWindow::softwareUpdateRequested, Qt::BlockingQueuedConnection); #endif @@ -430,12 +436,13 @@ WiresharkMainWindow::WiresharkMainWindow(QWidget *parent) : funnel_statistics_ = new FunnelStatistics(this, capture_file_); connect(df_combo_box_, &QComboBox::editTextChanged, funnel_statistics_, &FunnelStatistics::displayFilterTextChanged); connect(funnel_statistics_, &FunnelStatistics::setDisplayFilter, this, &WiresharkMainWindow::setDisplayFilter); - connect(funnel_statistics_, SIGNAL(openCaptureFile(QString, QString)), - this, SLOT(openCaptureFile(QString, QString))); + connect(funnel_statistics_, &FunnelStatistics::openCaptureFile, this, + [=](QString cf_path, QString filter) { openCaptureFile(cf_path, filter); }); + + connect(df_combo_box_, &QComboBox::editTextChanged, this, &WiresharkMainWindow::updateDisplayFilterTranslationActions); file_set_dialog_ = new FileSetDialog(this); - connect(file_set_dialog_, SIGNAL(fileSetOpenCaptureFile(QString)), - this, SLOT(openCaptureFile(QString))); + connect(file_set_dialog_, &FileSetDialog::fileSetOpenCaptureFile, this, [=](QString cf_path) { openCaptureFile(cf_path); }); initMainToolbarIcons(); @@ -452,20 +459,17 @@ WiresharkMainWindow::WiresharkMainWindow(QWidget *parent) : main_ui_->displayFilterToolBar->addWidget(filter_expression_toolbar_); #if defined(HAVE_LIBNL) && defined(HAVE_NL80211) - connect(wireless_frame_, SIGNAL(showWirelessPreferences(QString)), - this, SLOT(showPreferencesDialog(QString))); + connect(wireless_frame_, &WirelessFrame::showWirelessPreferences, this, &WiresharkMainWindow::showPreferencesDialog); #endif main_ui_->goToFrame->hide(); - connect(main_ui_->goToFrame, SIGNAL(visibilityChanged(bool)), - main_ui_->actionGoGoToPacket, SLOT(setChecked(bool))); + connect(main_ui_->goToFrame, &AccordionFrame::visibilityChanged, main_ui_->actionGoGoToPacket, &QAction::setChecked); // XXX For some reason the cursor is drawn funny with an input mask set // https://bugreports.qt-project.org/browse/QTBUG-7174 main_ui_->searchFrame->hide(); - connect(main_ui_->searchFrame, SIGNAL(visibilityChanged(bool)), - main_ui_->actionEditFindPacket, SLOT(setChecked(bool))); + connect(main_ui_->searchFrame, &SearchFrame::visibilityChanged, main_ui_->actionEditFindPacket, &QAction::setChecked); main_ui_->addressEditorFrame->hide(); main_ui_->columnEditorFrame->hide(); @@ -512,7 +516,7 @@ main_ui_->goToLineEdit->setValidator(goToLineQiv); #ifdef HAVE_SOFTWARE_UPDATE QAction *update_sep = main_ui_->menuHelp->insertSeparator(main_ui_->actionHelpAbout); main_ui_->menuHelp->insertAction(update_sep, update_action_); - connect(update_action_, SIGNAL(triggered()), this, SLOT(checkForUpdates())); + connect(update_action_, &QAction::triggered, this, &WiresharkMainWindow::checkForUpdates); #endif master_split_.setObjectName("splitterMaster"); extra_split_.setObjectName("splitterExtra"); @@ -525,18 +529,19 @@ main_ui_->goToLineEdit->setValidator(goToLineQiv); packet_list_ = new PacketList(&master_split_); main_ui_->wirelessTimelineWidget->setPacketList(packet_list_); - connect(packet_list_, SIGNAL(framesSelected(QList)), this, SLOT(setMenusForSelectedPacket())); - connect(packet_list_, SIGNAL(framesSelected(QList)), this, SIGNAL(framesSelected(QList))); + connect(packet_list_, &PacketList::framesSelected, this, &WiresharkMainWindow::setMenusForSelectedPacket); + connect(packet_list_, &PacketList::framesSelected, this, &WiresharkMainWindow::framesSelected); QAction *action = main_ui_->menuPacketComment->addAction(tr("Add New Comment…")); connect(action, &QAction::triggered, this, &WiresharkMainWindow::addPacketComment); action->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_C)); - connect(main_ui_->menuPacketComment, SIGNAL(aboutToShow()), this, SLOT(setEditCommentsMenu())); + connect(main_ui_->menuPacketComment, &QMenu::aboutToShow, this, &WiresharkMainWindow::setEditCommentsMenu); proto_tree_ = new ProtoTree(&master_split_); proto_tree_->installEventFilter(this); packet_list_->setProtoTree(proto_tree_); + packet_list_->setProfileSwitcher(profile_switcher_); packet_list_->installEventFilter(this); packet_diagram_ = new PacketDiagram(&master_split_); @@ -576,40 +581,27 @@ main_ui_->goToLineEdit->setValidator(goToLineQiv); setTabOrder(df_combo_box_->lineEdit(), packet_list_); setTabOrder(packet_list_, proto_tree_); - connect(&capture_file_, SIGNAL(captureEvent(CaptureEvent)), - this, SLOT(captureEventHandler(CaptureEvent))); - connect(&capture_file_, SIGNAL(captureEvent(CaptureEvent)), - mainApp, SLOT(captureEventHandler(CaptureEvent))); - connect(&capture_file_, SIGNAL(captureEvent(CaptureEvent)), - main_ui_->statusBar, SLOT(captureEventHandler(CaptureEvent))); - - connect(mainApp, SIGNAL(freezePacketList(bool)), - packet_list_, SLOT(freezePacketList(bool))); - connect(mainApp, SIGNAL(columnsChanged()), - packet_list_, SLOT(columnsChanged())); - connect(mainApp, SIGNAL(preferencesChanged()), - packet_list_, SLOT(preferencesChanged())); - connect(mainApp, SIGNAL(recentPreferencesRead()), - this, SLOT(applyRecentPaneGeometry())); - connect(mainApp, SIGNAL(recentPreferencesRead()), - this, SLOT(updateRecentActions())); - connect(mainApp, SIGNAL(packetDissectionChanged()), - this, SLOT(redissectPackets()), Qt::QueuedConnection); - - connect(mainApp, SIGNAL(checkDisplayFilter()), - this, SLOT(checkDisplayFilter())); - connect(mainApp, SIGNAL(fieldsChanged()), - this, SLOT(fieldsChanged())); - connect(mainApp, SIGNAL(reloadLuaPlugins()), - this, SLOT(reloadLuaPlugins())); - - connect(main_ui_->mainStack, SIGNAL(currentChanged(int)), - this, SLOT(mainStackChanged(int))); - - connect(welcome_page_, SIGNAL(startCapture(QStringList)), - this, SLOT(startCapture(QStringList))); - connect(welcome_page_, SIGNAL(recentFileActivated(QString)), - this, SLOT(openCaptureFile(QString))); + connect(&capture_file_, &CaptureFile::captureEvent, this, &WiresharkMainWindow::captureEventHandler); + connect(&capture_file_, &CaptureFile::captureEvent, mainApp, &WiresharkApplication::captureEventHandler); + connect(&capture_file_, &CaptureFile::captureEvent, main_ui_->statusBar, &MainStatusBar::captureEventHandler); + connect(&capture_file_, &CaptureFile::captureEvent, profile_switcher_, &ProfileSwitcher::captureEventHandler); + + connect(mainApp, &MainApplication::freezePacketList, packet_list_, &PacketList::freezePacketList); + connect(mainApp, &MainApplication::columnsChanged, packet_list_, &PacketList::columnsChanged); + connect(mainApp, &MainApplication::colorsChanged, packet_list_, &PacketList::colorsChanged); + connect(mainApp, &MainApplication::preferencesChanged, packet_list_, &PacketList::preferencesChanged); + connect(mainApp, &MainApplication::recentPreferencesRead, this, &WiresharkMainWindow::applyRecentPaneGeometry); + connect(mainApp, &MainApplication::recentPreferencesRead, this, &WiresharkMainWindow::updateRecentActions); + connect(mainApp, &MainApplication::packetDissectionChanged, this, &WiresharkMainWindow::redissectPackets, Qt::QueuedConnection); + + connect(mainApp, &MainApplication::checkDisplayFilter, this, &WiresharkMainWindow::checkDisplayFilter); + connect(mainApp, &MainApplication::fieldsChanged, this, &WiresharkMainWindow::fieldsChanged); + connect(mainApp, &MainApplication::reloadLuaPlugins, this, &WiresharkMainWindow::reloadLuaPlugins); + + connect(main_ui_->mainStack, &QStackedWidget::currentChanged, this, &WiresharkMainWindow::mainStackChanged); + + connect(welcome_page_, &WelcomePage::startCapture, this, [this](QStringList interfaces) { startCapture(interfaces); }); + connect(welcome_page_, &WelcomePage::recentFileActivated, this, [this](QString cfile) { openCaptureFile(cfile); }); connect(main_ui_->addressEditorFrame, &AddressEditorFrame::redissectPackets, this, &WiresharkMainWindow::redissectPackets); @@ -632,10 +624,9 @@ main_ui_->goToLineEdit->setValidator(goToLineQiv); connect(this, &WiresharkMainWindow::setCaptureFile, proto_tree_, &ProtoTree::setCaptureFile); - connect(mainApp, SIGNAL(zoomMonospaceFont(QFont)), - packet_list_, SLOT(setMonospaceFont(QFont))); - connect(mainApp, SIGNAL(zoomMonospaceFont(QFont)), - proto_tree_, SLOT(setMonospaceFont(QFont))); + connect(mainApp, &MainApplication::zoomMonospaceFont, packet_list_, &PacketList::setMonospaceFont); + connect(mainApp, &MainApplication::zoomRegularFont, packet_list_, &PacketList::setRegularFont); + connect(mainApp, &MainApplication::zoomMonospaceFont, proto_tree_, &ProtoTree::setMonospaceFont); connectFileMenuActions(); connectEditMenuActions(); @@ -649,26 +640,18 @@ main_ui_->goToLineEdit->setValidator(goToLineQiv); connectToolsMenuActions(); connectHelpMenuActions(); - connect(packet_list_, SIGNAL(packetDissectionChanged()), - this, SLOT(redissectPackets())); - connect(packet_list_, SIGNAL(showColumnPreferences(QString)), - this, SLOT(showPreferencesDialog(QString))); - connect(packet_list_, SIGNAL(showProtocolPreferences(QString)), - this, SLOT(showPreferencesDialog(QString))); + connect(packet_list_, &PacketList::packetDissectionChanged, this, &WiresharkMainWindow::redissectPackets); + connect(packet_list_, &PacketList::showColumnPreferences, this, &WiresharkMainWindow::showPreferencesDialog); + connect(packet_list_, &PacketList::showProtocolPreferences, this, &WiresharkMainWindow::showPreferencesDialog); connect(packet_list_, SIGNAL(editProtocolPreference(preference*, pref_module*)), main_ui_->preferenceEditorFrame, SLOT(editPreference(preference*, pref_module*))); - connect(packet_list_, SIGNAL(editColumn(int)), this, SLOT(showColumnEditor(int))); - connect(main_ui_->columnEditorFrame, SIGNAL(columnEdited()), - packet_list_, SLOT(columnsChanged())); - connect(packet_list_, SIGNAL(doubleClicked(QModelIndex)), - this, SLOT(openPacketDialog())); - connect(packet_list_, SIGNAL(packetListScrolled(bool)), - main_ui_->actionGoAutoScroll, SLOT(setChecked(bool))); - - connect(proto_tree_, SIGNAL(openPacketInNewWindow(bool)), - this, SLOT(openPacketDialog(bool))); - connect(proto_tree_, SIGNAL(showProtocolPreferences(QString)), - this, SLOT(showPreferencesDialog(QString))); + connect(packet_list_, &PacketList::editColumn, this, &WiresharkMainWindow::showColumnEditor); + connect(main_ui_->columnEditorFrame, &ColumnEditorFrame::columnEdited, packet_list_, &PacketList::columnsChanged); + connect(packet_list_, &QAbstractItemView::doubleClicked, this, [=](const QModelIndex &){ openPacketDialog(); }); + connect(packet_list_, &PacketList::packetListScrolled, main_ui_->actionGoAutoScroll, &QAction::setChecked); + + connect(proto_tree_, &ProtoTree::openPacketInNewWindow, this, &WiresharkMainWindow::openPacketDialog); + connect(proto_tree_, &ProtoTree::showProtocolPreferences, this, &WiresharkMainWindow::showPreferencesDialog); connect(proto_tree_, SIGNAL(editProtocolPreference(preference*, pref_module*)), main_ui_->preferenceEditorFrame, SLOT(editPreference(preference*, pref_module*))); @@ -690,16 +673,13 @@ main_ui_->goToLineEdit->setValidator(goToLineQiv); #ifdef HAVE_LIBPCAP QTreeWidget *iface_tree = findChild("interfaceTree"); if (iface_tree) { - connect(iface_tree, SIGNAL(itemSelectionChanged()), - this, SLOT(interfaceSelectionChanged())); + connect(iface_tree, &QTreeWidget::itemSelectionChanged, this, &WiresharkMainWindow::interfaceSelectionChanged); } - connect(main_ui_->welcomePage, SIGNAL(captureFilterSyntaxChanged(bool)), - this, SLOT(captureFilterSyntaxChanged(bool))); + connect(main_ui_->welcomePage, &WelcomePage::captureFilterSyntaxChanged, + this, &WiresharkMainWindow::captureFilterSyntaxChanged); - connect(this, SIGNAL(showExtcapOptions(QString&, bool)), - this, SLOT(showExtcapOptionsDialog(QString&, bool))); - connect(this->welcome_page_, SIGNAL(showExtcapOptions(QString&, bool)), - this, SLOT(showExtcapOptionsDialog(QString&, bool))); + connect(this, &WiresharkMainWindow::showExtcapOptions, this, &WiresharkMainWindow::showExtcapOptionsDialog); + connect(this->welcome_page_, &WelcomePage::showExtcapOptions, this, &WiresharkMainWindow::showExtcapOptionsDialog); #endif // HAVE_LIBPCAP @@ -730,7 +710,7 @@ main_ui_->goToLineEdit->setValidator(goToLineQiv); main_ui_->actionHelpMPText2pcap->setToolTip(gchar_free_to_qstring(topic_action_url(LOCALPAGE_MAN_TEXT2PCAP))); main_ui_->actionHelpMPTShark->setToolTip(gchar_free_to_qstring(topic_action_url(LOCALPAGE_MAN_TSHARK))); - main_ui_->actionHelpContents->setToolTip(gchar_free_to_qstring(topic_action_url(ONLINEPAGE_USERGUIDE))); + main_ui_->actionHelpContents->setToolTip(gchar_free_to_qstring(topic_action_url(HELP_CONTENT))); main_ui_->actionHelpWebsite->setToolTip(gchar_free_to_qstring(topic_action_url(ONLINEPAGE_HOME))); main_ui_->actionHelpFAQ->setToolTip(gchar_free_to_qstring(topic_action_url(ONLINEPAGE_FAQ))); main_ui_->actionHelpAsk->setToolTip(gchar_free_to_qstring(topic_action_url(ONLINEPAGE_ASK))); @@ -744,11 +724,14 @@ main_ui_->goToLineEdit->setValidator(goToLineQiv); WiresharkMainWindow::~WiresharkMainWindow() { disconnect(main_ui_->mainStack, 0, 0, 0); + if (previous_focus_ != nullptr) { + disconnect(previous_focus_, &QWidget::destroyed, this, &WiresharkMainWindow::resetPreviousFocus); + } #ifndef Q_OS_MAC // Below dialogs inherit GeometryStateDialog // For reasons described in geometry_state_dialog.h no parent is set when - // instantiating the dialogs and as a resul objects are not automatically + // instantiating the dialogs and as a result objects are not automatically // freed by its parent. Free then here explicitly to avoid leak and numerous // Valgrind complaints. delete file_set_dialog_; @@ -816,8 +799,8 @@ void WiresharkMainWindow::addInterfaceToolbar(const iface_toolbar *toolbar_entry menu->insertAction(before, action); InterfaceToolbar *interface_toolbar = new InterfaceToolbar(this, toolbar_entry); - connect(mainApp, SIGNAL(appInitialized()), interface_toolbar, SLOT(interfaceListChanged())); - connect(mainApp, SIGNAL(localInterfaceListChanged()), interface_toolbar, SLOT(interfaceListChanged())); + connect(mainApp, &MainApplication::appInitialized, interface_toolbar, &InterfaceToolbar::interfaceListChanged); + connect(mainApp, &MainApplication::localInterfaceListChanged, interface_toolbar, &InterfaceToolbar::interfaceListChanged); QToolBar *toolbar = new QToolBar(this); toolbar->addWidget(interface_toolbar); @@ -836,7 +819,7 @@ void WiresharkMainWindow::addInterfaceToolbar(const iface_toolbar *toolbar_entry menu->menuAction()->setVisible(true); } -void WiresharkMainWindow::removeInterfaceToolbar(const gchar *menu_title) +void WiresharkMainWindow::removeInterfaceToolbar(const char *menu_title) { QMenu *menu = main_ui_->menuInterfaceToolbars; QAction *action = NULL; @@ -945,13 +928,6 @@ void WiresharkMainWindow::keyPressEvent(QKeyEvent *event) { } void WiresharkMainWindow::closeEvent(QCloseEvent *event) { - if (main_ui_->actionCaptureStop->isEnabled()) { - // Capture is running, we should stop it before close and ignore the event - stopCapture(); - event->ignore(); - return; - } - saveWindowGeometry(); /* If we're in the middle of stopping a capture, don't do anything; @@ -1069,10 +1045,10 @@ void WiresharkMainWindow::dropEvent(QDropEvent *event) if (cf_merge_files_to_tempfile(this, global_capture_opts.temp_dir, &tmpname, static_cast(local_files.size()), in_filenames, wtap_pcapng_file_type_subtype(), - FALSE) == CF_OK) { + false) == CF_OK) { /* Merge succeeded; close the currently-open file and try to open the merged capture file. */ - openCaptureFile(tmpname, QString(), WTAP_TYPE_AUTO, TRUE); + openCaptureFile(tmpname, QString(), WTAP_TYPE_AUTO, true); } g_free(tmpname); @@ -1091,7 +1067,23 @@ void WiresharkMainWindow::loadWindowGeometry() #ifndef Q_OS_MAC if (recent.gui_geometry_main_maximized) { - setWindowState(Qt::WindowMaximized); + // [save|restore]Geometry does a better job (on Linux and Windows) + // of restoring to the original monitor because it saves + // QGuiApplication::screens().indexOf(screen()) + // (it also saves Qt::WindowFullScreen, restores the non-maximized + // size even when starting out maximized, etc.) + // Monitors of different DPI might still be tricky: + // https://bugreports.qt.io/browse/QTBUG-70721 + // https://bugreports.qt.io/browse/QTBUG-77385 + // + // We might eventually want to always use restoreGeometry, but + // for now at least use it just for maximized because it's better + // then what we've been doing. + if (recent.gui_geometry_main == nullptr || + !restoreGeometry(QByteArray::fromHex(recent.gui_geometry_main))) { + + setWindowState(Qt::WindowMaximized); + } } else #endif { @@ -1122,6 +1114,13 @@ void WiresharkMainWindow::loadWindowGeometry() void WiresharkMainWindow::saveWindowGeometry() { + if (prefs.gui_geometry_save_position || + prefs.gui_geometry_save_size || + prefs.gui_geometry_save_maximized) { + g_free(recent.gui_geometry_main); + recent.gui_geometry_main = g_strdup(saveGeometry().toHex().constData()); + } + if (prefs.gui_geometry_save_position) { recent.gui_geometry_main_x = pos().x(); recent.gui_geometry_main_y = pos().y(); @@ -1134,6 +1133,9 @@ void WiresharkMainWindow::saveWindowGeometry() if (prefs.gui_geometry_save_maximized) { // On macOS this is false when it shouldn't be + // XXX: Does save/restoreGeometry work any better on macOS + // for maximized windows? Apparently not: + // https://bugreports.qt.io/browse/QTBUG-100272 recent.gui_geometry_main_maximized = isMaximized(); } @@ -1141,6 +1143,14 @@ void WiresharkMainWindow::saveWindowGeometry() recent.gui_geometry_main_upper_pane = master_split_.sizes()[0]; } + g_free(recent.gui_geometry_main_master_split); + g_free(recent.gui_geometry_main_extra_split); + recent.gui_geometry_main_master_split = g_strdup(master_split_.saveState().toHex().constData()); + recent.gui_geometry_main_extra_split = g_strdup(extra_split_.saveState().toHex().constData()); + + // Saving the QSplitter state is more accurate (#19361), but save + // the old GTK-style pane information for backwards compatibility + // for switching back and forth with older versions. if (master_split_.sizes().length() > 2) { recent.gui_geometry_main_lower_pane = master_split_.sizes()[1]; } else if (extra_split_.sizes().length() > 0) { @@ -1151,7 +1161,7 @@ void WiresharkMainWindow::saveWindowGeometry() // Our event loop becomes nested whenever we call update_progress_dlg, which // includes several places in file.c. The GTK+ UI stays out of trouble by // showing a modal progress dialog. We attempt to do the equivalent below by -// disabling parts of the main window. At a minumum the ProgressFrame in the +// disabling parts of the main window. At a minimum the ProgressFrame in the // main status bar must remain accessible. // // We might want to do this any time the main status bar progress frame is @@ -1193,7 +1203,7 @@ void WiresharkMainWindow::mergeCaptureFile() if (prefs.gui_ask_unsaved) { if (cf_has_unsaved_data(capture_file_.capFile())) { QMessageBox msg_dialog; - gchar *display_basename; + char *display_basename; int response; msg_dialog.setIcon(QMessageBox::Question); @@ -1263,17 +1273,17 @@ void WiresharkMainWindow::mergeCaptureFile() /* chronological order */ in_filenames[0] = g_strdup(capture_file_.capFile()->filename); in_filenames[1] = qstring_strdup(file_name); - merge_status = cf_merge_files_to_tempfile(this, global_capture_opts.temp_dir, &tmpname, 2, in_filenames, file_type, FALSE); + merge_status = cf_merge_files_to_tempfile(this, global_capture_opts.temp_dir, &tmpname, 2, in_filenames, file_type, false); } else if (merge_dlg.mergeType() <= 0) { /* prepend file */ in_filenames[0] = qstring_strdup(file_name); in_filenames[1] = g_strdup(capture_file_.capFile()->filename); - merge_status = cf_merge_files_to_tempfile(this, global_capture_opts.temp_dir, &tmpname, 2, in_filenames, file_type, TRUE); + merge_status = cf_merge_files_to_tempfile(this, global_capture_opts.temp_dir, &tmpname, 2, in_filenames, file_type, true); } else { /* append file */ in_filenames[0] = g_strdup(capture_file_.capFile()->filename); in_filenames[1] = qstring_strdup(file_name); - merge_status = cf_merge_files_to_tempfile(this, global_capture_opts.temp_dir, &tmpname, 2, in_filenames, file_type, TRUE); + merge_status = cf_merge_files_to_tempfile(this, global_capture_opts.temp_dir, &tmpname, 2, in_filenames, file_type, true); } g_free(in_filenames[0]); @@ -1288,8 +1298,10 @@ void WiresharkMainWindow::mergeCaptureFile() cf_close(capture_file_.capFile()); /* Try to open the merged capture file. */ + // XXX - Just free rfcode and call + // openCaptureFile(tmpname, read_filter, WTAP_TYPE_AUTO, true); CaptureFile::globalCapFile()->window = this; - if (cf_open(CaptureFile::globalCapFile(), tmpname, WTAP_TYPE_AUTO, TRUE /* temporary file */, &err) != CF_OK) { + if (cf_open(CaptureFile::globalCapFile(), tmpname, WTAP_TYPE_AUTO, true /* temporary file */, &err) != CF_OK) { /* We couldn't open it; fail. */ CaptureFile::globalCapFile()->window = NULL; dfilter_free(rfcode); @@ -1302,7 +1314,7 @@ void WiresharkMainWindow::mergeCaptureFile() previous read filter attached to "cf"). */ cf_set_rfcode(CaptureFile::globalCapFile(), rfcode); - switch (cf_read(CaptureFile::globalCapFile(), /*reloading=*/FALSE)) { + switch (cf_read(CaptureFile::globalCapFile(), /*reloading=*/false)) { case CF_READ_OK: case CF_READ_ERROR: @@ -1320,8 +1332,7 @@ void WiresharkMainWindow::mergeCaptureFile() return; } - /* Save the name of the containing directory specified in the path name. */ - mainApp->setLastOpenDirFromFilename(tmpname); + /* This is a tempfile; don't change the last open directory. */ g_free(tmpname); main_ui_->statusBar->showExpert(); return; @@ -1343,12 +1354,12 @@ void WiresharkMainWindow::importCaptureFile() { return; } - openCaptureFile(import_dlg.capfileName()); + openCaptureFile(import_dlg.capfileName(), QString(), WTAP_TYPE_AUTO, true); } bool WiresharkMainWindow::saveCaptureFile(capture_file *cf, bool dont_reopen) { QString file_name; - gboolean discard_comments; + bool discard_comments; if (cf->is_tempfile) { /* This is a temporary capture file, so saving it means saving @@ -1358,7 +1369,7 @@ bool WiresharkMainWindow::saveCaptureFile(capture_file *cf, bool dont_reopen) { probably pcapng, which supports comments and, if it's not pcapng, let the user decide what they want to do if they've added comments. */ - return saveAsCaptureFile(cf, FALSE, dont_reopen); + return saveAsCaptureFile(cf, false, dont_reopen); } else { if (cf->unsaved_changes) { cf_write_status_t status; @@ -1377,7 +1388,7 @@ bool WiresharkMainWindow::saveCaptureFile(capture_file *cf, bool dont_reopen) { case SAVE: /* The file can be saved in the specified format as is; just drive on and save in the format they selected. */ - discard_comments = FALSE; + discard_comments = false; break; case SAVE_WITHOUT_COMMENTS: @@ -1385,7 +1396,7 @@ bool WiresharkMainWindow::saveCaptureFile(capture_file *cf, bool dont_reopen) { but it can be saved without the comments, and the user said "OK, discard the comments", so save it in the format they specified without the comments. */ - discard_comments = TRUE; + discard_comments = true; break; case SAVE_IN_ANOTHER_FORMAT: @@ -1393,7 +1404,7 @@ bool WiresharkMainWindow::saveCaptureFile(capture_file *cf, bool dont_reopen) { support comments, and the user said not to delete the comments. Do a "Save As" so the user can select one of those formats and choose a file name. */ - return saveAsCaptureFile(cf, TRUE, dont_reopen); + return saveAsCaptureFile(cf, true, dont_reopen); case CANCELLED: /* The user said "forget it". Just return. */ @@ -1461,8 +1472,8 @@ bool WiresharkMainWindow::saveAsCaptureFile(capture_file *cf, bool must_support_ int file_type; wtap_compression_type compression_type; cf_write_status_t status; - gchar *dirname; - gboolean discard_comments = FALSE; + char *dirname; + bool discard_comments = false; if (!cf) { return false; @@ -1479,7 +1490,7 @@ bool WiresharkMainWindow::saveAsCaptureFile(capture_file *cf, bool must_support_ case SAVE: /* The file can be saved in the specified format as is; just drive on and save in the format they selected. */ - discard_comments = FALSE; + discard_comments = false; break; case SAVE_WITHOUT_COMMENTS: @@ -1487,7 +1498,7 @@ bool WiresharkMainWindow::saveAsCaptureFile(capture_file *cf, bool must_support_ but it can be saved without the comments, and the user said "OK, discard the comments", so save it in the format they specified without the comments. */ - discard_comments = TRUE; + discard_comments = true; break; case SAVE_IN_ANOTHER_FORMAT: @@ -1497,7 +1508,7 @@ bool WiresharkMainWindow::saveAsCaptureFile(capture_file *cf, bool must_support_ formats that don't support comments trimmed from it, so run the dialog again, to let the user decide whether to save in one of those formats or give up. */ - must_support_comments = TRUE; + must_support_comments = true; continue; case CANCELLED: @@ -1518,11 +1529,6 @@ bool WiresharkMainWindow::saveAsCaptureFile(capture_file *cf, bool must_support_ } compression_type = save_as_dlg.compressionType(); -#ifdef Q_OS_WIN - // the Windows dialog does not fixup extensions, do it manually here. - fileAddExtension(file_name, file_type, compression_type); -#endif // Q_OS_WIN - //#ifndef _WIN32 // /* If the file exists and it's user-immutable or not writable, // ask the user whether they want to override that. */ @@ -1564,7 +1570,7 @@ bool WiresharkMainWindow::saveAsCaptureFile(capture_file *cf, bool must_support_ cf->unsaved_changes = false; //we just saved so we signal that we have no unsaved changes updateForUnsavedChanges(); // we update the title bar to remove the * /* Add this filename to the list of recent files in the "Recent Files" submenu */ - add_menu_recent_capture_file(qUtf8Printable(file_name)); + add_menu_recent_capture_file(qUtf8Printable(file_name), false); return true; case CF_WRITE_ERROR: @@ -1585,7 +1591,7 @@ void WiresharkMainWindow::exportSelectedPackets() { wtap_compression_type compression_type; packet_range_t range; cf_write_status_t status; - gchar *dirname; + char *dirname; bool discard_comments = false; if (!capture_file_.capFile()) @@ -1593,8 +1599,8 @@ void WiresharkMainWindow::exportSelectedPackets() { /* Init the packet range */ packet_range_init(&range, capture_file_.capFile()); - range.process_filtered = TRUE; - range.include_dependents = TRUE; + range.process_filtered = true; + range.include_dependents = true; QList rows = packet_list_->selectedRows(true); @@ -1614,7 +1620,7 @@ void WiresharkMainWindow::exportSelectedPackets() { case SAVE: /* The file can be saved in the specified format as is; just drive on and save in the format they selected. */ - discard_comments = FALSE; + discard_comments = false; break; case SAVE_WITHOUT_COMMENTS: @@ -1622,7 +1628,7 @@ void WiresharkMainWindow::exportSelectedPackets() { but it can be saved without the comments, and the user said "OK, discard the comments", so save it in the format they specified without the comments. */ - discard_comments = TRUE; + discard_comments = true; break; case SAVE_IN_ANOTHER_FORMAT: @@ -1650,7 +1656,7 @@ void WiresharkMainWindow::exportSelectedPackets() { */ if (files_identical(capture_file_.capFile()->filename, qUtf8Printable(file_name))) { QMessageBox msg_box; - gchar *display_basename = g_filename_display_basename(qUtf8Printable(file_name)); + char *display_basename = g_filename_display_basename(qUtf8Printable(file_name)); msg_box.setIcon(QMessageBox::Critical); msg_box.setText(QString(tr("Unable to export to \"%1\".").arg(display_basename))); @@ -1674,10 +1680,6 @@ void WiresharkMainWindow::exportSelectedPackets() { goto cleanup; } compression_type = esp_dlg.compressionType(); -#ifdef Q_OS_WIN - // the Windows dialog does not fixup extensions, do it manually here. - fileAddExtension(file_name, file_type, compression_type); -#endif // Q_OS_WIN //#ifndef _WIN32 // /* If the file exists and it's user-immutable or not writable, @@ -1706,7 +1708,7 @@ void WiresharkMainWindow::exportSelectedPackets() { if (discard_comments) packet_list_->redrawVisiblePackets(); /* Add this filename to the list of recent files in the "Recent Files" submenu */ - add_menu_recent_capture_file(qUtf8Printable(file_name)); + add_menu_recent_capture_file(qUtf8Printable(file_name), false); goto cleanup; case CF_WRITE_ERROR: @@ -1740,110 +1742,6 @@ void WiresharkMainWindow::exportDissections(export_type_e export_type) { ed_dlg->show(); } -#ifdef Q_OS_WIN -/* - * Ensure that: - * - * If the file is to be compressed: - * - * if there is a set of extensions used by the file type to be used, - * the file name has one of those extensions followed by the extension - * for the compression type to be used; - * - * otherwise, the file name has the extension for the compression type - * to be used; - * - * otherwise: - * - * if there is a set of extensions used by the file type to be used, - * the file name has one of those extensions. - */ -void WiresharkMainWindow::fileAddExtension(QString &file_name, int file_type, wtap_compression_type compression_type) { - QString file_name_lower; - GSList *extensions_list; - const char *compressed_file_extension; - gboolean add_extension_for_file_type; - - /* Lower-case the file name, so the extension matching is case-insensitive. */ - file_name_lower = file_name.toLower(); - - /* Get a list of all extensions used for this file type; don't - include the ones with compression type extensions, as we - only want to check for the extension for the compression - type we'll be using. */ - extensions_list = wtap_get_file_extensions_list(file_type, FALSE); - - /* Get the extension for the compression type we'll be using; - NULL is returned if the type isn't supported or compression - is not being done. */ - compressed_file_extension = wtap_compression_type_extension(compression_type); - - if (extensions_list != NULL) { - GSList *extension; - - /* This file type has one or more extensions. - Start out assuming we need to add the default one. */ - add_extension_for_file_type = TRUE; - - /* OK, see if the file has one of those extensions, followed - by the appropriate compression type extension if it's to be - compressed. */ - for (extension = extensions_list; extension != NULL; - extension = g_slist_next(extension)) { - QString file_suffix = QString(".") + (char *)extension->data; - if (compressed_file_extension != NULL) - file_suffix += QString(".") + compressed_file_extension; - if (file_name_lower.endsWith(file_suffix)) { - /* - * The file name has one of the extensions for this file - * type, followed by a compression type extension if - * appropriate, so we don't need to add an extension for - * the file type or the compression type. - */ - add_extension_for_file_type = FALSE; - break; - } - } - } else { - /* We have no extensions for this file type. Just check - to see if we need to add an extension for the compressed - file type. - - Start out assuming we do. */ - add_extension_for_file_type = TRUE; - if (compressed_file_extension != NULL) { - QString file_suffix = QString(".") + compressed_file_extension; - if (file_name_lower.endsWith(file_suffix)) { - /* - * The file name has the appropriate compressed file extension, - * so we don't need to add an extension for the compression - * type. - */ - add_extension_for_file_type = FALSE; - } - } - } - - /* - * If we need to add an extension for the file type or compressed - * file type, do so. - */ - if (add_extension_for_file_type) { - if (wtap_default_file_extension(file_type) != NULL) { - /* This file type has a default extension; append it. */ - file_name += QString(".") + wtap_default_file_extension(file_type); - } - if (compression_type != WTAP_UNCOMPRESSED) { - /* - * The file is to be compressed, so append the extension for - * its compression type. - */ - file_name += QString(".") + compressed_file_extension; - } - } -} -#endif // Q_OS_WIN - bool WiresharkMainWindow::testCaptureFileClose(QString before_what, FileCloseContext context) { bool capture_in_progress = false; bool do_close_file = false; @@ -1891,7 +1789,7 @@ bool WiresharkMainWindow::testCaptureFileClose(QString before_what, FileCloseCon return false; } - QMessageBox msg_dialog; + QMessageBox msg_dialog(this); QString question; QString infotext; QPushButton *save_button; @@ -1916,7 +1814,7 @@ bool WiresharkMainWindow::testCaptureFileClose(QString before_what, FileCloseCon } } else { // No capture in progress and not a tempfile, so this is not unsaved packets - gchar *display_basename = g_filename_display_basename(capture_file_.capFile()->filename); + char *display_basename = g_filename_display_basename(capture_file_.capFile()->filename); question = tr("Do you want to save the changes you've made to the capture file \"%1\"%2?").arg(display_basename, before_what); infotext = tr("Your changes will be lost if you don't save them."); g_free(display_basename); @@ -1991,7 +1889,7 @@ bool WiresharkMainWindow::testCaptureFileClose(QString before_what, FileCloseCon */ QList buttons = msg_dialog.buttons(); for (int i = 0; i < buttons.size(); ++i) { - QPushButton *button = static_cast(buttons.at(i));; + QPushButton *button = static_cast(buttons.at(i)); button->setAutoDefault(false); } @@ -2001,7 +1899,13 @@ bool WiresharkMainWindow::testCaptureFileClose(QString before_what, FileCloseCon */ discard_button->setFocus(); #endif - + /* + * On Windows, if multiple Wireshark processes are open, another + * application has focus, and "Close all [Wireshark] windows" is + * chosen from the taskbar, we need to activate the window to + * at least flash the taskbar (#16309). + */ + activateWindow(); msg_dialog.exec(); /* According to the Qt doc: * when using QMessageBox with custom buttons, exec() function returns an opaque value. @@ -2119,7 +2023,7 @@ void WiresharkMainWindow::findTextCodecs() { // annoying to properly place IBM00858 and IBM00924 in the middle of // code page numbers not zero padded to 5 digits. // We could manipulate the key further to have more commonly used - // charsets earlier. IANA MIB ordering would be unxpected: + // charsets earlier. IANA MIB ordering would be unexpected: // https://www.iana.org/assignments/character-sets/character-sets.xml // For data about use in HTTP (other protocols can be quite different): // https://w3techs.com/technologies/overview/character_encoding @@ -2152,11 +2056,10 @@ void WiresharkMainWindow::initMainToolbarIcons() main_ui_->actionCaptureRestart->setIcon(StockIcon("x-capture-restart")); main_ui_->actionCaptureOptions->setIcon(StockIcon("x-capture-options")); - // Menu icons are disabled in main_window.ui for these items. + // Menu icons are disabled in wireshark_main_window.ui for these File-> items. main_ui_->actionFileOpen->setIcon(StockIcon("document-open")); main_ui_->actionFileSave->setIcon(StockIcon("x-capture-file-save")); main_ui_->actionFileClose->setIcon(StockIcon("x-capture-file-close")); - main_ui_->actionViewReload->setIcon(StockIcon("x-capture-file-reload")); main_ui_->actionEditFindPacket->setIcon(StockIcon("edit-find")); main_ui_->actionGoPreviousPacket->setIcon(StockIcon("go-previous")); @@ -2183,6 +2086,8 @@ void WiresharkMainWindow::initMainToolbarIcons() main_ui_->actionViewZoomOut->setIcon(StockIcon("zoom-out")); main_ui_->actionViewNormalSize->setIcon(StockIcon("zoom-original")); main_ui_->actionViewResizeColumns->setIcon(StockIcon("x-resize-columns")); + main_ui_->actionViewResetLayout->setIcon(StockIcon("x-reset-layout_2")); + main_ui_->actionViewReload->setIcon(StockIcon("x-capture-file-reload")); main_ui_->actionNewDisplayFilterExpression->setIcon(StockIcon("list-add")); } @@ -2219,7 +2124,7 @@ void WiresharkMainWindow::initShowHideMainWidgets() /* Initially hide the additional toolbars menus */ main_ui_->menuAdditionalToolbars->menuAction()->setVisible(false); - connect(show_hide_actions_, SIGNAL(triggered(QAction*)), this, SLOT(showHideMainWidgets(QAction*))); + connect(show_hide_actions_, &QActionGroup::triggered, this, &WiresharkMainWindow::showHideMainWidgets); } void WiresharkMainWindow::initTimeDisplayFormatMenu() @@ -2246,7 +2151,7 @@ void WiresharkMainWindow::initTimeDisplayFormatMenu() time_display_actions_->addAction(tda); } - connect(time_display_actions_, SIGNAL(triggered(QAction*)), this, SLOT(setTimestampFormat(QAction*))); + connect(time_display_actions_, &QActionGroup::triggered, this, &WiresharkMainWindow::setTimestampFormat); } void WiresharkMainWindow::initTimePrecisionFormatMenu() @@ -2274,7 +2179,7 @@ void WiresharkMainWindow::initTimePrecisionFormatMenu() time_precision_actions_->addAction(tpa); } - connect(time_precision_actions_, SIGNAL(triggered(QAction*)), this, SLOT(setTimestampPrecision(QAction*))); + connect(time_precision_actions_, &QActionGroup::triggered, this, &WiresharkMainWindow::setTimestampPrecision); } // Menu items which will be disabled when we freeze() and whose state will @@ -2284,10 +2189,10 @@ void WiresharkMainWindow::initFreezeActions() QList freeze_actions = QList() << main_ui_->actionFileClose << main_ui_->actionViewReload - << main_ui_->actionEditMarkPacket + << main_ui_->actionEditMarkSelected << main_ui_->actionEditMarkAllDisplayed << main_ui_->actionEditUnmarkAllDisplayed - << main_ui_->actionEditIgnorePacket + << main_ui_->actionEditIgnoreSelected << main_ui_->actionEditIgnoreAllDisplayed << main_ui_->actionEditUnignoreAllDisplayed << main_ui_->actionEditSetTimeReference @@ -2315,8 +2220,8 @@ void WiresharkMainWindow::initConversationMenus() ConversationAction *conv_action = new ConversationAction(main_ui_->menuConversationFilter, conv_filter); main_ui_->menuConversationFilter->addAction(conv_action); - connect(this, SIGNAL(packetInfoChanged(_packet_info*)), conv_action, SLOT(setPacketInfo(_packet_info*))); - connect(conv_action, SIGNAL(triggered()), this, SLOT(applyConversationFilter()), Qt::QueuedConnection); + connect(this, &WiresharkMainWindow::packetInfoChanged, conv_action, &ConversationAction::setPacketInfo); + connect(conv_action, &ConversationAction::triggered, this, &WiresharkMainWindow::applyConversationFilter, Qt::QueuedConnection); // Packet list context menu items packet_list_->conversationMenu()->addAction(conv_action); @@ -2330,15 +2235,15 @@ void WiresharkMainWindow::initConversationMenus() conv_action->setIcon(cc_action->icon()); conv_action->setColorNumber(i++); submenu->addAction(conv_action); - connect(this, SIGNAL(packetInfoChanged(_packet_info*)), conv_action, SLOT(setPacketInfo(_packet_info*))); - connect(conv_action, SIGNAL(triggered()), this, SLOT(colorizeActionTriggered())); + connect(this, &WiresharkMainWindow::packetInfoChanged, conv_action, &ConversationAction::setPacketInfo); + connect(conv_action, &ConversationAction::triggered, this, &WiresharkMainWindow::colorizeActionTriggered); } conv_action = new ConversationAction(submenu, conv_filter); conv_action->setText(main_ui_->actionViewColorizeNewColoringRule->text()); submenu->addAction(conv_action); - connect(this, SIGNAL(packetInfoChanged(_packet_info*)), conv_action, SLOT(setPacketInfo(_packet_info*))); - connect(conv_action, SIGNAL(triggered()), this, SLOT(colorizeActionTriggered())); + connect(this, &WiresharkMainWindow::packetInfoChanged, conv_action, &ConversationAction::setPacketInfo); + connect(conv_action, &ConversationAction::triggered, this, &WiresharkMainWindow::colorizeActionTriggered); // Proto tree conversation menu is filled in in ProtoTree::contextMenuEvent. // We should probably do that here. @@ -2353,15 +2258,15 @@ void WiresharkMainWindow::initConversationMenus() colorize_action->setIcon(cc_action->icon()); colorize_action->setColorNumber(i++); proto_tree_->colorizeMenu()->addAction(colorize_action); - connect(this, SIGNAL(fieldFilterChanged(QByteArray)), colorize_action, SLOT(setFieldFilter(QByteArray))); - connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeActionTriggered())); + connect(this, &WiresharkMainWindow::fieldFilterChanged, colorize_action, &ColorizeAction::setFieldFilter); + connect(colorize_action, &ColorizeAction::triggered, this, &WiresharkMainWindow::colorizeActionTriggered); } colorize_action = new ColorizeAction(proto_tree_->colorizeMenu()); colorize_action->setText(main_ui_->actionViewColorizeNewColoringRule->text()); proto_tree_->colorizeMenu()->addAction(colorize_action); - connect(this, SIGNAL(fieldFilterChanged(QByteArray)), colorize_action, SLOT(setFieldFilter(QByteArray))); - connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeActionTriggered())); + connect(this, &WiresharkMainWindow::fieldFilterChanged, colorize_action, &ColorizeAction::setFieldFilter); + connect(colorize_action, &ColorizeAction::triggered, this, &WiresharkMainWindow::colorizeActionTriggered); } bool WiresharkMainWindow::addExportObjectsMenuItem(const void *, void *value, void *userdata) @@ -2375,9 +2280,9 @@ bool WiresharkMainWindow::addExportObjectsMenuItem(const void *, void *value, vo //initially disable until a file is loaded (then file signals will take over) export_action->setEnabled(false); - connect(&window->capture_file_, SIGNAL(captureEvent(CaptureEvent)), export_action, SLOT(captureFileEvent(CaptureEvent))); - connect(export_action, SIGNAL(triggered()), window, SLOT(applyExportObject())); - return FALSE; + connect(&window->capture_file_, &CaptureFile::captureEvent, export_action, &ExportObjectAction::captureFileEvent); + connect(export_action, &ExportObjectAction::triggered, window, &WiresharkMainWindow::applyExportObject); + return false; } void WiresharkMainWindow::initExportObjectsMenus() @@ -2417,12 +2322,14 @@ bool WiresharkMainWindow::addFollowStreamMenuItem(const void *key, void *value, follow_action->setText(tr("HTTP/2 Stream")); } else if (g_strcmp0(short_name, "SIP") == 0) { follow_action->setText(tr("SIP Call")); + } else if (g_strcmp0(short_name, "USBCOM") == 0) { + follow_action->setText(tr("USB CDC Data")); } connect(follow_action, &QAction::triggered, window, [window, follow]() { window->openFollowStreamDialog(get_follow_proto_id(follow)); }, Qt::QueuedConnection); - return FALSE; + return false; } void WiresharkMainWindow::initFollowStreamMenus() @@ -2434,24 +2341,8 @@ void WiresharkMainWindow::initFollowStreamMenus() // Titlebar void WiresharkMainWindow::setTitlebarForCaptureFile() { - if (capture_file_.capFile() && capture_file_.capFile()->filename) { - setWSWindowTitle(QString("[*]%1").arg(capture_file_.fileDisplayName())); - // - // XXX - on non-Mac platforms, put in the application - // name? Or do so only for temporary files? - // - if (!capture_file_.capFile()->is_tempfile) { - // - // Set the file path; that way, for macOS, it'll set the - // "proxy icon". - // - setWindowFilePath(capture_file_.filePath()); - } - setWindowModified(cf_has_unsaved_data(capture_file_.capFile())); - } else { - /* We have no capture file. */ - setWSWindowTitle(); - } + use_capturing_title_ = false; + updateTitlebar(); } QString WiresharkMainWindow::replaceWindowTitleVariables(QString title) @@ -2459,6 +2350,18 @@ QString WiresharkMainWindow::replaceWindowTitleVariables(QString title) title.replace("%P", get_profile_name()); title.replace("%V", get_ws_vcs_version_info()); +#ifdef HAVE_LIBPCAP + if (global_commandline_info.capture_comments) { + // Use the first capture comment from command line. + title.replace("%C", (char *)g_ptr_array_index(global_commandline_info.capture_comments, 0)); + } else { + // No capture comment. + title.remove("%C"); + } +#else + title.remove("%C"); +#endif + if (title.contains("%F")) { // %F is file path of the capture file. if (capture_file_.capFile()) { @@ -2528,10 +2431,30 @@ void WiresharkMainWindow::setWSWindowTitle(QString title) void WiresharkMainWindow::setTitlebarForCaptureInProgress() { - if (capture_file_.capFile()) { + use_capturing_title_ = true; + updateTitlebar(); +} + +void WiresharkMainWindow::updateTitlebar() +{ + if (use_capturing_title_ && capture_file_.capFile()) { setWSWindowTitle(tr("Capturing from %1").arg(cf_get_tempfile_source(capture_file_.capFile()))); + } else if (capture_file_.capFile() && capture_file_.capFile()->filename) { + setWSWindowTitle(QString("[*]%1").arg(capture_file_.fileDisplayName())); + // + // XXX - on non-Mac platforms, put in the application + // name? Or do so only for temporary files? + // + if (!capture_file_.capFile()->is_tempfile) { + // + // Set the file path; that way, for macOS, it'll set the + // "proxy icon". + // + setWindowFilePath(capture_file_.filePath()); + } + setWindowModified(cf_has_unsaved_data(capture_file_.capFile())); } else { - /* We have no capture in progress. */ + /* We have no capture file. */ setWSWindowTitle(); } } @@ -2708,7 +2631,7 @@ void WiresharkMainWindow::setWindowIcon(const QIcon &icon) { } void WiresharkMainWindow::updateForUnsavedChanges() { - setTitlebarForCaptureFile(); + updateTitlebar(); setMenusForCaptureFile(); } @@ -2722,7 +2645,7 @@ void WiresharkMainWindow::changeEvent(QEvent* event) main_ui_->retranslateUi(this); // make sure that the "Clear Menu" item is retranslated mainApp->emitAppSignal(WiresharkApplication::RecentCapturesChanged); - setTitlebarForCaptureFile(); + updateTitlebar(); break; case QEvent::LocaleChange: { QString locale = QLocale::system().name(); @@ -2773,6 +2696,13 @@ void WiresharkMainWindow::addMenuActions(QList &actions, int menu_gro switch (menu_group) { case REGISTER_PACKET_ANALYZE_GROUP_UNSORTED: case REGISTER_PACKET_STAT_GROUP_UNSORTED: + case REGISTER_STAT_GROUP_GENERIC: + // XXX - The Lua documentation claims that ANALYZE_GROUP_UNSORTED + // is under the Analyze menu, and STAT_GROUP_GENERIC and + // PACKET_STAT_GROUP_UNSORTED are distinguished by whether they + // go before the separator in the group of non protocol-specific + // actions or after the separator with the protocol-specific + // actions. We currently put them all in the same place. main_ui_->menuStatistics->insertAction( main_ui_->actionStatistics_REGISTER_STAT_GROUP_UNSORTED, action); @@ -2783,24 +2713,30 @@ void WiresharkMainWindow::addMenuActions(QList &actions, int menu_gro case REGISTER_STAT_GROUP_RSERPOOL: main_ui_->menuRSerPool->addAction(action); break; - case REGISTER_STAT_GROUP_TELEPHONY: + case REGISTER_TELEPHONY_GROUP_UNSORTED: main_ui_->menuTelephony->addAction(action); break; - case REGISTER_STAT_GROUP_TELEPHONY_ANSI: + case REGISTER_TELEPHONY_GROUP_ANSI: main_ui_->menuANSI->addAction(action); break; - case REGISTER_STAT_GROUP_TELEPHONY_GSM: + case REGISTER_TELEPHONY_GROUP_GSM: main_ui_->menuGSM->addAction(action); break; - case REGISTER_STAT_GROUP_TELEPHONY_LTE: + case REGISTER_TELEPHONY_GROUP_3GPP_UU: main_ui_->menuLTE->addAction(action); break; - case REGISTER_STAT_GROUP_TELEPHONY_MTP3: + case REGISTER_TELEPHONY_GROUP_MTP3: main_ui_->menuMTP3->addAction(action); break; + case REGISTER_TELEPHONY_GROUP_SCTP: + // XXX - There are two SCTP menus, under Analyze and Telephony, + // that have the same default actions. The default actions from + // Analyze are copied to the PacketList context menu. + main_ui_->menuTelephonySCTP->addAction(action); + break; case REGISTER_TOOLS_GROUP_UNSORTED: { - // Allow the creation of submenus. Mimics the behavor of + // Allow the creation of submenus. Mimics the behavior of // ui/gtk/main_menubar.c:add_menu_item_to_main_menubar // and GtkUIManager. // @@ -2829,9 +2765,9 @@ void WiresharkMainWindow::addMenuActions(QList &actions, int menu_gro // distinguish various types of actions. Setting their objectName // seems to work OK. if (action->objectName() == TapParameterDialog::actionName()) { - connect(action, SIGNAL(triggered(bool)), this, SLOT(openTapParameterDialog())); + connect(action, &QAction::triggered, this, [=]() { openTapParameterDialog(); }); } else if (action->objectName() == FunnelStatistics::actionName()) { - connect(action, SIGNAL(triggered(bool)), funnel_statistics_, SLOT(funnelActionTriggered())); + connect(action, &QAction::triggered, funnel_statistics_, &FunnelStatistics::funnelActionTriggered); } } } @@ -2841,6 +2777,7 @@ void WiresharkMainWindow::removeMenuActions(QList &actions, int menu_ switch (menu_group) { case REGISTER_PACKET_ANALYZE_GROUP_UNSORTED: case REGISTER_PACKET_STAT_GROUP_UNSORTED: + case REGISTER_STAT_GROUP_GENERIC: main_ui_->menuStatistics->removeAction(action); break; case REGISTER_STAT_GROUP_RESPONSE_TIME: @@ -2849,21 +2786,24 @@ void WiresharkMainWindow::removeMenuActions(QList &actions, int menu_ case REGISTER_STAT_GROUP_RSERPOOL: main_ui_->menuRSerPool->removeAction(action); break; - case REGISTER_STAT_GROUP_TELEPHONY: + case REGISTER_TELEPHONY_GROUP_UNSORTED: main_ui_->menuTelephony->removeAction(action); break; - case REGISTER_STAT_GROUP_TELEPHONY_ANSI: + case REGISTER_TELEPHONY_GROUP_ANSI: main_ui_->menuANSI->removeAction(action); break; - case REGISTER_STAT_GROUP_TELEPHONY_GSM: + case REGISTER_TELEPHONY_GROUP_GSM: main_ui_->menuGSM->removeAction(action); break; - case REGISTER_STAT_GROUP_TELEPHONY_LTE: + case REGISTER_TELEPHONY_GROUP_3GPP_UU: main_ui_->menuLTE->removeAction(action); break; - case REGISTER_STAT_GROUP_TELEPHONY_MTP3: + case REGISTER_TELEPHONY_GROUP_MTP3: main_ui_->menuMTP3->removeAction(action); break; + case REGISTER_TELEPHONY_GROUP_SCTP: + main_ui_->menuTelephonySCTP->removeAction(action); + break; case REGISTER_TOOLS_GROUP_UNSORTED: { // Allow removal of submenus. @@ -2894,12 +2834,12 @@ void WiresharkMainWindow::removeMenuActions(QList &actions, int menu_ void WiresharkMainWindow::addDynamicMenus() { // Manual additions - mainApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_GSM, main_ui_->actionTelephonyGsmMapSummary); - mainApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_LTE, main_ui_->actionTelephonyLteMacStatistics); - mainApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_LTE, main_ui_->actionTelephonyLteRlcStatistics); - mainApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_LTE, main_ui_->actionTelephonyLteRlcGraph); - mainApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_MTP3, main_ui_->actionTelephonyMtp3Summary); - mainApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY, main_ui_->actionTelephonySipFlows); + mainApp->addDynamicMenuGroupItem(REGISTER_TELEPHONY_GROUP_GSM, main_ui_->actionTelephonyGsmMapSummary); + mainApp->addDynamicMenuGroupItem(REGISTER_TELEPHONY_GROUP_3GPP_UU, main_ui_->actionTelephonyLteMacStatistics); + mainApp->addDynamicMenuGroupItem(REGISTER_TELEPHONY_GROUP_3GPP_UU, main_ui_->actionTelephonyLteRlcStatistics); + mainApp->addDynamicMenuGroupItem(REGISTER_TELEPHONY_GROUP_3GPP_UU, main_ui_->actionTelephonyLteRlcGraph); + mainApp->addDynamicMenuGroupItem(REGISTER_TELEPHONY_GROUP_MTP3, main_ui_->actionTelephonyMtp3Summary); + mainApp->addDynamicMenuGroupItem(REGISTER_TELEPHONY_GROUP_UNSORTED, main_ui_->actionTelephonySipFlows); // Fill in each menu foreach(register_stat_group_t menu_group, menu_groups_) { @@ -2910,16 +2850,16 @@ void WiresharkMainWindow::addDynamicMenus() // Empty menus don't show up: https://bugreports.qt.io/browse/QTBUG-33728 // We've added a placeholder in order to make sure some menus are visible. // Hide them as needed. - if (mainApp->dynamicMenuGroupItems(REGISTER_STAT_GROUP_TELEPHONY_ANSI).length() > 0) { + if (mainApp->dynamicMenuGroupItems(REGISTER_TELEPHONY_GROUP_ANSI).length() > 0) { main_ui_->actionTelephonyANSIPlaceholder->setVisible(false); } - if (mainApp->dynamicMenuGroupItems(REGISTER_STAT_GROUP_TELEPHONY_GSM).length() > 0) { + if (mainApp->dynamicMenuGroupItems(REGISTER_TELEPHONY_GROUP_GSM).length() > 0) { main_ui_->actionTelephonyGSMPlaceholder->setVisible(false); } - if (mainApp->dynamicMenuGroupItems(REGISTER_STAT_GROUP_TELEPHONY_LTE).length() > 0) { + if (mainApp->dynamicMenuGroupItems(REGISTER_TELEPHONY_GROUP_3GPP_UU).length() > 0) { main_ui_->actionTelephonyLTEPlaceholder->setVisible(false); } - if (mainApp->dynamicMenuGroupItems(REGISTER_STAT_GROUP_TELEPHONY_MTP3).length() > 0) { + if (mainApp->dynamicMenuGroupItems(REGISTER_TELEPHONY_GROUP_MTP3).length() > 0) { main_ui_->actionTelephonyMTP3Placeholder->setVisible(false); } } @@ -2938,7 +2878,7 @@ void WiresharkMainWindow::reloadDynamicMenus() mainApp->clearRemovedMenuGroupItems(); } -void WiresharkMainWindow::externalMenuHelper(ext_menu_t * menu, QMenu * subMenu, gint depth) +void WiresharkMainWindow::externalMenuHelper(ext_menu_t * menu, QMenu * subMenu, int depth) { QAction * itemAction = Q_NULLPTR; ext_menubar_t * item = Q_NULLPTR; @@ -3127,7 +3067,7 @@ QString WiresharkMainWindow::findRtpStreams(QVector *stream_id { rtpstream_tapinfo_t tapinfo; rtpstream_id_t *new_id; - const gchar filter_text[] = "rtp && rtp.version == 2 && rtp.ssrc && (ip || ipv6)"; + const char filter_text[] = "rtp && rtp.version == 2 && rtp.ssrc && (ip || ipv6)"; dfilter_t *sfcode; df_error_t *df_err = NULL; diff --git a/ui/qt/wireshark_main_window.h b/ui/qt/wireshark_main_window.h index 781a1b28..a1cc8b17 100644 --- a/ui/qt/wireshark_main_window.h +++ b/ui/qt/wireshark_main_window.h @@ -40,8 +40,6 @@ #include -#include - #include "file.h" #include "ui/ws_ui_util.h" @@ -123,7 +121,7 @@ public: void removeAdditionalToolbar(QString toolbarName); void addInterfaceToolbar(const iface_toolbar *toolbar_entry); - void removeInterfaceToolbar(const gchar *menu_title); + void removeInterfaceToolbar(const char *menu_title); QString getMwFileName(); void setMwFileName(QString fileName); @@ -181,6 +179,7 @@ private: bool capture_stopping_; bool capture_filter_valid_; + bool use_capturing_title_; #ifdef HAVE_LIBPCAP capture_session cap_session_; CaptureOptionsDialog *capture_options_dialog_; @@ -233,10 +232,10 @@ private: QString replaceWindowTitleVariables(QString title); void updateStyleSheet(); - void externalMenuHelper(ext_menu_t * menu, QMenu * subMenu, gint depth); + void externalMenuHelper(ext_menu_t * menu, QMenu * subMenu, int depth); void setForCaptureInProgress(bool capture_in_progress = false, bool handle_toolbars = false, GArray *ifaces = NULL); - QMenu* findOrAddMenu(QMenu *parent_menu, QString& menu_text); + QMenu* findOrAddMenu(QMenu *parent_menu, const QStringList& menu_parts); void captureFileReadStarted(const QString &action); @@ -269,11 +268,11 @@ public slots: * @param cf_path Path to the file. * @param display_filter Display filter to apply. May be empty. * @param type File type. - * @param is_tempfile TRUE/FALSE. + * @param is_tempfile true/false. * @return True on success, false on failure. */ // XXX We might want to return a cf_read_status_t or a CaptureFile. - bool openCaptureFile(QString cf_path, QString display_filter, unsigned int type, gboolean is_tempfile = FALSE); + bool openCaptureFile(QString cf_path, QString display_filter, unsigned int type, bool is_tempfile = false); bool openCaptureFile(QString cf_path = QString(), QString display_filter = QString()) { return openCaptureFile(cf_path, display_filter, WTAP_TYPE_AUTO); } void filterPackets(QString new_filter = QString(), bool force = false); void updateForUnsavedChanges(); @@ -299,8 +298,8 @@ public slots: void captureFileClosing(); void captureFileClosed(); - void launchRLCGraph(bool channelKnown, guint16 ueid, guint8 rlcMode, - guint16 channelType, guint16 channelId, guint8 direction); + void launchRLCGraph(bool channelKnown, uint8_t RAT, uint16_t ueid, uint8_t rlcMode, + uint16_t channelType, uint16_t channelId, uint8_t direction); void rtpPlayerDialogReplaceRtpStreams(QVector stream_ids); void rtpPlayerDialogAddRtpStreams(QVector stream_ids); @@ -332,6 +331,7 @@ private slots: */ void startCapture(QStringList); void startCapture(); + void pushLiveCaptureInProgress(); void popLiveCaptureInProgress(); void stopCapture(); @@ -363,6 +363,7 @@ private slots: void addPluginIFStructures(); QMenu * searchSubMenu(QString objectName); void activatePluginIFToolbar(bool); + void updateTitlebar(); void startInterfaceCapture(bool valid, const QString capture_filter); @@ -398,7 +399,7 @@ private slots: // Automatically connected slots ("on__"). // - // The slots below follow the naming conventaion described in + // The slots below follow the naming convention described in // https://doc.qt.io/archives/qt-4.8/qmetaobject.html#connectSlotsByName // and are automatically connected at initialization time via // main_ui_->setupUi, which in turn calls connectSlotsByName. @@ -423,7 +424,7 @@ private slots: void editConfigurationProfiles(); void editTimeShiftFinished(int); void addPacketCommentFinished(PacketCommentDialog* pc_dialog, int result); - void editPacketCommentFinished(PacketCommentDialog* pc_dialog, int result, guint nComment); + void editPacketCommentFinished(PacketCommentDialog* pc_dialog, int result, unsigned nComment); void deleteAllPacketComments(); void deleteAllPacketCommentsFinished(int result); void injectSecrets(); @@ -464,7 +465,7 @@ private slots: void applyConversationFilter(); void applyExportObject(); - void openFollowStreamDialog(int proto_id, guint stream_num, guint sub_stream_num, bool use_stream_index = true); + void openFollowStreamDialog(int proto_id, unsigned stream_num, unsigned sub_stream_num, bool use_stream_index = true); void openFollowStreamDialog(int proto_id); void statCommandExpertInfo(const char *, void *); @@ -494,8 +495,9 @@ private slots: void statCommandWlanStatistics(const char *arg, void *); - void openStatisticsTreeDialog(const gchar *abbr); + void openStatisticsTreeDialog(const char *abbr); void statCommandIOGraph(const char *, void *); + void showIOGraphDialog(io_graph_item_unit_t value_units, QString); void connectTelephonyMenuActions(); diff --git a/ui/qt/wireshark_main_window.ui b/ui/qt/wireshark_main_window.ui index cb01e642..5ff9f8e5 100644 --- a/ui/qt/wireshark_main_window.ui +++ b/ui/qt/wireshark_main_window.ui @@ -471,6 +471,13 @@ + + + DNS + + + + HTTP @@ -554,7 +561,7 @@ - + @@ -608,7 +615,7 @@ - &LTE + &3GPP Uu @@ -639,6 +646,7 @@ + @@ -670,13 +678,13 @@ - + - + @@ -779,6 +787,7 @@ + @@ -893,17 +902,15 @@ - &Contents + &User's Guide + - Help contents + Wireshark User's Guide F1 - - true - @@ -912,7 +919,7 @@ - Wireshark Filter + Display Filters @@ -1463,9 +1470,9 @@ Ctrl+B - + - &Mark/Unmark Packet(s) + &Mark/Unmark Selected Mark or unmark each selected packet @@ -1518,9 +1525,9 @@ Ctrl+Shift+B - + - &Ignore/Unignore Packet(s) + &Ignore/Unignore Selected Ignore or unignore each selected packet @@ -1812,12 +1819,20 @@ - DNS + General DNS statistics + + + Query-Response + + + DNS Query-Response Statistics + + HART-IP @@ -1970,6 +1985,14 @@ NGAP Messages + + + E2AP + + + E2AP Messages + + Decode &As… @@ -2181,7 +2204,7 @@ Reset Layout - Reset appearance layout to default size + Reset layout to default size Ctrl+Shift+W diff --git a/ui/qt/wireshark_main_window_slots.cpp b/ui/qt/wireshark_main_window_slots.cpp index a348bd47..db1e15f7 100644 --- a/ui/qt/wireshark_main_window_slots.cpp +++ b/ui/qt/wireshark_main_window_slots.cpp @@ -19,7 +19,7 @@ /* * The generated Ui_WiresharkMainWindow::setupUi() can grow larger than our configured limit, - * so turn off -Wframe-larger-than= for ui_main_window.h. + * so turn off -Wframe-larger-than= for ui_wireshark_main_window.h. */ DIAG_OFF(frame-larger-than=) #include @@ -188,14 +188,14 @@ DIAG_ON(frame-larger-than=) // Public slots // -bool WiresharkMainWindow::openCaptureFile(QString cf_path, QString read_filter, unsigned int type, gboolean is_tempfile) +bool WiresharkMainWindow::openCaptureFile(QString cf_path, QString read_filter, unsigned int type, bool is_tempfile) { QString file_name = ""; dfilter_t *rfcode = NULL; df_error_t *df_err = NULL; int err; - gboolean name_param; - gboolean ret = true; + bool name_param; + bool ret = true; // was a file name given as function parameter? name_param = !cf_path.isEmpty(); @@ -262,7 +262,7 @@ bool WiresharkMainWindow::openCaptureFile(QString cf_path, QString read_filter, continue; } - switch (cf_read(CaptureFile::globalCapFile(), /*reloading=*/FALSE)) { + switch (cf_read(CaptureFile::globalCapFile(), /*reloading=*/false)) { case CF_READ_OK: case CF_READ_ERROR: /* Just because we got an error, that doesn't mean we were unable @@ -282,7 +282,9 @@ bool WiresharkMainWindow::openCaptureFile(QString cf_path, QString read_filter, break; } - mainApp->setLastOpenDirFromFilename(cf_path); + if (!is_tempfile) { + mainApp->setLastOpenDirFromFilename(cf_path); + } main_ui_->statusBar->showExpert(); @@ -364,6 +366,16 @@ void WiresharkMainWindow::layoutToolbars() } } +static const char* layout_icons[] = { + NULL, + "x-reset-layout_5", + "x-reset-layout_2", + "x-reset-layout_1", + "x-reset-layout_4", + "x-reset-layout_3", + "x-reset-layout_6" +}; + void WiresharkMainWindow::updatePreferenceActions() { main_ui_->actionViewPacketList->setEnabled(prefs_has_layout_pane_content(layout_pane_content_plist)); @@ -374,6 +386,9 @@ void WiresharkMainWindow::updatePreferenceActions() main_ui_->actionViewNameResolutionPhysical->setChecked(gbl_resolv_flags.mac_name); main_ui_->actionViewNameResolutionNetwork->setChecked(gbl_resolv_flags.network_name); main_ui_->actionViewNameResolutionTransport->setChecked(gbl_resolv_flags.transport_name); + + if (prefs.gui_layout_type > 0) + main_ui_->actionViewResetLayout->setIcon(StockIcon(layout_icons[prefs.gui_layout_type])); } void WiresharkMainWindow::updateRecentActions() @@ -422,7 +437,7 @@ void WiresharkMainWindow::updateRecentActions() main_ui_->actionGoAutoScroll->setChecked(recent.capture_auto_scroll); } -// Don't connect to this directly. Connect to or emit fiterAction(...) instead. +// Don't connect to this directly. Connect to or emit filterAction(...) instead. void WiresharkMainWindow::queuedFilterAction(QString action_filter, FilterAction::Action action, FilterAction::ActionType type) { QString cur_filter, new_filter; @@ -506,17 +521,17 @@ void WiresharkMainWindow::queuedFilterAction(QString action_filter, FilterAction #ifdef HAVE_LIBPCAP void WiresharkMainWindow::captureCapturePrepared(capture_session *session) { setTitlebarForCaptureInProgress(); - setWindowIcon(mainApp->captureIcon()); + pushLiveCaptureInProgress(); /* Disable menu items that make no sense if you're currently running a capture. */ bool handle_toolbars = (session->session_will_restart ? false : true); setForCaptureInProgress(true, handle_toolbars, session->capture_opts->ifaces); -// set_capture_if_dialog_for_capture_in_progress(TRUE); +// set_capture_if_dialog_for_capture_in_progress(true); // /* Don't set up main window for a capture file. */ -// main_set_for_capture_file(FALSE); +// main_set_for_capture_file(false); showCapture(); } @@ -526,6 +541,7 @@ void WiresharkMainWindow::captureCaptureUpdateStarted(capture_session *session) switching to the next multiple file. */ setTitlebarForCaptureInProgress(); setWindowIcon(mainApp->captureIcon()); + pushLiveCaptureInProgress(); bool handle_toolbars = (session->session_will_restart ? false : true); setForCaptureInProgress(true, handle_toolbars, session->capture_opts->ifaces); @@ -540,6 +556,7 @@ void WiresharkMainWindow::captureCaptureUpdateFinished(capture_session *session) /* Update the main window as appropriate */ updateForUnsavedChanges(); + setTitlebarForCaptureFile(); /* Enable menu items that make sense if you're not currently running a capture. */ @@ -561,6 +578,7 @@ void WiresharkMainWindow::captureCaptureFixedFinished(capture_session *) { /* The capture isn't stopping any more - it's stopped. */ capture_stopping_ = false; + setTitlebarForCaptureFile(); /* Enable menu items that make sense if you're not currently running a capture. */ @@ -583,7 +601,7 @@ void WiresharkMainWindow::captureCaptureFixedFinished(capture_session *) { void WiresharkMainWindow::captureCaptureFailed(capture_session *) { /* Capture isn't stopping any more. */ capture_stopping_ = false; - + setTitlebarForCaptureFile(); setForCaptureInProgress(false); showWelcome(); @@ -666,7 +684,7 @@ void WiresharkMainWindow::captureEventHandler(CaptureEvent ev) thaw(); break; case CaptureEvent::Flushed: - draw_tap_listeners(FALSE); + draw_tap_listeners(false); break; default: break; @@ -756,7 +774,7 @@ void WiresharkMainWindow::captureFileReadStarted(const QString &action) { // tap_param_dlg_update(); /* Set up main window for a capture file. */ -// main_set_for_capture_file(TRUE); +// main_set_for_capture_file(true); mainApp->popStatus(WiresharkApplication::FileStatus); QString msg = QString(tr("%1: %2")).arg(action).arg(capture_file_.fileName()); @@ -770,7 +788,7 @@ void WiresharkMainWindow::captureFileReadStarted(const QString &action) { void WiresharkMainWindow::captureFileReadFinished() { if (!capture_file_.capFile()->is_tempfile && capture_file_.capFile()->filename) { /* Add this filename to the list of recent files in the "Recent Files" submenu */ - add_menu_recent_capture_file(capture_file_.capFile()->filename); + add_menu_recent_capture_file(capture_file_.capFile()->filename, false); /* Remember folder for next Open dialog and save it in recent */ mainApp->setLastOpenDirFromFilename(capture_file_.capFile()->filename); @@ -795,6 +813,7 @@ void WiresharkMainWindow::captureFileReadFinished() { void WiresharkMainWindow::captureFileClosing() { setMenusForCaptureFile(true); + setTitlebarForCaptureFile(); setForCapturedPackets(false); setForCaptureInProgress(false); @@ -839,12 +858,12 @@ void WiresharkMainWindow::startCapture() { startCapture(QStringList()); } -void WiresharkMainWindow::startCapture(QStringList interfaces _U_) { +void WiresharkMainWindow::startCapture(QStringList interfaces) { #ifdef HAVE_LIBPCAP interface_options *interface_opts; - guint i; + unsigned i; interface_t *device; - gboolean can_start_capture = TRUE; + bool can_start_capture = true; if (interfaces.count() > 0) { global_capture_opts.num_selected = 0; @@ -852,11 +871,11 @@ void WiresharkMainWindow::startCapture(QStringList interfaces _U_) { device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i); if (interfaces.contains(device->name)) { - device->selected = TRUE; + device->selected = true; global_capture_opts.num_selected++; } else { - device->selected = FALSE; + device->selected = false; } } } @@ -877,11 +896,11 @@ void WiresharkMainWindow::startCapture(QStringList interfaces _U_) { */ if (extcap_requires_configuration(device->name)) { - /* Request openning of extcap options dialog */ + /* Request opening of extcap options dialog */ QString device_name(device->name); emit showExtcapOptions(device_name, false); /* Cancel start of capture */ - can_start_capture = FALSE; + can_start_capture = false; } } } @@ -924,24 +943,6 @@ void WiresharkMainWindow::startCapture(QStringList interfaces _U_) { info_data_.ui.ui = this; if (capture_start(&global_capture_opts, NULL, &cap_session_, &info_data_, main_window_update)) { - capture_options *capture_opts = cap_session_.capture_opts; - GString *interface_names; - - /* Add "interface name" on main status bar */ - interface_names = get_iface_list_string(capture_opts, 0); - if (strlen(interface_names->str) > 0) { - g_string_append(interface_names, ":"); - } - g_string_append(interface_names, " "); - - mainApp->popStatus(WiresharkApplication::FileStatus); - QString msg = QString("%1").arg(interface_names->str); - QString msgtip = QString("to file: "); - if (capture_opts->save_file) - msgtip += capture_opts->save_file; - mainApp->pushStatus(WiresharkApplication::FileStatus, msg, msgtip); - g_string_free(interface_names, TRUE); - /* The capture succeeded, which means the capture filter syntax is valid; add this capture filter to the recent capture filter list. */ QByteArray filter_ba; @@ -979,6 +980,30 @@ DIAG_ON(stringop-overread) } else { CaptureFile::globalCapFile()->window = NULL; } +#else // HAVE_LIBPCAP + Q_UNUSED(interfaces) +#endif // HAVE_LIBPCAP +} + +void WiresharkMainWindow::pushLiveCaptureInProgress() { +#ifdef HAVE_LIBPCAP + capture_options *capture_opts = cap_session_.capture_opts; + GString *interface_names; + + /* Add "interface name" on main status bar */ + interface_names = get_iface_list_string(capture_opts, 0); + if (strlen(interface_names->str) > 0) { + g_string_append(interface_names, ":"); + } + g_string_append(interface_names, " "); + + mainApp->popStatus(WiresharkApplication::FileStatus); + QString msg = QString("%1").arg(interface_names->str); + QString msgtip = QString("to file: "); + if (capture_opts->save_file) + msgtip += capture_opts->save_file; + mainApp->pushStatus(WiresharkApplication::FileStatus, msg, msgtip); + g_string_free(interface_names, TRUE); #endif // HAVE_LIBPCAP } @@ -1044,7 +1069,9 @@ void WiresharkMainWindow::updateRecentCaptures() { /* Iterate through the actions in menuOpenRecentCaptureFile, * removing special items, a maybe duplicate entry and every item above count_max */ +#if defined(Q_OS_MAC) int shortcut = Qt::Key_0; +#endif foreach(recent_item_status *ri, mainApp->recentItems()) { // Add the new item ra = new QAction(recentMenu); @@ -1053,12 +1080,14 @@ void WiresharkMainWindow::updateRecentCaptures() { ra->setEnabled(ri->accessible); recentMenu->insertAction(NULL, ra); action_cf_name = ra->data().toString(); +#if defined(Q_OS_MAC) if (shortcut <= Qt::Key_9) { ra->setShortcut(Qt::META | (Qt::Key)shortcut); shortcut++; } +#endif ra->setText(action_cf_name); - connect(ra, SIGNAL(triggered()), this, SLOT(recentActionTriggered())); + connect(ra, &QAction::triggered, this, &WiresharkMainWindow::recentActionTriggered); /* This is slow, at least on my VM here. The added links also open Wireshark * in a new window. It might make more sense to add a recent item when we @@ -1082,8 +1111,15 @@ void WiresharkMainWindow::updateRecentCaptures() { QFileInfo fi(ri->filename); rda->setText(fi.fileName()); dock_menu_->insertAction(NULL, rda); - connect(rda, SIGNAL(triggered()), ra, SLOT(trigger())); + connect(rda, &QAction::triggered, ra, &QAction::trigger); +#endif +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + if (recentMenu->actions().count() == static_cast(prefs.gui_recent_files_count_max)) { +#else + if (recentMenu->actions().count() == static_cast(prefs.gui_recent_files_count_max)) { #endif + break; + } } if (recentMenu->actions().count() > 0) { @@ -1096,7 +1132,7 @@ void WiresharkMainWindow::updateRecentCaptures() { ra = new QAction(recentMenu); ra->setText(tr("Clear Menu")); recentMenu->insertAction(NULL, ra); - connect(ra, SIGNAL(triggered()), mainApp, SLOT(clearRecentCaptures())); + connect(ra, &QAction::triggered, mainApp, &MainApplication::clearRecentCaptures); } else { if (main_ui_->actionDummyNoFilesFound) { recentMenu->addAction(main_ui_->actionDummyNoFilesFound); @@ -1138,10 +1174,10 @@ void WiresharkMainWindow::setEditCommentsMenu() const int thisRow = selectedRows().first(); frame_data * current_frame = frameDataForRow(thisRow); wtap_block_t pkt_block = cf_get_packet_block(capture_file_.capFile(), current_frame); - guint nComments = wtap_block_count_option(pkt_block, OPT_COMMENT); + unsigned nComments = wtap_block_count_option(pkt_block, OPT_COMMENT); if (nComments > 0) { main_ui_->menuPacketComment->addSeparator(); - for (guint i = 0; i < nComments; i++) { + for (unsigned i = 0; i < nComments; i++) { QString comment = packet_list_->getPacketComment(i); comment = this->commentToMenuText(comment); action = main_ui_->menuPacketComment->addAction(tr("Edit \"%1\"", "edit packet comment").arg(comment)); @@ -1150,7 +1186,7 @@ void WiresharkMainWindow::setEditCommentsMenu() } main_ui_->menuPacketComment->addSeparator(); - for (guint i = 0; i < nComments; i++) { + for (unsigned i = 0; i < nComments; i++) { QString comment = packet_list_->getPacketComment(i); comment = this->commentToMenuText(comment); action = main_ui_->menuPacketComment->addAction(tr("Delete \"%1\"", "delete packet comment").arg(comment)); @@ -1172,8 +1208,8 @@ void WiresharkMainWindow::setEditCommentsMenu() void WiresharkMainWindow::setMenusForSelectedPacket() { - gboolean is_ip = FALSE, is_tcp = FALSE, is_udp = FALSE, is_sctp = FALSE, is_tls = FALSE, is_rtp = FALSE, is_lte_rlc = FALSE, - is_quic = FALSE, is_exported_pdu = FALSE; + bool is_ip = false, is_tcp = false, is_udp = false, is_sctp = false, is_tls = false, is_rtp = false, is_lte_rlc = false, + is_quic = false, is_exported_pdu = false; /* Making the menu context-sensitive allows for easier selection of the desired item and has the added benefit, with large captures, of @@ -1237,7 +1273,7 @@ void WiresharkMainWindow::setMenusForSelectedPacket() another_is_time_ref = have_time_ref && rows.count() <= 1 && !(capture_file_.capFile()->ref_time_count == 1 && frame_selected && current_frame->ref_time); - if (capture_file_.capFile()->edt && ! multi_selection) + if (capture_file_.capFile()->edt && ! multi_selection && frame_selected) { proto_get_frame_protocols(capture_file_.capFile()->edt->pi.layers, &is_ip, &is_tcp, &is_udp, &is_sctp, @@ -1249,30 +1285,31 @@ void WiresharkMainWindow::setMenusForSelectedPacket() if (is_exported_pdu && (capture_file_.capFile()->edt->pi.net_src.type == AT_IPv4 || capture_file_.capFile()->edt->pi.net_src.type == AT_IPv6) && (capture_file_.capFile()->edt->pi.net_dst.type == AT_IPv4 || capture_file_.capFile()->edt->pi.net_dst.type == AT_IPv6)) { - is_ip = TRUE; + is_ip = true; } foreach (FollowStreamAction *follow_action, main_ui_->menuFollow->findChildren()) { /* QUIC has TLS handshakes; don't enabled Follow TLS Stream if * there's QUIC. */ - gboolean is_frame = proto_is_frame_protocol(capture_file_.capFile()->edt->pi.layers, follow_action->filterName()); + bool is_frame = proto_is_frame_protocol(capture_file_.capFile()->edt->pi.layers, follow_action->filterName()); if (g_strcmp0(follow_action->filterName(), "tls") == 0) { follow_action->setEnabled(is_frame && !is_quic); } else { follow_action->setEnabled(is_frame); } } + } else { + foreach (FollowStreamAction *follow_action, main_ui_->menuFollow->findChildren()) { + follow_action->setEnabled(false); + } } } - main_ui_->actionEditMarkPacket->setText(tr("&Mark/Unmark Packet(s)", "", static_cast(selectedRows().count()))); - main_ui_->actionEditIgnorePacket->setText(tr("&Ignore/Unignore Packet(s)", "", static_cast(selectedRows().count()))); - main_ui_->actionCopyListAsText->setEnabled(selectedRows().count() > 0); main_ui_->actionCopyListAsCSV->setEnabled(selectedRows().count() > 0); main_ui_->actionCopyListAsYAML->setEnabled(selectedRows().count() > 0); - main_ui_->actionEditMarkPacket->setEnabled(frame_selected || multi_selection); + main_ui_->actionEditMarkSelected->setEnabled(frame_selected || multi_selection); main_ui_->actionEditMarkAllDisplayed->setEnabled(have_frames); /* Unlike un-ignore, do not allow unmark of all frames when no frames are displayed */ main_ui_->actionEditUnmarkAllDisplayed->setEnabled(have_marked); @@ -1287,7 +1324,7 @@ void WiresharkMainWindow::setMenusForSelectedPacket() main_ui_->menuPacketComment->setEnabled(enableEditComments && selectedRows().count() > 0); main_ui_->actionDeleteAllPacketComments->setEnabled(enableEditComments); - main_ui_->actionEditIgnorePacket->setEnabled(frame_selected || multi_selection); + main_ui_->actionEditIgnoreSelected->setEnabled(frame_selected || multi_selection); main_ui_->actionEditIgnoreAllDisplayed->setEnabled(have_filtered); /* Allow un-ignore of all frames even with no frames currently displayed */ main_ui_->actionEditUnignoreAllDisplayed->setEnabled(have_ignored); @@ -1361,10 +1398,26 @@ void WiresharkMainWindow::setMenusForSelectedTreeRow(FieldInformation *finfo) { if (fi && fi->ds_tvb && (fi->length > 0)) { have_packet_bytes = true; } + + if (!(capture_file_.capFile()->search_in_progress && (capture_file_.capFile()->hex || (capture_file_.capFile()->string && capture_file_.capFile()->packet_data)))) { + // If we're not in the middle of a packet bytes search, then set + // search_pos and search_len so that we can start a new search + // from this point. (If we are, then we already set it.) + if (fi && capture_file_.capFile()->edt && (fi->ds_tvb == capture_file_.capFile()->edt->tvb)) { + // We can only do a Packet Bytes search in the main bytes from + // the frame, not from any secondary data sources. (XXX: This + // might be surprising to users, though.) + capture_file_.capFile()->search_pos = (uint32_t)(finfo->position().start + finfo->position().length - 1); + capture_file_.capFile()->search_len = (uint32_t)finfo->position().length; + } else { + capture_file_.capFile()->search_pos = 0; + capture_file_.capFile()->search_len = 0; + } + } } if (capture_file_.capFile() != NULL && fi != NULL) { - header_field_info *hfinfo = fi->hfinfo; + const header_field_info *hfinfo = fi->hfinfo; int linked_frame = -1; can_match_selected = proto_can_match_selected(capture_file_.capFile()->finfo_selected, capture_file_.capFile()->edt); @@ -1522,7 +1575,7 @@ void WiresharkMainWindow::checkDisplayFilter() void WiresharkMainWindow::fieldsChanged() { - gchar *err_msg = NULL; + char *err_msg = NULL; if (!color_filters_reload(&err_msg, color_filter_add_cb)) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); g_free(err_msg); @@ -1545,7 +1598,7 @@ void WiresharkMainWindow::reloadLuaPlugins() if (mainApp->isReloadingLua()) return; - gboolean uses_lua_filehandler = FALSE; + bool uses_lua_filehandler = false; if (capture_file_.capFile()) { // Check if the current capture file is opened with a Lua FileHandler @@ -1633,11 +1686,11 @@ void WiresharkMainWindow::initViewColorizeMenu() << main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8 << main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10; - guint8 color_num = 1; + uint8_t color_num = 1; foreach(QAction *cc_action, cc_actions) { cc_action->setData(color_num); - connect(cc_action, SIGNAL(triggered()), this, SLOT(colorizeConversation())); + connect(cc_action, &QAction::triggered, this, &WiresharkMainWindow::colorizeConversation); const color_filter_t *colorf = color_filters_tmp_color(color_num); if (colorf) { @@ -1674,16 +1727,15 @@ void WiresharkMainWindow::addStatsPluginsToMenu() { parent_menu = main_ui_->menuStatistics; // gtk/main_menubar.c compresses double slashes, hence SkipEmptyParts #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - QStringList cfg_name_parts = QString(cfg->name).split("/", Qt::SkipEmptyParts); + QStringList cfg_name_parts = QString(cfg->path).split(STATS_TREE_MENU_SEPARATOR, Qt::SkipEmptyParts); #else - QStringList cfg_name_parts = QString(cfg->name).split("/", QString::SkipEmptyParts); + QStringList cfg_name_parts = QString(cfg->path).split(STATS_TREE_MENU_SEPARATOR, QString::SkipEmptyParts); #endif if (cfg_name_parts.isEmpty()) continue; - QString stat_name = cfg_name_parts.takeLast(); + QString stat_name = cfg_name_parts.takeLast().trimmed(); if (!cfg_name_parts.isEmpty()) { - QString menu_name = cfg_name_parts.join("/"); - parent_menu = findOrAddMenu(parent_menu, menu_name); + parent_menu = findOrAddMenu(parent_menu, cfg_name_parts); } stats_tree_action = new QAction(stat_name, this); @@ -1757,10 +1809,8 @@ void WiresharkMainWindow::openTapParameterDialog(const QString cfg_str, const QS TapParameterDialog *tp_dialog = TapParameterDialog::showTapParameterStatistics(*this, capture_file_, cfg_str, arg, userdata); if (!tp_dialog) return; - connect(tp_dialog, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType)), - this, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType))); - connect(tp_dialog, SIGNAL(updateFilter(QString)), - df_combo_box_->lineEdit(), SLOT(setText(QString))); + connect(tp_dialog, &TapParameterDialog::filterAction, this, &WiresharkMainWindow::filterAction); + connect(tp_dialog, &TapParameterDialog::updateFilter, df_combo_box_->lineEdit(), &QLineEdit::setText); tp_dialog->show(); } @@ -1881,7 +1931,7 @@ void WiresharkMainWindow::exportPacketBytes() ); if (file_name.length() > 0) { - const guint8 *data_p; + const uint8_t *data_p; data_p = tvb_get_ptr(capture_file_.capFile()->finfo_selected->ds_tvb, 0, -1) + capture_file_.capFile()->finfo_selected->start; @@ -1953,8 +2003,8 @@ void WiresharkMainWindow::exportTLSSessionKeys() tr("TLS Session Keys (*.keys *.txt);;All Files (" ALL_FILES_WILDCARD ")") ); if (file_name.length() > 0) { - gsize keylist_length; - gchar *keylist = ssl_export_sessions(&keylist_length); + size_t keylist_length; + char *keylist = ssl_export_sessions(&keylist_length); write_file_binary_mode(qUtf8Printable(file_name), keylist, keylist_length); /* Save the directory name for future file dialogs. */ @@ -2023,7 +2073,7 @@ void WiresharkMainWindow::connectEditMenuActions() // The items below are used in the packet list and detail context menus. // Use QueuedConnections so that the context menus aren't destroyed // prematurely. - connect(main_ui_->actionEditMarkPacket, &QAction::triggered, this, [this]() { + connect(main_ui_->actionEditMarkSelected, &QAction::triggered, this, [this]() { freeze(); packet_list_->markFrame(); thaw(); @@ -2056,7 +2106,7 @@ void WiresharkMainWindow::connectEditMenuActions() } }, Qt::QueuedConnection); - connect(main_ui_->actionEditIgnorePacket, &QAction::triggered, this, [this]() { + connect(main_ui_->actionEditIgnoreSelected, &QAction::triggered, this, [this]() { freeze(); packet_list_->ignoreFrame(); thaw(); @@ -2140,7 +2190,7 @@ void WiresharkMainWindow::copySelectedItems(WiresharkMainWindow::CopySelected se break; case CopySelectedValue: if (finfo_selected && capture_file_.capFile()->edt != 0) { - gchar* field_str = get_node_field_value(finfo_selected, capture_file_.capFile()->edt); + char* field_str = get_node_field_value(finfo_selected, capture_file_.capFile()->edt); clip.append(field_str); g_free(field_str); } @@ -2231,10 +2281,9 @@ void WiresharkMainWindow::findPacket() void WiresharkMainWindow::editTimeShift() { TimeShiftDialog *ts_dialog = new TimeShiftDialog(this, capture_file_.capFile()); - connect(ts_dialog, SIGNAL(finished(int)), this, SLOT(editTimeShiftFinished(int))); + connect(ts_dialog, &TimeShiftDialog::finished, this, &WiresharkMainWindow::editTimeShiftFinished); - connect(this, SIGNAL(setCaptureFile(capture_file*)), - ts_dialog, SLOT(setCaptureFile(capture_file*))); + connect(this, &WiresharkMainWindow::setCaptureFile, ts_dialog, &TimeShiftDialog::setCaptureFile); connect(ts_dialog, &TimeShiftDialog::timeShifted, packet_list_, &PacketList::applyTimeShift, Qt::QueuedConnection); ts_dialog->setWindowModality(Qt::ApplicationModal); @@ -2282,7 +2331,7 @@ void WiresharkMainWindow::editPacketComment() return; QAction *ra = qobject_cast(sender()); - guint nComment = ra->data().toUInt(); + unsigned nComment = ra->data().toUInt(); PacketCommentDialog* pc_dialog; pc_dialog = new PacketCommentDialog(true, this, packet_list_->getPacketComment(nComment)); connect(pc_dialog, &QDialog::finished, std::bind(&WiresharkMainWindow::editPacketCommentFinished, this, pc_dialog, std::placeholders::_1, nComment)); @@ -2291,7 +2340,7 @@ void WiresharkMainWindow::editPacketComment() pc_dialog->show(); } -void WiresharkMainWindow::editPacketCommentFinished(PacketCommentDialog* pc_dialog _U_, int result _U_, guint nComment) +void WiresharkMainWindow::editPacketCommentFinished(PacketCommentDialog* pc_dialog _U_, int result _U_, unsigned nComment) { if (result == QDialog::Accepted) { packet_list_->setPacketComment(nComment, pc_dialog->text()); @@ -2302,7 +2351,7 @@ void WiresharkMainWindow::editPacketCommentFinished(PacketCommentDialog* pc_dial void WiresharkMainWindow::deletePacketComment() { QAction *ra = qobject_cast(sender()); - guint nComment = ra->data().toUInt(); + unsigned nComment = ra->data().toUInt(); packet_list_->setPacketComment(nComment, QString("")); updateForUnsavedChanges(); } @@ -2316,7 +2365,7 @@ void WiresharkMainWindow::deleteCommentsFromPackets() void WiresharkMainWindow::deleteAllPacketComments() { QMessageBox *msg_dialog = new QMessageBox(); - connect(msg_dialog, SIGNAL(finished(int)), this, SLOT(deleteAllPacketCommentsFinished(int))); + connect(msg_dialog, &QMessageBox::finished, this, &WiresharkMainWindow::deleteAllPacketCommentsFinished); msg_dialog->setIcon(QMessageBox::Question); msg_dialog->setText(tr("Are you sure you want to remove all packet comments?")); @@ -2355,7 +2404,7 @@ void WiresharkMainWindow::injectSecrets() if (ret != QMessageBox::Yes) return; - QUrl wiki_url = QString(WS_WIKI_URL("TLS/#tls-decryption")); + QUrl wiki_url = QString(WS_WIKI_URL("TLS#tls-decryption")); QDesktopServices::openUrl(wiki_url); return; } @@ -2377,7 +2426,7 @@ void WiresharkMainWindow::discardAllSecrets() return; QMessageBox* msg_dialog = new QMessageBox(); - connect(msg_dialog, SIGNAL(finished(int)), this, SLOT(discardAllSecretsFinished(int))); + connect(msg_dialog, &QMessageBox::finished, this, &WiresharkMainWindow::discardAllSecretsFinished); msg_dialog->setIcon(QMessageBox::Question); msg_dialog->setText(tr("Are you sure you want to discard all decryption secrets?")); @@ -2398,7 +2447,7 @@ void WiresharkMainWindow::discardAllSecretsFinished(int result) */ capture_file* cf = capture_file_.capFile(); if (wtap_file_discard_decryption_secrets(cf->provider.wth)) { - cf->unsaved_changes = TRUE; + cf->unsaved_changes = true; updateForUnsavedChanges(); } } @@ -2415,7 +2464,7 @@ void WiresharkMainWindow::editConfigurationProfiles() void WiresharkMainWindow::showPreferencesDialog(QString module_name) { PreferencesDialog *pref_dialog = new PreferencesDialog(this); - connect(pref_dialog, SIGNAL(destroyed(QObject*)), mainApp, SLOT(flushAppSignals())); + connect(pref_dialog, &PreferencesDialog::destroyed, mainApp, &MainApplication::flushAppSignals); saveWindowGeometry(); // Save in case the layout panes are rearranged pref_dialog->setPane(module_name); @@ -2494,7 +2543,7 @@ void WiresharkMainWindow::connectViewMenuActions() [this]() { showColoringRulesDialog(); }); connect(main_ui_->actionViewColorizeResetColorization, &QAction::triggered, this, [this]() { - gchar *err_msg = NULL; + char *err_msg = NULL; if (!color_filters_reset_tmp(&err_msg)) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); g_free(err_msg); @@ -2509,6 +2558,10 @@ void WiresharkMainWindow::connectViewMenuActions() connect(main_ui_->actionViewResetLayout, &QAction::triggered, this, [this]() { recent.gui_geometry_main_upper_pane = 0; recent.gui_geometry_main_lower_pane = 0; + g_free(recent.gui_geometry_main_master_split); + g_free(recent.gui_geometry_main_extra_split); + recent.gui_geometry_main_master_split = NULL; + recent.gui_geometry_main_extra_split = NULL; applyRecentPaneGeometry(); }); @@ -2592,7 +2645,7 @@ void WiresharkMainWindow::showHideMainWidgets(QAction *action) if (widget == toolbar) { GList *entry = g_list_find_custom(recent.interface_toolbars, action->text().toUtf8(), (GCompareFunc)strcmp); if (show && !entry) { - recent.interface_toolbars = g_list_append(recent.interface_toolbars, g_strdup(action->text().toUtf8().constData())); + recent.interface_toolbars = g_list_append(recent.interface_toolbars, qstring_strdup(action->text())); } else if (!show && entry) { recent.interface_toolbars = g_list_remove(recent.interface_toolbars, entry->data); } @@ -2691,9 +2744,9 @@ void WiresharkMainWindow::editResolvedName() void WiresharkMainWindow::setNameResolution() { - gbl_resolv_flags.mac_name = main_ui_->actionViewNameResolutionPhysical->isChecked() ? TRUE : FALSE; - gbl_resolv_flags.network_name = main_ui_->actionViewNameResolutionNetwork->isChecked() ? TRUE : FALSE; - gbl_resolv_flags.transport_name = main_ui_->actionViewNameResolutionTransport->isChecked() ? TRUE : FALSE; + gbl_resolv_flags.mac_name = main_ui_->actionViewNameResolutionPhysical->isChecked() ? true : false; + gbl_resolv_flags.network_name = main_ui_->actionViewNameResolutionNetwork->isChecked() ? true : false; + gbl_resolv_flags.transport_name = main_ui_->actionViewNameResolutionTransport->isChecked() ? true : false; if (packet_list_) { packet_list_->resetColumns(); @@ -2727,8 +2780,8 @@ void WiresharkMainWindow::colorizeConversation(bool create_rule) if (capture_file_.capFile() && selectedRows().count() > 0) { packet_info *pi = capture_file_.packetInfo(); - guint8 cc_num = colorize_action->data().toUInt(); - gchar *filter = conversation_filter_from_packet(pi); + uint8_t cc_num = colorize_action->data().toUInt(); + char *filter = conversation_filter_from_packet(pi); if (filter == NULL) { mainApp->pushStatus(WiresharkApplication::TemporaryStatus, tr("Unable to build conversation filter.")); return; @@ -2742,8 +2795,8 @@ void WiresharkMainWindow::colorizeConversation(bool create_rule) this, &WiresharkMainWindow::filterAction); coloring_rules_dialog.exec(); } else { - gchar *err_msg = NULL; - if (!color_filters_set_tmp(cc_num, filter, FALSE, &err_msg)) { + char *err_msg = NULL; + if (!color_filters_set_tmp(cc_num, filter, false, &err_msg)) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); g_free(err_msg); } @@ -2779,8 +2832,8 @@ void WiresharkMainWindow::colorizeWithFilter(QByteArray filter, int color_number if (color_number > 0) { // Assume "Color X" - gchar *err_msg = NULL; - if (!color_filters_set_tmp(color_number, filter.constData(), FALSE, &err_msg)) { + char *err_msg = NULL; + if (!color_filters_set_tmp(color_number, filter.constData(), false, &err_msg)) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); g_free(err_msg); } @@ -2803,7 +2856,7 @@ void WiresharkMainWindow::openPacketDialog(bool from_reference) /* Find the frame for which we're popping up a dialog */ if (from_reference) { - guint32 framenum = fvalue_get_uinteger(capture_file_.capFile()->finfo_selected->value); + uint32_t framenum = fvalue_get_uinteger(capture_file_.capFile()->finfo_selected->value); if (framenum == 0) return; @@ -2929,9 +2982,9 @@ void WiresharkMainWindow::connectGoMenuActions() } void WiresharkMainWindow::goToConversationFrame(bool go_next) { - gchar *filter = NULL; + char *filter = NULL; dfilter_t *dfcode = NULL; - gboolean found_packet = FALSE; + bool found_packet = false; packet_info *pi = capture_file_.packetInfo(); if (!pi) { @@ -2985,7 +3038,7 @@ void WiresharkMainWindow::connectCaptureMenuActions() #ifdef HAVE_LIBPCAP connect(main_ui_->actionCaptureRestart, &QAction::triggered, this, [this]() { QString before_what(tr(" before restarting the capture")); - cap_session_.capture_opts->restart = TRUE; + cap_session_.capture_opts->restart = true; if (!testCaptureFileClose(before_what, Restart)) { return; } @@ -3061,13 +3114,13 @@ void WiresharkMainWindow::startCaptureTriggered() // /* // * There's an options dialog; get the values from it and close it. // */ -// gboolean success; +// bool success; // /* Determine if "capture start" while building of the "capture options" window */ // /* is in progress. If so, ignore the "capture start. */ // /* XXX: Would it be better/cleaner for the "capture options" window code to */ // /* disable the capture start button temporarily ? */ -// if (cap_open_complete == FALSE) { +// if (cap_open_complete == false) { // return; /* Building options window: ignore "capture start" */ // } // success = capture_dlg_prep(cap_open_w); @@ -3110,14 +3163,10 @@ void WiresharkMainWindow::connectAnalyzeMenuActions() }); connect(main_ui_->actionAnalyzeDisplayFilterMacros, &QAction::triggered, this, [=]() { - struct epan_uat* dfm_uat; - dfilter_macro_get_uat(&dfm_uat); - UatDialog *uat_dlg = new UatDialog(parentWidget(), dfm_uat); - connect(uat_dlg, SIGNAL(destroyed(QObject*)), mainApp, SLOT(flushAppSignals())); - - uat_dlg->setWindowModality(Qt::ApplicationModal); - uat_dlg->setAttribute(Qt::WA_DeleteOnClose); - uat_dlg->show(); + FilterDialog *display_filter_dlg = new FilterDialog(window(), FilterDialog::DisplayMacro); + display_filter_dlg->setWindowModality(Qt::ApplicationModal); + display_filter_dlg->setAttribute(Qt::WA_DeleteOnClose); + display_filter_dlg->show(); }); connect(main_ui_->actionDisplayFilterExpression, &QAction::triggered, this, [=]() { @@ -3133,7 +3182,7 @@ void WiresharkMainWindow::connectAnalyzeMenuActions() connect(main_ui_->actionAnalyzeEnabledProtocols, &QAction::triggered, this, [=]() { EnabledProtocolsDialog *enable_proto_dialog = new EnabledProtocolsDialog(this); - connect(enable_proto_dialog, SIGNAL(destroyed(QObject*)), mainApp, SLOT(flushAppSignals())); + connect(enable_proto_dialog, &EnabledProtocolsDialog::destroyed, mainApp, &MainApplication::flushAppSignals); enable_proto_dialog->setWindowModality(Qt::ApplicationModal); enable_proto_dialog->setAttribute(Qt::WA_DeleteOnClose); @@ -3145,7 +3194,7 @@ void WiresharkMainWindow::connectAnalyzeMenuActions() bool create_new = da_action && da_action->property("create_new").toBool(); DecodeAsDialog *da_dialog = new DecodeAsDialog(this, capture_file_.capFile(), create_new); - connect(da_dialog, SIGNAL(destroyed(QObject*)), mainApp, SLOT(flushAppSignals())); + connect(da_dialog, &DecodeAsDialog::destroyed, mainApp, &MainApplication::flushAppSignals); da_dialog->setWindowModality(Qt::ApplicationModal); da_dialog->setAttribute(Qt::WA_DeleteOnClose); @@ -3209,7 +3258,7 @@ void WiresharkMainWindow::matchFieldFilter(FilterAction::Action action, FilterAc void WiresharkMainWindow::applyFieldAsColumn() { if (capture_file_.capFile() != 0 && capture_file_.capFile()->finfo_selected != 0) { - header_field_info *hfinfo = capture_file_.capFile()->finfo_selected->hfinfo; + const header_field_info *hfinfo = capture_file_.capFile()->finfo_selected->hfinfo; int col = column_prefs_has_custom(hfinfo->abbrev); if (col == -1) { insertColumn(hfinfo->name, hfinfo->abbrev); @@ -3224,7 +3273,7 @@ void WiresharkMainWindow::applyFieldAsColumn() if (!get_column_visible(col)) { packet_list_->setColumnHidden(col, false); - set_column_visible(col, TRUE); + set_column_visible(col, true); prefs_main_write(); } } @@ -3261,10 +3310,10 @@ void WiresharkMainWindow::applyExportObject() export_dialog->show(); } -void WiresharkMainWindow::openFollowStreamDialog(int proto_id, guint stream_num, guint sub_stream_num, bool use_stream_index) { +void WiresharkMainWindow::openFollowStreamDialog(int proto_id, unsigned stream_num, unsigned sub_stream_num, bool use_stream_index) { FollowStreamDialog *fsd = new FollowStreamDialog(*this, capture_file_, proto_id); - connect(fsd, SIGNAL(updateFilter(QString, bool)), this, SLOT(filterPackets(QString, bool))); - connect(fsd, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int))); + connect(fsd, &FollowStreamDialog::updateFilter, this, &WiresharkMainWindow::filterPackets); + connect(fsd, &FollowStreamDialog::goToPacket, this, [=](int packet_num) {packet_list_->goToPacket(packet_num);}); fsd->addCodecs(text_codec_map_); fsd->show(); if (use_stream_index) { @@ -3283,10 +3332,8 @@ void WiresharkMainWindow::openFollowStreamDialog(int proto_id) { void WiresharkMainWindow::openSCTPAllAssocsDialog() { SCTPAllAssocsDialog *sctp_dialog = new SCTPAllAssocsDialog(this, capture_file_.capFile()); - connect(sctp_dialog, SIGNAL(filterPackets(QString, bool)), - this, SLOT(filterPackets(QString, bool))); - connect(this, SIGNAL(setCaptureFile(capture_file*)), - sctp_dialog, SLOT(setCaptureFile(capture_file*))); + connect(sctp_dialog, &SCTPAllAssocsDialog::filterPackets, this, &WiresharkMainWindow::filterPackets); + connect(this, &WiresharkMainWindow::setCaptureFile, sctp_dialog, &SCTPAllAssocsDialog::setCaptureFile); sctp_dialog->fillTable(); if (sctp_dialog->isMinimized() == true) @@ -3314,8 +3361,7 @@ void WiresharkMainWindow::on_actionSCTPAnalyseThisAssociation_triggered() return; } SCTPAssocAnalyseDialog *sctp_analyse = new SCTPAssocAnalyseDialog(this, assoc, capture_file_.capFile()); - connect(sctp_analyse, SIGNAL(filterPackets(QString, bool)), - this, SLOT(filterPackets(QString, bool))); + connect(sctp_analyse, &SCTPAssocAnalyseDialog::filterPackets, this, &WiresharkMainWindow::filterPackets); if (sctp_analyse->isMinimized() == true) { @@ -3344,9 +3390,8 @@ void WiresharkMainWindow::on_actionSCTPFilterThisAssociation_triggered() void WiresharkMainWindow::statCommandWlanStatistics(const char *arg, void *) { WlanStatisticsDialog *wlan_stats_dlg = new WlanStatisticsDialog(*this, capture_file_, arg); - connect(wlan_stats_dlg, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType)), - this, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType))); wlan_stats_dlg->show(); + connect(wlan_stats_dlg, &WlanStatisticsDialog::filterAction, this, &WiresharkMainWindow::filterAction); } // -z expert @@ -3355,10 +3400,9 @@ void WiresharkMainWindow::statCommandExpertInfo(const char *, void *) const DisplayFilterEdit *df_edit = dynamic_cast(df_combo_box_->lineEdit()); ExpertInfoDialog *expert_dialog = new ExpertInfoDialog(*this, capture_file_, df_edit->text()); - connect(expert_dialog->getExpertInfoView(), SIGNAL(goToPacket(int, int)), - packet_list_, SLOT(goToPacket(int, int))); - connect(expert_dialog, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType)), - this, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType))); + connect(expert_dialog->getExpertInfoView(), &ExpertInfoTreeView::goToPacket, + this, [=](int packet_num) {packet_list_->goToPacket(packet_num);}); + connect(expert_dialog, &ExpertInfoDialog::filterAction, this, &WiresharkMainWindow::filterAction); expert_dialog->show(); } @@ -3372,8 +3416,8 @@ void WiresharkMainWindow::connectStatisticsMenuActions() { connect(main_ui_->actionStatisticsCaptureFileProperties, &QAction::triggered, this, [=]() { CaptureFilePropertiesDialog *capture_file_properties_dialog = new CaptureFilePropertiesDialog(*this, capture_file_); - connect(capture_file_properties_dialog, SIGNAL(captureCommentChanged()), - this, SLOT(updateForUnsavedChanges())); + connect(capture_file_properties_dialog, &CaptureFilePropertiesDialog::captureCommentChanged, + this, &WiresharkMainWindow::updateForUnsavedChanges); capture_file_properties_dialog->show(); }); @@ -3381,8 +3425,7 @@ void WiresharkMainWindow::connectStatisticsMenuActions() connect(main_ui_->actionStatisticsProtocolHierarchy, &QAction::triggered, this, [=]() { ProtocolHierarchyDialog *phd = new ProtocolHierarchyDialog(*this, capture_file_); - connect(phd, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType)), - this, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType))); + connect(phd, &ProtocolHierarchyDialog::filterAction, this, &WiresharkMainWindow::filterAction); phd->show(); }); @@ -3400,6 +3443,7 @@ void WiresharkMainWindow::connectStatisticsMenuActions() connect(main_ui_->actionStatisticsCollectd, &QAction::triggered, this, [=]() { openStatisticsTreeDialog("collectd"); }); connect(main_ui_->actionStatisticsDNS, &QAction::triggered, this, [=]() { openStatisticsTreeDialog("dns"); }); + connect(main_ui_->actionStatisticsDNS_QR, &QAction::triggered, this, [=]() { openStatisticsTreeDialog("dns_qr"); }); connect(main_ui_->actionStatisticsHART_IP, &QAction::triggered, this, [=]() { openStatisticsTreeDialog("hart_ip"); }); connect(main_ui_->actionStatisticsHpfeeds, &QAction::triggered, this, [=]() { openStatisticsTreeDialog("hpfeeds"); }); connect(main_ui_->actionStatisticsHTTP2, &QAction::triggered, this, [=]() { openStatisticsTreeDialog("http2"); }); @@ -3451,28 +3495,22 @@ void WiresharkMainWindow::connectStatisticsMenuActions() connect(main_ui_->actionStatistics29WestUIM_Streams, &QAction::triggered, this, [=]() { LBMStreamDialog *stream_dialog = new LBMStreamDialog(this, capture_file_.capFile()); - // connect(stream_dialog, SIGNAL(goToPacket(int)), - // packet_list_, SLOT(goToPacket(int))); - connect(this, SIGNAL(setCaptureFile(capture_file*)), - stream_dialog, SLOT(setCaptureFile(capture_file*))); + // connect(stream_dialog, &LBMStreamDialog::goToPacket, packet_list_, &PacketList::goToPacket); + connect(this, &WiresharkMainWindow::setCaptureFile, stream_dialog, &LBMStreamDialog::setCaptureFile); stream_dialog->show(); }); connect(main_ui_->actionStatistics29WestLBTRM, &QAction::triggered, this, [=]() { LBMLBTRMTransportDialog * lbtrm_dialog = new LBMLBTRMTransportDialog(this, capture_file_.capFile()); - connect(lbtrm_dialog, SIGNAL(goToPacket(int)), - packet_list_, SLOT(goToPacket(int))); - connect(this, SIGNAL(setCaptureFile(capture_file*)), - lbtrm_dialog, SLOT(setCaptureFile(capture_file*))); + connect(lbtrm_dialog, &LBMLBTRMTransportDialog::goToPacket, this, [=](int packet_num) {packet_list_->goToPacket(packet_num);}); + connect(this, &WiresharkMainWindow::setCaptureFile, lbtrm_dialog, &LBMLBTRMTransportDialog::setCaptureFile); lbtrm_dialog->show(); }); connect(main_ui_->actionStatistics29WestLBTRU, &QAction::triggered, this, [=]() { LBMLBTRUTransportDialog * lbtru_dialog = new LBMLBTRUTransportDialog(this, capture_file_.capFile()); - connect(lbtru_dialog, SIGNAL(goToPacket(int)), - packet_list_, SLOT(goToPacket(int))); - connect(this, SIGNAL(setCaptureFile(capture_file*)), - lbtru_dialog, SLOT(setCaptureFile(capture_file*))); + connect(lbtru_dialog, &LBMLBTRUTransportDialog::goToPacket, this, [=](int packet_num) {packet_list_->goToPacket(packet_num);}); + connect(this, &WiresharkMainWindow::setCaptureFile, lbtru_dialog, &LBMLBTRUTransportDialog::setCaptureFile); lbtru_dialog->show(); }); @@ -3505,10 +3543,8 @@ void WiresharkMainWindow::connectStatisticsMenuActions() void WiresharkMainWindow::openTcpStreamDialog(int graph_type) { TCPStreamDialog *stream_dialog = new TCPStreamDialog(this, capture_file_.capFile(), (tcp_graph_type)graph_type); - connect(stream_dialog, SIGNAL(goToPacket(int)), - packet_list_, SLOT(goToPacket(int))); - connect(this, SIGNAL(setCaptureFile(capture_file*)), - stream_dialog, SLOT(setCaptureFile(capture_file*))); + connect(stream_dialog, &TCPStreamDialog::goToPacket, this, [=](int packet_num) {packet_list_->goToPacket(packet_num);}); + connect(this, &WiresharkMainWindow::setCaptureFile, stream_dialog, &TCPStreamDialog::setCaptureFile); if (stream_dialog->result() == QDialog::Accepted) { stream_dialog->show(); } @@ -3518,31 +3554,68 @@ void WiresharkMainWindow::openTcpStreamDialog(int graph_type) void WiresharkMainWindow::statCommandMulticastStatistics(const char *arg, void *) { MulticastStatisticsDialog *mcast_stats_dlg = new MulticastStatisticsDialog(*this, capture_file_, arg); - connect(mcast_stats_dlg, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType)), - this, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType))); + connect(mcast_stats_dlg, &MulticastStatisticsDialog::filterAction, this, &WiresharkMainWindow::filterAction); mcast_stats_dlg->show(); } -void WiresharkMainWindow::openStatisticsTreeDialog(const gchar *abbr) +void WiresharkMainWindow::openStatisticsTreeDialog(const char *abbr) { StatsTreeDialog *st_dialog = new StatsTreeDialog(*this, capture_file_, abbr); -// connect(st_dialog, SIGNAL(goToPacket(int)), -// packet_list_, SLOT(goToPacket(int))); +// connect(st_dialog, &StatsTreeDialog::goToPacket, packet_list_, &PacketList::goToPacket); st_dialog->show(); } // -z io,stat void WiresharkMainWindow::statCommandIOGraph(const char *, void *) +{ + showIOGraphDialog(IOG_ITEM_UNIT_PACKETS, QString()); +} + +void WiresharkMainWindow::showIOGraphDialog(io_graph_item_unit_t value_units, QString yfield) { const DisplayFilterEdit *df_edit = qobject_cast(df_combo_box_->lineEdit()); + IOGraphDialog *iog_dialog = nullptr; QString displayFilter; if (df_edit) displayFilter = df_edit->text(); - IOGraphDialog *iog_dialog = new IOGraphDialog(*this, capture_file_, displayFilter); - connect(iog_dialog, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int))); - connect(this, SIGNAL(reloadFields()), iog_dialog, SLOT(reloadFields())); - iog_dialog->show(); + if (!yfield.isEmpty()) { + QList iographdialogs = findChildren(); + // GeometryStateDialogs aren't parented on Linux and Windows + // (see geometry_state_dialog.h), so we search for an + // I/O Dialog in all the top level widgets. + if (iographdialogs.isEmpty()) { + foreach(QWidget *topLevelWidget, mainApp->topLevelWidgets()) { + if (qobject_cast(topLevelWidget)) { + iographdialogs << qobject_cast(topLevelWidget); + } + } + } + bool iog_found = false; + foreach(iog_dialog, iographdialogs) { + if (!iog_dialog->fileClosed()) { + iog_found = true; + iog_dialog->addGraph(true, displayFilter, value_units, yfield); + break; + } + } + if (!iog_found) { + iog_dialog = nullptr; + } + } + + if (iog_dialog == nullptr) { + iog_dialog = new IOGraphDialog(*this, capture_file_, displayFilter, value_units, yfield); + connect(iog_dialog, &IOGraphDialog::goToPacket, this, [=](int packet_num) {packet_list_->goToPacket(packet_num);}); + connect(this, &WiresharkMainWindow::reloadFields, iog_dialog, &IOGraphDialog::reloadFields); + } + if (iog_dialog->isMinimized()) { + iog_dialog->showNormal(); + } else { + iog_dialog->show(); + } + iog_dialog->raise(); + iog_dialog->activateWindow(); } // Telephony Menu @@ -3570,7 +3643,7 @@ void WiresharkMainWindow::connectTelephonyMenuActions() connect(main_ui_->actionTelephonyLteMacStatistics, &QAction::triggered, this, [=]() { statCommandLteMacStatistics(NULL, NULL); }); connect(main_ui_->actionTelephonyLteRlcGraph, &QAction::triggered, this, [=]() { // We don't yet know the channel. - launchRLCGraph(false, 0, 0, 0, 0, 0); + launchRLCGraph(false, RLC_RAT_LTE, 0, 0, 0, 0, 0); }); connect(main_ui_->actionTelephonyLteRlcStatistics, &QAction::triggered, this, [=]() { statCommandLteRlcStatistics(NULL, NULL); }); @@ -3595,6 +3668,8 @@ void WiresharkMainWindow::connectTelephonyMenuActions() connect(main_ui_->actionTelephonyNGAPMessages, &QAction::triggered, this, [=]() { openStatisticsTreeDialog("ngap"); }); + connect(main_ui_->actionTelephonyE2APMessages, &QAction::triggered, this, [=]() { openStatisticsTreeDialog("e2ap"); }); + connect(main_ui_->actionTelephonySipFlows, &QAction::triggered, this, [=]() { VoipCallsDialog *dialog = VoipCallsDialog::openVoipCallsDialogSip(*this, capture_file_, packet_list_); dialog->show(); @@ -3626,38 +3701,35 @@ RtpAnalysisDialog *WiresharkMainWindow::openTelephonyRtpAnalysisDialog() return dialog; } -// -z mac-lte,stat +// -z mac-3gpp,stat void WiresharkMainWindow::statCommandLteMacStatistics(const char *arg, void *) { LteMacStatisticsDialog *lte_mac_stats_dlg = new LteMacStatisticsDialog(*this, capture_file_, arg); - connect(lte_mac_stats_dlg, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType)), - this, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType))); + connect(lte_mac_stats_dlg, &LteMacStatisticsDialog::filterAction, this, &WiresharkMainWindow::filterAction); lte_mac_stats_dlg->show(); } void WiresharkMainWindow::statCommandLteRlcStatistics(const char *arg, void *) { LteRlcStatisticsDialog *lte_rlc_stats_dlg = new LteRlcStatisticsDialog(*this, capture_file_, arg); - connect(lte_rlc_stats_dlg, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType)), - this, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType))); + connect(lte_rlc_stats_dlg, &LteRlcStatisticsDialog::filterAction, this, &WiresharkMainWindow::filterAction); // N.B. It is necessary for the RLC Statistics window to launch the RLC graph in this way, to ensure // that the goToPacket() signal/slot connection gets set up... - connect(lte_rlc_stats_dlg, SIGNAL(launchRLCGraph(bool, guint16, guint8, guint16, guint16, guint8)), - this, SLOT(launchRLCGraph(bool, guint16, guint8, guint16, guint16, guint8))); + connect(lte_rlc_stats_dlg, &LteRlcStatisticsDialog::launchRLCGraph, this, &WiresharkMainWindow::launchRLCGraph); lte_rlc_stats_dlg->show(); } void WiresharkMainWindow::launchRLCGraph(bool channelKnown, - guint16 ueid, guint8 rlcMode, - guint16 channelType, guint16 channelId, guint8 direction) + uint8_t RAT, uint16_t ueid, uint8_t rlcMode, + uint16_t channelType, uint16_t channelId, uint8_t direction) { LteRlcGraphDialog *lrg_dialog = new LteRlcGraphDialog(*this, capture_file_, channelKnown); - connect(lrg_dialog, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int))); + connect(lrg_dialog, &LteRlcGraphDialog::goToPacket, this, [=](int packet_num) {packet_list_->goToPacket(packet_num);}); // This is a bit messy, but wanted to hide these parameters from users of // on_actionTelephonyLteRlcGraph_triggered(). if (channelKnown) { - lrg_dialog->setChannelInfo(ueid, rlcMode, channelType, channelId, direction); + lrg_dialog->setChannelInfo(RAT, ueid, rlcMode, channelType, channelId, direction); } lrg_dialog->show(); } @@ -3724,28 +3796,27 @@ void WiresharkMainWindow::connectWirelessMenuActions() { connect(main_ui_->actionBluetoothATT_Server_Attributes, &QAction::triggered, this, [=]() { BluetoothAttServerAttributesDialog *bluetooth_att_sever_attributes_dialog = new BluetoothAttServerAttributesDialog(*this, capture_file_); - connect(bluetooth_att_sever_attributes_dialog, SIGNAL(goToPacket(int)), - packet_list_, SLOT(goToPacket(int))); - connect(bluetooth_att_sever_attributes_dialog, SIGNAL(updateFilter(QString, bool)), - this, SLOT(filterPackets(QString, bool))); + connect(bluetooth_att_sever_attributes_dialog, &BluetoothAttServerAttributesDialog::goToPacket, + this, [=](int packet_num) {packet_list_->goToPacket(packet_num);}); + connect(bluetooth_att_sever_attributes_dialog, &BluetoothAttServerAttributesDialog::updateFilter, + this, &WiresharkMainWindow::filterPackets); bluetooth_att_sever_attributes_dialog->show(); }); connect(main_ui_->actionBluetoothDevices, &QAction::triggered, this, [=]() { BluetoothDevicesDialog *bluetooth_devices_dialog = new BluetoothDevicesDialog(*this, capture_file_, packet_list_); - connect(bluetooth_devices_dialog, SIGNAL(goToPacket(int)), - packet_list_, SLOT(goToPacket(int))); - connect(bluetooth_devices_dialog, SIGNAL(updateFilter(QString, bool)), - this, SLOT(filterPackets(QString, bool))); + connect(bluetooth_devices_dialog, &BluetoothDevicesDialog::goToPacket, this, [=](int packet_num) {packet_list_->goToPacket(packet_num);}); + connect(bluetooth_devices_dialog, &BluetoothDevicesDialog::updateFilter, + this, &WiresharkMainWindow::filterPackets); bluetooth_devices_dialog->show(); }); connect(main_ui_->actionBluetoothHCI_Summary, &QAction::triggered, this, [=]() { BluetoothHciSummaryDialog *bluetooth_hci_summary_dialog = new BluetoothHciSummaryDialog(*this, capture_file_); - connect(bluetooth_hci_summary_dialog, SIGNAL(goToPacket(int)), - packet_list_, SLOT(goToPacket(int))); - connect(bluetooth_hci_summary_dialog, SIGNAL(updateFilter(QString, bool)), - this, SLOT(filterPackets(QString, bool))); + connect(bluetooth_hci_summary_dialog, &BluetoothHciSummaryDialog::goToPacket, + this, [=](int packet_num) {packet_list_->goToPacket(packet_num);}); + connect(bluetooth_hci_summary_dialog, &BluetoothHciSummaryDialog::updateFilter, + this, &WiresharkMainWindow::filterPackets); bluetooth_hci_summary_dialog->show(); }); @@ -3824,7 +3895,7 @@ void WiresharkMainWindow::checkForUpdates() void WiresharkMainWindow::setPreviousFocus() { previous_focus_ = mainApp->focusWidget(); if (previous_focus_ != nullptr) { - connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus())); + connect(previous_focus_, &QWidget::destroyed, this, &WiresharkMainWindow::resetPreviousFocus); } } @@ -3836,7 +3907,7 @@ void WiresharkMainWindow::goToCancelClicked() { main_ui_->goToFrame->animatedHide(); if (previous_focus_) { - disconnect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus())); + disconnect(previous_focus_, &QWidget::destroyed, this, &WiresharkMainWindow::resetPreviousFocus); previous_focus_->setFocus(); resetPreviousFocus(); } @@ -3871,24 +3942,23 @@ void WiresharkMainWindow::showResolvedAddressesDialog() void WiresharkMainWindow::showConversationsDialog() { ConversationDialog *conv_dialog = new ConversationDialog(*this, capture_file_); - connect(conv_dialog, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType)), - this, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType))); - connect(conv_dialog, SIGNAL(openFollowStreamDialog(int, guint, guint)), - this, SLOT(openFollowStreamDialog(int, guint, guint))); - connect(conv_dialog, SIGNAL(openTcpStreamGraph(int)), - this, SLOT(openTcpStreamDialog(int))); + connect(conv_dialog, &ConversationDialog::filterAction, this, &WiresharkMainWindow::filterAction); + connect(conv_dialog, &ConversationDialog::openFollowStreamDialog, this, + [=](int proto_id, unsigned stream_num, unsigned sub_stream_num) { + openFollowStreamDialog(proto_id, stream_num, sub_stream_num); + }); + connect(conv_dialog, &ConversationDialog::openTcpStreamGraph, this, &WiresharkMainWindow::openTcpStreamDialog); conv_dialog->show(); } void WiresharkMainWindow::showEndpointsDialog() { EndpointDialog *endp_dialog = new EndpointDialog(*this, capture_file_); - connect(endp_dialog, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType)), - this, SIGNAL(filterAction(QString, FilterAction::Action, FilterAction::ActionType))); - connect(endp_dialog, SIGNAL(openFollowStreamDialog(int)), - this, SLOT(openFollowStreamDialog(int))); - connect(endp_dialog, SIGNAL(openTcpStreamGraph(int)), - this, SLOT(openTcpStreamDialog(int))); + connect(endp_dialog, &EndpointDialog::filterAction, this, &WiresharkMainWindow::filterAction); + connect(endp_dialog, &EndpointDialog::openFollowStreamDialog, this, + [=](int proto_id) {openFollowStreamDialog(proto_id); + }); + connect(endp_dialog, &EndpointDialog::openTcpStreamGraph, this, &WiresharkMainWindow::openTcpStreamDialog); endp_dialog->show(); } @@ -3906,9 +3976,9 @@ void WiresharkMainWindow::externalMenuItemTriggered() entry = (ext_menubar_t *)v.value(); if (entry->type == EXT_MENUBAR_ITEM) { - entry->callback(EXT_MENUBAR_QT_GUI, (gpointer)((void *)main_ui_), entry->user_data); + entry->callback(EXT_MENUBAR_QT_GUI, (void *)((void *)main_ui_), entry->user_data); } else { - QDesktopServices::openUrl(QUrl(QString((gchar *)entry->user_data))); + QDesktopServices::openUrl(QUrl(QString((char *)entry->user_data))); } } } @@ -3932,15 +4002,11 @@ void WiresharkMainWindow::showExtcapOptionsDialog(QString &device_name, bool sta if (extcap_options_dialog) { extcap_options_dialog->setModal(true); extcap_options_dialog->setAttribute(Qt::WA_DeleteOnClose); - if (startCaptureOnClose) { - connect(extcap_options_dialog, SIGNAL(finished(int)), - this, SLOT(extcap_options_finished(int))); - } + connect(extcap_options_dialog, &ExtcapOptionsDialog::finished, this, &WiresharkMainWindow::extcap_options_finished); #ifdef HAVE_LIBPCAP - if (capture_options_dialog_ && startCaptureOnClose) { + if (capture_options_dialog_) { /* Allow capture options dialog to close */ - connect(extcap_options_dialog, SIGNAL(accepted()), - capture_options_dialog_, SLOT(accept())); + connect(extcap_options_dialog, &ExtcapOptionsDialog::accepted, capture_options_dialog_, &CaptureOptionsDialog::accept); } #endif extcap_options_dialog->show(); diff --git a/ui/qt/wireshark_pl.ts b/ui/qt/wireshark_pl.ts index ed6ef978..530878c0 100644 --- a/ui/qt/wireshark_pl.ts +++ b/ui/qt/wireshark_pl.ts @@ -21,7 +21,7 @@ <span size=\"x-large\" weight=\"bold\">Network Protocol Analyzer</span> - <span size=\"x-large\" weight=\"bold\">Analizator protokołów sieciowych</span> + <span size=\"x-large\" weight=\"bold\">Analizator Protokołów</span> Copy the version information to the clipboard @@ -44,8 +44,8 @@ Foldery - Filter by path - Filtruj po ścieżce + Search Folders + Plugins @@ -79,6 +79,14 @@ License Licencja + + About Logray + O Logray + + + Logray + Logray + The directory does not exist Katalog nie istnieje. @@ -109,10 +117,10 @@ Copy Row(s) - - Kopiuj wiersz - Kopiuj wiersze - Kopiuj wiersze + + + + @@ -137,7 +145,7 @@ Can't assign %1 to %2. - Nie można przypisać %1 do %2. + Nie można przypisać %1 do %2 @@ -755,6 +763,28 @@ …jako EBCDIC + + CaptureCommentDialog + + Edit Capture Comments + Edytuj komentarze przechwytywania + + + Add Comment + Dodaj komentarz + + + Section %1 + Sekcja %1 + + + + CaptureCommentTabWidget + + Comment %1 + Komentarz %1 + + CaptureFile @@ -812,32 +842,6 @@ Automatically detect file type Automatycznie wykryj typ pliku - - %1, error after %Ln packet(s) - %1, error after %2 packets - - %1, błąd po wczytaniu %Ln pakiet - %1, błąd po wczytaniu %Ln pakietów - %1, błąd po wczytaniu %Ln pakietów - - - - %1, timed out at %Ln packet(s) - %1, timed out at %2 packets - - %1, przekroczenie czasu przy %Ln pakiecie - %1, przekroczenie czasu przy %Ln pakiecie - %1, przekroczenie czasu przy %Ln pakiecie - - - - %1, %Ln packet(s) - - %1, %Ln pakiet - %1, %Ln pakiety - %1, %Ln pakietów - - Prepend packets Dodaj pakiety na początku @@ -866,10 +870,6 @@ Read filter: Filtr wczytywania: - - Compress with g&zip - Kompresuj używając gzip - Open Capture File Wireshark: Open Capture File @@ -921,26 +921,26 @@ %1, error after %Ln data record(s) %1, error after %Ln record(s) - - %1, błąd po wczytaniu %Ln pakietu - %1, błąd po wczytaniu %Ln pakietów - %1, błąd po wczytaniu %Ln pakietów + + + + %1, timed out at %Ln data record(s) - - %1, przekroczono limit czasu dla %Ln rekordu danych - %1, przekroczono limit czasu dla %Ln rekordów danych - %1, przekroczono limit czasu dla %Ln rekordów danych + + + + %1, %Ln data record(s) - - %1, %Ln rekord danych - %1, %Ln rekordy danych - %1, %Ln rekordów danych + + + + @@ -955,8 +955,8 @@ Szczegóły - Capture file comments - Komentarze pliku przechwytywania + Edit Comments + Edytuj komentarze Refresh @@ -966,10 +966,6 @@ Copy To Clipboard Skopiuj do schowka - - Save Comments - Zapisz komentarze - Capture File Properties Szczegóły pliku przechwytywania @@ -1018,10 +1014,18 @@ First packet Pierwszy pakiet + + First event + + Last packet Ostatni pakiet + + Last event + + Elapsed Minęło @@ -1058,6 +1062,10 @@ Dropped packets Porzucone pakiety + + Dropped events + + Capture filter Filtr przechwytywania @@ -1070,6 +1078,10 @@ Packet size limit (snaplen) Limit rozmiaru pakietu (snaplen) + + Event size limit (snaplen) + + none brak @@ -1078,6 +1090,26 @@ %1 bytes %1 bajtów + + Comments + Komentarze + + + Comment %1: + Komentarz %1: + + + Decryption Secrets + + + + Type + Typ + + + Size + Rozmiar + Statistics Statystyki @@ -1102,6 +1134,10 @@ Packets Pakiety + + Events + Events + Time span, s Okres czasu, s @@ -1114,6 +1150,10 @@ Average packet size, B Średni rozmiar pakietu, B + + Average event size, B + + Bytes Bajty @@ -1126,14 +1166,14 @@ Average bits/s Średnio bitów/s - - Section Comment - Komentarz sekcji - Packet Comments Komentarze pakietu + + Event Comments + + <p>Frame %1: <p>Ramka %1: @@ -1144,6 +1184,14 @@ Stworzony dzięki Wiresharkowi %1 + + Created by Logray %1 + + + Stworzony dzięki Logray %1 + + + CaptureFilterCombo @@ -1326,7 +1374,7 @@ packets - pakiety + pakietów Switch to the next file after the file size exceeds the specified file size. @@ -1358,7 +1406,7 @@ hours - godzinach + godzin when time is a multiple of @@ -1369,6 +1417,14 @@ For example, use 1 hour to have a new file created every hour on the hour. + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>Zwykle bezprzewodowa karta sieciowa przechwytuje tylko ruch wysyłany do i z jej własnego adresu sieciowego, i tylko przechwytuje ruch <em>danych użytkownika</em> z &quot;fałszywymi&quot; ruch nagłówkami Ethernet. Jeśli chcesz przechwytywać cały ruch, który karty sieci bezprzewodowej mogą „widzieć”, lub interesują Cię pakiety zarządzania lub kontroli standardu 802.11 albo informacje warstwy radiowej, zaznacz tę opcję. Dostępność trybu monitorowania zależy od karty bezprzewodowej i sterownika. Więcej szczegółów na temat przechwytywania pakietów w sieciach WLAN można znaleźć na Wiki.</p></body></html> + + + Enable monitor mode on all 802.11 interfaces + Włącz tryb monitora na wszystkich interfejsach 802.11 + compression kompresja @@ -1381,9 +1437,33 @@ For example, use 1 hour to have a new file created every hour on the hour.gzip gzip + + File infix pattern + + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + + + + YYYYmmDDHHMMSS_NNNNN + YYYYmmDDHHMMSS_NNNNN + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + + + + NNNNN_YYYYmmDDHHMMSS + NNNNN_YYYYmmDDHHMMSS + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> - <html><head/><body><p>Kiedy przechwytywanie jest przekierowywane do nowego pliku i liczba plików zostanie przekroczona to skasuj najstarszy plik.</p></body></html> + Use a ring buffer with @@ -1391,7 +1471,7 @@ For example, use 1 hour to have a new file created every hour on the hour. files - pliki + plików Options @@ -1403,7 +1483,7 @@ For example, use 1 hour to have a new file created every hour on the hour. <html><head/><body><p>Using this option will show the captured packets immediately on the main screen. Please note: this will slow down capturing, so increased packet drops might appear.</p></body></html> - <html><head/><body><p>Wybierając tą opcję przechwytywane pakiety będą bezpośrednio wyświetlane na ekranie. Uwaga: to może spowalniać przechwytywanie, co może skutkować możliwością zgubienia pakietów.</p></body></html> + Update list of packets in real-time @@ -1527,15 +1607,15 @@ For example, use 1 hour to have a new file created every hour on the hour. no addresses - brak adresu + brak adresów Error Błąd - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. - Wiele plików: Żądana wielkość pliku jest zbyt duża. Wielkość pliku nie może być większa niż 2 GiB. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. + Multiple files: No capture file name given. You must specify a filename if you want to use multiple files. @@ -1543,7 +1623,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Multiple files: No file limit given. You must specify a file size, interval, or number of packets for each file. - Wiele plików: bez limitu plików. Dla każdego pliku należy określić rozmiar pliku, interwał lub liczbę pakietów. + @@ -1564,6 +1644,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Capture packets in promiscuous mode Zrzucaj pakiety w trybie mieszanym + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + + + + Capture packets in monitor mode on 802.11 devices + Przechwytuj pakiety w trybie monitora na urządzeniach 802.11 + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>Zapisuj pakiety w formacie pcap-ng</p></body></html> @@ -1746,7 +1834,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Resolve Names: - Rozwiązuj nazwy: + Rozwiąż nazwy: <html><head/><p>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</p></body></html> @@ -1791,6 +1879,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved Rozwiązane + + Width + Szerokość + + + Alignment + Wyrównanie + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> @@ -1838,6 +1934,25 @@ For example, use 1 hour to have a new file created every hour on the hour.Skopiuj filtr do schowka. + + CompressionGroupBox + + Compression options + + + + &Uncompressed + + + + Compress with g&zip + + + + Compress with &LZ4 + + + ConversationDataModel @@ -1904,6 +2019,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Bits/s B Bitów/sek. B + + Flows + + Total Packets Całkowita liczba pakietów @@ -1925,7 +2044,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Graph… - Wykres + Wykres... Graph a TCP conversation. @@ -1951,7 +2070,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Copy entries from another profile. - Kopiuj z innego profilu. + Skopiuj wpisy z innego profilu. System default @@ -2012,20 +2131,12 @@ For example, use 1 hour to have a new file created every hour on the hour. …as Hex Dump - …jako Hex Dump + Copy packet bytes as a hex dump. Kopiuj bajty pakietu jako Hex. - - …as Printable Text - …drukowalny tekst - - - Copy only the printable text in the packet. - Kopiuj tylko drukowalny tekst z pakietu. - …as MIME Data …jako dane MIME @@ -2038,9 +2149,41 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy packet bytes as printable ASCII characters and escape sequences. + + …as Go literal + + + + Copy packet bytes as Go literal. + + + + …as C Array + + + + Copy packet bytes as C Array. + + …as a Hex Stream - …jako strumień Hex + + + + …as UTF-8 Text + + + + Copy packet bytes as text, treating as UTF-8. + + + + …as ASCII Text + + + + Copy packet bytes as text, treating as ASCII. + Copy packet bytes as a stream of hex. @@ -2094,7 +2237,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Change behavior when the field matches this value - + Zmień zachowanie, gdy pole odpowiada tej wartości Field value type (and base, if Integer) @@ -2172,7 +2315,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Display Filter Expression… - Wyrażenie filtru wyświetlania... + Apply a display filter %1 <%2/> @@ -2348,7 +2491,7 @@ For example, use 1 hour to have a new file created every hour on the hour.DissectorTablesProxyModel Table Type - Typ Tabeli + String @@ -2395,7 +2538,7 @@ For example, use 1 hour to have a new file created every hour on the hour. in - w + Enable All @@ -2540,7 +2683,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Save As… - Zapisz jako… + Zapisz jako... Map file error @@ -2778,7 +2921,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Only display entries containing this string - + Wyświetlaj tylko wpisy zawierające ten ciąg Preview @@ -2838,6 +2981,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: Filtr: + + Export PDUs + + ExtArgSelector @@ -2876,10 +3023,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Start Start - - Save - Zapisz - Default Domyślnie @@ -2937,10 +3080,10 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln File(s) in Set %1 File%2 in Set - - %Ln plik w zbiorze - %Ln pliki w zbiorze - %Ln plików w zbiorze + + + + @@ -2971,11 +3114,11 @@ For example, use 1 hour to have a new file created every hour on the hour.FilterAction Selected - Wybrane + Wybrany Not Selected - Nie wybrane + Nie wybrany …and Selected @@ -3022,6 +3165,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Display Filters Filtry wyświetlania + + Display Filter Macros + + + + New macro + Nowe makro + Open Otwórz @@ -3065,7 +3216,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Comment: - Komentarz + Komentarz: Enter a comment for the filter button @@ -3105,10 +3256,18 @@ For example, use 1 hour to have a new file created every hour on the hour. FilterListModel + + Macro Name + Nazwa makra + Filter Name Nazwa filtra + + Macro Expression + + Filter Expression Wyrażenie filtru @@ -3118,11 +3277,11 @@ For example, use 1 hour to have a new file created every hour on the hour.FindLineEdit Textual Find - + Wyszukiwanie tekstu Regular Expression Find - + Wyszukiwanie wyrażeniem regularnym @@ -3194,22 +3353,10 @@ For example, use 1 hour to have a new file created every hour on the hour. FolderListModel - - "File" dialogs - - - - capture files - - Temp Temp - - untitled capture files - - Personal configuration @@ -3218,14 +3365,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Global configuration Konfiguracja globalna - - dfilters, preferences, ethers, … - - - - dfilters, preferences, manuf, … - - System @@ -3238,18 +3377,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Program - - program files - - Personal Plugins Wtyczki osobiste - - binary plugins - - Global Plugins Globalne wtyczki @@ -3266,12 +3397,36 @@ For example, use 1 hour to have a new file created every hour on the hour.Lua scripts Skrypty Lua + + "File" dialog location + + + + Capture files + + + + Untitled capture files + + + + Preferences, profiles, manuf, … + + + + Program files + + + + Binary plugins + + Personal Extcap path - external capture (extcap) plugins + External capture (extcap) plugins @@ -3333,22 +3488,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Print Drukuj - - %Ln client pkt(s), - - %Ln pakiet klienta, - %Ln pakiety klienta, - %Ln pakietów klienta, - - - - %Ln server pkt(s), - - %Ln pakiet serwera, - %Ln pakiety serwera, - %Ln pakietów serwera, - - ASCII ASCII @@ -3391,26 +3530,46 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln <span style="color: %1; background-color:%2">client</span> pkt(s), - - %Ln pakiet <span style="color: %1; background-color:%2">klienta</span>, - %Ln pakiety <span style="color: %1; background-color:%2">klienta</span>, - %Ln pakietów <span style="color: %1; background-color:%2">klienta</span>, + + + + %Ln <span style="color: %1; background-color:%2">server</span> pkt(s), - - %Ln pakiet <span style="color: %1; background-color:%2">serwera</span>, - %Ln pakiety <span style="color: %1; background-color:%2">serwera</span>, - %Ln pakietów <span style="color: %1; background-color:%2">serwera</span>, + + + + %Ln turn(s). - - %Ln próba. - %Ln próby. - %Ln prób. + + + + + + + + Event %1. + Zdarzenie %1. + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + + + + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + + + @@ -3445,6 +3604,18 @@ For example, use 1 hour to have a new file created every hour on the hour.%1 stream not found on the selected packet. Nie znaleziono strumienia %1 w wybranym pakiecie. + + Read activity(%6) + Aktywność odczytu(%6) + + + Write activity(%6) + Aktywność zapisu(%6) + + + Entire I/O activity (%1) + Cała aktywność we/wy (%1) + Entire conversation (%1) @@ -3458,19 +3629,15 @@ For example, use 1 hour to have a new file created every hour on the hour.Błąd tworzenia filtru dla tego strumienia. - Save Stream Content As… - Zapisz zawartość strumienia jako... - - - [Stream output truncated] - + Save Stream Content As… + Zapisz zawartość strumienia jako... %Ln total stream(s). - - %Ln strumień. - %Ln strumienie. - %Ln strumieni. + + + + @@ -3494,9 +3661,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Podpowiedź. - Show data as - Show and save data as - Pokazuj dane jako + Show as + Pokaż jako + + + No delta times + + + + Turn delta times + + + + All delta times + Stream @@ -3510,11 +3688,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: Znajdź: + + Case sensitive + Rozróżniaj wielkość znaków + Find &Next Znajdź &następny + + FollowStreamText + + [Stream output truncated] + [Obcięto dane strumienia] + + FontColorPreferencesFrame @@ -3584,7 +3773,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Sample warning filter Sample deprecated filter - Przykładowy filtr z ostrzeżeniem + Example GIF query packets have jumbo window sizes @@ -3843,30 +4032,29 @@ For example, use 1 hour to have a new file created every hour on the hour. - - Remove this graph. - Remove this dissection behavior. - Usuń ten wykres. - Add a new graph. Utwórz nowy wykres. - - Duplicate this graph. - Duplikuj ten wykres. - Clear all graphs. Wyczyść wszystkie wykresy. - Move this graph upwards. - Przesuń ten wykres w górę. + Remove the selected graph(s). + + + + Duplicate the selected graph(s). + + + + Move the selected graph(s) upwards. + - Move this graph downwards. - Przesuń ten wykres w dół. + Move the selected graph(s) downwards. + Mouse @@ -3908,10 +4096,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Enable legend Włącz legendę - - Reset - Reset - Reset Graph Resetuj wykres @@ -4111,7 +4295,7 @@ For example, use 1 hour to have a new file created every hour on the hour. I/O Graphs - Wykresy I/O + Wykresy we./wy. Save As… @@ -4125,6 +4309,42 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy graphs from another profile. Skopiuj wykresy z innego profilu. + + 1 μs + + + + 2 μs + + + + 5 μs + + + + 10 μs + + + + 20 μs + + + + 50 μs + + + + 100 μs + + + + 200 μs + + + + 500 μs + + 1 ms 1 ms @@ -4169,9 +4389,17 @@ For example, use 1 hour to have a new file created every hour on the hour.5 sec 5 sek. + + 2 min + 10 min {2 ?} + + + 5 min + 10 min {5 ?} + Wireshark I/O Graphs: %1 - Wireshark wykres we./wy.: %1 + Filtered packets @@ -4181,6 +4409,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Filtered events Filtrowane zdarzenia + + All packets + + + + All events + + All Packets Wszystkie pakiety @@ -4194,8 +4430,8 @@ For example, use 1 hour to have a new file created every hour on the hour.Wszystkie zdarzenia - Access Denied - Brak dostępu + All Execs + Hover over the graph for details. @@ -4241,6 +4477,34 @@ For example, use 1 hour to have a new file created every hour on the hour.Click to select a portion of the graph. Kliknij by wybrać obszar wykresu. + + %1 Intervals + + + + Move to top left + + + + Move to top center + + + + Move to top right + + + + Move to bottom left + + + + Move to bottom center + + + + Move to bottom right + + Portable Document Format (*.pdf) Dokument PDF (*.pdf) @@ -4263,7 +4527,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Save Graph As… - Zapisz wykres jako... + Zapisz wykres jako @@ -4718,7 +4982,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Prefix each frame with an Ethernet and IP header - Poprzedź każdą ramkę nagłówkami Ethernet i IPv4 + IP @@ -4726,19 +4990,19 @@ For example, use 1 hour to have a new file created every hour on the hour. Prefix each frame with an Ethernet, IP and UDP header - Poprzedź każdą ramkę nagłówkami Ethernet, IPv4 i UDP + Prefix each frame with an Ethernet, IP and TCP header - Poprzedź każdą ramkę nagłówkami Ethernet, IPv4 i TCP + Prefix each frame with an Ethernet, IP and SCTP header - Poprzedź każdą ramkę nagłówkami Ethernet, IPv4 i SCTP + Prefix each frame with an Ethernet, IP and SCTP (DATA) header - Poprzedź każdą ramkę nagłówkami Ethernet, IPv4 i SCTP (dane) + Source address: @@ -4993,6 +5257,13 @@ For example, use 1 hour to have a new file created every hour on the hour.Zastosuj zmiany + + InterfaceTreeDelegate + + default + domyślny + + InterfaceTreeModel @@ -5057,7 +5328,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Extcap interface: %1 - + Interfejs extcap: %1 No addresses @@ -5972,8 +6243,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteMacStatisticsDialog - LTE Mac Statistics - Statystyki LTE Mac + LTE/NR Mac Statistics + Statystyki LTE/NR Mac Include SR frames in filter @@ -6078,7 +6349,8 @@ For example, use 1 hour to have a new file created every hour on the hour. <html><head/><body><p>Switch the direction of the connection (view the opposite flow).</p></body></html> - <html><head/><body><p>Zmień kierunek przepływu w połączeniu (przepływ w przeciwnym kierunku).</p></body></html> + <html><head/><body><p>Zmień kierunek przepływu w połączeni (przepływ przeciwny). +</p></body></html> Switch Direction @@ -6277,12 +6549,12 @@ For example, use 1 hour to have a new file created every hour on the hour.Numer sekwencyjny - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) - Wykres LTE RLC (UE=%1 kanał=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) + - LTE RLC Graph - no channel selected - Wykres LTE RLC - brak wybranego kanału + 3GPP RLC Graph - no channel selected + Save As… @@ -6336,8 +6608,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteRlcStatisticsDialog - LTE RLC Statistics - Statystyki LTE RLC + 3GPP RLC Statistics + Statystyki 3GPP RLC Include SR frames in filter @@ -6422,6 +6694,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Profile: %1 Profil: %1 + + %1 Displayed: %2 (%3%) + %1 Wyświetlanych: %2 (%3%) + Manage Profiles… Zarządzaj profilami... @@ -6479,10 +6755,18 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln byte(s) , %1 bytes - - %Ln bajt - %Ln bajty - %Ln bajtów + + + + + + + + %Ln bit(s) + + + + @@ -6498,9 +6782,12 @@ For example, use 1 hour to have a new file created every hour on the hour.Wybrany pakiet: %1 %2 - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 - Pakietów: %1 %4 Wyświetlanych: %2 (%3%) + Selected Event: %1 %2 + Wybrane zdarzenie: %1 %2 + + + Events: %1 + Zdarzenie: %1 %1 Selected: %2 (%3%) @@ -6531,6 +6818,10 @@ For example, use 1 hour to have a new file created every hour on the hour.No Packets Brak pakietów + + No Events + Brak zdarzeń + From Zip File... Z pliku ZIP.... @@ -6564,6 +6855,13 @@ For example, use 1 hour to have a new file created every hour on the hour. + + MainWindow + + Display filter as %1 + + + MainWindowPreferencesFrame @@ -6595,6 +6893,10 @@ For example, use 1 hour to have a new file created every hour on the hour.The most recently used folder Ostanio użyty folder + + The current working directory + + Show up to Pokazuj aż do @@ -6790,7 +7092,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Short Name - Krótka Nazwa + Krótka nazwa Vendor Name @@ -7025,6 +7327,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show Field Values Pokaż wartości pól + + Refresh + Odśwież + Save Diagram As… Zapisz diagram jako… @@ -7072,6 +7378,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show packet bytes Pokaż bajty pakietu + + Layout: + Wygląd: + Packet %1 Pakiet %1 @@ -7090,10 +7400,18 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln byte(s) - - %Ln bajt - %Ln bajty - %Ln bajtów + + + + + + + + %Ln bit(s) + + + + @@ -7516,7 +7834,7 @@ For example, use 1 hour to have a new file created every hour on the hour. &Print… - &Drukuj… + &Drukuj... Page &Setup… @@ -7553,10 +7871,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy this profile. Kopiuj ten profil. + + The number of packets or events to check for automatic profile switching. + + + + Auto switch packet limit + + Configuration Profiles Konfiguracja profili + + Auto switch event limit + + Import noun @@ -7577,10 +7907,10 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln Selected Personal Profile(s)... - - %Ln wybrany profil osobisty... - %Ln wybrane profile osobiste... - %Ln wybranych profili osobistych... + + + + @@ -7607,29 +7937,13 @@ For example, use 1 hour to have a new file created every hour on the hour.Select zip file for export Wybierz plik ZIP do wyeksportowania - - … %Ln selected personal profile(s) - - ... %Ln wybrany profil osobisty - ... %Ln wybrane profile osobiste - ... %Ln wybranych profili osobistych - - - - %Ln selected personal profile(s) - - %Ln wybrany profil osobisty - %Ln wybrane profile osobiste - %Ln wybranych profili osobistych - - An import of profiles is not allowed, while changes are pending Import profili nie jest dozwolony, dopóki oczekujące zmiany nie zostaną wprowadzone An import is pending to be saved. Additional imports are not allowed - Import oczekuje na zapisanie. Kolejny import nie jest dozwolony + Import oczekuje na zapisanie. Dodatkowy import nie jest dozwolony An export of profiles is only allowed for personal profiles @@ -7641,10 +7955,10 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln profile(s) exported - - %Ln profil wyeksportowany - %Ln profile wyeksportowane - %Ln profili wyeksportowanych + + + + @@ -7673,18 +7987,18 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln profile(s) imported - - %Ln profil zaimportowany - %Ln profile zaimportowane - %Ln profili zaimportowanych + + + + , %Ln profile(s) skipped - - , %Ln profil pominięto - , %Ln profile pominięto - , %Ln profili pominięto + + + + @@ -7746,6 +8060,10 @@ For example, use 1 hour to have a new file created every hour on the hour.deleted usunięte + + Auto Switch Filter + + copy noun @@ -7789,7 +8107,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Renamed from: %1 - Przemianowano z %1 + Przemianowano z: %1 Copied from: %1 @@ -7898,7 +8216,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Filter Field Reference - Odwołania filtru pola + Odwołania filtru pola Copied @@ -8131,7 +8449,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Prepare as Filter - Przygotuj jako filtr + Find @@ -8269,6 +8587,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Marker missing? Brakujący znacznik? + + LTE + LTE + + + NR + NR + C-RNTI C-RNTI @@ -8289,6 +8615,10 @@ For example, use 1 hour to have a new file created every hour on the hour.UEId UEId + + RAT + RAT + UL Frames Ramki UL @@ -8466,56 +8796,116 @@ For example, use 1 hour to have a new file created every hour on the hour.Niepoprawny filtr wyświetlania - The filter expression %1 isn't a valid display filter. (%2). - Filtr %1 nie jest poprawnym filtrem wyświetlania. (%2). + The filter expression %1 isn't a valid display filter. (%2). + Filtr %1 nie jest poprawnym filtrem wyświetlania. (%2). + + + Error + Błąd + + + No remote interfaces found. + Nie znaleziono zdalnych interfejsów. + + + PCAP not found + PCAP nie znaleziony + + + Unknown error + Nieznany błąd + + + Default + Domyślnie + + + Changed + Zmienione + + + Has this preference been changed? + Czy to ustawienie zostało zmienione? + + + Default value is empty + Domyślna wartość jest pusta + + + Gap in dissection + + + + Edit… + Edytuj... + + + Browse… + Przeglądaj… + + + PACKETS + + + + EVENTS + + + + BYTES + - Error - Błąd + BITS + - No remote interfaces found. - Nie znaleziono zdalnych interfejsów. + COUNT FRAMES + - PCAP not found - PCAP nie znaleziony + COUNT FIELDS + - Unknown error - Nieznany błąd + SUM + - Default - Domyślnie + MAX + - Changed - Zmienione + MIN + - Has this preference been changed? - Czy to ustawienie zostało zmienione? + AVERAGE + - Default value is empty - Domyślna wartość jest pusta + THROUGHPUT + - Gap in dissection + LOAD - Edit… - Edytuj... + Left + W lewo - Browse… - Przeglądaj… + Center + + + + Right + W prawo - QObject::QObject + QObject::QObject::QObject CCCH CCCH @@ -8615,6 +9005,13 @@ For example, use 1 hour to have a new file created every hour on the hour.milisekundy + + ResizeHeaderView + + Resize all %1 to contents + + + ResolvedAddressesDialog @@ -8730,6 +9127,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved Addresses Rozwiązane Adresy + + Copy + Kopiuj + + + Save as… + Zapisz jako… + # Resolved addresses found in %1 # Rozwiązane adresy znalezione w %1 @@ -8743,6 +9148,61 @@ For example, use 1 hour to have a new file created every hour on the hour. + + ResolvedAddressesView + + as Plain Text + jako zwykły tekst + + + Copy selected rows + Skopiuj wybrane wiersze + + + Copy table + Skopiuj tabelę + + + as CSV + jako CSV + + + as JSON + jako JSON + + + Save selected rows as… + Zapisz wybrane wiersze jako… + + + Save table as… + Zapisz tabelę jako… + + + Save Resolved Addresses As… + Zapisz rozwiązane adresy jako… + + + Plain text (*.txt) + Zwykły tekst (*.txt) + + + CSV Document (*.csv) + Dokument CSV (*.csv) + + + JSON Document (*.json) + Dokument JSON (*.json) + + + Warning + Ostrzeżenie + + + Unable to save %1: %2 + Nie można zapisać %1: %2 + + ResponseTimeDelayDialog @@ -8965,7 +9425,7 @@ For example, use 1 hour to have a new file created every hour on the hour. %1 streams, - %1 strumieni, + %1 strumieni. Save one stream CSV @@ -9081,15 +9541,15 @@ For example, use 1 hour to have a new file created every hour on the hour. Prepare &Filter - Przygotuj &filtr + Przygotuj filtr Prepare a filter matching the selected stream(s). - Przygotuj filtr pasujący do wybranego(ych) strumieni. + Przygotuj filtr dla zaznaczonych strumieni. &Current Tab - &Bieżąca karta + Prepare a filter matching current tab. @@ -9364,7 +9824,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Remove Streams - Usuń strumienie + Remove selected streams from the list @@ -9440,15 +9900,15 @@ For example, use 1 hour to have a new file created every hour on the hour. Prepare &Filter - Przygotuj &filtr + Przygotuj filtr Prepare a filter matching the selected stream(s). - + Przygotuj filtr dla zaznaczonych strumieni. R&efresh streams - &Odśwież strumienie + Read captured packets from capture in progress to player @@ -9504,7 +9964,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Play the stream - + Odtwórz strumień To Left @@ -9536,7 +9996,7 @@ For example, use 1 hour to have a new file created every hour on the hour. &Play Streams - &Odtwarzaj strumienie + Open RTP player dialog @@ -9568,7 +10028,7 @@ For example, use 1 hour to have a new file created every hour on the hour. No Audio - Brak audio + Brak Audio Decoding streams... @@ -9616,7 +10076,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Playback of stream %1 failed! - Odtwarzanie strumienia %1 nie powiodło się! + Automatic @@ -9775,7 +10235,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Prepare &Filter - Przygotuj &filtr + Przygotuj filtr &Export @@ -9955,7 +10415,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Save RTPDump As… - + Zapisz RTPDump jako @@ -10417,6 +10877,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Packet bytes Bajty pakietu + + <b>Options:</b> + <b>Opcje:</b> + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>Szukaj ciągu znaków w kodowanie wąskim (UTF-8 i ASCII) lub szerokim (UTF-16).</p></body></html> @@ -10437,6 +10901,18 @@ For example, use 1 hour to have a new file created every hour on the hour.Case sensitive Rozróżniaj wielkość znaków + + Backwards + Wstecz + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + + + + Multiple occurrences + Wiele wystąpień + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10474,6 +10950,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Invalid filter. Błędny filtr. + + Event List + + + + Event Details + + + + Event Bytes + + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + + That filter doesn't test anything. Ten filtr nie sprawdza niczego. @@ -10539,18 +11031,18 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln node(s) - - %Ln węzeł - %Ln węzły - %Ln węzłów + + %Ln node + %Ln nodes + %Ln item(s) - - %Ln obiekt - %Ln obiekty - %Ln obiektów + + %Ln item + %Ln items + @@ -10919,16 +11411,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: Znajdź: + + Case sensitive + Rozróżniaj wielkość znaków + Find &Next Znajdź &następny Frame %1, %2, %Ln byte(s). - - Ramka %1, %2, %Ln bajt. - Ramka %1, %2, %Ln bajty. - Ramka %1, %2, %Ln bajtów. + + + + @@ -11015,16 +11511,24 @@ For example, use 1 hour to have a new file created every hour on the hour.Save as… Zapisz jako… + + Decoded as %1. + + Save Selected Packet Bytes As… Zapisz zaznaczone bajty pakietu jako + + compressed %1 + + - Displaying %Ln byte(s). - - Wyświetlanych %Ln bajt. - Wyświetlane bajty: %Ln. - Wyświetlanych bajtów: %Ln. + Using %Ln byte(s). + + + + @@ -11124,6 +11628,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: Filtr wyświetlania: + + Strip Headers + + SupportedProtocolsDialog @@ -11179,7 +11687,7 @@ For example, use 1 hour to have a new file created every hour on the hour. "%1" is deprecated in favour of "%2". See Help section 6.4.8 for details. - "%1" jest przestarzałe na rzecz "%2".. Aby uzyskać szczegółowe informacje, zobacz sekcję Pomocy 6.4.8. + %1 @@ -12024,7 +12532,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Copy all values of this page to the clipboard in CSV (Comma Separated Values) format. - Kopiuj wszystkie wartości z tej strony w CSV (Comma Separated Values) do schowka. + as YAML @@ -12032,7 +12540,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Copy all values of this page to the clipboard in the YAML data serialization format. - Kopiuj wszystkie wartości z tej strony w formacie YAML do schowka. + as JSON @@ -12040,7 +12548,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Copy all values of this page to the clipboard in the JSON data serialization format. - Kopiuj wszystkie wartości z tej strony w formacie JSON do schowka. + Save data as raw @@ -12092,22 +12600,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Stwórz nowy wpis. - Remove this entry. - Remove this profile. - Usuń wpis. + Remove the selected entry(ies). + - Copy this entry. - Copy this profile. - Kopiuj wpis. + Copy the selected entry(ies). + - Move entry up. - Przesuń wpis w górę. + Move the selected entry(ies) up. + - Move entry down. - Przesuń wpis w dół. + Move the selected entry(ies) down. + Clear all entries. @@ -12133,20 +12639,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Stwórz nowy wpis. - Remove this entry. - Usuń wpis. + Remove the selected entry(ies). + - Copy this entry. - Kopiuj wpis. + Copy the selected entry(ies). + - Move entry up. - Przesuń wpis w górę. + Move the selected entry(ies) up. + - Move entry down. - Przesuń wpis w dół. + Move the selected entry(ies) down. + Clear all entries. @@ -12197,7 +12703,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Prepare &Filter - Przygotuj &filtr + Przygotuj filtr Prepare a filter matching the selected calls(s). @@ -12293,7 +12799,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Select - &Wybrane + Wybrane @@ -12507,20 +13013,28 @@ a:hover { %n interface(s) shown, %1 hidden - - %n wyświetlany interfejs, %1 ukrytych - %n wyświetlane interfejsy, %1 ukrytych - %n wyświetlanych interfejsów, %1 ukrytych + + %n interface shown, %1 hidden + %n interfaces shown, %1 hidden + You are sniffing the glue that holds the Internet together using Wireshark Dzięki Wiresharkowi podglądasz fundamenty współczesnego Internetu. + + You are sniffing the glue that holds your system together using Logray + + You are running Wireshark Używasz Wireshark + + You are running Logray + Logray uruchomiony + You receive automatic updates. Automatyczne aktualizacje są włączone. @@ -12679,7 +13193,7 @@ a:hover { Prepare as Filter - Przygotuj jako filtr + SCTP @@ -12719,7 +13233,7 @@ a:hover { &Analyze - &Analiza + Analizuj Follow @@ -12797,21 +13311,13 @@ a:hover { No files found Nie znaleziono pliku - - &Contents - Podrę&cznik - - - Wireshark Filter - Filtr - TShark TShark Rawshark - RawShark + Dumpcap @@ -13055,7 +13561,7 @@ a:hover { &DTN - &DTN + Osmux @@ -13070,10 +13576,6 @@ a:hover { Wireless Toolbar Pasek sniffera WiFi - - Help contents - Pomoc - FAQs FAQ @@ -13194,11 +13696,6 @@ a:hover { Find the previous packet Znajdź poprzedni pakiet - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - &Zaznacz/odznacz pakiet - Mark All Displayed Zaznacz wszystkie wyświetlane @@ -13227,11 +13724,6 @@ a:hover { Go to the previous marked packet Idź do poprzedniego zaznaczonego pakietu - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - &Ignoruj/odignoruj pakiet - Ignore All Displayed Ignoruj wszystkie wyświetlane @@ -13538,7 +14030,7 @@ a:hover { Osmux packet counts - Liczba pakietów Osmux + RTSP packet counts @@ -13650,7 +14142,7 @@ a:hover { &I/O Graphs - &Wykresy wej./wyj. + &Wykresy we./wy. &Conversations @@ -13670,11 +14162,7 @@ a:hover { Reset Layout - - - - Reset appearance layout to default size - Resetuje układ do rozmiarów domyślnych + Resetuj wygląd Seconds Since First Captured Packet @@ -13762,7 +14250,7 @@ a:hover { Display Filter Expression… - Wyrażenie filtru wyświetlania... + REGISTER_STAT_GROUP_RSERPOOL @@ -13837,20 +14325,28 @@ a:hover { Bloki adresów MAC - TLS Keylog Launcher + &Options… + &Opcje… + + + &3GPP Uu - Release Notes - Informacje o wydaniu + &Wireless + Bezprze&wodowe - &Options… - &Opcje… + &User's Guide + - &Wireless - Bezprze&wodowe + Wireshark User's Guide + + + + Display Filters + Filtry wyświetlania Capture &Filters… @@ -13896,10 +14392,18 @@ a:hover { Find Pre&vious Znajdź poprzedni… + + &Mark/Unmark Selected + &Zaznacz/Odznacz wybrane + Mark or unmark each selected packet + + &Ignore/Unignore Selected + + Ignore or unignore each selected packet @@ -13940,6 +14444,18 @@ a:hover { TCP throughput + + General + Ogólne + + + Query-Response + + + + DNS Query-Response Statistics + Statystyki odpowiedzi na zapytania DNS + Request Sequences @@ -13948,6 +14464,14 @@ a:hover { HTTP Request Sequences + + E2AP + E2AP + + + E2AP Messages + + Decode &As… Dekoduj jako… @@ -14008,6 +14532,10 @@ a:hover { Normal Size Normalny rozmiar + + Reset layout to default size + + Resize Columns Zmień rozmiar kolumn @@ -14231,7 +14759,7 @@ a:hover { RTP Player - Odtwarzacz RTP + Odtwarzacz RTP Play selected stream. Press CTRL key for playing reverse stream too. @@ -14266,6 +14794,14 @@ a:hover { Go to the packet referenced by the selected field. Idź do pakietu do którego odwołuje się zaznaczone pole. + + TLS Keylog Launcher + + + + Release Notes + Informacje o wydaniu + &VoIP Calls Połączenia VoIP @@ -14298,10 +14834,6 @@ a:hover { &GSM &GSM - - &LTE - &LTE - &MTP3 &MTP3 @@ -14546,11 +15078,11 @@ a:hover { Unable to drop files during capture. - Nie można porzucić pliku podczas przechwytywania. + Unknown file type returned by merge dialog. - Nieznany typ pliku zwrócony przez okno dialogowe łączenia plików. + Please report this as a Wireshark issue at https://gitlab.com/wireshark/wireshark/-/issues. @@ -14558,7 +15090,7 @@ a:hover { Unknown file type returned by export dialog. - Nieznany typ pliku zwrócony przez okno dialogowe eksportu. + Do you want to stop the capture and save the captured packets%1? @@ -14586,9 +15118,13 @@ a:hover { Quit without Saving Wyjdź bez zapisy&wania + + USB CDC Data + Dane USB CDC + There is no "rtp.ssrc" field in this version of Wireshark. - Brak pola "rtp.ssrc" w tej wersji programu Wireshark. + Please select an RTPv2 packet with an SSRC value @@ -14648,15 +15184,6 @@ a:hover { No Keys Brak kluczy - - Export SSL Session Keys (%Ln key(s)) - Export SSL Session Keys (%1 key%2 - - Eksportuj klucze sesji SSL (%Ln klucz) - Eksportuj klucze sesji SSL (%Ln klucze) - Eksportuj klucze sesji SSL (%Ln kluczy) - - Raw data (*.bin *.dat *.raw);;All Files ( Surowe dane (*.bin *.dat *.raw);;Dowolny plik ( @@ -14687,7 +15214,7 @@ a:hover { No interface selected. - Nie wybrano interfejsu. + Nie wybrano interfejsu Saving %1… @@ -14726,10 +15253,10 @@ a:hover { Delete comments from %n packet(s) - - Usuń komentarze z %n pakietu - Usuń komentarze z %n pakietów - Usuń komentarze z %n pakietów + + + + @@ -14750,14 +15277,14 @@ a:hover { There are no TLS Session Keys to save. - Nie ma żadnych kluczy sesji SSL do zapisu. + Nie ma żadnych kluczy sesji TLS do zapisu. Export TLS Session Keys (%Ln key(s)) - - Eksportuj klucze sesji TLS (%Ln klucz) - Eksportuj klucze sesji TLS (%Ln klucze) - Eksportuj klucze sesji TLS (%Ln kluczy) + + + + @@ -14802,7 +15329,7 @@ a:hover { No Interface Selected. - Nie wybrano interfejsu. + Nie wybrano interfejsu before restarting the capture diff --git a/ui/qt/wireshark_ru.ts b/ui/qt/wireshark_ru.ts index b3d6b730..2bd5d309 100644 --- a/ui/qt/wireshark_ru.ts +++ b/ui/qt/wireshark_ru.ts @@ -44,8 +44,8 @@ Папки - Filter by path - Фильтр по пути размещения + Search Folders + Поиск папок Plugins @@ -79,6 +79,14 @@ License Лицензия + + About Logray + О Logray + + + Logray + Журнал + The directory does not exist Каталог отсутствует @@ -109,10 +117,10 @@ Copy Row(s) - - - - + + Копировать строку + Копировать строки + Копировать строки @@ -732,11 +740,11 @@ …as decimal - + ... как десятичный …as octal - + ...как восьмеричный …as bits @@ -755,6 +763,28 @@ …в виде EBCDIC + + CaptureCommentDialog + + Edit Capture Comments + Редактирование комментариев к захвату + + + Add Comment + Добавить комментарий + + + Section %1 + Раздел %1 + + + + CaptureCommentTabWidget + + Comment %1 + Комментарий %1 + + CaptureFile @@ -812,6 +842,32 @@ Automatically detect file type Автоматически определить тип файла + + %1, error after %Ln packet(s) + %1, error after %2 packets + + %1, ошибка после %Ln пакета + %1, ошибка после %Ln пакетов + %1, ошибка после %Ln пакетов + + + + %1, timed out at %Ln packet(s) + %1, timed out at %2 packets + + %1, таймер прерван на %Ln пакете + %1, таймер прерван на %Ln пакетах + %1, таймер прерван на %Ln пакетах + + + + %1, %Ln packet(s) + + %1, %Ln пакет + %1, %Ln пакета + %1, %Ln пакетов + + Prepend packets Добавить пакеты к началу файла @@ -840,10 +896,6 @@ Read filter: Фильтр чтения: - - Compress with g&zip - Сжать с помощью g&zip - Open Capture File Wireshark: Open Capture File @@ -895,26 +947,26 @@ %1, error after %Ln data record(s) %1, error after %Ln record(s) - - - - + + %1, ошибка после %Ln записи данных + %1, ошибка после %Ln записей данных + %1, ошибка после %Ln записей данных %1, timed out at %Ln data record(s) - - - - + + %1, таймер прерван на %Ln записи данных + %1, таймер прерван на %Ln записи данных + %1, таймер прерван на %Ln записях данных %1, %Ln data record(s) - - - - + + %1, %Ln запись данных + %1, %Ln записи данных + %1, %Ln записей данных @@ -929,8 +981,8 @@ Подробности - Capture file comments - Комментарии в файле захвата + Edit Comments + Редактировать комментарии Refresh @@ -940,10 +992,6 @@ Copy To Clipboard Копировать в буфер обмена - - Save Comments - Сохранить комментарии - Capture File Properties Свойства файла захвата @@ -992,10 +1040,18 @@ First packet Первый пакет + + First event + Первое событие + Last packet Последний пакет + + Last event + Последнее событие + Elapsed Прошло @@ -1032,6 +1088,10 @@ Dropped packets Потерянные пакеты + + Dropped events + Отмененные события + Capture filter Фильтр захвата @@ -1044,6 +1104,10 @@ Packet size limit (snaplen) Ограничение на размер пакета (snaplen) + + Event size limit (snaplen) + Ограничение размера события (оснастка) + none нет @@ -1052,6 +1116,26 @@ %1 bytes %1 Б + + Comments + Комментарии + + + Comment %1: + Комментарий %1: + + + Decryption Secrets + Секреты расшифровки + + + Type + Тип + + + Size + Размер + Statistics Статистика @@ -1076,18 +1160,26 @@ Packets Пакеты + + Events + События + Time span, s Временной промежуток, с Average pps - В среднем, пакетов/с + В среднем, пакетов/с Average packet size, B Средний размер пакета, Б + + Average event size, B + Средний размер события, B + Bytes Байты @@ -1100,14 +1192,14 @@ Average bits/s В среднем бит/с - - Section Comment - Комментарий к разделу - Packet Comments Комментарии к пакету + + Event Comments + Комментарии к событию + <p>Frame %1: <p>Кадр %1: @@ -1118,6 +1210,14 @@ Создано в Wireshark %1 + + + + Created by Logray %1 + + + Создано Logray %1 + @@ -1346,6 +1446,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Переходить на следующий файл при достижении указанного кратного интервала времени. Например, если указать 1 час, то каждый час будет создаваться новый файл. + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>Обычно беспроводная сетевая карта перехватывает только трафик, отправленный на ее собственный сетевой адрес и с него, а также трафик пользовательских данных<em> с &quot;поддельными</em>&quot; заголовками Ethernet. Если вы хотите перехватывать весь трафик, который могут &quot;видеть&quot; беспроводные сетевые карты, или вас интересуют пакеты управления или контроля 802.11, или информация радиоуровня, отметьте этот параметр. Доступность режима мониторинга зависит от беспроводной карты и драйвера. Дополнительные сведения о перехвате пакетов в сетях WLAN см. в Wiki.</p></body></html> + + + Enable monitor mode on all 802.11 interfaces + Включите режим монитора на всех интерфейсах 802.11 + compression сжатие @@ -1358,6 +1466,30 @@ For example, use 1 hour to have a new file created every hour on the hour.gzip gzip + + File infix pattern + Инфиксный шаблон файла + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + <html><head/><body><p>В режиме нескольких файлов дата и время, а также индексный номер файла вставляются между шаблоном имени файла и любым суффиксом. Выберите их порядок.</p></body></html> + + + YYYYmmDDHHMMSS_NNNNN + YYYYmmDDHHMMSS_NNNNN + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + <html><head/><p>Дата и время перед индексным номером файла. В результате файлы сортируются в порядке времени создания, а файлы из одной партии располагаются в строгом порядке.</p><body></html> + + + NNNNN_YYYYmmDDHHMMSS + NNNNN_YYYYmmDDHHMMSS + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + <html><head/><body><p>Номер индекса файла перед датой и временем. Это исторический заказ Wireshark.</p></body></html> + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> <html><head/><body><p>При переходе записи данных на следующий файл превышение указанного здесь числа файлов приведёт к удалению самого старого из них.</p></body></html> @@ -1448,7 +1580,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Stop capturing after the specified number of files have been created. - + Остановка захвата после создания указанного количества файлов. <html><head/><body><p>Stop capturing after the specified amount of data has been captured.</p></body></html> @@ -1511,8 +1643,8 @@ For example, use 1 hour to have a new file created every hour on the hour.Ошибка - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. - Несколько файлов: Указан слишком большой размер файла. Размер файла не может превышать 2 ГиБ. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. + Несколько файлов: Запрашиваемый размер файлов слишком велик. Размер файлов не может превышать 2 ТБ. Multiple files: No capture file name given. You must specify a filename if you want to use multiple files. @@ -1541,6 +1673,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Capture packets in promiscuous mode Захватывать пакеты в смешанном режиме + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>Обычно беспроводная сетевая карта перехватывает только трафик, отправленный на ее собственный сетевой адрес и с него,<em> а также трафик пользовательских данных с &quot;поддельными</em>&quot; заголовками Ethernet. Если вы хотите перехватывать весь трафик, который могут &quot;видеть&quot; беспроводные сетевые карты, или вас интересуют пакеты управления или контроля 802.11, или информация радиоуровня, отметьте этот параметр. Доступность режима мониторинга зависит от беспроводной карты и драйвера. Дополнительные сведения о перехвате пакетов в сетях WLAN см. в Wiki.</p></body></html> + + + Capture packets in monitor mode on 802.11 devices + Захват пакетов в режиме монитора на устройствах 802.11 + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>Выполнять захват пакетов в формате файла захвата следующего поколения «pcapng».</p></body></html> @@ -1559,15 +1699,15 @@ For example, use 1 hour to have a new file created every hour on the hour. Interval between updates (ms) - + Интервал между обновлениями (мс) <html><head/><body><p>How often the capture notifies the GUI of new packets. Affects how often the GUI updates and the granularity of timers.</p></body></html> - + <html><head/><body><p>Как часто захват уведомляет графический интерфейс о новых пакетах. Влияет на частоту обновления графического интерфейса и гранулярность таймеров.</p></body></html> <html><head/><body><p>The interval between new packet updates. Affects how often the GUI updates and the granularity of timers.</p></body></html> - + <head/><body><p>Интервал между новыми обновлениями пакетов. Влияет на частоту обновления графического интерфейса и гранулярность таймеров.</p></body><html> Don't load interfaces on startup @@ -1661,7 +1801,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Open - Открыть + Открыть Double click to edit. Drag to move. Rules are processed in order until a match is found. @@ -1768,6 +1908,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved Разрешено + + Width + Ширина + + + Alignment + Выравнивание + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> <html>Показывать человекочитаемые строки вместо необработанных значений полей. Может применяться только к дополнительным столбцам с полями, содержащими строки значений.</html> @@ -1815,6 +1963,25 @@ For example, use 1 hour to have a new file created every hour on the hour.Копировать текст фильтра в буфер обмена. + + CompressionGroupBox + + Compression options + Опции сжатия + + + &Uncompressed + &Не сжатый + + + Compress with g&zip + Сжатие с помощью g&zip + + + Compress with &LZ4 + Сжатие с помощью &LZ4 + + ConversationDataModel @@ -1881,6 +2048,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Bits/s B Бит/с B + + Flows + Потоки + Total Packets Всего пакетов @@ -1996,29 +2167,53 @@ For example, use 1 hour to have a new file created every hour on the hour.Копировать байты пакета в виде шестнадцатеричного дампа. - …as Printable Text - + …as MIME Data + ...как данные MIME - Copy only the printable text in the packet. - + …as C String + ...как строка C - …as MIME Data - + Copy packet bytes as printable ASCII characters and escape sequences. + Копирование байтов пакета в виде печатаемых символов ASCII и управляющих последовательностей. - …as C String - + …as Go literal + ...как буквальный го - Copy packet bytes as printable ASCII characters and escape sequences. - + Copy packet bytes as Go literal. + Скопируйте байты пакета как литерал Go. + + + …as C Array + ...как массив C + + + Copy packet bytes as C Array. + Скопируйте байты пакета в массив C. …as a Hex Stream …в виде шестнадцатеричного потока + + …as UTF-8 Text + ...как текст UTF-8 + + + Copy packet bytes as text, treating as UTF-8. + Копирование байтов пакета в виде текста с обработкой в формате UTF-8. + + + …as ASCII Text + ... как текст ASCII + + + Copy packet bytes as text, treating as ASCII. + Копирование байтов пакета в виде текста с обработкой в формате ASCII. + Copy packet bytes as a stream of hex. Копировать байты пакета в виде шестнадцатеричного потока. @@ -2060,7 +2255,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Open - Открыть + Открыть @@ -2299,11 +2494,11 @@ For example, use 1 hour to have a new file created every hour on the hour.DissectorSyntaxLineEdit Dissector entry - + Вход в диссектор Enter a dissector %1 - + Введите рассекатель %1 @@ -2815,6 +3010,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: Фильтр отображения: + + Export PDUs + Экспорт PDU + ExtArgSelector @@ -2853,10 +3052,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Start Старт - - Save - Сохранить - Default По умолчанию @@ -2914,10 +3109,10 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln File(s) in Set %1 File%2 in Set - - - - + + %Ln Файл в Наборе + %Ln Файла в Наборе + %Ln Файлов в Наборе @@ -2999,9 +3194,17 @@ For example, use 1 hour to have a new file created every hour on the hour.Display Filters Фильтры отображения + + Display Filter Macros + Макросы фильтров отображения + + + New macro + Новый макрос + Open - Открыть + Открыть New capture filter @@ -3082,10 +3285,18 @@ For example, use 1 hour to have a new file created every hour on the hour. FilterListModel + + Macro Name + Название макроса + Filter Name Имя фильтра + + Macro Expression + Макро выражение + Filter Expression Выражение фильтра @@ -3171,22 +3382,10 @@ For example, use 1 hour to have a new file created every hour on the hour. FolderListModel - - "File" dialogs - Диалоговые окна открытия файлов - - - capture files - Файлы захвата - Temp Временные файлы - - untitled capture files - Безымянные файлы захвата - Personal configuration Персональная конфигурация @@ -3195,14 +3394,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Global configuration Глобальная конфигурация - - dfilters, preferences, ethers, … - dfilters, preferences, ethers, … - - - dfilters, preferences, manuf, … - dfilters, preferences, manuf, … - System Конфигурация системы @@ -3215,18 +3406,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Program Программы - - program files - Файлы программ - Personal Plugins Пользовательские подключаемые модули - - binary plugins - Исполняемые файлы подключаемых модулей - Global Plugins Глобальные подключаемые модули @@ -3243,13 +3426,37 @@ For example, use 1 hour to have a new file created every hour on the hour.Lua scripts Сценарии Lua + + "File" dialog location + Местонахождение диалога "Файл" + + + Capture files + Захват файлов + + + Untitled capture files + Файлы захвата без названия + + + Preferences, profiles, manuf, … + Предпочтения, профили, производство, ... + + + Program files + Программные файлы + + + Binary plugins + Бинарные плагины + Personal Extcap path Пользовательский путь Extcap - external capture (extcap) plugins - модули внешненго захвата (extcap) + External capture (extcap) plugins + Плагины для внешнего захвата (extcap) Global Extcap path @@ -3296,7 +3503,7 @@ For example, use 1 hour to have a new file created every hour on the hour.FollowStreamAction %1 Stream - + %1 Поток @@ -3310,6 +3517,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Print Печать + + %Ln client pkt(s), + + %Ln клиентский пакет, + %Ln клиентских пакета, + %Ln клиентских пакетах, + + + + %Ln server pkt(s), + + %Ln серверный пакет, + %Ln серверных пакета, + %Ln серверных пакетов, + + ASCII ASCII @@ -3352,26 +3575,46 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln <span style="color: %1; background-color:%2">client</span> pkt(s), - - - - + + %Ln <span style="color: %1; background-color:%2">клиентский</span> пакет, + %Ln <span style="color: %1; background-color:%2">клиентских</span> пакета, + %Ln <span style="color: %1; background-color:%2">клиентских</span> пакетов, %Ln <span style="color: %1; background-color:%2">server</span> pkt(s), - - - - + + %Ln <span style="color: %1; background-color:%2">серверный</span> пакет, + %Ln <span style="color: %1; background-color:%2">серверных</span> пакета, + %Ln <span style="color: %1; background-color:%2">серверных</span> пакетов, %Ln turn(s). - - - - + + %Ln поворот. + %Ln поворота. + %Ln поворотов. + + + + Event %1. + Событие %1. + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + %Ln <span style="color: %1; background-color:%2">чтение</span>, + %Ln <span style="color: %1; background-color:%2">чтения</span>, + %Ln <span style="color: %1; background-color:%2">чтений</span>, + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + %Ln <span style="color: %1; background-color:%2">запись</span>, + %Ln <span style="color: %1; background-color:%2">записи</span>, + %Ln <span style="color: %1; background-color:%2">записей</span>, @@ -3406,6 +3649,18 @@ For example, use 1 hour to have a new file created every hour on the hour.%1 stream not found on the selected packet. Поток %1 не найден в выбранном пакете. + + Read activity(%6) + Активность чтения(%6) + + + Write activity(%6) + Письменная активность(%6) + + + Entire I/O activity (%1) + Вся активность ввода/вывода (%1) + Entire conversation (%1) Весь диалог (%1) @@ -3422,24 +3677,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Save Stream Content As… Сохранить содержимое потока как… - - [Stream output truncated] - [Вывод потока усечён] - %Ln total stream(s). - - - - + + %Ln всего поток. + %Ln всех потоков. + %Ln всех потоков. Max sub stream ID for the selected stream: %Ln - - - - + + Максимальный идентификатор подпотока для выбранного потока: %Ln + Максимальный идентификатор подпотока для выбранных потоков: %Ln + Максимальный идентификатор подпотока для выбранных потоков: %Ln @@ -3455,9 +3706,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Подсказка. - Show data as - Show and save data as - Отобразить данные в виде + Show as + Показать как + + + No delta times + Нет дельты времени + + + Turn delta times + Дельта времени поворота + + + All delta times + Все дельта-время Stream @@ -3471,11 +3733,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: Найти: + + Case sensitive + С учетом регистра + Find &Next Найти &далее + + FollowStreamText + + [Stream output truncated] + [Вывод потока усечен] + + FontColorPreferencesFrame @@ -3550,11 +3823,11 @@ For example, use 1 hour to have a new file created every hour on the hour. Example GIF query packets have jumbo window sizes These are pangrams. Feel free to replace with nonsense text that spans your alphabet. https://en.wikipedia.org/wiki/Pangram - Любя, съешь щипцы, — вздохнёт мэр, — кайф жгуч. + Любя, съешь щипцы, — вздохнёт мэр, — кайф жгуч Lazy badgers move unique waxy jellyfish packets - Съешь же ещё этих мягких французских булок да выпей чаю. + Съешь же ещё этих мягких французских булок да выпей чаю Font @@ -3698,23 +3971,23 @@ For example, use 1 hour to have a new file created every hour on the hour.IOConsoleDialog Dialog - + Диалог Enter code - + Введите код Evaluate - + Оценить Clear - Очистить + Очистить Use %1 to evaluate. - + Используйте %1 для оценки. @@ -3811,30 +4084,29 @@ For example, use 1 hour to have a new file created every hour on the hour. - - Remove this graph. - Remove this dissection behavior. - Удалить этот график. - Add a new graph. Добавить новый график. - - Duplicate this graph. - Дублировать этот график. - Clear all graphs. Очистить все графики. - Move this graph upwards. - Переместить этот график вверх. + Remove the selected graph(s). + Удалить выбранный график(ы). - Move this graph downwards. - Переместить этот график вниз. + Duplicate the selected graph(s). + Дублирование выбранного графика (графиков). + + + Move the selected graph(s) upwards. + Переместите выбранный график(ы) вверх. + + + Move the selected graph(s) downwards. + Переместите выбранный график(ы) вниз. Mouse @@ -3870,15 +4142,11 @@ For example, use 1 hour to have a new file created every hour on the hour. Automatic update - + Автоматическое обновление Enable legend - - - - Reset - Сброс + Включить легенду Reset Graph @@ -4093,6 +4361,42 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy graphs from another profile. Копировать графики из другого профиля. + + 1 μs + 1 мкс + + + 2 μs + 2 мкс + + + 5 μs + 5 мкс + + + 10 μs + 10 мкс + + + 20 μs + 20 мкс + + + 50 μs + 50 мкс + + + 100 μs + 100 мкс + + + 200 μs + 200 мкс + + + 500 μs + 500 мкс + 1 ms 1 мс @@ -4137,6 +4441,14 @@ For example, use 1 hour to have a new file created every hour on the hour.5 sec 5 сек + + 2 min + 2 минуты + + + 5 min + 5 минут + Wireshark I/O Graphs: %1 Графики ввода/вывода Wireshark: %1 @@ -4147,7 +4459,15 @@ For example, use 1 hour to have a new file created every hour on the hour. Filtered events - + Отфильтрованные события + + + All packets + Все пакеты + + + All events + Все события All Packets @@ -4159,11 +4479,11 @@ For example, use 1 hour to have a new file created every hour on the hour. All Events - + Все события - Access Denied - + All Execs + Все руководители Hover over the graph for details. @@ -4175,7 +4495,7 @@ For example, use 1 hour to have a new file created every hour on the hour. No events in interval - + Нет событий в интервале Click to select packet @@ -4187,11 +4507,11 @@ For example, use 1 hour to have a new file created every hour on the hour. Click to select event - + Нажмите, чтобы выбрать событие Event - Событие + Событие %1 (%2s%3). @@ -4209,6 +4529,34 @@ For example, use 1 hour to have a new file created every hour on the hour.Click to select a portion of the graph. Щёлкните для выбора участка графика. + + %1 Intervals + %1 Интервалы + + + Move to top left + Переместить в левый верхний угол + + + Move to top center + Переместить в верхний центр + + + Move to top right + Переместить в правый верхний угол + + + Move to bottom left + Переместить в левый нижний угол + + + Move to bottom center + Переместить в нижний центр + + + Move to bottom right + Перемещение в правый нижний угол + Portable Document Format (*.pdf) Portable Document Format (*.pdf) @@ -4961,6 +5309,13 @@ For example, use 1 hour to have a new file created every hour on the hour.Применить изменения + + InterfaceTreeDelegate + + default + по умолчанию + + InterfaceTreeModel @@ -5940,8 +6295,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteMacStatisticsDialog - LTE Mac Statistics - Статистика LTE Mac + LTE/NR Mac Statistics + Статистика LTE/NR Mac Include SR frames in filter @@ -5953,7 +6308,7 @@ For example, use 1 hour to have a new file created every hour on the hour. MAC Statistics - Статистика MAC + Статистика MAC @@ -6245,12 +6600,12 @@ For example, use 1 hour to have a new file created every hour on the hour.Номер последовательности - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) - График LTE RLC (UE=%1 канал=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) + %1 График RLC (UE=%2 канал=%3%4 %5 - %6) - LTE RLC Graph - no channel selected - График LTE RLC — канал не выбран + 3GPP RLC Graph - no channel selected + 3GPP RLC График - канал не выбран Save As… @@ -6304,8 +6659,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteRlcStatisticsDialog - LTE RLC Statistics - Статистика LTE RLC + 3GPP RLC Statistics + Статистика 3GPP RLC Include SR frames in filter @@ -6390,6 +6745,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Profile: %1 Профиль: %1 + + %1 Displayed: %2 (%3%) + %1 Отображено: %2 (%3%) + Manage Profiles… Управление профилями… @@ -6447,10 +6806,18 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln byte(s) , %1 bytes - - - - + + %Ln байт + %Ln байта + %Ln байтов + + + + %Ln bit(s) + + %Ln бит + %Ln бита + %Ln битов @@ -6466,9 +6833,12 @@ For example, use 1 hour to have a new file created every hour on the hour.Выбран пакет: %1 %2 - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 - Пакеты: %1 %4 Отображаются: %2 (%3%) + Selected Event: %1 %2 + Выбранное событие: %1 %2 + + + Events: %1 + События: %1 %1 Selected: %2 (%3%) @@ -6499,6 +6869,10 @@ For example, use 1 hour to have a new file created every hour on the hour.No Packets Пакеты отсутствуют + + No Events + Нет событий + From Zip File... Из zip-фйла… @@ -6532,6 +6906,13 @@ For example, use 1 hour to have a new file created every hour on the hour. + + MainWindow + + Display filter as %1 + Отображение фильтра как %1 + + MainWindowPreferencesFrame @@ -6563,6 +6944,10 @@ For example, use 1 hour to have a new file created every hour on the hour.The most recently used folder Последняя использованная папка + + The current working directory + Текущий рабочий каталог + Show up to Показывать до @@ -6707,62 +7092,62 @@ For example, use 1 hour to have a new file created every hour on the hour.ManufDialog MAC Address Blocks - + Блокировка MAC-адресов Search MAC address or address prefix. Special purpose bits are masked. - + Поиск MAC-адреса или префикса адреса. Биты специального назначения маскируются. MAC Address - + MAC-адрес Search vendor name using a case-insentitive regular expression. - + Поиск названия поставщика с помощью регулярного выражения, не зависящего от регистра. Vendor Name - + Название поставщика Show short name column. - + Показать колонку с короткими названиями. Short name - + Краткое название Select all - Выбрать все + Выбрать все Copy - Копировать + Копировать Find - Найти + Найти Clear - Очистить + Очистить ManufTableModel Address Block - + Адресный блокиратор Short Name - Короткое имя + Краткое название Vendor Name - + Название поставщика @@ -6993,6 +7378,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show Field Values Показать значения полей + + Refresh + Обновить + Save Diagram As… Сохранить диаграмму как… @@ -7040,6 +7429,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show packet bytes Показывать байты пакета + + Layout: + Макет: + Packet %1 Пакет %1 @@ -7058,10 +7451,18 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln byte(s) - - - - + + %Ln байт + %Ln байта + %Ln байтов + + + + %Ln bit(s) + + %Ln бит + %Ln бита + %Ln битов @@ -7234,7 +7635,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Sorting … - + Сортировка … @@ -7269,11 +7670,11 @@ For example, use 1 hour to have a new file created every hour on the hour. Include &depended upon packets - + Включать и зависеть от пакетов Also include packets depended upon, such as those used to reassemble displayed packets - + Включите также пакеты, от которых зависят, например, пакеты, используемые для повторной сборки отображаемых пакетов. First &to last marked @@ -7399,11 +7800,11 @@ For example, use 1 hour to have a new file created every hour on the hour. Checking this will show only changed preferences. - + Если установить этот флажок, будут показаны только измененные настройки. Show changed values - + Показать измененные значения Preferences @@ -7522,10 +7923,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy this profile. Копировать данный профиль. + + The number of packets or events to check for automatic profile switching. + Количество пакетов или событий, которые необходимо проверить для автоматического переключения профиля. + + + Auto switch packet limit + Ограничение пакетов автоматического переключения + Configuration Profiles Профили конфигурации + + Auto switch event limit + Предел события автоматического переключения + Import noun @@ -7546,10 +7959,10 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln Selected Personal Profile(s)... - - - - + + %Ln Выбранный персональный профиль... + %Ln Выбранный персональный профиля... + %Ln Выбранный персональный профилей... @@ -7576,6 +7989,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Select zip file for export Выбрать zip-файл для экспорта + + … %Ln selected personal profile(s) + + ... %Ln выбранный личный профиль + ... %Ln выбранных личных профиля + ... %Ln выбранных личных профилей + + + + %Ln selected personal profile(s) + + %Ln выбранный личный профиль + %Ln выбранных личных профиля + %Ln выбранных личных профилей + + An import of profiles is not allowed, while changes are pending Импорт профилей при наличии ожидающих сохранения изменений не допускается @@ -7594,10 +8023,10 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln profile(s) exported - - - - + + %Ln профиль экспортирован + %Ln профиля экспортировано + %Ln профилей экспортировано @@ -7626,18 +8055,18 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln profile(s) imported - - - - + + %Ln профиль импортирован + %Ln профиля импортировано + %Ln профилей импортировано , %Ln profile(s) skipped - - - - + + %Ln профиль пропущен + %Ln профиля пропущено + %Ln профилей пропущено @@ -7699,6 +8128,10 @@ For example, use 1 hour to have a new file created every hour on the hour.deleted удалённый + + Auto Switch Filter + Автоматический переключатель фильтра + copy noun @@ -7938,27 +8371,27 @@ For example, use 1 hour to have a new file created every hour on the hour. Copy short names - + Копирование коротких названий Copy short protocol names in use. - + Скопируйте используемые короткие названия протоколов. Disable unused protocols - + Отключите неиспользуемые протоколы Disable all protocols but those listed. - + Отключите все протоколы, кроме перечисленных. Re-enable unused protocols - + Повторное включение неиспользуемых протоколов Re-enable protocols that were disabled in this dialog. - + Повторное включение протоколов, которые были отключены в этом диалоговом окне. Protocol Hierarchy Statistics @@ -7978,19 +8411,19 @@ For example, use 1 hour to have a new file created every hour on the hour. protocol short names - + краткие названия протоколов Protocols - + Протоколы Disable unused - + Отключить неиспользуемые Revert changes - + Отмена изменений No display filter. @@ -8002,11 +8435,11 @@ For example, use 1 hour to have a new file created every hour on the hour. Unused protocols have been disabled. - + Неиспользуемые протоколы были отключены. Protocol changes have been reverted. - + Изменения протокола были отменены. @@ -8060,7 +8493,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Unacked (Outstanding) Bytes (B) - + Нераспакованные (выданные) байты (B) [no capture file] @@ -8222,6 +8655,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Marker missing? Отсутствует маркер? + + LTE + LTE + + + NR + NR + C-RNTI C-RNTI @@ -8242,6 +8683,10 @@ For example, use 1 hour to have a new file created every hour on the hour.UEId UEId + + RAT + КРЫСА + UL Frames Кадры UL @@ -8466,9 +8911,69 @@ For example, use 1 hour to have a new file created every hour on the hour.Browse… Обзор… + + PACKETS + ПАКЕТЫ + + + EVENTS + СОБЫТИЯ + + + BYTES + БАЙТЫ + + + BITS + БИТЫ + + + COUNT FRAMES + СЧЁТНЫЕ РАМКИ + + + COUNT FIELDS + СЧЕТНЫЕ ПОЛЯ + + + SUM + СУММА + + + MAX + МАКСИМАЛЬНО + + + MIN + МИНИМАЛЬНО + + + AVERAGE + СРЕДНИЙ + + + THROUGHPUT + ТРЕУГОЛЬНИК + + + LOAD + ЗАГРУЗКА + + + Left + Левый + + + Center + Центр + + + Right + Правый + - QObject::QObject + QObject::QObject::QObject CCCH CCCH @@ -8568,6 +9073,13 @@ For example, use 1 hour to have a new file created every hour on the hour.мс + + ResizeHeaderView + + Resize all %1 to contents + Изменить размер всех %1 по содержимому + + ResolvedAddressesDialog @@ -8683,6 +9195,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved Addresses Разрешённые адреса + + Copy + Копировать + + + Save as… + Сохранить как... + # Resolved addresses found in %1 # Разрешённые адреса найденные в %1 @@ -8696,6 +9216,61 @@ For example, use 1 hour to have a new file created every hour on the hour. + + ResolvedAddressesView + + as Plain Text + как обычный текст + + + Copy selected rows + Копирование выбранных строк + + + Copy table + Копирование таблицы + + + as CSV + как CSV + + + as JSON + как JSON + + + Save selected rows as… + Сохранить выбранные строки как... + + + Save table as… + Сохраните таблицу как... + + + Save Resolved Addresses As… + Сохранить решенные адреса как... + + + Plain text (*.txt) + Обычный текст (*.txt) + + + CSV Document (*.csv) + Документ CSV (*.csv) + + + JSON Document (*.json) + Документ JSON (*.json) + + + Warning + Внимание + + + Unable to save %1: %2 + Невозможно сохранить %1: %2 + + ResponseTimeDelayDialog @@ -10022,11 +10597,11 @@ For example, use 1 hour to have a new file created every hour on the hour. - - - + - <small><i>For complete analysis check SCTP preference Enable Association indexing</i></small> - + <small>Для полного анализа проверьте предпочтение SCTP Включить индексирование ассоциаций<i></small> Complete List of IP addresses from INIT Chunk: @@ -10370,6 +10945,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Packet bytes Байты пакета + + <b>Options:</b> + <b>Опции:</b> + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>Поиск строк, содержащих символы в обычной (UTF-8 и ASCII) или многобайтовой (UTF-16) кодировке.</p></body></html> @@ -10390,6 +10969,18 @@ For example, use 1 hour to have a new file created every hour on the hour.Case sensitive Чувствительность к регистру + + Backwards + Назад + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + <html><head/><body><p>Поиск последующего вхождения в текущем пакете перед переходом к следующему пакету.</p></body></html> + + + Multiple occurrences + Множественные случаи + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10427,6 +11018,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Invalid filter. Недопустимый фильтр. + + Event List + Список событий + + + Event Details + Подробности события + + + Event Bytes + Байты событий + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + <html><head/><body><p>Поиск в колонке "Информация" списка событий (панель сводки), в декодированных метках отображения событий (панель древовидного представления) или в преобразованных в ASCII данных события (панель шестнадцатеричного представления).</p></body></html> + That filter doesn't test anything. Этот фильтр не производит тестирование. @@ -10492,18 +11099,18 @@ For example, use 1 hour to have a new file created every hour on the hour. %Ln node(s) - - %Ln node - %Ln nodes - + + %Ln узел + %Ln узла + %Ln узлов %Ln item(s) - - %Ln item - %Ln items - + + %Ln элемент + %Ln элемента + %Ln элементов @@ -10872,16 +11479,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: Найти: + + Case sensitive + С учетом регистра + Find &Next Найти &следующий Frame %1, %2, %Ln byte(s). - - - - + + Кадр %1, %2, %Ln байт. + Кадров %1, %2, %Ln байт. + Кадров %1, %2, %Ln байт. @@ -10968,16 +11579,24 @@ For example, use 1 hour to have a new file created every hour on the hour.Save as… Сохранить как… + + Decoded as %1. + Расшифровано как %1. + Save Selected Packet Bytes As… Сохранение выбранных байтов пакета как… + + compressed %1 + сжато %1 + - Displaying %Ln byte(s). - - - - + Using %Ln byte(s). + + Использование %Ln байта. + Использование %Ln байта. + Использование %Ln байт. @@ -11049,7 +11668,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Applying changed preferences - + Применение измененных предпочтений (Unknown action) @@ -11077,6 +11696,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: Фильтр отображения: + + Strip Headers + Полосатые заголовки + SupportedProtocolsDialog @@ -11729,51 +12352,51 @@ For example, use 1 hour to have a new file created every hour on the hour.TLSKeylogDialog Dialog - + Диалог Browse… - Обзор… + Просмотреть... Command line - + Командная строка Run an application with the SSLKEYLOGFILE environment variable set to the file specified by the TLS key log filename preference. This enables TLS decryption in Wireshark. Set the key log file and start the capture before launching the application to ensure that the initial TLS handshakes are captured. - + Запустите приложение с переменной окружения SSLKEYLOGFILE, установленной на файл, указанный в параметре "Имя файла журнала ключей TLS". Это позволяет расшифровать TLS в Wireshark. Установите файл журнала ключей и запустите захват перед запуском приложения, чтобы обеспечить захват начальных рукопожатий TLS. <span style=" font-size:small;">Firefox and Chrome are known to work. If your desired browser is currently running, close it first before launching it below. Command line options are supported.</span> - + <span style=" font-size:small;">Известно, что Firefox и Chrome работают. Если нужный вам браузер запущен, закройте его, прежде чем запускать ниже. Поддерживаются параметры командной строки.</span> TLS (Pre)-Master-Secret log file path (tls.keylog_file) - + Путь к файлу журнала TLS (Предварительный) - Мастер-секрет (tls.keylog_file) <span style=" font-size:small;">TLS session secrets will be logged to this file. If you change this field, hit the Save button to update the TLS protocol preferences.</span> - + <span style=" font-size:small;">В этот файл будут записываться секреты сеанса TLS. Если вы измените это поле, нажмите кнопку Сохранить, чтобы обновить настройки протокола TLS.</span> Launch application with SSLKEYLOGFILE - + Запуск приложения с SSLKEYLOGFILE Launch - + Запуск Save - Сохранить + Сохранить TLS Keylog file - + Файл журнала ключей TLS Program to start with SSLKEYLOGFILE - + Программа для запуска с SSLKEYLOGFILE @@ -11893,7 +12516,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Time shifting is not available while capturing packets. - + Перемещение по времени при захвате пакетов недоступно. @@ -12050,22 +12673,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Создать новую запись. - Remove this entry. - Remove this profile. - Удалить эту запись. + Remove the selected entry(ies). + Удалить выбранную запись(и). - Copy this entry. - Copy this profile. - Копировать эту запись. + Copy the selected entry(ies). + Копирование выбранной записи (записей). - Move entry up. - Переместить запись выше. + Move the selected entry(ies) up. + Переместите выбранную запись(и) вверх. - Move entry down. - Переместить запись ниже. + Move the selected entry(ies) down. + Переместите выбранную запись(и) вниз. Clear all entries. @@ -12091,20 +12712,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Создать новую запись. - Remove this entry. - Удалить эту запись. + Remove the selected entry(ies). + Удалите выбранную запись(и). - Copy this entry. - Копировать эту запись. + Copy the selected entry(ies). + Копирование выбранной записи (записей). - Move entry up. - Переместить запись выше. + Move the selected entry(ies) up. + Переместите выбранную запись(и) вверх. - Move entry down. - Переместить запись ниже. + Move the selected entry(ies) down. + Переместите выбранную запись(и) вниз. Clear all entries. @@ -12465,20 +13086,28 @@ a:hover { %n interface(s) shown, %1 hidden - - %n interface shown, %1 hidden - %n interfaces shown, %1 hidden - + + %n интерфейсов показано, %1 скрыт + %n интерфейсов показано, %1 скрыто + %n интерфейсов показано, %1 скрыто You are sniffing the glue that holds the Internet together using Wireshark Все составные звенья Интернета анализировать поможет Wireshark + + You are sniffing the glue that holds your system together using Logray + Вы нюхаете клей, который держит вашу систему вместе, используя Logray. + You are running Wireshark Работа производится в Wireshark + + You are running Logray + Вы используете Logray + You receive automatic updates. Обновления выполняются автоматически. @@ -12755,14 +13384,6 @@ a:hover { No files found Файлы не найдены - - &Contents - &Содержание - - - Wireshark Filter - Фильтр Wireshark - TShark TShark @@ -13028,10 +13649,6 @@ a:hover { Wireless Toolbar Панель инструментов беспроводного соединения - - Help contents - Содержание справки - FAQs Вопросы и ответы @@ -13152,11 +13769,6 @@ a:hover { Find the previous packet Найти предыдущий пакет - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - &Установить/снять отметку пакета (пакетов) - Mark All Displayed Отметить всё отображаемое @@ -13185,11 +13797,6 @@ a:hover { Go to the previous marked packet Перейти к предыдущему отмеченному пакету - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - &Игнорировать/отменить игнорирование пакета - Ignore All Displayed Игнорировать всё отображаемое @@ -13630,33 +14237,29 @@ a:hover { Reset Layout Сбросить разметку - - Reset appearance layout to default size - Сбросить внешний вид разметки к размеру по умолчанию - Seconds Since First Captured Packet Количество секунд с момента захвата первого пакета Show packet times as the seconds since the first captured packet. - + Показывает время прохождения пакетов в секундах с момента первого захваченного пакета. Tenths of a millisecond - + Десятые доли миллисекунды Hundredths of a millisecond - + Сотые доли миллисекунды Tenths of a microsecond - + Десятые доли микросекунды Hundredths of a microsecond - + Сотые доли микросекунды Packet &Diagram @@ -13792,24 +14395,32 @@ a:hover { MAC Address Blocks - - - - TLS Keylog Launcher - - - - Release Notes - + Блокировка MAC-адресов &Options… &Опции… + + &3GPP Uu + &3GPP Uu + &Wireless &Беспроводная связь + + &User's Guide + &Руководство пользователя + + + Wireshark User's Guide + Руководство пользователя Wireshark + + + Display Filters + Фильтры дисплея + Capture &Filters… Фильтры &захвата… @@ -13854,10 +14465,18 @@ a:hover { Find Pre&vious Найти пр&едыдущий + + &Mark/Unmark Selected + &Маркировать/немаркировать выбранное + Mark or unmark each selected packet Установить или снять отметку всех выбранных пакетов + + &Ignore/Unignore Selected + &Игнорировать/Неигнорировать выбранное + Ignore or unignore each selected packet Игнорировать или отменить игнорирование всех выбранных пакетов @@ -13876,19 +14495,19 @@ a:hover { Inject TLS Secrets - + Инъекция секретов TLS Embed used TLS secrets in the capture file - + Встраивание используемых секретов TLS в файл захвата Discard All Secrets - + Выбросить все секреты Discard all decryption secrets in the capture file - + Отбросьте все секреты расшифровки в файле захвата &Preferences… @@ -13898,6 +14517,18 @@ a:hover { TCP throughput Пропускная способность TCP + + General + Общий + + + Query-Response + Запрос-ответ + + + DNS Query-Response Statistics + Статистика DNS-запросов-ответов + Request Sequences Последовательности запросов @@ -13906,6 +14537,14 @@ a:hover { HTTP Request Sequences Последовательности HTTP-запросов + + E2AP + E2AP + + + E2AP Messages + Сообщения E2AP + Decode &As… Декодировать &как… @@ -13966,6 +14605,10 @@ a:hover { Normal Size Обычный размер + + Reset layout to default size + Сброс макета до размера по умолчанию + Resize Columns Изменить размер столбцов @@ -14224,6 +14867,14 @@ a:hover { Go to the packet referenced by the selected field. Перейти к пакету по ссылке из выбранного поля. + + TLS Keylog Launcher + Запускатель TLS Keylog + + + Release Notes + Примечания к выпуску + &VoIP Calls Вызовы &VoIP @@ -14256,10 +14907,6 @@ a:hover { &GSM &GSM - - &LTE - &LTE - &MTP3 &MTP3 @@ -14544,6 +15191,10 @@ a:hover { Quit without Saving Выйти &без сохранения + + USB CDC Data + Данные USB CDC + There is no "rtp.ssrc" field in this version of Wireshark. В этой версии Wireshark отсутствует поле «rtp.ssrc». @@ -14606,6 +15257,15 @@ a:hover { No Keys Отсутствуют ключи + + Export SSL Session Keys (%Ln key(s)) + Export SSL Session Keys (%1 key%2 + + Экспорт ключей сеансов SSL (%Ln ключа) + Экспорт ключей сеансов SSL (%Ln ключа) + Экспорт ключей сеансов SSL (%Ln ключей) + + Raw data (*.bin *.dat *.raw);;All Files ( Необработанные данные (*.bin *.dat *.raw);;Все Файлы ( @@ -14675,10 +15335,10 @@ a:hover { Delete comments from %n packet(s) - - - - + + Удалить комментарии из %n пакета(ов) + Удалить комментарии из %n пакета(ов) + Удалить комментарии из %n пакета(ов) @@ -14695,7 +15355,7 @@ a:hover { before updating - + перед обновлением There are no TLS Session Keys to save. @@ -14703,10 +15363,10 @@ a:hover { Export TLS Session Keys (%Ln key(s)) - - - - + + Экспорт ключей сеанса TLS (%Ln ключ) + Экспорт ключей сеанса TLS (%Ln ключа) + Экспорт ключей сеанса TLS (%Ln ключей) @@ -14715,15 +15375,15 @@ a:hover { No TLS Secrets - + Нет секретов TLS There are no available secrets used to decrypt TLS traffic in the capture file. Would you like to view information about how to decrypt TLS traffic on the wiki? - + В файле захвата нет доступных секретов, используемых для расшифровки трафика TLS. Вы хотите просмотреть информацию о расшифровке трафика TLS в вики? Are you sure you want to discard all decryption secrets? - + Вы уверены, что хотите выбросить все секреты расшифровки? No filter available. Try another %1. diff --git a/ui/qt/wireshark_sv.ts b/ui/qt/wireshark_sv.ts index 5db51c97..a12781ae 100644 --- a/ui/qt/wireshark_sv.ts +++ b/ui/qt/wireshark_sv.ts @@ -44,8 +44,8 @@ Mappar - Filter by path - Filtrera efter sökväg + Search Folders + Plugins @@ -79,6 +79,14 @@ License Licens + + About Logray + + + + Logray + + The directory does not exist Katalogen finns inte @@ -754,6 +762,28 @@ … som EBCDIC + + CaptureCommentDialog + + Edit Capture Comments + + + + Add Comment + + + + Section %1 + Avsnitt %1 + + + + CaptureCommentTabWidget + + Comment %1 + + + CaptureFile @@ -839,10 +869,6 @@ Read filter: Läsfilter: - - Compress with g&zip - Komprimera med g&zip - Open Capture File Wireshark: Open Capture File @@ -925,8 +951,8 @@ Detaljer - Capture file comments - Fångstfilkommentarer + Edit Comments + Refresh @@ -936,10 +962,6 @@ Copy To Clipboard Kopiera till urklipp - - Save Comments - Spara kommentarer - Capture File Properties Fångstfilegenskaper @@ -988,10 +1010,18 @@ First packet Första paket + + First event + + Last packet Sista paket + + Last event + + Elapsed Förflutet @@ -1028,6 +1058,10 @@ Dropped packets Släppta paket + + Dropped events + + Capture filter Fångstfilter @@ -1040,6 +1074,10 @@ Packet size limit (snaplen) Storleksgräns på paket (snaplen) + + Event size limit (snaplen) + + none ingen @@ -1048,6 +1086,26 @@ %1 bytes %1 byte + + Comments + Kommentarer + + + Comment %1: + + + + Decryption Secrets + + + + Type + Typ + + + Size + Storlek + Statistics Statistik @@ -1072,6 +1130,10 @@ Packets Paket + + Events + Händelser + Time span, s Tidsintervall, s @@ -1084,6 +1146,10 @@ Average packet size, B Genomsnittlig paketstorlek, B + + Average event size, B + + Bytes Byte @@ -1096,14 +1162,14 @@ Average bits/s Genomsnittligt bitar/s - - Section Comment - Avsnittskommentar - Packet Comments Paketkommentarer + + Event Comments + + <p>Frame %1: <p>Ram %1: @@ -1116,6 +1182,12 @@ + + Created by Logray %1 + + + + CaptureFilterCombo @@ -1342,6 +1414,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Byt till nästa fil när (väggklocks)tiden är en jämn multipel av det angivna intervallet Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid hel timma. + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + + + + Enable monitor mode on all 802.11 interfaces + + compression komprimering @@ -1354,6 +1434,30 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he gzip gzip + + File infix pattern + + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + + + + YYYYmmDDHHMMSS_NNNNN + + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + + + + NNNNN_YYYYmmDDHHMMSS + + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> <html><head/><body><p>Efter att infångandet har bytt till nästa fil och det angivna antalet filer har överskridits tas den äldsta filen bort.</p></body></html> @@ -1507,8 +1611,8 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Fel - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. - Flera filer: den begärda filstorleken är för stor. Filstorleken får inte vara större än 2 GiB. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. + Multiple files: No capture file name given. You must specify a filename if you want to use multiple files. @@ -1537,6 +1641,14 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Capture packets in promiscuous mode Fånga paket i promiskuöst läge + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + + + + Capture packets in monitor mode on 802.11 devices + + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>Fånga paket i nästa generations format för fångstfiler.</p></body></html> @@ -1764,6 +1876,14 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Resolved Uppslagen + + Width + + + + Alignment + + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> <html>Visa mänskligt läsbara strängar istället för råa värden för fält. Endast tillämpligt på anpassade kolumner med fält som har värdesträngar.</html> @@ -1811,6 +1931,25 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Kopiera filtertext till urklipp. + + CompressionGroupBox + + Compression options + + + + &Uncompressed + + + + Compress with g&zip + + + + Compress with &LZ4 + + + ConversationDataModel @@ -1851,7 +1990,7 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Packets B - + Paket B Bytes B @@ -1877,6 +2016,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Bits/s B Bitar/s B + + Flows + + Total Packets Totalt antal paket @@ -1992,40 +2135,64 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Kopiera paketbyte som en hex-dump. - …as Printable Text + …as MIME Data - Copy only the printable text in the packet. + …as C String - …as MIME Data + Copy packet bytes as printable ASCII characters and escape sequences. - …as C String + …as Go literal - Copy packet bytes as printable ASCII characters and escape sequences. + Copy packet bytes as Go literal. + + + + …as C Array + + + + Copy packet bytes as C Array. …as a Hex Stream … som en hex-ström + + …as UTF-8 Text + + + + Copy packet bytes as text, treating as UTF-8. + + + + …as ASCII Text + + + + Copy packet bytes as text, treating as ASCII. + + Copy packet bytes as a stream of hex. Kopiera paketbyte som en ström av hex. …as a Base64 String - + … som en Base64-sträng Copy packet bytes as a base64 encoded string. - + Kopiera paketbyte som en Base64-kodad sträng. Copy packet bytes as application/octet-stream MIME data. @@ -2177,7 +2344,7 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Invalid filter: - Felaktigt filter: + Felaktigt filter: Save this filter @@ -2329,7 +2496,7 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Dissector Description - + Dissekeringsbeskrivning Integer @@ -2474,11 +2641,11 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Latitude - + Latitud Longitude - + Longitud AS Number @@ -2811,6 +2978,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Display filter: Visningsfilter: + + Export PDUs + + ExtArgSelector @@ -2849,10 +3020,6 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Start Starta - - Save - Spara - Default Standard @@ -2994,6 +3161,14 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Display Filters Visningsfilter + + Display Filter Macros + + + + New macro + + Open Öppna @@ -3077,10 +3252,18 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he FilterListModel + + Macro Name + + Filter Name Filternamn + + Macro Expression + + Filter Expression Filteruttryck @@ -3166,22 +3349,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he FolderListModel - - "File" dialogs - ”Arkiv”-dialoger - - - capture files - fångstfiler - Temp Temp - - untitled capture files - namnlösa fångstfiler - Personal configuration Personlig konfiguration @@ -3190,14 +3361,6 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Global configuration Global konfiguration - - dfilters, preferences, ethers, … - dfilter, inställningar, ether:ar, … - - - dfilters, preferences, manuf, … - dfilter, inställningar, manuf, … - System System @@ -3210,18 +3373,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Program Program - - program files - programfiler - Personal Plugins Personliga insticksmoduler - - binary plugins - binära insticksmoduler - Global Plugins Globala insticksmoduler @@ -3236,6 +3391,30 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Lua scripts + Lua-skript + + + "File" dialog location + + + + Capture files + + + + Untitled capture files + + + + Preferences, profiles, manuf, … + + + + Program files + + + + Binary plugins @@ -3243,7 +3422,7 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Personlig extcap-sökväg - external capture (extcap) plugins + External capture (extcap) plugins @@ -3366,6 +3545,24 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he %Ln vändningar. + + Event %1. + + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + + + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + + + + Click to select. Klicka för att välja. @@ -3396,6 +3593,18 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he %1 stream not found on the selected packet. + %1-strömmar fanns inte i det valda paketet. + + + Read activity(%6) + + + + Write activity(%6) + + + + Entire I/O activity (%1) @@ -3414,10 +3623,6 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Save Stream Content As… Spara ströminnehållet som … - - [Stream output truncated] - [Strömutdatan avhuggen] - %Ln total stream(s). @@ -3427,9 +3632,9 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Max sub stream ID for the selected stream: %Ln - - - + + Maximalt underströms-ID för den valda strömmen: %Ln + Maximalt underströms-ID för den valda strömmen: %Ln @@ -3445,9 +3650,20 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Tips. - Show data as - Show and save data as - Visa data som + Show as + Visa som + + + No delta times + + + + Turn delta times + + + + All delta times + Stream @@ -3461,11 +3677,22 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Find: Sök: + + Case sensitive + Skiftlägeskänsligt + Find &Next Sök &nästa + + FollowStreamText + + [Stream output truncated] + + + FontColorPreferencesFrame @@ -3801,29 +4028,28 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he </tbody></table> </body></html> - - Remove this graph. - Remove this dissection behavior. - Ta bort denna graf. - Add a new graph. Lägg till en ny graf. - - Duplicate this graph. - Dubblera denna graf. - Clear all graphs. Nollställ alla grafer. - Move this graph upwards. + Remove the selected graph(s). - Move this graph downwards. + Duplicate the selected graph(s). + + + + Move the selected graph(s) upwards. + + + + Move the selected graph(s) downwards. @@ -3866,10 +4092,6 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Enable legend - - Reset - Återställ - Reset Graph Återställ grafen @@ -4083,6 +4305,42 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Copy graphs from another profile. Kopiera grafer från en annan profil. + + 1 μs + + + + 2 μs + + + + 5 μs + + + + 10 μs + + + + 20 μs + + + + 50 μs + + + + 100 μs + + + + 200 μs + + + + 500 μs + + 1 ms 1 ms @@ -4127,6 +4385,14 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he 5 sec 5 s + + 2 min + 10 min {2 ?} + + + 5 min + 10 min {5 ?} + Wireshark I/O Graphs: %1 Wireshark I/O-grafer: %1 @@ -4139,6 +4405,14 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Filtered events + + All packets + + + + All events + + All Packets Alla paket @@ -4152,7 +4426,7 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he - Access Denied + All Execs @@ -4199,6 +4473,34 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Click to select a portion of the graph. Klicka för att välja en del av grafen. + + %1 Intervals + + + + Move to top left + + + + Move to top center + + + + Move to top right + + + + Move to bottom left + + + + Move to bottom center + + + + Move to bottom right + + Portable Document Format (*.pdf) Portable Document Format (*.pdf) @@ -4951,6 +5253,13 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Verkställ ändringar + + InterfaceTreeDelegate + + default + standard + + InterfaceTreeModel @@ -5902,11 +6211,11 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Maximum number of cached rows (affects sorting) - + Maximalt antal cachade rader (påverkar sortering) <html><head/><body><p>If more than this many rows are displayed, then sorting by columns that require packet dissection will be disabled. Increasing this number increases memory consumption by caching column values.</p></body></html> - + <html><head/><body><p>Om mer än så här många rader visas kommer sortering enligt kolumner som kräver paketdissekering att avaktiveras. Att öka detta tal ökar minnesförbrukningen genom att kolumnvärden cachas.</p></body></html> Enable mouse-over colorization @@ -5928,8 +6237,8 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he LteMacStatisticsDialog - LTE Mac Statistics - LTE Mac-statistik + LTE/NR Mac Statistics + Include SR frames in filter @@ -6233,12 +6542,12 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Sekvensnummer - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) - LTE RLC-graf (UE=%1 kan=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) + - LTE RLC Graph - no channel selected - LTE RLC-graf – ingen kanal vald + 3GPP RLC Graph - no channel selected + Save As… @@ -6292,8 +6601,8 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he LteRlcStatisticsDialog - LTE RLC Statistics - LTE RLC-statistik + 3GPP RLC Statistics + Include SR frames in filter @@ -6378,6 +6687,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Profile: %1 Profil: %1 + + %1 Displayed: %2 (%3%) + + Manage Profiles… Hantera profiler … @@ -6440,6 +6753,13 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he %Ln byte + + %Ln bit(s) + + + + + Byte %1 Byte %1 @@ -6453,9 +6773,12 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Välj paket: %1 %2 - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 - Paket: %1 %4 Visat: %2 (%3 %) + Selected Event: %1 %2 + + + + Events: %1 + %1 Selected: %2 (%3%) @@ -6487,20 +6810,24 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Inga paket - From Zip File... + No Events + + From Zip File... + Från en zip-fil … + From Directory... - + Från en katalog … Selected Personal Profile... - + Vald personlig profil … All Personal Profiles... - + Alla personliga profiler … Packets: %1 @@ -6518,6 +6845,13 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he + + MainWindow + + Display filter as %1 + + + MainWindowPreferencesFrame @@ -6549,6 +6883,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he The most recently used folder Den senast använda mappen + + The current working directory + + Show up to Visa upp till @@ -6979,6 +7317,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Show Field Values Visa fältvärden + + Refresh + Uppdatera + Save Diagram As… Spara diagrammet som … @@ -7026,6 +7368,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Show packet bytes Visa paketbyte + + Layout: + + Packet %1 Paket %1 @@ -7049,6 +7395,13 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he %Ln byte + + %Ln bit(s) + + + + + PacketFormatGroupBox @@ -7207,11 +7560,11 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he PacketListModel Column - + Kolumn %1 can only be sorted with %2 or fewer visible rows; increase cache size in Layout preferences - + %1 kan bara sorteras med %2 eller färre synliga rader; öka cachestorleken i inställningarna av layout Sorting "%1"… @@ -7219,7 +7572,7 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Sorting … - + Sortering … @@ -7507,10 +7860,22 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Copy this profile. Kopiera denna profil. + + The number of packets or events to check for automatic profile switching. + + + + Auto switch packet limit + + Configuration Profiles Konfigurationsprofiler + + Auto switch event limit + + Import noun @@ -7523,22 +7888,22 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he From Zip File... - + Från en zip-fil … From Directory... - + Från en katalog … %Ln Selected Personal Profile(s)... - - - + + %Ln vald personlig profil … + %Ln valda personliga profiler … All Personal Profiles... - + Alla personliga profiler … New profile @@ -7679,6 +8044,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he deleted borttagen + + Auto Switch Filter + + copy noun @@ -8202,6 +8571,14 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Marker missing? Saknad markör? + + LTE + + + + NR + + C-RNTI C-RNTI @@ -8222,6 +8599,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he UEId UEId + + RAT + + UL Frames UL-ramar @@ -8403,55 +8784,115 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Filteruttrycket %1 är inte ett giltigt visningsfilter. (%2). - Error - Fel + Error + Fel + + + No remote interfaces found. + Inga fjärrgränssnitt hittades + + + PCAP not found + PCAP finns inte + + + Unknown error + Okänt fel + + + Default + Standard + + + Changed + Ändrad + + + Has this preference been changed? + Har denna inställning ändrats? + + + Default value is empty + Standardvärdet är tomt + + + Gap in dissection + Gap i dissektionen + + + Edit… + Redigera … + + + Browse… + Bläddra… + + + PACKETS + + + + EVENTS + + + + BYTES + + + + BITS + + + + COUNT FRAMES + - No remote interfaces found. - Inga fjärrgränssnitt hittades + COUNT FIELDS + - PCAP not found - PCAP finns inte + SUM + - Unknown error - Okänt fel + MAX + - Default - Standard + MIN + - Changed - Ändrad + AVERAGE + - Has this preference been changed? - Har denna inställning ändrats? + THROUGHPUT + - Default value is empty - Standardvärdet är tomt + LOAD + - Gap in dissection - Gap i dissektionen + Left + Vänster - Edit… - Redigera … + Center + - Browse… - Bläddra… + Right + Höger - QObject::QObject + QObject::QObject::QObject CCCH - CCCH + CCCH @@ -8548,6 +8989,13 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he millisekund + + ResizeHeaderView + + Resize all %1 to contents + + + ResolvedAddressesDialog @@ -8663,6 +9111,14 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Resolved Addresses Uppslagna adresser + + Copy + Kopiera + + + Save as… + Spara som … + # Resolved addresses found in %1 # Uppslagna adresser hittade i %1 @@ -8676,6 +9132,61 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he # + + ResolvedAddressesView + + as Plain Text + + + + Copy selected rows + + + + Copy table + + + + as CSV + som CSV + + + as JSON + som JSON + + + Save selected rows as… + + + + Save table as… + + + + Save Resolved Addresses As… + + + + Plain text (*.txt) + Vanlig text (*.txt) + + + CSV Document (*.csv) + + + + JSON Document (*.json) + + + + Warning + Varning + + + Unable to save %1: %2 + + + ResponseTimeDelayDialog @@ -10350,6 +10861,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Packet bytes Paketbyte + + <b>Options:</b> + + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>Sök efter strängar som innehåller smala (UTF-8 och ASCII) eller breda (UTF-16) tecken.</p></body></html> @@ -10370,6 +10885,18 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Case sensitive Skiftlägeskänsligt + + Backwards + + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + + + + Multiple occurrences + + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10407,6 +10934,22 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Invalid filter. Felaktigt filter. + + Event List + + + + Event Details + + + + Event Bytes + + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + + That filter doesn't test anything. Det filtret testar inte någonting. @@ -10850,6 +11393,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Find: Sök: + + Case sensitive + Skiftlägeskänsligt + Find &Next Sök &nästa @@ -10879,7 +11426,7 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Percent-Encoding - + Procentkodning Quoted-Printable @@ -10945,15 +11492,23 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Save as… Spara som … + + Decoded as %1. + + Save Selected Packet Bytes As… Spara valda paketbyte som … + + compressed %1 + + - Displaying %Ln byte(s). - - Visar %Ln byte. - Visar %Ln byte. + Using %Ln byte(s). + + + @@ -11053,6 +11608,10 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Display filter: Visningsfilter: + + Strip Headers + + SupportedProtocolsDialog @@ -11104,7 +11663,7 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he SyntaxLineEdit Invalid filter: %1 - + Felaktigt filter: %1 "%1" is deprecated in favour of "%2". See Help section 6.4.8 for details. @@ -11741,7 +12300,7 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Save - Spara + TLS Keylog file @@ -12026,22 +12585,20 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Skapa en ny post. - Remove this entry. - Remove this profile. - Ta bort denna post. + Remove the selected entry(ies). + - Copy this entry. - Copy this profile. - Kopiera denna post. + Copy the selected entry(ies). + - Move entry up. - Flytta upp posten. + Move the selected entry(ies) up. + - Move entry down. - Flytta ned posten. + Move the selected entry(ies) down. + Clear all entries. @@ -12067,20 +12624,20 @@ Till exempel, använd 1 timma för att en ny fil skall skapas varje timma vid he Skapa en ny post. - Remove this entry. - Ta bort denna post. + Remove the selected entry(ies). + - Copy this entry. - Kopiera denna post. + Copy the selected entry(ies). + - Move entry up. - Flytta upp posten. + Move the selected entry(ies) up. + - Move entry down. - Flytta ned posten. + Move the selected entry(ies) down. + Clear all entries. @@ -12379,7 +12936,49 @@ a:hover { </tr></table> </body></html> - + <html><head> +<style> +a:link { + color: palette(text); + text-decoration: none; +} +a:hover { + color: palette(text); + text-decoration: underline; +} +</style> +</head> +<body> + +<table><tr> +<th><a href="https://www.wireshark.org/docs/wsug_html_chunked/">Användarguide</a></th> + +<td style="padding-left: 8px; padding-right: 8px;">·</td> + +<th><a href="https://gitlab.com/wireshark/wireshark/-/wikis/">Wiki</a></th> + +<td style="padding-left: 8px; padding-right: 8px;">·</td> + +<th><a href="https://ask.wireshark.org/">Frågor och svar</a></th> + +<td style="padding-left: 8px; padding-right: 8px;">·</td> + +<th><a href="https://www.wireshark.org/lists/">Sändlistor</a></th> + +<td style="padding-left: 8px; padding-right: 8px;">·</td> + +<th><a href="https://sharkfest.wireshark.org/">SharkFest</a></th> + +<td style="padding-left: 8px; padding-right: 8px;">·</td> + +<th><a href="https://discord.com/invite/ts9GZCjGj5">Wireshark Discord</a></th> + +<td style="padding-left: 8px; padding-right: 8px;">·</td> + +<th><a href="https://wiresharkfoundation.org/donate/">Donate</a></th> + +</tr></table> +</body></html> Show in Finder @@ -12408,10 +13007,18 @@ a:hover { You are sniffing the glue that holds the Internet together using Wireshark Du luktar på limmet som håller samman Internet med Wireshark + + You are sniffing the glue that holds your system together using Logray + + You are running Wireshark Du kör Wireshark + + You are running Logray + + You receive automatic updates. Du får automatiska uppdateringar. @@ -12688,14 +13295,6 @@ a:hover { No files found Inga filer hittades - - &Contents - &Innehåll - - - Wireshark Filter - Wireshark-filter - TShark TShark @@ -12946,7 +13545,7 @@ a:hover { &DTN - + &DTN Osmux @@ -12961,10 +13560,6 @@ a:hover { Wireless Toolbar Verktygsrad för trådlöst - - Help contents - Hjälpinnehåll - FAQs Frågor och svar @@ -13085,11 +13680,6 @@ a:hover { Find the previous packet Sök efter föregående paket - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - &Markera/avmarkera paket - Mark All Displayed Markera alla visade @@ -13118,11 +13708,6 @@ a:hover { Go to the previous marked packet Gå till föregående märkta paket - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - &Ignorera/avignorera paket - Ignore All Displayed Ignorera alla visade @@ -13413,11 +13998,11 @@ a:hover { &LTP - + &LTP LTP segment and block statistics - + LTP-segment- och blockstatistik &ISUP Messages @@ -13563,10 +14148,6 @@ a:hover { Reset Layout Återställ layouten - - Reset appearance layout to default size - Återställ utseendelayouten till sin standardstorlek - Seconds Since First Captured Packet Sekunder sedan första fångade paket @@ -13728,20 +14309,28 @@ a:hover { - TLS Keylog Launcher + &Options… + &Alternativ … + + + &3GPP Uu - Release Notes + &Wireless + &Trådlöst + + + &User's Guide - &Options… - &Alternativ … + Wireshark User's Guide + - &Wireless - &Trådlöst + Display Filters + Visningsfilter Capture &Filters… @@ -13787,10 +14376,18 @@ a:hover { Find Pre&vious Sök f&öregående + + &Mark/Unmark Selected + + Mark or unmark each selected packet Markera eller avmarkera varje valt paket + + &Ignore/Unignore Selected + + Ignore or unignore each selected packet Ignorera eller avignorera varje valt paket @@ -13831,6 +14428,18 @@ a:hover { TCP throughput TCP-genomströmning + + General + + + + Query-Response + + + + DNS Query-Response Statistics + + Request Sequences Begärandesekvenser @@ -13839,6 +14448,14 @@ a:hover { HTTP Request Sequences HTTP-begärandesekvenser + + E2AP + + + + E2AP Messages + + Decode &As… Avkoda &som … @@ -13899,6 +14516,10 @@ a:hover { Normal Size Normal storlek + + Reset layout to default size + + Resize Columns Ändra storlek på kolumner @@ -14157,6 +14778,14 @@ a:hover { Go to the packet referenced by the selected field. Gå till paketet refererat av det valda fältet. + + TLS Keylog Launcher + + + + Release Notes + + &VoIP Calls &VoIP-anrop @@ -14189,10 +14818,6 @@ a:hover { &GSM &GSM - - &LTE - &LTE - &MTP3 &MTP3 @@ -14477,6 +15102,10 @@ a:hover { Quit without Saving Avsluta &utan att spara + + USB CDC Data + + There is no "rtp.ssrc" field in this version of Wireshark. Det finns inget "rtp.ssrc"-fält i denna version av Wireshark. diff --git a/ui/qt/wireshark_tr_TR.ts b/ui/qt/wireshark_tr_TR.ts index b96f5510..85e0e3aa 100644 --- a/ui/qt/wireshark_tr_TR.ts +++ b/ui/qt/wireshark_tr_TR.ts @@ -44,8 +44,8 @@ Klasörler - Filter by path - Yola göre filtrele + Search Folders + Plugins @@ -79,6 +79,14 @@ License Lisans + + About Logray + Logray Hakkında + + + Logray + Logray + The directory does not exist Dizin mevcut değil @@ -730,11 +738,11 @@ …as decimal - + …ondalık sayı olarak …as octal - + …sekizli olarak …as bits @@ -753,6 +761,28 @@ …EBCDIC olarak + + CaptureCommentDialog + + Edit Capture Comments + Yakalama Yorumlarını Düzenle + + + Add Comment + Yorum Ekle + + + Section %1 + Bölüm %1 + + + + CaptureCommentTabWidget + + Comment %1 + Yorum %1 + + CaptureFile @@ -838,10 +868,6 @@ Read filter: Filtreyi oku: - - Compress with g&zip - G&zip ile sıkıştır - Open Capture File Wireshark: Open Capture File @@ -921,8 +947,8 @@ Detaylar - Capture file comments - Dosya yorumlarını yakala + Edit Comments + Yorumları Düzenle Refresh @@ -932,10 +958,6 @@ Copy To Clipboard Panoya Kopyala - - Save Comments - Yorumları Kaydet - Capture File Properties Yakalama Dosyası Özellikleri @@ -984,10 +1006,18 @@ First packet İlk paket + + First event + + Last packet Son paket + + Last event + + Elapsed Geçen @@ -1024,6 +1054,10 @@ Dropped packets Bırakılan paketler + + Dropped events + + Capture filter Yakalama filtresi @@ -1036,6 +1070,10 @@ Packet size limit (snaplen) Paket boyutu sınırı (snaplen) + + Event size limit (snaplen) + + none yok @@ -1044,6 +1082,26 @@ %1 bytes %1 bayt + + Comments + Yorumlar + + + Comment %1: + Yorum %1: + + + Decryption Secrets + Şifre Çözme Sırları + + + Type + Tür + + + Size + Boyut + Statistics İstatistikler @@ -1068,6 +1126,10 @@ Packets Paketler + + Events + Etkinlikler + Time span, s Zaman aralığı, s @@ -1080,6 +1142,10 @@ Average packet size, B Ortalama paket boyutu, B + + Average event size, B + + Bytes Bayt @@ -1092,14 +1158,14 @@ Average bits/s Ortalama bit/sn - - Section Comment - Bölüm Yorumu - Packet Comments Paket Yorumları + + Event Comments + + <p>Frame %1: <p>Çerçeve %1: @@ -1110,6 +1176,14 @@ Wireshark tarafından oluşturuldu %1 + + + + Created by Logray %1 + + + Logray %1 tarafından oluşturuldu + @@ -1338,6 +1412,14 @@ For example, use 1 hour to have a new file created every hour on the hour.(duvar saati) süresi belirtilen aralığın çift katı olduğunda sonraki dosyaya geçin. Örneğin, her saat başı yeni bir dosyanın oluşturulması için 1 saat kullanın. + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + </html><head/></body></p>Genellikle bir kablosuz ağ kartı, yalnızca kendi ağ adresine gönderilen ve ondan gelen trafiği yakalar ve yalnızca "sahte" Ethernet başlıklarıyla <em>kullanıcı verisi</em> trafiğini yakalar. Kablosuz ağ kartlarının "görebildiği" tüm trafiği yakalamak istiyorsanız veya 802.11 yönetim veya kontrol paketleri veya radyo katmanı bilgileriyle ilgileniyorsanız, bu seçeneği işaretleyin. Monitor modu, kablosuz kart ve sürücüye bağlıdır. WLAN ağlarında paket yakalama hakkında daha fazla ayrıntı için Wiki'ye bakın.</p></body></html> + + + Enable monitor mode on all 802.11 interfaces + Tüm 802.11 arayüzlerinde monitör modunu etkinleştirin + compression sıkıştırma @@ -1350,6 +1432,30 @@ For example, use 1 hour to have a new file created every hour on the hour.gzip gzip + + File infix pattern + Dosya ek deseni + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + <html><head/><body><p>Çoklu dosya modunda, tarih ve saat ile dosya dizin numarası, dosya adı şablonu ve herhangi bir ek arasına yerleştirilir. Sıralamayı seçin.</p></body></html> + + + YYYYmmDDHHMMSS_NNNNN + + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + <html><head/><body><p>Tarih ve saat, dosya dizin numarasından önce gelir. Bu, dosyaların oluşturma zamanına göre sıralanmasına ve aynı grup dosyaların yakın bir şekilde sıralanmasına neden olur.</p></body></html> + + + NNNNN_YYYYmmDDHHMMSS + + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + <html><head/><body><p>Dosya dizin numarası tarih ve saat öncesinde. Bu, tarihsel Wireshark sıralamasıdır.</p></body></html> + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> <html><head/><body><p>Yakalama bir sonraki dosyaya geçtikten ve verilen dosya sayısı aşıldıktan sonra, en eski dosya kaldırılacaktır.</p></body></html> @@ -1503,8 +1609,8 @@ For example, use 1 hour to have a new file created every hour on the hour.Hata - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. - Birden çok dosya: İstenen dosya boyutu çok büyük. Dosya boyutu 2 GiB'den büyük olamaz. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. + Multiple files: No capture file name given. You must specify a filename if you want to use multiple files. @@ -1533,6 +1639,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Capture packets in promiscuous mode Paketleri karışık modda yakalayın + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + <html><head/><body><p>Genellikle bir kablosuz ağ kartı, yalnızca kendi ağ adresine gönderilen ve ondan gelen trafiği yakalar ve yalnızca "sahte" Ethernet başlıklarıyla <em>kullanıcı verisi</em> trafiğini yakalar. Kablosuz ağ kartlarının "görebildiği" tüm trafiği yakalamak istiyorsanız veya 802.11 yönetim veya kontrol paketleri veya radyo katmanı bilgileriyle ilgileniyorsanız, bu seçeneği işaretleyin. Monitor modu, kablosuz kart ve sürücüye bağlıdır. WLAN ağlarında paket yakalama hakkında daha fazla ayrıntı için Wiki'ye bakın.</p></body></html> + + + Capture packets in monitor mode on 802.11 devices + 802.11 cihazlarda monitör modunda paketleri yakalayın. + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>Paketleri yeni nesil yakalama dosyası biçiminde yakalayın.</p></body></html> @@ -1551,15 +1665,15 @@ For example, use 1 hour to have a new file created every hour on the hour. Interval between updates (ms) - + Güncellemeler arasındaki süre (ms) <html><head/><body><p>How often the capture notifies the GUI of new packets. Affects how often the GUI updates and the granularity of timers.</p></body></html> - + <html><head/><body><p>Yakalamanın Arayüz`e yeni paketler hakkında ne sıklıkta bildirimde bulunduğu. Arayüz`ün ne sıklıkta güncellendiğini ve zamanlayıcıların ayrıntı düzeyini etkiler.</p></body></html> <html><head/><body><p>The interval between new packet updates. Affects how often the GUI updates and the granularity of timers.</p></body></html> - + <html><head/><body><p>Yeni paket güncellemeleri arasındaki süre. Arayüz'ün ne sıklıkla güncellendiğini ve zamanlayıcıların ayrıntısını etkiler.</p></body></html> Don't load interfaces on startup @@ -1760,6 +1874,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved Çözüldü + + Width + Genişlik + + + Alignment + Hizalama + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> <html>Alanlar için ham değerler yerine insan tarafından okunabilir dizeleri gösterin. Yalnızca değer dizeleri olan alanlara sahip özel sütunlar için geçerlidir.</html> @@ -1807,6 +1929,25 @@ For example, use 1 hour to have a new file created every hour on the hour.Filtre metnini panoya kopyalayın. + + CompressionGroupBox + + Compression options + + + + &Uncompressed + + + + Compress with g&zip + + + + Compress with &LZ4 + + + ConversationDataModel @@ -1873,6 +2014,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Bits/s B Bit/s B + + Flows + + Total Packets Toplam Paket @@ -1988,28 +2133,52 @@ For example, use 1 hour to have a new file created every hour on the hour.Paket baytlarını hex dökümü olarak kopyalayın. - …as Printable Text + …as MIME Data + …MIME Verisi + + + …as C String + …C Dizesi olarak + + + Copy packet bytes as printable ASCII characters and escape sequences. + Paket baytlarını yazdırılabilir ASCII karakterleri ve kaçış dizilerini kopyala. + + + …as Go literal + …Go literali olarak + + + Copy packet bytes as Go literal. + Paket baytlarını Go literali olarak kopyala. + + + …as C Array - Copy only the printable text in the packet. + Copy packet bytes as C Array. - …as MIME Data + …as a Hex Stream + …Hex Akışı olarak + + + …as UTF-8 Text - …as C String + Copy packet bytes as text, treating as UTF-8. - Copy packet bytes as printable ASCII characters and escape sequences. + …as ASCII Text - …as a Hex Stream - …Hex Akışı olarak + Copy packet bytes as text, treating as ASCII. + Copy packet bytes as a stream of hex. @@ -2291,11 +2460,11 @@ For example, use 1 hour to have a new file created every hour on the hour.DissectorSyntaxLineEdit Dissector entry - + Dissektör girişi Enter a dissector %1 - + Bir dissector %1 girin. @@ -2807,6 +2976,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: Ekran filtresi: + + Export PDUs + + ExtArgSelector @@ -2845,10 +3018,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Start Başla - - Save - Kaydet - Default Ön tanımlı @@ -2989,6 +3158,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Display Filters Ekran Filtreleri + + Display Filter Macros + Filtre Makrolarını Görüntüle + + + New macro + Yeni makro + Open @@ -3072,10 +3249,18 @@ For example, use 1 hour to have a new file created every hour on the hour. FilterListModel + + Macro Name + Macro Adı + Filter Name Filtre Adı + + Macro Expression + Makro İfade + Filter Expression Filtre İfadesi @@ -3161,22 +3346,10 @@ For example, use 1 hour to have a new file created every hour on the hour. FolderListModel - - "File" dialogs - "Dosya" diyalogları - - - capture files - yakalama dosyaları - Temp Geçici - - untitled capture files - başlıksız yakalama dosyaları - Personal configuration Kişisel yapılandırma @@ -3185,14 +3358,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Global configuration Genel yapılandırma - - dfilters, preferences, ethers, … - filtreler, tercihler, eterler, … - - - dfilters, preferences, manuf, … - filtreler, tercihler, üretici, … - System Sistem @@ -3205,18 +3370,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Program Uygulama - - program files - program dosyaları - Personal Plugins Kişisel Eklentiler - - binary plugins - ikili eklentiler - Global Plugins Genel Eklentiler @@ -3233,13 +3390,37 @@ For example, use 1 hour to have a new file created every hour on the hour.Lua scripts Lua betikleri + + "File" dialog location + + + + Capture files + + + + Untitled capture files + + + + Preferences, profiles, manuf, … + + + + Program files + + + + Binary plugins + + Personal Extcap path Kişisel Excap yolu - external capture (extcap) plugins - harici yakalama (extcap) eklentileri + External capture (extcap) plugins + Global Extcap path @@ -3286,7 +3467,7 @@ For example, use 1 hour to have a new file created every hour on the hour.FollowStreamAction %1 Stream - + %1 Akış @@ -3358,6 +3539,22 @@ For example, use 1 hour to have a new file created every hour on the hour. + + Event %1. + Etkinlik %1. + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + + + Click to select. Seçmek için tıkla. @@ -3390,6 +3587,18 @@ For example, use 1 hour to have a new file created every hour on the hour.%1 stream not found on the selected packet. Seçili pakette %1 akışı bulunamadı. + + Read activity(%6) + Etkinliği oku(%6) + + + Write activity(%6) + Etkinlik yaz (%6) + + + Entire I/O activity (%1) + Tüm G/Ç etkinliği (%1) + Entire conversation (%1) Tüm konuşma (%1) @@ -3406,10 +3615,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Save Stream Content As… Akış İçeriğini Farklı Kaydet… - - [Stream output truncated] - [Akış çıkışı kesildi] - %Ln total stream(s). @@ -3435,9 +3640,20 @@ For example, use 1 hour to have a new file created every hour on the hour.İpucu. - Show data as - Show and save data as - Verileri şu şekilde göster + Show as + Olarak göster + + + No delta times + Delta zamanları yok + + + Turn delta times + Delta zamanlarını çevirin + + + All delta times + Tüm delta süreleri Stream @@ -3451,11 +3667,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: Bul: + + Case sensitive + Büyük küçük harf duyarlı + Find &Next Sonrakini &Bul + + FollowStreamText + + [Stream output truncated] + [Akış çıkışı kesildi] + + FontColorPreferencesFrame @@ -3678,23 +3905,23 @@ For example, use 1 hour to have a new file created every hour on the hour.IOConsoleDialog Dialog - + İletişim Enter code - + Kod girin Evaluate - + Değerlendir Clear - Temiz + Temizle Use %1 to evaluate. - + %1 'i değerlendirmek için kullanın. @@ -3791,30 +4018,29 @@ For example, use 1 hour to have a new file created every hour on the hour. - - Remove this graph. - Remove this dissection behavior. - Bu grafiği kaldırın. - Add a new graph. Yeni bir grafik ekleyin. - - Duplicate this graph. - Bu grafiği çoğaltın. - Clear all graphs. Tüm grafikleri temizle. - Move this graph upwards. - Bu grafiği yukarı doğru götür. + Remove the selected graph(s). + - Move this graph downwards. - Bu grafiği aşağı doğru götür. + Duplicate the selected graph(s). + + + + Move the selected graph(s) upwards. + + + + Move the selected graph(s) downwards. + Mouse @@ -3856,10 +4082,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Enable legend - - Reset - Sıfırla - Reset Graph Grafiği Sıfırla @@ -4073,6 +4295,42 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy graphs from another profile. Grafikleri başka bir profilden kopyalayın. + + 1 μs + + + + 2 μs + + + + 5 μs + + + + 10 μs + + + + 20 μs + + + + 50 μs + + + + 100 μs + + + + 200 μs + + + + 500 μs + + 1 ms 1 ms @@ -4117,6 +4375,14 @@ For example, use 1 hour to have a new file created every hour on the hour.5 sec 5 san + + 2 min + 10 dakika {2 ?} + + + 5 min + 10 dakika {5 ?} + Wireshark I/O Graphs: %1 Wireshark G/Ç Grafikleri: %1 @@ -4129,6 +4395,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Filtered events + + All packets + + + + All events + + All Packets Tüm Paketler @@ -4142,7 +4416,7 @@ For example, use 1 hour to have a new file created every hour on the hour. - Access Denied + All Execs @@ -4189,6 +4463,34 @@ For example, use 1 hour to have a new file created every hour on the hour.Click to select a portion of the graph. Grafiğin bir bölümünü seçmek için tıklayın. + + %1 Intervals + + + + Move to top left + + + + Move to top center + + + + Move to top right + + + + Move to bottom left + + + + Move to bottom center + + + + Move to bottom right + + Portable Document Format (*.pdf) Taşınabilir Belge Formatı (*.pdf) @@ -4941,6 +5243,13 @@ For example, use 1 hour to have a new file created every hour on the hour.Değişiklikleri uygula + + InterfaceTreeDelegate + + default + öntanımlı + + InterfaceTreeModel @@ -5916,8 +6225,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteMacStatisticsDialog - LTE Mac Statistics - LTE Mac İstatistikleri + LTE/NR Mac Statistics + Include SR frames in filter @@ -6221,12 +6530,12 @@ For example, use 1 hour to have a new file created every hour on the hour.Sıra Numarası - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) - LTE RLC Grafiği (UE=%1 chan=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) + - LTE RLC Graph - no channel selected - LTE RLC Grafiği - kanal seçilmedi + 3GPP RLC Graph - no channel selected + Save As… @@ -6280,8 +6589,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteRlcStatisticsDialog - LTE RLC Statistics - LTE RLC İstatistikleri + 3GPP RLC Statistics + Include SR frames in filter @@ -6366,6 +6675,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Profile: %1 Profil: %1 + + %1 Displayed: %2 (%3%) + + Manage Profiles… Profilleri Yönet… @@ -6427,6 +6740,12 @@ For example, use 1 hour to have a new file created every hour on the hour. + + %Ln bit(s) + + + + Byte %1 Bayt %1 @@ -6440,9 +6759,12 @@ For example, use 1 hour to have a new file created every hour on the hour.Seçilen Paket: %1 %2 - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 - Paketler: %1 %4 Görüntülenen: %2 (%3%) + Selected Event: %1 %2 + + + + Events: %1 + %1 Selected: %2 (%3%) @@ -6473,6 +6795,10 @@ For example, use 1 hour to have a new file created every hour on the hour.No Packets Paket Yok + + No Events + + From Zip File... Zip Dosyasından... @@ -6504,6 +6830,13 @@ For example, use 1 hour to have a new file created every hour on the hour. + + MainWindow + + Display filter as %1 + + + MainWindowPreferencesFrame @@ -6535,6 +6868,10 @@ For example, use 1 hour to have a new file created every hour on the hour.The most recently used folder En son kullanılan klasör + + The current working directory + + Show up to Kadar göster @@ -6719,7 +7056,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Clear - Temiz + @@ -6965,6 +7302,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show Field Values Alan Değerlerini Göster + + Refresh + Yenile + Save Diagram As… Şemayı Farklı Kaydet… @@ -7012,6 +7353,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show packet bytes Paket baytlarını göster + + Layout: + + Packet %1 Paket %1 @@ -7034,6 +7379,12 @@ For example, use 1 hour to have a new file created every hour on the hour. + + %Ln bit(s) + + + + PacketFormatGroupBox @@ -7204,7 +7555,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Sorting … - + Sıralanıyor ... @@ -7492,10 +7843,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy this profile. Bu profili kopyalayın. + + The number of packets or events to check for automatic profile switching. + + + + Auto switch packet limit + + Configuration Profiles Yapılandırma Profilleri + + Auto switch event limit + + Import noun @@ -7659,6 +8022,10 @@ For example, use 1 hour to have a new file created every hour on the hour.deleted silindi + + Auto Switch Filter + + copy noun @@ -8182,6 +8549,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Marker missing? İşaretçi eksik mi? + + LTE + + + + NR + + C-RNTI C-RNTI @@ -8202,6 +8577,10 @@ For example, use 1 hour to have a new file created every hour on the hour.UEId UEId + + RAT + + UL Frames YÜ Çerçeveler @@ -8426,12 +8805,72 @@ For example, use 1 hour to have a new file created every hour on the hour.Browse… Gözat… + + PACKETS + + + + EVENTS + + + + BYTES + + + + BITS + + + + COUNT FRAMES + + + + COUNT FIELDS + + + + SUM + + + + MAX + + + + MIN + + + + AVERAGE + + + + THROUGHPUT + + + + LOAD + + + + Left + Sol + + + Center + + + + Right + Sağa + - QObject::QObject + QObject::QObject::QObject CCCH - CCCH + CCCH @@ -8528,6 +8967,13 @@ For example, use 1 hour to have a new file created every hour on the hour.milisaniye + + ResizeHeaderView + + Resize all %1 to contents + + + ResolvedAddressesDialog @@ -8643,6 +9089,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved Addresses Çözümlenen Adresler + + Copy + Kopyala + + + Save as… + + # Resolved addresses found in %1 # Çözülmüş adresler %1'de bulundu @@ -8656,6 +9110,61 @@ For example, use 1 hour to have a new file created every hour on the hour. + + ResolvedAddressesView + + as Plain Text + + + + Copy selected rows + + + + Copy table + + + + as CSV + CSV olarak + + + as JSON + JSON olarak + + + Save selected rows as… + + + + Save table as… + + + + Save Resolved Addresses As… + + + + Plain text (*.txt) + Düz metin (*.txt) + + + CSV Document (*.csv) + + + + JSON Document (*.json) + + + + Warning + Uyarı + + + Unable to save %1: %2 + + + ResponseTimeDelayDialog @@ -10330,6 +10839,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Packet bytes Paket bayt + + <b>Options:</b> + + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>Dar (UTF-8 ve ASCII) veya geniş (UTF-16) karakterler içeren dizeleri arayın.</p></body></html> @@ -10350,6 +10863,18 @@ For example, use 1 hour to have a new file created every hour on the hour.Case sensitive Büyük küçük harf duyarlı + + Backwards + + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + + + + Multiple occurrences + + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10387,6 +10912,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Invalid filter. Geçersiz filtre. + + Event List + + + + Event Details + + + + Event Bytes + + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + + That filter doesn't test anything. O filtre hiçbir şeyi test etmez. @@ -10828,6 +11369,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: Bul: + + Case sensitive + Büyük küçük harf duyarlı + Find &Next Sonrakini &Bul @@ -10922,12 +11467,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Save as… Farklı kaydet… + + Decoded as %1. + + Save Selected Packet Bytes As… Seçili Paket Baytlarını Farklı Kaydet… + + compressed %1 + + - Displaying %Ln byte(s). + Using %Ln byte(s). @@ -11029,6 +11582,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: Görüntüleme filtresi: + + Strip Headers + + SupportedProtocolsDialog @@ -11717,7 +12274,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Save - Kaydet + TLS Keylog file @@ -12002,22 +12559,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Yeni bir giriş oluşturun. - Remove this entry. - Remove this profile. - Bu girişi kaldırın. + Remove the selected entry(ies). + - Copy this entry. - Copy this profile. - Bu girişi kopyalayın. + Copy the selected entry(ies). + - Move entry up. - Girişi yukarı taşı. + Move the selected entry(ies) up. + - Move entry down. - Girişi aşağı taşı. + Move the selected entry(ies) down. + Clear all entries. @@ -12043,20 +12598,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Yeni bir giriş oluşturun. - Remove this entry. - Bu girişi kaldırın. + Remove the selected entry(ies). + - Copy this entry. - Bu girişi kopyalayın. + Copy the selected entry(ies). + - Move entry up. - Girişi yukarı taşı. + Move the selected entry(ies) up. + - Move entry down. - Girişi aşağı taşı. + Move the selected entry(ies) down. + Clear all entries. @@ -12425,10 +12980,18 @@ a:üzerine gelin{ You are sniffing the glue that holds the Internet together using Wireshark Wireshark kullanarak interneti bir arada tutan yapıştırıcıyı kokluyorsunuz + + You are sniffing the glue that holds your system together using Logray + + You are running Wireshark Wireshark'ı çalıştırıyorsunuz + + You are running Logray + + You receive automatic updates. Otomatik güncelleme alıyorsunuz. @@ -12705,14 +13268,6 @@ a:üzerine gelin{ No files found Dosya bulunamadı - - &Contents - &İçerik - - - Wireshark Filter - Wireshark Filtresi - TShark TShark @@ -12978,10 +13533,6 @@ a:üzerine gelin{ Wireless Toolbar Kablosuz Araç Çubuğu - - Help contents - Yardım içeriği - FAQs SSS @@ -13102,11 +13653,6 @@ a:üzerine gelin{ Find the previous packet Önceki paketi bul - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - &Paketi İşaretle/İşaretini Kaldır - Mark All Displayed Tüm Görüntülenenleri İşaretle @@ -13135,11 +13681,6 @@ a:üzerine gelin{ Go to the previous marked packet Önceki işaretli pakete git - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - &Paketi Yoksay/Yoksaymaktan vazgeç - Ignore All Displayed Tüm Görüntülenenleri Yoksay @@ -13580,10 +14121,6 @@ a:üzerine gelin{ Reset Layout Düzeni Sıfırla - - Reset appearance layout to default size - Görünüm düzenini varsayılan boyuta sıfırla - Seconds Since First Captured Packet İlk Yakalanan Paketten Beri Saniye @@ -13745,20 +14282,28 @@ a:üzerine gelin{ - TLS Keylog Launcher + &Options… + &Seçenekler… + + + &3GPP Uu - Release Notes + &Wireless + &Kablosuz + + + &User's Guide - &Options… - &Seçenekler… + Wireshark User's Guide + - &Wireless - &Kablosuz + Display Filters + Ekran Filtreleri Capture &Filters… @@ -13804,10 +14349,18 @@ a:üzerine gelin{ Find Pre&vious Öncekini Bu&l + + &Mark/Unmark Selected + + Mark or unmark each selected packet Seçilen her paketi işaretleyin veya işaretini kaldırın + + &Ignore/Unignore Selected + + Ignore or unignore each selected packet Seçilen her paketi yoksay veya yoksay @@ -13848,6 +14401,18 @@ a:üzerine gelin{ TCP throughput TCP verimi + + General + + + + Query-Response + + + + DNS Query-Response Statistics + + Request Sequences İstek Dizileri @@ -13856,6 +14421,14 @@ a:üzerine gelin{ HTTP Request Sequences HTTP İstek Dizileri + + E2AP + + + + E2AP Messages + + Decode &As… Kodu &Çöz… @@ -13916,6 +14489,10 @@ a:üzerine gelin{ Normal Size Normal Boyut + + Reset layout to default size + + Resize Columns Sütunları Yeniden Boyutlandır @@ -14174,6 +14751,14 @@ a:üzerine gelin{ Go to the packet referenced by the selected field. Seçili alan tarafından başvurulan pakete gidin. + + TLS Keylog Launcher + + + + Release Notes + + &VoIP Calls &VoIP Aramaları @@ -14206,10 +14791,6 @@ a:üzerine gelin{ &GSM &GSM - - &LTE - &LTE - &MTP3 &MTP3 @@ -14494,6 +15075,10 @@ a:üzerine gelin{ Quit without Saving Kaydetmeden &çık + + USB CDC Data + + There is no "rtp.ssrc" field in this version of Wireshark. Wireshark'ın bu sürümünde "rtp.ssrc" alanı yoktur. diff --git a/ui/qt/wireshark_uk.ts b/ui/qt/wireshark_uk.ts index 75040b35..f95322a1 100644 --- a/ui/qt/wireshark_uk.ts +++ b/ui/qt/wireshark_uk.ts @@ -29,7 +29,7 @@ Copy to Clipboard - + Скопіювати до буферу обміну Authors @@ -44,8 +44,8 @@ Каталоги - Filter by path - Фільтр за шляхом + Search Folders + Plugins @@ -79,6 +79,14 @@ License Ліцензія + + About Logray + Про Logray + + + Logray + Logray + The directory does not exist Директорія не існує @@ -137,14 +145,14 @@ Can't assign %1 to %2. - + Неможливо призначити %1 до %2. AdvancedPrefsModel Name - + Ім'я Status @@ -170,7 +178,7 @@ AuthorListModel Name - + Ім'я Email @@ -225,15 +233,15 @@ Mark/Unmark Row - + Позначити/Зняти позначку з рядка Ctrl-M - + Ctrl-M Mark/Unmark Cell - + Позначити/зняти позначку з клітинки Save Table Image @@ -248,171 +256,171 @@ BluetoothDeviceDialog Bluetooth Device - + Пристрій Bluetooth BD_ADDR - BD_ADDR + BD_ADDR OUI - УІО (OUI) + OUI Name - + Ім'я Class of Device - + Клас пристрою LMP Version - Версія LMP + Версія LMP LMP Subversion - Підверсія LMP + Підверсія LMP Manufacturer - Виробник + Виробник HCI Version - Версія HCI + Версія HCI HCI Revision - Ревізія HCI + Ревізія HCI Scan - + Сканувати Authentication - + Аутентифікація Encryption - + Шифрування ACL MTU - + ACL MTU ACL Total Packets - + Всього пакетів ACL SCO MTU - + SCO MTU SCO Total Packets - + Всього пакетів SCO LE ACL MTU - + LE ACL MTU LE ACL Total Packets - + Всього пакетів LE ACL LE ISO MTU - + LE ISO MTU LE ISO Total Packets - + Всього пакетів LE ISO Inquiry Mode - + Режим запитів Page Timeout - + Таймаут сторінки Simple Pairing Mode - + Простий режим парування Voice Setting - + Налаштування голосу Value - Значення + Значення Changes - + Зміни %1 changes - + %1 зміни Copy Cell - Скопіювати Клітинку + Копіювати клітинку Copy Rows - Скопіювати Рядки + Копіювати рядки Copy All - Скопіювати Все + Копіювати все Save as image - Зберегти як зображення + Зберегти як зображення Mark/Unmark Row - + Позначити/Зняти позначку з рядка Ctrl+M - + Ctrl+M Mark/Unmark Cell - + Позначити/зняти позначку з клітинки Unknown - Невідомо + Невідомий Bluetooth Device - %1%2 - + Пристрій Bluetooth - %1%2 enabled - + ввімкнено disabled - + вимкнено %1 ms (%2 slots) - + %1 мс (%2 слоти) Save Table Image - Зберегти Зображення Таблиці + Зберегти зображення таблиці PNG Image (*.png) - Зображення PNG (*.png) + Зображення PNG (*.png) @@ -463,11 +471,11 @@ Show information steps - + Показати кроки інформації %1 items; Right click for more option; Double click for device details - + %1 елементів; Клацніть правою кнопкою миші для отримання додаткових опцій; Подвійний клік для отримання деталей пристрою Copy Cell @@ -487,19 +495,19 @@ Mark/Unmark Row - + Позначити/Зняти позначку з рядка Ctrl-M - + Ctrl-M Mark/Unmark Cell - + Позначити/зняти позначку з клітинки true - + істина Save Table Image @@ -538,7 +546,7 @@ Subevent - + Підподія Status @@ -554,7 +562,7 @@ Occurrence - + Випадок Link Control Commands @@ -646,11 +654,11 @@ Results filter: - + Фільтр результатів: Display filter: - Фільтр відображення: + Фільтр відображення: All Interfaces @@ -678,19 +686,19 @@ Mark/Unmark Row - + Позначити/Зняти позначку з рядка Ctrl+M - + Ctrl+M Mark/Unmark Cell - + Позначити/зняти позначку з клітинки Unknown - Невідомо + Adapter %1 @@ -755,6 +763,28 @@ + + CaptureCommentDialog + + Edit Capture Comments + + + + Add Comment + + + + Section %1 + + + + + CaptureCommentTabWidget + + Comment %1 + + + CaptureFile @@ -840,10 +870,6 @@ Read filter: - - Compress with g&zip - &Стиснути gzip'ом - Open Capture File Wireshark: Open Capture File @@ -929,8 +955,8 @@ Подробиці - Capture file comments - Коментарі файлу захоплення + Edit Comments + Refresh @@ -940,10 +966,6 @@ Copy To Clipboard Скопіювати До Буферу Обміну - - Save Comments - Зберегти Коментарі - Capture File Properties Властивості Файлу Захоплення @@ -992,10 +1014,18 @@ First packet Перший пакет + + First event + + Last packet Останній пакет + + Last event + + Elapsed Витрачено @@ -1032,6 +1062,10 @@ Dropped packets Відкинуті пакети + + Dropped events + + Capture filter Фільтр захоплення @@ -1044,6 +1078,10 @@ Packet size limit (snaplen) + + Event size limit (snaplen) + + none відсутній @@ -1052,6 +1090,26 @@ %1 bytes %1 байтів + + Comments + + + + Comment %1: + + + + Decryption Secrets + + + + Type + Тип + + + Size + + Statistics Статистика @@ -1076,6 +1134,10 @@ Packets Пакетів + + Events + Події + Time span, s Проміжок часу, с @@ -1088,6 +1150,10 @@ Average packet size, B Середній розмір пакету, Б + + Average event size, B + + Bytes Байтів @@ -1101,11 +1167,11 @@ біт/с (середнє значення) - Section Comment + Packet Comments - Packet Comments + Event Comments @@ -1120,6 +1186,12 @@ + + Created by Logray %1 + + + + CaptureFilterCombo @@ -1345,6 +1417,14 @@ For example, use 1 hour to have a new file created every hour on the hour. + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + + + + Enable monitor mode on all 802.11 interfaces + + compression @@ -1357,6 +1437,30 @@ For example, use 1 hour to have a new file created every hour on the hour.gzip + + File infix pattern + + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + + + + YYYYmmDDHHMMSS_NNNNN + + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + + + + NNNNN_YYYYmmDDHHMMSS + + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> @@ -1510,7 +1614,7 @@ For example, use 1 hour to have a new file created every hour on the hour.Помилка - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. @@ -1540,6 +1644,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Capture packets in promiscuous mode Захоплювати пакети в нерозбірливому режимі + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + + + + Capture packets in monitor mode on 802.11 devices + + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>Захоплювати пакети в форматі файлу захоплення наступного покоління.</p></body></html> @@ -1767,6 +1879,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved + + Width + + + + Alignment + + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> @@ -1814,6 +1934,25 @@ For example, use 1 hour to have a new file created every hour on the hour.Скопіювати текст фільтру до буферу обміну + + CompressionGroupBox + + Compression options + + + + &Uncompressed + + + + Compress with g&zip + + + + Compress with &LZ4 + + + ConversationDataModel @@ -1880,6 +2019,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Bits/s B + + Flows + + Total Packets @@ -1995,29 +2138,53 @@ For example, use 1 hour to have a new file created every hour on the hour. - …as Printable Text + …as MIME Data - Copy only the printable text in the packet. + …as C String - …as MIME Data + Copy packet bytes as printable ASCII characters and escape sequences. - …as C String + …as Go literal - Copy packet bytes as printable ASCII characters and escape sequences. + Copy packet bytes as Go literal. + + + + …as C Array + + + + Copy packet bytes as C Array. …as a Hex Stream + + …as UTF-8 Text + + + + Copy packet bytes as text, treating as UTF-8. + + + + …as ASCII Text + + + + Copy packet bytes as text, treating as ASCII. + + Copy packet bytes as a stream of hex. @@ -2812,6 +2979,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: Фільтр відображення: + + Export PDUs + + ExtArgSelector @@ -2850,10 +3021,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Start - - Save - - Default @@ -2996,6 +3163,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Display Filters + + Display Filter Macros + + + + New macro + + Open Відкрити @@ -3079,10 +3254,18 @@ For example, use 1 hour to have a new file created every hour on the hour. FilterListModel + + Macro Name + + Filter Name + + Macro Expression + + Filter Expression @@ -3169,75 +3352,71 @@ For example, use 1 hour to have a new file created every hour on the hour. FolderListModel - "File" dialogs + Temp - capture files + Personal configuration - Temp + Global configuration - untitled capture files + System - Personal configuration + ethers, ipxnets - Global configuration + Program - dfilters, preferences, ethers, … + Personal Plugins - dfilters, preferences, manuf, … + Global Plugins - System + Personal Lua Plugins - ethers, ipxnets + Global Lua Plugins - Program + Lua scripts - program files + "File" dialog location - Personal Plugins + Capture files - binary plugins + Untitled capture files - Global Plugins + Preferences, profiles, manuf, … - Personal Lua Plugins + Program files - Global Lua Plugins - - - - Lua scripts + Binary plugins @@ -3245,7 +3424,7 @@ For example, use 1 hour to have a new file created every hour on the hour. - external capture (extcap) plugins + External capture (extcap) plugins @@ -3371,6 +3550,26 @@ For example, use 1 hour to have a new file created every hour on the hour. + + Event %1. + + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + + + + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + + + + + Click to select. Клікніть для вибору. @@ -3403,6 +3602,18 @@ For example, use 1 hour to have a new file created every hour on the hour.%1 stream not found on the selected packet. + + Read activity(%6) + + + + Write activity(%6) + + + + Entire I/O activity (%1) + + Entire conversation (%1) @@ -3419,10 +3630,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Save Stream Content As… - - [Stream output truncated] - - %Ln total stream(s). @@ -3452,8 +3659,19 @@ For example, use 1 hour to have a new file created every hour on the hour.Підказка. - Show data as - Show and save data as + Show as + + + + No delta times + + + + Turn delta times + + + + All delta times @@ -3468,11 +3686,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: Знайти: + + Case sensitive + Враховувати регістр + Find &Next Знайти &Наступний + + FollowStreamText + + [Stream output truncated] + + + FontColorPreferencesFrame @@ -3779,29 +4008,28 @@ For example, use 1 hour to have a new file created every hour on the hour. - - Remove this graph. - Remove this dissection behavior. - Видалити цей графік. - Add a new graph. Додати новий графік. - Duplicate this graph. - Продублювати цей графік. + Clear all graphs. + - Clear all graphs. + Remove the selected graph(s). - Move this graph upwards. + Duplicate the selected graph(s). - Move this graph downwards. + Move the selected graph(s) upwards. + + + + Move the selected graph(s) downwards. @@ -3844,10 +4072,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Enable legend - - Reset - Скинути - Reset Graph Скинути Зміни До Діаграми @@ -4061,6 +4285,42 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy graphs from another profile. + + 1 μs + + + + 2 μs + + + + 5 μs + + + + 10 μs + + + + 20 μs + + + + 50 μs + + + + 100 μs + + + + 200 μs + + + + 500 μs + + 1 ms @@ -4105,6 +4365,14 @@ For example, use 1 hour to have a new file created every hour on the hour.5 sec 10 сек {5 ?} + + 2 min + 10 хв {2 ?} + + + 5 min + 10 хв {5 ?} + Wireshark I/O Graphs: %1 @@ -4117,6 +4385,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Filtered events + + All packets + + + + All events + + All Packets @@ -4130,7 +4406,7 @@ For example, use 1 hour to have a new file created every hour on the hour. - Access Denied + All Execs @@ -4177,6 +4453,34 @@ For example, use 1 hour to have a new file created every hour on the hour.Click to select a portion of the graph. Клікніть, щоб виділити частину графіку. + + %1 Intervals + + + + Move to top left + + + + Move to top center + + + + Move to top right + + + + Move to bottom left + + + + Move to bottom center + + + + Move to bottom right + + Portable Document Format (*.pdf) Формат Переносних Документів (*.pdf) @@ -4929,6 +5233,13 @@ For example, use 1 hour to have a new file created every hour on the hour.Застосувати зміни + + InterfaceTreeDelegate + + default + + + InterfaceTreeModel @@ -5908,7 +6219,7 @@ For example, use 1 hour to have a new file created every hour on the hour. LteMacStatisticsDialog - LTE Mac Statistics + LTE/NR Mac Statistics @@ -6188,11 +6499,11 @@ For example, use 1 hour to have a new file created every hour on the hour. - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) - LTE RLC Graph - no channel selected + 3GPP RLC Graph - no channel selected @@ -6247,7 +6558,7 @@ For example, use 1 hour to have a new file created every hour on the hour. LteRlcStatisticsDialog - LTE RLC Statistics + 3GPP RLC Statistics @@ -6333,6 +6644,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Profile: %1 + + %1 Displayed: %2 (%3%) + + Manage Profiles… @@ -6396,6 +6711,14 @@ For example, use 1 hour to have a new file created every hour on the hour. + + %Ln bit(s) + + + + + + Byte %1 @@ -6409,8 +6732,11 @@ For example, use 1 hour to have a new file created every hour on the hour. - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 + Selected Event: %1 %2 + + + + Events: %1 @@ -6442,6 +6768,10 @@ For example, use 1 hour to have a new file created every hour on the hour.No Packets Пакети відсутні + + No Events + + From Zip File... @@ -6475,6 +6805,13 @@ For example, use 1 hour to have a new file created every hour on the hour. + + MainWindow + + Display filter as %1 + + + MainWindowPreferencesFrame @@ -6503,7 +6840,11 @@ For example, use 1 hour to have a new file created every hour on the hour.Перегляд... - The most recently used folder + The most recently used folder + + + + The current working directory @@ -6936,6 +7277,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show Field Values + + Refresh + Оновити + Save Diagram As… @@ -6983,6 +7328,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show packet bytes + + Layout: + + Packet %1 @@ -7007,6 +7356,14 @@ For example, use 1 hour to have a new file created every hour on the hour. + + %Ln bit(s) + + + + + + PacketFormatGroupBox @@ -7463,10 +7820,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy this profile. Скопіювати цей профіль. + + The number of packets or events to check for automatic profile switching. + + + + Auto switch packet limit + + Configuration Profiles Профілі Конфігурації + + Auto switch event limit + + Import noun @@ -7640,6 +8009,10 @@ For example, use 1 hour to have a new file created every hour on the hour.deleted + + Auto Switch Filter + + copy noun @@ -8163,6 +8536,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Marker missing? + + LTE + + + + NR + + C-RNTI @@ -8183,6 +8564,10 @@ For example, use 1 hour to have a new file created every hour on the hour.UEId + + RAT + + UL Frames @@ -8329,7 +8714,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Unknown - Невідомо + UE Id @@ -8407,9 +8792,69 @@ For example, use 1 hour to have a new file created every hour on the hour.Browse… Перегляд... + + PACKETS + + + + EVENTS + + + + BYTES + + + + BITS + + + + COUNT FRAMES + + + + COUNT FIELDS + + + + SUM + + + + MAX + + + + MIN + + + + AVERAGE + + + + THROUGHPUT + + + + LOAD + + + + Left + Вліво + + + Center + + + + Right + Вправо + - QObject::QObject + QObject::QObject::QObject CCCH @@ -8431,7 +8876,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Authentication - + Аутентифікація Null authentication @@ -8509,6 +8954,13 @@ For example, use 1 hour to have a new file created every hour on the hour. + + ResizeHeaderView + + Resize all %1 to contents + + + ResolvedAddressesDialog @@ -8624,6 +9076,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved Addresses Визначені Адреси + + Copy + Скопіювати + + + Save as… + Зберегти як... + # Resolved addresses found in %1 @@ -8635,6 +9095,61 @@ For example, use 1 hour to have a new file created every hour on the hour. + + ResolvedAddressesView + + as Plain Text + + + + Copy selected rows + + + + Copy table + + + + as CSV + як CSV + + + as JSON + + + + Save selected rows as… + + + + Save table as… + + + + Save Resolved Addresses As… + + + + Plain text (*.txt) + Звичайний текст (*.txt) + + + CSV Document (*.csv) + + + + JSON Document (*.json) + + + + Warning + Попередження + + + Unable to save %1: %2 + + + ResponseTimeDelayDialog @@ -9576,7 +10091,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Unknown - Невідомо + @@ -10305,6 +10820,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Packet bytes Байти пакету + + <b>Options:</b> + + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>Шукати рядки, що містять звичайні (UTF-8 та ASCII) або розширені (UTF-16) символи.</p></body></html> @@ -10325,6 +10844,18 @@ For example, use 1 hour to have a new file created every hour on the hour.Case sensitive Враховувати регістр + + Backwards + + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + + + + Multiple occurrences + + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10362,6 +10893,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Invalid filter. Некоректний фільтр. + + Event List + + + + Event Details + + + + Event Bytes + + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + + That filter doesn't test anything. Цей фільтр нічого не перевіряє. @@ -10784,6 +11331,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: Знайти: + + Case sensitive + Враховувати регістр + Find &Next Знайти &Наступний @@ -10880,12 +11431,20 @@ For example, use 1 hour to have a new file created every hour on the hour.Save as… Зберегти як... + + Decoded as %1. + + Save Selected Packet Bytes As… + + compressed %1 + + - Displaying %Ln byte(s). + Using %Ln byte(s). @@ -10989,6 +11548,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: Фільтр відображення: + + Strip Headers + + SupportedProtocolsDialog @@ -11832,7 +12395,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Unknown - Невідомо + @@ -11923,21 +12486,19 @@ For example, use 1 hour to have a new file created every hour on the hour. - Remove this entry. - Remove this profile. + Remove the selected entry(ies). - Copy this entry. - Copy this profile. + Copy the selected entry(ies). - Move entry up. + Move the selected entry(ies) up. - Move entry down. + Move the selected entry(ies) down. @@ -11964,19 +12525,19 @@ For example, use 1 hour to have a new file created every hour on the hour. - Remove this entry. + Remove the selected entry(ies). - Copy this entry. + Copy the selected entry(ies). - Move entry up. + Move the selected entry(ies) up. - Move entry down. + Move the selected entry(ies) down. @@ -12306,10 +12867,18 @@ a:hover { You are sniffing the glue that holds the Internet together using Wireshark + + You are sniffing the glue that holds your system together using Logray + + You are running Wireshark + + You are running Logray + + You receive automatic updates. @@ -12586,14 +13155,6 @@ a:hover { No files found Не знайдено жодного файлу - - &Contents - &Зміст - - - Wireshark Filter - Фільтр Wireshark’а - TShark TShark @@ -12859,10 +13420,6 @@ a:hover { Wireless Toolbar Панель Бездротової Мережі - - Help contents - - FAQs @@ -12983,11 +13540,6 @@ a:hover { Find the previous packet Знайти попередній пакет - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - - Mark All Displayed Позначити Всі Відображені @@ -13016,11 +13568,6 @@ a:hover { Go to the previous marked packet Перейти до попереднього позначеного пакету - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - - Ignore All Displayed Прибрати Всі Відображені @@ -13461,10 +14008,6 @@ a:hover { Reset Layout - - Reset appearance layout to default size - - Seconds Since First Captured Packet @@ -13626,19 +14169,27 @@ a:hover { - TLS Keylog Launcher + &Options… + &Опції... + + + &3GPP Uu - Release Notes + &Wireless - &Options… - &Опції... + &User's Guide + - &Wireless + Wireshark User's Guide + + + + Display Filters @@ -13685,10 +14236,18 @@ a:hover { Find Pre&vious Знайти Поп&ередній + + &Mark/Unmark Selected + + Mark or unmark each selected packet + + &Ignore/Unignore Selected + + Ignore or unignore each selected packet @@ -13729,6 +14288,18 @@ a:hover { TCP throughput + + General + + + + Query-Response + + + + DNS Query-Response Statistics + + Request Sequences @@ -13737,6 +14308,14 @@ a:hover { HTTP Request Sequences + + E2AP + + + + E2AP Messages + + Decode &As… Декодувати &Як... @@ -13797,6 +14376,10 @@ a:hover { Normal Size Нормальний Розмір + + Reset layout to default size + + Resize Columns Змінити Розмір Колонок @@ -14055,6 +14638,14 @@ a:hover { Go to the packet referenced by the selected field. + + TLS Keylog Launcher + + + + Release Notes + + &VoIP Calls &Виклики VoIP @@ -14087,10 +14678,6 @@ a:hover { &GSM - - &LTE - - &MTP3 @@ -14375,6 +14962,10 @@ a:hover { Quit without Saving + + USB CDC Data + + There is no "rtp.ssrc" field in this version of Wireshark. diff --git a/ui/qt/wireshark_zh_CN.ts b/ui/qt/wireshark_zh_CN.ts index d57f2066..b2bf81cb 100644 --- a/ui/qt/wireshark_zh_CN.ts +++ b/ui/qt/wireshark_zh_CN.ts @@ -29,7 +29,7 @@ Copy to Clipboard - + 复制到剪贴板 Authors @@ -44,8 +44,8 @@ 文件夹 - Filter by path - 按路径过滤 + Search Folders + Plugins @@ -79,6 +79,14 @@ License 许可 + + About Logray + + + + Logray + + The directory does not exist 该目录不存在 @@ -270,7 +278,7 @@ LMP Subversion - LMP 子版本 + LMP 子版本 Manufacturer @@ -378,7 +386,7 @@ Ctrl+M - Ctrl+M + Ctrl+M Mark/Unmark Cell @@ -753,6 +761,28 @@ + + CaptureCommentDialog + + Edit Capture Comments + + + + Add Comment + + + + Section %1 + + + + + CaptureCommentTabWidget + + Comment %1 + + + CaptureFile @@ -838,10 +868,6 @@ Read filter: 读取过滤器: - - Compress with g&zip - 用 gzip 压缩(&Z) - Open Capture File Wireshark: Open Capture File @@ -921,8 +947,8 @@ 细节 - Capture file comments - 捕获文件描述 + Edit Comments + Refresh @@ -932,10 +958,6 @@ Copy To Clipboard 复制到剪贴板 - - Save Comments - 保存注释 - Capture File Properties 捕获文件属性 @@ -984,10 +1006,18 @@ First packet 第一个分组 + + First event + + Last packet 最后分组 + + Last event + + Elapsed 经过时间 @@ -1024,6 +1054,10 @@ Dropped packets 丢弃分组 + + Dropped events + + Capture filter 捕获过滤器 @@ -1036,6 +1070,10 @@ Packet size limit (snaplen) + + Event size limit (snaplen) + + none @@ -1044,6 +1082,26 @@ %1 bytes %1 字节 + + Comments + 注释 + + + Comment %1: + + + + Decryption Secrets + + + + Type + 类型 + + + Size + 大小 + Statistics 统计 @@ -1068,6 +1126,10 @@ Packets 分组 + + Events + 事件 + Time span, s 时间跨度,s @@ -1080,6 +1142,10 @@ Average packet size, B 平均分组大小,B + + Average event size, B + + Bytes 字节 @@ -1092,14 +1158,14 @@ Average bits/s 平均 比特/秒 - - Section Comment - - Packet Comments 分组注释 + + Event Comments + + <p>Frame %1: <p>帧 %1: @@ -1110,6 +1176,12 @@ 通过 Wireshark 创建 %1 + + Created by Logray %1 + + + + CaptureFilterCombo @@ -1336,6 +1408,14 @@ For example, use 1 hour to have a new file created every hour on the hour.当当前时间为指定时间的整数倍时切换到下一个文件。 例如,如果设置成1小时,则每个整点将创建一个文件。 + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for some more details of capturing packets on WLAN networks.</p></body></html> + + + + Enable monitor mode on all 802.11 interfaces + + compression 压缩 @@ -1348,6 +1428,30 @@ For example, use 1 hour to have a new file created every hour on the hour.gzip gzip + + File infix pattern + + + + <html><head/><body><p>In multiple file mode, the date and time and file index number are inserted between filename template and any suffix. Select their order.</p></body></html> + + + + YYYYmmDDHHMMSS_NNNNN + + + + <html><head/><body><p>Date and time before the file index number. This causes files to sort in creation time order, and keeps files from the same batch closely ordered.</p></body></html> + + + + NNNNN_YYYYmmDDHHMMSS + + + + <html><head/><body><p>File index number before the date and time. This is the historic Wireshark ordering.</p></body></html> + + <html><head/><body><p>After capturing has switched to the next file and the given number of files has exceeded, the oldest file will be removed.</p></body></html> <html><head/><body><p>当捕获切换到下一个文件并且给定的文件数已经达到时,则最早的文件将会被删除。</p></body></html> @@ -1501,7 +1605,7 @@ For example, use 1 hour to have a new file created every hour on the hour.错误 - Multiple files: Requested filesize too large. The filesize cannot be greater than 2 GiB. + Multiple files: Requested filesize too large. The filesize cannot be greater than 2 TB. @@ -1531,6 +1635,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Capture packets in promiscuous mode 使用混杂模式捕获分组 + + <html><head/><body><p>Usually a wireless network card will only capture the traffic sent to and from its own network address, and only captures <em>user data</em> traffic with &quot;fake&quot; Ethernet headers. If you want to capture all traffic that wireless network cards can &quot;see&quot;, or are interested in 802.11 management or control packets, or radio-layer information, mark this option. Monitor mode availability depends on the wireless card and driver. See the Wiki for more details of capturing packets on WLAN networks.</p></body></html> + + + + Capture packets in monitor mode on 802.11 devices + + <html><head/><body><p>Capture packets in the next-generation capture file format.</p></body></html> <html><head/><body><p>使用下一代捕获文件格式来捕获分组。</p></body></html> @@ -1758,6 +1870,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved + + Width + + + + Alignment + + <html>Show human-readable strings instead of raw values for fields. Only applicable to custom columns with fields that have value strings.</html> @@ -1805,6 +1925,25 @@ For example, use 1 hour to have a new file created every hour on the hour.复制过滤器文本到剪贴板。 + + CompressionGroupBox + + Compression options + + + + &Uncompressed + + + + Compress with g&zip + + + + Compress with &LZ4 + + + ConversationDataModel @@ -1871,6 +2010,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Bits/s B + + Flows + + Total Packets @@ -1986,29 +2129,53 @@ For example, use 1 hour to have a new file created every hour on the hour.将分组字节复制为十六进制转储。 - …as Printable Text + …as MIME Data - Copy only the printable text in the packet. + …as C String - …as MIME Data + Copy packet bytes as printable ASCII characters and escape sequences. - …as C String + …as Go literal - Copy packet bytes as printable ASCII characters and escape sequences. + Copy packet bytes as Go literal. + + + + …as C Array + + + + Copy packet bytes as C Array. …as a Hex Stream + + …as UTF-8 Text + + + + Copy packet bytes as text, treating as UTF-8. + + + + …as ASCII Text + + + + Copy packet bytes as text, treating as ASCII. + + Copy packet bytes as a stream of hex. 将分组字节复制为十六进制流。 @@ -2803,6 +2970,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: 显示过滤器: + + Export PDUs + + ExtArgSelector @@ -2841,10 +3012,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Start 开始 - - Save - - Default 默认 @@ -2985,6 +3152,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Display Filters 显示过滤器 + + Display Filter Macros + + + + New macro + + Open 打开 @@ -3068,10 +3243,18 @@ For example, use 1 hour to have a new file created every hour on the hour. FilterListModel + + Macro Name + + Filter Name + + Macro Expression + + Filter Expression @@ -3157,22 +3340,10 @@ For example, use 1 hour to have a new file created every hour on the hour. FolderListModel - - "File" dialogs - “文件”对话框 - - - capture files - 捕获文件 - Temp 临时 - - untitled capture files - 无标题捕获文件 - Personal configuration 个人配置 @@ -3181,14 +3352,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Global configuration 全局配置 - - dfilters, preferences, ethers, … - - - - dfilters, preferences, manuf, … - - System 系统 @@ -3201,18 +3364,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Program 程序 - - program files - 程序文件 - Personal Plugins 个人插件 - - binary plugins - 二进制插件 - Global Plugins 全局插件 @@ -3229,12 +3384,36 @@ For example, use 1 hour to have a new file created every hour on the hour.Lua scripts + + "File" dialog location + + + + Capture files + + + + Untitled capture files + + + + Preferences, profiles, manuf, … + + + + Program files + + + + Binary plugins + + Personal Extcap path - external capture (extcap) plugins + External capture (extcap) plugins @@ -3354,6 +3533,22 @@ For example, use 1 hour to have a new file created every hour on the hour.%Ln turn(s). + + Event %1. + + + + %Ln <span style="color: %1; background-color:%2">reads</span>, + + + + + + %Ln <span style="color: %1; background-color:%2">writes</span>, + + + + Click to select. 点击选择。 @@ -3386,6 +3581,18 @@ For example, use 1 hour to have a new file created every hour on the hour.%1 stream not found on the selected packet. + + Read activity(%6) + + + + Write activity(%6) + + + + Entire I/O activity (%1) + + Entire conversation (%1) 整个对话(%1) @@ -3402,10 +3609,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Save Stream Content As… - - [Stream output truncated] - [流输出被截断] - %Ln total stream(s). @@ -3431,8 +3634,19 @@ For example, use 1 hour to have a new file created every hour on the hour.提示。 - Show data as - Show and save data as + Show as + 显示为 + + + No delta times + + + + Turn delta times + + + + All delta times @@ -3447,11 +3661,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: 查找: + + Case sensitive + 区分大小写 + Find &Next 查找下一个(&N) + + FollowStreamText + + [Stream output truncated] + + + FontColorPreferencesFrame @@ -3787,29 +4012,28 @@ For example, use 1 hour to have a new file created every hour on the hour. - - Remove this graph. - Remove this dissection behavior. - 删除图形。 - Add a new graph. 增加新图形。 - - Duplicate this graph. - 复制图形。 - Clear all graphs. 清除所有图形。 - Move this graph upwards. + Remove the selected graph(s). + + + + Duplicate the selected graph(s). + + + + Move the selected graph(s) upwards. - Move this graph downwards. + Move the selected graph(s) downwards. @@ -3852,10 +4076,6 @@ For example, use 1 hour to have a new file created every hour on the hour.Enable legend - - Reset - 复位 - Reset Graph 复位图形 @@ -4069,6 +4289,42 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy graphs from another profile. 从另一个配置文件复制图形。 + + 1 μs + + + + 2 μs + + + + 5 μs + + + + 10 μs + + + + 20 μs + + + + 50 μs + + + + 100 μs + + + + 200 μs + + + + 500 μs + + 1 ms 1毫秒 @@ -4113,6 +4369,14 @@ For example, use 1 hour to have a new file created every hour on the hour.5 sec 10秒 {5 ?} + + 2 min + 10分钟 {2 ?} + + + 5 min + 10分钟 {5 ?} + Wireshark I/O Graphs: %1 @@ -4125,6 +4389,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Filtered events + + All packets + + + + All events + + All Packets @@ -4138,7 +4410,7 @@ For example, use 1 hour to have a new file created every hour on the hour. - Access Denied + All Execs @@ -4185,6 +4457,34 @@ For example, use 1 hour to have a new file created every hour on the hour.Click to select a portion of the graph. 点击选择图形的一部分。 + + %1 Intervals + + + + Move to top left + + + + Move to top center + + + + Move to top right + + + + Move to bottom left + + + + Move to bottom center + + + + Move to bottom right + + Portable Document Format (*.pdf) 便携式文档格式 (*.pdf) @@ -4937,6 +5237,13 @@ For example, use 1 hour to have a new file created every hour on the hour.应用更改 + + InterfaceTreeDelegate + + default + 默认 + + InterfaceTreeModel @@ -5912,8 +6219,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteMacStatisticsDialog - LTE Mac Statistics - LTE MAC 统计 + LTE/NR Mac Statistics + Include SR frames in filter @@ -6217,12 +6524,12 @@ For example, use 1 hour to have a new file created every hour on the hour.序列号 - LTE RLC Graph (UE=%1 chan=%2%3 %4 - %5) - LTE RLC 图表 (UE=%1 chan=%2%3 %4 - %5) + %1 RLC Graph (UE=%2 chan=%3%4 %5 - %6) + - LTE RLC Graph - no channel selected - LTE RLC 图表 - 没有选择信道 + 3GPP RLC Graph - no channel selected + Save As… @@ -6276,8 +6583,8 @@ For example, use 1 hour to have a new file created every hour on the hour. LteRlcStatisticsDialog - LTE RLC Statistics - LTE RLC 统计 + 3GPP RLC Statistics + Include SR frames in filter @@ -6362,6 +6669,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Profile: %1 配置:%1 + + %1 Displayed: %2 (%3%) + + Manage Profiles… @@ -6423,6 +6734,12 @@ For example, use 1 hour to have a new file created every hour on the hour. + + %Ln bit(s) + + + + Byte %1 字节 %1 @@ -6436,9 +6753,12 @@ For example, use 1 hour to have a new file created every hour on the hour.所选分组:%1 %2 - Packets: %1 %4 Displayed: %2 (%3%) - Packets: %1 %4 Displayed: %2 %4 Marked: %3 - 分组: %1 %4 已显示: %2 (%3%) + Selected Event: %1 %2 + + + + Events: %1 + %1 Selected: %2 (%3%) @@ -6469,6 +6789,10 @@ For example, use 1 hour to have a new file created every hour on the hour.No Packets 无分组 + + No Events + + From Zip File... @@ -6500,6 +6824,13 @@ For example, use 1 hour to have a new file created every hour on the hour. + + MainWindow + + Display filter as %1 + + + MainWindowPreferencesFrame @@ -6531,6 +6862,10 @@ For example, use 1 hour to have a new file created every hour on the hour.The most recently used folder 最近使用的文件夹 + + The current working directory + + Show up to 显示最多 @@ -6961,6 +7296,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Show Field Values + + Refresh + 刷新 + Save Diagram As… @@ -7005,7 +7344,11 @@ For example, use 1 hour to have a new file created every hour on the hour.<small><i></i></small> - Show packet bytes + Show packet bytes + + + + Layout: @@ -7030,6 +7373,12 @@ For example, use 1 hour to have a new file created every hour on the hour. + + %Ln bit(s) + + + + PacketFormatGroupBox @@ -7487,10 +7836,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Copy this profile. 复制该配置文件。 + + The number of packets or events to check for automatic profile switching. + + + + Auto switch packet limit + + Configuration Profiles 配置文件 + + Auto switch event limit + + Import noun @@ -7654,6 +8015,10 @@ For example, use 1 hour to have a new file created every hour on the hour.deleted + + Auto Switch Filter + + copy noun @@ -8177,6 +8542,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Marker missing? 标记缺失? + + LTE + + + + NR + + C-RNTI C-RNTI @@ -8197,6 +8570,10 @@ For example, use 1 hour to have a new file created every hour on the hour.UEId UEId + + RAT + + UL Frames UL 帧 @@ -8421,12 +8798,72 @@ For example, use 1 hour to have a new file created every hour on the hour.Browse… 浏览… + + PACKETS + + + + EVENTS + + + + BYTES + + + + BITS + + + + COUNT FRAMES + + + + COUNT FIELDS + + + + SUM + + + + MAX + + + + MIN + + + + AVERAGE + + + + THROUGHPUT + + + + LOAD + + + + Left + + + + Center + + + + Right + + - QObject::QObject + QObject::QObject::QObject CCCH - CCCH + CCCH @@ -8523,6 +8960,13 @@ For example, use 1 hour to have a new file created every hour on the hour.毫秒 + + ResizeHeaderView + + Resize all %1 to contents + + + ResolvedAddressesDialog @@ -8638,6 +9082,14 @@ For example, use 1 hour to have a new file created every hour on the hour.Resolved Addresses 解析后的地址 + + Copy + 复制 + + + Save as… + 另存为… + # Resolved addresses found in %1 # 在 %1 中找到的解析后的地址 @@ -8651,6 +9103,61 @@ For example, use 1 hour to have a new file created every hour on the hour. + + ResolvedAddressesView + + as Plain Text + + + + Copy selected rows + + + + Copy table + + + + as CSV + 作为 CSV + + + as JSON + + + + Save selected rows as… + + + + Save table as… + + + + Save Resolved Addresses As… + + + + Plain text (*.txt) + 纯文本 (*.txt) + + + CSV Document (*.csv) + + + + JSON Document (*.json) + + + + Warning + 警告 + + + Unable to save %1: %2 + + + ResponseTimeDelayDialog @@ -9420,7 +9927,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Left + Right - + 左 + 右 To Right @@ -9731,7 +10238,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Shift+R - + Shift+R Find Only &Singles @@ -9743,7 +10250,7 @@ For example, use 1 hour to have a new file created every hour on the hour. Ctrl+R - + Ctrl+R Mark Packets @@ -10325,6 +10832,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Packet bytes 分组字节流 + + <b>Options:</b> + + <html><head/><body><p>Search for strings containing narrow (UTF-8 and ASCII) or wide (UTF-16) characters.</p></body></html> <html><head/><body><p>搜索包含窄字符集 (UTF-8 与 ASCII) 或宽字符集 (UTF-16) 的字符串。</p></body></html> @@ -10345,6 +10856,18 @@ For example, use 1 hour to have a new file created every hour on the hour.Case sensitive 区分大小写 + + Backwards + + + + <html><head/><body><p>Search for a subsequent occurrence in the current packet before advancing to the next packet.</p></body></html> + + + + Multiple occurrences + + <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5), a plain string (e.g. My String) or a regular expression (e.g. colou?r).</p></body></html> <html><head/><body><p>Search for data using display filter syntax (e.g. ip.addr==10.1.1.1), a hexadecimal string (e.g. fffffda5) or a plain string (e.g. My String).</p></body></html> @@ -10382,6 +10905,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Invalid filter. 无效过滤器。 + + Event List + + + + Event Details + + + + Event Bytes + + + + <html><head/><body><p>Search the Info column of the event list (summary pane), decoded event display labels (tree view pane) or the ASCII-converted event data (hex view pane).</p></body></html> + + That filter doesn't test anything. 该过滤器未测试任何项目。 @@ -10823,6 +11362,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Find: 查找: + + Case sensitive + 区分大小写 + Find &Next 查找下一个(&N) @@ -10917,14 +11460,22 @@ For example, use 1 hour to have a new file created every hour on the hour.Save as… 另存为… + + Decoded as %1. + + Save Selected Packet Bytes As… + + compressed %1 + + - Displaying %Ln byte(s). - - 已显示 %Ln 字节。 + Using %Ln byte(s). + + @@ -11024,6 +11575,10 @@ For example, use 1 hour to have a new file created every hour on the hour.Display filter: + + Strip Headers + + SupportedProtocolsDialog @@ -11993,22 +12548,20 @@ For example, use 1 hour to have a new file created every hour on the hour.创建一个新项。 - Remove this entry. - Remove this profile. - 移除此项。 + Remove the selected entry(ies). + - Copy this entry. - Copy this profile. - 复制此项。 + Copy the selected entry(ies). + - Move entry up. - 向上移动条目。 + Move the selected entry(ies) up. + - Move entry down. - 向下移动条目。 + Move the selected entry(ies) down. + Clear all entries. @@ -12034,20 +12587,20 @@ For example, use 1 hour to have a new file created every hour on the hour.创建一个新条目。 - Remove this entry. - 删除此条目。 + Remove the selected entry(ies). + - Copy this entry. - 复制此条目。 + Copy the selected entry(ies). + - Move entry up. - 向上移动条目。 + Move the selected entry(ies) up. + - Move entry down. - 向下移动条目。 + Move the selected entry(ies) down. + Clear all entries. @@ -12374,10 +12927,18 @@ a:hover { You are sniffing the glue that holds the Internet together using Wireshark 你正在使用 Wireshark 嗅探互联网的联机 + + You are sniffing the glue that holds your system together using Logray + + You are running Wireshark 正在运行 Wireshark + + You are running Logray + + You receive automatic updates. 接受自动更新。 @@ -12654,14 +13215,6 @@ a:hover { No files found 未找到文件 - - &Contents - 内容(&C) - - - Wireshark Filter - Wireshark 过滤器 - TShark TShark @@ -12927,10 +13480,6 @@ a:hover { Wireless Toolbar 无线工具栏 - - Help contents - 帮助内容 - FAQs @@ -13051,11 +13600,6 @@ a:hover { Find the previous packet 查找上一分组 - - &Mark/Unmark Packet(s) - &Mark/Unmark Packet - 标记/取消标记 分组(&M) - Mark All Displayed 标记所有显示的分组 @@ -13084,11 +13628,6 @@ a:hover { Go to the previous marked packet 转到前一个已标记的分组 - - &Ignore/Unignore Packet(s) - &Ignore/Unignore Packet - 忽略/取消忽略 分组(&I) - Ignore All Displayed 忽略所有显示的分组 @@ -13529,10 +14068,6 @@ a:hover { Reset Layout 重置布局 - - Reset appearance layout to default size - 重置外观布局为默认尺寸 - Seconds Since First Captured Packet @@ -13694,20 +14229,28 @@ a:hover { - TLS Keylog Launcher + &Options… + 选项(&O)… + + + &3GPP Uu - Release Notes + &Wireless + 无线(&W) + + + &User's Guide - &Options… - 选项(&O)… + Wireshark User's Guide + - &Wireless - 无线(&W) + Display Filters + 显示过滤器 Capture &Filters… @@ -13753,10 +14296,18 @@ a:hover { Find Pre&vious 查找上一个(&v) + + &Mark/Unmark Selected + + Mark or unmark each selected packet + + &Ignore/Unignore Selected + + Ignore or unignore each selected packet @@ -13797,6 +14348,18 @@ a:hover { TCP throughput + + General + + + + Query-Response + + + + DNS Query-Response Statistics + + Request Sequences 请求序列 @@ -13805,6 +14368,14 @@ a:hover { HTTP Request Sequences HTTP 请求序列 + + E2AP + + + + E2AP Messages + + Decode &As… 解码为(&A)… @@ -13865,6 +14436,10 @@ a:hover { Normal Size 普通大小 + + Reset layout to default size + + Resize Columns 调整列宽 @@ -14123,6 +14698,14 @@ a:hover { Go to the packet referenced by the selected field. 转至选定字段引用的分组。 + + TLS Keylog Launcher + + + + Release Notes + + &VoIP Calls &VoIP 通话 @@ -14155,10 +14738,6 @@ a:hover { &GSM - - &LTE - - &MTP3 @@ -14443,6 +15022,10 @@ a:hover { Quit without Saving 直接退出,不保存(&W) + + USB CDC Data + + There is no "rtp.ssrc" field in this version of Wireshark. diff --git a/ui/qt/wlan_statistics_dialog.cpp b/ui/qt/wlan_statistics_dialog.cpp index 0fc529ea..7166cbab 100644 --- a/ui/qt/wlan_statistics_dialog.cpp +++ b/ui/qt/wlan_statistics_dialog.cpp @@ -222,7 +222,7 @@ public: } else if (wlan_hdr->stats.ssid_len == 1 && wlan_hdr->stats.ssid[0] == 0) { ssid_text = QObject::tr(""); } else { - gchar *str = format_text(NULL, (const char *)wlan_hdr->stats.ssid, wlan_hdr->stats.ssid_len); + char *str = format_text(NULL, (const char *)wlan_hdr->stats.ssid, wlan_hdr->stats.ssid_len); ssid_text = str; wmem_free(NULL, str); } @@ -293,7 +293,7 @@ public: } if (update_ssid) { - gchar* str; + char* str; ssid_ = QByteArray::fromRawData((const char *)wlan_hdr->stats.ssid, wlan_hdr->stats.ssid_len); str = format_text(NULL, (const char *)wlan_hdr->stats.ssid, wlan_hdr->stats.ssid_len); setText(col_ssid_, str); @@ -571,7 +571,7 @@ tap_packet_status WlanStatisticsDialog::tapPacket(void *ws_dlg_ptr, _packet_info const wlan_hdr_t *wlan_hdr = (const wlan_hdr_t *)wlan_hdr_ptr; if (!ws_dlg || !wlan_hdr) return TAP_PACKET_DONT_REDRAW; - guint16 frame_type = wlan_hdr->type & 0xff0; + uint16_t frame_type = wlan_hdr->type & 0xff0; if (!((frame_type == 0x0) || (frame_type == 0x20) || (frame_type == 0x30)) || ((frame_type == 0x20) && DATA_FRAME_IS_NULL(wlan_hdr->type))) { /* Not a management or non null data or extension frame; let's skip it */ -- cgit v1.2.3