diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index face9b58d6..bbe6f09113 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -88,6 +88,7 @@ set(WIRESHARK_QT_HEADERS progress_bar.h proto_tree.h protocol_hierarchy_dialog.h + protocol_preferences_menu.h qcustomplot.h recent_file_status.h related_packet_delegate.h @@ -205,6 +206,7 @@ set(WIRESHARK_QT_SRC progress_bar.cpp proto_tree.cpp protocol_hierarchy_dialog.cpp + protocol_preferences_menu.cpp qcustomplot.cpp qt_ui_utils.cpp recent_file_status.cpp diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common index cf9ec50e93..d9a46bd794 100644 --- a/ui/qt/Makefile.common +++ b/ui/qt/Makefile.common @@ -192,6 +192,7 @@ MOC_HDRS = \ progress_bar.h \ proto_tree.h \ protocol_hierarchy_dialog.h \ + protocol_preferences_menu.h \ qcustomplot.h \ recent_file_status.h \ related_packet_delegate.h \ @@ -408,6 +409,7 @@ WIRESHARK_QT_SRC = \ progress_bar.cpp \ proto_tree.cpp \ protocol_hierarchy_dialog.cpp \ + protocol_preferences_menu.cpp \ qcustomplot.cpp \ qt_ui_utils.cpp \ recent_file_status.cpp \ diff --git a/ui/qt/Wireshark.pro b/ui/qt/Wireshark.pro index ccefec364c..bb35bb3863 100644 --- a/ui/qt/Wireshark.pro +++ b/ui/qt/Wireshark.pro @@ -311,6 +311,7 @@ HEADERS += $$HEADERS_WS_C \ print_dialog.h \ profile_dialog.h \ protocol_hierarchy_dialog.h \ + protocol_preferences_menu.h \ remote_capture_dialog.h \ remote_settings_dialog.h \ rtp_stream_dialog.h \ @@ -684,6 +685,7 @@ SOURCES += \ progress_bar.cpp \ proto_tree.cpp \ protocol_hierarchy_dialog.cpp \ + protocol_preferences_menu.cpp \ qcustomplot.cpp \ qt_ui_utils.cpp \ recent_file_status.cpp \ diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 53d9d7ae52..09d2b85d07 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -416,8 +416,10 @@ MainWindow::MainWindow(QWidget *parent) : this, SLOT(redissectPackets())); connect(packet_list_, SIGNAL(packetSelectionChanged()), this, SLOT(setMenusForFollowStream())); - connect(packet_list_, SIGNAL(showPreferences(PreferencesDialog::PreferencesPane)), + connect(packet_list_, SIGNAL(showColumnPreferences(PreferencesDialog::PreferencesPane)), this, SLOT(showPreferencesDialog(PreferencesDialog::PreferencesPane))); + connect(packet_list_, SIGNAL(showProtocolPreferences(QString)), + this, SLOT(showPreferencesDialog(QString))); connect(packet_list_, SIGNAL(editColumn(int)), this, SLOT(showColumnEditor(int))); connect(main_ui_->columnEditorFrame, SIGNAL(columnEdited()), packet_list_, SLOT(redrawVisiblePackets())); @@ -432,6 +434,8 @@ MainWindow::MainWindow(QWidget *parent) : this, SLOT(setMenusForSelectedTreeRow(field_info *))); connect(proto_tree_, SIGNAL(openPacketInNewWindow(bool)), this, SLOT(openPacketDialog(bool))); + connect(proto_tree_, SIGNAL(showProtocolPreferences(QString)), + this, SLOT(showPreferencesDialog(QString))); connect(byte_view_tab_, SIGNAL(byteFieldHovered(const QString&)), main_ui_->statusBar, SLOT(pushByteStatus(const QString&))); diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp index bffc2fee60..9240a142fc 100644 --- a/ui/qt/packet_list.cpp +++ b/ui/qt/packet_list.cpp @@ -400,11 +400,10 @@ PacketList::PacketList(QWidget *parent) : // " \n" // " \n" ctx_menu_.addSeparator(); -// " \n" + ctx_menu_.addMenu(&proto_prefs_menu_); decode_as_ = window()->findChild("actionAnalyzeDecodeAs"); ctx_menu_.addAction(decode_as_); // "Print" not ported intentionally -// " \n" action = window()->findChild("actionViewShowPacketInNewWindow"); ctx_menu_.addAction(action); @@ -423,6 +422,9 @@ PacketList::PacketList(QWidget *parent) : this, SLOT(sectionResized(int,int,int))); connect(verticalScrollBar(), SIGNAL(actionTriggered(int)), this, SLOT(vScrollBarActionTriggered(int))); + + connect(&proto_prefs_menu_, SIGNAL(showProtocolPreferences(QString)), + this, SIGNAL(showProtocolPreferences(QString))); } void PacketList::setProtoTree (ProtoTree *proto_tree) { @@ -533,6 +535,29 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) else action->setEnabled(FALSE); + const char *module_name = NULL; + if (cap_file_ && cap_file_->edt && cap_file_->edt->tree) { + GPtrArray *finfo_array = proto_all_finfos(cap_file_->edt->tree); + + for (guint i = finfo_array->len - 1; i > 0 ; i --) { + field_info *fi = (field_info *)g_ptr_array_index (finfo_array, i); + header_field_info *hfinfo = fi->hfinfo; + + if (!g_str_has_prefix(hfinfo->abbrev, "text") && + !g_str_has_prefix(hfinfo->abbrev, "_ws.expert") && + !g_str_has_prefix(hfinfo->abbrev, "_ws.malformed")) { + + if (hfinfo->parent == -1) { + module_name = hfinfo->abbrev; + } else { + module_name = proto_registrar_get_abbrev(hfinfo->parent); + } + break; + } + } + } + proto_prefs_menu_.setModule(module_name); + decode_as_->setData(qVariantFromValue(true)); ctx_column_ = columnAt(event->x()); ctx_menu_.exec(event->globalPos()); @@ -1162,7 +1187,7 @@ void PacketList::headerMenuTriggered() recent_set_column_xalign(header_ctx_column_, checked ? COLUMN_XALIGN_RIGHT : COLUMN_XALIGN_DEFAULT); break; case caColumnPreferences: - emit showPreferences(PreferencesDialog::ppColumn); + emit showColumnPreferences(PreferencesDialog::ppColumn); break; case caEditColumn: emit editColumn(header_ctx_column_); diff --git a/ui/qt/packet_list.h b/ui/qt/packet_list.h index 41ae6b141b..206b8b5858 100644 --- a/ui/qt/packet_list.h +++ b/ui/qt/packet_list.h @@ -26,6 +26,7 @@ #include "packet_list_model.h" #include "preferences_dialog.h" #include "proto_tree.h" +#include "protocol_preferences_menu.h" #include "related_packet_delegate.h" #include @@ -84,6 +85,7 @@ private: capture_file *cap_file_; QMenu ctx_menu_; QMenu conv_menu_; + ProtocolPreferencesMenu proto_prefs_menu_; QAction *decode_as_; int ctx_column_; QByteArray column_state_; @@ -111,9 +113,10 @@ private: signals: void packetDissectionChanged(); void packetSelectionChanged(); - void showPreferences(PreferencesDialog::PreferencesPane start_pane); + void showColumnPreferences(PreferencesDialog::PreferencesPane start_pane); void editColumn(int column); void packetListScrolled(bool at_end); + void showProtocolPreferences(const QString module_name); public slots: void setCaptureFile(capture_file *cf); diff --git a/ui/qt/proto_tree.cpp b/ui/qt/proto_tree.cpp index 2d1b404587..e2848f41f3 100644 --- a/ui/qt/proto_tree.cpp +++ b/ui/qt/proto_tree.cpp @@ -251,8 +251,8 @@ ProtoTree::ProtoTree(QWidget *parent) : // " \n" // " \n" // " \n" -// " \n" -// ctx_menu_.addSeparator(); + ctx_menu_.addMenu(&proto_prefs_menu_); + ctx_menu_.addSeparator(); decode_as_ = window()->findChild("actionAnalyzeDecodeAs"); ctx_menu_.addAction(decode_as_); // " \n" @@ -269,6 +269,9 @@ ProtoTree::ProtoTree(QWidget *parent) : connect(this, SIGNAL(collapsed(QModelIndex)), this, SLOT(collapse(QModelIndex))); connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(itemDoubleClick(QTreeWidgetItem*, int))); + + connect(&proto_prefs_menu_, SIGNAL(showProtocolPreferences(QString)), + this, SIGNAL(showProtocolPreferences(QString))); } void ProtoTree::clear() { @@ -286,6 +289,19 @@ void ProtoTree::contextMenuEvent(QContextMenuEvent *event) conv_menu_.addAction(action); } + const char *module_name = NULL; + if (selectedItems().count() > 0) { + field_info *fi = selectedItems()[0]->data(0, Qt::UserRole).value(); + if (fi && fi->hfinfo) { + if (fi->hfinfo->parent == -1) { + module_name = fi->hfinfo->abbrev; + } else { + module_name = proto_registrar_get_abbrev(fi->hfinfo->parent); + } + } + } + proto_prefs_menu_.setModule(module_name); + decode_as_->setData(qVariantFromValue(true)); ctx_menu_.exec(event->globalPos()); decode_as_->setData(QVariant()); diff --git a/ui/qt/proto_tree.h b/ui/qt/proto_tree.h index d2b86a4345..2114fccd7c 100644 --- a/ui/qt/proto_tree.h +++ b/ui/qt/proto_tree.h @@ -26,6 +26,8 @@ #include +#include "protocol_preferences_menu.h" + #include #include @@ -47,6 +49,7 @@ protected: private: QMenu ctx_menu_; QMenu conv_menu_; + ProtocolPreferencesMenu proto_prefs_menu_; QAction *decode_as_; QFont mono_font_; @@ -56,6 +59,7 @@ signals: void openPacketInNewWindow(bool); void goToPacket(int); void relatedFrame(int, ft_framenum_type_t); + void showProtocolPreferences(const QString module_name); public slots: void setMonospaceFont(const QFont &mono_font); diff --git a/ui/qt/protocol_preferences_menu.cpp b/ui/qt/protocol_preferences_menu.cpp new file mode 100644 index 0000000000..ddc285cf93 --- /dev/null +++ b/ui/qt/protocol_preferences_menu.cpp @@ -0,0 +1,315 @@ +/* protocol_preferences_menu.h + * + * 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 "config.h" + +#include + +#include +#include +#include + +#include +#include + +#include "protocol_preferences_menu.h" + +#include "uat_dialog.h" +#include "wireshark_application.h" + +// To do: +// - Add a PreferencesEditorFrame to the main window similar to +// menu_prefs_edit_dlg in the GTK+ UI. For now we just open the main +// preferences dialog. +// - Elide really long items? + +#include + +class EnumPreferenceAction : public QAction +{ +public: + EnumPreferenceAction(pref_t *pref, const char *title, int enumval, QActionGroup *ag) : + QAction(NULL), + pref_(pref), + enumval_(enumval) + { + setText(title); + setActionGroup(ag); + setCheckable(true); + } + + bool setEnumValue() { + if (*pref_->varp.enump != enumval_) { + *pref_->varp.enump = enumval_; + return true; + } + return false; + } + +private: + pref_t *pref_; + int enumval_; +}; + +class UatPreferenceAction : public QAction +{ +public: + UatPreferenceAction(pref_t *pref) : + QAction(NULL), + pref_(pref) + { + setText(QString("%1" UTF8_HORIZONTAL_ELLIPSIS).arg(pref_->title)); + } + + void showUatDialog() { + UatDialog uat_dlg(parentWidget(), pref_->varp.uat); + uat_dlg.exec(); + } + +private: + pref_t *pref_; +}; + + +class PreferenceAction : public QAction +{ +public: + PreferenceAction(pref_t *pref) : + QAction(NULL), + pref_(pref) + { + QString title = pref_->title; + + switch(pref_->type) { + case PREF_UINT: + { + int base = 10; + switch(pref_->info.base) { + case 8: + base = 8; + break; + case 16: + base = 16; + break; + default: + break; + } + title.append(QString(": %1" UTF8_HORIZONTAL_ELLIPSIS).arg(QString::number(*pref->varp.uint, base))); + break; + } + case PREF_BOOL: + setCheckable(true); + setChecked(*pref->varp.boolp); + break; + case PREF_ENUM: + // We shoudn't be here. + break; + case PREF_STRING: + title.append(QString(": %1" UTF8_HORIZONTAL_ELLIPSIS).arg(*pref->varp.string)); + break; + case PREF_UAT: + title.append(UTF8_HORIZONTAL_ELLIPSIS); + break; + case PREF_COLOR: // XXX Add an icon? + + case PREF_CUSTOM: // We shouldn't be here. + case PREF_STATIC_TEXT: + case PREF_OBSOLETE: + default: + break; + } + + setText(title); + } + + void setBoolValue() { + *pref_->varp.boolp = isChecked(); + } + +private: + pref_t *pref_; +}; + +extern "C" { +// Preference callback + +static guint +add_prefs_menu_item(pref_t *pref, gpointer menu_ptr) +{ + ProtocolPreferencesMenu *pp_menu = static_cast(menu_ptr); + if (!pp_menu) return 1; + + pp_menu->addMenuItem(pref); + + return 0; +} +} + + +ProtocolPreferencesMenu::ProtocolPreferencesMenu() +{ + setTitle(tr("Protocol Preferences")); + setModule(NULL); +} + +void ProtocolPreferencesMenu::setModule(const char *module_name) +{ + QAction *action; + int proto_id = -1; + protocol_t *protocol; + + clear(); + module_name_.clear(); + module_ = NULL; + + if (module_name) { + proto_id = proto_get_id_by_filter_name(module_name); + protocol = find_protocol_by_id(proto_id); + } + + if (proto_id < 0 || !protocol) { + action = addAction(tr("No protocol preferences available")); + action->setDisabled(true); + return; + } + + module_ = prefs_find_module(module_name); + const QString proto_name = proto_get_protocol_long_name(protocol); + if (!module_ || !prefs_is_registered_protocol(module_name)) { + action = addAction(tr("%1 has no preferences").arg(proto_name)); + action->setDisabled(true); + return; + } + + module_name_ = module_name; + + action = addAction(tr("Open %1 preferences" UTF8_HORIZONTAL_ELLIPSIS).arg(proto_name)); + action->setData(QString(module_name)); + connect(action, SIGNAL(triggered(bool)), this, SLOT(protocolPreferencesTriggered())); + + addSeparator(); + + prefs_pref_foreach(module_, add_prefs_menu_item, this); +} + +void ProtocolPreferencesMenu::addMenuItem(preference *pref) +{ + switch (pref->type) { + case PREF_ENUM: + { + QActionGroup *ag = new QActionGroup(this); + QMenu *enum_menu = addMenu(pref->title); + for (const enum_val_t *enum_valp = pref->info.enum_info.enumvals; enum_valp->name; enum_valp++) { + EnumPreferenceAction *epa = new EnumPreferenceAction(pref, enum_valp->description, enum_valp->value, ag); + if (*pref->varp.enump == enum_valp->value) { + epa->setChecked(true); + } + enum_menu->addAction(epa); + connect(epa, SIGNAL(triggered(bool)), this, SLOT(enumPreferenceTriggered())); + } + break; + } + case PREF_UAT: + { + UatPreferenceAction *upa = new UatPreferenceAction(pref); + addAction(upa); + connect(upa, SIGNAL(triggered(bool)), this, SLOT(uatPreferenceTriggered())); + break; + } + case PREF_CUSTOM: + case PREF_STATIC_TEXT: + case PREF_OBSOLETE: + break; + default: + { + PreferenceAction *pa = new PreferenceAction(pref); + addAction(pa); + if (pref->type == PREF_BOOL) { + connect(pa, SIGNAL(triggered(bool)), this, SLOT(boolPreferenceTriggered())); + } else { + connect(pa, SIGNAL(triggered(bool)), this, SLOT(protocolPreferencesTriggered())); + } + break; + } + } + + if (pref->type != PREF_ENUM) { + } else { + } +} + +void ProtocolPreferencesMenu::protocolPreferencesTriggered() +{ + if (!module_name_.isEmpty()) { + emit showProtocolPreferences(module_name_); + } +} + +void ProtocolPreferencesMenu::boolPreferenceTriggered() +{ + PreferenceAction *pa = static_cast(QObject::sender()); + if (!pa) return; + + pa->setBoolValue(); + + prefs_apply(module_); + if (!prefs.gui_use_pref_save) { + prefs_main_write(); + } + + wsApp->emitAppSignal(WiresharkApplication::PacketDissectionChanged); +} + +void ProtocolPreferencesMenu::enumPreferenceTriggered() +{ + EnumPreferenceAction *epa = static_cast(QObject::sender()); + if (!epa) return; + + if (epa->setEnumValue()) { // Changed + prefs_apply(module_); + if (!prefs.gui_use_pref_save) { + prefs_main_write(); + } + + wsApp->emitAppSignal(WiresharkApplication::PacketDissectionChanged); + } +} + +void ProtocolPreferencesMenu::uatPreferenceTriggered() +{ + UatPreferenceAction *upa = static_cast(QObject::sender()); + if (!upa) return; + + upa->showUatDialog(); +} + +/* + * 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/protocol_preferences_menu.h b/ui/qt/protocol_preferences_menu.h new file mode 100644 index 0000000000..da39b61c94 --- /dev/null +++ b/ui/qt/protocol_preferences_menu.h @@ -0,0 +1,67 @@ +/* protocol_preferences_menu.h + * + * 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 __PROTOCOL_PREFERENCES_MENU_H__ +#define __PROTOCOL_PREFERENCES_MENU_H__ + +#include + +struct pref_module; +struct preference; + +class ProtocolPreferencesMenu : public QMenu +{ + Q_OBJECT + +public: + ProtocolPreferencesMenu(); + + void setModule(const char *module_name); + void addMenuItem(struct preference *pref); + +signals: + void showProtocolPreferences(const QString module_name); + +private: + QString module_name_; + struct pref_module *module_; + +private slots: + void protocolPreferencesTriggered(); + void boolPreferenceTriggered(); + void enumPreferenceTriggered(); + void uatPreferenceTriggered(); +}; + +#endif // __PROTOCOL_PREFERENCES_MENU_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: + */