From ea28298e961bca09a4294a4130463ea54123fa14 Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Thu, 21 Nov 2013 01:28:17 +0000 Subject: Add a statistics tree dialog. Add menu items for each corresponding item in gtk/main_menubar.c that calls gtk_stats_tree_cb(). Hopefully that's everything. Note that we use quite a bit less code than the GTK+ flavor and why we might not want to do that. Change a few things in ui/qt/CMakeLists.txt to more closely match the GTK+ version. Add plumbing for tap registrations in CMakeLists.txt and Makefile.am. Add the ability to copy text as CSV or YAML. svn path=/trunk/; revision=53464 --- ui/qt/CMakeLists.txt | 60 +++++---- ui/qt/Makefile.am | 27 ++++ ui/qt/Makefile.common | 6 +- ui/qt/QtShark.pro | 3 + ui/qt/capture_file_dialog.cpp | 2 +- ui/qt/display_filter_combo.cpp | 2 +- ui/qt/display_filter_edit.h | 2 +- ui/qt/main.cpp | 4 +- ui/qt/main_window.h | 21 ++- ui/qt/main_window.ui | 164 ++++++++++++++++++++++ ui/qt/main_window_slots.cpp | 93 +++++++++++++ ui/qt/stats_tree_dialog.cpp | 292 ++++++++++++++++++++++++++++++++++++++++ ui/qt/stats_tree_dialog.h | 88 ++++++++++++ ui/qt/stats_tree_dialog.ui | 141 +++++++++++++++++++ ui/qt/wireshark_application.cpp | 26 +++- ui/qt/wireshark_application.h | 5 +- 16 files changed, 897 insertions(+), 39 deletions(-) create mode 100644 ui/qt/stats_tree_dialog.cpp create mode 100644 ui/qt/stats_tree_dialog.h create mode 100644 ui/qt/stats_tree_dialog.ui (limited to 'ui') diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index c4ba1fc528..e1412ef494 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -23,7 +23,7 @@ # All .h files which inherit from QObject aka which use the Q_OBJECT macro # need to go here. -set(QTSHARK_H_SRC +set(WIRESHARK_QT_HEADERS accordion_frame.h byte_view_tab.h byte_view_text.h @@ -73,6 +73,7 @@ set(QTSHARK_H_SRC sequence_dialog.h simple_dialog_qt.h splash_overlay.h + stats_tree_dialog.h summary_dialog.h syntax_line_edit.h tcp_stream_dialog.h @@ -87,7 +88,7 @@ set(QTSHARK_H_SRC # sparkline_delegate.h ) -set(CLEAN_FILES +set(WIRESHARK_QT_SRC accordion_frame.cpp byte_view_tab.cpp byte_view_text.cpp @@ -150,11 +151,20 @@ set(CLEAN_FILES wireshark_application.cpp ) +set(WIRESHARK_QT_TAP_SRC + stats_tree_dialog.cpp +) + +set(CLEAN_FILES + ${WIRESHARK_QT_SRC} + ${WIRESHARK_QT_TAP_SRC} +) + set(DIRTY_FILES qcustomplot.cpp ) -set(QTSHARK_UI +set(WIRESHARK_QT_UI capture_preferences_frame.ui column_preferences_frame.ui export_object_dialog.ui @@ -177,13 +187,14 @@ set(QTSHARK_UI search_frame.ui sequence_dialog.ui splash_overlay.ui + stats_tree_dialog.ui summary_dialog.ui tcp_stream_dialog.ui time_shift_dialog.ui uat_dialog.ui ) -set(QTSHARK_QRC +set(WIRESHARK_QT_QRC ../../image/display_filter.qrc ../../image/layout.qrc ../../image/status.qrc @@ -192,7 +203,7 @@ set(QTSHARK_QRC welcome.qrc ) -set(QTSHARK_TS +set(WIRESHARK_QT_TS qtshark_de.ts qtshark_en.ts # lupdate -pluralonly qtshark_fr.ts @@ -205,32 +216,27 @@ include_directories( ) if (QT_VERSION EQUAL 5) - QT5_ADD_TRANSLATION(QTSHARK_TS_QM ${QTSHARK_TS}) - QT5_ADD_RESOURCES(QTSHARK_QRC_SRC ${QTSHARK_QRC}) - QT5_WRAP_UI(QTSHARK_UI_SRC ${QTSHARK_UI}) + QT5_ADD_TRANSLATION(WIRESHARK_QT_TS_QM ${WIRESHARK_QT_TS}) + QT5_ADD_RESOURCES(WIRESHARK_QT_QRC_SRC ${WIRESHARK_QT_QRC}) + QT5_WRAP_UI(WIRESHARK_QT_UI_SRC ${WIRESHARK_QT_UI}) # For now, do the moc stuff manually - QT5_WRAP_CPP(QTSHARK_MOC_SRC ${QTSHARK_H_SRC}) + QT5_WRAP_CPP(WIRESHARK_QT_MOC_SRC ${WIRESHARK_QT_HEADERS}) # Starting with cmake 2.8.6, we may also use # set(CMAKE_AUTOMOC TRUE) # or # set_target_properties(${some-source-files} PROPERTIES AUTOMOC TRUE) else() - QT4_ADD_TRANSLATION(QTSHARK_TS_QM ${QTSHARK_TS}) - QT4_ADD_RESOURCES(QTSHARK_QRC_SRC ${QTSHARK_QRC}) - QT4_WRAP_UI(QTSHARK_UI_SRC ${QTSHARK_UI}) + QT4_ADD_TRANSLATION(WIRESHARK_QT_TS_QM ${WIRESHARK_QT_TS}) + QT4_ADD_RESOURCES(WIRESHARK_QT_QRC_SRC ${WIRESHARK_QT_QRC}) + QT4_WRAP_UI(WIRESHARK_QT_UI_SRC ${WIRESHARK_QT_UI}) # For now, do the moc stuff manually - QT4_WRAP_CPP(QTSHARK_MOC_SRC ${QTSHARK_H_SRC}) + QT4_WRAP_CPP(WIRESHARK_QT_MOC_SRC ${WIRESHARK_QT_HEADERS}) # Starting with cmake 2.8.6, we may also use # set(CMAKE_AUTOMOC TRUE) # or # set_target_properties(${some-source-files} PROPERTIES AUTOMOC TRUE) endif() -set(QTSHARK_SRC - ${CLEAN_FILES} - ${DIRTY_FILES} -) - if (WERROR) set_source_files_properties( ${CLEAN_FILES} @@ -249,12 +255,20 @@ endif() add_definitions(${QT_DEFINITIONS}) +register_tap_files(wireshark-tap-register.c + taps + ${WIRESHARK_QT_TAP_SRC} +) + add_library(qtui STATIC - ${QTSHARK_SRC} - ${QTSHARK_UI_SRC} - ${QTSHARK_MOC_SRC} - ${QTSHARK_QRC_SRC} - ${QTSHARK_TS_QM} + ${WIRESHARK_QT_SRC} + ${WIRESHARK_QT_TAP_SRC} + ${WIRESHARK_QT_UI_SRC} + ${WIRESHARK_QT_MOC_SRC} + ${WIRESHARK_QT_QRC_SRC} + ${WIRESHARK_QT_TS_QM} + ${DIRTY_FILES} + wireshark-tap-register.c ) set_target_properties(qtui PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}") set_target_properties(qtui PROPERTIES FOLDER "UI") diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am index 142b297e91..21016e618b 100644 --- a/ui/qt/Makefile.am +++ b/ui/qt/Makefile.am @@ -32,6 +32,8 @@ noinst_LIBRARIES = libqtui.a CLEANFILES = \ libqtui.a \ + wireshark-tap-register.c-tmp \ + wireshark-tap-register-cache.pkl \ *~ DISTCLEANFILES = \ @@ -42,6 +44,29 @@ MAINTAINERCLEANFILES = \ $(NODIST_GENERATED_FILES) \ Makefile.in +# +# Build "wireshark-tap-register.c", which contains a function +# "register_all_tap_listeners()" +# that calls the register routines for all wireshark tap listeners. +# +# We do this by grepping through sources. +# +# Formatting conventions: The name of the tap_listener_register_* +# routines must start in column zero, or must be preceded only by +# "void " starting in column zero, and must not be inside #if. +# +# The first argument is the directory in which the source files live. +# All subsequent arguments are the files to scan. +# +wireshark-tap-register.c: $(WIRESHARK_TAP_SRC) $(top_srcdir)/tools/make-tapreg-dotc $(top_srcdir)/tools/make-tap-reg.py + @if test -n "$(PYTHON)"; then \ + echo Making wireshark-tap-register.c with python ; \ + $(PYTHON) $(top_srcdir)/tools/make-tap-reg.py $(srcdir) taps $(WIRESHARK_TAP_SRC); \ + else \ + echo Making wireshark-tap-register.c; \ + $(top_srcdir)/tools/make-tapreg-dotc wireshark-tap-register.c $(srcdir) $(WIRESHARK_TAP_SRC); \ + fi + RUNLEX=$(top_srcdir)/tools/runlex.sh libqtui_a_SOURCES = \ @@ -143,6 +168,8 @@ sequence_dialog.cpp sequence_dialog.h: ui_sequence_dialog.h splash_overlay.cpp splash_overlay.h: ui_splash_overlay.h +stats_tree_dialog.cpp stats_tree_dialog.h: ui_stats_tree_dialog.h + summary_dialog.cpp summary_dialog.h: ui_summary_dialog.h tcp_stream_dialog.cpp: ui_tcp_stream_dialog.h diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common index 7ca3cc991e..cbbde23abf 100644 --- a/ui/qt/Makefile.common +++ b/ui/qt/Makefile.common @@ -59,7 +59,8 @@ NODIST_GENERATED_HEADER_FILES = \ ui_uat_dialog.h # Generated C source files that we want in the distribution. -GENERATED_C_FILES = +GENERATED_C_FILES = \ + wireshark-tap-register.c # Generated C source files that we don't want in the distribution. NODIST_GENERATED_C_FILES = @@ -142,6 +143,7 @@ MOC_HDRS = \ simple_dialog_qt.h \ sparkline_delegate.h \ splash_overlay.h \ + stats_tree_dialog.h \ summary_dialog.h \ syntax_line_edit.h \ tcp_stream_dialog.h \ @@ -176,6 +178,7 @@ UI_FILES = \ search_frame.ui \ sequence_dialog.ui \ splash_overlay.ui \ + stats_tree_dialog.ui \ summary_dialog.ui \ tcp_stream_dialog.ui \ time_shift_dialog.ui \ @@ -284,6 +287,7 @@ WIRESHARK_QT_SRC = \ sequence_dialog.cpp \ simple_dialog_qt.cpp \ sparkline_delegate.cpp \ + stats_tree_dialog.cpp \ summary_dialog.cpp \ splash_overlay.cpp \ syntax_line_edit.cpp \ diff --git a/ui/qt/QtShark.pro b/ui/qt/QtShark.pro index c7ba7da1e9..604f54f8ac 100644 --- a/ui/qt/QtShark.pro +++ b/ui/qt/QtShark.pro @@ -224,6 +224,7 @@ FORMS += \ search_frame.ui \ sequence_dialog.ui \ splash_overlay.ui \ + stats_tree_dialog.ui \ summary_dialog.ui \ time_shift_dialog.ui \ uat_dialog.ui \ @@ -250,6 +251,7 @@ HEADERS += $$HEADERS_WS_C \ profile_dialog.h \ search_frame.h \ splash_overlay.h \ + stats_tree_dialog.h \ summary_dialog.h \ tango_colors.h \ uat_dialog.h \ @@ -569,6 +571,7 @@ SOURCES += \ simple_dialog_qt.cpp \ sparkline_delegate.cpp \ splash_overlay.cpp \ + stats_tree_dialog.cpp \ summary_dialog.cpp \ syntax_line_edit.cpp \ time_shift_dialog.cpp \ diff --git a/ui/qt/capture_file_dialog.cpp b/ui/qt/capture_file_dialog.cpp index 850b81d06c..68cd033e1d 100644 --- a/ui/qt/capture_file_dialog.cpp +++ b/ui/qt/capture_file_dialog.cpp @@ -493,7 +493,7 @@ void CaptureFileDialog::addDisplayFilterEdit() { fd_grid->addWidget(new QLabel(tr("Display Filter:")), last_row_, 0); - display_filter_edit_ = new DisplayFilterEdit(this, true); + display_filter_edit_ = new DisplayFilterEdit(this); display_filter_edit_->setText(display_filter_); fd_grid->addWidget(display_filter_edit_, last_row_, 1); last_row_++; diff --git a/ui/qt/display_filter_combo.cpp b/ui/qt/display_filter_combo.cpp index cf852faa33..448e391606 100644 --- a/ui/qt/display_filter_combo.cpp +++ b/ui/qt/display_filter_combo.cpp @@ -42,7 +42,7 @@ DisplayFilterCombo::DisplayFilterCombo(QWidget *parent) : QComboBox(parent) { setEditable(true); - setLineEdit(new DisplayFilterEdit()); + setLineEdit(new DisplayFilterEdit(this, false)); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); setAccessibleName(tr("Display filter selector")); cur_display_filter_combo = this; diff --git a/ui/qt/display_filter_edit.h b/ui/qt/display_filter_edit.h index 3d4ae8f88f..00a527f8b2 100644 --- a/ui/qt/display_filter_edit.h +++ b/ui/qt/display_filter_edit.h @@ -31,7 +31,7 @@ class DisplayFilterEdit : public SyntaxLineEdit { Q_OBJECT public: - explicit DisplayFilterEdit(QWidget *parent = 0, bool plain = false); + explicit DisplayFilterEdit(QWidget *parent = 0, bool plain = true); protected: void paintEvent(QPaintEvent *evt); diff --git a/ui/qt/main.cpp b/ui/qt/main.cpp index bb27930b36..2dfc039a85 100644 --- a/ui/qt/main.cpp +++ b/ui/qt/main.cpp @@ -140,8 +140,6 @@ GString *comp_info_str, *runtime_info_str; //static gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */ -//static guint tap_update_timer_id; - static void console_log_handler(const char *log_domain, GLogLevelFlags log_level, const char *message, gpointer user_data); @@ -879,7 +877,7 @@ int main(int argc, char *argv[]) register_all_plugin_tap_listeners(); #endif -// register_all_tap_listeners(); + register_all_tap_listeners(); /* Removed thread code: * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027 diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index ff42c0a6a9..c6ac5219ca 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -318,8 +318,27 @@ private slots: void on_actionStatisticsTcpStreamThroughput_triggered(); void on_actionStatisticsTcpStreamRoundTripTime_triggered(); void on_actionStatisticsTcpStreamWindowScaling_triggered(); -}; + void openStatisticsTreeDialog(const gchar *abbr); + void on_actionStatisticsANCP_triggered(); + void on_actionStatisticsBACappInstanceId_triggered(); + void on_actionStatisticsBACappIP_triggered(); + void on_actionStatisticsBACappObjectId_triggered(); + void on_actionStatisticsBACappService_triggered(); + void on_actionStatisticsCollectd_triggered(); + void on_actionStatisticsHART_IP_triggered(); + void on_actionStatisticsHTTPPacketCounter_triggered(); + void on_actionStatisticsHTTPRequests_triggered(); + void on_actionStatisticsHTTPLoadDistribution_triggered(); + void on_actionStatisticsPacketLen_triggered(); + void on_actionStatisticsSametime_triggered(); + + void on_actionTelephonyISUPMessages_triggered(); + void on_actionTelephonyRTSPPacketCounter_triggered(); + void on_actionTelephonySMPPOperations_triggered(); + void on_actionTelephonyUCPMessages_triggered(); + +}; #endif // MAINWINDOW_H diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index a38b25ed22..92574efde4 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -330,15 +330,51 @@ + + + BACnet + + + + + + + + + HTTP + + + + + + + + + + + + + + Telephony + + + RTSP + + + + + + + @@ -1330,6 +1366,134 @@ Flow sequence diagram + + + ANCP + + + ANCP statistics + + + + + Packets sorted by Instance ID + + + BACapp statistics sorted by instance ID + + + + + Packets sorted by IP + + + BACapp statistics sorted by IP + + + + + Packets sorted by object type + + + BACapp statistics sorted by object type + + + + + Packets sorted by service + + + BACapp statistics sorted by service + + + + + Collectd + + + Collectd statistics + + + + + HART-IP + + + HART-IP statistics + + + + + Packet Counter + + + HTTP packet counter + + + + + Requests + + + HTTP requests + + + + + Load Distribution + + + HTTP load distribution + + + + + Packet Lengths + + + Packet length statistics + + + + + Sametime + + + Sametime statistics + + + + + &ISUP Messages + + + ISUP message statistics + + + + + Packet Counter + + + RTSP packet counts + + + + + SM&PP Operations + + + SMPP operation statistics + + + + + &UCP Messages + + + UCP message statistics + + diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 8c41cf8911..252799a1dc 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -78,6 +78,7 @@ #include "profile_dialog.h" #include "qt_ui_utils.h" #include "sequence_dialog.h" +#include "stats_tree_dialog.h" #include "tcp_stream_dialog.h" #include "time_shift_dialog.h" #include "wireshark_application.h" @@ -1775,6 +1776,98 @@ void MainWindow::on_actionStatisticsTcpStreamWindowScaling_triggered() openTcpStreamDialog(GRAPH_WSCALE); } +void MainWindow::openStatisticsTreeDialog(const gchar *abbr) +{ + StatsTreeDialog *st_dialog = new StatsTreeDialog(this, cap_file_, abbr); +// connect(st_dialog, SIGNAL(goToPacket(int)), +// packet_list_, SLOT(goToPacket(int))); + connect(this, SIGNAL(setCaptureFile(capture_file*)), + st_dialog, SLOT(setCaptureFile(capture_file*))); + st_dialog->show(); +} + +void MainWindow::on_actionStatisticsANCP_triggered() +{ + openStatisticsTreeDialog("ancp"); +} + +void MainWindow::on_actionStatisticsBACappInstanceId_triggered() +{ + openStatisticsTreeDialog("bacapp_instanceid"); +} + +void MainWindow::on_actionStatisticsBACappIP_triggered() +{ + openStatisticsTreeDialog("bacapp_ip"); +} + +void MainWindow::on_actionStatisticsBACappObjectId_triggered() +{ + openStatisticsTreeDialog("bacapp_objectid"); +} + +void MainWindow::on_actionStatisticsBACappService_triggered() +{ + openStatisticsTreeDialog("bacapp_service"); +} + +void MainWindow::on_actionStatisticsCollectd_triggered() +{ + openStatisticsTreeDialog("collectd"); +} + +void MainWindow::on_actionStatisticsHART_IP_triggered() +{ + openStatisticsTreeDialog("hart_ip"); +} + +void MainWindow::on_actionStatisticsHTTPPacketCounter_triggered() +{ + openStatisticsTreeDialog("http"); +} + +void MainWindow::on_actionStatisticsHTTPRequests_triggered() +{ + openStatisticsTreeDialog("http_req"); +} + +void MainWindow::on_actionStatisticsHTTPLoadDistribution_triggered() +{ + openStatisticsTreeDialog("http_srv"); +} + +void MainWindow::on_actionStatisticsPacketLen_triggered() +{ + openStatisticsTreeDialog("plen"); +} + +void MainWindow::on_actionStatisticsSametime_triggered() +{ + openStatisticsTreeDialog("sametime"); +} + +// Telephony Menu + +void MainWindow::on_actionTelephonyISUPMessages_triggered() +{ + openStatisticsTreeDialog("isup_msg"); +} + +void MainWindow::on_actionTelephonyRTSPPacketCounter_triggered() +{ + openStatisticsTreeDialog("rtsp"); +} + +void MainWindow::on_actionTelephonySMPPOperations_triggered() +{ + openStatisticsTreeDialog("smpp_commands"); +} + +void MainWindow::on_actionTelephonyUCPMessages_triggered() +{ + openStatisticsTreeDialog("ucp_messages"); +} + // Help Menu void MainWindow::on_actionHelpContents_triggered() { diff --git a/ui/qt/stats_tree_dialog.cpp b/ui/qt/stats_tree_dialog.cpp new file mode 100644 index 0000000000..52564dea2c --- /dev/null +++ b/ui/qt/stats_tree_dialog.cpp @@ -0,0 +1,292 @@ +/* stats_tree_dialog.cpp + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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 "stats_tree_dialog.h" +#include "ui_stats_tree_dialog.h" + +#include "file.h" + +#include "epan/stats_tree_priv.h" + +#include "wireshark_application.h" + +#include +#include +#include +#include + +// The GTK+ counterpart uses tap_param_dlg, which we don't use. If we +// need tap parameters we should probably create a TapParameterDialog +// class based on QDialog and subclass it here. + +// To do: +// - Add help + +#include + +const int item_col_ = 0; +const int count_col_ = 1; +const int rate_col_ = 2; +const int percent_col_ = 3; + +Q_DECLARE_METATYPE(stat_node *); + +StatsTreeDialog::StatsTreeDialog(QWidget *parent, capture_file *cf, const char *cfg_abbr) : + QDialog(parent), + ui(new Ui::StatsTreeDialog), + st_(NULL), + st_cfg_(NULL), + cap_file_(cf) +{ + ui->setupUi(this); + st_cfg_ = stats_tree_get_cfg_by_abbr(cfg_abbr); + + if (!st_cfg_) { + QMessageBox::critical(this, tr("Configuration not found"), + tr("Unable to find configuration for %1.").arg(cfg_abbr)); + QMetaObject::invokeMethod(this, "reject", Qt::QueuedConnection); + } + + ui->statsTreeWidget->addAction(ui->actionCopyAsCSV); + ui->statsTreeWidget->addAction(ui->actionCopyAsYAML); + ui->statsTreeWidget->setContextMenuPolicy(Qt::ActionsContextMenu); + + QPushButton *copy_as_bt; + copy_as_bt = ui->buttonBox->addButton(tr("Copy as CSV"), QDialogButtonBox::ActionRole); + connect(copy_as_bt, SIGNAL(clicked()), this, SLOT(on_actionCopyAsCSV_triggered())); + + copy_as_bt = ui->buttonBox->addButton(tr("Copy as YAML"), QDialogButtonBox::ActionRole); + connect(copy_as_bt, SIGNAL(clicked()), this, SLOT(on_actionCopyAsYAML_triggered())); + + fillTree(); +} + +StatsTreeDialog::~StatsTreeDialog() +{ + if (st_) { + stats_tree_free(st_); + } + delete ui; +} + +void StatsTreeDialog::setCaptureFile(capture_file *cf) +{ + if (!cf) { // We only want to know when the file closes. + cap_file_ = NULL; + ui->displayFilterLineEdit->setEnabled(false); + ui->applyFilterButton->setEnabled(false); + } +} + +void StatsTreeDialog::fillTree() +{ + GString *error_string; + if (!st_cfg_) return; + + setWindowTitle(st_cfg_->name + tr(" Stats Tree")); + + if (!cap_file_) return; + + if (st_cfg_->in_use) { + QMessageBox::warning(this, tr("%1 already open").arg(st_cfg_->name), + tr("Each type of tree can only be generated one at at time.")); + reject(); + } + + st_cfg_->in_use = TRUE; + st_cfg_->pr = &cfg_pr_; + cfg_pr_.st_dlg = this; + + st_ = stats_tree_new(st_cfg_, NULL, ui->displayFilterLineEdit->text().toUtf8().constData()); + + error_string = register_tap_listener(st_cfg_->tapname, + st_, + st_->filter, + st_cfg_->flags, + resetTap, + stats_tree_packet, + drawTreeItems); + if (error_string) { + QMessageBox::critical(this, tr("%1 failed to attach to tap").arg(st_cfg_->name), + error_string->str); + g_string_free(error_string, TRUE); + reject(); + } + + cf_retap_packets(cap_file_); + drawTreeItems(st_); + remove_tap_listener(st_); + + stats_tree_free(st_); + st_ = NULL; + st_cfg_->in_use = FALSE; + st_cfg_->pr = NULL; +} + +void StatsTreeDialog::resetTap(void *st_ptr) +{ + stats_tree *st = (stats_tree *) st_ptr; + if (!st || !st->cfg || !st->cfg->pr || !st->cfg->pr->st_dlg) return; + + st->cfg->pr->st_dlg->ui->statsTreeWidget->clear(); + st->cfg->init(st); +} + +// Adds a node to the QTreeWidget +// Note: We're passing QTreeWidgetItem pointers as st_node_pres pointers +void StatsTreeDialog::setupNode(stat_node* node) +{ + if (!node || !node->st || !node->st->cfg || !node->st->cfg->pr + || !node->st->cfg->pr->st_dlg) return; + StatsTreeDialog *st_dlg = node->st->cfg->pr->st_dlg; + + QTreeWidgetItem *ti = new QTreeWidgetItem(), *parent = NULL; + + ti->setText(item_col_, node->name); + ti->setData(item_col_, Qt::UserRole, qVariantFromValue(node)); + node->pr = (st_node_pres *) ti; + if (node->parent && node->parent->pr) { + parent = (QTreeWidgetItem *) node->parent->pr; + parent->setExpanded(true); + } + if (parent) { + parent->addChild(ti); + } else { + st_dlg->ui->statsTreeWidget->addTopLevelItem(ti); + } + st_dlg->ui->statsTreeWidget->resizeColumnToContents(item_col_); +} + +void StatsTreeDialog::drawTreeItems(void *st_ptr) +{ + stats_tree *st = (stats_tree *) st_ptr; + if (!st || !st->cfg || !st->cfg->pr || !st->cfg->pr->st_dlg) return; + StatsTreeDialog *st_dlg = st->cfg->pr->st_dlg; + QTreeWidgetItemIterator iter(st_dlg->ui->statsTreeWidget); + + while (*iter) { + gchar value[NUM_BUF_SIZE]; + gchar rate[NUM_BUF_SIZE]; + gchar percent[NUM_BUF_SIZE]; + stat_node *node = (*iter)->data(item_col_, Qt::UserRole).value(); + if (node) { + stats_tree_get_strs_from_node(node, value, rate, + percent); + (*iter)->setText(count_col_, value); + (*iter)->setText(rate_col_, rate); + (*iter)->setText(percent_col_, percent); + } + ++iter; + } + st_dlg->ui->statsTreeWidget->resizeColumnToContents(count_col_); + st_dlg->ui->statsTreeWidget->resizeColumnToContents(rate_col_); + st_dlg->ui->statsTreeWidget->resizeColumnToContents(percent_col_); +} + +void StatsTreeDialog::on_applyFilterButton_clicked() +{ + fillTree(); +} + +void StatsTreeDialog::on_actionCopyAsCSV_triggered() +{ + QTreeWidgetItemIterator iter(ui->statsTreeWidget); + QString clip = QString("%1,%2,%3,%4\n") + .arg(ui->statsTreeWidget->headerItem()->text(item_col_)) + .arg(ui->statsTreeWidget->headerItem()->text(count_col_)) + .arg(ui->statsTreeWidget->headerItem()->text(rate_col_)) + .arg(ui->statsTreeWidget->headerItem()->text(percent_col_)); + + while (*iter) { + clip += QString("\"%1\",\"%2\",\"%3\",\"%4\"\n") + .arg((*iter)->text(item_col_)) + .arg((*iter)->text(count_col_)) + .arg((*iter)->text(rate_col_)) + .arg((*iter)->text(percent_col_)); + ++iter; + } + wsApp->clipboard()->setText(clip); +} + +void StatsTreeDialog::on_actionCopyAsYAML_triggered() +{ + QTreeWidgetItemIterator iter(ui->statsTreeWidget); + QString clip; + + while (*iter) { + QString indent; + if ((*iter)->parent()) { + QTreeWidgetItem *parent = (*iter)->parent(); + while (parent) { + indent += " "; + parent = parent->parent(); + } + clip += indent + "- description: \"" + (*iter)->text(item_col_) + "\"\n"; + indent += " "; + clip += indent + "count: " + (*iter)->text(count_col_) + "\n"; + clip += indent + "rate_ms: " + (*iter)->text(rate_col_) + "\n"; + clip += indent + "percent: " + (*iter)->text(percent_col_) + "\n"; + } else { + // Top level + clip += "description: \"" + (*iter)->text(item_col_) + "\"\n"; + clip += "count: " + (*iter)->text(count_col_) + "\n"; + clip += "rate_ms: " + (*iter)->text(rate_col_) + "\n"; + } + if ((*iter)->childCount() > 0) { + clip += indent + "items:\n"; + } + ++iter; + } + wsApp->clipboard()->setText(clip); +} + +extern "C" { +void +register_tap_listener_stats_tree_stat(void) +{ + + stats_tree_presentation(NULL, + StatsTreeDialog::setupNode, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL); +} +} + +/* + * 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/stats_tree_dialog.h b/ui/qt/stats_tree_dialog.h new file mode 100644 index 0000000000..1bf8df6d5e --- /dev/null +++ b/ui/qt/stats_tree_dialog.h @@ -0,0 +1,88 @@ +/* stats_tree_dialog.h + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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 STATS_TREE_DIALOG_H +#define STATS_TREE_DIALOG_H + +#include "config.h" + +#include + +#include "cfile.h" + +#include "epan/stats_tree_priv.h" + +#include + +namespace Ui { +class StatsTreeDialog; +} + +struct _tree_cfg_pres { + class StatsTreeDialog* st_dlg; +}; + +class StatsTreeDialog : public QDialog +{ + Q_OBJECT + +public: + explicit StatsTreeDialog(QWidget *parent = 0, capture_file *cf = NULL, const char *cfg_abbr = NULL); + ~StatsTreeDialog(); + static void setupNode(stat_node* node); + +public slots: + void setCaptureFile(capture_file *cf); + +private: + Ui::StatsTreeDialog *ui; + + struct _tree_cfg_pres cfg_pr_; + stats_tree *st_; + stats_tree_cfg *st_cfg_; + capture_file *cap_file_; + + void fillTree(); + static void resetTap(void *st_ptr); + static void drawTreeItems(void *st_ptr); + +private slots: + void on_applyFilterButton_clicked(); + void on_actionCopyAsCSV_triggered(); + void on_actionCopyAsYAML_triggered(); +}; + +#endif // STATS_TREE_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/stats_tree_dialog.ui b/ui/qt/stats_tree_dialog.ui new file mode 100644 index 0000000000..7ae32e7cc4 --- /dev/null +++ b/ui/qt/stats_tree_dialog.ui @@ -0,0 +1,141 @@ + + + StatsTreeDialog + + + + 0 + 0 + 587 + 459 + + + + Dialog + + + + + + + Item + + + + + Count + + + + + Rate (ms) + + + + + Percent + + + + + + + + + + Display filter: + + + + + + + + + + Regenerate statistics using this display filter + + + Apply + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close|QDialogButtonBox::Help + + + + + + + Copy as CSV + + + Copy the tree as CSV + + + Ctrl+C + + + + + Copy as YAML + + + Copy the tree as YAML + + + Ctrl+Y + + + + + + DisplayFilterEdit + QLineEdit +
display_filter_edit.h
+
+
+ + + + buttonBox + accepted() + StatsTreeDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + StatsTreeDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/ui/qt/wireshark_application.cpp b/ui/qt/wireshark_application.cpp index 613cdce3b6..92c22e80de 100644 --- a/ui/qt/wireshark_application.cpp +++ b/ui/qt/wireshark_application.cpp @@ -23,9 +23,11 @@ #include "wireshark_application.h" -#include -#include -#include +#include "wsutil/filesystem.h" + +#include "epan/disabled_protos.h" +#include "epan/tap.h" +#include "epan/timestamp.h" #include "ui/recent.h" #include "ui/simple_dialog.h" @@ -179,6 +181,11 @@ void WiresharkApplication::refreshRecentFiles(void) { } } +void WiresharkApplication::updateTaps() +{ + draw_tap_listeners(FALSE); +} + void WiresharkApplication::captureCallback(int event _U_, capture_session *cap_session _U_) { #ifdef HAVE_LIBPCAP @@ -437,7 +444,7 @@ void WiresharkApplication::setConfigurationProfile(const gchar *profile_name) timestamp_set_type (recent.gui_time_format); timestamp_set_seconds_type (recent.gui_seconds_format); color_filters_enable(recent.packet_list_colorize); - + tap_update_timer_.setInterval(prefs.tap_update_interval); prefsToCaptureOpts(); prefs_apply_all(); @@ -584,9 +591,14 @@ WiresharkApplication::WiresharkApplication(int &argc, char **argv) : setAttribute(Qt::AA_DontShowIconsInMenus, true); - recent_timer_ = new QTimer(this); - connect(recent_timer_, SIGNAL(timeout()), this, SLOT(refreshRecentFiles())); - recent_timer_->start(2000); + recent_timer_.setParent(this); + connect(&recent_timer_, SIGNAL(timeout()), this, SLOT(refreshRecentFiles())); + recent_timer_.start(2000); + + tap_update_timer_.setParent(this); + tap_update_timer_.setInterval(TAP_UPDATE_DEFAULT_INTERVAL); + connect(this, SIGNAL(appInitialized()), &tap_update_timer_, SLOT(start())); + connect(&tap_update_timer_, SIGNAL(timeout()), this, SLOT(updateTaps())); connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(cleanup())); } diff --git a/ui/qt/wireshark_application.h b/ui/qt/wireshark_application.h index edd219f7ad..067b7c66b5 100644 --- a/ui/qt/wireshark_application.h +++ b/ui/qt/wireshark_application.h @@ -42,6 +42,7 @@ #include #include #include +#include // Recent items: // - Read from prefs @@ -94,7 +95,8 @@ private: bool initialized_; QFont mono_regular_font_; QFont mono_bold_font_; - QTimer *recent_timer_; + QTimer recent_timer_; + QTimer tap_update_timer_; QList pending_open_files_; protected: @@ -136,6 +138,7 @@ private slots: void cleanup(); void itemStatusFinished(const QString &filename = "", qint64 size = 0, bool accessible = false); void refreshRecentFiles(void); + void updateTaps(); }; extern WiresharkApplication *wsApp; -- cgit v1.2.3