diff options
author | John Thacker <johnthacker@gmail.com> | 2023-02-16 07:31:31 -0500 |
---|---|---|
committer | John Thacker <johnthacker@gmail.com> | 2023-02-22 02:38:12 +0000 |
commit | 33493cb602ce105663c54a252240cbddbd44e0f0 (patch) | |
tree | e0f23579452cbb0308ab13068f842b580a6ee955 | |
parent | a2b584b8bd5a353b083063d6dcb161d262391556 (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.cpp | 23 | ||||
-rw-r--r-- | ui/qt/models/timeline_delegate.cpp | 49 | ||||
-rw-r--r-- | ui/qt/models/timeline_delegate.h | 3 | ||||
-rw-r--r-- | ui/qt/widgets/traffic_tab.cpp | 27 | ||||
-rw-r--r-- | ui/qt/widgets/traffic_tab.h | 9 | ||||
-rw-r--r-- | ui/qt/widgets/traffic_tree.h | 1 |
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> |