diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index 3a254c5fa8..ed87d57ecb 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -30,6 +30,7 @@ set(WIRESHARK_WIDGET_HEADERS widgets/clickable_label.h widgets/display_filter_combo.h widgets/display_filter_edit.h + widgets/dissector_tables_view.h widgets/drag_drop_toolbar.h widgets/drag_label.h widgets/editor_color_dialog.h @@ -66,6 +67,7 @@ set(WIRESHARK_MODEL_HEADERS models/cache_proxy_model.h models/decode_as_delegate.h models/decode_as_model.h + models/dissector_tables_model.h models/enabled_protocols_model.h models/expert_info_model.h models/expert_info_proxy_model.h @@ -246,6 +248,7 @@ set(WIRESHARK_WIDGET_SRCS widgets/clickable_label.cpp widgets/display_filter_combo.cpp widgets/display_filter_edit.cpp + widgets/dissector_tables_view.cpp widgets/drag_drop_toolbar.cpp widgets/drag_label.cpp widgets/editor_color_dialog.cpp @@ -280,6 +283,7 @@ set(WIRESHARK_MODEL_SRCS models/cache_proxy_model.cpp models/decode_as_delegate.cpp models/decode_as_model.cpp + models/dissector_tables_model.cpp models/enabled_protocols_model.cpp models/expert_info_model.cpp models/expert_info_proxy_model.cpp diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am index 11d2c37b39..385f909d3f 100644 --- a/ui/qt/Makefile.am +++ b/ui/qt/Makefile.am @@ -160,6 +160,9 @@ MOC_WIDGET_HDRS = \ widgets/clickable_label.h \ widgets/display_filter_combo.h \ widgets/display_filter_edit.h \ + widgets/dissector_tables_view.h \ + widgets/drag_drop_toolbar.h \ + widgets/drag_label.h \ widgets/editor_color_dialog.h \ widgets/editor_file_dialog.h \ widgets/elided_label.h \ @@ -173,8 +176,6 @@ MOC_WIDGET_HDRS = \ widgets/syntax_line_edit.h \ widgets/stock_icon_tool_button.h \ widgets/tabnav_tree_view.h \ - widgets/drag_drop_toolbar.h \ - widgets/drag_label.h \ widgets/qcustomplot.h # Files that are utility classes with multi-purpose, but no widgets @@ -195,6 +196,7 @@ MOC_MODELS_HDRS = \ models/cache_proxy_model.h \ models/decode_as_delegate.h \ models/decode_as_model.h \ + models/dissector_tables_model.h \ models/enabled_protocols_model.h \ models/expert_info_model.h \ models/expert_info_proxy_model.h \ @@ -490,6 +492,9 @@ WIRESHARK_QT_WIDGET_SRC = \ widgets/clickable_label.cpp \ widgets/display_filter_combo.cpp \ widgets/display_filter_edit.cpp \ + widgets/dissector_tables_view.cpp \ + widgets/drag_drop_toolbar.cpp \ + widgets/drag_label.cpp \ widgets/editor_color_dialog.cpp \ widgets/editor_file_dialog.cpp \ widgets/elided_label.cpp \ @@ -503,8 +508,6 @@ WIRESHARK_QT_WIDGET_SRC = \ widgets/stock_icon_tool_button.cpp \ widgets/syntax_line_edit.cpp \ widgets/tabnav_tree_view.cpp \ - widgets/drag_drop_toolbar.cpp \ - widgets/drag_label.cpp \ widgets/qcustomplot.cpp WIRESHARK_QT_UTILS_SRC = \ @@ -522,6 +525,7 @@ WIRESHARK_QT_MODELS_SRCS = \ models/cache_proxy_model.cpp \ models/decode_as_delegate.cpp \ models/decode_as_model.cpp \ + models/dissector_tables_model.cpp \ models/enabled_protocols_model.cpp \ models/expert_info_model.cpp \ models/expert_info_proxy_model.cpp \ diff --git a/ui/qt/dissector_tables_dialog.cpp b/ui/qt/dissector_tables_dialog.cpp index 7a1490b21b..029c2dfddc 100644 --- a/ui/qt/dissector_tables_dialog.cpp +++ b/ui/qt/dissector_tables_dialog.cpp @@ -4,277 +4,60 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ + #include "config.h" + #include "dissector_tables_dialog.h" #include -#include "config.h" - -#include - -#include +#include #include "wireshark_application.h" -enum { - col_table_name_, - col_short_name_ -}; - -enum { - top_level_type_ = 1000, - table_type_, - string_type_, - integer_type_, - custom_type_, - heuristic_type_ -}; - -class DissectorTableTreeWidgetItem : public QTreeWidgetItem -{ -public: - DissectorTableTreeWidgetItem(QString table_name, QString short_name) : QTreeWidgetItem (table_type_) { - setText(col_table_name_, table_name); - setText(col_short_name_, short_name); - } -}; - -class IntegerTableTreeWidgetItem : public QTreeWidgetItem -{ -public: - IntegerTableTreeWidgetItem(unsigned port, QString proto_name) : - QTreeWidgetItem (integer_type_), - port_(port) - { - setText(col_table_name_, QString::number(port_)); - setText(col_short_name_, proto_name); - } - bool operator< (const QTreeWidgetItem &other) const - { - if (other.type() != integer_type_) return QTreeWidgetItem::operator< (other); - const IntegerTableTreeWidgetItem *other_row = static_cast(&other); - - if (treeWidget()->sortColumn() == col_table_name_) { - return port_ < other_row->port_; - } - return QTreeWidgetItem::operator< (other); - } - -private: - unsigned port_; -}; DissectorTablesDialog::DissectorTablesDialog(QWidget *parent) : GeometryStateDialog(parent), - ui(new Ui::DissectorTablesDialog) + ui(new Ui::DissectorTablesDialog), + dissector_tables_model_(new DissectorTablesModel()), + proxyModel_(new DissectorTablesProxyModel(this)) { ui->setupUi(this); if (parent) loadGeometry(parent->width() * 3 / 4, parent->height() * 3 / 4); setAttribute(Qt::WA_DeleteOnClose, true); setWindowTitle(wsApp->windowTitleString(tr("Dissector Tables"))); - on_tableTreeWidget_itemSelectionChanged(); + proxyModel_->setSourceModel(dissector_tables_model_); + ui->tableTree->setModel(proxyModel_); - QTreeWidgetItem *string_ti = new QTreeWidgetItem(ui->tableTreeWidget, top_level_type_); - string_ti->setText(col_table_name_, tr("String Tables")); - string_ti->setFirstColumnSpanned(true); - string_ti->setExpanded(true); - - QTreeWidgetItem *integer_ti = new QTreeWidgetItem(ui->tableTreeWidget, top_level_type_); - integer_ti->setText(col_table_name_, tr("Integer Tables")); - integer_ti->setFirstColumnSpanned(true); - integer_ti->setExpanded(true); - - QTreeWidgetItem *custom_ti = new QTreeWidgetItem(ui->tableTreeWidget, top_level_type_); - custom_ti->setText(col_table_name_, tr("Custom Tables")); - custom_ti->setFirstColumnSpanned(true); - custom_ti->setExpanded(true); - - dissector_all_tables_foreach_table(gatherTableNames, this, NULL); - - string_ti->addChildren(string_dissectors_); - integer_ti->addChildren(integer_dissectors_); - integer_ti->addChildren(custom_dissectors_); - - QTreeWidgetItem *heuristic_ti = new QTreeWidgetItem(ui->tableTreeWidget, top_level_type_); - heuristic_ti->setText(col_table_name_, tr("Heuristic Tables")); - heuristic_ti->setFirstColumnSpanned(true); - heuristic_ti->setExpanded(true); - - dissector_all_heur_tables_foreach_table(gatherHeurTableNames, this, NULL); - - heuristic_ti->addChildren(heuristic_dissectors_); - - ui->tableTreeWidget->sortByColumn(col_table_name_, Qt::AscendingOrder); - ui->tableTreeWidget->resizeColumnToContents(col_table_name_); + QTimer::singleShot(0, this, SLOT(fillTree())); } DissectorTablesDialog::~DissectorTablesDialog() { delete ui; + delete proxyModel_; + delete dissector_tables_model_; } -void DissectorTablesDialog::gatherTableNames(const char *short_name, const char *table_name, gpointer dlg_ptr) +void DissectorTablesDialog::fillTree() { - DissectorTablesDialog *dt_dlg = qobject_cast((DissectorTablesDialog *)dlg_ptr); - if (!dt_dlg) return; + dissector_tables_model_->populate(); - ftenum_t selector_type = get_dissector_table_selector_type(short_name); - DissectorTableTreeWidgetItem *dt_ti = new DissectorTableTreeWidgetItem(table_name, short_name); + //it's recommended to sort after list is populated + proxyModel_->sort(DissectorTablesModel::colTableName); - switch (selector_type) { - case FT_UINT8: - case FT_UINT16: - case FT_UINT24: - case FT_UINT32: - dt_dlg->integer_dissectors_ << dt_ti; - break; - case FT_STRING: - case FT_STRINGZ: - case FT_UINT_STRING: - case FT_STRINGZPAD: - dt_dlg->string_dissectors_ << dt_ti; - break; - case FT_BYTES: - dt_dlg->custom_dissectors_ << dt_ti; - break; - default: - // Assert? - delete dt_ti; - return; + //expand the "type" tables + for (int row = 0; row < proxyModel_->rowCount(); row++) { + ui->tableTree->setExpanded(proxyModel_->index(row, DissectorTablesModel::colTableName), true); } - QList proto_decode_list; - dissector_table_foreach(short_name, gatherProtocolDecodes, &proto_decode_list); - - dt_ti->addChildren(proto_decode_list); + ui->tableTree->resizeColumnToContents(DissectorTablesModel::colTableName); } -void DissectorTablesDialog::gatherProtocolDecodes(const char *, ftenum_t selector_type, gpointer key, gpointer value, gpointer list_ptr) +void DissectorTablesDialog::on_search_line_edit__textChanged(const QString &search_re) { - QList *pdl_ptr = dynamic_cast *>((QList *)list_ptr); - if (!pdl_ptr) return; - - dtbl_entry_t *dtbl_entry; - dissector_handle_t handle; - - dtbl_entry = (dtbl_entry_t*)value; - handle = dtbl_entry_get_handle(dtbl_entry); - const QString proto_name = dissector_handle_get_short_name(handle); - QTreeWidgetItem *ti = NULL; - - switch (selector_type) { - case FT_UINT8: - case FT_UINT16: - case FT_UINT24: - case FT_UINT32: - { - ti = new IntegerTableTreeWidgetItem(GPOINTER_TO_UINT(key), proto_name); - break; - } - - case FT_STRING: - case FT_STRINGZ: - case FT_UINT_STRING: - case FT_STRINGZPAD: - { - ti = new QTreeWidgetItem(string_type_); - ti->setText(col_table_name_, (const char *)key); - ti->setText(col_short_name_, proto_name); - break; - } - - case FT_BYTES: - { - const QString dissector_name = dissector_handle_get_dissector_name(handle); - ti = new QTreeWidgetItem(string_type_); - ti->setText(col_table_name_, dissector_name); - ti->setText(col_short_name_, proto_name); - break; - } - - default: - g_assert_not_reached(); - } - - if (ti) *pdl_ptr << ti; -} - -void DissectorTablesDialog::gatherHeurTableNames(const char *table_name, heur_dissector_list *list, gpointer dlg_ptr) -{ - DissectorTablesDialog *dt_dlg = qobject_cast((DissectorTablesDialog *)dlg_ptr); - if (!dt_dlg) return; - - QTreeWidgetItem *ti = new QTreeWidgetItem(heuristic_type_); - ti->setText(col_table_name_, table_name); - ti->setFirstColumnSpanned(true); - - dt_dlg->heuristic_dissectors_ << ti; - - if (list) { - QList heur_decode_list; - heur_dissector_table_foreach(table_name, gatherHeurProtocolDecodes, &heur_decode_list); - ti->addChildren(heur_decode_list); - } -} - -void DissectorTablesDialog::gatherHeurProtocolDecodes(const char *, struct heur_dtbl_entry *dtbl_entry, gpointer list_ptr) -{ - QList *hdl_ptr = dynamic_cast *>((QList *)list_ptr); - if (!hdl_ptr) return; - - if (dtbl_entry->protocol) { - QTreeWidgetItem *ti = new QTreeWidgetItem(heuristic_type_); - ti->setText(col_table_name_, proto_get_protocol_long_name(dtbl_entry->protocol)); - ti->setText(col_short_name_, proto_get_protocol_short_name(dtbl_entry->protocol)); - *hdl_ptr << ti; - } -} - -void DissectorTablesDialog::on_tableTreeWidget_itemSelectionChanged() -{ - int type = top_level_type_; - QStringList header_labels; - - if (ui->tableTreeWidget->currentItem()) { - type = ui->tableTreeWidget->currentItem()->type(); - } - - switch (type) { - case table_type_: - header_labels << tr("Table Name") << tr("Selector Name"); - break; - case string_type_: - header_labels << tr("String") << tr("Dissector"); - break; - case integer_type_: - header_labels << tr("Port") << tr("Dissector"); - break; - case custom_type_: - header_labels << tr("String") << tr("Dissector"); - break; - case heuristic_type_: - header_labels << tr("Protocol") << tr("Short Name"); - break; - case top_level_type_: - header_labels << tr("Table Type") << QString(); - break; - } - - ui->tableTreeWidget->setHeaderLabels(header_labels); + proxyModel_->setFilter(search_re); } /* diff --git a/ui/qt/dissector_tables_dialog.h b/ui/qt/dissector_tables_dialog.h index 3d3aadc881..ed73d91ddc 100644 --- a/ui/qt/dissector_tables_dialog.h +++ b/ui/qt/dissector_tables_dialog.h @@ -4,29 +4,14 @@ * 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. + * SPDX-License-Identifier: GPL-2.0+ */ #ifndef DISSECTOR_TABLES_DIALOG_H #define DISSECTOR_TABLES_DIALOG_H -#include - -#include - #include "geometry_state_dialog.h" +#include namespace Ui { class DissectorTablesDialog; @@ -43,19 +28,14 @@ public: ~DissectorTablesDialog(); private slots: - void on_tableTreeWidget_itemSelectionChanged(); + void on_search_line_edit__textChanged(const QString &search_re); + void fillTree(); private: Ui::DissectorTablesDialog *ui; - QList string_dissectors_; - QList integer_dissectors_; - QList custom_dissectors_; - QList heuristic_dissectors_; - static void gatherTableNames(const char *short_name, const char *table_name, gpointer dlg_ptr); - static void gatherProtocolDecodes(const char *, ftenum_t selector_type, gpointer key, gpointer value, gpointer list_ptr); - static void gatherHeurTableNames(const char *table_name, struct heur_dissector_list *list, gpointer dlg_ptr); - static void gatherHeurProtocolDecodes(const char *, struct heur_dtbl_entry *dtbl_entry, gpointer list_ptr); + DissectorTablesModel* dissector_tables_model_; + DissectorTablesProxyModel* proxyModel_; }; #endif // DISSECTOR_TABLES_DIALOG_H diff --git a/ui/qt/dissector_tables_dialog.ui b/ui/qt/dissector_tables_dialog.ui index 380c2e34d0..6e8a4bdc57 100644 --- a/ui/qt/dissector_tables_dialog.ui +++ b/ui/qt/dissector_tables_dialog.ui @@ -15,22 +15,26 @@ - + true - - - Table Name - - - - - Short Name - - + + + + + + Search: + + + + + + + + @@ -43,6 +47,13 @@ + + + DissectorTablesTreeView + QTreeView +
widgets/dissector_tables_view.h
+
+
diff --git a/ui/qt/models/dissector_tables_model.cpp b/ui/qt/models/dissector_tables_model.cpp new file mode 100644 index 0000000000..7986cc54d8 --- /dev/null +++ b/ui/qt/models/dissector_tables_model.cpp @@ -0,0 +1,497 @@ +/* dissector_tables_model.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#include +#include "wireshark_application.h" + +static const char* CUSTOM_TABLE_NAME = "Custom Tables"; +static const char* INTEGER_TABLE_NAME = "Integer Tables"; +static const char* STRING_TABLE_NAME = "String Tables"; +static const char* HEURISTIC_TABLE_NAME = "Heuristic Tables"; + +class DissectorTablesItem +{ +public: + DissectorTablesItem(QString tableName, QString shortName, DissectorTablesItem* parent); + virtual ~DissectorTablesItem(); + + QString tableName() const {return tableName_;} + QString shortName() const {return shortName_;} + + void appendChild(DissectorTablesItem* child); + DissectorTablesItem* child(int row) const; + int childCount() const; + int row() const; + + DissectorTablesItem* parentItem() const {return parent_; } + + virtual bool lessThan(DissectorTablesItem &right) const; + +protected: + QString tableName_; + QString shortName_; + DissectorTablesItem* parent_; + QList childItems_; +}; + +class IntegerTablesItem : public DissectorTablesItem +{ +public: + IntegerTablesItem(unsigned int value, QString shortName, DissectorTablesItem* parent); + virtual ~IntegerTablesItem(); + + virtual bool lessThan(DissectorTablesItem &right) const; + +protected: + unsigned int value_; +}; + + +DissectorTablesItem::DissectorTablesItem(QString tableName, QString shortName, DissectorTablesItem* parent) : + tableName_(tableName), + shortName_(shortName), + parent_(parent) +{ +} + +DissectorTablesItem::~DissectorTablesItem() +{ + for (int row = 0; row < childItems_.count(); row++) + { + delete VariantPointer::asPtr(childItems_.value(row)); + } + + childItems_.clear(); +} + +void DissectorTablesItem::appendChild(DissectorTablesItem* child) +{ + childItems_.prepend(VariantPointer::asQVariant(child)); +} + +DissectorTablesItem* DissectorTablesItem::child(int row) const +{ + return VariantPointer::asPtr(childItems_.value(row)); +} + +int DissectorTablesItem::childCount() const +{ + return childItems_.count(); +} + +int DissectorTablesItem::row() const +{ + if (parent_) + return parent_->childItems_.indexOf(VariantPointer::asQVariant((DissectorTablesItem*)this)); + + return 0; +} + +bool DissectorTablesItem::lessThan(DissectorTablesItem &right) const +{ + if (tableName().compare(right.tableName(), Qt::CaseInsensitive) < 0) + return true; + + return false; +} + + +IntegerTablesItem::IntegerTablesItem(unsigned int value, QString shortName, DissectorTablesItem* parent) + : DissectorTablesItem(QString("%1").arg(value), shortName, parent) + , value_(value) +{ +} + +IntegerTablesItem::~IntegerTablesItem() +{ +} + +bool IntegerTablesItem::lessThan(DissectorTablesItem &right) const +{ + if (value_ == ((IntegerTablesItem&)right).value_) { + return DissectorTablesItem::lessThan(right); + } + + if (value_ < ((IntegerTablesItem&)right).value_) { + return true; + } + + return false; +} + + + + + + + + +DissectorTablesModel::DissectorTablesModel(QObject *parent) : + QAbstractItemModel(parent), + root_(new DissectorTablesItem(QString("ROOT"), QString("ROOT"), NULL)) +{ +} + +DissectorTablesModel::~DissectorTablesModel() +{ + delete root_; +} + +int DissectorTablesModel::rowCount(const QModelIndex &parent) const +{ + DissectorTablesItem *parent_item; + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) + parent_item = root_; + else + parent_item = static_cast(parent.internalPointer()); + + if (parent_item == NULL) + return 0; + + return parent_item->childCount(); +} + +int DissectorTablesModel::columnCount(const QModelIndex&) const +{ + return colLast; +} + +QModelIndex DissectorTablesModel::parent(const QModelIndex& index) const +{ + if (!index.isValid()) + return QModelIndex(); + + DissectorTablesItem* item = static_cast(index.internalPointer()); + if (item != NULL) { + DissectorTablesItem* parent_item = item->parentItem(); + if (parent_item != NULL) { + if (parent_item == root_) + return QModelIndex(); + + return createIndex(parent_item->row(), 0, parent_item); + } + } + + return QModelIndex(); +} + +QModelIndex DissectorTablesModel::index(int row, int column, const QModelIndex& parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + DissectorTablesItem *parent_item, *child_item; + + if (!parent.isValid()) + parent_item = root_; + else + parent_item = static_cast(parent.internalPointer()); + + Q_ASSERT(parent_item); + + child_item = parent_item->child(row); + if (child_item) { + return createIndex(row, column, child_item); + } + + return QModelIndex(); +} + +QVariant DissectorTablesModel::data(const QModelIndex &index, int role) const +{ + if ((!index.isValid()) || (role != Qt::DisplayRole)) + return QVariant(); + + DissectorTablesItem* item = static_cast(index.internalPointer()); + if (item == NULL) + return QVariant(); + + switch ((enum DissectorTablesColumn)index.column()) + { + case colTableName: + return item->tableName(); + case colShortName: + return item->shortName(); + default: + break; + } + + return QVariant(); +} + +static void gatherProtocolDecodes(const char *, ftenum_t selector_type, gpointer key, gpointer value, gpointer item_ptr) +{ + DissectorTablesItem* pdl_ptr = (DissectorTablesItem*)item_ptr; + if (pdl_ptr == NULL) + return; + + dtbl_entry_t *dtbl_entry = (dtbl_entry_t*)value; + dissector_handle_t handle = dtbl_entry_get_handle(dtbl_entry); + const QString proto_name = dissector_handle_get_short_name(handle); + DissectorTablesItem *ti = NULL; + + switch (selector_type) { + case FT_UINT8: + case FT_UINT16: + case FT_UINT24: + case FT_UINT32: + ti = new IntegerTablesItem(GPOINTER_TO_UINT(key), proto_name, pdl_ptr); + pdl_ptr->appendChild(ti); + break; + + case FT_STRING: + case FT_STRINGZ: + case FT_UINT_STRING: + case FT_STRINGZPAD: + ti = new DissectorTablesItem((const char *)key, proto_name, pdl_ptr); + pdl_ptr->appendChild(ti); + break; + + case FT_BYTES: + ti = new DissectorTablesItem(dissector_handle_get_dissector_name(handle), proto_name, pdl_ptr); + pdl_ptr->appendChild(ti); + break; + + default: + break; + } +} + +struct tables_root +{ + DissectorTablesItem* custom_table; + DissectorTablesItem* integer_table; + DissectorTablesItem* string_table; +}; + +static void gatherTableNames(const char *short_name, const char *table_name, gpointer model_ptr) +{ + struct tables_root* tables = (struct tables_root*)model_ptr; + if (model_ptr == NULL) + return; + + ftenum_t selector_type = get_dissector_table_selector_type(short_name); + DissectorTablesItem *dt_ti = NULL; + + switch (selector_type) { + case FT_UINT8: + case FT_UINT16: + case FT_UINT24: + case FT_UINT32: + dt_ti = new DissectorTablesItem(table_name, short_name, tables->integer_table); + tables->integer_table->appendChild(dt_ti); + break; + case FT_STRING: + case FT_STRINGZ: + case FT_UINT_STRING: + case FT_STRINGZPAD: + dt_ti = new DissectorTablesItem(table_name, short_name, tables->string_table); + tables->string_table->appendChild(dt_ti); + break; + case FT_BYTES: + dt_ti = new DissectorTablesItem(table_name, short_name, tables->custom_table); + tables->custom_table->appendChild(dt_ti); + break; + default: + // Assert? + return; + } + + dissector_table_foreach(short_name, gatherProtocolDecodes, dt_ti); +} + +static void gatherHeurProtocolDecodes(const char *, struct heur_dtbl_entry *dtbl_entry, gpointer list_ptr) +{ + DissectorTablesItem* hdl_ptr = (DissectorTablesItem*)list_ptr; + if (hdl_ptr == NULL) + return; + + if (dtbl_entry->protocol) { + DissectorTablesItem *heur = new DissectorTablesItem(proto_get_protocol_long_name(dtbl_entry->protocol), proto_get_protocol_short_name(dtbl_entry->protocol), hdl_ptr); + hdl_ptr->appendChild(heur); + } +} + +static void gatherHeurTableNames(const char *table_name, heur_dissector_list *list, gpointer heur_tables) +{ + DissectorTablesItem* table = (DissectorTablesItem*)heur_tables; + if (table == NULL) + return; + + DissectorTablesItem *heur = new DissectorTablesItem(table_name, QString(""), table); + table->appendChild(heur); + + if (list) { + heur_dissector_table_foreach(table_name, gatherHeurProtocolDecodes, heur); + } +} + +void DissectorTablesModel::populate() +{ + emit beginResetModel(); + + struct tables_root tables; + + tables.custom_table = new DissectorTablesItem(tr(CUSTOM_TABLE_NAME), QString(""), root_); + root_->appendChild(tables.custom_table); + tables.integer_table = new DissectorTablesItem(tr(INTEGER_TABLE_NAME), QString(""), root_); + root_->appendChild(tables.integer_table); + tables.string_table = new DissectorTablesItem(tr(STRING_TABLE_NAME), QString(""), root_); + root_->appendChild(tables.string_table); + + dissector_all_tables_foreach_table(gatherTableNames, &tables, NULL); + + DissectorTablesItem* heuristic_table = new DissectorTablesItem(tr(HEURISTIC_TABLE_NAME), QString(""), root_); + root_->appendChild(heuristic_table); + + dissector_all_heur_tables_foreach_table(gatherHeurTableNames, heuristic_table, NULL); + + emit endResetModel(); +} + + + + + +DissectorTablesProxyModel::DissectorTablesProxyModel(QObject * parent) +: QSortFilterProxyModel(parent), +tableName_(tr("Table Type")), +shortName_(), +filter_() +{ +} + +QVariant DissectorTablesProxyModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + + switch ((enum DissectorTablesModel::DissectorTablesColumn)section) { + case DissectorTablesModel::colTableName: + return tableName_; + case DissectorTablesModel::colShortName: + return shortName_; + default: + break; + } + } + return QVariant(); +} + +bool DissectorTablesProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + //Use DissectorTablesItem directly for better performance + DissectorTablesItem* left_item = static_cast(left.internalPointer()); + DissectorTablesItem* right_item = static_cast(right.internalPointer()); + + if ((left_item != NULL) && (right_item != NULL)) { + return left_item->lessThan(*right_item); + } + + return false; +} + +bool DissectorTablesProxyModel::filterAcceptItem(DissectorTablesItem& item) const +{ + QRegExp regex(filter_, Qt::CaseInsensitive); + + if (item.tableName().contains(regex)) + return true; + + if (item.shortName().contains(regex)) + return true; + + DissectorTablesItem *child_item; + for (int child_row = 0; child_row < item.childCount(); child_row++) + { + child_item = item.child(child_row); + if ((child_item != NULL) && (filterAcceptItem(*child_item))) + return true; + } + + return false; +} + +bool DissectorTablesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + QModelIndex nameIdx = sourceModel()->index(sourceRow, DissectorTablesModel::colTableName, sourceParent); + DissectorTablesItem* item = static_cast(nameIdx.internalPointer()); + if (item == NULL) + return true; + + if (!filter_.isEmpty()) { + if (filterAcceptItem(*item)) + return true; + } + + return true; +} + +void DissectorTablesProxyModel::setFilter(const QString& filter) +{ + filter_ = filter; + invalidateFilter(); +} + +void DissectorTablesProxyModel::adjustHeader(const QModelIndex ¤tIndex) +{ + tableName_ = tr("Table Type"); + shortName_ = QString(); + if (currentIndex.isValid() && currentIndex.parent().isValid()) { + QString table; + + if (currentIndex.parent().parent().isValid()) { + table = data(index(currentIndex.parent().parent().row(), DissectorTablesModel::colTableName), Qt::DisplayRole).toString(); + if ((table.compare(CUSTOM_TABLE_NAME) == 0) || + (table.compare(STRING_TABLE_NAME) == 0)) { + tableName_ = tr("String"); + shortName_ = tr("Dissector"); + } else if (table.compare(INTEGER_TABLE_NAME) == 0) { + tableName_ = tr("Integer"); + shortName_ = tr("Dissector"); + } else if (table.compare(HEURISTIC_TABLE_NAME) == 0) { + tableName_ = tr("Protocol"); + shortName_ = tr("Short Name"); + } + } else { + table = data(index(currentIndex.parent().row(), DissectorTablesModel::colTableName), Qt::DisplayRole).toString(); + if ((table.compare(CUSTOM_TABLE_NAME) == 0) || + (table.compare(INTEGER_TABLE_NAME) == 0) || + (table.compare(STRING_TABLE_NAME) == 0)) { + tableName_ = tr("Table Name"); + shortName_ = tr("Selector Name"); + } else if (table.compare(HEURISTIC_TABLE_NAME) == 0) { + tableName_ = tr("Protocol"); + shortName_ = tr("Short Name"); + } + } + } + + + emit headerDataChanged(Qt::Vertical, 0, 1); +} + +/* + * 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/models/dissector_tables_model.h b/ui/qt/models/dissector_tables_model.h new file mode 100644 index 0000000000..550285025e --- /dev/null +++ b/ui/qt/models/dissector_tables_model.h @@ -0,0 +1,87 @@ +/* dissector_tables_model.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef DISSECTOR_TABLES_MODEL_H +#define DISSECTOR_TABLES_MODEL_H + +#include + +#include +#include + +class DissectorTablesItem; + +class DissectorTablesModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit DissectorTablesModel(QObject * parent = Q_NULLPTR); + virtual ~DissectorTablesModel(); + + enum DissectorTablesColumn { + colTableName = 0, + colShortName, + colLast + }; + + QModelIndex index(int row, int column, + const QModelIndex & = QModelIndex()) const; + QModelIndex parent(const QModelIndex &) const; + QVariant data(const QModelIndex &index, int role) const; + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + void populate(); + +private: + DissectorTablesItem* root_; +}; + +class DissectorTablesProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + + explicit DissectorTablesProxyModel(QObject * parent = Q_NULLPTR); + + virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + + void adjustHeader(const QModelIndex ¤tIndex); + void setFilter(const QString& filter); + +protected: + bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; + bool filterAcceptItem(DissectorTablesItem& item) const; + +private: + + QString tableName_; + QString shortName_; + QString filter_; +}; + +#endif // DISSECTOR_TABLES_MODEL_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/widgets/dissector_tables_view.cpp b/ui/qt/widgets/dissector_tables_view.cpp new file mode 100644 index 0000000000..c3b383b0f0 --- /dev/null +++ b/ui/qt/widgets/dissector_tables_view.cpp @@ -0,0 +1,38 @@ +/* dissector_tables_view.cpp + * Tree view of Dissector Table data. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "dissector_tables_view.h" +#include + +DissectorTablesTreeView::DissectorTablesTreeView(QWidget *parent) : QTreeView(parent) +{ +} + +void DissectorTablesTreeView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + if (current.isValid()) + { + ((DissectorTablesProxyModel*)model())->adjustHeader(current); + } + + QTreeView::currentChanged(current, previous); +} + +/* * 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/widgets/dissector_tables_view.h b/ui/qt/widgets/dissector_tables_view.h new file mode 100644 index 0000000000..446268a0c2 --- /dev/null +++ b/ui/qt/widgets/dissector_tables_view.h @@ -0,0 +1,39 @@ +/* dissector_tables_view.h + * Tree view of Dissector Table data. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef DISSECTOR_TABLES_VIEW_H +#define DISSECTOR_TABLES_VIEW_H + +#include +#include + +class DissectorTablesTreeView : public QTreeView +{ + Q_OBJECT +public: + DissectorTablesTreeView(QWidget *parent = 0); + +protected slots: + void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); +}; +#endif // DISSECTOR_TABLES_VIEW_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: + */