aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--color_filters.c2
-rw-r--r--color_filters.h2
-rw-r--r--epan/funnel.c1
-rw-r--r--epan/funnel.h52
-rw-r--r--epan/wslua/wslua.h2
-rw-r--r--epan/wslua/wslua_gui.c14
-rw-r--r--ui/cli/tap-funnel.c1
-rw-r--r--ui/gtk/funnel_stat.c34
-rw-r--r--ui/qt/CMakeLists.txt8
-rw-r--r--ui/qt/Makefile.am4
-rw-r--r--ui/qt/Makefile.common10
-rw-r--r--ui/qt/Wireshark.pro8
-rw-r--r--ui/qt/capture_file.cpp7
-rw-r--r--ui/qt/capture_file.h3
-rw-r--r--ui/qt/capture_file_progress_frame.cpp21
-rw-r--r--ui/qt/funnel_statistics.cpp302
-rw-r--r--ui/qt/funnel_statistics.h76
-rw-r--r--ui/qt/funnel_string_dialog.cpp101
-rw-r--r--ui/qt/funnel_string_dialog.h75
-rw-r--r--ui/qt/funnel_string_dialog.ui67
-rw-r--r--ui/qt/funnel_text_dialog.cpp239
-rw-r--r--ui/qt/funnel_text_dialog.h98
-rw-r--r--ui/qt/funnel_text_dialog.ui88
-rw-r--r--ui/qt/main_window.cpp47
-rw-r--r--ui/qt/main_window.h6
-rw-r--r--ui/qt/main_window.ui21
-rw-r--r--ui/qt/wireshark_application.cpp21
-rw-r--r--ui/qt/wireshark_application.h2
28 files changed, 1255 insertions, 57 deletions
diff --git a/color_filters.c b/color_filters.c
index 0cb8e6b57a..834c626c26 100644
--- a/color_filters.c
+++ b/color_filters.c
@@ -139,7 +139,7 @@ color_filters_find_by_name_cb(gconstpointer arg1, gconstpointer arg2)
/* Set the filter off a temporary colorfilters and enable it */
void
-color_filters_set_tmp(guint8 filt_nr, gchar *filter, gboolean disabled)
+color_filters_set_tmp(guint8 filt_nr, const gchar *filter, gboolean disabled)
{
gchar *name = NULL;
const gchar *tmpfilter = NULL;
diff --git a/color_filters.h b/color_filters.h
index 7fe8068011..098d1c5833 100644
--- a/color_filters.h
+++ b/color_filters.h
@@ -85,7 +85,7 @@ color_filters_enable(gboolean enable);
* @param disabled whether the filter-rule should be disabled
*/
void
-color_filters_set_tmp(guint8 filt_nr, gchar *filter, gboolean disabled);
+color_filters_set_tmp(guint8 filt_nr, const gchar *filter, gboolean disabled);
/** Reset the temporary color filters
*
diff --git a/epan/funnel.c b/epan/funnel.c
index 876f84b57e..02cd4f1171 100644
--- a/epan/funnel.c
+++ b/epan/funnel.c
@@ -37,6 +37,7 @@ typedef struct _funnel_menu_t {
struct _funnel_menu_t* next;
} funnel_menu_t;
+/* XXX This assumes one main window and one capture file. */
static const funnel_ops_t* ops = NULL;
static funnel_menu_t* menus = NULL;
diff --git a/epan/funnel.h b/epan/funnel.h
index 3d66f54c63..b7e2ac1d01 100644
--- a/epan/funnel.h
+++ b/epan/funnel.h
@@ -23,17 +23,22 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef _FUNNEL_H
-#define _FUNNEL_H
+#ifndef __FUNNEL_H__
+#define __FUNNEL_H__
#include <glib.h>
#include <epan/stat_groups.h>
#include "ws_symbol_export.h"
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _funnel_ops_id_t funnel_ops_id_t; /* Opaque pointer to ops instance */
typedef struct _funnel_progress_window_t funnel_progress_window_t ;
typedef struct _funnel_text_window_t funnel_text_window_t ;
-typedef struct _funnel_tree_window_t funnel_tree_window_t ;
-typedef struct _funnel_node_t funnel_node_t ;
+typedef struct _funnel_tree_window_t funnel_tree_window_t ; /* XXX Unused? */
+typedef struct _funnel_node_t funnel_node_t ; /* XXX Unused? */
typedef void (*text_win_close_cb_t)(void*);
@@ -49,17 +54,20 @@ typedef struct _funnel_bt_t {
void (*free_data_fcn)(void*);
} funnel_bt_t;
+struct progdlg;
+
typedef struct _funnel_ops_t {
- funnel_text_window_t* (*new_text_window)(const gchar* label);
- void (*set_text)(funnel_text_window_t* win, const gchar* text);
- void (*append_text)(funnel_text_window_t* win, const gchar* text);
- void (*prepend_text)(funnel_text_window_t* win, const gchar* text);
+ funnel_ops_id_t *ops_id;
+ funnel_text_window_t* (*new_text_window)(const char* label);
+ void (*set_text)(funnel_text_window_t* win, const char* text);
+ void (*append_text)(funnel_text_window_t* win, const char* text);
+ void (*prepend_text)(funnel_text_window_t* win, const char* text);
void (*clear_text)(funnel_text_window_t* win);
- const gchar* (*get_text)(funnel_text_window_t* win);
+ const char* (*get_text)(funnel_text_window_t* win);
void (*set_close_cb)(funnel_text_window_t* win, text_win_close_cb_t cb, void* data);
void (*set_editable)(funnel_text_window_t* win, gboolean editable);
void (*destroy_text_window)(funnel_text_window_t* win);
- void (*add_button)(funnel_text_window_t* win, funnel_bt_t* cb, const gchar* label);
+ void (*add_button)(funnel_text_window_t* win, funnel_bt_t* cb, const char* label);
void (*new_dialog)(const gchar* title,
const gchar** fieldnames,
@@ -73,22 +81,22 @@ typedef struct _funnel_ops_t {
gpointer user_data);
- void (*retap_packets)(void);
+ void (*retap_packets)(funnel_ops_id_t *ops_id);
void (*copy_to_clipboard)(GString *str);
- gchar * (*get_filter)(void);
- void (*set_filter)(const char*);
+ const gchar * (*get_filter)(funnel_ops_id_t *ops_id);
+ void (*set_filter)(funnel_ops_id_t *ops_id, const char* filter);
void (*set_color_filter_slot)(guint8 flit_nr, const gchar* filter);
- gboolean (*open_file)(const char* fname, const char* filter, char** error);
- void (*reload)(void);
- void (*apply_filter)(void);
+ gboolean (*open_file)(funnel_ops_id_t *ops_id, const char* fname, const char* filter, char** error);
+ void (*reload)(funnel_ops_id_t *ops_id);
+ void (*apply_filter)(funnel_ops_id_t *ops_id);
gboolean (*browser_open_url)(const gchar *url);
void (*browser_open_data_file)(const gchar *filename);
- funnel_progress_window_t* (*new_progress_window)(const gchar* label, const gchar* task, gboolean terminate_is_stop, gboolean *stop_flag);
- void (*update_progress)(funnel_progress_window_t*, float pr, const gchar* task);
- void (*destroy_progress_window)(funnel_progress_window_t*);
+ struct progdlg* (*new_progress_window)(funnel_ops_id_t *ops_id, const gchar* label, const gchar* task, gboolean terminate_is_stop, gboolean *stop_flag);
+ void (*update_progress)(struct progdlg*, float pr, const gchar* task);
+ void (*destroy_progress_window)(struct progdlg*);
} funnel_ops_t;
WS_DLL_PUBLIC const funnel_ops_t* funnel_get_funnel_ops(void);
@@ -112,4 +120,8 @@ extern void initialize_funnel_ops(void);
extern void funnel_dump_all_text_windows(void);
-#endif
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __FUNNEL_H__ */
diff --git a/epan/wslua/wslua.h b/epan/wslua/wslua.h
index 80a333618e..8d41607ee3 100644
--- a/epan/wslua/wslua.h
+++ b/epan/wslua/wslua.h
@@ -295,7 +295,7 @@ struct _wslua_dir {
};
struct _wslua_progdlg {
- funnel_progress_window_t* pw;
+ struct progdlg* pw;
char* title;
char* task;
gboolean stopped;
diff --git a/epan/wslua/wslua_gui.c b/epan/wslua/wslua_gui.c
index c505eb15f6..0586293aa3 100644
--- a/epan/wslua/wslua_gui.c
+++ b/epan/wslua/wslua_gui.c
@@ -292,7 +292,7 @@ WSLUA_CONSTRUCTOR ProgDlg_new(lua_State* L) { /* Creates a new `ProgDlg` progres
pd->stopped = FALSE;
if (ops->new_progress_window) {
- pd->pw = ops->new_progress_window(pd->title,pd->task,TRUE,&(pd->stopped));
+ pd->pw = ops->new_progress_window(ops->ops_id, pd->title, pd->task, TRUE, &(pd->stopped));
} else {
WSLUA_ERROR(ProgDlg_new, "GUI not available");
return 0;
@@ -697,7 +697,7 @@ WSLUA_FUNCTION wslua_retap_packets(lua_State* L) {
Rescan all packets and just run taps - don't reconstruct the display.
*/
if ( ops->retap_packets ) {
- ops->retap_packets();
+ ops->retap_packets(ops->ops_id);
} else {
WSLUA_ERROR(wslua_retap_packets, "GUI not available");
}
@@ -737,7 +737,7 @@ WSLUA_FUNCTION wslua_open_capture_file(lua_State* L) { /* Open and display a cap
return 0;
}
- if (! ops->open_file(fname,filter,&error) ) {
+ if (! ops->open_file(ops->ops_id, fname, filter, &error) ) {
lua_pushboolean(L,FALSE);
if (error) {
@@ -761,7 +761,7 @@ WSLUA_FUNCTION wslua_get_filter(lua_State* L) { /* Get the main filter text. */
return 0;
}
- filter_str = ops->get_filter();
+ filter_str = ops->get_filter(ops->ops_id);
lua_pushstring(L,filter_str);
return 1;
@@ -776,7 +776,7 @@ WSLUA_FUNCTION wslua_set_filter(lua_State* L) { /* Set the main filter text. */
return 0;
}
- ops->set_filter(filter_str);
+ ops->set_filter(ops->ops_id, filter_str);
return 0;
}
@@ -803,7 +803,7 @@ WSLUA_FUNCTION wslua_apply_filter(lua_State* L) { /* Apply the filter in the mai
return 0;
}
- ops->apply_filter();
+ ops->apply_filter(ops->ops_id);
return 0;
}
@@ -816,7 +816,7 @@ WSLUA_FUNCTION wslua_reload(lua_State* L) { /* Reload the current capture file.
return 0;
}
- ops->reload();
+ ops->reload(ops->ops_id);
return 0;
}
diff --git a/ui/cli/tap-funnel.c b/ui/cli/tap-funnel.c
index 0c79d89b97..fe42dcbe03 100644
--- a/ui/cli/tap-funnel.c
+++ b/ui/cli/tap-funnel.c
@@ -85,6 +85,7 @@ static void funnel_logger(const gchar *log_domain _U_,
static const funnel_ops_t funnel_ops = {
+ NULL,
new_text_window,
text_window_set_text,
text_window_append,
diff --git a/ui/gtk/funnel_stat.c b/ui/gtk/funnel_stat.c
index 319f80ec75..b791b423cd 100644
--- a/ui/gtk/funnel_stat.c
+++ b/ui/gtk/funnel_stat.c
@@ -141,7 +141,7 @@ static gboolean text_window_delete_event_cb(GtkWidget *win _U_, GdkEvent *event
return TRUE;
}
-static funnel_text_window_t* new_text_window(const gchar* title) {
+static funnel_text_window_t* new_text_window(const char* title) {
funnel_text_window_t* tw = (funnel_text_window_t *)g_malloc(sizeof(funnel_text_window_t));
GtkWidget *txt_scrollw, *main_vb, *hbox;
@@ -243,7 +243,7 @@ static void text_window_append(funnel_text_window_t* tw, const char *str)
}
-static void text_window_set_text(funnel_text_window_t* tw, const gchar* text)
+static void text_window_set_text(funnel_text_window_t* tw, const char* text)
{
if (! tw->win) return;
@@ -410,12 +410,11 @@ static void funnel_new_dialog(const gchar* title,
dd->dlg_cb = dlg_cb;
dd->data = data;
- for (i=0; fieldnames[i]; i++);
-
win = dlg_window_new(title);
dd->win = win;
+ for (i=0; fieldnames[i]; i++);
gtk_window_resize(GTK_WINDOW(win),400,10*(i+2));
main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
@@ -457,11 +456,11 @@ static void funnel_new_dialog(const gchar* title,
gtk_widget_show(win);
}
-static gchar * funnel_get_filter(void) {
- return (gchar *)gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
+static const gchar * funnel_get_filter(funnel_ops_id_t *ops_id _U_ _U_) {
+ return gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
}
-static void funnel_set_filter(const char* filter_string) {
+static void funnel_set_filter(funnel_ops_id_t *ops_id _U_, const char* filter_string) {
gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget), filter_string);
}
@@ -469,7 +468,7 @@ static void funnel_set_color_filter_slot(guint8 filt_nr, const gchar* filter_str
color_filters_set_tmp(filt_nr, (gchar *)filter_string, FALSE);
}
-static void funnel_apply_filter(void) {
+static void funnel_apply_filter(funnel_ops_id_t *ops_id _U_) {
const char* filter_string = gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
main_filter_packets(&cfile, filter_string, FALSE);
}
@@ -482,11 +481,11 @@ static void funnel_logger(const gchar *log_domain _U_,
fputs(message,stderr);
}
-static void funnel_retap_packets(void) {
+static void funnel_retap_packets(funnel_ops_id_t *ops_id _U_) {
cf_retap_packets(&cfile);
}
-static gboolean funnel_open_file(const char* fname, const char* filter, char** err_str) {
+static gboolean funnel_open_file(funnel_ops_id_t *ops_id _U_, const char* fname, const char* filter, char** err_str) {
int err = 0;
dfilter_t *rfcode = NULL;
@@ -529,23 +528,24 @@ static gboolean funnel_open_file(const char* fname, const char* filter, char** e
return TRUE;
}
-static funnel_progress_window_t* funnel_new_progress_window(const gchar* label, const gchar* task, gboolean terminate_is_stop, gboolean *stop_flag) {
- return (funnel_progress_window_t*)create_progress_dlg(top_level, label, task, terminate_is_stop, stop_flag);
+static struct progdlg* funnel_new_progress_window(funnel_ops_id_t *ops_id _U_, const gchar* label, const gchar* task, gboolean terminate_is_stop, gboolean *stop_flag) {
+ return create_progress_dlg(top_level, label, task, terminate_is_stop, stop_flag);
}
-static void funnel_update_progress(funnel_progress_window_t* win, float pr, const gchar* task) {
- update_progress_dlg((progdlg_t*)win, pr, task);
+static void funnel_update_progress(struct progdlg* win, float pr, const gchar* task) {
+ update_progress_dlg(win, pr, task);
}
-static void funnel_destroy_progress_window(funnel_progress_window_t* win) {
- destroy_progress_dlg((progdlg_t*)win);
+static void funnel_destroy_progress_window(struct progdlg* win) {
+ destroy_progress_dlg(win);
}
-static void funnel_reload(void) {
+static void funnel_reload(funnel_ops_id_t *ops_id _U_) {
if (cfile.state == FILE_READ_DONE) cf_reload(&cfile);
}
static const funnel_ops_t funnel_ops = {
+ NULL, /* ops_id */
new_text_window,
text_window_set_text,
text_window_append,
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index dbd57ad3c0..bb64a01df4 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -63,6 +63,9 @@ set(WIRESHARK_QT_HEADERS
follow_stream_dialog.h
follow_stream_text.h
font_color_preferences_frame.h
+ funnel_string_dialog.h
+ funnel_text_dialog.h
+ funnel_statistics.h
import_text_dialog.h
interface_tree.h
io_graph_dialog.h
@@ -182,6 +185,8 @@ set(WIRESHARK_QT_SRC
follow_stream_dialog.cpp
follow_stream_text.cpp
font_color_preferences_frame.cpp
+ funnel_string_dialog.cpp
+ funnel_text_dialog.cpp
import_text_dialog.cpp
interface_tree.cpp
label_stack.cpp
@@ -262,6 +267,7 @@ endif()
set(WIRESHARK_QT_TAP_SRC
conversation_dialog.cpp
endpoint_dialog.cpp
+ funnel_statistics.cpp
io_graph_dialog.cpp
stats_tree_dialog.cpp
)
@@ -293,6 +299,8 @@ set(WIRESHARK_QT_UI
filter_expressions_preferences_frame.ui
follow_stream_dialog.ui
font_color_preferences_frame.ui
+ funnel_string_dialog.ui
+ funnel_text_dialog.ui
import_text_dialog.ui
io_graph_dialog.ui
layout_preferences_frame.ui
diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am
index 01cd6ab54b..cc9ff5aa1c 100644
--- a/ui/qt/Makefile.am
+++ b/ui/qt/Makefile.am
@@ -164,6 +164,10 @@ follow_stream_dialog.cpp: ui_follow_stream_dialog.h
font_color_preferences_frame.cpp font_color_preferences_frame.h: ui_font_color_preferences_frame.h
+funnel_string_dialog.cpp funnel_string_dialog.h: ui_funnel_string_dialog.h
+
+funnel_text_dialog.cpp funnel_text_dialog.h: ui_funnel_text_dialog.h
+
import_text_dialog.cpp import_text_dialog.h: ui_import_text_dialog.h
io_graph_dialog.cpp io_graph_dialog.h: ui_io_graph_dialog.h
diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common
index 9536d983ca..1e89b4c94b 100644
--- a/ui/qt/Makefile.common
+++ b/ui/qt/Makefile.common
@@ -51,6 +51,8 @@ NODIST_GENERATED_HEADER_FILES = \
ui_filter_expressions_preferences_frame.h \
ui_follow_stream_dialog.h \
ui_font_color_preferences_frame.h \
+ ui_funnel_string_dialog.h \
+ ui_funnel_text_dialog.h \
ui_import_text_dialog.h \
ui_io_graph_dialog.h \
ui_layout_preferences_frame.h \
@@ -168,6 +170,9 @@ MOC_HDRS = \
follow_stream_dialog.h \
follow_stream_text.h \
font_color_preferences_frame.h \
+ funnel_string_dialog.h \
+ funnel_text_dialog.h \
+ funnel_statistics.h \
import_text_dialog.h \
interface_tree.h \
io_graph_dialog.h \
@@ -254,6 +259,8 @@ UI_FILES = \
filter_expressions_preferences_frame.ui \
follow_stream_dialog.ui \
font_color_preferences_frame.ui \
+ funnel_string_dialog.ui \
+ funnel_text_dialog.ui \
import_text_dialog.ui \
io_graph_dialog.ui \
layout_preferences_frame.ui \
@@ -387,6 +394,9 @@ WIRESHARK_QT_SRC = \
follow_stream_dialog.cpp \
follow_stream_text.cpp \
font_color_preferences_frame.cpp \
+ funnel_string_dialog.cpp \
+ funnel_text_dialog.cpp \
+ funnel_statistics.cpp \
import_text_dialog.cpp \
interface_tree.cpp \
io_graph_dialog.cpp \
diff --git a/ui/qt/Wireshark.pro b/ui/qt/Wireshark.pro
index f9d6a2b689..72140d221e 100644
--- a/ui/qt/Wireshark.pro
+++ b/ui/qt/Wireshark.pro
@@ -227,6 +227,8 @@ FORMS += \
filter_expressions_preferences_frame.ui \
follow_stream_dialog.ui \
font_color_preferences_frame.ui \
+ funnel_string_dialog.ui \
+ funnel_text_dialog.ui \
import_text_dialog.ui \
io_graph_dialog.ui \
layout_preferences_frame.ui \
@@ -299,6 +301,9 @@ HEADERS += $$HEADERS_WS_C \
follow_stream_dialog.h \
follow_stream_text.h \
font_color_preferences_frame.h \
+ funnel_string_dialog.h \
+ funnel_text_dialog.h \
+ funnel_statistics.h \
layout_preferences_frame.h \
lbm_lbtrm_transport_dialog.h \
lbm_lbtru_transport_dialog.h \
@@ -662,6 +667,9 @@ SOURCES += \
follow_stream_dialog.cpp \
follow_stream_text.cpp \
font_color_preferences_frame.cpp \
+ funnel_string_dialog.cpp \
+ funnel_text_dialog.cpp \
+ funnel_statistics.cpp \
import_text_dialog.cpp \
interface_tree.cpp \
io_graph_dialog.cpp \
diff --git a/ui/qt/capture_file.cpp b/ui/qt/capture_file.cpp
index 37358e044d..82a26d1f19 100644
--- a/ui/qt/capture_file.cpp
+++ b/ui/qt/capture_file.cpp
@@ -96,6 +96,13 @@ void CaptureFile::retapPackets()
}
}
+void CaptureFile::reload()
+{
+ if (cap_file_ && cap_file_->state == FILE_READ_DONE) {
+ cf_reload(cap_file_);
+ }
+}
+
void CaptureFile::stopLoading()
{
setCaptureStopFlag(true);
diff --git a/ui/qt/capture_file.h b/ui/qt/capture_file.h
index 9fd8ba92c8..a4b77fdaaf 100644
--- a/ui/qt/capture_file.h
+++ b/ui/qt/capture_file.h
@@ -72,6 +72,9 @@ public:
*/
void retapPackets();
+ /** Re;load the capture file
+ */
+ void reload();
// XXX This shouldn't be needed.
static capture_file *globalCapFile();
diff --git a/ui/qt/capture_file_progress_frame.cpp b/ui/qt/capture_file_progress_frame.cpp
index 2a42958d26..329510f715 100644
--- a/ui/qt/capture_file_progress_frame.cpp
+++ b/ui/qt/capture_file_progress_frame.cpp
@@ -38,14 +38,10 @@
// - Start adding the progress bar to dialogs.
// - Don't complain so loudly when the user stops a capture.
-progdlg_t *
-delayed_create_progress_dlg(const gpointer top_level_window, const gchar *task_title, const gchar *item_title,
- gboolean terminate_is_stop, gboolean *stop_flag,
- const GTimeVal *start_time, gfloat progress)
-{
+progdlg_t *create_progress_dlg(const gpointer top_level_window, const gchar *task_title, const gchar *item_title,
+ gboolean terminate_is_stop, gboolean *stop_flag) {
Q_UNUSED(task_title);
Q_UNUSED(item_title);
- Q_UNUSED(start_time);
CaptureFileProgressFrame *cfpf;
QWidget *main_window;
@@ -65,7 +61,18 @@ delayed_create_progress_dlg(const gpointer top_level_window, const gchar *task_t
if (!cfpf) {
return NULL;
}
- return cfpf->show(true, terminate_is_stop, stop_flag, progress * 100);
+ return cfpf->show(true, terminate_is_stop, stop_flag, 0);
+}
+
+progdlg_t *
+delayed_create_progress_dlg(const gpointer top_level_window, const gchar *task_title, const gchar *item_title,
+ gboolean terminate_is_stop, gboolean *stop_flag,
+ const GTimeVal *start_time, gfloat progress)
+{
+ Q_UNUSED(start_time);
+ progdlg_t *progress_dialog = create_progress_dlg(top_level_window, task_title, item_title, terminate_is_stop, stop_flag);
+ update_progress_dlg(progress_dialog, progress, item_title);
+ return progress_dialog;
}
/*
diff --git a/ui/qt/funnel_statistics.cpp b/ui/qt/funnel_statistics.cpp
new file mode 100644
index 0000000000..d2d1ee3063
--- /dev/null
+++ b/ui/qt/funnel_statistics.cpp
@@ -0,0 +1,302 @@
+/* funnel_statistics.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include "color.h"
+#include "color_filters.h"
+#include "file.h"
+
+#include "epan/funnel.h"
+
+#include "ui/progress_dlg.h"
+
+#include "funnel_statistics.h"
+#include "funnel_string_dialog.h"
+#include "funnel_text_dialog.h"
+
+#include <QAction>
+#include <QClipboard>
+#include <QDebug>
+#include <QDesktopServices>
+#include <QUrl>
+
+#include "wireshark_application.h"
+
+// To do:
+// - Handle menu paths. Do we create a new path (GTK+) or use the base element?
+// - Add a FunnelGraphDialog class?
+
+extern "C" {
+static void funnel_statistics_logger(const gchar *, GLogLevelFlags, const gchar *message, gpointer);
+static void funnel_statistics_retap_packets(funnel_ops_id_t *ops_id);
+static void funnel_statistics_copy_to_clipboard(GString *text);
+static const gchar *funnel_statistics_get_filter(funnel_ops_id_t *ops_id);
+static void funnel_statistics_set_filter(funnel_ops_id_t *ops_id, const char* filter_string);
+static void funnel_statistics_set_color_filter_slot(guint8 filter_num, const gchar* filter_string);
+static gboolean funnel_statistics_open_file(funnel_ops_id_t *ops_id, const char* fname, const char* filter, char**);
+static void funnel_statistics_reload(funnel_ops_id_t *ops_id);
+static void funnel_statistics_apply_filter(funnel_ops_id_t *ops_id);
+static gboolean browser_open_url(const gchar *url);
+static void browser_open_data_file(const gchar *filename);
+static struct progdlg *progress_window_new(funnel_ops_id_t *ops_id, const gchar* title, const gchar* task, gboolean terminate_is_stop, gboolean *stop_flag);
+static void progress_window_update(struct progdlg *progress_dialog, float percentage, const gchar* status);
+static void progress_window_destroy(struct progdlg *progress_dialog);
+}
+
+class FunnelAction : public QAction
+{
+public:
+ FunnelAction(const QString title, void (*callback)(gpointer), gpointer callback_data, gboolean retap) :
+ QAction(NULL),
+ callback_(callback),
+ callback_data_(callback_data),
+ retap_(retap)
+ {
+ setText(title);
+ }
+
+ void triggerCallback() {
+ if (callback_) {
+ callback_(callback_data_);
+ }
+ }
+
+ bool retap() {
+ if (retap_) return true;
+ return false;
+ }
+
+private:
+ void (*callback_)(gpointer);
+ gpointer callback_data_;
+ gboolean retap_;
+};
+
+static QList<FunnelAction *> funnel_actions_;
+
+FunnelStatistics::FunnelStatistics(QObject *parent, CaptureFile &cf) :
+ QObject(parent),
+ capture_file_(cf)
+{
+ funnel_ops_ = new(struct _funnel_ops_t);
+ memset(funnel_ops_, 0, sizeof(struct _funnel_ops_t));
+
+ funnel_ops_->ops_id = (funnel_ops_id_t*) this;
+ funnel_ops_->new_text_window = text_window_new;
+ funnel_ops_->set_text = text_window_set_text;
+ funnel_ops_->append_text = text_window_append;
+ funnel_ops_->prepend_text = text_window_prepend;
+ funnel_ops_->clear_text = text_window_clear;
+ funnel_ops_->get_text = text_window_get_text;
+ funnel_ops_->set_close_cb = text_window_set_close_cb;
+ funnel_ops_->set_editable = text_window_set_editable;
+ funnel_ops_->destroy_text_window = text_window_destroy;
+ funnel_ops_->add_button = text_window_add_button;
+ funnel_ops_->new_dialog = string_dialog_new;
+ funnel_ops_->logger = funnel_statistics_logger;
+ funnel_ops_->retap_packets = funnel_statistics_retap_packets;
+ funnel_ops_->copy_to_clipboard = funnel_statistics_copy_to_clipboard;
+ funnel_ops_->get_filter = funnel_statistics_get_filter;
+ funnel_ops_->set_filter = funnel_statistics_set_filter;
+ funnel_ops_->set_color_filter_slot = funnel_statistics_set_color_filter_slot;
+ funnel_ops_->open_file = funnel_statistics_open_file;
+ funnel_ops_->reload = funnel_statistics_reload;
+ funnel_ops_->apply_filter = funnel_statistics_apply_filter;
+ funnel_ops_->browser_open_url = browser_open_url;
+ funnel_ops_->browser_open_data_file = browser_open_data_file;
+ funnel_ops_->new_progress_window = progress_window_new;
+ funnel_ops_->update_progress = progress_window_update;
+ funnel_ops_->destroy_progress_window = progress_window_destroy;
+
+ funnel_set_funnel_ops(funnel_ops_);
+}
+
+void FunnelStatistics::retapPackets()
+{
+ capture_file_.retapPackets();
+}
+
+struct progdlg *FunnelStatistics::progressDialogNew(const gchar *task_title, const gchar *item_title, gboolean terminate_is_stop, gboolean *stop_flag)
+{
+ return create_progress_dlg(capture_file_.window(), task_title, item_title, terminate_is_stop, stop_flag);
+}
+
+const char *FunnelStatistics::displayFilter()
+{
+ return display_filter_.constData();
+}
+
+void FunnelStatistics::emitSetDisplayFilter(const QString &filter)
+{
+ emit setDisplayFilter(filter);
+}
+
+void FunnelStatistics::reloadPackets()
+{
+ capture_file_.reload();
+}
+
+void FunnelStatistics::emitApplyDisplayFilter()
+{
+ emit applyDisplayFilter();
+}
+
+void FunnelStatistics::emitOpenCaptureFile(QString &cf_path, QString &filter)
+{
+ emit openCaptureFile(cf_path, filter);
+}
+
+void FunnelStatistics::funnelActionTriggered()
+{
+ FunnelAction *funnel_action = dynamic_cast<FunnelAction *>(sender());
+ if (!funnel_action) return;
+
+ funnel_action->triggerCallback();
+}
+
+void FunnelStatistics::displayFilterTextChanged(const QString &filter)
+{
+ display_filter_ = filter.toUtf8();
+}
+
+
+/* The GTK+ code says "finish this." We shall follow its lead */
+// XXX Finish this.
+void funnel_statistics_logger(const gchar *,
+ GLogLevelFlags,
+ const gchar *message,
+ gpointer) {
+ qDebug() << message;
+}
+void funnel_statistics_retap_packets(funnel_ops_id_t *ops_id) {
+ FunnelStatistics *funnel_statistics = dynamic_cast<FunnelStatistics *>((FunnelStatistics *)ops_id);
+ if (!funnel_statistics) return;
+
+ funnel_statistics->retapPackets();
+}
+
+void funnel_statistics_copy_to_clipboard(GString *text) {
+ wsApp->clipboard()->setText(text->str);
+}
+
+const gchar *funnel_statistics_get_filter(funnel_ops_id_t *ops_id) {
+ FunnelStatistics *funnel_statistics = dynamic_cast<FunnelStatistics *>((FunnelStatistics *)ops_id);
+ if (!funnel_statistics) return NULL;
+
+ return funnel_statistics->displayFilter();
+}
+
+void funnel_statistics_set_filter(funnel_ops_id_t *ops_id, const char* filter_string) {
+ FunnelStatistics *funnel_statistics = dynamic_cast<FunnelStatistics *>((FunnelStatistics *)ops_id);
+ if (!funnel_statistics) return;
+
+ funnel_statistics->emitSetDisplayFilter(filter_string);
+}
+
+void funnel_statistics_set_color_filter_slot(guint8 filter_num, const gchar* filter_string) {
+ color_filters_set_tmp(filter_num, (gchar *)filter_string, FALSE);
+}
+
+gboolean funnel_statistics_open_file(funnel_ops_id_t *ops_id, const char* fname, const char* filter, char**) {
+ // XXX We need to return a proper error value. We should probably move
+ // MainWindow::openCaptureFile to CaptureFile and add error handling
+ // there.
+ FunnelStatistics *funnel_statistics = dynamic_cast<FunnelStatistics *>((FunnelStatistics *)ops_id);
+ if (!funnel_statistics) return FALSE;
+
+ QString cf_name(fname);
+ QString cf_filter(filter);
+ funnel_statistics->emitOpenCaptureFile(cf_name, cf_filter);
+ return TRUE;
+}
+
+void funnel_statistics_reload(funnel_ops_id_t *ops_id) {
+ FunnelStatistics *funnel_statistics = dynamic_cast<FunnelStatistics *>((FunnelStatistics *)ops_id);
+ if (!funnel_statistics) return;
+
+ funnel_statistics->reloadPackets();
+}
+
+void funnel_statistics_apply_filter(funnel_ops_id_t *ops_id) {
+ FunnelStatistics *funnel_statistics = dynamic_cast<FunnelStatistics *>((FunnelStatistics *)ops_id);
+ if (!funnel_statistics) return;
+
+ funnel_statistics->emitApplyDisplayFilter();
+}
+
+gboolean browser_open_url(const gchar *url) {
+ return QDesktopServices::openUrl(QUrl(url)) ? TRUE : FALSE;
+}
+
+void browser_open_data_file(const gchar *filename) {
+ QDesktopServices::openUrl(QUrl::fromLocalFile(filename));
+}
+
+struct progdlg *progress_window_new(funnel_ops_id_t *ops_id, const gchar* task_title, const gchar* item_title, gboolean terminate_is_stop, gboolean *stop_flag) {
+ FunnelStatistics *funnel_statistics = dynamic_cast<FunnelStatistics *>((FunnelStatistics *)ops_id);
+ if (!funnel_statistics) return NULL;
+
+ return funnel_statistics->progressDialogNew(task_title, item_title, terminate_is_stop, stop_flag);
+}
+
+void progress_window_update(struct progdlg *progress_dialog, float percentage, const gchar* status) {
+ update_progress_dlg(progress_dialog, percentage, status);
+}
+
+void progress_window_destroy(progdlg *progress_dialog) {
+ destroy_progress_dlg(progress_dialog);
+}
+
+extern "C" {
+
+static void register_menu_cb(const char *name,
+ register_stat_group_t group,
+ void (*callback)(gpointer),
+ gpointer callback_data,
+ gboolean retap) {
+ FunnelAction *funnel_action = new FunnelAction(name, callback, callback_data, retap);
+ wsApp->addFunnelGroupItem(group, funnel_action);
+ funnel_actions_ << funnel_action;
+}
+
+void
+register_tap_listener_qt_funnel(void)
+{
+ funnel_register_all_menus(register_menu_cb);
+}
+
+} // extern "C"
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/funnel_statistics.h b/ui/qt/funnel_statistics.h
new file mode 100644
index 0000000000..ba8e2bf31d
--- /dev/null
+++ b/ui/qt/funnel_statistics.h
@@ -0,0 +1,76 @@
+/* funnel_statistics.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef FUNNELSTATISTICS_H
+#define FUNNELSTATISTICS_H
+
+#include <QObject>
+
+#include "capture_file.h"
+
+#include "funnel_text_dialog.h"
+
+struct _funnel_ops_t;
+struct _funnel_progress_window_t;
+struct progdlg;
+
+class FunnelStatistics : public QObject
+{
+ Q_OBJECT
+public:
+ explicit FunnelStatistics(QObject *parent, CaptureFile &cf);
+ void retapPackets();
+ struct progdlg *progressDialogNew(const gchar *task_title, const gchar *item_title, gboolean terminate_is_stop, gboolean *stop_flag);
+ const char *displayFilter();
+ void emitSetDisplayFilter(const QString &filter);
+ void reloadPackets();
+ void emitApplyDisplayFilter();
+ void emitOpenCaptureFile(QString &cf_path, QString &filter);
+
+signals:
+ void setDisplayFilter(const QString &filter);
+ void applyDisplayFilter();
+ void openCaptureFile(QString &cf_path, QString &filter);
+
+public slots:
+ void funnelActionTriggered();
+ void displayFilterTextChanged(const QString &filter);
+
+private:
+ struct _funnel_ops_t *funnel_ops_;
+ CaptureFile &capture_file_;
+ QByteArray display_filter_;
+};
+
+#endif // FUNNELSTATISTICS_H
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/funnel_string_dialog.cpp b/ui/qt/funnel_string_dialog.cpp
new file mode 100644
index 0000000000..187acbfd27
--- /dev/null
+++ b/ui/qt/funnel_string_dialog.cpp
@@ -0,0 +1,101 @@
+/* funnel_string_dialog.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "funnel_string_dialog.h"
+#include "ui_funnel_string_dialog.h"
+
+#include <QLabel>
+#include <QLineEdit>
+
+#include "qt_ui_utils.h"
+#include "wireshark_application.h"
+
+const int min_edit_width_ = 20; // em widths
+FunnelStringDialog::FunnelStringDialog(const QString title, const QStringList field_name_list, funnel_dlg_cb_t dialog_cb, void *dialog_cb_data) :
+ QDialog(NULL),
+ ui(new Ui::FunnelStringDialog),
+ dialog_cb_(dialog_cb),
+ dialog_cb_data_(dialog_cb_data)
+{
+ ui->setupUi(this);
+ setWindowTitle(wsApp->windowTitleString(title));
+ int one_em = fontMetrics().height();
+
+ int row = 0;
+ foreach (QString field_name, field_name_list) {
+ QLabel *field_label = new QLabel(field_name, this);
+ ui->stringGridLayout->addWidget(field_label, row, 0);
+ QLineEdit *field_edit = new QLineEdit(this);
+ field_edit->setMinimumWidth(one_em * min_edit_width_);
+ field_edits_ << field_edit;
+ ui->stringGridLayout->addWidget(field_edit, row, 1);
+ row++;
+ }
+}
+
+FunnelStringDialog::~FunnelStringDialog()
+{
+ delete ui;
+}
+
+void FunnelStringDialog::on_buttonBox_accepted()
+{
+ if (!dialog_cb_) return;
+
+ GPtrArray* returns = g_ptr_array_new();
+
+ foreach (QLineEdit *field_edit, field_edits_) {
+ g_ptr_array_add(returns, qstring_strdup(field_edit->text()));
+ }
+ g_ptr_array_add(returns, NULL);
+
+ dialog_cb_((gchar**)returns->pdata, dialog_cb_data_);
+
+ g_ptr_array_free(returns, FALSE);
+}
+
+void FunnelStringDialog::stringDialogNew(const QString title, const QStringList field_name_list, funnel_dlg_cb_t dialog_cb, void *dialog_cb_data)
+{
+ FunnelStringDialog *fsd = new FunnelStringDialog(title, field_name_list, dialog_cb, dialog_cb_data);
+ fsd->show();
+}
+
+void string_dialog_new(const gchar *title, const gchar **fieldnames, funnel_dlg_cb_t dialog_cb, void *dialog_cb_data)
+{
+ QStringList field_name_list;
+ for (int i = 0; fieldnames[i]; i++) {
+ field_name_list << fieldnames[i];
+ }
+ FunnelStringDialog::stringDialogNew(title, field_name_list, dialog_cb, dialog_cb_data);
+}
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/funnel_string_dialog.h b/ui/qt/funnel_string_dialog.h
new file mode 100644
index 0000000000..1f4dd9ae30
--- /dev/null
+++ b/ui/qt/funnel_string_dialog.h
@@ -0,0 +1,75 @@
+/* funnel_string_dialog.h
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef FUNNEL_STRING_DIALOG_H
+#define FUNNEL_STRING_DIALOG_H
+
+#include <glib.h>
+
+#include "epan/funnel.h"
+
+#include <QDialog>
+
+class QLineEdit;
+
+namespace Ui {
+class FunnelStringDialog;
+}
+
+class FunnelStringDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit FunnelStringDialog(const QString title, const QStringList field_name_list, funnel_dlg_cb_t dialog_cb, void *dialog_cb_data);
+ ~FunnelStringDialog();
+
+ // Funnel ops
+ static void stringDialogNew(const QString title, const QStringList field_name_list, funnel_dlg_cb_t dialog_cb, void* dialog_cb_data);
+
+private slots:
+ void on_buttonBox_accepted();
+
+private:
+ Ui::FunnelStringDialog *ui;
+ funnel_dlg_cb_t dialog_cb_;
+ void *dialog_cb_data_;
+ QList<QLineEdit *> field_edits_;
+};
+
+extern "C" {
+void string_dialog_new(const gchar* title, const gchar** fieldnames, funnel_dlg_cb_t dialog_cb, void* dialog_cb_data);
+}
+
+#endif // FUNNEL_STRING_DIALOG_H
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/funnel_string_dialog.ui b/ui/qt/funnel_string_dialog.ui
new file mode 100644
index 0000000000..c6ba7e2d10
--- /dev/null
+++ b/ui/qt/funnel_string_dialog.ui
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FunnelStringDialog</class>
+ <widget class="QDialog" name="FunnelStringDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>176</width>
+ <height>66</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QGridLayout" name="stringGridLayout"/>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>FunnelStringDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>FunnelStringDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/ui/qt/funnel_text_dialog.cpp b/ui/qt/funnel_text_dialog.cpp
new file mode 100644
index 0000000000..7aee7d165b
--- /dev/null
+++ b/ui/qt/funnel_text_dialog.cpp
@@ -0,0 +1,239 @@
+/* funnel_text_dialog.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "funnel_text_dialog.h"
+#include "ui_funnel_text_dialog.h"
+
+#include <QPushButton>
+#include <QRegExp>
+#include <QTextCharFormat>
+#include <QTextCursor>
+
+#include "qt_ui_utils.h"
+#include "wireshark_application.h"
+
+// To do:
+// - Add "Find next" to highlighting.
+// - Add rich text support?
+// - Zoom text?
+
+static QHash<QObject *, funnel_bt_t*> text_button_to_funnel_button_;
+
+FunnelTextDialog::FunnelTextDialog() :
+ QDialog(NULL),
+ ui(new Ui::FunnelTextDialog),
+ close_cb_(NULL),
+ close_cb_data_(NULL)
+{
+ ui->setupUi(this);
+
+ funnel_text_window_.funnel_text_dialog = this;
+
+ ui->textEdit->setFont(wsApp->monospaceFont());
+ ui->textEdit->setReadOnly(true);
+ ui->textEdit->setAcceptRichText(false);
+}
+
+FunnelTextDialog::~FunnelTextDialog()
+{
+ delete ui;
+
+ if (close_cb_) {
+ close_cb_(close_cb_data_);
+ }
+}
+
+struct _funnel_text_window_t *FunnelTextDialog::textWindowNew(const QString title)
+{
+ FunnelTextDialog *ftd = new FunnelTextDialog();
+ ftd->setWindowTitle(wsApp->windowTitleString(title));
+ ftd->show();
+ return &ftd->funnel_text_window_;
+}
+
+void FunnelTextDialog::setText(const QString text)
+{
+ ui->textEdit->setText(text);
+}
+
+void FunnelTextDialog::appendText(const QString text)
+{
+ ui->textEdit->moveCursor(QTextCursor::Start);
+ ui->textEdit->insertPlainText(text);
+}
+
+void FunnelTextDialog::prependText(const QString text)
+{
+ ui->textEdit->moveCursor(QTextCursor::End);
+ ui->textEdit->insertPlainText(text);
+}
+
+void FunnelTextDialog::clearText()
+{
+ ui->textEdit->clear();
+}
+
+const char *FunnelTextDialog::getText()
+{
+ return qstring_strdup(ui->textEdit->toPlainText());
+}
+
+void FunnelTextDialog::setCloseCallback(text_win_close_cb_t close_cb, void *close_cb_data)
+{
+ close_cb_ = close_cb;
+ close_cb_data_ = close_cb_data;
+}
+
+void FunnelTextDialog::setTextEditable(gboolean editable)
+{
+ ui->textEdit->setReadOnly(!editable);
+}
+
+void FunnelTextDialog::addButton(funnel_bt_t *funnel_button, const QString label)
+{
+ QPushButton *button = new QPushButton(label);
+ ui->buttonBox->addButton(button, QDialogButtonBox::ActionRole);
+ text_button_to_funnel_button_[button] = funnel_button;
+ connect(button, SIGNAL(clicked(bool)), this, SLOT(buttonClicked()));
+}
+
+void FunnelTextDialog::buttonClicked()
+{
+ if (text_button_to_funnel_button_.contains(sender())) {
+ funnel_bt_t *funnel_button = text_button_to_funnel_button_[sender()];
+ if (funnel_button) {
+ funnel_button->func(&funnel_text_window_, funnel_button->data);
+ }
+ }
+}
+
+void FunnelTextDialog::on_findLineEdit_textChanged(const QString &pattern)
+{
+ QRegExp re(pattern, Qt::CaseInsensitive);
+ QTextCharFormat plain_fmt, highlight_fmt;
+ highlight_fmt.setBackground(Qt::yellow);
+ QTextCursor csr(ui->textEdit->document());
+ int position = csr.position();
+
+ setUpdatesEnabled(false);
+
+ // Reset highlighting
+ csr.movePosition(QTextCursor::Start);
+ csr.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+ csr.setCharFormat(plain_fmt);
+
+ // Apply new highlighting
+ if (!pattern.isEmpty()) {
+ int match_pos = 0;
+ while ((match_pos = re.indexIn(ui->textEdit->toPlainText(), match_pos)) > -1) {
+ csr.setPosition(match_pos, QTextCursor::MoveAnchor);
+ csr.setPosition(match_pos + re.matchedLength(), QTextCursor::KeepAnchor);
+ csr.setCharFormat(highlight_fmt);
+ match_pos += re.matchedLength();
+ }
+ }
+
+ // Restore cursor and anchor
+ csr.setPosition(position, QTextCursor::MoveAnchor);
+ setUpdatesEnabled(true);
+}
+
+struct _funnel_text_window_t* text_window_new(const char* title)
+{
+ return FunnelTextDialog::textWindowNew(title);
+}
+
+void text_window_set_text(funnel_text_window_t *ftw, const char* text)
+{
+ if (ftw) {
+ ftw->funnel_text_dialog->setText(text);
+ }
+}
+
+void text_window_append(funnel_text_window_t* ftw, const char* text)
+{
+ if (ftw) {
+ ftw->funnel_text_dialog->appendText(text);
+ }
+}
+
+void text_window_prepend(funnel_text_window_t *ftw, const char* text)
+{
+ if (ftw) {
+ ftw->funnel_text_dialog->prependText(text);
+ }
+}
+
+void text_window_clear(funnel_text_window_t* ftw)
+{
+ if (ftw) {
+ ftw->funnel_text_dialog->clearText();
+ }
+}
+
+const char *text_window_get_text(funnel_text_window_t *ftw)
+{
+ if (ftw) {
+ return ftw->funnel_text_dialog->getText();
+ }
+ return NULL;
+}
+
+void text_window_set_close_cb(funnel_text_window_t *ftw, text_win_close_cb_t close_cb, void *close_cb_data)
+{
+ if (ftw) {
+ ftw->funnel_text_dialog->setCloseCallback(close_cb, close_cb_data);
+ }
+}
+
+void text_window_set_editable(funnel_text_window_t *ftw, gboolean editable)
+{
+ if (ftw) {
+ ftw->funnel_text_dialog->setTextEditable(editable);
+ }
+}
+
+void text_window_destroy(funnel_text_window_t *ftw)
+{
+ if (ftw) {
+ ftw->funnel_text_dialog->close();
+ }
+}
+
+void text_window_add_button(funnel_text_window_t *ftw, funnel_bt_t *funnel_button, const char *label)
+{
+ if (ftw) {
+ ftw->funnel_text_dialog->addButton(funnel_button, label);
+ }
+}
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/funnel_text_dialog.h b/ui/qt/funnel_text_dialog.h
new file mode 100644
index 0000000000..0ee9be5edf
--- /dev/null
+++ b/ui/qt/funnel_text_dialog.h
@@ -0,0 +1,98 @@
+/* funnel_text_dialog.h
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef FUNNEL_TEXT_DIALOG_H
+#define FUNNEL_TEXT_DIALOG_H
+
+#include <glib.h>
+
+#include "epan/funnel.h"
+
+#include <QDialog>
+
+namespace Ui {
+class FunnelTextDialog;
+}
+
+class FunnelTextDialog;
+struct _funnel_text_window_t {
+ FunnelTextDialog* funnel_text_dialog;
+};
+
+class FunnelTextDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit FunnelTextDialog();
+ ~FunnelTextDialog();
+
+ // Funnel ops
+ static struct _funnel_text_window_t *textWindowNew(const QString title);
+ void setText(const QString text);
+ void appendText(const QString text);
+ void prependText(const QString text);
+ void clearText();
+ const char *getText();
+ void setCloseCallback(text_win_close_cb_t close_cb, void* close_cb_data);
+ void setTextEditable(gboolean editable);
+ void addButton(funnel_bt_t *button_cb, const QString label);
+
+private slots:
+ void buttonClicked();
+ void on_findLineEdit_textChanged(const QString &pattern);
+
+private:
+ Ui::FunnelTextDialog *ui;
+
+ struct _funnel_text_window_t funnel_text_window_;
+ text_win_close_cb_t close_cb_;
+ void *close_cb_data_;
+};
+
+extern "C" {
+struct _funnel_text_window_t* text_window_new(const char* title);
+void text_window_set_text(funnel_text_window_t* ftw, const char* text);
+void text_window_append(funnel_text_window_t *ftw, const char* text);
+void text_window_prepend(funnel_text_window_t* ftw, const char* text);
+void text_window_clear(funnel_text_window_t *ftw);
+const char *text_window_get_text(funnel_text_window_t* ftw);
+void text_window_set_close_cb(funnel_text_window_t *ftw, text_win_close_cb_t close_cb, void* close_cb_data);
+void text_window_set_editable(funnel_text_window_t* ftw, gboolean editable);
+void text_window_destroy(funnel_text_window_t* ftw);
+void text_window_add_button(funnel_text_window_t* ftw, funnel_bt_t* funnel_button, const char* label);
+}
+
+
+#endif // FUNNEL_TEXT_DIALOG_H
+
+/*
+ * 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:
+ */
diff --git a/ui/qt/funnel_text_dialog.ui b/ui/qt/funnel_text_dialog.ui
new file mode 100644
index 0000000000..80bb02f371
--- /dev/null
+++ b/ui/qt/funnel_text_dialog.ui
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FunnelTextDialog</class>
+ <widget class="QDialog" name="FunnelTextDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>620</width>
+ <height>450</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTextEdit" name="textEdit"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enter some text or a regular expression. It will be highlighted above.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Highlight:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="findLineEdit">
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enter some text or a regular expression. It will be highlighted above.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Close</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>FunnelTextDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>FunnelTextDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index 737aadc511..312769829d 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -47,6 +47,7 @@
#include "byte_view_tab.h"
#include "display_filter_edit.h"
#include "export_dissection_dialog.h"
+#include "funnel_statistics.h"
#include "import_text_dialog.h"
#include "packet_list.h"
#include "proto_tree.h"
@@ -202,6 +203,7 @@ MainWindow::MainWindow(QWidget *parent) :
show_hide_actions_(NULL),
time_display_actions_(NULL),
time_precision_actions_(NULL),
+ funnel_statistics_(new FunnelStatistics(this, capture_file_)),
capture_stopping_(false),
capture_filter_valid_(false),
#ifdef _WIN32
@@ -239,6 +241,7 @@ MainWindow::MainWindow(QWidget *parent) :
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addStatsPluginsToMenu()));
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addStatisticsMenus()));
connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addExternalMenus()));
+ connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addFunnelMenus()));
connect(wsApp, SIGNAL(profileChanging()), this, SLOT(saveWindowGeometry()));
connect(wsApp, SIGNAL(preferencesChanged()), this, SLOT(layoutPanes()));
@@ -262,6 +265,11 @@ MainWindow::MainWindow(QWidget *parent) :
main_ui_->statusBar, SLOT(pushTemporaryStatus(const QString&)));
connect(df_edit, SIGNAL(filterPackets(QString&,bool)), this, SLOT(filterPackets(QString&,bool)));
connect(df_edit, SIGNAL(addBookmark(QString)), this, SLOT(addDisplayFilterButton(QString)));
+ 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()));
+ connect(funnel_statistics_, SIGNAL(openCaptureFile(QString&,QString&)),
+ this, SLOT(openCaptureFile(QString&,QString&)));
connect(this, SIGNAL(displayFilterSuccess(bool)), df_edit, SLOT(displayFilterSuccess(bool)));
initMainToolbarIcons();
@@ -1971,8 +1979,6 @@ void MainWindow::setForCaptureInProgress(gboolean capture_in_progress)
void MainWindow::addStatisticsMenus()
{
-
- // Unsorted
// actionStatistics_REGISTER_STAT_GROUP_UNSORTED should exist and be.
// invisible.
QList<QAction *>unsorted_actions = wsApp->statisticsGroupItems(REGISTER_STAT_GROUP_UNSORTED);
@@ -2066,6 +2072,43 @@ void MainWindow::addExternalMenus()
}
}
+void MainWindow::addFunnelMenus()
+{
+ // XXX Add support for MENU_STAT_UNSORTED, MENU_STAT_GENERIC, etc. We
+ // should probably add a common routine that we can use in
+ // addStatisticsMenus as well.
+ QList<QAction *>funnel_actions = wsApp->funnelGroupItems(REGISTER_TOOLS_GROUP_UNSORTED);
+
+ // Empty menus don't show up: https://bugreports.qt.io/browse/QTBUG-33728
+ // We've added a placeholder in order to make sure the "Tools" menu is
+ // visible. Hide it as needed.
+ if (funnel_actions.length() > 0) {
+ main_ui_->actionToolsPlaceholder->setVisible(false);
+ }
+
+ foreach (QAction *tools_action, funnel_actions) {
+ QStringList menu_path = tools_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());
+ }
+ cur_menu = submenu;
+ }
+ tools_action->setText(menu_path.last());
+ cur_menu->addAction(tools_action);
+ connect(tools_action, SIGNAL(triggered(bool)), funnel_statistics_, SLOT(funnelActionTriggered()));
+ }
+}
+
/*
* Editor modelines
*
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index ea53ad115a..0bc10938bc 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -61,6 +61,7 @@
class AccordionFrame;
class ByteViewTab;
+class FunnelStatistics;
class MainWelcome;
class PacketList;
class ProtoTree;
@@ -136,6 +137,7 @@ private:
QActionGroup *show_hide_actions_;
QActionGroup *time_display_actions_;
QActionGroup *time_precision_actions_;
+ FunnelStatistics *funnel_statistics_;
bool capture_stopping_;
bool capture_filter_valid_;
@@ -207,7 +209,8 @@ public slots:
* @return True on success, false on failure.
*/
// XXX We might want to return a cf_read_status_t or a CaptureFile.
- bool openCaptureFile(QString& cf_path = *new QString(), QString& display_filter = *new QString(), unsigned int type = WTAP_TYPE_AUTO);
+ bool openCaptureFile(QString& cf_path, QString& display_filter, unsigned int type);
+ bool openCaptureFile(QString& cf_path = *new QString(), QString& display_filter = *new QString()) { return openCaptureFile(cf_path, display_filter, WTAP_TYPE_AUTO); }
void filterPackets(QString& new_filter = *new QString(), bool force = false);
void updateForUnsavedChanges();
void layoutPanes();
@@ -261,6 +264,7 @@ private slots:
void addStatsPluginsToMenu();
void addStatisticsMenus();
void addExternalMenus();
+ void addFunnelMenus();
void startInterfaceCapture(bool valid);
diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui
index 50cef78629..72f163c7e9 100644
--- a/ui/qt/main_window.ui
+++ b/ui/qt/main_window.ui
@@ -539,6 +539,12 @@
<addaction name="actionATT_Server_Attributes"/>
<addaction name="actionDevices"/>
</widget>
+ <widget class="QMenu" name="menuTools">
+ <property name="title">
+ <string>Tools</string>
+ </property>
+ <addaction name="actionToolsPlaceholder"/>
+ </widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuView"/>
@@ -547,6 +553,7 @@
<addaction name="menuAnalyze"/>
<addaction name="menuStatistics"/>
<addaction name="menuTelephony"/>
+ <addaction name="menuTools"/>
<addaction name="menuBluetooth"/>
<addaction name="menuHelp"/>
</widget>
@@ -2369,6 +2376,20 @@
<enum>QAction::NoRole</enum>
</property>
</action>
+ <action name="actionToolsPlaceholder">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>No tools registered</string>
+ </property>
+ <property name="toolTip">
+ <string>No tools have been registered.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
diff --git a/ui/qt/wireshark_application.cpp b/ui/qt/wireshark_application.cpp
index e34c1ae3dc..1439c72f0f 100644
--- a/ui/qt/wireshark_application.cpp
+++ b/ui/qt/wireshark_application.cpp
@@ -90,6 +90,7 @@ static char *last_open_dir = NULL;
static bool updated_last_open_dir = FALSE;
static QList<recent_item_status *> recent_items_;
static QHash<int, QList<QAction *> > statistics_groups_;
+static QHash<int, QList<QAction *> > funnel_groups_;
QString WiresharkApplication::window_title_separator_ = QString::fromUtf8(" " UTF8_MIDDLE_DOT " ");
@@ -571,6 +572,7 @@ void WiresharkApplication::emitTapParameterSignal(const QString cfg_abbr, const
emit openTapParameterDialog(cfg_abbr, arg, userdata);
}
+// XXX Combine statistics and funnel routines into addGroupItem + groupItems?
void WiresharkApplication::addStatisticsGroupItem(int group, QAction *sg_action)
{
if (!statistics_groups_.contains(group)) {
@@ -590,6 +592,25 @@ QList<QAction *> WiresharkApplication::statisticsGroupItems(int group)
return sgi_list;
}
+void WiresharkApplication::addFunnelGroupItem(int group, QAction *fg_action)
+{
+ if (!funnel_groups_.contains(group)) {
+ funnel_groups_[group] = QList<QAction *>();
+ }
+ funnel_groups_[group] << fg_action;
+}
+
+QList<QAction *> WiresharkApplication::funnelGroupItems(int group)
+{
+ if (!funnel_groups_.contains(group)) {
+ return QList<QAction *>();
+ }
+
+ QList<QAction *> fgi_list = funnel_groups_[group];
+ std::sort(fgi_list.begin(), fgi_list.end(), qActionLessThan);
+ return fgi_list;
+}
+
#ifdef HAVE_LIBPCAP
static void
diff --git a/ui/qt/wireshark_application.h b/ui/qt/wireshark_application.h
index 5cfd5ee032..1b7941e8e8 100644
--- a/ui/qt/wireshark_application.h
+++ b/ui/qt/wireshark_application.h
@@ -77,6 +77,8 @@ public:
// Map a register_stat_group_t to a list of stat_tap_ui.title
void addStatisticsGroupItem(int group, QAction *sg_action);
QList<QAction *>statisticsGroupItems(int group);
+ void addFunnelGroupItem(int group, QAction *fg_action);
+ QList<QAction *> funnelGroupItems(int group);
void allSystemsGo();
void refreshLocalInterfaces();