forked from osmocom/wireshark
Qt: Hide columns for traffic tree
Allow columns to be hidden for the traffic tree dialogs Conversations and Endpoints and store the information profile specific
This commit is contained in:
parent
f75f577579
commit
2b4878d452
|
@ -40,6 +40,7 @@ wsbuglink:17779[]
|
||||||
- The dialog elements have been moved to make it easier to handle for new users.
|
- The dialog elements have been moved to make it easier to handle for new users.
|
||||||
- Selection of tap elements is done via list
|
- Selection of tap elements is done via list
|
||||||
- All configurations and options are done via a left side button row
|
- All configurations and options are done via a left side button row
|
||||||
|
- Columns for the Conversations and Endpoint dialogs can be hidden by context menu
|
||||||
|
|
||||||
* The PCRE2 library (https://www.pcre.org/) is now a required dependency to build Wireshark.
|
* The PCRE2 library (https://www.pcre.org/) is now a required dependency to build Wireshark.
|
||||||
|
|
||||||
|
@ -77,6 +78,8 @@ The following features are new (or have been significantly updated) since versio
|
||||||
* The Windows installers now ship with Qt 6.2.3.
|
* The Windows installers now ship with Qt 6.2.3.
|
||||||
They previously shipped with Qt 6.2.4.
|
They previously shipped with Qt 6.2.4.
|
||||||
|
|
||||||
|
* The Conversation and Endpoint dialogs have been reworked extensively
|
||||||
|
|
||||||
The following features are new (or have been significantly updated) since version 3.6.0:
|
The following features are new (or have been significantly updated) since version 3.6.0:
|
||||||
|
|
||||||
* The Windows installers now ship with Npcap 1.60.
|
* The Windows installers now ship with Npcap 1.60.
|
||||||
|
|
|
@ -95,7 +95,7 @@ ConversationDialog::ConversationDialog(QWidget &parent, CaptureFile &cf) :
|
||||||
{
|
{
|
||||||
trafficList()->setProtocolInfo(table_name_, &(recent.conversation_tabs));
|
trafficList()->setProtocolInfo(table_name_, &(recent.conversation_tabs));
|
||||||
|
|
||||||
trafficTab()->setProtocolInfo(table_name_, trafficList()->protocols(), trafficList()->selectedProtocols(), &createModel);
|
trafficTab()->setProtocolInfo(table_name_, trafficList(), &(recent.conversation_tabs_columns), &createModel);
|
||||||
trafficTab()->setDelegate(CONV_COLUMN_START, &createDelegate);
|
trafficTab()->setDelegate(CONV_COLUMN_START, &createDelegate);
|
||||||
trafficTab()->setDelegate(CONV_COLUMN_DURATION, &createDelegate);
|
trafficTab()->setDelegate(CONV_COLUMN_DURATION, &createDelegate);
|
||||||
trafficTab()->setFilter(cf.displayFilter());
|
trafficTab()->setFilter(cf.displayFilter());
|
||||||
|
|
|
@ -69,7 +69,7 @@ EndpointDialog::EndpointDialog(QWidget &parent, CaptureFile &cf) :
|
||||||
{
|
{
|
||||||
trafficList()->setProtocolInfo(table_name_, &(recent.endpoint_tabs));
|
trafficList()->setProtocolInfo(table_name_, &(recent.endpoint_tabs));
|
||||||
|
|
||||||
trafficTab()->setProtocolInfo(table_name_, trafficList()->protocols(), trafficList()->selectedProtocols(), &createModel);
|
trafficTab()->setProtocolInfo(table_name_, trafficList(), &(recent.endpoint_tabs_columns), &createModel);
|
||||||
trafficTab()->setFilter(cf.displayFilter());
|
trafficTab()->setFilter(cf.displayFilter());
|
||||||
displayFilterCheckBox()->setChecked(cf.displayFilter().length() > 0);
|
displayFilterCheckBox()->setChecked(cf.displayFilter().length() > 0);
|
||||||
connect(trafficTab(), &TrafficTab::filterAction, this, &EndpointDialog::filterAction);
|
connect(trafficTab(), &TrafficTab::filterAction, this, &EndpointDialog::filterAction);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <ui/qt/utils/variant_pointer.h>
|
#include <ui/qt/utils/variant_pointer.h>
|
||||||
#include <ui/qt/widgets/traffic_tab.h>
|
#include <ui/qt/widgets/traffic_tab.h>
|
||||||
#include <ui/qt/widgets/traffic_tree.h>
|
#include <ui/qt/widgets/traffic_tree.h>
|
||||||
|
#include <ui/qt/widgets/traffic_types_list.h>
|
||||||
#include <ui/qt/widgets/detachable_tabwidget.h>
|
#include <ui/qt/widgets/detachable_tabwidget.h>
|
||||||
|
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
@ -176,6 +177,24 @@ bool TrafficDataFilterProxy::lessThan(const QModelIndex &source_left, const QMod
|
||||||
return QSortFilterProxyModel::lessThan(source_left, source_right);
|
return QSortFilterProxyModel::lessThan(source_left, source_right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TrafficDataFilterProxy::filterAcceptsColumn(int source_column, const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return (!hideColumns_.contains(source_column));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrafficDataFilterProxy::setColumnVisibility(int column, bool visible)
|
||||||
|
{
|
||||||
|
hideColumns_.removeAll(column);
|
||||||
|
if (!visible)
|
||||||
|
hideColumns_.append(column);
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TrafficDataFilterProxy::columnVisible(int column) const
|
||||||
|
{
|
||||||
|
return ! hideColumns_.contains(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TrafficTab::TrafficTab(QWidget * parent) :
|
TrafficTab::TrafficTab(QWidget * parent) :
|
||||||
DetachableTabWidget(parent)
|
DetachableTabWidget(parent)
|
||||||
|
@ -189,14 +208,17 @@ TrafficTab::TrafficTab(QWidget * parent) :
|
||||||
TrafficTab::~TrafficTab()
|
TrafficTab::~TrafficTab()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void TrafficTab::setProtocolInfo(QString tableName, QList<int> allProtocols, QList<int> openTabs, ATapModelCallback createModel)
|
void TrafficTab::setProtocolInfo(QString tableName, TrafficTypesList * trafficList, GList ** recentColumnList, ATapModelCallback createModel)
|
||||||
{
|
{
|
||||||
setTabBasename(tableName);
|
setTabBasename(tableName);
|
||||||
_allProtocols = allProtocols;
|
|
||||||
|
_allProtocols = trafficList->protocols();
|
||||||
if (createModel)
|
if (createModel)
|
||||||
_createModel = createModel;
|
_createModel = createModel;
|
||||||
|
|
||||||
setOpenTabs(openTabs);
|
_recentColumnList = recentColumnList;
|
||||||
|
|
||||||
|
setOpenTabs(trafficList->selectedProtocols());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrafficTab::setDelegate(int column, ATapCreateDelegate createDelegate)
|
void TrafficTab::setDelegate(int column, ATapCreateDelegate createDelegate)
|
||||||
|
@ -228,7 +250,7 @@ void TrafficTab::setDelegate(int column, ATapCreateDelegate createDelegate)
|
||||||
|
|
||||||
QTreeView * TrafficTab::createTree(int protoId)
|
QTreeView * TrafficTab::createTree(int protoId)
|
||||||
{
|
{
|
||||||
TrafficTree * tree = new TrafficTree(tabBasename(), this);
|
TrafficTree * tree = new TrafficTree(tabBasename(), _recentColumnList, this);
|
||||||
|
|
||||||
if (_createModel) {
|
if (_createModel) {
|
||||||
ATapDataModel * model = _createModel(protoId, "");
|
ATapDataModel * model = _createModel(protoId, "");
|
||||||
|
@ -253,6 +275,8 @@ QTreeView * TrafficTab::createTree(int protoId)
|
||||||
tree->setSelectionModel(ism);
|
tree->setSelectionModel(ism);
|
||||||
connect(ism, &QItemSelectionModel::currentChanged, this, &TrafficTab::doCurrentIndexChange);
|
connect(ism, &QItemSelectionModel::currentChanged, this, &TrafficTab::doCurrentIndexChange);
|
||||||
|
|
||||||
|
tree->applyRecentColumns();
|
||||||
|
|
||||||
tree->sortByColumn(0, Qt::AscendingOrder);
|
tree->sortByColumn(0, Qt::AscendingOrder);
|
||||||
|
|
||||||
connect(proxyModel, &TrafficDataFilterProxy::modelReset, this, [tree]() {
|
connect(proxyModel, &TrafficDataFilterProxy::modelReset, this, [tree]() {
|
||||||
|
@ -262,6 +286,13 @@ QTreeView * TrafficTab::createTree(int protoId)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(proxyModel, &TrafficDataFilterProxy::modelReset, this, &TrafficTab::modelReset);
|
connect(proxyModel, &TrafficDataFilterProxy::modelReset, this, &TrafficTab::modelReset);
|
||||||
|
|
||||||
|
/* If the columns for the tree have changed, contact the tab. By also having the tab
|
||||||
|
* columns changed signal connecting back to the tree, it will propagate to all trees
|
||||||
|
* registered with this tab. Attention, this heavily relies on the fact, that all
|
||||||
|
* tree data models are identical */
|
||||||
|
connect(tree, &TrafficTree::columnsHaveChanged, this, &TrafficTab::columnsHaveChanged);
|
||||||
|
connect(this, &TrafficTab::columnsHaveChanged, tree, &TrafficTree::columnsChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tree;
|
return tree;
|
||||||
|
|
|
@ -12,9 +12,12 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
#include <ui/qt/models/atap_data_model.h>
|
#include <ui/qt/models/atap_data_model.h>
|
||||||
#include <ui/qt/filter_action.h>
|
#include <ui/qt/filter_action.h>
|
||||||
#include <ui/qt/widgets/detachable_tabwidget.h>
|
#include <ui/qt/widgets/detachable_tabwidget.h>
|
||||||
|
#include <ui/qt/widgets/traffic_types_list.h>
|
||||||
|
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
|
@ -67,10 +70,17 @@ class TrafficDataFilterProxy : public QSortFilterProxyModel
|
||||||
public:
|
public:
|
||||||
TrafficDataFilterProxy(QObject *parent = nullptr);
|
TrafficDataFilterProxy(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
void setColumnVisibility(int column, bool visible);
|
||||||
|
bool columnVisible(int column) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
|
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
|
||||||
|
virtual bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const;
|
||||||
virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
|
virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<int> hideColumns_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,13 +107,13 @@ public:
|
||||||
* without having to removing the predefined object during setup of the UI.
|
* 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 tableName The name for the table. Used for the protocol selection button
|
||||||
* @param allProtocols a list of all possible protocols. It's order will set the tab oder
|
* @param trafficList an element of traffictypeslist, which handles all profile selections
|
||||||
* @param openTabs a list of protocol ids to open at start of dialog
|
* @param recentColumnList a list of columns to be displayed for this traffic type
|
||||||
* @param createModel A callback, which will create the correct model for the trees
|
* @param createModel A callback, which will create the correct model for the trees
|
||||||
*
|
*
|
||||||
* @see ATapModelCallback
|
* @see ATapModelCallback
|
||||||
*/
|
*/
|
||||||
void setProtocolInfo(QString tableName, QList<int> allProtocols, QList<int> openTabs, ATapModelCallback createModel);
|
void setProtocolInfo(QString tableName, TrafficTypesList * trafficList, GList ** recentColumnList, ATapModelCallback createModel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the Delegate object for a specific column
|
* @brief Set the Delegate object for a specific column
|
||||||
|
@ -219,6 +229,7 @@ signals:
|
||||||
void retapRequired();
|
void retapRequired();
|
||||||
void disablingTaps();
|
void disablingTaps();
|
||||||
void tabsChanged(QList<int> protocols);
|
void tabsChanged(QList<int> protocols);
|
||||||
|
void columnsHaveChanged(QList<int> columns);
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
|
|
||||||
|
@ -230,6 +241,7 @@ private:
|
||||||
QMap<int, int> _tabs;
|
QMap<int, int> _tabs;
|
||||||
ATapModelCallback _createModel;
|
ATapModelCallback _createModel;
|
||||||
QMap<int, ATapCreateDelegate> _createDelegates;
|
QMap<int, ATapCreateDelegate> _createDelegates;
|
||||||
|
GList ** _recentColumnList;
|
||||||
|
|
||||||
bool _disableTaps;
|
bool _disableTaps;
|
||||||
bool _nameResolution;
|
bool _nameResolution;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <ui/qt/filter_action.h>
|
#include <ui/qt/filter_action.h>
|
||||||
#include <ui/qt/models/atap_data_model.h>
|
#include <ui/qt/models/atap_data_model.h>
|
||||||
#include <ui/qt/utils/variant_pointer.h>
|
#include <ui/qt/utils/variant_pointer.h>
|
||||||
|
#include <ui/qt/widgets/traffic_tab.h>
|
||||||
#include <ui/qt/widgets/traffic_tree.h>
|
#include <ui/qt/widgets/traffic_tree.h>
|
||||||
|
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
@ -39,20 +40,120 @@
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
#include <QHeaderView>
|
||||||
|
|
||||||
TrafficTree::TrafficTree(QString baseName, QWidget *parent) :
|
TrafficTreeHeaderView::TrafficTreeHeaderView(GList ** recentColumnList, QWidget * parent):
|
||||||
|
QHeaderView(Qt::Horizontal, parent)
|
||||||
|
{
|
||||||
|
_recentColumnList = recentColumnList;
|
||||||
|
|
||||||
|
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
|
||||||
|
connect(this, &QHeaderView::customContextMenuRequested, this, &TrafficTreeHeaderView::headerContextMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrafficTreeHeaderView::~TrafficTreeHeaderView()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void TrafficTreeHeaderView::headerContextMenu(const QPoint &pos)
|
||||||
|
{
|
||||||
|
TrafficTree * tree = qobject_cast<TrafficTree *>(parent());
|
||||||
|
if (!tree)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TrafficDataFilterProxy * proxy = qobject_cast<TrafficDataFilterProxy *>(tree->model());
|
||||||
|
if (sender() != this || ! proxy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QMenu ctxMenu;
|
||||||
|
|
||||||
|
for (int col = 0; col < tree->dataModel()->columnCount(); col++)
|
||||||
|
{
|
||||||
|
QString name = tree->dataModel()->headerData(col).toString();
|
||||||
|
QAction * action = new QAction(name);
|
||||||
|
action->setCheckable(true);
|
||||||
|
action->setChecked(proxy->columnVisible(col));
|
||||||
|
action->setProperty("col_nr", col);
|
||||||
|
ctxMenu.addAction(action);
|
||||||
|
|
||||||
|
connect(action, &QAction::triggered, this, &TrafficTreeHeaderView::columnTriggered);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxMenu.exec(mapToGlobal(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrafficTreeHeaderView::applyRecent()
|
||||||
|
{
|
||||||
|
TrafficTree * tree = qobject_cast<TrafficTree *>(parent());
|
||||||
|
if (!tree)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QList<int> columns;
|
||||||
|
for (GList * endTab = *_recentColumnList; endTab; endTab = endTab->next) {
|
||||||
|
QString colStr = QString((const char *)endTab->data);
|
||||||
|
bool ok = false;
|
||||||
|
int col = colStr.toInt(&ok);
|
||||||
|
if (ok)
|
||||||
|
columns << col;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (columns.count() > 0) {
|
||||||
|
TrafficDataFilterProxy * proxy = qobject_cast<TrafficDataFilterProxy *>(tree->model());
|
||||||
|
for (int col = 0; col < tree->dataModel()->columnCount(); col++) {
|
||||||
|
proxy->setColumnVisibility(col, columns.contains(col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrafficTreeHeaderView::columnTriggered(bool checked)
|
||||||
|
{
|
||||||
|
TrafficTree * tree = qobject_cast<TrafficTree *>(parent());
|
||||||
|
if (!tree)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TrafficDataFilterProxy * proxy = qobject_cast<TrafficDataFilterProxy *>(tree->model());
|
||||||
|
QAction * entry = qobject_cast<QAction *>(sender());
|
||||||
|
if (! proxy || ! entry || ! entry->property("col_nr").isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int col = entry->property("col_nr").toInt();
|
||||||
|
proxy->setColumnVisibility(col, checked);
|
||||||
|
|
||||||
|
prefs_clear_string_list(*_recentColumnList);
|
||||||
|
*_recentColumnList = NULL;
|
||||||
|
|
||||||
|
QList<int> visible;
|
||||||
|
|
||||||
|
for (int col = 0; col < tree->dataModel()->columnCount(); col++) {
|
||||||
|
if (proxy->columnVisible(col)) {
|
||||||
|
visible << col;
|
||||||
|
gchar *nr = qstring_strdup(QString::number(col));
|
||||||
|
*_recentColumnList = g_list_append(*_recentColumnList, nr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit columnsHaveChanged(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TrafficTree::TrafficTree(QString baseName, GList ** recentColumnList, QWidget *parent) :
|
||||||
QTreeView(parent)
|
QTreeView(parent)
|
||||||
{
|
{
|
||||||
_tapEnabled = true;
|
_tapEnabled = true;
|
||||||
_saveRaw = true;
|
_saveRaw = true;
|
||||||
_baseName = baseName;
|
_baseName = baseName;
|
||||||
_exportRole = ATapDataModel::UNFORMATTED_DISPLAYDATA;
|
_exportRole = ATapDataModel::UNFORMATTED_DISPLAYDATA;
|
||||||
|
_header = nullptr;
|
||||||
|
|
||||||
setAlternatingRowColors(true);
|
setAlternatingRowColors(true);
|
||||||
setRootIsDecorated(false);
|
setRootIsDecorated(false);
|
||||||
setSortingEnabled(true);
|
setSortingEnabled(true);
|
||||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
|
||||||
|
_header = new TrafficTreeHeaderView(recentColumnList);
|
||||||
|
setHeader(_header);
|
||||||
|
|
||||||
|
connect(_header, &TrafficTreeHeaderView::columnsHaveChanged, this, &TrafficTree::columnsHaveChanged);
|
||||||
connect(this, &QTreeView::customContextMenuRequested, this, &TrafficTree::customContextMenu);
|
connect(this, &QTreeView::customContextMenuRequested, this, &TrafficTree::customContextMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,3 +378,22 @@ void TrafficTree::disableTap()
|
||||||
return;
|
return;
|
||||||
model->disableTap();
|
model->disableTap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrafficTree::applyRecentColumns()
|
||||||
|
{
|
||||||
|
if (_header)
|
||||||
|
_header->applyRecent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrafficTree::columnsChanged(QList<int> columns)
|
||||||
|
{
|
||||||
|
TrafficDataFilterProxy * proxy = qobject_cast<TrafficDataFilterProxy *>(model());
|
||||||
|
if (!proxy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int col = 0; col < dataModel()->columnCount(); col++) {
|
||||||
|
proxy->setColumnVisibility(col, columns.contains(col));
|
||||||
|
}
|
||||||
|
|
||||||
|
resizeAction();
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
#include <ui/recent.h>
|
#include <ui/recent.h>
|
||||||
|
|
||||||
#include <ui/qt/models/atap_data_model.h>
|
#include <ui/qt/models/atap_data_model.h>
|
||||||
|
@ -19,6 +21,29 @@
|
||||||
|
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include <QHeaderView>
|
||||||
|
|
||||||
|
class TrafficTreeHeaderView : public QHeaderView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
TrafficTreeHeaderView(GList ** recentColumnList, QWidget * parent = nullptr);
|
||||||
|
~TrafficTreeHeaderView();
|
||||||
|
|
||||||
|
void applyRecent();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void columnsHaveChanged(QList<int> visible);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GList ** _recentColumnList;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void headerContextMenu(const QPoint &pos);
|
||||||
|
void columnTriggered(bool checked = false);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class TrafficTree : public QTreeView
|
class TrafficTree : public QTreeView
|
||||||
{
|
{
|
||||||
|
@ -35,7 +60,7 @@ public:
|
||||||
CLIPBOARD_JSON /* export as JSON */
|
CLIPBOARD_JSON /* export as JSON */
|
||||||
} eTrafficTreeClipboard;
|
} eTrafficTreeClipboard;
|
||||||
|
|
||||||
TrafficTree(QString baseName, QWidget *parent = nullptr);
|
TrafficTree(QString baseName, GList ** recentColumnList, QWidget *parent = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a menu containing clipboard copy entries for this tab
|
* @brief Create a menu containing clipboard copy entries for this tab
|
||||||
|
@ -48,12 +73,16 @@ public:
|
||||||
*/
|
*/
|
||||||
QMenu * createCopyMenu(QWidget * parent = nullptr);
|
QMenu * createCopyMenu(QWidget * parent = nullptr);
|
||||||
|
|
||||||
|
void applyRecentColumns();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void filterAction(QString filter, FilterAction::Action action, FilterAction::ActionType type);
|
void filterAction(QString filter, FilterAction::Action action, FilterAction::ActionType type);
|
||||||
|
void columnsHaveChanged(QList<int> columns);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void tapListenerEnabled(bool enable);
|
void tapListenerEnabled(bool enable);
|
||||||
void disableTap();
|
void disableTap();
|
||||||
|
void columnsChanged(QList<int> columns);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _tapEnabled;
|
bool _tapEnabled;
|
||||||
|
@ -61,18 +90,21 @@ private:
|
||||||
bool _saveRaw;
|
bool _saveRaw;
|
||||||
QString _baseName;
|
QString _baseName;
|
||||||
|
|
||||||
|
TrafficTreeHeaderView * _header;
|
||||||
|
|
||||||
ATapDataModel * dataModel();
|
ATapDataModel * dataModel();
|
||||||
|
|
||||||
QMenu * createActionSubMenu(FilterAction::Action cur_action, QModelIndex idx, bool isConversation);
|
QMenu * createActionSubMenu(FilterAction::Action cur_action, QModelIndex idx, bool isConversation);
|
||||||
void copyToClipboard(eTrafficTreeClipboard type);
|
void copyToClipboard(eTrafficTreeClipboard type);
|
||||||
|
|
||||||
|
friend class TrafficTreeHeaderView;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void customContextMenu(const QPoint &pos);
|
void customContextMenu(const QPoint &pos);
|
||||||
void useFilterAction();
|
void useFilterAction();
|
||||||
void clipboardAction();
|
void clipboardAction();
|
||||||
void resizeAction();
|
void resizeAction();
|
||||||
void toggleSaveRawAction();
|
void toggleSaveRawAction();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TRAFFIC_TREE_H
|
#endif // TRAFFIC_TREE_H
|
||||||
|
|
20
ui/recent.c
20
ui/recent.c
|
@ -60,7 +60,9 @@
|
||||||
#define RECENT_LAST_USED_PROFILE "gui.last_used_profile"
|
#define RECENT_LAST_USED_PROFILE "gui.last_used_profile"
|
||||||
#define RECENT_GUI_FILEOPEN_REMEMBERED_DIR "gui.fileopen_remembered_dir"
|
#define RECENT_GUI_FILEOPEN_REMEMBERED_DIR "gui.fileopen_remembered_dir"
|
||||||
#define RECENT_GUI_CONVERSATION_TABS "gui.conversation_tabs"
|
#define RECENT_GUI_CONVERSATION_TABS "gui.conversation_tabs"
|
||||||
|
#define RECENT_GUI_CONVERSATION_TABS_COLUMNS "gui.conversation_tabs_columns"
|
||||||
#define RECENT_GUI_ENDPOINT_TABS "gui.endpoint_tabs"
|
#define RECENT_GUI_ENDPOINT_TABS "gui.endpoint_tabs"
|
||||||
|
#define RECENT_GUI_ENDPOINT_TABS_COLUMNS "gui.endpoint_tabs_columns"
|
||||||
#define RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES "gui.rlc_pdus_from_mac_frames"
|
#define RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES "gui.rlc_pdus_from_mac_frames"
|
||||||
#define RECENT_GUI_CUSTOM_COLORS "gui.custom_colors"
|
#define RECENT_GUI_CUSTOM_COLORS "gui.custom_colors"
|
||||||
#define RECENT_GUI_TOOLBAR_SHOW "gui.additional_toolbar_show"
|
#define RECENT_GUI_TOOLBAR_SHOW "gui.additional_toolbar_show"
|
||||||
|
@ -918,12 +920,24 @@ write_profile_recent(void)
|
||||||
fprintf(rf, RECENT_GUI_CONVERSATION_TABS ": %s\n", string_list);
|
fprintf(rf, RECENT_GUI_CONVERSATION_TABS ": %s\n", string_list);
|
||||||
g_free(string_list);
|
g_free(string_list);
|
||||||
|
|
||||||
|
fprintf(rf, "\n# Conversation dialog tabs columns.\n");
|
||||||
|
fprintf(rf, "# List of conversation columns numbers.\n");
|
||||||
|
string_list = join_string_list(recent.conversation_tabs_columns);
|
||||||
|
fprintf(rf, RECENT_GUI_CONVERSATION_TABS_COLUMNS ": %s\n", string_list);
|
||||||
|
g_free(string_list);
|
||||||
|
|
||||||
fprintf(rf, "\n# Open endpoint dialog tabs.\n");
|
fprintf(rf, "\n# Open endpoint dialog tabs.\n");
|
||||||
fprintf(rf, "# List of endpoint names, e.g. \"TCP\", \"IPv6\".\n");
|
fprintf(rf, "# List of endpoint names, e.g. \"TCP\", \"IPv6\".\n");
|
||||||
string_list = join_string_list(recent.endpoint_tabs);
|
string_list = join_string_list(recent.endpoint_tabs);
|
||||||
fprintf(rf, RECENT_GUI_ENDPOINT_TABS ": %s\n", string_list);
|
fprintf(rf, RECENT_GUI_ENDPOINT_TABS ": %s\n", string_list);
|
||||||
g_free(string_list);
|
g_free(string_list);
|
||||||
|
|
||||||
|
fprintf(rf, "\n# Endpoint dialog tabs columns.\n");
|
||||||
|
fprintf(rf, "# List of endpoint columns numbers.\n");
|
||||||
|
string_list = join_string_list(recent.endpoint_tabs_columns);
|
||||||
|
fprintf(rf, RECENT_GUI_ENDPOINT_TABS_COLUMNS ": %s\n", string_list);
|
||||||
|
g_free(string_list);
|
||||||
|
|
||||||
write_recent_boolean(rf, "For RLC stats, whether to use RLC PDUs found inside MAC frames",
|
write_recent_boolean(rf, "For RLC stats, whether to use RLC PDUs found inside MAC frames",
|
||||||
RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES,
|
RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES,
|
||||||
recent.gui_rlc_use_pdus_from_mac);
|
recent.gui_rlc_use_pdus_from_mac);
|
||||||
|
@ -1122,8 +1136,12 @@ read_set_recent_pair_static(gchar *key, const gchar *value,
|
||||||
recent.has_gui_geometry_main_lower_pane = TRUE;
|
recent.has_gui_geometry_main_lower_pane = TRUE;
|
||||||
} else if (strcmp(key, RECENT_GUI_CONVERSATION_TABS) == 0) {
|
} else if (strcmp(key, RECENT_GUI_CONVERSATION_TABS) == 0) {
|
||||||
recent.conversation_tabs = prefs_get_string_list(value);
|
recent.conversation_tabs = prefs_get_string_list(value);
|
||||||
|
} else if (strcmp(key, RECENT_GUI_CONVERSATION_TABS_COLUMNS) == 0) {
|
||||||
|
recent.conversation_tabs_columns = prefs_get_string_list(value);
|
||||||
} else if (strcmp(key, RECENT_GUI_ENDPOINT_TABS) == 0) {
|
} else if (strcmp(key, RECENT_GUI_ENDPOINT_TABS) == 0) {
|
||||||
recent.endpoint_tabs = prefs_get_string_list(value);
|
recent.endpoint_tabs = prefs_get_string_list(value);
|
||||||
|
} else if (strcmp(key, RECENT_GUI_ENDPOINT_TABS_COLUMNS) == 0) {
|
||||||
|
recent.endpoint_tabs_columns = prefs_get_string_list(value);
|
||||||
} else if (strcmp(key, RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES) == 0) {
|
} else if (strcmp(key, RECENT_GUI_RLC_PDUS_FROM_MAC_FRAMES) == 0) {
|
||||||
parse_recent_boolean(value, &recent.gui_rlc_use_pdus_from_mac);
|
parse_recent_boolean(value, &recent.gui_rlc_use_pdus_from_mac);
|
||||||
} else if (strcmp(key, RECENT_KEY_COL_WIDTH) == 0) {
|
} else if (strcmp(key, RECENT_KEY_COL_WIDTH) == 0) {
|
||||||
|
@ -1611,6 +1629,8 @@ recent_cleanup(void)
|
||||||
g_list_free_full(recent.gui_additional_toolbars, g_free);
|
g_list_free_full(recent.gui_additional_toolbars, g_free);
|
||||||
g_list_free_full(recent.interface_toolbars, g_free);
|
g_list_free_full(recent.interface_toolbars, g_free);
|
||||||
prefs_clear_string_list(recent.conversation_tabs);
|
prefs_clear_string_list(recent.conversation_tabs);
|
||||||
|
prefs_clear_string_list(recent.conversation_tabs_columns);
|
||||||
prefs_clear_string_list(recent.endpoint_tabs);
|
prefs_clear_string_list(recent.endpoint_tabs);
|
||||||
|
prefs_clear_string_list(recent.endpoint_tabs_columns);
|
||||||
prefs_clear_string_list(recent.custom_colors);
|
prefs_clear_string_list(recent.custom_colors);
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,9 @@ typedef struct recent_settings_tag {
|
||||||
gboolean sys_warn_if_no_capture;
|
gboolean sys_warn_if_no_capture;
|
||||||
GList *col_width_list; /* column widths */
|
GList *col_width_list; /* column widths */
|
||||||
GList *conversation_tabs; /* enabled conversation dialog tabs */
|
GList *conversation_tabs; /* enabled conversation dialog tabs */
|
||||||
|
GList *conversation_tabs_columns; /* save the columns for conversation dialogs */
|
||||||
GList *endpoint_tabs; /* enabled endpoint dialog tabs */
|
GList *endpoint_tabs; /* enabled endpoint dialog tabs */
|
||||||
|
GList *endpoint_tabs_columns; /* save the columns for endpoint dialogs */
|
||||||
gchar *gui_fileopen_remembered_dir; /* folder of last capture loaded in File Open dialog */
|
gchar *gui_fileopen_remembered_dir; /* folder of last capture loaded in File Open dialog */
|
||||||
gboolean gui_rlc_use_pdus_from_mac;
|
gboolean gui_rlc_use_pdus_from_mac;
|
||||||
GList *custom_colors;
|
GList *custom_colors;
|
||||||
|
|
Loading…
Reference in New Issue