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 #include #include +#include // 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(); if (_dataRole == ATapDataModel::TIMELINE_DATA) { double span_s = span_px.maxRelTime - span_px.minRelTime; - if (qobject_cast(parent()) == nullptr) - return; QTreeView * tree = qobject_cast(parent()); - int start_px = tree->columnWidth(span_px.colStart); - int column_px = start_px + tree->columnWidth(span_px.colDuration); + if (tree) { + QAbstractProxyModel * proxy = qobject_cast(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; + 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 (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(widget(idx))) { QTreeView * tree = qobject_cast(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 _allProtocols; QMap _tabs; ATapModelCallback _createModel; - QMap _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 #include #include +#include #include #include