diff --git a/epan/stat_groups.h b/epan/stat_groups.h index c6fcbe2d1d..f31eba9c8f 100644 --- a/epan/stat_groups.h +++ b/epan/stat_groups.h @@ -56,7 +56,7 @@ extern "C" { /** The group this stat should be registered in. */ typedef enum { REGISTER_ANALYZE_GROUP_UNSORTED, /* unsorted analyze stuff */ - REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER, /* conversation filters */ + REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER, /* conversation filters. Unused? */ REGISTER_STAT_GROUP_UNSORTED, /* unsorted statistic function */ REGISTER_STAT_GROUP_GENERIC, /* generic statistic function, not specific to a protocol */ REGISTER_STAT_GROUP_CONVERSATION_LIST, /* member of the conversation list */ diff --git a/ui/qt/funnel_statistics.cpp b/ui/qt/funnel_statistics.cpp index d2d1ee3063..a1cd51c62e 100644 --- a/ui/qt/funnel_statistics.cpp +++ b/ui/qt/funnel_statistics.cpp @@ -74,6 +74,7 @@ public: retap_(retap) { setText(title); + setObjectName(FunnelStatistics::actionName()); } void triggerCallback() { @@ -94,6 +95,7 @@ private: }; static QList funnel_actions_; +const QString FunnelStatistics::action_name_ = "FunnelStatisticsAction"; FunnelStatistics::FunnelStatistics(QObject *parent, CaptureFile &cf) : QObject(parent), @@ -276,7 +278,7 @@ static void register_menu_cb(const char *name, gpointer callback_data, gboolean retap) { FunnelAction *funnel_action = new FunnelAction(name, callback, callback_data, retap); - wsApp->addFunnelGroupItem(group, funnel_action); + wsApp->addDynamicMenuGroupItem(group, funnel_action); funnel_actions_ << funnel_action; } diff --git a/ui/qt/funnel_statistics.h b/ui/qt/funnel_statistics.h index ba8e2bf31d..19778cef6e 100644 --- a/ui/qt/funnel_statistics.h +++ b/ui/qt/funnel_statistics.h @@ -44,6 +44,7 @@ public: void reloadPackets(); void emitApplyDisplayFilter(); void emitOpenCaptureFile(QString &cf_path, QString &filter); + static const QString &actionName() { return action_name_; } signals: void setDisplayFilter(const QString &filter); @@ -55,6 +56,7 @@ public slots: void displayFilterTextChanged(const QString &filter); private: + static const QString action_name_; struct _funnel_ops_t *funnel_ops_; CaptureFile &capture_file_; QByteArray display_filter_; diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 9a462e0578..16297ec08a 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -53,6 +53,7 @@ #include "proto_tree.h" #include "simple_dialog.h" #include "stock_icon.h" +#include "tap_parameter_dialog.h" #include "wireless_frame.h" #include "wireshark_application.h" @@ -239,9 +240,8 @@ MainWindow::MainWindow(QWidget *parent) : connect(wsApp, SIGNAL(appInitialized()), this, SLOT(setFeaturesEnabled())); connect(wsApp, SIGNAL(appInitialized()), this, SLOT(zoomText())); connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addStatsPluginsToMenu())); - connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addStatisticsMenus())); + connect(wsApp, SIGNAL(appInitialized()), this, SLOT(addDynamicMenus())); 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())); @@ -1977,33 +1977,93 @@ void MainWindow::setForCaptureInProgress(gboolean capture_in_progress) #endif } -void MainWindow::addStatisticsMenus() +void MainWindow::addDynamicMenus() { - // actionStatistics_REGISTER_STAT_GROUP_UNSORTED should exist and be. - // invisible. - QListunsorted_actions = wsApp->statisticsGroupItems(REGISTER_STAT_GROUP_UNSORTED); + QList menu_groups = QList() + << REGISTER_ANALYZE_GROUP_UNSORTED + << REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER + << REGISTER_STAT_GROUP_UNSORTED + << REGISTER_STAT_GROUP_GENERIC + << REGISTER_STAT_GROUP_CONVERSATION_LIST + << REGISTER_STAT_GROUP_ENDPOINT_LIST + << REGISTER_STAT_GROUP_RESPONSE_TIME + << REGISTER_STAT_GROUP_TELEPHONY + << REGISTER_STAT_GROUP_TELEPHONY_ANSI + << REGISTER_STAT_GROUP_TELEPHONY_GSM + << REGISTER_STAT_GROUP_TELEPHONY_LTE + << REGISTER_STAT_GROUP_TELEPHONY_SCTP + << REGISTER_TOOLS_GROUP_UNSORTED; - foreach (QAction *unsorted_action, unsorted_actions) { - main_ui_->menuStatistics->insertAction( - main_ui_->actionStatistics_REGISTER_STAT_GROUP_UNSORTED, - unsorted_action); - connect(unsorted_action, SIGNAL(triggered(bool)), this, SLOT(openTapParameterDialog())); + foreach (register_stat_group_t menu_group, menu_groups) { + QListactions = wsApp->dynamicMenuGroupItems(menu_group); + foreach (QAction *action, actions) { + switch (menu_group) { + case REGISTER_ANALYZE_GROUP_UNSORTED: + case REGISTER_STAT_GROUP_UNSORTED: + main_ui_->menuStatistics->insertAction( + main_ui_->actionStatistics_REGISTER_STAT_GROUP_UNSORTED, + action); + break; + case REGISTER_STAT_GROUP_RESPONSE_TIME: + main_ui_->menuServiceResponseTime->addAction(action); + break; + case REGISTER_STAT_GROUP_TELEPHONY: + main_ui_->menuTelephony->addAction(action); + break; + case REGISTER_STAT_GROUP_TELEPHONY_ANSI: + main_ui_->menuANSI->addAction(action); + break; + case REGISTER_TOOLS_GROUP_UNSORTED: + { + // Allow the creation of submenus. Mimics the behavor of + // ui/gtk/main_menubar.c:add_menu_item_to_main_menubar + // and GtkUIManager. + // + // For now we limit the insanity to the "Tools" menu. + QStringList menu_path = action->text().split('/'); + QMenu *cur_menu = main_ui_->menuTools; + while (menu_path.length() > 1) { + QString menu_title = menu_path.takeFirst(); + #if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0)) + QMenu *submenu = cur_menu->findChild(menu_title.toLower(), Qt::FindDirectChildrenOnly); + #else + QMenu *submenu = cur_menu->findChild(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; + } + action->setText(menu_path.last()); + cur_menu->addAction(action); + break; + } + default: +// qDebug() << "FIX: Add" << action->text() << "to the menu"; + break; + } + + // Connect each action type to its corresponding slot. We to + // distinguish various types of actions. Setting their objectName + // seems to work OK. + if (action->objectName() == TapParameterDialog::actionName()) { + connect(action, SIGNAL(triggered(bool)), this, SLOT(openTapParameterDialog())); + } else if (action->objectName() == FunnelStatistics::actionName()) { + connect(action, SIGNAL(triggered(bool)), funnel_statistics_, SLOT(funnelActionTriggered())); + } + } } - // Response time - QListsg_actions = wsApp->statisticsGroupItems(REGISTER_STAT_GROUP_RESPONSE_TIME); - - foreach (QAction *sg_action, sg_actions) { - main_ui_->menuServiceResponseTime->addAction(sg_action); - connect(sg_action, SIGNAL(triggered(bool)), this, SLOT(openTapParameterDialog())); + // 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 (wsApp->dynamicMenuGroupItems(REGISTER_TOOLS_GROUP_UNSORTED).length() > 0) { + main_ui_->actionToolsPlaceholder->setVisible(false); } - - // Telephony - sg_actions = wsApp->statisticsGroupItems(REGISTER_STAT_GROUP_TELEPHONY); - - foreach (QAction *sg_action, sg_actions) { - main_ui_->menuTelephony->addAction(sg_action); - connect(sg_action, SIGNAL(triggered(bool)), this, SLOT(openTapParameterDialog())); + if (wsApp->dynamicMenuGroupItems(REGISTER_STAT_GROUP_TELEPHONY_ANSI).length() > 0) { + main_ui_->actionTelephonyANSIPlaceholder->setVisible(false); } } @@ -2080,43 +2140,6 @@ 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. - QListfunnel_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(menu_title.toLower(), Qt::FindDirectChildrenOnly); -#else - QMenu *submenu = cur_menu->findChild(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 0bc10938bc..d11248b094 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -262,9 +262,8 @@ private slots: void showColumnEditor(int column); void showPreferenceEditor(); // module_t *, pref * void addStatsPluginsToMenu(); - void addStatisticsMenus(); + void addDynamicMenus(); void addExternalMenus(); - void addFunnelMenus(); void startInterfaceCapture(bool valid); diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index 72f163c7e9..b0d238bffb 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -481,7 +481,14 @@ + + + ANSI + + + + @@ -2390,6 +2397,14 @@ QAction::NoRole + + + false + + + No ANSI statistics registered + + diff --git a/ui/qt/tap_parameter_dialog.cpp b/ui/qt/tap_parameter_dialog.cpp index 9bc6433c46..b337b857d7 100644 --- a/ui/qt/tap_parameter_dialog.cpp +++ b/ui/qt/tap_parameter_dialog.cpp @@ -70,6 +70,7 @@ const int expand_all_threshold_ = 100; // Arbitrary static QHash cfg_str_to_creator_; +const QString TapParameterDialog::action_name_ = "TapParameterAction"; TapParameterDialog::TapParameterDialog(QWidget &parent, CaptureFile &cf, int help_topic) : WiresharkDialog(parent, cf), @@ -117,8 +118,9 @@ void TapParameterDialog::registerDialog(const QString title, const char *cfg_abb cfg_str_to_creator_[cfg_str] = creator; QAction *tpd_action = new QAction(title, NULL); + tpd_action->setObjectName(action_name_); tpd_action->setData(cfg_str); - wsApp->addStatisticsGroupItem(group, tpd_action); + wsApp->addDynamicMenuGroupItem(group, tpd_action); } TapParameterDialog *TapParameterDialog::showTapParameterStatistics(QWidget &parent, CaptureFile &cf, const QString cfg_str, const QString arg, void *) diff --git a/ui/qt/tap_parameter_dialog.h b/ui/qt/tap_parameter_dialog.h index 8203fcbd7f..f9af3391bd 100644 --- a/ui/qt/tap_parameter_dialog.h +++ b/ui/qt/tap_parameter_dialog.h @@ -52,6 +52,7 @@ public: explicit TapParameterDialog(QWidget &parent, CaptureFile &cf, int help_topic = 0); ~TapParameterDialog(); + static const QString &actionName() { return action_name_; } static void registerDialog(const QString title, const char *cfg_abbr, register_stat_group_t group, stat_tap_init_cb tap_init_cb, tpdCreator creator); static TapParameterDialog *showTapParameterStatistics(QWidget &parent, CaptureFile &cf, const QString cfg_str, const QString arg, void *); @@ -81,6 +82,7 @@ protected slots: private: Ui::TapParameterDialog *ui; int help_topic_; + static const QString action_name_; // Called by the constructor. The subclass should tap packets here. virtual void fillTree() = 0; diff --git a/ui/qt/wireshark_application.cpp b/ui/qt/wireshark_application.cpp index 1439c72f0f..fb37ccf2e8 100644 --- a/ui/qt/wireshark_application.cpp +++ b/ui/qt/wireshark_application.cpp @@ -89,7 +89,7 @@ WiresharkApplication *wsApp = NULL; static char *last_open_dir = NULL; static bool updated_last_open_dir = FALSE; static QList recent_items_; -static QHash > statistics_groups_; +static QHash > dynamic_menu_groups_; static QHash > funnel_groups_; QString WiresharkApplication::window_title_separator_ = QString::fromUtf8(" " UTF8_MIDDLE_DOT " "); @@ -573,44 +573,25 @@ void WiresharkApplication::emitTapParameterSignal(const QString cfg_abbr, const } // XXX Combine statistics and funnel routines into addGroupItem + groupItems? -void WiresharkApplication::addStatisticsGroupItem(int group, QAction *sg_action) +void WiresharkApplication::addDynamicMenuGroupItem(int group, QAction *sg_action) { - if (!statistics_groups_.contains(group)) { - statistics_groups_[group] = QList(); + if (!dynamic_menu_groups_.contains(group)) { + dynamic_menu_groups_[group] = QList(); } - statistics_groups_[group] << sg_action; + dynamic_menu_groups_[group] << sg_action; } -QList WiresharkApplication::statisticsGroupItems(int group) +QList WiresharkApplication::dynamicMenuGroupItems(int group) { - if (!statistics_groups_.contains(group)) { + if (!dynamic_menu_groups_.contains(group)) { return QList(); } - QList sgi_list = statistics_groups_[group]; + QList sgi_list = dynamic_menu_groups_[group]; std::sort(sgi_list.begin(), sgi_list.end(), qActionLessThan); return sgi_list; } -void WiresharkApplication::addFunnelGroupItem(int group, QAction *fg_action) -{ - if (!funnel_groups_.contains(group)) { - funnel_groups_[group] = QList(); - } - funnel_groups_[group] << fg_action; -} - -QList WiresharkApplication::funnelGroupItems(int group) -{ - if (!funnel_groups_.contains(group)) { - return QList(); - } - - QList 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 1b7941e8e8..dcd9cb24ea 100644 --- a/ui/qt/wireshark_application.h +++ b/ui/qt/wireshark_application.h @@ -74,11 +74,8 @@ public: void emitAppSignal(AppSignal signal); void emitStatCommandSignal(const QString &menu_path, const char *arg, void *userdata); void emitTapParameterSignal(const QString cfg_abbr, const QString arg, void *userdata); - // Map a register_stat_group_t to a list of stat_tap_ui.title - void addStatisticsGroupItem(int group, QAction *sg_action); - QListstatisticsGroupItems(int group); - void addFunnelGroupItem(int group, QAction *fg_action); - QList funnelGroupItems(int group); + void addDynamicMenuGroupItem(int group, QAction *sg_action); + QList dynamicMenuGroupItems(int group); void allSystemsGo(); void refreshLocalInterfaces();