aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Thacker <johnthacker@gmail.com>2023-02-16 07:31:31 -0500
committerJohn Thacker <johnthacker@gmail.com>2023-02-22 02:38:12 +0000
commit33493cb602ce105663c54a252240cbddbd44e0f0 (patch)
treee0f23579452cbb0308ab13068f842b580a6ee955
parenta2b584b8bd5a353b083063d6dcb161d262391556 (diff)
Qt: Fix conversation dialog timeline graph columns
Remove the separate copy of the conversation column type enum in ConversationDialog. It doesn't correspond to the enum in ATapDataModel, because it doesn't include the Conversation ID and Total columns. Delegates set to the Traffic Tree (a QTreeView) apply to the displayed column number, not the what is displayed in the column. That is, when columns are hidden (filtered), the delegates stay with the old column number and end up being displayed on new content. That's not what we want; we want to always have the timeline graph on the Start and Duration columns. Moving around the Delegate depending on which columns are filtered is complicated; just set the TimeLine delegate to the entire TrafficTree, and use the default paint if we're on any column other than Start or Duration. This does mean that we don't need to store a map of Delegates. Use a slightly different way to get TimelineDelegate to paint the rect with no text using the current style, so we can use the default paint with text for other columns. The timeline graph needs to get the value of the Start and Duration columns as filtered by the proxy column, so have the model pass in indices so that they can be mapped to the current displayed column. Have the timeline graph apply to just the Start or just the Duration column if only one is visible. Together these compute the proper pixel values to apply the timeline graph to the Start and Duration columns regardless of which columns are displayed and which are filtered, in any tab, regardless of what optional columns appear in that tab. Fix #18860
-rw-r--r--ui/qt/conversation_dialog.cpp23
-rw-r--r--ui/qt/models/timeline_delegate.cpp49
-rw-r--r--ui/qt/models/timeline_delegate.h3
-rw-r--r--ui/qt/widgets/traffic_tab.cpp27
-rw-r--r--ui/qt/widgets/traffic_tab.h9
-rw-r--r--ui/qt/widgets/traffic_tree.h1
6 files changed, 52 insertions, 60 deletions
diff --git a/ui/qt/conversation_dialog.cpp b/ui/qt/conversation_dialog.cpp
index f9e75537de..c346713b04 100644
--- a/ui/qt/conversation_dialog.cpp
+++ b/ui/qt/conversation_dialog.cpp
@@ -50,25 +50,6 @@
// - The value of 'Rel start' and 'Duration' in "Conversations" no need too precise https://gitlab.com/wireshark/wireshark/-/issues/12803
-typedef enum {
- CONV_COLUMN_SRC_ADDR,
- CONV_COLUMN_SRC_PORT,
- CONV_COLUMN_DST_ADDR,
- CONV_COLUMN_DST_PORT,
- CONV_COLUMN_PACKETS,
- CONV_COLUMN_BYTES,
- CONV_COLUMN_PKT_AB,
- CONV_COLUMN_BYTES_AB,
- CONV_COLUMN_PKT_BA,
- CONV_COLUMN_BYTES_BA,
- CONV_COLUMN_START,
- CONV_COLUMN_DURATION,
- CONV_COLUMN_BPS_AB,
- CONV_COLUMN_BPS_BA,
- CONV_NUM_COLUMNS,
- CONV_INDEX_COLUMN = CONV_NUM_COLUMNS
-} conversation_column_type_e;
-
static const QString table_name_ = QObject::tr("Conversation");
static ATapDataModel * createModel(int protoId, QString filter)
@@ -91,8 +72,8 @@ ConversationDialog::ConversationDialog(QWidget &parent, CaptureFile &cf) :
trafficList()->setProtocolInfo(table_name_, &(recent.conversation_tabs));
trafficTab()->setProtocolInfo(table_name_, trafficList(), &(recent.conversation_tabs_columns), &createModel);
- trafficTab()->setDelegate(CONV_COLUMN_START, &createDelegate);
- trafficTab()->setDelegate(CONV_COLUMN_DURATION, &createDelegate);
+ trafficTab()->setDelegate(&createDelegate);
+ trafficTab()->setDelegate(&createDelegate);
trafficTab()->setFilter(cf.displayFilter());
connect(trafficTab(), &TrafficTab::filterAction, this, &ConversationDialog::filterAction);
diff --git a/ui/qt/models/timeline_delegate.cpp b/ui/qt/models/timeline_delegate.cpp
index f3f6abbc72..07a7409c26 100644
--- a/ui/qt/models/timeline_delegate.cpp
+++ b/ui/qt/models/timeline_delegate.cpp
@@ -15,6 +15,7 @@
#include <QApplication>
#include <QPainter>
#include <QTreeView>
+#include <QAbstractProxyModel>
// XXX We might want to move this to conversation_dialog.cpp.
@@ -40,26 +41,52 @@ void TimelineDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
QStyleOptionViewItem option_vi = option;
QStyledItemDelegate::initStyleOption(&option_vi, index);
+ bool drawBar = false;
struct timeline_span span_px = index.data(_dataRole).value<struct timeline_span>();
if (_dataRole == ATapDataModel::TIMELINE_DATA) {
double span_s = span_px.maxRelTime - span_px.minRelTime;
- if (qobject_cast<QTreeView *>(parent()) == nullptr)
- return;
QTreeView * tree = qobject_cast<QTreeView *>(parent());
- int start_px = tree->columnWidth(span_px.colStart);
- int column_px = start_px + tree->columnWidth(span_px.colDuration);
-
- span_px.start = ((span_px.startTime - span_px.minRelTime) * column_px) / span_s;
- span_px.width = ((span_px.stopTime - span_px.startTime) * column_px) / span_s;
-
- if (index.column() == span_px.colDuration) {
- span_px.start -= start_px;
+ if (tree) {
+ QAbstractProxyModel * proxy = qobject_cast<QAbstractProxyModel *>(tree->model());
+ if (proxy && proxy->sourceModel()) {
+ QModelIndex indexStart = proxy->mapFromSource(proxy->sourceModel()->index(0, span_px.colStart));
+ int colStart = -1;
+ int start_px = 0;
+ if (indexStart.isValid()) {
+ colStart = indexStart.column();
+ start_px = tree->columnWidth(colStart);
+ }
+ int colDuration = -1;
+ int column_px = start_px;
+ QModelIndex indexDuration = proxy->mapFromSource(proxy->sourceModel()->index(0, span_px.colDuration));
+ if (indexDuration.isValid()) {
+ colDuration = indexDuration.column();
+ column_px += tree->columnWidth(colDuration);
+ }
+
+ span_px.start = ((span_px.startTime - span_px.minRelTime) * column_px) / span_s;
+ span_px.width = ((span_px.stopTime - span_px.startTime) * column_px) / span_s;
+
+ if (index.column() == colStart) {
+ drawBar = true;
+ } else if (index.column() == colDuration) {
+ drawBar = true;
+ span_px.start -= start_px;
+ }
+ }
}
}
+ if (!drawBar) {
+ QStyledItemDelegate::paint(painter, option, index);
+ return;
+ }
+
// Paint our rect with no text using the current style, then draw our
// bar and text over it.
- QStyledItemDelegate::paint(painter, option, index);
+ option_vi.text = QString();
+ QStyle *style = option_vi.widget ? option_vi.widget->style() : QApplication::style();
+ style->drawControl(QStyle::CE_ItemViewItem, &option_vi, painter, option_vi.widget);
if (QApplication::style()->objectName().contains("vista")) {
// QWindowsVistaStyle::drawControl does this internally. Unfortunately there
diff --git a/ui/qt/models/timeline_delegate.h b/ui/qt/models/timeline_delegate.h
index 925e266656..06218b87a0 100644
--- a/ui/qt/models/timeline_delegate.h
+++ b/ui/qt/models/timeline_delegate.h
@@ -53,9 +53,6 @@ class TimelineDelegate : public QStyledItemDelegate
public:
TimelineDelegate(QWidget *parent = 0);
- // Make sure QStyledItemDelegate::paint doesn't draw any text.
- virtual QString displayText(const QVariant &, const QLocale &) const { return QString(); }
-
void setDataRole(int role);
protected:
diff --git a/ui/qt/widgets/traffic_tab.cpp b/ui/qt/widgets/traffic_tab.cpp
index f4dcec0c43..9913acaac5 100644
--- a/ui/qt/widgets/traffic_tab.cpp
+++ b/ui/qt/widgets/traffic_tab.cpp
@@ -69,6 +69,7 @@ TrafficTab::TrafficTab(QWidget * parent) :
DetachableTabWidget(parent)
{
_createModel = nullptr;
+ _createDelegate = nullptr;
_disableTaps = false;
_nameResolution = false;
setTabBasename(QString());
@@ -90,29 +91,19 @@ void TrafficTab::setProtocolInfo(QString tableName, TrafficTypesList * trafficLi
setOpenTabs(trafficList->protocols(true));
}
-void TrafficTab::setDelegate(int column, ATapCreateDelegate createDelegate)
+void TrafficTab::setDelegate(ATapCreateDelegate createDelegate)
{
- if (! createDelegate || column < 0)
+ if (! createDelegate)
return;
- if (_createDelegates.keys().contains(column))
- _createDelegates.remove(column);
- _createDelegates.insert(column, createDelegate);
+ _createDelegate = createDelegate;
for (int idx = 0; idx < count(); idx++) {
- int setColumn = column;
- ATapDataModel * model = modelForTabIndex(idx);
- if (model->portsAreHidden()) {
- if (model->modelType() == ATapDataModel::DATAMODEL_ENDPOINT && column > EndpointDataModel::ENDP_COLUMN_PORT)
- setColumn -= 1;
- else if (model->modelType() == ATapDataModel::DATAMODEL_CONVERSATION && column > ConversationDataModel::CONV_COLUMN_DST_PORT)
- setColumn -= 2;
- }
if (qobject_cast<QTreeView *>(widget(idx)))
{
QTreeView * tree = qobject_cast<QTreeView *>(widget(idx));
- tree->setItemDelegateForColumn(setColumn, createDelegate(tree));
+ tree->setItemDelegate(createDelegate(tree));
}
}
}
@@ -128,13 +119,9 @@ QTreeView * TrafficTab::createTree(int protoId)
model->enableTap();
- foreach(int col, _createDelegates.keys())
+ if (_createDelegate)
{
- if (_createDelegates[col])
- {
- ATapCreateDelegate creator = _createDelegates[col];
- tree->setItemDelegateForColumn(col, creator(tree));
- }
+ tree->setItemDelegate(_createDelegate(tree));
}
TrafficDataFilterProxy * proxyModel = new TrafficDataFilterProxy(tree);
diff --git a/ui/qt/widgets/traffic_tab.h b/ui/qt/widgets/traffic_tab.h
index 7d7a93c596..71c48ae50a 100644
--- a/ui/qt/widgets/traffic_tab.h
+++ b/ui/qt/widgets/traffic_tab.h
@@ -97,15 +97,14 @@ public:
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 the tab. It will apply for all
+ * models residing in this tab object
*
- * @param column the column to set the delegate for. It will apply for all models
- * residing inside this tab object
* @param createDelegate the callback for the delegate creation
*
* @see ATapCreateDelegate
*/
- void setDelegate(int column, ATapCreateDelegate createDelegate);
+ void setDelegate(ATapCreateDelegate createDelegate);
/**
* @brief Set the filter or remove it by providing an empty filter
@@ -221,7 +220,7 @@ private:
QList<int> _allProtocols;
QMap<int, int> _tabs;
ATapModelCallback _createModel;
- QMap<int, ATapCreateDelegate> _createDelegates;
+ ATapCreateDelegate _createDelegate;
GList ** _recentColumnList;
bool _disableTaps;
diff --git a/ui/qt/widgets/traffic_tree.h b/ui/qt/widgets/traffic_tree.h
index 81d1431eb8..5bc87e91b0 100644
--- a/ui/qt/widgets/traffic_tree.h
+++ b/ui/qt/widgets/traffic_tree.h
@@ -22,6 +22,7 @@
#include <QTreeView>
#include <QMenu>
#include <QHeaderView>
+#include <QSortFilterProxyModel>
#include <QWidgetAction>
#include <QLineEdit>