2012-01-04 22:13:01 +00:00
|
|
|
/* main_window.cpp
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2017-12-07 16:15:30 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0+
|
2012-01-04 22:13:01 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "main_window.h"
|
2017-05-31 19:34:55 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The generated Ui_MainWindow::setupUi() can grow larger than our configured limit,
|
|
|
|
* so turn off -Wframe-larger-than= for ui_main_window.h.
|
|
|
|
*/
|
|
|
|
DIAG_OFF(frame-larger-than=)
|
2015-06-25 16:17:03 +00:00
|
|
|
#include <ui_main_window.h>
|
2017-05-31 19:34:55 +00:00
|
|
|
DIAG_ON(frame-larger-than=)
|
2012-01-04 22:13:01 +00:00
|
|
|
|
2014-12-12 20:35:31 +00:00
|
|
|
#include <epan/addr_resolv.h>
|
2016-03-18 17:34:41 +00:00
|
|
|
#include "epan/dissector_filters.h"
|
2013-09-11 17:39:49 +00:00
|
|
|
#include <epan/epan_dissect.h>
|
2013-11-17 02:55:14 +00:00
|
|
|
#include <wsutil/filesystem.h>
|
2017-09-26 14:04:56 +00:00
|
|
|
#include <version_info.h>
|
2012-01-04 22:13:01 +00:00
|
|
|
#include <epan/prefs.h>
|
2015-01-06 09:22:48 +00:00
|
|
|
#include <epan/stats_tree_priv.h>
|
2015-06-05 09:19:37 +00:00
|
|
|
#include <epan/plugin_if.h>
|
2016-11-24 14:37:01 +00:00
|
|
|
#include <epan/export_object.h>
|
2012-01-04 22:13:01 +00:00
|
|
|
|
2017-04-15 21:30:30 +00:00
|
|
|
#include "ui/iface_toolbar.h"
|
2016-06-28 01:40:09 +00:00
|
|
|
|
2012-08-31 22:25:51 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2014-06-30 05:38:29 +00:00
|
|
|
#include "ui/capture.h"
|
2014-06-30 05:08:59 +00:00
|
|
|
#include <capchild/capture_session.h>
|
2012-08-31 22:25:51 +00:00
|
|
|
#endif
|
|
|
|
|
2012-07-18 16:40:34 +00:00
|
|
|
#include "ui/alert_box.h"
|
2014-06-30 01:36:22 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
#include "ui/capture_ui_utils.h"
|
|
|
|
#endif
|
2012-08-31 22:25:51 +00:00
|
|
|
#include "ui/capture_globals.h"
|
2013-10-11 17:20:50 +00:00
|
|
|
#include "ui/main_statusbar.h"
|
2013-10-30 22:39:52 +00:00
|
|
|
#include "ui/recent.h"
|
2016-09-02 13:21:46 +00:00
|
|
|
#include "ui/recent_utils.h"
|
2013-10-11 17:20:50 +00:00
|
|
|
#include "ui/util.h"
|
2015-06-05 09:19:37 +00:00
|
|
|
#include "ui/preference_utils.h"
|
2012-01-14 00:16:16 +00:00
|
|
|
|
2012-01-04 22:13:01 +00:00
|
|
|
#include "byte_view_tab.h"
|
2016-03-31 00:24:44 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
#include "capture_interfaces_dialog.h"
|
|
|
|
#endif
|
2016-03-18 17:34:41 +00:00
|
|
|
#include "conversation_colorize_action.h"
|
2016-11-24 14:37:01 +00:00
|
|
|
#include "export_object_action.h"
|
2017-07-05 14:56:45 +00:00
|
|
|
#include <ui/qt/widgets/display_filter_edit.h>
|
2012-10-12 23:40:29 +00:00
|
|
|
#include "export_dissection_dialog.h"
|
2016-03-31 00:24:44 +00:00
|
|
|
#include "file_set_dialog.h"
|
2017-09-26 11:14:02 +00:00
|
|
|
#include "filter_dialog.h"
|
2015-07-03 20:52:49 +00:00
|
|
|
#include "funnel_statistics.h"
|
2014-09-18 21:09:55 +00:00
|
|
|
#include "import_text_dialog.h"
|
2017-04-15 21:30:30 +00:00
|
|
|
#include "interface_toolbar.h"
|
2015-02-11 23:00:27 +00:00
|
|
|
#include "packet_list.h"
|
2017-04-06 21:45:33 +00:00
|
|
|
#include "wireless_timeline.h"
|
2014-09-18 21:09:55 +00:00
|
|
|
#include "proto_tree.h"
|
2014-09-24 21:06:23 +00:00
|
|
|
#include "simple_dialog.h"
|
2017-07-25 14:15:18 +00:00
|
|
|
#include <ui/qt/utils/stock_icon.h>
|
2015-07-08 22:44:04 +00:00
|
|
|
#include "tap_parameter_dialog.h"
|
2015-06-11 22:05:44 +00:00
|
|
|
#include "wireless_frame.h"
|
2014-09-18 21:09:55 +00:00
|
|
|
#include "wireshark_application.h"
|
2012-01-04 22:13:01 +00:00
|
|
|
|
2017-07-05 14:56:45 +00:00
|
|
|
#include <ui/qt/widgets/additional_toolbar.h>
|
2017-07-25 14:15:18 +00:00
|
|
|
#include <ui/qt/utils/variant_pointer.h>
|
2017-01-24 16:34:07 +00:00
|
|
|
|
2017-07-25 14:15:18 +00:00
|
|
|
#include <ui/qt/utils/qt_ui_utils.h>
|
2012-01-04 22:13:01 +00:00
|
|
|
|
2017-06-27 14:36:19 +00:00
|
|
|
#include <ui/qt/widgets/drag_drop_toolbar.h>
|
|
|
|
|
2012-01-04 22:13:01 +00:00
|
|
|
#include <QAction>
|
2014-10-21 20:36:10 +00:00
|
|
|
#include <QActionGroup>
|
2013-10-30 22:39:52 +00:00
|
|
|
#include <QDesktopWidget>
|
2012-01-04 22:13:01 +00:00
|
|
|
#include <QKeyEvent>
|
2012-08-31 22:25:51 +00:00
|
|
|
#include <QMessageBox>
|
2013-10-30 22:39:52 +00:00
|
|
|
#include <QMetaObject>
|
2015-06-14 18:04:51 +00:00
|
|
|
#include <QMimeData>
|
2013-10-30 22:39:52 +00:00
|
|
|
#include <QTabWidget>
|
|
|
|
#include <QToolButton>
|
|
|
|
#include <QTreeWidget>
|
2015-06-14 18:30:24 +00:00
|
|
|
#include <QUrl>
|
2012-01-04 22:13:01 +00:00
|
|
|
|
2014-02-11 19:45:30 +00:00
|
|
|
#if defined(QT_MACEXTRAS_LIB) && QT_VERSION < QT_VERSION_CHECK(5, 2, 1)
|
2013-06-10 21:21:51 +00:00
|
|
|
#include <QtMacExtras/QMacNativeToolBar>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2012-01-04 22:13:01 +00:00
|
|
|
//menu_recent_file_write_all
|
|
|
|
|
|
|
|
// If we ever add support for multiple windows this will need to be replaced.
|
2014-07-09 17:50:51 +00:00
|
|
|
static MainWindow *gbl_cur_main_window_ = NULL;
|
2012-01-04 22:13:01 +00:00
|
|
|
|
2015-06-10 00:30:15 +00:00
|
|
|
void pipe_input_set_handler(gint source, gpointer user_data, ws_process_id *child_process, pipe_input_cb_t input_cb)
|
2012-08-31 22:25:51 +00:00
|
|
|
{
|
2014-07-09 17:50:51 +00:00
|
|
|
gbl_cur_main_window_->setPipeInputHandler(source, user_data, child_process, input_cb);
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
|
2017-12-14 22:13:39 +00:00
|
|
|
static void plugin_if_mainwindow_apply_filter(GHashTable * data_set)
|
2015-06-05 09:19:37 +00:00
|
|
|
{
|
2017-12-14 22:13:39 +00:00
|
|
|
if (!gbl_cur_main_window_ || !data_set)
|
2016-01-23 12:18:30 +00:00
|
|
|
return;
|
2015-06-05 09:19:37 +00:00
|
|
|
|
2016-01-23 12:18:30 +00:00
|
|
|
if (g_hash_table_lookup_extended(data_set, "filter_string", NULL, NULL)) {
|
|
|
|
QString filter((const char *)g_hash_table_lookup(data_set, "filter_string"));
|
|
|
|
gbl_cur_main_window_->filterPackets(filter);
|
2015-06-05 09:19:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-14 22:13:39 +00:00
|
|
|
static void plugin_if_mainwindow_preference(GHashTable * data_set)
|
2015-06-05 09:19:37 +00:00
|
|
|
{
|
2017-12-14 22:13:39 +00:00
|
|
|
if (!gbl_cur_main_window_ || !data_set)
|
2016-01-23 12:18:30 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
const char * module_name;
|
|
|
|
const char * pref_name;
|
|
|
|
const char * 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))
|
2015-06-05 09:19:37 +00:00
|
|
|
{
|
2016-01-23 12:18:30 +00:00
|
|
|
if (prefs_store_ext(module_name, pref_name, pref_value)) {
|
|
|
|
wsApp->emitAppSignal(WiresharkApplication::PacketDissectionChanged);
|
|
|
|
wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
|
2015-06-05 09:19:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-14 22:13:39 +00:00
|
|
|
static void plugin_if_mainwindow_gotoframe(GHashTable * data_set)
|
2015-08-09 12:36:53 +00:00
|
|
|
{
|
2017-12-14 22:13:39 +00:00
|
|
|
if (!gbl_cur_main_window_ || !data_set)
|
2016-01-23 12:18:30 +00:00
|
|
|
return;
|
2015-08-09 12:36:53 +00:00
|
|
|
|
2016-01-23 12:18:30 +00:00
|
|
|
gpointer framenr;
|
|
|
|
|
|
|
|
if (g_hash_table_lookup_extended(data_set, "frame_nr", NULL, &framenr)) {
|
|
|
|
if (GPOINTER_TO_UINT(framenr) != 0)
|
|
|
|
gbl_cur_main_window_->gotoFrame(GPOINTER_TO_UINT(framenr));
|
2015-08-09 12:36:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-07 07:39:14 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
|
2017-12-14 22:13:39 +00:00
|
|
|
static void plugin_if_mainwindow_get_ws_info(GHashTable * data_set)
|
2016-01-07 07:39:14 +00:00
|
|
|
{
|
2017-12-14 22:13:39 +00:00
|
|
|
if (!gbl_cur_main_window_ || !data_set)
|
2016-01-23 12:18:30 +00:00
|
|
|
return;
|
2016-01-07 07:39:14 +00:00
|
|
|
|
2016-01-23 12:18:30 +00:00
|
|
|
ws_info_t *ws_info = NULL;
|
2016-01-07 07:39:14 +00:00
|
|
|
|
2016-01-23 12:18:30 +00:00
|
|
|
if (!g_hash_table_lookup_extended(data_set, "ws_info", NULL, (void**)&ws_info))
|
|
|
|
return;
|
2016-01-07 07:39:14 +00:00
|
|
|
|
2016-01-23 12:18:30 +00:00
|
|
|
CaptureFile *cfWrap = gbl_cur_main_window_->captureFile();
|
|
|
|
capture_file *cf = cfWrap->capFile();
|
2016-01-07 07:39:14 +00:00
|
|
|
|
2016-01-23 12:18:30 +00:00
|
|
|
ws_info->ws_info_supported = true;
|
2016-01-07 07:39:14 +00:00
|
|
|
|
2017-11-05 10:39:54 +00:00
|
|
|
/* If we have a filename attached to ws_info clear it */
|
|
|
|
if (ws_info->cf_filename != NULL)
|
|
|
|
{
|
|
|
|
g_free(ws_info->cf_filename);
|
|
|
|
ws_info->cf_filename = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Determine the true state of the capture file. We return the true state in
|
|
|
|
the ws_info structure and DON'T CHANGE the cf->state as we don't want to cause problems
|
|
|
|
with code that follows this. */
|
|
|
|
if (cf)
|
|
|
|
{
|
|
|
|
if (cf->filename)
|
|
|
|
{
|
|
|
|
/* As we have a cf->filename we'll use the name and the state */
|
|
|
|
ws_info->cf_filename = g_strdup(cf->filename);
|
|
|
|
ws_info->cf_state = cf->state;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* When we come through here the cf->state can show FILE_READ_DONE even though the
|
|
|
|
file is actually closed (no filename). A better fix would be to have a
|
|
|
|
FILE_CLOSE_PENDING state but that involves a lot of code change elsewhere. */
|
|
|
|
ws_info->cf_state = FILE_CLOSED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ws_info->cf_filename)
|
|
|
|
{
|
|
|
|
/* We may have a filename associated with the main window so let's use it */
|
|
|
|
QString fileNameString = gbl_cur_main_window_->getMwFileName();
|
|
|
|
if (fileNameString.length())
|
|
|
|
{
|
|
|
|
QByteArray ba = fileNameString.toLatin1();
|
|
|
|
const char *c_file_name = ba.data();
|
|
|
|
ws_info->cf_filename = g_strdup(c_file_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-23 12:18:30 +00:00
|
|
|
if (cf) {
|
|
|
|
ws_info->cf_count = cf->count;
|
|
|
|
|
2017-01-17 17:25:24 +00:00
|
|
|
if (cf->state == FILE_READ_DONE && cf->current_frame) {
|
2016-01-23 12:18:30 +00:00
|
|
|
ws_info->cf_framenr = cf->current_frame->num;
|
|
|
|
ws_info->frame_passed_dfilter = (cf->current_frame->flags.passed_dfilter == 1);
|
2017-11-05 10:39:54 +00:00
|
|
|
}
|
|
|
|
else {
|
2016-01-23 12:18:30 +00:00
|
|
|
ws_info->cf_framenr = 0;
|
|
|
|
ws_info->frame_passed_dfilter = FALSE;
|
2016-01-07 07:39:14 +00:00
|
|
|
}
|
2017-11-05 10:39:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Initialise the other ws_info structure values */
|
2016-01-23 12:18:30 +00:00
|
|
|
ws_info->cf_count = 0;
|
|
|
|
ws_info->cf_framenr = 0;
|
|
|
|
ws_info->frame_passed_dfilter = FALSE;
|
2016-01-07 07:39:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* HAVE_LIBPCAP */
|
|
|
|
|
2017-12-14 22:13:39 +00:00
|
|
|
static void plugin_if_mainwindow_update_toolbars(GHashTable * data_set)
|
2017-01-24 16:34:07 +00:00
|
|
|
{
|
2017-12-14 22:13:39 +00:00
|
|
|
if (!gbl_cur_main_window_ || ! data_set)
|
2017-01-24 16:34:07 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (g_hash_table_lookup_extended(data_set, "toolbar_name", NULL, NULL)) {
|
|
|
|
QString toolbarName((const char *)g_hash_table_lookup(data_set, "toolbar_name"));
|
|
|
|
gbl_cur_main_window_->removeAdditionalToolbar(toolbarName);
|
2017-04-15 21:30:30 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-31 06:28:02 +00:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
|
2017-04-15 21:30:30 +00:00
|
|
|
static void mainwindow_add_toolbar(const iface_toolbar *toolbar_entry)
|
|
|
|
{
|
|
|
|
if (gbl_cur_main_window_ && toolbar_entry)
|
|
|
|
{
|
|
|
|
gbl_cur_main_window_->addInterfaceToolbar(toolbar_entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mainwindow_remove_toolbar(const gchar *menu_title)
|
|
|
|
{
|
|
|
|
if (gbl_cur_main_window_ && menu_title)
|
|
|
|
{
|
|
|
|
gbl_cur_main_window_->removeInterfaceToolbar(menu_title);
|
2017-01-24 16:34:07 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-31 06:28:02 +00:00
|
|
|
#endif
|
2017-01-24 16:34:07 +00:00
|
|
|
|
2015-01-06 09:22:48 +00:00
|
|
|
QMenu* MainWindow::findOrAddMenu(QMenu *parent_menu, QString& menu_text) {
|
|
|
|
QList<QAction *> actions = parent_menu->actions();
|
|
|
|
QList<QAction *>::const_iterator i;
|
|
|
|
for (i = actions.constBegin(); i != actions.constEnd(); ++i) {
|
|
|
|
if ((*i)->text()==menu_text) {
|
|
|
|
return (*i)->menu();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If we get here there menu entry was not found, add a sub menu
|
|
|
|
return parent_menu->addMenu(menu_text);
|
|
|
|
}
|
|
|
|
|
2012-01-04 22:13:01 +00:00
|
|
|
MainWindow::MainWindow(QWidget *parent) :
|
|
|
|
QMainWindow(parent),
|
2012-08-31 22:25:51 +00:00
|
|
|
main_ui_(new Ui::MainWindow),
|
2015-02-06 18:36:27 +00:00
|
|
|
cur_layout_(QVector<unsigned>()),
|
2016-03-31 00:24:44 +00:00
|
|
|
df_combo_box_(NULL),
|
2015-07-27 22:28:50 +00:00
|
|
|
packet_list_(NULL),
|
|
|
|
proto_tree_(NULL),
|
2012-08-31 22:25:51 +00:00
|
|
|
previous_focus_(NULL),
|
2016-03-31 00:24:44 +00:00
|
|
|
file_set_dialog_(NULL),
|
2014-10-22 17:05:35 +00:00
|
|
|
show_hide_actions_(NULL),
|
2014-10-21 20:36:10 +00:00
|
|
|
time_display_actions_(NULL),
|
|
|
|
time_precision_actions_(NULL),
|
2016-03-31 00:24:44 +00:00
|
|
|
funnel_statistics_(NULL),
|
2015-11-10 18:12:56 +00:00
|
|
|
freeze_focus_(NULL),
|
2016-10-19 18:53:40 +00:00
|
|
|
was_maximized_(false),
|
2012-09-01 02:56:32 +00:00
|
|
|
capture_stopping_(false),
|
2016-04-29 15:53:44 +00:00
|
|
|
capture_filter_valid_(false)
|
2015-12-23 13:46:45 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2016-04-29 15:53:44 +00:00
|
|
|
, capture_interfaces_dialog_(NULL)
|
|
|
|
, info_data_()
|
2015-12-23 13:46:45 +00:00
|
|
|
#endif
|
2017-09-26 11:14:02 +00:00
|
|
|
, display_filter_dlg_(NULL)
|
|
|
|
, capture_filter_dlg_(NULL)
|
2012-08-31 22:25:51 +00:00
|
|
|
#ifdef _WIN32
|
2016-04-29 15:53:44 +00:00
|
|
|
, pipe_timer_(NULL)
|
2012-08-31 22:25:51 +00:00
|
|
|
#else
|
2016-04-29 15:53:44 +00:00
|
|
|
, pipe_notifier_(NULL)
|
|
|
|
#endif
|
|
|
|
#if defined(Q_OS_MAC) && QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
|
|
|
|
, dock_menu_(NULL)
|
2012-08-31 22:25:51 +00:00
|
|
|
#endif
|
2012-01-04 22:13:01 +00:00
|
|
|
{
|
2014-07-09 17:50:51 +00:00
|
|
|
if (!gbl_cur_main_window_) {
|
|
|
|
connect(wsApp, SIGNAL(openStatCommandDialog(QString,const char*,void*)),
|
|
|
|
this, SLOT(openStatCommandDialog(QString,const char*,void*)));
|
2015-06-05 20:17:13 +00:00
|
|
|
connect(wsApp, SIGNAL(openTapParameterDialog(QString,const QString,void*)),
|
|
|
|
this, SLOT(openTapParameterDialog(QString,const QString,void*)));
|
2014-07-09 17:50:51 +00:00
|
|
|
}
|
|
|
|
gbl_cur_main_window_ = this;
|
2014-09-30 20:19:24 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2014-09-09 20:42:58 +00:00
|
|
|
capture_session_init(&cap_session_, CaptureFile::globalCapFile());
|
2014-09-30 20:19:24 +00:00
|
|
|
#endif
|
2016-03-31 00:24:44 +00:00
|
|
|
|
|
|
|
// setpUi calls QMetaObject::connectSlotsByName(this). connectSlotsByName
|
|
|
|
// iterates over *all* of our children, looking for matching "on_" slots.
|
|
|
|
// The fewer children we have at this point the better.
|
2012-08-17 00:58:50 +00:00
|
|
|
main_ui_->setupUi(this);
|
2016-12-13 18:33:02 +00:00
|
|
|
#ifdef HAVE_SOFTWARE_UPDATE
|
|
|
|
update_action_ = new QAction(tr("Check for Updates" UTF8_HORIZONTAL_ELLIPSIS), main_ui_->menuHelp);
|
|
|
|
#endif
|
2015-01-23 17:18:29 +00:00
|
|
|
setWindowIcon(wsApp->normalIcon());
|
2013-03-31 22:59:56 +00:00
|
|
|
setTitlebarForCaptureFile();
|
2012-08-31 22:25:51 +00:00
|
|
|
setMenusForCaptureFile();
|
2012-11-01 22:12:57 +00:00
|
|
|
setForCapturedPackets(false);
|
2012-10-01 22:40:20 +00:00
|
|
|
setMenusForFileSet(false);
|
2012-12-03 19:58:55 +00:00
|
|
|
interfaceSelectionChanged();
|
2015-02-20 18:32:15 +00:00
|
|
|
loadWindowGeometry();
|
2012-01-04 22:13:01 +00:00
|
|
|
|
2015-11-17 23:11:28 +00:00
|
|
|
#ifndef HAVE_LUA
|
|
|
|
main_ui_->actionAnalyzeReloadLuaPlugins->setVisible(false);
|
|
|
|
#endif
|
|
|
|
|
2016-06-22 19:44:02 +00:00
|
|
|
qRegisterMetaType<FilterAction::Action>("FilterAction::Action");
|
|
|
|
qRegisterMetaType<FilterAction::ActionType>("FilterAction::ActionType");
|
|
|
|
connect(this, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
|
|
|
|
this, SLOT(queuedFilterAction(QString,FilterAction::Action,FilterAction::ActionType)),
|
|
|
|
Qt::QueuedConnection);
|
|
|
|
|
2013-05-20 18:56:33 +00:00
|
|
|
//To prevent users use features before initialization complete
|
|
|
|
//Otherwise unexpected problems may occur
|
|
|
|
setFeaturesEnabled(false);
|
|
|
|
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(setFeaturesEnabled()));
|
2016-06-30 21:55:19 +00:00
|
|
|
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(applyGlobalCommandLineOptions()));
|
2014-09-23 20:35:10 +00:00
|
|
|
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(zoomText()));
|
2015-07-10 23:15:55 +00:00
|
|
|
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(initViewColorizeMenu()));
|
2015-01-06 09:22:48 +00:00
|
|
|
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addStatsPluginsToMenu()));
|
2015-07-08 22:44:04 +00:00
|
|
|
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addDynamicMenus()));
|
2017-01-24 16:34:07 +00:00
|
|
|
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addPluginIFStructures()));
|
2016-03-18 17:34:41 +00:00
|
|
|
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(initConversationMenus()));
|
2016-11-24 14:37:01 +00:00
|
|
|
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(initExportObjectsMenus()));
|
2013-05-20 18:56:33 +00:00
|
|
|
|
2015-02-19 01:18:27 +00:00
|
|
|
connect(wsApp, SIGNAL(profileChanging()), this, SLOT(saveWindowGeometry()));
|
2013-09-03 13:29:09 +00:00
|
|
|
connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(layoutPanes()));
|
2014-12-10 00:54:17 +00:00
|
|
|
connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(layoutToolbars()));
|
2015-02-20 14:30:23 +00:00
|
|
|
connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(updatePreferenceActions()));
|
2014-09-23 20:35:10 +00:00
|
|
|
connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(zoomText()));
|
2016-01-19 17:03:51 +00:00
|
|
|
connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(setTitlebarForCaptureFile()));
|
2013-09-03 13:29:09 +00:00
|
|
|
|
2015-07-08 23:48:58 +00:00
|
|
|
connect(wsApp, SIGNAL(updateRecentCaptureStatus(const QString &, qint64, bool)), this, SLOT(updateRecentCaptures()));
|
|
|
|
updateRecentCaptures();
|
2012-01-04 22:13:01 +00:00
|
|
|
|
2016-12-13 18:33:02 +00:00
|
|
|
#ifdef HAVE_SOFTWARE_UPDATE
|
|
|
|
connect(wsApp, SIGNAL(softwareUpdateRequested()), this, SLOT(softwareUpdateRequested()),
|
|
|
|
Qt::BlockingQueuedConnection);
|
|
|
|
connect(wsApp, SIGNAL(softwareUpdateClose()), this, SLOT(close()),
|
|
|
|
Qt::BlockingQueuedConnection);
|
|
|
|
#endif
|
|
|
|
|
2016-03-31 00:24:44 +00:00
|
|
|
df_combo_box_ = new DisplayFilterCombo();
|
2012-08-23 02:59:31 +00:00
|
|
|
const DisplayFilterEdit *df_edit = dynamic_cast<DisplayFilterEdit *>(df_combo_box_->lineEdit());
|
2015-03-04 23:43:33 +00:00
|
|
|
connect(df_edit, SIGNAL(pushFilterSyntaxStatus(const QString&)),
|
|
|
|
main_ui_->statusBar, SLOT(pushFilterStatus(const QString&)));
|
2012-08-23 02:59:31 +00:00
|
|
|
connect(df_edit, SIGNAL(popFilterSyntaxStatus()), main_ui_->statusBar, SLOT(popFilterStatus()));
|
2015-03-04 23:43:33 +00:00
|
|
|
connect(df_edit, SIGNAL(pushFilterSyntaxWarning(const QString&)),
|
|
|
|
main_ui_->statusBar, SLOT(pushTemporaryStatus(const QString&)));
|
2015-09-11 18:13:23 +00:00
|
|
|
connect(df_edit, SIGNAL(filterPackets(QString,bool)), this, SLOT(filterPackets(QString,bool)));
|
2015-10-27 16:52:51 +00:00
|
|
|
connect(df_edit, SIGNAL(showPreferencesDialog(PreferencesDialog::PreferencesPane)),
|
|
|
|
this, SLOT(showPreferencesDialog(PreferencesDialog::PreferencesPane)));
|
2015-09-02 21:51:33 +00:00
|
|
|
connect(wsApp, SIGNAL(preferencesChanged()), df_edit, SLOT(checkFilter()));
|
|
|
|
|
2016-03-31 00:24:44 +00:00
|
|
|
funnel_statistics_ = new FunnelStatistics(this, capture_file_);
|
2015-07-03 20:52:49 +00:00
|
|
|
connect(df_edit, SIGNAL(textChanged(QString)), funnel_statistics_, SLOT(displayFilterTextChanged(QString)));
|
|
|
|
connect(funnel_statistics_, SIGNAL(setDisplayFilter(QString)), df_edit, SLOT(setText(QString)));
|
|
|
|
connect(funnel_statistics_, SIGNAL(applyDisplayFilter()), df_combo_box_, SLOT(applyDisplayFilter()));
|
2015-09-11 18:13:23 +00:00
|
|
|
connect(funnel_statistics_, SIGNAL(openCaptureFile(QString,QString)),
|
|
|
|
this, SLOT(openCaptureFile(QString,QString)));
|
2013-02-06 18:22:54 +00:00
|
|
|
connect(this, SIGNAL(displayFilterSuccess(bool)), df_edit, SLOT(displayFilterSuccess(bool)));
|
2012-01-04 22:13:01 +00:00
|
|
|
|
2016-09-18 19:54:50 +00:00
|
|
|
file_set_dialog_ = new FileSetDialog(this);
|
|
|
|
connect(file_set_dialog_, SIGNAL(fileSetOpenCaptureFile(QString)),
|
|
|
|
this, SLOT(openCaptureFile(QString)));
|
|
|
|
|
2014-10-21 20:36:10 +00:00
|
|
|
initMainToolbarIcons();
|
2012-12-04 17:16:09 +00:00
|
|
|
|
2015-06-01 23:29:17 +00:00
|
|
|
main_ui_->displayFilterToolBar->insertWidget(main_ui_->actionDisplayFilterExpression, df_combo_box_);
|
2012-08-20 04:34:23 +00:00
|
|
|
|
2016-04-27 23:53:03 +00:00
|
|
|
// Make sure filter expressions overflow into a menu instead of a
|
|
|
|
// larger toolbar. We do this by adding them to a child toolbar.
|
|
|
|
// https://bugreports.qt.io/browse/QTBUG-2472
|
2017-06-27 14:36:19 +00:00
|
|
|
filter_expression_toolbar_ = new DragDropToolBar();
|
2016-04-27 23:53:03 +00:00
|
|
|
filter_expression_toolbar_->setStyleSheet("QToolBar { background: none; border: none; }");
|
2017-06-21 21:19:36 +00:00
|
|
|
filter_expression_toolbar_->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
|
connect(filter_expression_toolbar_, SIGNAL(customContextMenuRequested(QPoint)),
|
|
|
|
this, SLOT(filterToolbarCustomMenuHandler(QPoint)));
|
2017-06-27 14:36:19 +00:00
|
|
|
connect(filter_expression_toolbar_, SIGNAL(actionMoved(QAction*, int, int)),
|
|
|
|
this, SLOT(filterToolbarActionMoved(QAction*, int, int)));
|
2017-11-07 15:51:43 +00:00
|
|
|
connect(filter_expression_toolbar_, SIGNAL(newFilterDropped(QString, QString)),
|
|
|
|
this, SLOT(filterDropped(QString, QString)));
|
2017-06-21 21:19:36 +00:00
|
|
|
|
2016-04-27 23:53:03 +00:00
|
|
|
main_ui_->displayFilterToolBar->addWidget(filter_expression_toolbar_);
|
|
|
|
|
2015-06-11 22:05:44 +00:00
|
|
|
wireless_frame_ = new WirelessFrame(this);
|
|
|
|
main_ui_->wirelessToolBar->addWidget(wireless_frame_);
|
|
|
|
connect(wireless_frame_, SIGNAL(pushAdapterStatus(const QString&)),
|
|
|
|
main_ui_->statusBar, SLOT(pushTemporaryStatus(const QString&)));
|
|
|
|
connect (wireless_frame_, SIGNAL(showWirelessPreferences(QString)),
|
|
|
|
this, SLOT(showPreferencesDialog(QString)));
|
|
|
|
|
2012-12-15 01:04:39 +00:00
|
|
|
main_ui_->goToFrame->hide();
|
2015-07-09 17:29:21 +00:00
|
|
|
connect(main_ui_->goToFrame, SIGNAL(visibilityChanged(bool)),
|
|
|
|
main_ui_->actionGoGoToPacket, SLOT(setChecked(bool)));
|
|
|
|
|
2012-12-15 01:04:39 +00:00
|
|
|
// 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();
|
2015-03-04 23:43:33 +00:00
|
|
|
connect(main_ui_->searchFrame, SIGNAL(pushFilterSyntaxStatus(const QString&)),
|
|
|
|
main_ui_->statusBar, SLOT(pushTemporaryStatus(const QString&)));
|
2015-07-09 17:29:21 +00:00
|
|
|
connect(main_ui_->searchFrame, SIGNAL(visibilityChanged(bool)),
|
|
|
|
main_ui_->actionEditFindPacket, SLOT(setChecked(bool)));
|
2012-12-04 17:16:09 +00:00
|
|
|
|
2015-07-21 16:51:12 +00:00
|
|
|
main_ui_->addressEditorFrame->hide();
|
2015-01-01 19:41:03 +00:00
|
|
|
main_ui_->columnEditorFrame->hide();
|
2017-09-17 16:57:25 +00:00
|
|
|
connect(main_ui_->columnEditorFrame, SIGNAL(pushFilterSyntaxStatus(const QString&)),
|
|
|
|
main_ui_->statusBar, SLOT(pushTemporaryStatus(const QString&)));
|
2015-06-17 15:41:41 +00:00
|
|
|
main_ui_->preferenceEditorFrame->hide();
|
2017-09-18 17:20:50 +00:00
|
|
|
connect(main_ui_->preferenceEditorFrame, SIGNAL(pushFilterSyntaxStatus(const QString&)),
|
|
|
|
main_ui_->statusBar, SLOT(pushTemporaryStatus(const QString&)));
|
2015-10-28 21:41:59 +00:00
|
|
|
main_ui_->filterExpressionFrame->hide();
|
2017-09-18 18:24:20 +00:00
|
|
|
connect(main_ui_->filterExpressionFrame, SIGNAL(pushFilterSyntaxStatus(const QString&)),
|
|
|
|
main_ui_->statusBar, SLOT(pushTemporaryStatus(const QString&)));
|
2015-01-01 19:41:03 +00:00
|
|
|
|
2013-10-11 21:26:26 +00:00
|
|
|
#ifndef HAVE_LIBPCAP
|
|
|
|
main_ui_->menuCapture->setEnabled(false);
|
|
|
|
#endif
|
|
|
|
|
2016-10-19 18:53:40 +00:00
|
|
|
// Set OS specific shortcuts for fullscreen mode
|
|
|
|
#if defined(Q_OS_MAC) && QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
|
|
|
main_ui_->actionViewFullScreen->setShortcut(QKeySequence::FullScreen);
|
|
|
|
#else
|
|
|
|
main_ui_->actionViewFullScreen->setShortcut(QKeySequence(Qt::Key_F11));
|
|
|
|
#endif
|
|
|
|
|
2013-04-24 11:07:25 +00:00
|
|
|
#if defined(Q_OS_MAC)
|
2014-02-11 19:45:30 +00:00
|
|
|
#if defined(QT_MACEXTRAS_LIB) && QT_VERSION < QT_VERSION_CHECK(5, 2, 1)
|
2013-06-13 18:58:29 +00:00
|
|
|
QMacNativeToolBar *ntb = QtMacExtras::setNativeToolBar(main_ui_->mainToolBar);
|
|
|
|
ntb->setIconSize(QSize(24, 24));
|
2013-07-15 20:17:17 +00:00
|
|
|
#endif // QT_MACEXTRAS_LIB
|
2013-06-10 21:21:51 +00:00
|
|
|
|
2016-02-18 19:48:23 +00:00
|
|
|
main_ui_->goToPacketLabel->setAttribute(Qt::WA_MacSmallSize, true);
|
2012-08-21 03:07:39 +00:00
|
|
|
main_ui_->goToLineEdit->setAttribute(Qt::WA_MacSmallSize, true);
|
|
|
|
main_ui_->goToGo->setAttribute(Qt::WA_MacSmallSize, true);
|
|
|
|
main_ui_->goToCancel->setAttribute(Qt::WA_MacSmallSize, true);
|
2013-06-10 21:21:51 +00:00
|
|
|
|
2013-07-15 20:17:17 +00:00
|
|
|
main_ui_->actionEditPreferences->setMenuRole(QAction::PreferencesRole);
|
|
|
|
|
2013-06-10 21:21:51 +00:00
|
|
|
#endif // Q_OS_MAC
|
2012-08-20 04:34:23 +00:00
|
|
|
|
2013-03-06 22:04:17 +00:00
|
|
|
#ifdef HAVE_SOFTWARE_UPDATE
|
|
|
|
QAction *update_sep = main_ui_->menuHelp->insertSeparator(main_ui_->actionHelpAbout);
|
2016-12-13 18:33:02 +00:00
|
|
|
main_ui_->menuHelp->insertAction(update_sep, update_action_);
|
|
|
|
connect(update_action_, SIGNAL(triggered()), this, SLOT(checkForUpdates()));
|
2013-03-06 22:04:17 +00:00
|
|
|
#endif
|
2015-10-04 18:35:13 +00:00
|
|
|
master_split_.setObjectName("splitterMaster");
|
|
|
|
extra_split_.setObjectName("splitterExtra");
|
2013-10-14 16:54:41 +00:00
|
|
|
main_ui_->mainStack->addWidget(&master_split_);
|
2013-03-06 22:04:17 +00:00
|
|
|
|
2015-10-04 18:35:13 +00:00
|
|
|
empty_pane_.setObjectName("emptyPane");
|
2013-09-03 12:53:32 +00:00
|
|
|
|
2013-10-05 22:39:49 +00:00
|
|
|
packet_list_ = new PacketList(&master_split_);
|
2017-06-19 20:28:10 +00:00
|
|
|
main_ui_->wirelessTimelineWidget->setPacketList(packet_list_);
|
2017-10-30 12:58:28 +00:00
|
|
|
connect(packet_list_, SIGNAL(fieldSelected(FieldInformation *)),
|
|
|
|
this, SIGNAL(fieldSelected(FieldInformation *)));
|
2017-11-12 10:29:13 +00:00
|
|
|
connect(packet_list_, SIGNAL(frameSelected(int)),
|
|
|
|
this, SIGNAL(frameSelected(int)));
|
2017-11-19 16:43:02 +00:00
|
|
|
connect(this, SIGNAL(frameSelected(int)),
|
|
|
|
this, SLOT(setMenusForSelectedPacket()));
|
2017-07-25 23:07:04 +00:00
|
|
|
connect(packet_list_->packetListModel(), SIGNAL(bgColorizationProgress(int,int)),
|
|
|
|
main_ui_->wirelessTimelineWidget, SLOT(bgColorizationProgress(int,int)));
|
2013-10-05 22:39:49 +00:00
|
|
|
|
|
|
|
proto_tree_ = new ProtoTree(&master_split_);
|
2013-09-03 12:53:32 +00:00
|
|
|
proto_tree_->installEventFilter(this);
|
|
|
|
|
|
|
|
packet_list_->setProtoTree(proto_tree_);
|
|
|
|
packet_list_->installEventFilter(this);
|
|
|
|
|
2012-08-17 19:37:18 +00:00
|
|
|
main_welcome_ = main_ui_->welcomePage;
|
2012-08-31 22:25:51 +00:00
|
|
|
|
2017-10-30 12:58:28 +00:00
|
|
|
connect(proto_tree_, SIGNAL(fieldSelected(FieldInformation *)),
|
|
|
|
this, SIGNAL(fieldSelected(FieldInformation *)));
|
|
|
|
connect(this, SIGNAL(fieldSelected(FieldInformation *)),
|
|
|
|
proto_tree_, SLOT(selectedFieldChanged(FieldInformation *)));
|
|
|
|
connect(this, SIGNAL(fieldHighlight(FieldInformation *)),
|
|
|
|
main_ui_->statusBar, SLOT(highlightedFieldChanged(FieldInformation *)));
|
|
|
|
connect(this, SIGNAL(fieldSelected(FieldInformation *)),
|
|
|
|
main_ui_->statusBar, SLOT(selectedFieldChanged(FieldInformation *)));
|
2017-11-17 13:39:03 +00:00
|
|
|
connect(wsApp, SIGNAL(captureActive(int)), this, SIGNAL(captureActive(int)));
|
2017-10-30 12:58:28 +00:00
|
|
|
|
|
|
|
createByteViewDialog();
|
|
|
|
|
2015-07-29 19:09:28 +00:00
|
|
|
// Packet list and proto tree must exist before these are called.
|
|
|
|
setMenusForSelectedPacket();
|
|
|
|
setMenusForSelectedTreeRow();
|
|
|
|
|
2014-10-22 17:05:35 +00:00
|
|
|
initShowHideMainWidgets();
|
2014-10-21 20:36:10 +00:00
|
|
|
initTimeDisplayFormatMenu();
|
|
|
|
initTimePrecisionFormatMenu();
|
2015-11-10 18:12:56 +00:00
|
|
|
initFreezeActions();
|
2015-02-20 14:30:23 +00:00
|
|
|
updatePreferenceActions();
|
2015-12-03 09:22:23 +00:00
|
|
|
updateRecentActions();
|
2015-02-20 14:30:23 +00:00
|
|
|
setForCaptureInProgress(false);
|
2014-10-21 20:36:10 +00:00
|
|
|
|
2016-06-12 23:07:30 +00:00
|
|
|
setTabOrder(df_combo_box_->lineEdit(), packet_list_);
|
|
|
|
setTabOrder(packet_list_, proto_tree_);
|
2015-09-01 14:37:45 +00:00
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureCapturePrepared(capture_session *)),
|
2013-05-22 08:47:17 +00:00
|
|
|
this, SLOT(captureCapturePrepared(capture_session *)));
|
2014-09-09 20:42:58 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureUpdateStarted(capture_session *)),
|
2013-05-22 08:47:17 +00:00
|
|
|
this, SLOT(captureCaptureUpdateStarted(capture_session *)));
|
2014-09-09 20:42:58 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureUpdateFinished(capture_session *)),
|
2013-05-22 08:47:17 +00:00
|
|
|
this, SLOT(captureCaptureUpdateFinished(capture_session *)));
|
2014-09-09 20:42:58 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureFixedStarted(capture_session *)),
|
2013-05-22 08:47:17 +00:00
|
|
|
this, SLOT(captureCaptureFixedStarted(capture_session *)));
|
2015-04-06 21:56:17 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureFixedContinue(capture_session *)),
|
|
|
|
main_ui_->statusBar, SLOT(updateCaptureFixedStatistics(capture_session*)));
|
2014-09-09 20:42:58 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureFixedFinished(capture_session *)),
|
2013-05-22 08:47:17 +00:00
|
|
|
this, SLOT(captureCaptureFixedFinished(capture_session *)));
|
2014-09-09 20:42:58 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureStopping(capture_session *)),
|
2013-05-22 08:47:17 +00:00
|
|
|
this, SLOT(captureCaptureStopping(capture_session *)));
|
2014-09-09 20:42:58 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureFailed(capture_session *)),
|
2013-05-22 08:47:17 +00:00
|
|
|
this, SLOT(captureCaptureFailed(capture_session *)));
|
2014-12-22 00:41:49 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureUpdateContinue(capture_session*)),
|
|
|
|
main_ui_->statusBar, SLOT(updateCaptureStatistics(capture_session*)));
|
2012-01-14 00:16:16 +00:00
|
|
|
|
2015-10-03 16:45:16 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureUpdateStarted(capture_session *)),
|
|
|
|
wsApp, SLOT(captureStarted()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureUpdateFinished(capture_session *)),
|
|
|
|
wsApp, SLOT(captureFinished()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureFixedStarted(capture_session *)),
|
|
|
|
wsApp, SLOT(captureStarted()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureCaptureFixedFinished(capture_session *)),
|
|
|
|
wsApp, SLOT(captureFinished()));
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureFileOpened()),
|
|
|
|
this, SLOT(captureFileOpened()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileReadStarted()),
|
|
|
|
this, SLOT(captureFileReadStarted()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileReadFinished()),
|
|
|
|
this, SLOT(captureFileReadFinished()));
|
2015-05-22 22:33:38 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureFileReloadStarted()),
|
|
|
|
this, SLOT(captureFileReloadStarted()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileReloadFinished()),
|
|
|
|
this, SLOT(captureFileReadFinished()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileRescanStarted()),
|
|
|
|
this, SLOT(captureFileRescanStarted()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileRescanFinished()),
|
|
|
|
this, SLOT(captureFileReadFinished()));
|
2015-08-26 19:48:56 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureFileRetapStarted()),
|
|
|
|
this, SLOT(captureFileRetapStarted()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileRetapFinished()),
|
|
|
|
this, SLOT(captureFileRetapFinished()));
|
2017-01-21 00:05:56 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureFileMergeStarted()),
|
|
|
|
this, SLOT(captureFileMergeStarted()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileMergeFinished()),
|
|
|
|
this, SLOT(captureFileMergeFinished()));
|
2015-12-06 21:29:53 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureFileFlushTapsData()),
|
|
|
|
this, SLOT(captureFileFlushTapsData()));
|
2014-09-09 20:42:58 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureFileClosing()),
|
|
|
|
this, SLOT(captureFileClosing()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileClosed()),
|
|
|
|
this, SLOT(captureFileClosed()));
|
|
|
|
|
2015-05-22 22:33:38 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureFileSaveStarted(QString)),
|
|
|
|
this, SLOT(captureFileSaveStarted(QString)));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileSaveFinished()),
|
|
|
|
main_ui_->statusBar, SLOT(popFileStatus()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileSaveFailed()),
|
|
|
|
main_ui_->statusBar, SLOT(popFileStatus()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileSaveStopped()),
|
|
|
|
main_ui_->statusBar, SLOT(popFileStatus()));
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
connect(&capture_file_, SIGNAL(captureFileReadStarted()),
|
|
|
|
wsApp, SLOT(captureFileReadStarted()));
|
|
|
|
connect(&capture_file_, SIGNAL(captureFileReadFinished()),
|
|
|
|
wsApp, SLOT(updateTaps()));
|
|
|
|
|
2015-05-13 22:46:51 +00:00
|
|
|
connect(wsApp, SIGNAL(columnsChanged()),
|
2015-07-09 23:47:11 +00:00
|
|
|
packet_list_, SLOT(columnsChanged()));
|
2015-08-06 19:31:21 +00:00
|
|
|
connect(wsApp, SIGNAL(preferencesChanged()),
|
2015-10-27 22:04:44 +00:00
|
|
|
packet_list_, SLOT(preferencesChanged()));
|
2015-07-08 23:48:58 +00:00
|
|
|
connect(wsApp, SIGNAL(recentPreferencesRead()),
|
2015-02-19 01:18:27 +00:00
|
|
|
this, SLOT(applyRecentPaneGeometry()));
|
2015-07-08 23:48:58 +00:00
|
|
|
connect(wsApp, SIGNAL(recentPreferencesRead()),
|
2015-12-03 09:22:23 +00:00
|
|
|
this, SLOT(updateRecentActions()));
|
2013-01-18 00:50:14 +00:00
|
|
|
connect(wsApp, SIGNAL(packetDissectionChanged()),
|
2016-01-08 19:43:19 +00:00
|
|
|
this, SLOT(redissectPackets()), Qt::QueuedConnection);
|
2013-02-06 18:22:54 +00:00
|
|
|
connect(wsApp, SIGNAL(appInitialized()),
|
|
|
|
this, SLOT(filterExpressionsChanged()));
|
|
|
|
connect(wsApp, SIGNAL(filterExpressionsChanged()),
|
|
|
|
this, SLOT(filterExpressionsChanged()));
|
2015-12-02 21:15:28 +00:00
|
|
|
connect(wsApp, SIGNAL(checkDisplayFilter()),
|
|
|
|
this, SLOT(checkDisplayFilter()));
|
2014-11-06 10:19:25 +00:00
|
|
|
connect(wsApp, SIGNAL(fieldsChanged()),
|
|
|
|
this, SLOT(fieldsChanged()));
|
2016-01-03 12:48:39 +00:00
|
|
|
connect(wsApp, SIGNAL(reloadLuaPlugins()),
|
|
|
|
this, SLOT(reloadLuaPlugins()));
|
2012-01-14 00:16:16 +00:00
|
|
|
|
2015-09-06 19:00:48 +00:00
|
|
|
connect(main_ui_->mainStack, SIGNAL(currentChanged(int)),
|
|
|
|
this, SLOT(mainStackChanged(int)));
|
|
|
|
|
2012-12-03 19:58:55 +00:00
|
|
|
connect(main_welcome_, SIGNAL(startCapture()),
|
|
|
|
this, SLOT(startCapture()));
|
2015-09-11 18:13:23 +00:00
|
|
|
connect(main_welcome_, SIGNAL(recentFileActivated(QString)),
|
|
|
|
this, SLOT(openCaptureFile(QString)));
|
2015-03-04 23:43:33 +00:00
|
|
|
connect(main_welcome_, SIGNAL(pushFilterSyntaxStatus(const QString&)),
|
|
|
|
main_ui_->statusBar, SLOT(pushFilterStatus(const QString&)));
|
2013-08-08 00:26:57 +00:00
|
|
|
connect(main_welcome_, SIGNAL(popFilterSyntaxStatus()),
|
|
|
|
main_ui_->statusBar, SLOT(popFilterStatus()));
|
2012-08-31 22:25:51 +00:00
|
|
|
|
2015-07-21 16:51:12 +00:00
|
|
|
connect(main_ui_->addressEditorFrame, SIGNAL(editAddressStatus(QString)),
|
|
|
|
main_ui_->statusBar, SLOT(pushTemporaryStatus(QString)));
|
|
|
|
connect(main_ui_->addressEditorFrame, SIGNAL(redissectPackets()),
|
|
|
|
this, SLOT(redissectPackets()));
|
|
|
|
connect(main_ui_->addressEditorFrame, SIGNAL(showNameResolutionPreferences(QString)),
|
|
|
|
this, SLOT(showPreferencesDialog(QString)));
|
2015-06-17 15:41:41 +00:00
|
|
|
connect(main_ui_->preferenceEditorFrame, SIGNAL(showProtocolPreferences(QString)),
|
|
|
|
this, SLOT(showPreferencesDialog(QString)));
|
2015-10-28 21:41:59 +00:00
|
|
|
connect(main_ui_->filterExpressionFrame, SIGNAL(showPreferencesDialog(PreferencesDialog::PreferencesPane)),
|
|
|
|
this, SLOT(showPreferencesDialog(PreferencesDialog::PreferencesPane)));
|
|
|
|
connect(main_ui_->filterExpressionFrame, SIGNAL(filterExpressionsChanged()),
|
|
|
|
this, SLOT(filterExpressionsChanged()));
|
2015-06-17 15:41:41 +00:00
|
|
|
|
2017-10-30 12:58:28 +00:00
|
|
|
/* Connect change of capture file */
|
2012-12-15 01:04:39 +00:00
|
|
|
connect(this, SIGNAL(setCaptureFile(capture_file*)),
|
|
|
|
main_ui_->searchFrame, SLOT(setCaptureFile(capture_file*)));
|
2012-12-03 19:58:55 +00:00
|
|
|
connect(this, SIGNAL(setCaptureFile(capture_file*)),
|
|
|
|
main_ui_->statusBar, SLOT(setCaptureFile(capture_file*)));
|
2012-10-30 19:21:24 +00:00
|
|
|
connect(this, SIGNAL(setCaptureFile(capture_file*)),
|
|
|
|
packet_list_, SLOT(setCaptureFile(capture_file*)));
|
2017-11-07 15:51:43 +00:00
|
|
|
connect(this, SIGNAL(setCaptureFile(capture_file*)),
|
|
|
|
proto_tree_, SLOT(setCaptureFile(capture_file*)));
|
2017-11-12 10:29:13 +00:00
|
|
|
connect(this, SIGNAL(frameSelected(int)),
|
|
|
|
main_ui_->wirelessTimelineWidget, SLOT(selectedFrameChanged(int)));
|
|
|
|
connect(this, SIGNAL(frameSelected(int)),
|
|
|
|
main_ui_->statusBar, SLOT(selectedFrameChanged(int)));
|
2012-10-30 19:21:24 +00:00
|
|
|
|
2017-10-30 12:58:28 +00:00
|
|
|
connect(wsApp, SIGNAL(zoomMonospaceFont(QFont)),
|
2014-09-23 20:35:10 +00:00
|
|
|
packet_list_, SLOT(setMonospaceFont(QFont)));
|
2017-10-30 12:58:28 +00:00
|
|
|
connect(wsApp, SIGNAL(zoomMonospaceFont(QFont)),
|
2014-09-23 20:35:10 +00:00
|
|
|
proto_tree_, SLOT(setMonospaceFont(QFont)));
|
|
|
|
|
2012-08-17 00:58:50 +00:00
|
|
|
connect(main_ui_->actionGoNextPacket, SIGNAL(triggered()),
|
|
|
|
packet_list_, SLOT(goNextPacket()));
|
|
|
|
connect(main_ui_->actionGoPreviousPacket, SIGNAL(triggered()),
|
|
|
|
packet_list_, SLOT(goPreviousPacket()));
|
|
|
|
connect(main_ui_->actionGoFirstPacket, SIGNAL(triggered()),
|
|
|
|
packet_list_, SLOT(goFirstPacket()));
|
|
|
|
connect(main_ui_->actionGoLastPacket, SIGNAL(triggered()),
|
|
|
|
packet_list_, SLOT(goLastPacket()));
|
2017-03-01 16:03:17 +00:00
|
|
|
connect(main_ui_->actionGoNextHistoryPacket, SIGNAL(triggered()),
|
|
|
|
packet_list_, SLOT(goNextHistoryPacket()));
|
|
|
|
connect(main_ui_->actionGoPreviousHistoryPacket, SIGNAL(triggered()),
|
|
|
|
packet_list_, SLOT(goPreviousHistoryPacket()));
|
2012-08-14 04:12:56 +00:00
|
|
|
|
2012-08-17 00:58:50 +00:00
|
|
|
connect(main_ui_->actionViewExpandSubtrees, SIGNAL(triggered()),
|
2012-12-07 01:46:20 +00:00
|
|
|
proto_tree_, SLOT(expandSubtrees()));
|
2012-08-17 00:58:50 +00:00
|
|
|
connect(main_ui_->actionViewExpandAll, SIGNAL(triggered()),
|
2012-12-07 01:46:20 +00:00
|
|
|
proto_tree_, SLOT(expandAll()));
|
2012-08-17 00:58:50 +00:00
|
|
|
connect(main_ui_->actionViewCollapseAll, SIGNAL(triggered()),
|
2012-12-07 01:46:20 +00:00
|
|
|
proto_tree_, SLOT(collapseAll()));
|
2012-08-14 04:12:56 +00:00
|
|
|
|
2017-11-12 10:29:13 +00:00
|
|
|
connect(packet_list_, SIGNAL(frameSelected(int)),
|
|
|
|
this, SIGNAL(frameSelected(int)));
|
2013-01-18 00:50:14 +00:00
|
|
|
connect(packet_list_, SIGNAL(packetDissectionChanged()),
|
2012-12-17 23:03:21 +00:00
|
|
|
this, SLOT(redissectPackets()));
|
2015-06-17 00:24:19 +00:00
|
|
|
connect(packet_list_, SIGNAL(showColumnPreferences(PreferencesDialog::PreferencesPane)),
|
2015-01-01 19:41:03 +00:00
|
|
|
this, SLOT(showPreferencesDialog(PreferencesDialog::PreferencesPane)));
|
2015-06-17 00:24:19 +00:00
|
|
|
connect(packet_list_, SIGNAL(showProtocolPreferences(QString)),
|
|
|
|
this, SLOT(showPreferencesDialog(QString)));
|
2015-06-17 15:41:41 +00:00
|
|
|
connect(packet_list_, SIGNAL(editProtocolPreference(preference*,pref_module*)),
|
|
|
|
main_ui_->preferenceEditorFrame, SLOT(editPreference(preference*,pref_module*)));
|
2015-01-01 19:41:03 +00:00
|
|
|
connect(packet_list_, SIGNAL(editColumn(int)), this, SLOT(showColumnEditor(int)));
|
|
|
|
connect(main_ui_->columnEditorFrame, SIGNAL(columnEdited()),
|
2015-09-12 12:06:12 +00:00
|
|
|
packet_list_, SLOT(columnsChanged()));
|
2015-02-13 03:00:59 +00:00
|
|
|
connect(packet_list_, SIGNAL(doubleClicked(QModelIndex)),
|
|
|
|
this, SLOT(openPacketDialog()));
|
2015-02-20 14:30:23 +00:00
|
|
|
connect(packet_list_, SIGNAL(packetListScrolled(bool)),
|
|
|
|
main_ui_->actionGoAutoScroll, SLOT(setChecked(bool)));
|
2015-07-17 22:06:55 +00:00
|
|
|
connect(packet_list_->packetListModel(), SIGNAL(pushBusyStatus(QString)),
|
|
|
|
main_ui_->statusBar, SLOT(pushBusyStatus(QString)));
|
|
|
|
connect(packet_list_->packetListModel(), SIGNAL(popBusyStatus()),
|
|
|
|
main_ui_->statusBar, SLOT(popBusyStatus()));
|
2015-08-27 00:14:39 +00:00
|
|
|
connect(packet_list_->packetListModel(), SIGNAL(pushProgressStatus(QString,bool,bool,gboolean*)),
|
|
|
|
main_ui_->statusBar, SLOT(pushProgressStatus(QString,bool,bool,gboolean*)));
|
|
|
|
connect(packet_list_->packetListModel(), SIGNAL(updateProgressStatus(int)),
|
|
|
|
main_ui_->statusBar, SLOT(updateProgressStatus(int)));
|
|
|
|
connect(packet_list_->packetListModel(), SIGNAL(popProgressStatus()),
|
|
|
|
main_ui_->statusBar, SLOT(popProgressStatus()));
|
2012-12-17 23:03:21 +00:00
|
|
|
|
2017-10-30 12:58:28 +00:00
|
|
|
connect(proto_tree_, SIGNAL(fieldSelected(FieldInformation *)),
|
|
|
|
this, SIGNAL(fieldSelected(FieldInformation *)));
|
|
|
|
connect(this, SIGNAL(fieldSelected(FieldInformation *)),
|
|
|
|
main_ui_->statusBar, SLOT(selectedFieldChanged(FieldInformation *)));
|
|
|
|
connect(this, SIGNAL(fieldSelected(FieldInformation *)),
|
|
|
|
this, SLOT(setMenusForSelectedTreeRow(FieldInformation *)));
|
2015-02-13 16:36:53 +00:00
|
|
|
connect(proto_tree_, SIGNAL(openPacketInNewWindow(bool)),
|
|
|
|
this, SLOT(openPacketDialog(bool)));
|
2015-06-17 00:24:19 +00:00
|
|
|
connect(proto_tree_, SIGNAL(showProtocolPreferences(QString)),
|
|
|
|
this, SLOT(showPreferencesDialog(QString)));
|
2015-06-17 15:41:41 +00:00
|
|
|
connect(proto_tree_, SIGNAL(editProtocolPreference(preference*,pref_module*)),
|
|
|
|
main_ui_->preferenceEditorFrame, SLOT(editPreference(preference*,pref_module*)));
|
2012-01-04 22:13:01 +00:00
|
|
|
|
2015-03-11 22:22:20 +00:00
|
|
|
connect(main_ui_->statusBar, SIGNAL(showExpertInfo()),
|
|
|
|
this, SLOT(on_actionAnalyzeExpertInfo_triggered()));
|
|
|
|
|
2015-06-19 23:56:44 +00:00
|
|
|
connect(main_ui_->statusBar, SIGNAL(stopLoading()),
|
|
|
|
&capture_file_, SLOT(stopLoading()));
|
|
|
|
|
2014-11-12 22:24:16 +00:00
|
|
|
connect(main_ui_->statusBar, SIGNAL(editCaptureComment()),
|
|
|
|
this, SLOT(on_actionStatisticsCaptureFileProperties_triggered()));
|
|
|
|
|
2013-11-25 21:50:58 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2012-12-03 19:58:55 +00:00
|
|
|
QTreeWidget *iface_tree = findChild<QTreeWidget *>("interfaceTree");
|
|
|
|
if (iface_tree) {
|
|
|
|
connect(iface_tree, SIGNAL(itemSelectionChanged()),
|
|
|
|
this, SLOT(interfaceSelectionChanged()));
|
|
|
|
}
|
2013-08-08 00:26:57 +00:00
|
|
|
connect(main_ui_->welcomePage, SIGNAL(captureFilterSyntaxChanged(bool)),
|
|
|
|
this, SLOT(captureFilterSyntaxChanged(bool)));
|
|
|
|
|
2016-03-18 17:31:09 +00:00
|
|
|
#ifdef HAVE_EXTCAP
|
2015-04-28 08:26:46 +00:00
|
|
|
connect(this->main_welcome_, SIGNAL(showExtcapOptions(QString&)),
|
|
|
|
this, SLOT(showExtcapOptionsDialog(QString&)));
|
|
|
|
#endif
|
|
|
|
|
2016-03-31 00:24:44 +00:00
|
|
|
#endif // HAVE_LIBPCAP
|
2013-11-25 14:15:49 +00:00
|
|
|
|
2015-06-05 09:19:37 +00:00
|
|
|
/* Create plugin_if hooks */
|
2016-01-23 12:18:30 +00:00
|
|
|
plugin_if_register_gui_cb(PLUGIN_IF_FILTER_ACTION_APPLY, plugin_if_mainwindow_apply_filter);
|
|
|
|
plugin_if_register_gui_cb(PLUGIN_IF_FILTER_ACTION_PREPARE, plugin_if_mainwindow_apply_filter);
|
2015-06-05 09:19:37 +00:00
|
|
|
plugin_if_register_gui_cb(PLUGIN_IF_PREFERENCE_SAVE, plugin_if_mainwindow_preference);
|
2015-08-09 12:36:53 +00:00
|
|
|
plugin_if_register_gui_cb(PLUGIN_IF_GOTO_FRAME, plugin_if_mainwindow_gotoframe);
|
2016-01-07 07:39:14 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
plugin_if_register_gui_cb(PLUGIN_IF_GET_WS_INFO, plugin_if_mainwindow_get_ws_info);
|
|
|
|
#endif
|
2017-01-24 16:34:07 +00:00
|
|
|
plugin_if_register_gui_cb(PLUGIN_IF_REMOVE_TOOLBAR, plugin_if_mainwindow_update_toolbars);
|
2015-06-05 09:19:37 +00:00
|
|
|
|
2017-08-25 09:28:34 +00:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
|
2017-04-15 21:30:30 +00:00
|
|
|
// Register Interface Toolbar callbacks
|
|
|
|
//
|
|
|
|
// Qt version must be 5.2 or higher because the use of
|
|
|
|
// QThread::requestInterruption() in interface_toolbar.cpp and
|
|
|
|
// QThread::isInterruptionRequested() in interface_toolbar_reader.cpp
|
|
|
|
iface_toolbar_register_cb(mainwindow_add_toolbar, mainwindow_remove_toolbar);
|
|
|
|
#endif
|
|
|
|
|
2012-08-17 00:58:50 +00:00
|
|
|
main_ui_->mainStack->setCurrentWidget(main_welcome_);
|
2012-01-04 22:13:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MainWindow::~MainWindow()
|
|
|
|
{
|
2017-09-25 21:18:31 +00:00
|
|
|
disconnect(main_ui_->mainStack, 0, 0, 0);
|
|
|
|
|
|
|
|
#ifndef Q_OS_MAC
|
2017-09-26 11:14:02 +00:00
|
|
|
// Below dialogs inherit GeometryStateDialog
|
2017-09-25 21:18:31 +00:00
|
|
|
// For reasons described in geometry_state_dialog.h no parent is set when
|
2017-09-26 11:14:02 +00:00
|
|
|
// instantiating the dialogs and as a resul objects are not automatically
|
|
|
|
// freed by its parent. Free then here explicitly to avoid leak and numerous
|
2017-09-25 21:18:31 +00:00
|
|
|
// Valgrind complaints.
|
|
|
|
delete file_set_dialog_;
|
2017-09-26 11:14:02 +00:00
|
|
|
delete capture_filter_dlg_;
|
|
|
|
delete display_filter_dlg_;
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
delete capture_interfaces_dialog_;
|
|
|
|
#endif
|
|
|
|
|
2017-09-25 21:18:31 +00:00
|
|
|
#endif
|
2012-08-17 00:58:50 +00:00
|
|
|
delete main_ui_;
|
2012-01-04 22:13:01 +00:00
|
|
|
}
|
|
|
|
|
2013-09-09 19:30:30 +00:00
|
|
|
QString MainWindow::getFilter()
|
|
|
|
{
|
2016-01-08 13:25:17 +00:00
|
|
|
return df_combo_box_->currentText();
|
2013-09-09 19:30:30 +00:00
|
|
|
}
|
|
|
|
|
2015-06-17 03:51:44 +00:00
|
|
|
QMenu *MainWindow::createPopupMenu()
|
|
|
|
{
|
|
|
|
QMenu *menu = new QMenu();
|
|
|
|
menu->addAction(main_ui_->actionViewMainToolbar);
|
|
|
|
menu->addAction(main_ui_->actionViewFilterToolbar);
|
|
|
|
menu->addAction(main_ui_->actionViewWirelessToolbar);
|
2017-01-24 16:34:07 +00:00
|
|
|
|
2017-04-15 21:30:30 +00:00
|
|
|
if (!main_ui_->menuInterfaceToolbars->actions().isEmpty()) {
|
|
|
|
QMenu *submenu = menu->addMenu(main_ui_->menuInterfaceToolbars->title());
|
|
|
|
foreach (QAction *action, main_ui_->menuInterfaceToolbars->actions()) {
|
|
|
|
submenu->addAction(action);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-18 08:03:00 +00:00
|
|
|
if (!main_ui_->menuAdditionalToolbars->actions().isEmpty()) {
|
|
|
|
QMenu *subMenu = menu->addMenu(main_ui_->menuAdditionalToolbars->title());
|
|
|
|
foreach (QAction *action, main_ui_->menuAdditionalToolbars->actions()) {
|
2017-01-24 16:34:07 +00:00
|
|
|
subMenu->addAction(action);
|
2017-02-24 08:49:11 +00:00
|
|
|
}
|
2017-01-24 16:34:07 +00:00
|
|
|
}
|
|
|
|
|
2015-06-17 03:51:44 +00:00
|
|
|
menu->addAction(main_ui_->actionViewStatusBar);
|
2017-01-24 16:34:07 +00:00
|
|
|
|
2015-06-17 03:51:44 +00:00
|
|
|
menu->addSeparator();
|
|
|
|
menu->addAction(main_ui_->actionViewPacketList);
|
|
|
|
menu->addAction(main_ui_->actionViewPacketDetails);
|
|
|
|
menu->addAction(main_ui_->actionViewPacketBytes);
|
|
|
|
return menu;
|
|
|
|
}
|
|
|
|
|
2017-04-15 21:30:30 +00:00
|
|
|
void MainWindow::addInterfaceToolbar(const iface_toolbar *toolbar_entry)
|
|
|
|
{
|
|
|
|
QMenu *menu = main_ui_->menuInterfaceToolbars;
|
|
|
|
bool visible = g_list_find_custom(recent.interface_toolbars, toolbar_entry->menu_title, (GCompareFunc) strcmp) ? true : false;
|
|
|
|
|
|
|
|
QString title = QString().fromUtf8(toolbar_entry->menu_title);
|
|
|
|
QAction *action = new QAction(title, menu);
|
|
|
|
action->setEnabled(true);
|
|
|
|
action->setCheckable(true);
|
|
|
|
action->setChecked(visible);
|
|
|
|
action->setToolTip(tr("Show or hide the toolbar"));
|
|
|
|
|
|
|
|
QAction *before = NULL;
|
|
|
|
foreach (QAction *action, menu->actions()) {
|
|
|
|
// Ensure we add the menu entries in sorted order
|
|
|
|
if (action->text().compare(title, Qt::CaseInsensitive) > 0) {
|
|
|
|
before = action;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
menu->insertAction(before, action);
|
|
|
|
|
|
|
|
InterfaceToolbar *interface_toolbar = new InterfaceToolbar(this, toolbar_entry);
|
2017-04-28 19:26:53 +00:00
|
|
|
connect(wsApp, SIGNAL(appInitialized()), interface_toolbar, SLOT(interfaceListChanged()));
|
|
|
|
connect(wsApp, SIGNAL(localInterfaceListChanged()), interface_toolbar, SLOT(interfaceListChanged()));
|
2017-04-15 21:30:30 +00:00
|
|
|
|
|
|
|
QToolBar *toolbar = new QToolBar(this);
|
|
|
|
toolbar->addWidget(interface_toolbar);
|
|
|
|
toolbar->setMovable(false);
|
|
|
|
toolbar->setVisible(visible);
|
|
|
|
|
|
|
|
action->setData(qVariantFromValue(toolbar));
|
|
|
|
|
|
|
|
addToolBar(Qt::TopToolBarArea, toolbar);
|
|
|
|
insertToolBarBreak(toolbar);
|
|
|
|
|
|
|
|
if (show_hide_actions_) {
|
|
|
|
show_hide_actions_->addAction(action);
|
|
|
|
}
|
|
|
|
|
|
|
|
menu->menuAction()->setVisible(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::removeInterfaceToolbar(const gchar *menu_title)
|
|
|
|
{
|
|
|
|
QMenu *menu = main_ui_->menuInterfaceToolbars;
|
|
|
|
QAction *action = NULL;
|
|
|
|
QMap<QAction *, QWidget *>::iterator i;
|
|
|
|
|
|
|
|
QString title = QString().fromUtf8(menu_title);
|
|
|
|
foreach (action, menu->actions()) {
|
|
|
|
if (title.compare(action->text()) == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action) {
|
|
|
|
if (show_hide_actions_) {
|
|
|
|
show_hide_actions_->removeAction(action);
|
|
|
|
}
|
|
|
|
menu->removeAction(action);
|
|
|
|
|
|
|
|
QToolBar *toolbar = action->data().value<QToolBar *>();
|
|
|
|
removeToolBar(toolbar);
|
|
|
|
|
|
|
|
delete action;
|
|
|
|
delete toolbar;
|
|
|
|
}
|
|
|
|
|
|
|
|
menu->menuAction()->setVisible(!menu->actions().isEmpty());
|
|
|
|
}
|
|
|
|
|
2015-06-10 00:30:15 +00:00
|
|
|
void MainWindow::setPipeInputHandler(gint source, gpointer user_data, ws_process_id *child_process, pipe_input_cb_t input_cb)
|
2012-08-31 22:25:51 +00:00
|
|
|
{
|
|
|
|
pipe_source_ = source;
|
|
|
|
pipe_child_process_ = child_process;
|
|
|
|
pipe_user_data_ = user_data;
|
|
|
|
pipe_input_cb_ = input_cb;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
/* Tricky to use pipes in win9x, as no concept of wait. NT can
|
|
|
|
do this but that doesn't cover all win32 platforms. GTK can do
|
|
|
|
this but doesn't seem to work over processes. Attempt to do
|
|
|
|
something similar here, start a timer and check for data on every
|
|
|
|
timeout. */
|
|
|
|
/*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_input_set_handler: new");*/
|
|
|
|
|
|
|
|
if (pipe_timer_) {
|
2012-08-31 23:18:45 +00:00
|
|
|
disconnect(pipe_timer_, SIGNAL(timeout()), this, SLOT(pipeTimeout()));
|
2012-08-31 22:25:51 +00:00
|
|
|
delete pipe_timer_;
|
|
|
|
}
|
|
|
|
|
|
|
|
pipe_timer_ = new QTimer(this);
|
2012-08-31 23:18:45 +00:00
|
|
|
connect(pipe_timer_, SIGNAL(timeout()), this, SLOT(pipeTimeout()));
|
2012-08-31 23:37:10 +00:00
|
|
|
connect(pipe_timer_, SIGNAL(destroyed()), this, SLOT(pipeNotifierDestroyed()));
|
2012-08-31 22:25:51 +00:00
|
|
|
pipe_timer_->start(200);
|
|
|
|
#else
|
|
|
|
if (pipe_notifier_) {
|
|
|
|
disconnect(pipe_notifier_, SIGNAL(activated(int)), this, SLOT(pipeActivated(int)));
|
|
|
|
delete pipe_notifier_;
|
|
|
|
}
|
|
|
|
|
|
|
|
pipe_notifier_ = new QSocketNotifier(pipe_source_, QSocketNotifier::Read);
|
|
|
|
// XXX ui/gtk/gui_utils.c sets the encoding. Do we need to do the same?
|
|
|
|
connect(pipe_notifier_, SIGNAL(activated(int)), this, SLOT(pipeActivated(int)));
|
|
|
|
connect(pipe_notifier_, SIGNAL(destroyed()), this, SLOT(pipeNotifierDestroyed()));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-08-23 02:59:31 +00:00
|
|
|
bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
|
|
|
|
|
|
|
|
// The user typed some text. Start filling in a filter.
|
|
|
|
// We may need to be more choosy here. We just need to catch events for the packet list,
|
|
|
|
// proto tree, and main welcome widgets.
|
|
|
|
if (event->type() == QEvent::KeyPress) {
|
|
|
|
QKeyEvent *kevt = static_cast<QKeyEvent *>(event);
|
2017-07-18 08:17:53 +00:00
|
|
|
if (kevt->text().length() > 0 && kevt->text()[0].isPrint() &&
|
|
|
|
!(kevt->modifiers() & Qt::ControlModifier)) {
|
2012-08-23 02:59:31 +00:00
|
|
|
df_combo_box_->lineEdit()->insert(kevt->text());
|
|
|
|
df_combo_box_->lineEdit()->setFocus();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-10 17:55:26 +00:00
|
|
|
return QMainWindow::eventFilter(obj, event);
|
2012-08-23 02:59:31 +00:00
|
|
|
}
|
|
|
|
|
2012-01-14 00:16:16 +00:00
|
|
|
void MainWindow::keyPressEvent(QKeyEvent *event) {
|
|
|
|
|
2012-08-14 04:12:56 +00:00
|
|
|
// Explicitly focus on the display filter combo.
|
2012-01-14 00:16:16 +00:00
|
|
|
if (event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_Slash) {
|
2012-08-17 00:58:50 +00:00
|
|
|
df_combo_box_->setFocus(Qt::ShortcutFocusReason);
|
2012-01-14 00:16:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-22 20:39:36 +00:00
|
|
|
if (wsApp->focusWidget() == main_ui_->goToLineEdit) {
|
|
|
|
if (event->modifiers() == Qt::NoModifier) {
|
|
|
|
if (event->key() == Qt::Key_Escape) {
|
|
|
|
on_goToCancel_clicked();
|
|
|
|
} else if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
|
|
|
|
on_goToGo_clicked();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return; // goToLineEdit didn't want it and we don't either.
|
|
|
|
}
|
|
|
|
|
2012-08-14 04:12:56 +00:00
|
|
|
// Move up & down the packet list.
|
2012-08-13 01:50:14 +00:00
|
|
|
if (event->key() == Qt::Key_F7) {
|
2012-08-17 00:58:50 +00:00
|
|
|
packet_list_->goPreviousPacket();
|
2012-08-13 01:50:14 +00:00
|
|
|
} else if (event->key() == Qt::Key_F8) {
|
2012-08-17 00:58:50 +00:00
|
|
|
packet_list_->goNextPacket();
|
2012-08-13 01:50:14 +00:00
|
|
|
}
|
|
|
|
|
2012-08-14 04:12:56 +00:00
|
|
|
// Move along, citizen.
|
2012-01-14 00:16:16 +00:00
|
|
|
QMainWindow::keyPressEvent(event);
|
|
|
|
}
|
|
|
|
|
2012-08-31 22:25:51 +00:00
|
|
|
void MainWindow::closeEvent(QCloseEvent *event) {
|
2013-10-30 22:39:52 +00:00
|
|
|
saveWindowGeometry();
|
|
|
|
|
|
|
|
/* If we're in the middle of stopping a capture, don't do anything;
|
|
|
|
the user can try deleting the window after the capture stops. */
|
2012-08-31 22:50:44 +00:00
|
|
|
if (capture_stopping_) {
|
2012-08-31 22:25:51 +00:00
|
|
|
event->ignore();
|
2013-05-20 18:56:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-25 12:51:50 +00:00
|
|
|
QString before_what(tr(" before quitting"));
|
2016-01-25 11:07:10 +00:00
|
|
|
if (!testCaptureFileClose(before_what, Quit)) {
|
2015-02-21 01:03:48 +00:00
|
|
|
event->ignore();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-17 12:05:35 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2016-03-31 00:24:44 +00:00
|
|
|
if (capture_interfaces_dialog_) capture_interfaces_dialog_->close();
|
2014-05-17 12:05:35 +00:00
|
|
|
#endif
|
2013-08-23 02:34:51 +00:00
|
|
|
// Make sure we kill any open dumpcap processes.
|
|
|
|
delete main_welcome_;
|
|
|
|
|
2015-02-14 00:18:57 +00:00
|
|
|
// One of the many places we assume one main window.
|
2013-10-30 22:39:52 +00:00
|
|
|
if(!wsApp->isInitialized()) {
|
|
|
|
// If we're still initializing, QCoreApplication::quit() won't
|
|
|
|
// exit properly because we are not in the event loop. This
|
|
|
|
// means that the application won't clean up after itself. We
|
|
|
|
// might want to call wsApp->processEvents() during startup
|
|
|
|
// instead so that we can do a normal exit here.
|
2013-05-20 18:56:47 +00:00
|
|
|
exit(0);
|
|
|
|
}
|
2015-02-14 00:18:57 +00:00
|
|
|
wsApp->quit();
|
2017-06-12 12:23:32 +00:00
|
|
|
// When the main loop is not yet running (i.e. when openCaptureFile is
|
|
|
|
// executing in wireshark-qt.cpp), the above quit action has no effect.
|
|
|
|
// Schedule a quit action for the next execution of the main loop.
|
|
|
|
QMetaObject::invokeMethod(wsApp, "quit", Qt::QueuedConnection);
|
2013-10-30 22:39:52 +00:00
|
|
|
}
|
|
|
|
|
2017-01-20 20:26:32 +00:00
|
|
|
// XXX On windows the drag description is "Copy". It should be "Open" or
|
|
|
|
// "Merge" as appropriate. It looks like we need access to IDataObject in
|
|
|
|
// order to set DROPDESCRIPTION.
|
2015-06-14 18:04:51 +00:00
|
|
|
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
|
|
|
|
{
|
2017-01-22 20:14:33 +00:00
|
|
|
if (!main_ui_->actionFileOpen->isEnabled()) {
|
|
|
|
// We could alternatively call setAcceptDrops(!capture_in_progress)
|
|
|
|
// in setMenusForCaptureInProgress but that wouldn't provide feedback.
|
|
|
|
|
|
|
|
main_ui_->statusBar->pushTemporaryStatus(tr("Unable to drop files during capture."));
|
|
|
|
event->setDropAction(Qt::IgnoreAction);
|
|
|
|
event->ignore();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool have_files = false;
|
2015-06-14 18:04:51 +00:00
|
|
|
foreach (QUrl drag_url, event->mimeData()->urls()) {
|
|
|
|
if (!drag_url.toLocalFile().isEmpty()) {
|
2017-01-22 20:14:33 +00:00
|
|
|
have_files = true;
|
2015-06-14 18:04:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-01-22 20:14:33 +00:00
|
|
|
|
|
|
|
if (have_files) {
|
|
|
|
event->acceptProposedAction();
|
|
|
|
}
|
2015-06-14 18:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::dropEvent(QDropEvent *event)
|
|
|
|
{
|
2017-01-20 20:26:32 +00:00
|
|
|
QList<QByteArray> local_files;
|
|
|
|
|
2015-06-14 18:04:51 +00:00
|
|
|
foreach (QUrl drop_url, event->mimeData()->urls()) {
|
2017-01-20 20:26:32 +00:00
|
|
|
QString drop_file = drop_url.toLocalFile();
|
|
|
|
if (!drop_file.isEmpty()) {
|
|
|
|
local_files << drop_file.toUtf8();
|
2015-06-14 18:04:51 +00:00
|
|
|
}
|
|
|
|
}
|
2017-01-20 20:26:32 +00:00
|
|
|
|
|
|
|
if (local_files.size() < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
event->acceptProposedAction();
|
|
|
|
|
|
|
|
|
|
|
|
if (local_files.size() == 1) {
|
|
|
|
openCaptureFile(local_files.at(0));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-12-14 22:13:39 +00:00
|
|
|
char **in_filenames = (char **) g_malloc(sizeof(char*) * local_files.size());
|
2017-01-20 20:26:32 +00:00
|
|
|
char *tmpname = NULL;
|
|
|
|
|
|
|
|
for (int i = 0; i < local_files.size(); i++) {
|
2017-12-14 22:13:39 +00:00
|
|
|
in_filenames[i] = const_cast<char *>(local_files.at(i).constData());
|
2017-01-20 20:26:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* merge the files in chronological order */
|
2017-01-21 08:21:18 +00:00
|
|
|
if (cf_merge_files_to_tempfile(this, &tmpname, local_files.size(),
|
|
|
|
in_filenames, WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
|
|
|
|
FALSE) == CF_OK) {
|
2017-01-20 20:26:32 +00:00
|
|
|
/* Merge succeeded; close the currently-open file and try
|
|
|
|
to open the merged capture file. */
|
|
|
|
openCaptureFile(tmpname, QString(), WTAP_TYPE_AUTO, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(tmpname);
|
|
|
|
g_free(in_filenames);
|
|
|
|
|
2015-06-14 18:04:51 +00:00
|
|
|
}
|
|
|
|
|
2015-02-20 18:32:15 +00:00
|
|
|
// Apply recent settings to the main window geometry.
|
|
|
|
// We haven't loaded the preferences at this point so we assume that the
|
|
|
|
// position and size preference are enabled.
|
2016-06-07 22:26:03 +00:00
|
|
|
// Note we might end up with unexpected screen geometries if the user
|
|
|
|
// unplugs or plugs in a monitor:
|
|
|
|
// https://bugreports.qt.io/browse/QTBUG-44213
|
2013-10-30 22:39:52 +00:00
|
|
|
void MainWindow::loadWindowGeometry()
|
|
|
|
{
|
2015-11-05 22:30:53 +00:00
|
|
|
int min_sensible_dimension = 200;
|
2013-10-30 22:39:52 +00:00
|
|
|
|
2013-10-30 23:23:24 +00:00
|
|
|
#ifndef Q_OS_MAC
|
2015-04-07 20:51:13 +00:00
|
|
|
if (recent.gui_geometry_main_maximized) {
|
2013-10-30 23:23:24 +00:00
|
|
|
setWindowState(Qt::WindowMaximized);
|
|
|
|
} else
|
|
|
|
#endif
|
2015-02-20 18:32:15 +00:00
|
|
|
{
|
2015-11-05 22:30:53 +00:00
|
|
|
QRect recent_geom(recent.gui_geometry_main_x, recent.gui_geometry_main_y,
|
|
|
|
recent.gui_geometry_main_width, recent.gui_geometry_main_height);
|
|
|
|
if (!rect_on_screen(recent_geom)) {
|
2016-06-07 22:26:03 +00:00
|
|
|
// We're not visible on any screens. See if we can move onscreen
|
|
|
|
// without resizing.
|
|
|
|
recent_geom.moveTo(50, 50); // recent.c defaults to 20.
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!rect_on_screen(recent_geom)) {
|
|
|
|
// Give up and use the default geometry.
|
2015-11-05 22:30:53 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-02-20 18:32:15 +00:00
|
|
|
// if (prefs.gui_geometry_save_position) {
|
2015-11-05 22:30:53 +00:00
|
|
|
move(recent_geom.topLeft());
|
2015-02-20 18:32:15 +00:00
|
|
|
// }
|
|
|
|
|
|
|
|
if (// prefs.gui_geometry_save_size &&
|
2015-11-05 22:30:53 +00:00
|
|
|
recent_geom.width() > min_sensible_dimension &&
|
|
|
|
recent_geom.height() > min_sensible_dimension) {
|
|
|
|
resize(recent_geom.size());
|
2015-02-20 18:32:15 +00:00
|
|
|
}
|
2013-10-30 22:39:52 +00:00
|
|
|
}
|
|
|
|
}
|
2013-05-20 18:56:47 +00:00
|
|
|
|
2013-10-30 22:39:52 +00:00
|
|
|
void MainWindow::saveWindowGeometry()
|
|
|
|
{
|
|
|
|
if (prefs.gui_geometry_save_position) {
|
|
|
|
recent.gui_geometry_main_x = pos().x();
|
|
|
|
recent.gui_geometry_main_y = pos().y();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prefs.gui_geometry_save_size) {
|
|
|
|
recent.gui_geometry_main_width = size().width();
|
|
|
|
recent.gui_geometry_main_height = size().height();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prefs.gui_geometry_save_maximized) {
|
2017-04-05 19:15:27 +00:00
|
|
|
// On macOS this is false when it shouldn't be
|
2013-10-30 22:39:52 +00:00
|
|
|
recent.gui_geometry_main_maximized = isMaximized();
|
|
|
|
}
|
2015-02-19 01:18:27 +00:00
|
|
|
|
|
|
|
if (master_split_.sizes().length() > 0) {
|
|
|
|
recent.gui_geometry_main_upper_pane = master_split_.sizes()[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (master_split_.sizes().length() > 2) {
|
|
|
|
recent.gui_geometry_main_lower_pane = master_split_.sizes()[1];
|
|
|
|
} else if (extra_split_.sizes().length() > 0) {
|
|
|
|
recent.gui_geometry_main_lower_pane = extra_split_.sizes()[0];
|
|
|
|
}
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
|
2013-09-03 16:06:20 +00:00
|
|
|
QWidget* MainWindow::getLayoutWidget(layout_pane_content_e type) {
|
|
|
|
switch (type) {
|
|
|
|
case layout_pane_content_none:
|
2013-10-05 22:39:49 +00:00
|
|
|
return &empty_pane_;
|
2013-09-03 16:06:20 +00:00
|
|
|
case layout_pane_content_plist:
|
|
|
|
return packet_list_;
|
|
|
|
case layout_pane_content_pdetails:
|
|
|
|
return proto_tree_;
|
|
|
|
case layout_pane_content_pbytes:
|
|
|
|
return byte_view_tab_;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2012-09-06 22:58:39 +00:00
|
|
|
|
2015-11-10 18:12:56 +00:00
|
|
|
// 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
|
|
|
|
// main status bar must remain accessible.
|
|
|
|
//
|
|
|
|
// We might want to do this any time the main status bar progress frame is
|
|
|
|
// shown and hidden.
|
|
|
|
void MainWindow::freeze()
|
|
|
|
{
|
|
|
|
freeze_focus_ = wsApp->focusWidget();
|
|
|
|
|
|
|
|
// XXX Alternatively we could just disable and enable the main menu.
|
|
|
|
for (int i = 0; i < freeze_actions_.size(); i++) {
|
|
|
|
QAction *action = freeze_actions_[i].first;
|
|
|
|
freeze_actions_[i].second = action->isEnabled();
|
|
|
|
action->setEnabled(false);
|
|
|
|
}
|
|
|
|
main_ui_->centralWidget->setEnabled(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::thaw()
|
|
|
|
{
|
|
|
|
main_ui_->centralWidget->setEnabled(true);
|
|
|
|
for (int i = 0; i < freeze_actions_.size(); i++) {
|
|
|
|
freeze_actions_[i].first->setEnabled(freeze_actions_[i].second);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (freeze_focus_) freeze_focus_->setFocus();
|
|
|
|
freeze_focus_ = NULL;
|
|
|
|
}
|
|
|
|
|
2012-09-06 22:58:39 +00:00
|
|
|
void MainWindow::mergeCaptureFile()
|
|
|
|
{
|
|
|
|
QString file_name = "";
|
2015-11-16 16:20:40 +00:00
|
|
|
QString read_filter = "";
|
2012-09-06 22:58:39 +00:00
|
|
|
dfilter_t *rfcode = NULL;
|
|
|
|
int err;
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
if (!capture_file_.capFile())
|
2012-09-06 22:58:39 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (prefs.gui_ask_unsaved) {
|
2014-09-09 20:42:58 +00:00
|
|
|
if (cf_has_unsaved_data(capture_file_.capFile())) {
|
2012-09-06 22:58:39 +00:00
|
|
|
QMessageBox msg_dialog;
|
|
|
|
gchar *display_basename;
|
|
|
|
int response;
|
|
|
|
|
|
|
|
msg_dialog.setIcon(QMessageBox::Question);
|
2013-04-01 23:44:29 +00:00
|
|
|
/* This file has unsaved data; ask the user whether to save
|
|
|
|
the capture. */
|
2014-09-09 20:42:58 +00:00
|
|
|
if (capture_file_.capFile()->is_tempfile) {
|
2012-10-04 18:16:08 +00:00
|
|
|
msg_dialog.setText(tr("Save packets before merging?"));
|
|
|
|
msg_dialog.setInformativeText(tr("A temporary capture file can't be merged."));
|
2012-09-06 22:58:39 +00:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Format the message.
|
|
|
|
*/
|
2014-09-09 20:42:58 +00:00
|
|
|
display_basename = g_filename_display_basename(capture_file_.capFile()->filename);
|
2012-10-04 18:16:08 +00:00
|
|
|
msg_dialog.setText(QString(tr("Save changes in \"%1\" before merging?")).arg(display_basename));
|
2012-09-06 22:58:39 +00:00
|
|
|
g_free(display_basename);
|
2012-10-04 18:16:08 +00:00
|
|
|
msg_dialog.setInformativeText(tr("Changes must be saved before the files can be merged."));
|
2012-09-06 22:58:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
msg_dialog.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
|
|
|
|
msg_dialog.setDefaultButton(QMessageBox::Save);
|
|
|
|
|
|
|
|
response = msg_dialog.exec();
|
|
|
|
|
|
|
|
switch (response) {
|
|
|
|
|
|
|
|
case QMessageBox::Save:
|
|
|
|
/* Save the file but don't close it */
|
2016-05-28 03:33:37 +00:00
|
|
|
saveCaptureFile(capture_file_.capFile(), false);
|
2012-09-06 22:58:39 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case QMessageBox::Cancel:
|
|
|
|
default:
|
|
|
|
/* Don't do the merge. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;) {
|
2015-11-16 16:20:40 +00:00
|
|
|
CaptureFileDialog merge_dlg(this, capture_file_.capFile(), read_filter);
|
2012-09-06 22:58:39 +00:00
|
|
|
int file_type;
|
|
|
|
cf_status_t merge_status;
|
|
|
|
char *in_filenames[2];
|
|
|
|
char *tmpname;
|
|
|
|
|
|
|
|
if (merge_dlg.merge(file_name)) {
|
2015-01-18 10:22:19 +00:00
|
|
|
gchar *err_msg;
|
|
|
|
|
2017-12-14 18:29:48 +00:00
|
|
|
if (!dfilter_compile(qUtf8Printable(read_filter), &rfcode, &err_msg)) {
|
2016-06-22 21:41:16 +00:00
|
|
|
/* Not valid. Tell the user, and go back and run the file
|
2012-09-06 22:58:39 +00:00
|
|
|
selection box again once they dismiss the alert. */
|
2016-06-22 21:41:16 +00:00
|
|
|
// Similar to commandline_info.jfilter section in main().
|
2015-11-16 16:20:40 +00:00
|
|
|
QMessageBox::warning(this, tr("Invalid Read Filter"),
|
|
|
|
QString(tr("The filter expression %1 isn't a valid read filter. (%2).").arg(read_filter, err_msg)),
|
2012-09-06 22:58:39 +00:00
|
|
|
QMessageBox::Ok);
|
2015-01-18 10:22:19 +00:00
|
|
|
g_free(err_msg);
|
2012-09-06 22:58:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
file_type = capture_file_.capFile()->cd_t;
|
2012-09-06 22:58:39 +00:00
|
|
|
|
|
|
|
/* Try to merge or append the two files */
|
|
|
|
if (merge_dlg.mergeType() == 0) {
|
|
|
|
/* chronological order */
|
2015-09-05 17:39:51 +00:00
|
|
|
in_filenames[0] = g_strdup(capture_file_.capFile()->filename);
|
|
|
|
in_filenames[1] = qstring_strdup(file_name);
|
2017-01-21 00:05:56 +00:00
|
|
|
merge_status = cf_merge_files_to_tempfile(this, &tmpname, 2, in_filenames, file_type, FALSE);
|
2012-09-06 22:58:39 +00:00
|
|
|
} else if (merge_dlg.mergeType() <= 0) {
|
|
|
|
/* prepend file */
|
2015-09-05 17:39:51 +00:00
|
|
|
in_filenames[0] = qstring_strdup(file_name);
|
|
|
|
in_filenames[1] = g_strdup(capture_file_.capFile()->filename);
|
2017-01-21 00:05:56 +00:00
|
|
|
merge_status = cf_merge_files_to_tempfile(this, &tmpname, 2, in_filenames, file_type, TRUE);
|
2012-09-06 22:58:39 +00:00
|
|
|
} else {
|
|
|
|
/* append file */
|
2015-09-05 17:39:51 +00:00
|
|
|
in_filenames[0] = g_strdup(capture_file_.capFile()->filename);
|
|
|
|
in_filenames[1] = qstring_strdup(file_name);
|
2017-01-21 00:05:56 +00:00
|
|
|
merge_status = cf_merge_files_to_tempfile(this, &tmpname, 2, in_filenames, file_type, TRUE);
|
2012-09-06 22:58:39 +00:00
|
|
|
}
|
|
|
|
|
2015-09-05 17:39:51 +00:00
|
|
|
g_free(in_filenames[0]);
|
|
|
|
g_free(in_filenames[1]);
|
|
|
|
|
2012-09-06 22:58:39 +00:00
|
|
|
if (merge_status != CF_OK) {
|
2017-08-26 08:30:47 +00:00
|
|
|
dfilter_free(rfcode);
|
2012-09-06 22:58:39 +00:00
|
|
|
g_free(tmpname);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
cf_close(capture_file_.capFile());
|
2012-09-06 22:58:39 +00:00
|
|
|
|
|
|
|
/* Try to open the merged capture file. */
|
2014-09-09 20:42:58 +00:00
|
|
|
CaptureFile::globalCapFile()->window = this;
|
|
|
|
if (cf_open(CaptureFile::globalCapFile(), tmpname, WTAP_TYPE_AUTO, TRUE /* temporary file */, &err) != CF_OK) {
|
2012-09-06 22:58:39 +00:00
|
|
|
/* We couldn't open it; fail. */
|
2014-09-09 20:42:58 +00:00
|
|
|
CaptureFile::globalCapFile()->window = NULL;
|
2017-08-26 08:30:47 +00:00
|
|
|
dfilter_free(rfcode);
|
2012-09-06 22:58:39 +00:00
|
|
|
g_free(tmpname);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Attach the new read filter to "cf" ("cf_open()" succeeded, so
|
|
|
|
it closed the previous capture file, and thus destroyed any
|
|
|
|
previous read filter attached to "cf"). */
|
2015-11-17 00:27:34 +00:00
|
|
|
cf_set_rfcode(CaptureFile::globalCapFile(), rfcode);
|
2012-09-06 22:58:39 +00:00
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
switch (cf_read(CaptureFile::globalCapFile(), FALSE)) {
|
2012-09-06 22:58:39 +00:00
|
|
|
|
|
|
|
case CF_READ_OK:
|
|
|
|
case CF_READ_ERROR:
|
|
|
|
/* Just because we got an error, that doesn't mean we were unable
|
|
|
|
to read any of the file; we handle what we could get from the
|
|
|
|
file. */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CF_READ_ABORTED:
|
|
|
|
/* The user bailed out of re-reading the capture file; the
|
|
|
|
capture file has been closed - just free the capture file name
|
|
|
|
string and return (without changing the last containing
|
|
|
|
directory). */
|
|
|
|
g_free(tmpname);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save the name of the containing directory specified in the path name,
|
|
|
|
if any; we can write over cf_merged_name, which is a good thing, given that
|
|
|
|
"get_dirname()" does write over its argument. */
|
2012-09-17 23:40:53 +00:00
|
|
|
wsApp->setLastOpenDir(get_dirname(tmpname));
|
2012-09-06 22:58:39 +00:00
|
|
|
g_free(tmpname);
|
|
|
|
main_ui_->statusBar->showExpert();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-09-17 23:40:53 +00:00
|
|
|
void MainWindow::importCaptureFile() {
|
|
|
|
ImportTextDialog import_dlg;
|
|
|
|
|
2016-01-25 11:07:10 +00:00
|
|
|
QString before_what(tr(" before importing a capture"));
|
2016-01-11 09:46:02 +00:00
|
|
|
if (!testCaptureFileClose(before_what))
|
2012-09-17 23:40:53 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
import_dlg.exec();
|
|
|
|
|
|
|
|
if (import_dlg.result() != QDialog::Accepted) {
|
2012-09-18 22:52:34 +00:00
|
|
|
main_ui_->mainStack->setCurrentWidget(main_welcome_);
|
2012-09-17 23:40:53 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
openCaptureFile(import_dlg.capfileName());
|
|
|
|
}
|
|
|
|
|
2016-06-22 14:56:07 +00:00
|
|
|
bool MainWindow::saveCaptureFile(capture_file *cf, bool dont_reopen) {
|
2012-09-26 19:52:53 +00:00
|
|
|
QString file_name;
|
|
|
|
gboolean discard_comments;
|
|
|
|
|
|
|
|
if (cf->is_tempfile) {
|
|
|
|
/* This is a temporary capture file, so saving it means saving
|
|
|
|
it to a permanent file. Prompt the user for a location
|
|
|
|
to which to save it. Don't require that the file format
|
|
|
|
support comments - if it's a temporary capture file, it's
|
|
|
|
probably pcap-ng, which supports comments and, if it's
|
|
|
|
not pcap-ng, let the user decide what they want to do
|
|
|
|
if they've added comments. */
|
2016-06-22 14:56:07 +00:00
|
|
|
return saveAsCaptureFile(cf, FALSE, dont_reopen);
|
2012-09-26 19:52:53 +00:00
|
|
|
} else {
|
|
|
|
if (cf->unsaved_changes) {
|
2012-10-13 01:29:29 +00:00
|
|
|
cf_write_status_t status;
|
|
|
|
|
2012-09-26 19:52:53 +00:00
|
|
|
/* This is not a temporary capture file, but it has unsaved
|
|
|
|
changes, so saving it means doing a "safe save" on top
|
|
|
|
of the existing file, in the same format - no UI needed
|
|
|
|
unless the file has comments and the file's format doesn't
|
|
|
|
support them.
|
|
|
|
|
|
|
|
If the file has comments, does the file's format support them?
|
|
|
|
If not, ask the user whether they want to discard the comments
|
|
|
|
or choose a different format. */
|
2012-09-26 21:16:59 +00:00
|
|
|
switch (CaptureFileDialog::checkSaveAsWithComments(this, cf, cf->cd_t)) {
|
2012-09-26 19:52:53 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SAVE_WITHOUT_COMMENTS:
|
|
|
|
/* The file can't be saved in the specified format as is,
|
|
|
|
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;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SAVE_IN_ANOTHER_FORMAT:
|
|
|
|
/* There are file formats in which we can save this that
|
|
|
|
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. */
|
2016-06-22 14:56:07 +00:00
|
|
|
return saveAsCaptureFile(cf, TRUE, dont_reopen);
|
2012-09-26 19:52:53 +00:00
|
|
|
|
|
|
|
case CANCELLED:
|
|
|
|
/* The user said "forget it". Just return. */
|
2016-06-22 14:56:07 +00:00
|
|
|
return false;
|
2012-09-26 19:52:53 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
/* Squelch warnings that discard_comments is being used
|
|
|
|
uninitialized. */
|
|
|
|
g_assert_not_reached();
|
2016-06-22 14:56:07 +00:00
|
|
|
return false;
|
2012-09-26 19:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX - cf->filename might get freed out from under us, because
|
2014-05-24 18:28:30 +00:00
|
|
|
the code path through which cf_save_records() goes currently
|
2012-09-26 19:52:53 +00:00
|
|
|
closes the current file and then opens and reloads the saved file,
|
|
|
|
so make a copy and free it later. */
|
|
|
|
file_name = cf->filename;
|
2017-12-14 18:29:48 +00:00
|
|
|
status = cf_save_records(cf, qUtf8Printable(file_name), cf->cd_t, cf->iscompressed,
|
2015-05-22 19:57:44 +00:00
|
|
|
discard_comments, dont_reopen);
|
2012-09-26 19:52:53 +00:00
|
|
|
switch (status) {
|
|
|
|
|
|
|
|
case CF_WRITE_OK:
|
|
|
|
/* The save succeeded; we're done.
|
|
|
|
If we discarded comments, redraw the packet list to reflect
|
|
|
|
any packets that no longer have comments. */
|
|
|
|
if (discard_comments)
|
|
|
|
packet_list_queue_draw();
|
2013-07-09 18:08:40 +00:00
|
|
|
|
|
|
|
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 *
|
2012-09-26 19:52:53 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CF_WRITE_ERROR:
|
|
|
|
/* The write failed.
|
|
|
|
XXX - OK, what do we do now? Let them try a
|
|
|
|
"Save As", in case they want to try to save to a
|
If we're "[Saving] the file and [closing] it", actually *close* it.
Otherwise, if you've modified the file (added, removed, or changed
comments), and you try to close the file or quit, and answer "Save" to
the "save your work?" question, Wireshark tries to clean up the wmem
scopes, but the file scope hasn't been left, and wmem crashes with an
assertion error.
(The GTK+ version does the close, so it doesn't have the bug.)
Change-Id: Ie5942e415cfab1907e29b09926a62e2679aca6ee
Reviewed-on: https://code.wireshark.org/review/15598
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2016-05-28 18:04:06 +00:00
|
|
|
different directory or file system? */
|
2012-09-26 19:52:53 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CF_WRITE_ABORTED:
|
|
|
|
/* The write was aborted; just drive on. */
|
2016-06-22 14:56:07 +00:00
|
|
|
return false;
|
2012-09-26 19:52:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Otherwise just do nothing. */
|
|
|
|
}
|
2016-06-22 14:56:07 +00:00
|
|
|
|
|
|
|
return true;
|
2012-09-26 19:52:53 +00:00
|
|
|
}
|
|
|
|
|
2016-06-22 14:56:07 +00:00
|
|
|
bool MainWindow::saveAsCaptureFile(capture_file *cf, bool must_support_comments, bool dont_reopen) {
|
2012-09-26 19:52:53 +00:00
|
|
|
QString file_name = "";
|
|
|
|
int file_type;
|
|
|
|
gboolean compressed;
|
|
|
|
cf_write_status_t status;
|
|
|
|
gchar *dirname;
|
|
|
|
gboolean discard_comments = FALSE;
|
|
|
|
|
|
|
|
if (!cf) {
|
2016-06-22 14:56:07 +00:00
|
|
|
return false;
|
2012-09-26 19:52:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (;;) {
|
2012-10-08 20:01:59 +00:00
|
|
|
CaptureFileDialog save_as_dlg(this, cf);
|
2012-09-26 19:52:53 +00:00
|
|
|
|
|
|
|
/* If the file has comments, does the format the user selected
|
|
|
|
support them? If not, ask the user whether they want to
|
|
|
|
discard the comments or choose a different format. */
|
2012-10-08 20:01:59 +00:00
|
|
|
switch(save_as_dlg.saveAs(file_name, must_support_comments)) {
|
2012-09-26 19:52:53 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SAVE_WITHOUT_COMMENTS:
|
|
|
|
/* The file can't be saved in the specified format as is,
|
|
|
|
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;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SAVE_IN_ANOTHER_FORMAT:
|
|
|
|
/* There are file formats in which we can save this that
|
|
|
|
support comments, and the user said not to delete the
|
|
|
|
comments. The combo box of file formats has had the
|
|
|
|
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;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case CANCELLED:
|
|
|
|
/* The user said "forget it". Just get rid of the dialog box
|
|
|
|
and return. */
|
2016-06-22 14:56:07 +00:00
|
|
|
return false;
|
2012-09-26 19:52:53 +00:00
|
|
|
}
|
|
|
|
file_type = save_as_dlg.selectedFileType();
|
|
|
|
compressed = save_as_dlg.isCompressed();
|
|
|
|
|
2012-10-08 20:01:59 +00:00
|
|
|
fileAddExtension(file_name, file_type, compressed);
|
|
|
|
|
|
|
|
//#ifndef _WIN32
|
|
|
|
// /* If the file exists and it's user-immutable or not writable,
|
|
|
|
// ask the user whether they want to override that. */
|
2017-12-14 18:29:48 +00:00
|
|
|
// if (!file_target_unwritable_ui(top_level, qUtf8Printable(file_name))) {
|
2012-10-08 20:01:59 +00:00
|
|
|
// /* They don't. Let them try another file name or cancel. */
|
|
|
|
// continue;
|
|
|
|
// }
|
|
|
|
//#endif
|
|
|
|
|
|
|
|
/* Attempt to save the file */
|
2017-12-14 18:29:48 +00:00
|
|
|
status = cf_save_records(cf, qUtf8Printable(file_name), file_type, compressed,
|
2015-05-22 19:57:44 +00:00
|
|
|
discard_comments, dont_reopen);
|
2012-10-08 20:01:59 +00:00
|
|
|
switch (status) {
|
|
|
|
|
|
|
|
case CF_WRITE_OK:
|
|
|
|
/* The save succeeded; we're done. */
|
|
|
|
/* Save the directory name for future file dialogs. */
|
2016-02-03 17:28:46 +00:00
|
|
|
dirname = qstring_strdup(file_name); /* Overwrites cf_name */
|
|
|
|
set_last_open_dir(get_dirname(dirname));
|
2014-11-29 18:32:30 +00:00
|
|
|
g_free(dirname);
|
2012-10-08 20:01:59 +00:00
|
|
|
/* If we discarded comments, redraw the packet list to reflect
|
|
|
|
any packets that no longer have comments. */
|
|
|
|
if (discard_comments)
|
|
|
|
packet_list_queue_draw();
|
2013-07-09 18:08:40 +00:00
|
|
|
|
|
|
|
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 *
|
2016-09-02 13:21:46 +00:00
|
|
|
/* Add this filename to the list of recent files in the "Recent Files" submenu */
|
2017-12-14 18:29:48 +00:00
|
|
|
add_menu_recent_capture_file(qUtf8Printable(file_name));
|
2016-06-22 14:56:07 +00:00
|
|
|
return true;
|
2012-10-08 20:01:59 +00:00
|
|
|
|
|
|
|
case CF_WRITE_ERROR:
|
|
|
|
/* The save failed; let the user try again. */
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case CF_WRITE_ABORTED:
|
|
|
|
/* The user aborted the save; just return. */
|
2016-06-22 14:56:07 +00:00
|
|
|
return false;
|
2012-10-08 20:01:59 +00:00
|
|
|
}
|
|
|
|
}
|
2016-06-22 14:56:07 +00:00
|
|
|
return true;
|
2012-10-08 20:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::exportSelectedPackets() {
|
|
|
|
QString file_name = "";
|
|
|
|
int file_type;
|
|
|
|
gboolean compressed;
|
|
|
|
packet_range_t range;
|
|
|
|
cf_write_status_t status;
|
|
|
|
gchar *dirname;
|
|
|
|
gboolean discard_comments = FALSE;
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
if (!capture_file_.capFile())
|
2012-10-08 20:01:59 +00:00
|
|
|
return;
|
|
|
|
|
2012-10-12 23:40:29 +00:00
|
|
|
/* Init the packet range */
|
2014-09-09 20:42:58 +00:00
|
|
|
packet_range_init(&range, capture_file_.capFile());
|
2012-10-08 20:01:59 +00:00
|
|
|
range.process_filtered = TRUE;
|
|
|
|
range.include_dependents = TRUE;
|
|
|
|
|
|
|
|
for (;;) {
|
2014-09-09 20:42:58 +00:00
|
|
|
CaptureFileDialog esp_dlg(this, capture_file_.capFile());
|
2012-10-08 20:01:59 +00:00
|
|
|
|
|
|
|
/* If the file has comments, does the format the user selected
|
|
|
|
support them? If not, ask the user whether they want to
|
|
|
|
discard the comments or choose a different format. */
|
|
|
|
switch(esp_dlg.exportSelectedPackets(file_name, &range)) {
|
|
|
|
|
|
|
|
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;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SAVE_WITHOUT_COMMENTS:
|
|
|
|
/* The file can't be saved in the specified format as is,
|
|
|
|
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;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SAVE_IN_ANOTHER_FORMAT:
|
|
|
|
/* There are file formats in which we can save this that
|
|
|
|
support comments, and the user said not to delete the
|
|
|
|
comments. The combo box of file formats has had the
|
|
|
|
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. */
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case CANCELLED:
|
|
|
|
/* The user said "forget it". Just get rid of the dialog box
|
|
|
|
and return. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-09-26 19:52:53 +00:00
|
|
|
/*
|
2012-10-08 20:01:59 +00:00
|
|
|
* Check that we're not going to save on top of the current
|
|
|
|
* capture file.
|
|
|
|
* We do it here so we catch all cases ...
|
|
|
|
* Unfortunately, the file requester gives us an absolute file
|
|
|
|
* name and the read file name may be relative (if supplied on
|
|
|
|
* the command line). From Joerg Mayer.
|
2012-09-26 19:52:53 +00:00
|
|
|
*/
|
2017-12-14 18:29:48 +00:00
|
|
|
if (files_identical(capture_file_.capFile()->filename, qUtf8Printable(file_name))) {
|
2012-10-08 20:01:59 +00:00
|
|
|
QMessageBox msg_box;
|
2017-12-14 18:29:48 +00:00
|
|
|
gchar *display_basename = g_filename_display_basename(qUtf8Printable(file_name));
|
2012-10-08 20:01:59 +00:00
|
|
|
|
|
|
|
msg_box.setIcon(QMessageBox::Critical);
|
|
|
|
msg_box.setText(QString(tr("Unable to export to \"%1\".").arg(display_basename)));
|
|
|
|
msg_box.setInformativeText(tr("You cannot export packets to the current capture file."));
|
|
|
|
msg_box.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msg_box.setDefaultButton(QMessageBox::Ok);
|
|
|
|
msg_box.exec();
|
|
|
|
g_free(display_basename);
|
|
|
|
continue;
|
2012-09-26 19:52:53 +00:00
|
|
|
}
|
|
|
|
|
2012-10-08 20:01:59 +00:00
|
|
|
file_type = esp_dlg.selectedFileType();
|
|
|
|
compressed = esp_dlg.isCompressed();
|
|
|
|
fileAddExtension(file_name, file_type, compressed);
|
|
|
|
|
2012-09-26 19:52:53 +00:00
|
|
|
//#ifndef _WIN32
|
|
|
|
// /* If the file exists and it's user-immutable or not writable,
|
|
|
|
// ask the user whether they want to override that. */
|
2017-12-14 18:29:48 +00:00
|
|
|
// if (!file_target_unwritable_ui(top_level, qUtf8Printable(file_name))) {
|
2012-09-26 19:52:53 +00:00
|
|
|
// /* They don't. Let them try another file name or cancel. */
|
|
|
|
// continue;
|
|
|
|
// }
|
|
|
|
//#endif
|
|
|
|
|
|
|
|
/* Attempt to save the file */
|
2017-12-14 18:29:48 +00:00
|
|
|
status = cf_export_specified_packets(capture_file_.capFile(), qUtf8Printable(file_name), &range, file_type, compressed);
|
2012-09-26 19:52:53 +00:00
|
|
|
switch (status) {
|
|
|
|
|
|
|
|
case CF_WRITE_OK:
|
|
|
|
/* The save succeeded; we're done. */
|
|
|
|
/* Save the directory name for future file dialogs. */
|
2016-02-03 17:28:46 +00:00
|
|
|
dirname = qstring_strdup(file_name); /* Overwrites cf_name */
|
|
|
|
set_last_open_dir(get_dirname(dirname));
|
2014-11-29 18:32:30 +00:00
|
|
|
g_free(dirname);
|
2012-09-26 19:52:53 +00:00
|
|
|
/* If we discarded comments, redraw the packet list to reflect
|
|
|
|
any packets that no longer have comments. */
|
|
|
|
if (discard_comments)
|
|
|
|
packet_list_queue_draw();
|
2017-01-27 20:20:51 +00:00
|
|
|
/* Add this filename to the list of recent files in the "Recent Files" submenu */
|
2017-12-14 18:29:48 +00:00
|
|
|
add_menu_recent_capture_file(qUtf8Printable(file_name));
|
2012-09-26 19:52:53 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case CF_WRITE_ERROR:
|
|
|
|
/* The save failed; let the user try again. */
|
|
|
|
continue;
|
|
|
|
|
|
|
|
case CF_WRITE_ABORTED:
|
|
|
|
/* The user aborted the save; just return. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
|
2012-10-12 23:40:29 +00:00
|
|
|
void MainWindow::exportDissections(export_type_e export_type) {
|
2014-09-09 20:42:58 +00:00
|
|
|
ExportDissectionDialog ed_dlg(this, capture_file_.capFile(), export_type);
|
2012-10-12 23:40:29 +00:00
|
|
|
packet_range_t range;
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
if (!capture_file_.capFile())
|
2012-10-12 23:40:29 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* Init the packet range */
|
2014-09-09 20:42:58 +00:00
|
|
|
packet_range_init(&range, capture_file_.capFile());
|
2012-10-12 23:40:29 +00:00
|
|
|
range.process_filtered = TRUE;
|
|
|
|
range.include_dependents = TRUE;
|
|
|
|
|
|
|
|
ed_dlg.exec();
|
|
|
|
}
|
|
|
|
|
2012-10-08 20:01:59 +00:00
|
|
|
void MainWindow::fileAddExtension(QString &file_name, int file_type, bool compressed) {
|
|
|
|
QString file_name_lower;
|
2012-10-13 01:29:29 +00:00
|
|
|
GSList *extensions_list;
|
2012-10-08 20:01:59 +00:00
|
|
|
gboolean add_extension;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Append the default file extension if there's none given by
|
|
|
|
* the user or if they gave one that's not one of the valid
|
|
|
|
* extensions for the file type.
|
|
|
|
*/
|
|
|
|
file_name_lower = file_name.toLower();
|
|
|
|
extensions_list = wtap_get_file_extensions_list(file_type, FALSE);
|
|
|
|
if (extensions_list != NULL) {
|
2012-10-13 01:29:29 +00:00
|
|
|
GSList *extension;
|
|
|
|
|
2012-10-08 20:01:59 +00:00
|
|
|
/* We have one or more extensions for this file type.
|
|
|
|
Start out assuming we need to add the default one. */
|
|
|
|
add_extension = TRUE;
|
|
|
|
|
|
|
|
/* OK, see if the file has one of those extensions. */
|
|
|
|
for (extension = extensions_list; extension != NULL;
|
|
|
|
extension = g_slist_next(extension)) {
|
2016-12-06 22:14:39 +00:00
|
|
|
QString file_suffix = tr(".") + (char *)extension->data;
|
2012-10-08 20:01:59 +00:00
|
|
|
if (file_name_lower.endsWith(file_suffix)) {
|
|
|
|
/*
|
|
|
|
* The file name has one of the extensions for
|
|
|
|
* this file type.
|
|
|
|
*/
|
|
|
|
add_extension = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
file_suffix += ".gz";
|
|
|
|
if (file_name_lower.endsWith(file_suffix)) {
|
|
|
|
/*
|
|
|
|
* The file name has one of the extensions for
|
|
|
|
* this file type.
|
|
|
|
*/
|
|
|
|
add_extension = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* We have no extensions for this file type. Don't add one. */
|
|
|
|
add_extension = FALSE;
|
|
|
|
}
|
|
|
|
if (add_extension) {
|
|
|
|
if (wtap_default_file_extension(file_type) != NULL) {
|
|
|
|
file_name += tr(".") + wtap_default_file_extension(file_type);
|
|
|
|
if (compressed) {
|
|
|
|
file_name += ".gz";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-25 11:07:10 +00:00
|
|
|
bool MainWindow::testCaptureFileClose(QString before_what, FileCloseContext context) {
|
2016-01-07 22:03:49 +00:00
|
|
|
bool capture_in_progress = false;
|
|
|
|
bool do_close_file = false;
|
2012-08-31 22:25:51 +00:00
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
if (!capture_file_.capFile() || capture_file_.capFile()->state == FILE_CLOSED)
|
2012-08-31 22:25:51 +00:00
|
|
|
return true; /* Already closed, nothing to do */
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBPCAP
|
2016-01-07 22:03:49 +00:00
|
|
|
if (capture_file_.capFile()->state == FILE_READ_IN_PROGRESS) {
|
2017-06-12 12:23:32 +00:00
|
|
|
/*
|
|
|
|
* This (FILE_READ_IN_PROGRESS) is true if we're reading a capture file
|
|
|
|
* *or* if we're doing a live capture. From the capture file itself we
|
|
|
|
* cannot differentiate the cases, so check the current capture session.
|
|
|
|
*/
|
|
|
|
capture_in_progress = captureSession()->state != CAPTURE_STOPPED;
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (prefs.gui_ask_unsaved) {
|
2017-06-12 12:23:32 +00:00
|
|
|
if (cf_has_unsaved_data(capture_file_.capFile())) {
|
2012-08-31 22:25:51 +00:00
|
|
|
QMessageBox msg_dialog;
|
|
|
|
QString question;
|
2016-01-25 11:07:10 +00:00
|
|
|
QString infotext;
|
|
|
|
QPushButton *save_button;
|
|
|
|
QPushButton *discard_button;
|
2012-08-31 22:25:51 +00:00
|
|
|
|
|
|
|
msg_dialog.setIcon(QMessageBox::Question);
|
2015-07-31 17:34:43 +00:00
|
|
|
msg_dialog.setWindowTitle("Unsaved packets" UTF8_HORIZONTAL_ELLIPSIS);
|
2016-01-25 11:07:10 +00:00
|
|
|
|
2013-04-01 23:44:29 +00:00
|
|
|
/* This file has unsaved data or there's a capture in
|
|
|
|
progress; ask the user whether to save the data. */
|
2016-01-25 11:07:10 +00:00
|
|
|
if (capture_in_progress && context != Restart) {
|
|
|
|
question = tr("Do you want to stop the capture and save the captured packets%1?").arg(before_what);
|
|
|
|
infotext = tr("Your captured packets will be lost if you don't save them.");
|
|
|
|
} else if (capture_file_.capFile()->is_tempfile) {
|
2016-01-25 21:11:55 +00:00
|
|
|
if (context == Reload) {
|
|
|
|
// Reloading a tempfile will keep the packets, so this is not unsaved packets
|
|
|
|
question = tr("Do you want to save the changes you've made%1?").arg(before_what);
|
|
|
|
infotext = tr("Your changes will be lost if you don't save them.");
|
|
|
|
} else {
|
|
|
|
question = tr("Do you want to save the captured packets%1?").arg(before_what);
|
|
|
|
infotext = tr("Your captured packets will be lost if you don't save them.");
|
|
|
|
}
|
2012-08-31 22:25:51 +00:00
|
|
|
} else {
|
2016-01-25 11:07:10 +00:00
|
|
|
// 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);
|
|
|
|
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);
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
|
2016-01-25 11:07:10 +00:00
|
|
|
msg_dialog.setText(question);
|
|
|
|
msg_dialog.setInformativeText(infotext);
|
|
|
|
|
2012-08-31 22:25:51 +00:00
|
|
|
// XXX Text comes from ui/gtk/stock_icons.[ch]
|
|
|
|
// Note that the button roles differ from the GTK+ version.
|
|
|
|
// Cancel = RejectRole
|
|
|
|
// Save = AcceptRole
|
|
|
|
// Don't Save = DestructiveRole
|
2013-05-20 18:56:47 +00:00
|
|
|
msg_dialog.addButton(QMessageBox::Cancel);
|
2012-08-31 22:25:51 +00:00
|
|
|
|
|
|
|
if (capture_in_progress) {
|
2016-01-25 11:07:10 +00:00
|
|
|
QString save_button_text;
|
|
|
|
if (context == Restart) {
|
|
|
|
save_button_text = tr("Save before Continue");
|
2015-12-19 21:36:30 +00:00
|
|
|
} else {
|
2016-01-25 11:07:10 +00:00
|
|
|
save_button_text = tr("Stop and Save");
|
2015-12-19 21:36:30 +00:00
|
|
|
}
|
2016-01-25 11:07:10 +00:00
|
|
|
save_button = msg_dialog.addButton(save_button_text, QMessageBox::AcceptRole);
|
2012-08-31 22:25:51 +00:00
|
|
|
} else {
|
2016-01-25 11:07:10 +00:00
|
|
|
save_button = msg_dialog.addButton(QMessageBox::Save);
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
2016-01-25 11:07:10 +00:00
|
|
|
msg_dialog.setDefaultButton(save_button);
|
2012-08-31 22:25:51 +00:00
|
|
|
|
2016-01-25 11:07:10 +00:00
|
|
|
QString discard_button_text;
|
2016-01-11 09:46:02 +00:00
|
|
|
if (capture_in_progress) {
|
2016-01-25 11:07:10 +00:00
|
|
|
switch (context) {
|
|
|
|
case Quit:
|
2016-04-07 08:36:22 +00:00
|
|
|
discard_button_text = tr("Stop and Quit &without Saving");
|
2016-01-11 09:46:02 +00:00
|
|
|
break;
|
2016-01-25 11:07:10 +00:00
|
|
|
case Restart:
|
2016-04-07 08:36:22 +00:00
|
|
|
discard_button_text = tr("Continue &without Saving");
|
2016-01-11 09:46:02 +00:00
|
|
|
break;
|
|
|
|
default:
|
2016-04-07 08:36:22 +00:00
|
|
|
discard_button_text = tr("Stop and Continue &without Saving");
|
2016-01-11 09:46:02 +00:00
|
|
|
break;
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
} else {
|
2016-01-25 11:07:10 +00:00
|
|
|
switch (context) {
|
|
|
|
case Quit:
|
2016-04-07 08:36:22 +00:00
|
|
|
discard_button_text = tr("Quit &without Saving");
|
2016-01-11 09:46:02 +00:00
|
|
|
break;
|
2016-01-25 11:07:10 +00:00
|
|
|
case Restart:
|
2016-01-11 09:46:02 +00:00
|
|
|
default:
|
2016-04-07 08:36:22 +00:00
|
|
|
discard_button_text = tr("Continue &without Saving");
|
2016-01-11 09:46:02 +00:00
|
|
|
break;
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
}
|
2016-01-25 11:07:10 +00:00
|
|
|
discard_button = msg_dialog.addButton(discard_button_text, QMessageBox::DestructiveRole);
|
2012-08-31 22:25:51 +00:00
|
|
|
|
2017-03-10 12:03:02 +00:00
|
|
|
discard_button->setAutoDefault(false);
|
|
|
|
discard_button->setFocus();
|
|
|
|
|
2013-05-20 18:56:47 +00:00
|
|
|
msg_dialog.exec();
|
|
|
|
/* According to the Qt doc:
|
|
|
|
* when using QMessageBox with custom buttons, exec() function returns an opaque value.
|
|
|
|
*
|
|
|
|
* Therefore we should use clickedButton() to determine which button was clicked. */
|
2012-08-31 22:25:51 +00:00
|
|
|
|
2016-01-25 11:07:10 +00:00
|
|
|
if (msg_dialog.clickedButton() == save_button) {
|
2012-08-31 22:25:51 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
/* If there's a capture in progress, we have to stop the capture
|
2016-01-07 22:03:49 +00:00
|
|
|
and then do the save. */
|
2012-08-31 22:25:51 +00:00
|
|
|
if (capture_in_progress)
|
2012-10-01 22:40:20 +00:00
|
|
|
captureStop();
|
2012-08-31 22:25:51 +00:00
|
|
|
#endif
|
|
|
|
/* Save the file and close it */
|
2017-06-12 12:23:32 +00:00
|
|
|
// XXX if no packets were captured, any unsaved comments set by
|
|
|
|
// the user are silently discarded because capFile() is null.
|
|
|
|
if (capture_file_.capFile() && saveCaptureFile(capture_file_.capFile(), true) == false)
|
2016-06-22 14:56:07 +00:00
|
|
|
return false;
|
If we're "[Saving] the file and [closing] it", actually *close* it.
Otherwise, if you've modified the file (added, removed, or changed
comments), and you try to close the file or quit, and answer "Save" to
the "save your work?" question, Wireshark tries to clean up the wmem
scopes, but the file scope hasn't been left, and wmem crashes with an
assertion error.
(The GTK+ version does the close, so it doesn't have the bug.)
Change-Id: Ie5942e415cfab1907e29b09926a62e2679aca6ee
Reviewed-on: https://code.wireshark.org/review/15598
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2016-05-28 18:04:06 +00:00
|
|
|
do_close_file = true;
|
2016-01-25 11:07:10 +00:00
|
|
|
} else if(msg_dialog.clickedButton() == discard_button) {
|
2016-01-07 22:03:49 +00:00
|
|
|
/* Just close the file, discarding changes */
|
|
|
|
do_close_file = true;
|
|
|
|
} else {
|
|
|
|
// cancelButton or some other unspecified button
|
2013-05-20 18:56:47 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-08-31 22:25:51 +00:00
|
|
|
} else {
|
2016-01-07 22:03:49 +00:00
|
|
|
/* Unchanged file or capturing with no packets */
|
|
|
|
do_close_file = true;
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* User asked not to be bothered by those prompts, just close it.
|
|
|
|
XXX - should that apply only to saving temporary files? */
|
2016-01-07 22:03:49 +00:00
|
|
|
do_close_file = true;
|
|
|
|
}
|
|
|
|
|
2017-06-12 12:23:32 +00:00
|
|
|
/*
|
|
|
|
* Are we done with this file and should we close the file?
|
|
|
|
*/
|
2016-01-07 22:03:49 +00:00
|
|
|
if (do_close_file) {
|
2012-08-31 22:25:51 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
/* If there's a capture in progress, we have to stop the capture
|
|
|
|
and then do the close. */
|
|
|
|
if (capture_in_progress)
|
2012-10-01 22:40:20 +00:00
|
|
|
captureStop();
|
2017-06-12 12:23:32 +00:00
|
|
|
else if (capture_file_.capFile() && capture_file_.capFile()->state == FILE_READ_IN_PROGRESS) {
|
|
|
|
/*
|
|
|
|
* When an offline capture is being read, mark it as aborted.
|
|
|
|
* cf_read will be responsible for actually closing the capture.
|
|
|
|
*
|
|
|
|
* We cannot just invoke cf_close here since cf_read is up in the
|
|
|
|
* call chain. (update_progress_dlg can end up processing the Quit
|
|
|
|
* event from the user which then ends up here.)
|
|
|
|
*/
|
|
|
|
capture_file_.capFile()->state = FILE_READ_ABORTED;
|
|
|
|
return true;
|
|
|
|
}
|
2012-08-31 22:25:51 +00:00
|
|
|
#endif
|
2017-11-05 10:39:54 +00:00
|
|
|
/* Clear MainWindow file name details */
|
|
|
|
gbl_cur_main_window_->setMwFileName("");
|
|
|
|
|
2016-01-07 22:03:49 +00:00
|
|
|
/* captureStop() will close the file if not having any packets */
|
2016-01-25 21:11:55 +00:00
|
|
|
if (capture_file_.capFile() && context != Restart && context != Reload)
|
|
|
|
// Don't really close if Restart or Reload
|
2016-01-07 22:03:49 +00:00
|
|
|
cf_close(capture_file_.capFile());
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
|
2012-09-18 22:52:34 +00:00
|
|
|
return true; /* File closed */
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
|
2012-10-01 22:40:20 +00:00
|
|
|
void MainWindow::captureStop() {
|
2012-08-31 22:25:51 +00:00
|
|
|
stopCapture();
|
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
while(capture_file_.capFile() && capture_file_.capFile()->state == FILE_READ_IN_PROGRESS) {
|
2012-08-31 22:25:51 +00:00
|
|
|
WiresharkApplication::processEvents();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-21 20:36:10 +00:00
|
|
|
void MainWindow::initMainToolbarIcons()
|
|
|
|
{
|
2015-11-06 17:32:39 +00:00
|
|
|
// Normally 16 px. Reflects current GTK+ behavior and other Windows apps.
|
|
|
|
int icon_size = style()->pixelMetric(QStyle::PM_SmallIconSize);
|
|
|
|
#if !defined(Q_OS_WIN)
|
2014-10-21 20:36:10 +00:00
|
|
|
// Force icons to 24x24 for now, otherwise actionFileOpen looks wonky.
|
2017-04-05 19:15:27 +00:00
|
|
|
// The macOS HIG specifies 32-pixel icons but they're a little too
|
2015-11-06 17:32:39 +00:00
|
|
|
// large IMHO.
|
|
|
|
icon_size = icon_size * 3 / 2;
|
2014-10-21 20:36:10 +00:00
|
|
|
#endif
|
2015-11-06 17:32:39 +00:00
|
|
|
main_ui_->mainToolBar->setIconSize(QSize(icon_size, icon_size));
|
2014-10-21 20:36:10 +00:00
|
|
|
|
|
|
|
// Toolbar actions. The GNOME HIG says that we should have a menu icon for each
|
|
|
|
// toolbar item but that clutters up our menu. Set menu icons sparingly.
|
|
|
|
|
|
|
|
main_ui_->actionCaptureStart->setIcon(StockIcon("x-capture-start"));
|
|
|
|
main_ui_->actionCaptureStop->setIcon(StockIcon("x-capture-stop"));
|
|
|
|
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.
|
|
|
|
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"));
|
2015-06-23 18:26:30 +00:00
|
|
|
main_ui_->actionViewReload->setIcon(StockIcon("x-capture-file-reload"));
|
2014-10-21 20:36:10 +00:00
|
|
|
|
|
|
|
main_ui_->actionEditFindPacket->setIcon(StockIcon("edit-find"));
|
|
|
|
main_ui_->actionGoPreviousPacket->setIcon(StockIcon("go-previous"));
|
|
|
|
main_ui_->actionGoNextPacket->setIcon(StockIcon("go-next"));
|
|
|
|
main_ui_->actionGoGoToPacket->setIcon(StockIcon("go-jump"));
|
|
|
|
main_ui_->actionGoFirstPacket->setIcon(StockIcon("go-first"));
|
|
|
|
main_ui_->actionGoLastPacket->setIcon(StockIcon("go-last"));
|
2015-11-12 16:35:34 +00:00
|
|
|
main_ui_->actionGoPreviousConversationPacket->setIcon(StockIcon("go-previous"));
|
|
|
|
main_ui_->actionGoNextConversationPacket->setIcon(StockIcon("go-next"));
|
|
|
|
#if defined(Q_OS_MAC)
|
|
|
|
main_ui_->actionGoPreviousConversationPacket->setShortcut(QKeySequence(Qt::META | Qt::Key_Comma));
|
|
|
|
main_ui_->actionGoNextConversationPacket->setShortcut(QKeySequence(Qt::META | Qt::Key_Period));
|
|
|
|
#endif
|
2017-03-01 16:03:17 +00:00
|
|
|
main_ui_->actionGoPreviousHistoryPacket->setIcon(StockIcon("go-previous"));
|
|
|
|
main_ui_->actionGoNextHistoryPacket->setIcon(StockIcon("go-next"));
|
2015-02-20 14:30:23 +00:00
|
|
|
main_ui_->actionGoAutoScroll->setIcon(StockIcon("x-stay-last"));
|
2014-10-21 20:36:10 +00:00
|
|
|
|
|
|
|
main_ui_->actionViewColorizePacketList->setIcon(StockIcon("x-colorize-packets"));
|
|
|
|
|
|
|
|
QList<QKeySequence> zi_seq = main_ui_->actionViewZoomIn->shortcuts();
|
|
|
|
zi_seq << QKeySequence(Qt::CTRL + Qt::Key_Equal);
|
|
|
|
main_ui_->actionViewZoomIn->setIcon(StockIcon("zoom-in"));
|
|
|
|
main_ui_->actionViewZoomIn->setShortcuts(zi_seq);
|
|
|
|
main_ui_->actionViewZoomOut->setIcon(StockIcon("zoom-out"));
|
|
|
|
main_ui_->actionViewNormalSize->setIcon(StockIcon("zoom-original"));
|
|
|
|
main_ui_->actionViewResizeColumns->setIcon(StockIcon("x-resize-columns"));
|
|
|
|
}
|
|
|
|
|
2014-10-22 17:05:35 +00:00
|
|
|
void MainWindow::initShowHideMainWidgets()
|
|
|
|
{
|
|
|
|
if (show_hide_actions_) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
show_hide_actions_ = new QActionGroup(this);
|
|
|
|
QMap<QAction *, QWidget *> shmw_actions;
|
|
|
|
|
|
|
|
show_hide_actions_->setExclusive(false);
|
|
|
|
shmw_actions[main_ui_->actionViewMainToolbar] = main_ui_->mainToolBar;
|
|
|
|
shmw_actions[main_ui_->actionViewFilterToolbar] = main_ui_->displayFilterToolBar;
|
2015-06-11 22:05:44 +00:00
|
|
|
shmw_actions[main_ui_->actionViewWirelessToolbar] = main_ui_->wirelessToolBar;
|
2014-10-22 17:05:35 +00:00
|
|
|
shmw_actions[main_ui_->actionViewStatusBar] = main_ui_->statusBar;
|
|
|
|
shmw_actions[main_ui_->actionViewPacketList] = packet_list_;
|
|
|
|
shmw_actions[main_ui_->actionViewPacketDetails] = proto_tree_;
|
|
|
|
shmw_actions[main_ui_->actionViewPacketBytes] = byte_view_tab_;
|
|
|
|
|
|
|
|
foreach (QAction *shmwa, shmw_actions.keys()) {
|
|
|
|
shmwa->setData(qVariantFromValue(shmw_actions[shmwa]));
|
|
|
|
show_hide_actions_->addAction(shmwa);
|
|
|
|
showHideMainWidgets(shmwa);
|
|
|
|
}
|
|
|
|
|
2017-04-15 21:30:30 +00:00
|
|
|
// Initial hide the Interface Toolbar submenu
|
|
|
|
main_ui_->menuInterfaceToolbars->menuAction()->setVisible(false);
|
|
|
|
|
2017-01-24 16:34:07 +00:00
|
|
|
/* Initially hide the additional toolbars menus */
|
2017-04-18 08:03:00 +00:00
|
|
|
main_ui_->menuAdditionalToolbars->menuAction()->setVisible(false);
|
2017-01-24 16:34:07 +00:00
|
|
|
|
2014-10-22 17:05:35 +00:00
|
|
|
connect(show_hide_actions_, SIGNAL(triggered(QAction*)), this, SLOT(showHideMainWidgets(QAction*)));
|
|
|
|
}
|
|
|
|
|
2014-10-21 20:36:10 +00:00
|
|
|
void MainWindow::initTimeDisplayFormatMenu()
|
|
|
|
{
|
|
|
|
if (time_display_actions_) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
time_display_actions_ = new QActionGroup(this);
|
|
|
|
|
|
|
|
td_actions[main_ui_->actionViewTimeDisplayFormatDateYMDandTimeOfDay] = TS_ABSOLUTE_WITH_YMD;
|
|
|
|
td_actions[main_ui_->actionViewTimeDisplayFormatDateYDOYandTimeOfDay] = TS_ABSOLUTE_WITH_YDOY;
|
|
|
|
td_actions[main_ui_->actionViewTimeDisplayFormatTimeOfDay] = TS_ABSOLUTE;
|
|
|
|
td_actions[main_ui_->actionViewTimeDisplayFormatSecondsSinceEpoch] = TS_EPOCH;
|
|
|
|
td_actions[main_ui_->actionViewTimeDisplayFormatSecondsSinceBeginningOfCapture] = TS_RELATIVE;
|
|
|
|
td_actions[main_ui_->actionViewTimeDisplayFormatSecondsSincePreviousCapturedPacket] = TS_DELTA;
|
|
|
|
td_actions[main_ui_->actionViewTimeDisplayFormatSecondsSincePreviousDisplayedPacket] = TS_DELTA_DIS;
|
|
|
|
td_actions[main_ui_->actionViewTimeDisplayFormatUTCDateYMDandTimeOfDay] = TS_UTC_WITH_YMD;
|
|
|
|
td_actions[main_ui_->actionViewTimeDisplayFormatUTCDateYDOYandTimeOfDay] = TS_UTC_WITH_YDOY;
|
|
|
|
td_actions[main_ui_->actionViewTimeDisplayFormatUTCTimeOfDay] = TS_UTC;
|
|
|
|
|
|
|
|
foreach (QAction* tda, td_actions.keys()) {
|
|
|
|
tda->setData(qVariantFromValue(td_actions[tda]));
|
|
|
|
time_display_actions_->addAction(tda);
|
|
|
|
}
|
|
|
|
|
|
|
|
connect(time_display_actions_, SIGNAL(triggered(QAction*)), this, SLOT(setTimestampFormat(QAction*)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::initTimePrecisionFormatMenu()
|
|
|
|
{
|
|
|
|
if (time_precision_actions_) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
time_precision_actions_ = new QActionGroup(this);
|
2015-12-03 09:22:23 +00:00
|
|
|
|
2014-10-21 20:36:10 +00:00
|
|
|
tp_actions[main_ui_->actionViewTimeDisplayFormatPrecisionAutomatic] = TS_PREC_AUTO;
|
|
|
|
tp_actions[main_ui_->actionViewTimeDisplayFormatPrecisionSeconds] = TS_PREC_FIXED_SEC;
|
|
|
|
tp_actions[main_ui_->actionViewTimeDisplayFormatPrecisionDeciseconds] = TS_PREC_FIXED_DSEC;
|
|
|
|
tp_actions[main_ui_->actionViewTimeDisplayFormatPrecisionCentiseconds] = TS_PREC_FIXED_CSEC;
|
|
|
|
tp_actions[main_ui_->actionViewTimeDisplayFormatPrecisionMilliseconds] = TS_PREC_FIXED_MSEC;
|
|
|
|
tp_actions[main_ui_->actionViewTimeDisplayFormatPrecisionMicroseconds] = TS_PREC_FIXED_USEC;
|
|
|
|
tp_actions[main_ui_->actionViewTimeDisplayFormatPrecisionNanoseconds] = TS_PREC_FIXED_NSEC;
|
|
|
|
|
|
|
|
foreach (QAction* tpa, tp_actions.keys()) {
|
|
|
|
tpa->setData(qVariantFromValue(tp_actions[tpa]));
|
|
|
|
time_precision_actions_->addAction(tpa);
|
|
|
|
}
|
|
|
|
|
|
|
|
connect(time_precision_actions_, SIGNAL(triggered(QAction*)), this, SLOT(setTimestampPrecision(QAction*)));
|
|
|
|
}
|
|
|
|
|
2015-11-10 18:12:56 +00:00
|
|
|
// Menu items which will be disabled when we freeze() and whose state will
|
|
|
|
// be restored when we thaw(). Add to the list as needed.
|
|
|
|
void MainWindow::initFreezeActions()
|
|
|
|
{
|
|
|
|
QList<QAction *> freeze_actions = QList<QAction *>()
|
|
|
|
<< main_ui_->actionFileClose
|
|
|
|
<< main_ui_->actionViewReload
|
|
|
|
<< main_ui_->actionEditMarkPacket
|
|
|
|
<< main_ui_->actionEditMarkAllDisplayed
|
|
|
|
<< main_ui_->actionEditUnmarkAllDisplayed
|
|
|
|
<< main_ui_->actionEditIgnorePacket
|
|
|
|
<< main_ui_->actionEditIgnoreAllDisplayed
|
|
|
|
<< main_ui_->actionEditUnignoreAllDisplayed
|
|
|
|
<< main_ui_->actionEditSetTimeReference
|
|
|
|
<< main_ui_->actionEditUnsetAllTimeReferences;
|
|
|
|
|
|
|
|
foreach (QAction *action, freeze_actions) {
|
|
|
|
freeze_actions_ << QPair<QAction *, bool>(action, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-18 17:34:41 +00:00
|
|
|
void MainWindow::initConversationMenus()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
QList<QAction *> cc_actions = QList<QAction *>()
|
|
|
|
<< main_ui_->actionViewColorizeConversation1 << main_ui_->actionViewColorizeConversation2
|
|
|
|
<< main_ui_->actionViewColorizeConversation3 << main_ui_->actionViewColorizeConversation4
|
|
|
|
<< main_ui_->actionViewColorizeConversation5 << main_ui_->actionViewColorizeConversation6
|
|
|
|
<< main_ui_->actionViewColorizeConversation7 << main_ui_->actionViewColorizeConversation8
|
|
|
|
<< main_ui_->actionViewColorizeConversation9 << main_ui_->actionViewColorizeConversation10;
|
|
|
|
|
|
|
|
for (GList *conv_filter_list_entry = conv_filter_list; conv_filter_list_entry; conv_filter_list_entry = g_list_next(conv_filter_list_entry)) {
|
|
|
|
// Main menu items
|
|
|
|
conversation_filter_t* conv_filter = (conversation_filter_t *)conv_filter_list_entry->data;
|
|
|
|
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()));
|
|
|
|
|
|
|
|
// Packet list context menu items
|
|
|
|
packet_list_->conversationMenu()->addAction(conv_action);
|
|
|
|
|
|
|
|
QMenu *submenu = packet_list_->colorizeMenu()->addMenu(conv_action->text());
|
|
|
|
i = 1;
|
|
|
|
|
|
|
|
foreach (QAction *cc_action, cc_actions) {
|
|
|
|
conv_action = new ConversationAction(submenu, conv_filter);
|
|
|
|
conv_action->setText(cc_action->text());
|
|
|
|
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*)));
|
2016-06-24 22:17:25 +00:00
|
|
|
connect(conv_action, SIGNAL(triggered()), this, SLOT(colorizeActionTriggered()));
|
2016-03-18 17:34:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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*)));
|
2016-06-24 22:17:25 +00:00
|
|
|
connect(conv_action, SIGNAL(triggered()), this, SLOT(colorizeActionTriggered()));
|
2016-03-18 17:34:41 +00:00
|
|
|
|
|
|
|
// Proto tree conversation menu is filled in in ProtoTree::contextMenuEvent.
|
|
|
|
// We should probably do that here.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Proto tree colorization items
|
|
|
|
i = 1;
|
|
|
|
ColorizeAction *colorize_action;
|
|
|
|
foreach (QAction *cc_action, cc_actions) {
|
|
|
|
colorize_action = new ColorizeAction(proto_tree_->colorizeMenu());
|
|
|
|
colorize_action->setText(cc_action->text());
|
|
|
|
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)));
|
2016-06-24 22:17:25 +00:00
|
|
|
connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeActionTriggered()));
|
2016-03-18 17:34:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)));
|
2016-06-24 22:17:25 +00:00
|
|
|
connect(colorize_action, SIGNAL(triggered()), this, SLOT(colorizeActionTriggered()));
|
2016-03-18 17:34:41 +00:00
|
|
|
}
|
|
|
|
|
2017-04-25 20:48:23 +00:00
|
|
|
gboolean MainWindow::addExportObjectsMenuItem(const void *, void *value, void *userdata)
|
2016-11-24 14:37:01 +00:00
|
|
|
{
|
2017-02-08 00:44:19 +00:00
|
|
|
register_eo_t *eo = (register_eo_t*)value;
|
|
|
|
MainWindow *window = (MainWindow*)userdata;
|
2016-11-24 14:37:01 +00:00
|
|
|
|
|
|
|
ExportObjectAction *export_action = new ExportObjectAction(window->main_ui_->menuFileExportObjects, eo);
|
|
|
|
window->main_ui_->menuFileExportObjects->addAction(export_action);
|
|
|
|
|
|
|
|
//initially disable until a file is loaded (then file signals will take over)
|
|
|
|
export_action->setEnabled(false);
|
|
|
|
|
|
|
|
connect(&window->capture_file_, SIGNAL(captureFileOpened()), export_action, SLOT(captureFileOpened()));
|
|
|
|
connect(&window->capture_file_, SIGNAL(captureFileClosed()), export_action, SLOT(captureFileClosed()));
|
|
|
|
connect(export_action, SIGNAL(triggered()), window, SLOT(applyExportObject()));
|
2017-02-08 00:44:19 +00:00
|
|
|
return FALSE;
|
2016-11-24 14:37:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::initExportObjectsMenus()
|
|
|
|
{
|
|
|
|
eo_iterate_tables(addExportObjectsMenuItem, this);
|
|
|
|
}
|
|
|
|
|
2013-03-31 22:59:56 +00:00
|
|
|
// Titlebar
|
|
|
|
void MainWindow::setTitlebarForCaptureFile()
|
|
|
|
{
|
2014-09-09 20:42:58 +00:00
|
|
|
if (capture_file_.capFile() && capture_file_.capFile()->filename) {
|
|
|
|
if (capture_file_.capFile()->is_tempfile) {
|
2013-04-02 22:10:16 +00:00
|
|
|
//
|
|
|
|
// For a temporary file, put the source of the data
|
|
|
|
// in the window title, not whatever random pile
|
|
|
|
// of characters is the last component of the path
|
|
|
|
// name.
|
|
|
|
//
|
|
|
|
// XXX - on non-Mac platforms, put in the application
|
|
|
|
// name?
|
|
|
|
//
|
2015-12-15 11:12:27 +00:00
|
|
|
setWSWindowTitle(QString("[*]%1").arg(cf_get_tempfile_source(capture_file_.capFile())));
|
2013-04-02 22:10:16 +00:00
|
|
|
} else {
|
|
|
|
//
|
|
|
|
// For a user file, set the full path; that way,
|
2017-04-05 19:15:27 +00:00
|
|
|
// for macOS, it'll set the "proxy icon". Qt
|
2013-04-02 22:10:16 +00:00
|
|
|
// handles extracting the last component.
|
|
|
|
//
|
|
|
|
// Sadly, some UN*Xes don't necessarily use UTF-8
|
|
|
|
// for their file names, so we have to map the
|
|
|
|
// file path to UTF-8. If that fails, we're somewhat
|
|
|
|
// stuck.
|
|
|
|
//
|
2014-09-09 20:42:58 +00:00
|
|
|
char *utf8_filename = g_filename_to_utf8(capture_file_.capFile()->filename,
|
2013-04-02 22:10:16 +00:00
|
|
|
-1,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
2016-01-12 14:01:45 +00:00
|
|
|
if (utf8_filename) {
|
|
|
|
QFileInfo fi(utf8_filename);
|
2016-02-19 17:27:44 +00:00
|
|
|
setWSWindowTitle(QString("[*]%1").arg(fi.fileName()));
|
2016-01-12 14:01:45 +00:00
|
|
|
setWindowFilePath(utf8_filename);
|
2013-04-02 22:10:16 +00:00
|
|
|
g_free(utf8_filename);
|
2016-01-12 14:01:45 +00:00
|
|
|
} else {
|
|
|
|
// So what the heck else can we do here?
|
|
|
|
setWSWindowTitle(tr("(File name can't be mapped to UTF-8)"));
|
2013-04-02 22:10:16 +00:00
|
|
|
}
|
|
|
|
}
|
2014-09-09 20:42:58 +00:00
|
|
|
setWindowModified(cf_has_unsaved_data(capture_file_.capFile()));
|
2013-03-31 22:59:56 +00:00
|
|
|
} else {
|
|
|
|
/* We have no capture file. */
|
2015-12-15 11:12:27 +00:00
|
|
|
setWSWindowTitle();
|
2013-03-31 22:59:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-19 17:26:41 +00:00
|
|
|
QString MainWindow::replaceWindowTitleVariables(QString title)
|
|
|
|
{
|
|
|
|
title.replace ("%P", get_profile_name());
|
|
|
|
title.replace ("%V", get_ws_vcs_version_info());
|
|
|
|
|
|
|
|
return title;
|
|
|
|
}
|
|
|
|
|
2015-12-15 11:12:27 +00:00
|
|
|
void MainWindow::setWSWindowTitle(QString title)
|
2013-07-09 18:08:40 +00:00
|
|
|
{
|
2016-01-13 08:58:19 +00:00
|
|
|
if (title.isEmpty()) {
|
2015-12-15 11:12:27 +00:00
|
|
|
title = tr("The Wireshark Network Analyzer");
|
|
|
|
}
|
|
|
|
|
2016-01-13 08:58:19 +00:00
|
|
|
if (prefs.gui_prepend_window_title && prefs.gui_prepend_window_title[0]) {
|
2016-01-23 12:18:30 +00:00
|
|
|
QString custom_title = replaceWindowTitleVariables(prefs.gui_prepend_window_title);
|
|
|
|
title.prepend(QString("[%1] ").arg(custom_title));
|
2015-12-15 14:40:30 +00:00
|
|
|
}
|
|
|
|
|
2016-01-13 08:58:19 +00:00
|
|
|
if (prefs.gui_window_title && prefs.gui_window_title[0]) {
|
2016-01-23 12:18:30 +00:00
|
|
|
QString custom_title = replaceWindowTitleVariables(prefs.gui_window_title);
|
2016-01-13 08:58:19 +00:00
|
|
|
#ifdef __APPLE__
|
2017-04-05 19:15:27 +00:00
|
|
|
// On macOS we separate the titles with a unicode em dash
|
2016-01-23 12:18:30 +00:00
|
|
|
title.append(QString(" %1 %2").arg(UTF8_EM_DASH).arg(custom_title));
|
2016-01-13 08:58:19 +00:00
|
|
|
#else
|
2016-01-23 12:18:30 +00:00
|
|
|
title.append(QString(" [%1]").arg(custom_title));
|
2016-01-13 08:58:19 +00:00
|
|
|
#endif
|
2015-12-15 11:12:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
setWindowTitle(title);
|
2016-01-12 14:01:45 +00:00
|
|
|
setWindowFilePath(NULL);
|
2013-07-09 18:08:40 +00:00
|
|
|
}
|
|
|
|
|
2013-04-01 17:57:47 +00:00
|
|
|
void MainWindow::setTitlebarForCaptureInProgress()
|
|
|
|
{
|
2014-09-09 20:42:58 +00:00
|
|
|
if (capture_file_.capFile()) {
|
2015-12-15 11:12:27 +00:00
|
|
|
setWSWindowTitle(tr("Capturing from %1").arg(cf_get_tempfile_source(capture_file_.capFile())));
|
2013-04-01 17:57:47 +00:00
|
|
|
} else {
|
|
|
|
/* We have no capture in progress. */
|
2015-12-15 11:12:27 +00:00
|
|
|
setWSWindowTitle();
|
2013-04-01 17:57:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-31 22:25:51 +00:00
|
|
|
// Menu state
|
|
|
|
|
|
|
|
/* Enable or disable menu items based on whether you have a capture file
|
|
|
|
you've finished reading and, if you have one, whether it's been saved
|
|
|
|
and whether it could be saved except by copying the raw packet data. */
|
|
|
|
void MainWindow::setMenusForCaptureFile(bool force_disable)
|
|
|
|
{
|
2016-03-22 16:25:34 +00:00
|
|
|
bool enable = true;
|
|
|
|
bool can_write = false;
|
|
|
|
bool can_save = false;
|
Enable "Save As..." iff cf_can_save_as() returns TRUE.
Currently, cf_can_save() really means "*there's something to save* and
we can write it out"; "Save As..." should be enabled even if there are
no changes to save, in case the user just wants to write the existing
file contents out to a new file and have the new file be the current
file. That matches the behavior of the GTK+ version.
(We might want to enable "Save" even if there are no changes to save;
some other programs do that, such as the TextEdit, WordPad, KWrite, and
gedit simple text editors. If so, however, we should make "Save" write
stuff out even if there are no changes to save.
Note, however, that we're a bit different from most "editors", in that
we don't read the entire file into memory - we keep the file open and
read packet data from it, because we want to be able to read files that
won't fit into memory. That *might* change what we ultimately want to
do with "Save".)
Bug: 12630
Change-Id: I8a2327b5d6ddab7c4f0367f132460b507da38577
Reviewed-on: https://code.wireshark.org/review/16612
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2016-07-24 02:16:36 +00:00
|
|
|
bool can_save_as = false;
|
2016-03-22 16:25:34 +00:00
|
|
|
|
2014-09-09 20:42:58 +00:00
|
|
|
if (force_disable || capture_file_.capFile() == NULL || capture_file_.capFile()->state == FILE_READ_IN_PROGRESS) {
|
2012-08-31 22:25:51 +00:00
|
|
|
/* We have no capture file or we're currently reading a file */
|
2016-03-22 16:25:34 +00:00
|
|
|
enable = false;
|
2012-08-31 22:25:51 +00:00
|
|
|
} else {
|
2016-03-22 16:25:34 +00:00
|
|
|
/* We have a capture file. Can we write or save? */
|
|
|
|
can_write = cf_can_write_with_wiretap(capture_file_.capFile());
|
|
|
|
can_save = cf_can_save(capture_file_.capFile());
|
Enable "Save As..." iff cf_can_save_as() returns TRUE.
Currently, cf_can_save() really means "*there's something to save* and
we can write it out"; "Save As..." should be enabled even if there are
no changes to save, in case the user just wants to write the existing
file contents out to a new file and have the new file be the current
file. That matches the behavior of the GTK+ version.
(We might want to enable "Save" even if there are no changes to save;
some other programs do that, such as the TextEdit, WordPad, KWrite, and
gedit simple text editors. If so, however, we should make "Save" write
stuff out even if there are no changes to save.
Note, however, that we're a bit different from most "editors", in that
we don't read the entire file into memory - we keep the file open and
read packet data from it, because we want to be able to read files that
won't fit into memory. That *might* change what we ultimately want to
do with "Save".)
Bug: 12630
Change-Id: I8a2327b5d6ddab7c4f0367f132460b507da38577
Reviewed-on: https://code.wireshark.org/review/16612
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2016-07-24 02:16:36 +00:00
|
|
|
can_save_as = cf_can_save_as(capture_file_.capFile());
|
2016-03-22 16:25:34 +00:00
|
|
|
}
|
2012-08-31 22:25:51 +00:00
|
|
|
|
2016-03-22 16:25:34 +00:00
|
|
|
main_ui_->actionViewReload_as_File_Format_or_Capture->setEnabled(enable);
|
|
|
|
main_ui_->actionFileMerge->setEnabled(can_write);
|
|
|
|
main_ui_->actionFileClose->setEnabled(enable);
|
|
|
|
main_ui_->actionFileSave->setEnabled(can_save);
|
Enable "Save As..." iff cf_can_save_as() returns TRUE.
Currently, cf_can_save() really means "*there's something to save* and
we can write it out"; "Save As..." should be enabled even if there are
no changes to save, in case the user just wants to write the existing
file contents out to a new file and have the new file be the current
file. That matches the behavior of the GTK+ version.
(We might want to enable "Save" even if there are no changes to save;
some other programs do that, such as the TextEdit, WordPad, KWrite, and
gedit simple text editors. If so, however, we should make "Save" write
stuff out even if there are no changes to save.
Note, however, that we're a bit different from most "editors", in that
we don't read the entire file into memory - we keep the file open and
read packet data from it, because we want to be able to read files that
won't fit into memory. That *might* change what we ultimately want to
do with "Save".)
Bug: 12630
Change-Id: I8a2327b5d6ddab7c4f0367f132460b507da38577
Reviewed-on: https://code.wireshark.org/review/16612
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2016-07-24 02:16:36 +00:00
|
|
|
main_ui_->actionFileSaveAs->setEnabled(can_save_as);
|
2016-03-22 16:25:34 +00:00
|
|
|
main_ui_->actionStatisticsCaptureFileProperties->setEnabled(enable);
|
|
|
|
/*
|
|
|
|
* "Export Specified Packets..." should be available only if
|
|
|
|
* we can write the file out in at least one format.
|
|
|
|
*/
|
|
|
|
main_ui_->actionFileExportPackets->setEnabled(can_write);
|
|
|
|
|
|
|
|
main_ui_->actionFileExportAsCArrays->setEnabled(enable);
|
|
|
|
main_ui_->actionFileExportAsCSV->setEnabled(enable);
|
|
|
|
main_ui_->actionFileExportAsPDML->setEnabled(enable);
|
|
|
|
main_ui_->actionFileExportAsPlainText->setEnabled(enable);
|
|
|
|
main_ui_->actionFileExportAsPSML->setEnabled(enable);
|
2016-06-19 14:52:50 +00:00
|
|
|
main_ui_->actionFileExportAsJSON->setEnabled(enable);
|
2016-03-22 16:25:34 +00:00
|
|
|
|
|
|
|
main_ui_->actionFileExportPacketBytes->setEnabled(enable);
|
|
|
|
main_ui_->actionFileExportPDU->setEnabled(enable);
|
|
|
|
main_ui_->actionFileExportSSLSessionKeys->setEnabled(enable);
|
|
|
|
|
|
|
|
foreach (QAction *eo_action, main_ui_->menuFileExportObjects->actions()) {
|
|
|
|
eo_action->setEnabled(enable);
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
2016-03-22 16:25:34 +00:00
|
|
|
|
|
|
|
main_ui_->actionViewReload->setEnabled(enable);
|
2016-12-13 18:33:02 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_SOFTWARE_UPDATE
|
|
|
|
// We might want to enable or disable automatic checks here as well.
|
|
|
|
update_action_->setEnabled(!can_save);
|
|
|
|
#endif
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::setMenusForCaptureInProgress(bool capture_in_progress) {
|
|
|
|
/* Either a capture was started or stopped; in either case, it's not
|
|
|
|
in the process of stopping, so allow quitting. */
|
|
|
|
|
|
|
|
main_ui_->actionFileOpen->setEnabled(!capture_in_progress);
|
|
|
|
main_ui_->menuOpenRecentCaptureFile->setEnabled(!capture_in_progress);
|
2016-03-22 16:25:34 +00:00
|
|
|
|
|
|
|
main_ui_->actionFileExportAsCArrays->setEnabled(capture_in_progress);
|
|
|
|
main_ui_->actionFileExportAsCSV->setEnabled(capture_in_progress);
|
|
|
|
main_ui_->actionFileExportAsPDML->setEnabled(capture_in_progress);
|
|
|
|
main_ui_->actionFileExportAsPlainText->setEnabled(capture_in_progress);
|
|
|
|
main_ui_->actionFileExportAsPSML->setEnabled(capture_in_progress);
|
2016-06-19 14:52:50 +00:00
|
|
|
main_ui_->actionFileExportAsJSON->setEnabled(capture_in_progress);
|
2016-03-22 16:25:34 +00:00
|
|
|
|
2016-09-19 07:37:27 +00:00
|
|
|
main_ui_->actionFileExportPacketBytes->setEnabled(capture_in_progress);
|
2016-09-18 21:00:07 +00:00
|
|
|
main_ui_->actionFileExportPDU->setEnabled(!capture_in_progress);
|
2012-08-31 22:25:51 +00:00
|
|
|
main_ui_->actionFileExportSSLSessionKeys->setEnabled(capture_in_progress);
|
2016-03-22 16:25:34 +00:00
|
|
|
|
|
|
|
foreach (QAction *eo_action, main_ui_->menuFileExportObjects->actions()) {
|
|
|
|
eo_action->setEnabled(capture_in_progress);
|
|
|
|
}
|
|
|
|
|
2012-10-01 22:40:20 +00:00
|
|
|
main_ui_->menuFileSet->setEnabled(!capture_in_progress);
|
2012-08-31 22:25:51 +00:00
|
|
|
main_ui_->actionFileQuit->setEnabled(true);
|
2016-12-13 18:33:02 +00:00
|
|
|
#ifdef HAVE_SOFTWARE_UPDATE
|
|
|
|
// We might want to enable or disable automatic checks here as well.
|
|
|
|
update_action_->setEnabled(!capture_in_progress);
|
|
|
|
#endif
|
2012-08-31 22:25:51 +00:00
|
|
|
|
2014-11-12 22:24:16 +00:00
|
|
|
main_ui_->actionStatisticsCaptureFileProperties->setEnabled(capture_in_progress);
|
2013-07-09 18:08:40 +00:00
|
|
|
|
2014-10-05 19:23:33 +00:00
|
|
|
// XXX Fix packet list heading menu sensitivity
|
2012-08-31 22:25:51 +00:00
|
|
|
// set_menu_sensitivity(ui_manager_packet_list_heading, "/PacketListHeadingPopup/SortAscending",
|
|
|
|
// !capture_in_progress);
|
|
|
|
// set_menu_sensitivity(ui_manager_packet_list_heading, "/PacketListHeadingPopup/SortDescending",
|
|
|
|
// !capture_in_progress);
|
|
|
|
// set_menu_sensitivity(ui_manager_packet_list_heading, "/PacketListHeadingPopup/NoSorting",
|
|
|
|
// !capture_in_progress);
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
main_ui_->actionCaptureOptions->setEnabled(!capture_in_progress);
|
2014-09-18 21:09:55 +00:00
|
|
|
main_ui_->actionCaptureStart->setEnabled(!capture_in_progress);
|
|
|
|
main_ui_->actionCaptureStart->setChecked(capture_in_progress);
|
|
|
|
main_ui_->actionCaptureStop->setEnabled(capture_in_progress);
|
2012-08-31 22:25:51 +00:00
|
|
|
main_ui_->actionCaptureRestart->setEnabled(capture_in_progress);
|
2015-06-24 21:33:27 +00:00
|
|
|
main_ui_->actionCaptureRefreshInterfaces->setEnabled(!capture_in_progress);
|
2012-08-31 22:25:51 +00:00
|
|
|
#endif /* HAVE_LIBPCAP */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::setMenusForCaptureStopping() {
|
|
|
|
main_ui_->actionFileQuit->setEnabled(false);
|
2016-12-13 18:33:02 +00:00
|
|
|
#ifdef HAVE_SOFTWARE_UPDATE
|
|
|
|
update_action_->setEnabled(false);
|
|
|
|
#endif
|
2014-11-12 22:24:16 +00:00
|
|
|
main_ui_->actionStatisticsCaptureFileProperties->setEnabled(false);
|
2012-08-31 22:25:51 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
2014-09-18 21:09:55 +00:00
|
|
|
main_ui_->actionCaptureStart->setChecked(false);
|
|
|
|
main_ui_->actionCaptureStop->setEnabled(false);
|
2012-08-31 22:25:51 +00:00
|
|
|
main_ui_->actionCaptureRestart->setEnabled(false);
|
|
|
|
#endif /* HAVE_LIBPCAP */
|
|
|
|
}
|
|
|
|
|
2012-11-01 22:12:57 +00:00
|
|
|
void MainWindow::setForCapturedPackets(bool have_captured_packets)
|
|
|
|
{
|
|
|
|
main_ui_->actionFilePrint->setEnabled(have_captured_packets);
|
|
|
|
|
|
|
|
// set_menu_sensitivity(ui_manager_packet_list_menu, "/PacketListMenuPopup/Print",
|
|
|
|
// have_captured_packets);
|
|
|
|
|
2012-12-15 01:04:39 +00:00
|
|
|
main_ui_->actionEditFindPacket->setEnabled(have_captured_packets);
|
|
|
|
main_ui_->actionEditFindNext->setEnabled(have_captured_packets);
|
|
|
|
main_ui_->actionEditFindPrevious->setEnabled(have_captured_packets);
|
2012-11-01 22:12:57 +00:00
|
|
|
|
|
|
|
main_ui_->actionGoGoToPacket->setEnabled(have_captured_packets);
|
|
|
|
main_ui_->actionGoPreviousPacket->setEnabled(have_captured_packets);
|
|
|
|
main_ui_->actionGoNextPacket->setEnabled(have_captured_packets);
|
|
|
|
main_ui_->actionGoFirstPacket->setEnabled(have_captured_packets);
|
|
|
|
main_ui_->actionGoLastPacket->setEnabled(have_captured_packets);
|
2015-11-16 10:05:24 +00:00
|
|
|
main_ui_->actionGoNextConversationPacket->setEnabled(have_captured_packets);
|
|
|
|
main_ui_->actionGoPreviousConversationPacket->setEnabled(have_captured_packets);
|
2012-11-01 22:12:57 +00:00
|
|
|
|
2014-09-23 20:35:10 +00:00
|
|
|
main_ui_->actionViewZoomIn->setEnabled(have_captured_packets);
|
|
|
|
main_ui_->actionViewZoomOut->setEnabled(have_captured_packets);
|
|
|
|
main_ui_->actionViewNormalSize->setEnabled(have_captured_packets);
|
|
|
|
main_ui_->actionViewResizeColumns->setEnabled(have_captured_packets);
|
|
|
|
|
2015-02-03 16:39:14 +00:00
|
|
|
main_ui_->actionStatisticsCaptureFileProperties->setEnabled(have_captured_packets);
|
|
|
|
main_ui_->actionStatisticsProtocolHierarchy->setEnabled(have_captured_packets);
|
Add a Qt I/O Graph dialog.
For each graph you can set:
- Its visibility
- A name
- A display filter
- Color, from a fixed list
- Plot style: Line, Impulse, Bar, Stacked Bar, Dot, Square, Diamond
- Basic Y Axes (packets/s, bytes/s, bits/s)
- Computed Y Axes (SUM, MIN, AVG, MAX)
- Smoothing
You can pan and zoom using the mouse and keyboard. Clicking on a graph
selects the last packet for that interval. If all graphs have the same Y
axis a single label is shown, otherwise a legend is shown.
The time scale (X axis) can be toggled between relative seconds and the
time of day.
Graphs can be saved as PDF, PNG, BMP, and JPEG. Settings are "sticky"
via the io_graphs UAT.
To do:
- Minimize graph drawing delays.
- Figure out why smoothing differs from GTK+
- Everything else at the top of io_graph_dialog.cpp
- Fix empty resets.
A fair amount of code was copied from TCPStreamDialog. We might want to
subclass QCustomPlot and place the shared code there.
Move common syntax checking to SyntaxLineEdit.
Move some common code from ui/gtk/io_stat.c to ui/io_graph_item.[ch] and
use it in both GTK+ and Qt.
Make the io_graph_item_t array allocation in io_stat.c static. The
behavior should be identical and this gives us additional compile-time
checks.
Change-Id: I9a3d544469b7048f0761fdbf7bcf20f44ae76577
Reviewed-on: https://code.wireshark.org/review/435
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Tested-by: Gerald Combs <gerald@wireshark.org>
2014-02-12 00:07:10 +00:00
|
|
|
main_ui_->actionStatisticsIOGraph->setEnabled(have_captured_packets);
|
2012-11-01 22:12:57 +00:00
|
|
|
}
|
|
|
|
|
2012-10-01 22:40:20 +00:00
|
|
|
void MainWindow::setMenusForFileSet(bool enable_list_files) {
|
|
|
|
bool enable_next = fileset_get_next() != NULL && enable_list_files;
|
|
|
|
bool enable_prev = fileset_get_previous() != NULL && enable_list_files;
|
|
|
|
|
|
|
|
main_ui_->actionFileSetListFiles->setEnabled(enable_list_files);
|
|
|
|
main_ui_->actionFileSetNextFile->setEnabled(enable_next);
|
|
|
|
main_ui_->actionFileSetPreviousFile->setEnabled(enable_prev);
|
|
|
|
}
|
|
|
|
|
2015-10-29 18:47:41 +00:00
|
|
|
void MainWindow::setWindowIcon(const QIcon &icon) {
|
|
|
|
wsApp->setWindowIcon(icon);
|
|
|
|
QMainWindow::setWindowIcon(icon);
|
|
|
|
}
|
|
|
|
|
2012-08-31 22:25:51 +00:00
|
|
|
void MainWindow::updateForUnsavedChanges() {
|
2013-03-31 22:59:56 +00:00
|
|
|
setTitlebarForCaptureFile();
|
2012-08-31 22:25:51 +00:00
|
|
|
setMenusForCaptureFile();
|
|
|
|
}
|
|
|
|
|
2014-06-16 22:20:16 +00:00
|
|
|
void MainWindow::changeEvent(QEvent* event)
|
|
|
|
{
|
2013-12-21 16:55:43 +00:00
|
|
|
if (0 != event)
|
2014-06-16 22:20:16 +00:00
|
|
|
{
|
2013-12-21 16:55:43 +00:00
|
|
|
switch (event->type())
|
2014-06-16 22:20:16 +00:00
|
|
|
{
|
|
|
|
case QEvent::LanguageChange:
|
|
|
|
main_ui_->retranslateUi(this);
|
2015-10-31 11:53:49 +00:00
|
|
|
// make sure that the "Clear Menu" item is retranslated
|
2015-07-08 23:48:58 +00:00
|
|
|
wsApp->emitAppSignal(WiresharkApplication::RecentCapturesChanged);
|
2014-06-16 22:20:16 +00:00
|
|
|
break;
|
2013-12-21 16:55:43 +00:00
|
|
|
case QEvent::LocaleChange:{
|
|
|
|
QString locale = QLocale::system().name();
|
|
|
|
locale.truncate(locale.lastIndexOf('_'));
|
|
|
|
wsApp->loadLanguage(locale);
|
|
|
|
}
|
|
|
|
break;
|
2016-10-19 18:53:40 +00:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
|
|
|
case QEvent::WindowStateChange:
|
|
|
|
main_ui_->actionViewFullScreen->setChecked(this->isFullScreen());
|
|
|
|
break;
|
|
|
|
#endif
|
2014-06-16 22:20:16 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-12-21 16:55:43 +00:00
|
|
|
QMainWindow::changeEvent(event);
|
2014-06-16 22:20:16 +00:00
|
|
|
}
|
|
|
|
|
2016-04-29 21:33:44 +00:00
|
|
|
void MainWindow::resizeEvent(QResizeEvent *event)
|
2016-04-27 23:53:03 +00:00
|
|
|
{
|
|
|
|
df_combo_box_->setMinimumWidth(width() * 2 / 3); // Arbitrary
|
2016-04-29 21:33:44 +00:00
|
|
|
QMainWindow::resizeEvent(event);
|
2016-04-27 23:53:03 +00:00
|
|
|
}
|
|
|
|
|
2012-08-31 22:25:51 +00:00
|
|
|
/* Update main window items based on whether there's a capture in progress. */
|
2017-04-15 21:30:30 +00:00
|
|
|
void MainWindow::setForCaptureInProgress(bool capture_in_progress, GArray *ifaces)
|
2012-08-31 22:25:51 +00:00
|
|
|
{
|
|
|
|
setMenusForCaptureInProgress(capture_in_progress);
|
|
|
|
|
2015-06-11 22:05:44 +00:00
|
|
|
wireless_frame_->setCaptureInProgress(capture_in_progress);
|
|
|
|
|
2015-02-20 14:30:23 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
packet_list_->setCaptureInProgress(capture_in_progress);
|
2016-06-24 19:59:07 +00:00
|
|
|
packet_list_->setVerticalAutoScroll(capture_in_progress && main_ui_->actionGoAutoScroll->isChecked());
|
2012-08-31 22:25:51 +00:00
|
|
|
|
|
|
|
// set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
|
2015-02-20 14:30:23 +00:00
|
|
|
#endif
|
2017-04-15 21:30:30 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_EXTCAP
|
|
|
|
QList<InterfaceToolbar *> toolbars = findChildren<InterfaceToolbar *>();
|
|
|
|
foreach (InterfaceToolbar *toolbar, toolbars) {
|
|
|
|
if (capture_in_progress && ifaces) {
|
2017-04-28 19:26:53 +00:00
|
|
|
toolbar->startCapture(ifaces);
|
2017-04-15 21:30:30 +00:00
|
|
|
} else {
|
|
|
|
toolbar->stopCapture();
|
|
|
|
}
|
|
|
|
}
|
2017-04-26 04:47:29 +00:00
|
|
|
#else
|
2017-04-26 06:28:48 +00:00
|
|
|
Q_UNUSED(ifaces)
|
2017-04-15 21:30:30 +00:00
|
|
|
#endif
|
2012-08-31 22:25:51 +00:00
|
|
|
}
|
|
|
|
|
2015-08-11 12:08:08 +00:00
|
|
|
static QList<register_stat_group_t> menu_groups = QList<register_stat_group_t>()
|
2015-07-08 22:44:04 +00:00
|
|
|
<< REGISTER_ANALYZE_GROUP_UNSORTED
|
|
|
|
<< REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER
|
|
|
|
<< REGISTER_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_TELEPHONY
|
|
|
|
<< REGISTER_STAT_GROUP_TELEPHONY_ANSI
|
|
|
|
<< REGISTER_STAT_GROUP_TELEPHONY_GSM
|
|
|
|
<< REGISTER_STAT_GROUP_TELEPHONY_LTE
|
2015-08-31 19:24:48 +00:00
|
|
|
<< REGISTER_STAT_GROUP_TELEPHONY_MTP3
|
2015-07-08 22:44:04 +00:00
|
|
|
<< REGISTER_STAT_GROUP_TELEPHONY_SCTP
|
|
|
|
<< REGISTER_TOOLS_GROUP_UNSORTED;
|
|
|
|
|
2015-08-11 12:08:08 +00:00
|
|
|
void MainWindow::addMenuActions(QList<QAction *> &actions, int menu_group)
|
|
|
|
{
|
|
|
|
foreach (QAction *action, actions) {
|
|
|
|
switch (menu_group) {
|
|
|
|
case REGISTER_ANALYZE_GROUP_UNSORTED:
|
|
|
|
case REGISTER_STAT_GROUP_UNSORTED:
|
|
|
|
main_ui_->menuStatistics->insertAction(
|
2015-07-08 22:44:04 +00:00
|
|
|
main_ui_->actionStatistics_REGISTER_STAT_GROUP_UNSORTED,
|
|
|
|
action);
|
2015-08-11 12:08:08 +00:00
|
|
|
break;
|
|
|
|
case REGISTER_STAT_GROUP_RESPONSE_TIME:
|
|
|
|
main_ui_->menuServiceResponseTime->addAction(action);
|
|
|
|
break;
|
|
|
|
case REGISTER_STAT_GROUP_TELEPHONY:
|
|
|
|
main_ui_->menuTelephony->addAction(action);
|
|
|
|
break;
|
|
|
|
case REGISTER_STAT_GROUP_TELEPHONY_ANSI:
|
|
|
|
main_ui_->menuANSI->addAction(action);
|
|
|
|
break;
|
|
|
|
case REGISTER_STAT_GROUP_TELEPHONY_GSM:
|
|
|
|
main_ui_->menuGSM->addAction(action);
|
|
|
|
break;
|
2015-09-09 18:50:24 +00:00
|
|
|
case REGISTER_STAT_GROUP_TELEPHONY_LTE:
|
|
|
|
main_ui_->menuLTE->addAction(action);
|
|
|
|
break;
|
2015-08-31 19:24:48 +00:00
|
|
|
case REGISTER_STAT_GROUP_TELEPHONY_MTP3:
|
|
|
|
main_ui_->menuMTP3->addAction(action);
|
|
|
|
break;
|
2015-08-11 12:08:08 +00:00
|
|
|
case REGISTER_TOOLS_GROUP_UNSORTED:
|
|
|
|
{
|
|
|
|
// Allow the creation of submenus. Mimics the behavor of
|
|
|
|
// ui/gtk/main_menubar.c:add_menu_item_to_main_menubar
|
|
|
|
// and GtkUIManager.
|
|
|
|
//
|
|
|
|
// For now we limit the insanity to the "Tools" menu.
|
|
|
|
QStringList menu_path = action->text().split('/');
|
|
|
|
QMenu *cur_menu = main_ui_->menuTools;
|
|
|
|
while (menu_path.length() > 1) {
|
|
|
|
QString menu_title = menu_path.takeFirst();
|
|
|
|
#if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0))
|
|
|
|
QMenu *submenu = cur_menu->findChild<QMenu *>(menu_title.toLower(), Qt::FindDirectChildrenOnly);
|
|
|
|
#else
|
|
|
|
QMenu *submenu = cur_menu->findChild<QMenu *>(menu_title.toLower());
|
|
|
|
if (submenu && submenu->parent() != cur_menu) submenu = NULL;
|
|
|
|
#endif
|
|
|
|
if (!submenu) {
|
|
|
|
submenu = cur_menu->addMenu(menu_title);
|
|
|
|
submenu->setObjectName(menu_title.toLower());
|
2015-07-08 22:44:04 +00:00
|
|
|
}
|
2015-08-11 12:08:08 +00:00
|
|
|
cur_menu = submenu;
|
2015-07-08 22:44:04 +00:00
|
|
|
}
|
2015-08-11 12:08:08 +00:00
|
|
|
action->setText(menu_path.last());
|
|
|
|
cur_menu->addAction(action);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
// qDebug() << "FIX: Add" << action->text() << "to the menu";
|
|
|
|
break;
|
|
|
|
}
|
2015-06-05 20:17:13 +00:00
|
|
|
|
2015-08-11 12:08:08 +00:00
|
|
|
// Connect each action type to its corresponding slot. We to
|
|
|
|
// 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()));
|
|
|
|
} else if (action->objectName() == FunnelStatistics::actionName()) {
|
|
|
|
connect(action, SIGNAL(triggered(bool)), funnel_statistics_, SLOT(funnelActionTriggered()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void MainWindow::removeMenuActions(QList<QAction *> &actions, int menu_group)
|
|
|
|
{
|
|
|
|
foreach (QAction *action, actions) {
|
|
|
|
switch (menu_group) {
|
|
|
|
case REGISTER_ANALYZE_GROUP_UNSORTED:
|
|
|
|
case REGISTER_STAT_GROUP_UNSORTED:
|
|
|
|
main_ui_->menuStatistics->removeAction(action);
|
|
|
|
break;
|
|
|
|
case REGISTER_STAT_GROUP_RESPONSE_TIME:
|
|
|
|
main_ui_->menuServiceResponseTime->removeAction(action);
|
|
|
|
break;
|
|
|
|
case REGISTER_STAT_GROUP_TELEPHONY:
|
|
|
|
main_ui_->menuTelephony->removeAction(action);
|
|
|
|
break;
|
|
|
|
case REGISTER_STAT_GROUP_TELEPHONY_ANSI:
|
|
|
|
main_ui_->menuANSI->removeAction(action);
|
|
|
|
break;
|
|
|
|
case REGISTER_STAT_GROUP_TELEPHONY_GSM:
|
|
|
|
main_ui_->menuGSM->removeAction(action);
|
|
|
|
break;
|
2015-09-09 18:50:24 +00:00
|
|
|
case REGISTER_STAT_GROUP_TELEPHONY_LTE:
|
|
|
|
main_ui_->menuLTE->removeAction(action);
|
|
|
|
break;
|
2015-08-31 19:24:48 +00:00
|
|
|
case REGISTER_STAT_GROUP_TELEPHONY_MTP3:
|
|
|
|
main_ui_->menuMTP3->removeAction(action);
|
|
|
|
break;
|
2015-08-11 12:08:08 +00:00
|
|
|
case REGISTER_TOOLS_GROUP_UNSORTED:
|
|
|
|
{
|
|
|
|
// Allow removal of submenus.
|
|
|
|
// For now we limit the insanity to the "Tools" menu.
|
|
|
|
QStringList menu_path = action->text().split('/');
|
|
|
|
QMenu *cur_menu = main_ui_->menuTools;
|
|
|
|
while (menu_path.length() > 1) {
|
|
|
|
QString menu_title = menu_path.takeFirst();
|
|
|
|
#if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0))
|
|
|
|
QMenu *submenu = cur_menu->findChild<QMenu *>(menu_title.toLower(), Qt::FindDirectChildrenOnly);
|
|
|
|
#else
|
|
|
|
QMenu *submenu = cur_menu->findChild<QMenu *>(menu_title.toLower());
|
|
|
|
if (submenu && submenu->parent() != cur_menu) submenu = NULL;
|
|
|
|
#endif
|
|
|
|
cur_menu = submenu;
|
2015-07-08 22:44:04 +00:00
|
|
|
}
|
2015-08-11 12:08:08 +00:00
|
|
|
cur_menu->removeAction(action);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
// qDebug() << "FIX: Remove" << action->text() << "from the menu";
|
|
|
|
break;
|
2015-07-08 22:44:04 +00:00
|
|
|
}
|
2015-06-05 20:17:13 +00:00
|
|
|
}
|
2015-08-11 12:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::addDynamicMenus()
|
|
|
|
{
|
|
|
|
// Manual additions
|
|
|
|
wsApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_GSM, main_ui_->actionTelephonyGsmMapSummary);
|
2015-09-20 07:42:11 +00:00
|
|
|
wsApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_LTE, main_ui_->actionTelephonyLteMacStatistics);
|
2015-09-28 10:38:29 +00:00
|
|
|
wsApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_LTE, main_ui_->actionTelephonyLteRlcStatistics);
|
2015-10-10 22:53:45 +00:00
|
|
|
wsApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_LTE, main_ui_->actionTelephonyLteRlcGraph);
|
2015-08-31 19:24:48 +00:00
|
|
|
wsApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_MTP3, main_ui_->actionTelephonyMtp3Summary);
|
2015-10-25 00:45:51 +00:00
|
|
|
wsApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY, main_ui_->actionTelephonySipFlows);
|
2015-08-11 12:08:08 +00:00
|
|
|
|
|
|
|
// Fill in each menu
|
|
|
|
foreach (register_stat_group_t menu_group, menu_groups) {
|
|
|
|
QList<QAction *>actions = wsApp->dynamicMenuGroupItems(menu_group);
|
|
|
|
addMenuActions(actions, menu_group);
|
|
|
|
}
|
2015-07-07 23:18:00 +00:00
|
|
|
|
2015-07-08 22:44:04 +00:00
|
|
|
// Empty menus don't show up: https://bugreports.qt.io/browse/QTBUG-33728
|
2016-06-01 01:29:39 +00:00
|
|
|
// We've added a placeholder in order to make sure some menus are visible.
|
|
|
|
// Hide them as needed.
|
2015-07-08 22:44:04 +00:00
|
|
|
if (wsApp->dynamicMenuGroupItems(REGISTER_STAT_GROUP_TELEPHONY_ANSI).length() > 0) {
|
|
|
|
main_ui_->actionTelephonyANSIPlaceholder->setVisible(false);
|
2015-07-07 23:18:00 +00:00
|
|
|
}
|
2015-08-31 19:24:48 +00:00
|
|
|
if (wsApp->dynamicMenuGroupItems(REGISTER_STAT_GROUP_TELEPHONY_GSM).length() > 0) {
|
|
|
|
main_ui_->actionTelephonyGSMPlaceholder->setVisible(false);
|
|
|
|
}
|
2015-09-09 18:50:24 +00:00
|
|
|
if (wsApp->dynamicMenuGroupItems(REGISTER_STAT_GROUP_TELEPHONY_LTE).length() > 0) {
|
|
|
|
main_ui_->actionTelephonyLTEPlaceholder->setVisible(false);
|
|
|
|
}
|
2015-08-31 19:24:48 +00:00
|
|
|
if (wsApp->dynamicMenuGroupItems(REGISTER_STAT_GROUP_TELEPHONY_MTP3).length() > 0) {
|
|
|
|
main_ui_->actionTelephonyMTP3Placeholder->setVisible(false);
|
|
|
|
}
|
2015-06-05 20:17:13 +00:00
|
|
|
}
|
|
|
|
|
2015-08-11 12:08:08 +00:00
|
|
|
void MainWindow::reloadDynamicMenus()
|
|
|
|
{
|
|
|
|
foreach (register_stat_group_t menu_group, menu_groups) {
|
|
|
|
QList<QAction *>actions = wsApp->removedMenuGroupItems(menu_group);
|
|
|
|
removeMenuActions(actions, menu_group);
|
|
|
|
|
|
|
|
actions = wsApp->addedMenuGroupItems(menu_group);
|
|
|
|
addMenuActions(actions, menu_group);
|
|
|
|
}
|
|
|
|
|
|
|
|
wsApp->clearAddedMenuGroupItems();
|
|
|
|
wsApp->clearRemovedMenuGroupItems();
|
|
|
|
}
|
|
|
|
|
2015-03-30 14:10:01 +00:00
|
|
|
void MainWindow::externalMenuHelper(ext_menu_t * menu, QMenu * subMenu, gint depth)
|
|
|
|
{
|
|
|
|
QAction * itemAction = NULL;
|
|
|
|
ext_menubar_t * item = NULL;
|
|
|
|
GList * children = NULL;
|
|
|
|
|
|
|
|
/* There must exists an xpath parent */
|
|
|
|
g_assert(subMenu != NULL);
|
|
|
|
|
|
|
|
/* If the depth counter exceeds, something must have gone wrong */
|
|
|
|
g_assert(depth < EXT_MENUBAR_MAX_DEPTH);
|
|
|
|
|
|
|
|
children = menu->children;
|
|
|
|
/* Iterate the child entries */
|
2016-01-23 12:18:30 +00:00
|
|
|
while (children && children->data) {
|
2015-03-30 14:10:01 +00:00
|
|
|
item = (ext_menubar_t *) children->data;
|
|
|
|
|
2016-01-23 12:18:30 +00:00
|
|
|
if (item->type == EXT_MENUBAR_MENU) {
|
2015-03-30 14:10:01 +00:00
|
|
|
/* Handle Submenu entry */
|
2016-01-23 12:18:30 +00:00
|
|
|
this->externalMenuHelper(item, subMenu->addMenu(item->label), depth++);
|
|
|
|
} else if (item->type == EXT_MENUBAR_SEPARATOR) {
|
2015-03-30 14:10:01 +00:00
|
|
|
subMenu->addSeparator();
|
2016-01-23 12:18:30 +00:00
|
|
|
} else if (item->type == EXT_MENUBAR_ITEM || item->type == EXT_MENUBAR_URL) {
|
2015-03-30 14:10:01 +00:00
|
|
|
itemAction = subMenu->addAction(item->name);
|
|
|
|
itemAction->setData(QVariant::fromValue((void *)item));
|
|
|
|
itemAction->setText(item->label);
|
|
|
|
connect(itemAction, SIGNAL(triggered()),
|
2015-05-03 16:01:29 +00:00
|
|
|
this, SLOT(externalMenuItem_triggered()));
|
2015-03-30 14:10:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Iterate Loop */
|
|
|
|
children = g_list_next(children);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-09 12:36:53 +00:00
|
|
|
QMenu * MainWindow::searchSubMenu(QString objectName)
|
|
|
|
{
|
|
|
|
QList<QMenu*> lst;
|
|
|
|
|
2016-01-23 12:18:30 +00:00
|
|
|
if (objectName.length() > 0) {
|
2015-08-09 12:36:53 +00:00
|
|
|
QString searchName = QString("menu") + objectName;
|
|
|
|
|
|
|
|
lst = main_ui_->menuBar->findChildren<QMenu*>();
|
2016-01-23 12:18:30 +00:00
|
|
|
foreach (QMenu* m, lst) {
|
|
|
|
if (QString::compare(m->objectName(), searchName) == 0)
|
2015-08-09 12:36:53 +00:00
|
|
|
return m;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-01-24 16:34:07 +00:00
|
|
|
void MainWindow::addPluginIFStructures()
|
2015-03-30 14:10:01 +00:00
|
|
|
{
|
2017-02-24 08:49:11 +00:00
|
|
|
GList *user_menu = ext_menubar_get_entries();
|
2015-03-30 14:10:01 +00:00
|
|
|
|
2016-01-23 12:18:30 +00:00
|
|
|
while (user_menu && user_menu->data) {
|
2017-02-24 08:49:11 +00:00
|
|
|
QMenu *subMenu = NULL;
|
|
|
|
ext_menu_t *menu = (ext_menu_t *) user_menu->data;
|
2015-03-30 14:10:01 +00:00
|
|
|
|
|
|
|
/* On this level only menu items should exist. Not doing an assert here,
|
|
|
|
* as it could be an honest mistake */
|
2016-01-23 12:18:30 +00:00
|
|
|
if (menu->type != EXT_MENUBAR_MENU) {
|
2015-03-30 14:10:01 +00:00
|
|
|
user_menu = g_list_next(user_menu);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create main submenu and add it to the menubar */
|
2016-01-23 12:18:30 +00:00
|
|
|
if (menu->parent_menu) {
|
2017-02-24 08:49:11 +00:00
|
|
|
QMenu *sortUnderneath = searchSubMenu(QString(menu->parent_menu));
|
2016-01-23 12:18:30 +00:00
|
|
|
if (sortUnderneath)
|
2015-08-09 12:36:53 +00:00
|
|
|
subMenu = sortUnderneath->addMenu(menu->label);
|
|
|
|
}
|
|
|
|
|
2016-01-23 12:18:30 +00:00
|
|
|
if (!subMenu)
|
2015-08-09 12:36:53 +00:00
|
|
|
subMenu = main_ui_->menuBar->addMenu(menu->label);
|
2015-03-30 14:10:01 +00:00
|
|
|
|
|
|
|
/* This will generate the action structure for each menu. It is recursive,
|
|
|
|
* therefore a sub-routine, and we have a depth counter to prevent endless loops. */
|
|
|
|
this->externalMenuHelper(menu, subMenu, 0);
|
|
|
|
|
|
|
|
/* Iterate Loop */
|
|
|
|
user_menu = g_list_next (user_menu);
|
|
|
|
}
|
2017-01-24 16:34:07 +00:00
|
|
|
|
|
|
|
int cntToolbars = 0;
|
|
|
|
|
2017-04-18 08:03:00 +00:00
|
|
|
QMenu *tbMenu = main_ui_->menuAdditionalToolbars;
|
2017-02-24 08:49:11 +00:00
|
|
|
GList *if_toolbars = ext_toolbar_get_entries();
|
|
|
|
while (if_toolbars && if_toolbars->data) {
|
|
|
|
ext_toolbar_t *toolbar = (ext_toolbar_t*) if_toolbars->data;
|
2017-01-24 16:34:07 +00:00
|
|
|
|
2017-02-24 08:49:11 +00:00
|
|
|
if (toolbar->type != EXT_TOOLBAR_BAR) {
|
|
|
|
if_toolbars = g_list_next (if_toolbars);
|
2017-01-24 16:34:07 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool visible = g_list_find_custom(recent.gui_additional_toolbars, toolbar->name, (GCompareFunc) strcmp) ? true : false;
|
|
|
|
|
2017-02-27 18:25:20 +00:00
|
|
|
AdditionalToolBar *ifToolBar = AdditionalToolBar::create(this, toolbar);
|
2017-01-24 16:34:07 +00:00
|
|
|
|
2017-02-24 08:49:11 +00:00
|
|
|
if (ifToolBar) {
|
2017-02-27 18:25:20 +00:00
|
|
|
ifToolBar->setVisible(visible);
|
|
|
|
|
2017-02-24 08:49:11 +00:00
|
|
|
QAction *iftbAction = new QAction(QString(toolbar->name), this);
|
2017-01-24 16:34:07 +00:00
|
|
|
iftbAction->setToolTip(toolbar->tooltip);
|
|
|
|
iftbAction->setEnabled(true);
|
|
|
|
iftbAction->setCheckable(true);
|
|
|
|
iftbAction->setChecked(visible);
|
|
|
|
iftbAction->setToolTip(tr("Show or hide the toolbar"));
|
|
|
|
iftbAction->setData(VariantPointer<ext_toolbar_t>::asQVariant(toolbar));
|
|
|
|
|
2017-02-24 08:49:11 +00:00
|
|
|
QAction *before = 0;
|
2017-01-24 16:34:07 +00:00
|
|
|
|
2017-02-24 08:49:11 +00:00
|
|
|
foreach (QAction *action, tbMenu->actions()) {
|
2017-01-24 16:34:07 +00:00
|
|
|
/* Ensure we add the menu entries in sorted order */
|
2017-02-24 08:49:11 +00:00
|
|
|
if (action->text().compare(toolbar->name, Qt::CaseInsensitive) > 0) {
|
2017-01-24 16:34:07 +00:00
|
|
|
before = action;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tbMenu->insertAction(before, iftbAction);
|
|
|
|
|
|
|
|
addToolBar(Qt::TopToolBarArea, ifToolBar);
|
|
|
|
insertToolBarBreak(ifToolBar);
|
|
|
|
|
2017-02-24 08:49:11 +00:00
|
|
|
if (show_hide_actions_)
|
2017-01-24 16:34:07 +00:00
|
|
|
show_hide_actions_->addAction(iftbAction);
|
|
|
|
|
|
|
|
cntToolbars++;
|
|
|
|
}
|
|
|
|
|
2017-02-24 08:49:11 +00:00
|
|
|
if_toolbars = g_list_next (if_toolbars);
|
2017-01-24 16:34:07 +00:00
|
|
|
}
|
|
|
|
|
2017-02-24 08:49:11 +00:00
|
|
|
if (cntToolbars)
|
2017-01-24 16:34:07 +00:00
|
|
|
tbMenu->menuAction()->setVisible(true);
|
2015-03-30 14:10:01 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 16:34:07 +00:00
|
|
|
void MainWindow::removeAdditionalToolbar(QString toolbarName)
|
|
|
|
{
|
2017-02-24 08:49:11 +00:00
|
|
|
if (toolbarName.length() == 0)
|
2017-01-24 16:34:07 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
QList<QToolBar *> toolbars = findChildren<QToolBar *>();
|
2017-02-24 08:49:11 +00:00
|
|
|
foreach(QToolBar *tb, toolbars) {
|
|
|
|
AdditionalToolBar *ifToolBar = dynamic_cast<AdditionalToolBar *>(tb);
|
2017-01-24 16:34:07 +00:00
|
|
|
|
2017-02-24 08:49:11 +00:00
|
|
|
if (ifToolBar && ifToolBar->menuName().compare(toolbarName)) {
|
2017-12-14 18:29:48 +00:00
|
|
|
GList *entry = g_list_find_custom(recent.gui_additional_toolbars, qUtf8Printable(ifToolBar->menuName()), (GCompareFunc) strcmp);
|
2017-01-24 16:34:07 +00:00
|
|
|
if (entry) {
|
|
|
|
recent.gui_additional_toolbars = g_list_remove(recent.gui_additional_toolbars, entry->data);
|
|
|
|
}
|
2017-04-18 08:03:00 +00:00
|
|
|
QList<QAction *> actions = main_ui_->menuAdditionalToolbars->actions();
|
2017-02-24 08:49:11 +00:00
|
|
|
foreach(QAction *action, actions) {
|
|
|
|
ext_toolbar_t *item = VariantPointer<ext_toolbar_t>::asPtr(action->data());
|
|
|
|
if (item && ifToolBar->menuName().compare(item->name)) {
|
|
|
|
if (show_hide_actions_)
|
2017-01-24 16:34:07 +00:00
|
|
|
show_hide_actions_->removeAction(action);
|
2017-04-18 08:03:00 +00:00
|
|
|
main_ui_->menuAdditionalToolbars->removeAction(action);
|
2017-01-24 16:34:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-11-05 10:39:54 +00:00
|
|
|
QString MainWindow::getMwFileName()
|
|
|
|
{
|
|
|
|
return mwFileName_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::setMwFileName(QString fileName)
|
|
|
|
{
|
|
|
|
mwFileName_ = fileName;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-10-30 12:58:28 +00:00
|
|
|
void MainWindow::createByteViewDialog()
|
|
|
|
{
|
|
|
|
byte_view_tab_ = new ByteViewTab(&master_split_);
|
|
|
|
}
|
2017-01-24 16:34:07 +00:00
|
|
|
|
2012-09-04 08:18:31 +00:00
|
|
|
/*
|
|
|
|
* Editor modelines
|
|
|
|
*
|
|
|
|
* Local Variables:
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
|
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
|
|
*/
|