aboutsummaryrefslogtreecommitdiffstats
path: root/ui/qt/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'ui/qt/widgets')
-rw-r--r--ui/qt/widgets/traffic_tab.cpp240
-rw-r--r--ui/qt/widgets/traffic_tab.h21
-rw-r--r--ui/qt/widgets/traffic_tree.cpp3
-rw-r--r--ui/qt/widgets/traffic_types_list.cpp236
-rw-r--r--ui/qt/widgets/traffic_types_list.h100
5 files changed, 448 insertions, 152 deletions
diff --git a/ui/qt/widgets/traffic_tab.cpp b/ui/qt/widgets/traffic_tab.cpp
index 8cfaeb5316..d517e46529 100644
--- a/ui/qt/widgets/traffic_tab.cpp
+++ b/ui/qt/widgets/traffic_tab.cpp
@@ -16,8 +16,6 @@
#include <wsutil/utf8_entities.h>
#include <wsutil/filesystem.h>
-#include "ui/recent.h"
-
#include <ui/qt/main_application.h>
#include <ui/qt/filter_action.h>
#include <ui/qt/models/atap_data_model.h>
@@ -26,7 +24,6 @@
#include <ui/qt/widgets/traffic_tree.h>
#include <ui/qt/widgets/detachable_tabwidget.h>
-#include <QVector>
#include <QStringList>
#include <QTreeView>
#include <QList>
@@ -175,103 +172,26 @@ bool TrafficDataFilterProxy::lessThan(const QModelIndex &source_left, const QMod
}
-static gboolean iterateProtocols(const void *key, void *value, void *userdata)
-{
- QMap<int, QString> *protocols = (QMap<int, QString> *)userdata;
- register_ct_t* ct = (register_ct_t*)value;
- const QString title = (const gchar*)key;
- int proto_id = get_conversation_proto_id(ct);
- protocols->insert(proto_id, title);
-
- return FALSE;
-}
-
TrafficTab::TrafficTab(QWidget * parent) :
DetachableTabWidget(parent)
{
_createModel = nullptr;
_disableTaps = false;
_nameResolution = false;
- _recentList = nullptr;
setTabBasename(QString());
-
}
TrafficTab::~TrafficTab()
-{
- prefs_clear_string_list(*_recentList);
- *_recentList = NULL;
- _protocolButtons.clear();
-
- foreach (int protoId, _tabs.keys())
- {
- char *title = g_strdup(proto_get_protocol_short_name(find_protocol_by_id(protoId)));
- *_recentList = g_list_append(*_recentList, title);
- }
-}
+{}
-void TrafficTab::setProtocolInfo(QString tableName, GList ** recentList, ATapModelCallback createModel)
+void TrafficTab::setProtocolInfo(QString tableName, QList<int> allProtocols, QList<int> openTabs, ATapModelCallback createModel)
{
setTabBasename(tableName);
- _recentList = recentList;
+ _allProtocols = allProtocols;
if (createModel)
_createModel = createModel;
- for (GList * endTab = *_recentList; endTab; endTab = endTab->next) {
- int protoId = proto_get_id_by_short_name((const char *)endTab->data);
- if (protoId > -1 && ! _protocols.contains(protoId))
- _protocols.append(protoId);
- }
-
- if (_protocols.isEmpty()) {
- QStringList protoNames = QStringList() << "eth" << "ip" << "ipv6" << "tcp" << "udp";
- foreach(QString name, protoNames)
- _protocols << proto_get_id_by_filter_name(name.toStdString().c_str());
- }
-
- QWidget * container = new QWidget(this);
- container->setFixedHeight(tabBar()->height());
- container->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
-
- QHBoxLayout * layout = new QHBoxLayout(container);
- layout->setContentsMargins(1, 0, 1, 0);
-
- QPushButton * cornerButton = new QPushButton(tr("%1 Types").arg(tableName));
- cornerButton->setFixedHeight(tabBar()->height());
- cornerButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
- QMenu * cornerMenu = new QMenu();
- conversation_table_iterate_tables(iterateProtocols, &_allTaps);
- foreach (int protoId, _allTaps.keys())
- {
- QAction * endPoint = new QAction(_allTaps[protoId], this);
- endPoint->setProperty("protocol", QVariant::fromValue(protoId));
- endPoint->setCheckable(true);
- endPoint->setChecked(_protocols.contains(protoId));
- connect(endPoint, &QAction::triggered, this, &TrafficTab::toggleTab);
- _protocolButtons.insert(protoId, endPoint);
- cornerMenu->addAction(endPoint);
- }
- cornerButton->setMenu(cornerMenu);
-
- layout->addWidget(cornerButton);
- setCornerWidget(container, Qt::TopRightCorner);
-
- updateTabs();
-}
-
-void TrafficTab::toggleTab(bool checked)
-{
- QAction * orig = qobject_cast<QAction *>(sender());
- if (!orig || ! orig->property("protocol").isValid())
- return;
-
- int protocol = orig->property("protocol").toInt();
- if (!checked && _protocols.contains(protocol))
- _protocols.removeAll(protocol);
- else if (checked && ! _protocols.contains(protocol))
- _protocols.append(protocol);
-
- updateTabs();
+ setOpenTabs(openTabs);
}
void TrafficTab::setDelegate(int column, ATapCreateDelegate createDelegate)
@@ -376,61 +296,79 @@ void TrafficTab::disableTap()
emit disablingTaps();
}
-void TrafficTab::updateTabs()
+void TrafficTab::setOpenTabs(QList<int> protocols)
{
- QList<int> keys = _tabs.keys();
- QList<int> allProtocols = _allTaps.keys();
-
- /* Adding new Tabs, and keeping the same order they are in the drop-down menu */
- foreach (int proto, _protocols) {
- if (!keys.contains(proto)) {
-
- int insertIndex = -1;
- auto bIdx = allProtocols.indexOf(proto);
- int idx = 0;
- while (insertIndex < 0 && idx < keys.count())
- {
- auto aIdx = allProtocols.indexOf(keys[idx]);
- if (aIdx < 0) /* Key not in all protocols. This would be a fluke */
- break;
- if (aIdx > bIdx) /* Should never be equal, as proto is not yet in keys */
- insertIndex = _tabs[keys[idx]];
- idx++;
- }
+ QList<int> tabs = _tabs.keys();
+ QList<int> remove;
+ blockSignals(true);
- QTreeView * tree = createTree(proto);
- QString tableName = proto_get_protocol_short_name(find_protocol_by_id(proto));
- TabData tabData(tableName, proto);
- QVariant storage;
- storage.setValue(tabData);
- if (tree->model()->rowCount() > 0)
- tableName += QString(" %1 %2").arg(UTF8_MIDDLE_DOT).arg(tree->model()->rowCount());
-
- int tabId = insertTab(insertIndex, tree, tableName);
- _protocolButtons[proto]->setChecked(true);
- tabBar()->setTabData(tabId, storage);
+ foreach(int protocol, protocols)
+ {
+ if (! tabs.contains(protocol)) {
+ insertProtoTab(protocol, false);
}
+ tabs.removeAll(protocol);
}
- /* Removing tabs no longer required. First filter the key array, for all tabs which
- * are still being displayed */
- foreach(int key, keys)
+ foreach(int protocol, tabs)
+ removeProtoTab(protocol, false);
+
+ blockSignals(false);
+
+ emit tabsChanged(_tabs.keys());
+ emit retapRequired();
+}
+
+void TrafficTab::insertProtoTab(int protoId, bool emitSignals)
+{
+ QList<int> lUsed = _tabs.keys();
+
+ if (lUsed.contains(protoId) && lUsed.count() != count())
{
- if ( _protocols.contains(key)) {
- _protocolButtons[key]->setChecked(true);
- keys.removeAll(key);
+ _tabs.clear();
+ for (int idx = 0; idx < count(); idx++) {
+ TabData tabData = qvariant_cast<TabData>(tabBar()->tabData(idx));
+ _tabs.insert(tabData.protoId(), idx);
}
+ lUsed = _tabs.keys();
}
- /* Removal step 2, now actually remove all elements. Counting down, otherwise removing
- * a tab will shift the indeces */
- for(int idx = count(); idx > 0; idx--) {
- TabData tabData = qvariant_cast<TabData>(tabBar()->tabData(idx - 1));
- if (keys.contains(tabData.protoId())) {
- removeTab(idx - 1);
- _protocolButtons[tabData.protoId()]->setChecked(false);
+
+ if (protoId <= 0 || lUsed.contains(protoId))
+ return;
+
+ QList<int> lFull = _allProtocols;
+ int idx = lFull.indexOf(protoId);
+ if (idx < 0)
+ return;
+
+ QList<int> part = lFull.mid(0, idx);
+ int insertAt = 0;
+ if (part.count() > 0) {
+ for (int cnt = idx - 1; cnt >= 0; cnt--) {
+ if (lUsed.contains(part[cnt]) && part[cnt] != protoId) {
+ insertAt = lUsed.indexOf(part[cnt]) + 1;
+ break;
+ }
}
}
+ QTreeView * tree = createTree(protoId);
+ QString tableName = proto_get_protocol_short_name(find_protocol_by_id(protoId));
+ TabData tabData(tableName, protoId);
+ QVariant storage;
+ storage.setValue(tabData);
+ if (tree->model()->rowCount() > 0)
+ tableName += QString(" %1 %2").arg(UTF8_MIDDLE_DOT).arg(tree->model()->rowCount());
+
+ int tabId = -1;
+ if (insertAt > -1)
+ tabId = insertTab(insertAt, tree, tableName);
+ else
+ tabId = addTab(tree, tableName);
+ if (tabId >= 0)
+ tabBar()->setTabData(tabId, storage);
+
+
/* We reset the correct tab idxs. That operations is costly, but it is only
* called during this operation and ensures, that other operations do not
* need to iterate, but rather can lookup the indeces. */
@@ -440,7 +378,37 @@ void TrafficTab::updateTabs()
_tabs.insert(tabData.protoId(), idx);
}
- emit retapRequired();
+ if (emitSignals) {
+ emit tabsChanged(_tabs.keys());
+ emit retapRequired();
+ }
+}
+
+void TrafficTab::removeProtoTab(int protoId, bool emitSignals)
+{
+ if (_tabs.keys().contains(protoId)) {
+ for(int idx = 0; idx < count(); idx++) {
+ TabData tabData = qvariant_cast<TabData>(tabBar()->tabData(idx));
+ if (protoId == tabData.protoId()) {
+ removeTab(idx);
+ break;
+ }
+ }
+ }
+
+ /* We reset the correct tab idxs. That operations is costly, but it is only
+ * called during this operation and ensures, that other operations do not
+ * need to iterate, but rather can lookup the indeces. */
+ _tabs.clear();
+ for (int idx = 0; idx < count(); idx++) {
+ TabData tabData = qvariant_cast<TabData>(tabBar()->tabData(idx));
+ _tabs.insert(tabData.protoId(), idx);
+ }
+
+ if (emitSignals) {
+ emit tabsChanged(_tabs.keys());
+ emit retapRequired();
+ }
}
void TrafficTab::doCurrentIndexChange(const QModelIndex & cur, const QModelIndex &)
@@ -484,7 +452,7 @@ void TrafficTab::modelReset()
return;
TrafficDataFilterProxy * qsfpm = qobject_cast<TrafficDataFilterProxy *>(sender());
- if (! qobject_cast<ATapDataModel *>(qsfpm->sourceModel()))
+ if (!qsfpm || ! qobject_cast<ATapDataModel *>(qsfpm->sourceModel()))
return;
ATapDataModel * atdm = qobject_cast<ATapDataModel *>(qsfpm->sourceModel());
@@ -519,7 +487,7 @@ ATapDataModel * TrafficTab::modelForWidget(QWidget * searchWidget)
QTreeView * tree = qobject_cast<QTreeView *>(searchWidget);
if (qobject_cast<TrafficDataFilterProxy *>(tree->model())) {
TrafficDataFilterProxy * qsfpm = qobject_cast<TrafficDataFilterProxy *>(tree->model());
- if (qobject_cast<ATapDataModel *>(qsfpm->sourceModel())) {
+ if (qsfpm && qobject_cast<ATapDataModel *>(qsfpm->sourceModel())) {
return qobject_cast<ATapDataModel *>(qsfpm->sourceModel());
}
}
@@ -736,9 +704,6 @@ void TrafficTab::detachTab(int tabIdx, QPoint pos) {
if (!model)
return;
- int protocol = model->protoId();
- _protocols.removeAll(protocol);
-
TrafficTree * tree = qobject_cast<TrafficTree *>(widget(tabIdx));
if (!tree)
return;
@@ -746,7 +711,7 @@ void TrafficTab::detachTab(int tabIdx, QPoint pos) {
connect(this, &TrafficTab::disablingTaps ,tree , &TrafficTree::disableTap);
DetachableTabWidget::detachTab(tabIdx, pos);
- updateTabs();
+ removeProtoTab(model->protoId());
}
void TrafficTab::attachTab(QWidget * content, QString name)
@@ -757,8 +722,5 @@ void TrafficTab::attachTab(QWidget * content, QString name)
return;
}
- int protocol = model->protoId();
- _protocols.append(protocol);
-
- updateTabs();
+ insertProtoTab(model->protoId());
}
diff --git a/ui/qt/widgets/traffic_tab.h b/ui/qt/widgets/traffic_tab.h
index 6a47984fec..c58a7ed592 100644
--- a/ui/qt/widgets/traffic_tab.h
+++ b/ui/qt/widgets/traffic_tab.h
@@ -12,8 +12,6 @@
#include "config.h"
-#include <ui/recent.h>
-
#include <ui/qt/models/atap_data_model.h>
#include <ui/qt/filter_action.h>
#include <ui/qt/widgets/detachable_tabwidget.h>
@@ -99,12 +97,13 @@ public:
* without having to removing the predefined object during setup of the UI.
*
* @param tableName The name for the table. Used for the protocol selection button
- * @param recentList The list to store the selected protocols in
+ * @param allProtocols a list of all possible protocols. It's order will set the tab oder
+ * @param openTabs a list of protocol ids to open at start of dialog
* @param createModel A callback, which will create the correct model for the trees
*
* @see ATapModelCallback
*/
- void setProtocolInfo(QString tableName, GList ** recentList, ATapModelCallback createModel);
+ void setProtocolInfo(QString tableName, QList<int> allProtocols, QList<int> openTabs, ATapModelCallback createModel);
/**
* @brief Set the Delegate object for a specific column
@@ -212,11 +211,14 @@ public slots:
*/
void useAbsoluteTime(bool absolute);
+ void setOpenTabs(QList<int> protocols);
+
signals:
void filterAction(QString filter, FilterAction::Action action, FilterAction::ActionType type);
void tabDataChanged(int idx);
void retapRequired();
void disablingTaps();
+ void tabsChanged(QList<int> protocols);
protected slots:
@@ -224,29 +226,26 @@ protected slots:
virtual void attachTab(QWidget * content, QString name) override;
private:
- QVector<int> _protocols;
- QMap<int, QString> _allTaps;
- QMap<int, QAction *> _protocolButtons;
+ QList<int> _allProtocols;
QMap<int, int> _tabs;
- GList ** _recentList;
ATapModelCallback _createModel;
QMap<int, ATapCreateDelegate> _createDelegates;
bool _disableTaps;
bool _nameResolution;
- void updateTabs();
QTreeView * createTree(int protoId);
ATapDataModel * modelForTabIndex(int tabIdx = -1);
ATapDataModel * modelForWidget(QWidget * widget);
+ void insertProtoTab(int protoId, bool emitSignals = true);
+ void removeProtoTab(int protoId, bool emitSignals = true);
+
#ifdef HAVE_MAXMINDDB
bool writeGeoIPMapFile(QFile * fp, bool json_only, ATapDataModel * dataModel);
#endif
private slots:
- void toggleTab(bool checked = false);
-
void modelReset();
void doCurrentIndexChange(const QModelIndex & cur, const QModelIndex & prev);
diff --git a/ui/qt/widgets/traffic_tree.cpp b/ui/qt/widgets/traffic_tree.cpp
index 31a1ab2bc6..3e370da83c 100644
--- a/ui/qt/widgets/traffic_tree.cpp
+++ b/ui/qt/widgets/traffic_tree.cpp
@@ -27,7 +27,6 @@
#include <ui/qt/utils/variant_pointer.h>
#include <ui/qt/widgets/traffic_tree.h>
-#include <QVector>
#include <QStringList>
#include <QTreeView>
#include <QList>
@@ -53,7 +52,7 @@ TrafficTree::TrafficTree(QString baseName, QWidget *parent) :
setRootIsDecorated(false);
setSortingEnabled(true);
setContextMenuPolicy(Qt::CustomContextMenu);
-
+
connect(this, &QTreeView::customContextMenuRequested, this, &TrafficTree::customContextMenu);
}
diff --git a/ui/qt/widgets/traffic_types_list.cpp b/ui/qt/widgets/traffic_types_list.cpp
new file mode 100644
index 0000000000..031f8c0295
--- /dev/null
+++ b/ui/qt/widgets/traffic_types_list.cpp
@@ -0,0 +1,236 @@
+/** @file
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include <epan/conversation_table.h>
+
+#include <ui/qt/widgets/traffic_types_list.h>
+
+#include <QStringList>
+
+TrafficTypesRowData::TrafficTypesRowData(int protocol, QString name) :
+ _protocol(protocol),
+ _name(name),
+ _checked(false)
+{}
+
+int TrafficTypesRowData::protocol() const
+{
+ return _protocol;
+}
+
+QString TrafficTypesRowData::name() const
+{
+ return _name;
+}
+
+bool TrafficTypesRowData::checked() const
+{
+ return _checked;
+}
+
+void TrafficTypesRowData::setChecked(bool checked)
+{
+ _checked = checked;
+}
+
+static gboolean iterateProtocols(const void *key, void *value, void *userdata)
+{
+ QList<TrafficTypesRowData> * protocols = (QList<TrafficTypesRowData> *)userdata;
+
+ register_ct_t* ct = (register_ct_t*)value;
+ const QString title = (const gchar*)key;
+ int proto_id = get_conversation_proto_id(ct);
+ TrafficTypesRowData entry(proto_id, title);
+ protocols->append(entry);
+
+ return FALSE;
+}
+
+TrafficTypesModel::TrafficTypesModel(GList ** recentList, QObject *parent) :
+ QAbstractListModel(parent),
+ _recentList(recentList)
+{
+ conversation_table_iterate_tables(iterateProtocols, &_allTaps);
+
+ QList<int> _protocols;
+
+ for (GList * endTab = *_recentList; endTab; endTab = endTab->next) {
+ int protoId = proto_get_id_by_short_name((const char *)endTab->data);
+ if (protoId > -1 && ! _protocols.contains(protoId))
+ _protocols.append(protoId);
+ }
+
+ if (_protocols.isEmpty()) {
+ QStringList protoNames = QStringList() << "eth" << "ip" << "ipv6" << "tcp" << "udp";
+ foreach(QString name, protoNames)
+ _protocols << proto_get_id_by_filter_name(name.toStdString().c_str());
+ }
+
+ for(int cnt = 0; cnt < _allTaps.count(); cnt++)
+ {
+ _allTaps[cnt].setChecked(false);
+ if (_protocols.contains(_allTaps[cnt].protocol()))
+ _allTaps[cnt].setChecked(true);
+ }
+
+}
+
+int TrafficTypesModel::rowCount(const QModelIndex &) const
+{
+ return _allTaps.count();
+}
+
+int TrafficTypesModel::columnCount(const QModelIndex &) const
+{
+ return TrafficTypesModel::COL_NUM;
+}
+
+QVariant TrafficTypesModel::data(const QModelIndex &idx, int role) const
+{
+ if (!idx.isValid())
+ return QVariant();
+
+ TrafficTypesRowData data = _allTaps[idx.row()];
+ if (role == Qt::DisplayRole)
+ {
+ switch(idx.column())
+ {
+ case(TrafficTypesModel::COL_NAME):
+ return data.name();
+ case(TrafficTypesModel::COL_PROTOCOL):
+ return data.protocol();
+ }
+ } else if (role == Qt::CheckStateRole && idx.column() == TrafficTypesModel::COL_CHECKED) {
+ return data.checked() ? Qt::Checked : Qt::Unchecked;
+ } else if (role == TrafficTypesModel::TRAFFIC_PROTOCOL) {
+ return data.protocol();
+ } else if (role == TrafficTypesModel::TRAFFIC_IS_CHECKED) {
+ return (bool)data.checked();
+ }
+
+ return QVariant();
+}
+
+QVariant TrafficTypesModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (section < 0 || role != Qt::DisplayRole || orientation != Qt::Horizontal)
+ return QVariant();
+
+ if (section == TrafficTypesModel::COL_NAME)
+ return tr("Protocol");
+ return QVariant();
+}
+
+Qt::ItemFlags TrafficTypesModel::flags (const QModelIndex & idx) const
+{
+ Qt::ItemFlags defaultFlags = QAbstractListModel::flags(idx);
+ if (idx.isValid())
+ return defaultFlags | Qt::ItemIsUserCheckable;
+
+ return defaultFlags;
+}
+
+bool TrafficTypesModel::setData(const QModelIndex &idx, const QVariant &value, int role)
+{
+ if(!idx.isValid() || role != Qt::CheckStateRole)
+ return false;
+
+ if (_allTaps.count() <= idx.row())
+ return false;
+
+ _allTaps[idx.row()].setChecked(value == Qt::Checked);
+
+ QList<int> selected;
+ prefs_clear_string_list(*_recentList);
+ *_recentList = NULL;
+
+ for (int cnt = 0; cnt < _allTaps.count(); cnt++) {
+ if (_allTaps[cnt].checked()) {
+ int protoId = _allTaps[cnt].protocol();
+ selected.append(protoId);
+ char *title = g_strdup(proto_get_protocol_short_name(find_protocol_by_id(protoId)));
+ *_recentList = g_list_append(*_recentList, title);
+ }
+ }
+
+ emit protocolsChanged(selected);
+
+ emit dataChanged(idx, idx);
+ return true;
+}
+
+void TrafficTypesModel::selectProtocols(QList<int> protocols)
+{
+ beginResetModel();
+ for (int cnt = 0; cnt < _allTaps.count(); cnt++) {
+ _allTaps[cnt].setChecked(false);
+ if (protocols.contains(_allTaps[cnt].protocol()))
+ _allTaps[cnt].setChecked(true);
+ }
+ endResetModel();
+}
+
+TrafficTypesList::TrafficTypesList(QWidget *parent) :
+ QTreeView(parent)
+{
+ _name = QString();
+ _model = nullptr;
+
+ setAlternatingRowColors(true);
+ setRootIsDecorated(false);
+}
+
+void TrafficTypesList::setProtocolInfo(QString name, GList ** recentList)
+{
+ _name = name;
+
+ _model = new TrafficTypesModel(recentList);
+ setModel(_model);
+
+ connect(_model, &TrafficTypesModel::protocolsChanged, this, &TrafficTypesList::protocolsChanged);
+
+ resizeColumnToContents(0);
+ resizeColumnToContents(1);
+}
+
+void TrafficTypesList::selectProtocols(QList<int> protocols)
+{
+ if (_model)
+ _model->selectProtocols(protocols);
+}
+
+QList<int> TrafficTypesList::protocols() const
+{
+ QList<int> entries;
+ for (int cnt = 0; cnt < _model->rowCount(); cnt++) {
+ QModelIndex idx = _model->index(cnt, TrafficTypesModel::COL_CHECKED);
+ int protoId = _model->data(idx, TrafficTypesModel::TRAFFIC_PROTOCOL).toInt();
+ if (protoId > 0 && ! entries.contains(protoId))
+ entries.append(protoId);
+ }
+
+ return entries;
+}
+
+QList<int> TrafficTypesList::selectedProtocols() const
+{
+ QList<int> entries;
+ for (int cnt = 0; cnt < _model->rowCount(); cnt++) {
+ QModelIndex idx = _model->index(cnt, TrafficTypesModel::COL_CHECKED);
+ int protoId = _model->data(idx, TrafficTypesModel::TRAFFIC_PROTOCOL).toInt();
+ if (protoId > 0 && ! entries.contains(protoId) && _model->data(idx, TrafficTypesModel::TRAFFIC_IS_CHECKED).toBool())
+ entries.append(protoId);
+ }
+
+ return entries;
+}
diff --git a/ui/qt/widgets/traffic_types_list.h b/ui/qt/widgets/traffic_types_list.h
new file mode 100644
index 0000000000..fece2ef86a
--- /dev/null
+++ b/ui/qt/widgets/traffic_types_list.h
@@ -0,0 +1,100 @@
+/** @file
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef TRAFFIC_TYPES_LIST_H
+#define TRAFFIC_TYPES_LIST_H
+
+#include "config.h"
+
+#include <QTreeView>
+#include <QAbstractListModel>
+#include <QMap>
+#include <QString>
+
+class TrafficTypesRowData
+{
+
+public:
+ TrafficTypesRowData(int protocol, QString name);
+
+ int protocol() const;
+ QString name() const;
+ bool checked() const;
+ void setChecked(bool checked);
+
+private:
+ int _protocol;
+ QString _name;
+ bool _checked;
+};
+
+class TrafficTypesModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+
+ enum {
+ TRAFFIC_PROTOCOL = Qt::UserRole,
+ TRAFFIC_IS_CHECKED,
+ } eTrafficUserData;
+
+ enum {
+ COL_CHECKED,
+ COL_NAME,
+ COL_NUM,
+ COL_PROTOCOL,
+ } eTrafficColumnNames;
+
+ TrafficTypesModel(GList ** recentList, QObject *parent = nullptr);
+
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+ virtual QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override;
+ virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+
+ virtual bool setData(const QModelIndex &idx, const QVariant &value, int role) override;
+ virtual Qt::ItemFlags flags (const QModelIndex & idx) const override;
+
+ QList<int> protocols() const;
+
+public slots:
+ void selectProtocols(QList<int> protocols);
+
+signals:
+ void protocolsChanged(QList<int> protocols);
+
+private:
+ QList<TrafficTypesRowData> _allTaps;
+ GList ** _recentList;
+
+};
+
+class TrafficTypesList : public QTreeView
+{
+ Q_OBJECT
+public:
+
+ TrafficTypesList(QWidget *parent = nullptr);
+
+ void setProtocolInfo(QString name, GList ** recentList);
+ QList<int> protocols() const;
+ QList<int> selectedProtocols() const;
+
+public slots:
+ void selectProtocols(QList<int> protocols);
+
+signals:
+ void protocolsChanged(QList<int> protocols);
+
+private:
+ QString _name;
+ TrafficTypesModel * _model;
+};
+
+#endif // TRAFFIC_TYPES_LIST_H \ No newline at end of file