forked from osmocom/wireshark
Convert Dissector Tables dialog to use model
Now with searchability! Change-Id: I6ab4e89d4080d3599d522807d39de80cc46e7360 Reviewed-on: https://code.wireshark.org/review/24898 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot Reviewed-by: Roland Knall <rknall@gmail.com> Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
parent
c781cc38fd
commit
8521dbbe67
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -4,277 +4,60 @@
|
|||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "dissector_tables_dialog.h"
|
||||
#include <ui_dissector_tables_dialog.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <epan/packet.h>
|
||||
|
||||
#include <QTreeWidgetItem>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#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<const IntegerTableTreeWidgetItem *>(&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 *>((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<QTreeWidgetItem *> 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<QTreeWidgetItem *> *pdl_ptr = dynamic_cast<QList<QTreeWidgetItem *> *>((QList<QTreeWidgetItem *> *)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 *>((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<QTreeWidgetItem *> 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<QTreeWidgetItem *> *hdl_ptr = dynamic_cast<QList<QTreeWidgetItem *> *>((QList<QTreeWidgetItem *> *)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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -4,29 +4,14 @@
|
|||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef DISSECTOR_TABLES_DIALOG_H
|
||||
#define DISSECTOR_TABLES_DIALOG_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <epan/ftypes/ftypes.h>
|
||||
|
||||
#include "geometry_state_dialog.h"
|
||||
#include <ui/qt/models/dissector_tables_model.h>
|
||||
|
||||
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<QTreeWidgetItem *> string_dissectors_;
|
||||
QList<QTreeWidgetItem *> integer_dissectors_;
|
||||
QList<QTreeWidgetItem *> custom_dissectors_;
|
||||
QList<QTreeWidgetItem *> 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
|
||||
|
|
|
@ -15,22 +15,26 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="tableTreeWidget">
|
||||
<widget class="DissectorTablesTreeView" name="tableTree">
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Table Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Short Name</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Search:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="search_line_edit_"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
|
@ -43,6 +47,13 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>DissectorTablesTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>widgets/dissector_tables_view.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
|
|
|
@ -0,0 +1,497 @@
|
|||
/* dissector_tables_model.cpp
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <ui/qt/models/dissector_tables_model.h>
|
||||
#include <epan/ftypes/ftypes.h>
|
||||
#include <epan/packet.h>
|
||||
|
||||
#include <ui/qt/utils/variant_pointer.h>
|
||||
#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<QVariant> 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<DissectorTablesItem>::asPtr(childItems_.value(row));
|
||||
}
|
||||
|
||||
childItems_.clear();
|
||||
}
|
||||
|
||||
void DissectorTablesItem::appendChild(DissectorTablesItem* child)
|
||||
{
|
||||
childItems_.prepend(VariantPointer<DissectorTablesItem>::asQVariant(child));
|
||||
}
|
||||
|
||||
DissectorTablesItem* DissectorTablesItem::child(int row) const
|
||||
{
|
||||
return VariantPointer<DissectorTablesItem>::asPtr(childItems_.value(row));
|
||||
}
|
||||
|
||||
int DissectorTablesItem::childCount() const
|
||||
{
|
||||
return childItems_.count();
|
||||
}
|
||||
|
||||
int DissectorTablesItem::row() const
|
||||
{
|
||||
if (parent_)
|
||||
return parent_->childItems_.indexOf(VariantPointer<DissectorTablesItem>::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<DissectorTablesItem*>(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<DissectorTablesItem*>(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<DissectorTablesItem*>(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<DissectorTablesItem*>(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<DissectorTablesItem*>(left.internalPointer());
|
||||
DissectorTablesItem* right_item = static_cast<DissectorTablesItem*>(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<DissectorTablesItem*>(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:
|
||||
*/
|
|
@ -0,0 +1,87 @@
|
|||
/* dissector_tables_model.h
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef DISSECTOR_TABLES_MODEL_H
|
||||
#define DISSECTOR_TABLES_MODEL_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
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:
|
||||
*/
|
|
@ -0,0 +1,38 @@
|
|||
/* dissector_tables_view.cpp
|
||||
* Tree view of Dissector Table data.
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include "dissector_tables_view.h"
|
||||
#include <ui/qt/models/dissector_tables_model.h>
|
||||
|
||||
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:
|
||||
*/
|
|
@ -0,0 +1,39 @@
|
|||
/* dissector_tables_view.h
|
||||
* Tree view of Dissector Table data.
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef DISSECTOR_TABLES_VIEW_H
|
||||
#define DISSECTOR_TABLES_VIEW_H
|
||||
|
||||
#include <config.h>
|
||||
#include <QTreeView>
|
||||
|
||||
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:
|
||||
*/
|
Loading…
Reference in New Issue