aboutsummaryrefslogtreecommitdiffstats
path: root/ui/qt
diff options
context:
space:
mode:
Diffstat (limited to 'ui/qt')
-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
20 files changed, 1194 insertions, 10 deletions
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();