From a46544f7084593d028ab0c202783125fa833cc79 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Sat, 4 Nov 2023 02:16:48 +0800 Subject: [PATCH] cabana/sparkline: Fix "Painter not active" warning (#30370) fix painter not active --- tools/cabana/chart/sparkline.cc | 55 ++++++++++----------------------- tools/cabana/chart/sparkline.h | 17 ++++------ tools/cabana/signalview.cc | 17 +++------- 3 files changed, 28 insertions(+), 61 deletions(-) diff --git a/tools/cabana/chart/sparkline.cc b/tools/cabana/chart/sparkline.cc index 1ae6a1bfe0..42608c030f 100644 --- a/tools/cabana/chart/sparkline.cc +++ b/tools/cabana/chart/sparkline.cc @@ -1,5 +1,6 @@ #include "tools/cabana/chart/sparkline.h" +#include #include #include @@ -12,52 +13,30 @@ void Sparkline::update(const MessageId &msg_id, const cabana::Signal *sig, doubl auto first = std::lower_bound(msgs.cbegin(), msgs.cend(), first_ts, CompareCanEvent()); auto last = std::upper_bound(first, msgs.cend(), ts, CompareCanEvent()); - bool update_values = last_ts != last_msg_ts || time_range != range; - last_ts = last_msg_ts; - time_range = range; - - if (first != last) { - if (update_values) { - values.clear(); - if (values.capacity() < std::distance(first, last)) { - values.reserve(std::distance(first, last) * 2); - } - min_val = std::numeric_limits::max(); - max_val = std::numeric_limits::lowest(); - for (auto it = first; it != last; ++it) { - const CanEvent *e = *it; - double value = 0; - if (sig->getValue(e->dat, e->size, &value)) { - values.emplace_back((e->mono_time - (*first)->mono_time) / 1e9, value); - if (min_val > value) min_val = value; - if (max_val < value) max_val = value; - } - } - if (min_val == max_val) { - min_val -= 1; - max_val += 1; + if (first != last && !size.isEmpty()) { + points.clear(); + double value = 0; + for (auto it = first; it != last; ++it) { + if (sig->getValue((*it)->dat, (*it)->size, &value)) { + points.emplace_back(((*it)->mono_time - (*first)->mono_time) / 1e9, value); } } - } else { - values.clear(); - } - - if (!values.empty()) { - render(sig->color, size); + const auto [min, max] = std::minmax_element(points.begin(), points.end(), + [](auto &l, auto &r) { return l.y() < r.y(); }); + min_val = min->y() == max->y() ? min->y() - 1 : min->y(); + max_val = min->y() == max->y() ? max->y() + 1 : max->y(); + freq_ = points.size() / std::max(points.back().x() - points.front().x(), 1.0); + render(sig->color, range, size); } else { pixmap = QPixmap(); - min_val = -1; - max_val = 1; } } -void Sparkline::render(const QColor &color, QSize size) { - const double xscale = (size.width() - 1) / (double)time_range; +void Sparkline::render(const QColor &color, int range, QSize size) { + const double xscale = (size.width() - 1) / (double)range; const double yscale = (size.height() - 3) / (max_val - min_val); - points.clear(); - points.reserve(values.capacity()); - for (auto &v : values) { - points.emplace_back(v.x() * xscale, 1 + std::abs(v.y() - max_val) * yscale); + for (auto &v : points) { + v = QPoint(v.x() * xscale, 1 + std::abs(v.y() - max_val) * yscale); } qreal dpr = qApp->devicePixelRatio(); diff --git a/tools/cabana/chart/sparkline.h b/tools/cabana/chart/sparkline.h index 21cbd40a3f..3bdd8a3ee5 100644 --- a/tools/cabana/chart/sparkline.h +++ b/tools/cabana/chart/sparkline.h @@ -1,29 +1,24 @@ #pragma once -#include - #include #include #include -#include "tools/cabana/dbc/dbcmanager.h" +#include "tools/cabana/dbc/dbc.h" class Sparkline { public: void update(const MessageId &msg_id, const cabana::Signal *sig, double last_msg_ts, int range, QSize size); - const QSize size() const { return pixmap.size() / pixmap.devicePixelRatio(); } - inline double freq() const { - return values.empty() ? 0 : values.size() / std::max(values.back().x() - values.front().x(), 1.0); - } + inline double freq() const { return freq_; } + bool isEmpty() const { return pixmap.isNull(); } QPixmap pixmap; double min_val = 0; double max_val = 0; - double last_ts = 0; - int time_range = 0; private: - void render(const QColor &color, QSize size); - std::vector values; + void render(const QColor &color, int range, QSize size); + std::vector points; + double freq_ = 0; }; diff --git a/tools/cabana/signalview.cc b/tools/cabana/signalview.cc index 3abcf4d111..7eb647b650 100644 --- a/tools/cabana/signalview.cc +++ b/tools/cabana/signalview.cc @@ -351,7 +351,7 @@ void SignalItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op painter->setPen(option.palette.color(option.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text)); QRect rect = r.adjusted(sparkline_size.width() + 1, 0, 0, 0); int value_adjust = 10; - if (item->highlight || option.state & QStyle::State_Selected) { + if (!item->sparkline.isEmpty() && (item->highlight || option.state & QStyle::State_Selected)) { painter->drawLine(rect.topLeft(), rect.bottomLeft()); rect.adjust(5, -v_margin, 0, v_margin); painter->setFont(minmax_font); @@ -361,7 +361,7 @@ void SignalItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op painter->drawText(rect, Qt::AlignLeft | Qt::AlignBottom, min); QFontMetrics fm(minmax_font); value_adjust = std::max(fm.width(min), fm.width(max)) + 5; - } else if (item->sig->type == cabana::Signal::Type::Multiplexed) { + } else if (!item->sparkline.isEmpty() && item->sig->type == cabana::Signal::Type::Multiplexed) { // display freq of multiplexed signal painter->setFont(label_font); QString freq = QString("%1 hz").arg(item->sparkline.freq(), 0, 'g', 2); @@ -610,12 +610,8 @@ void SignalView::handleSignalAdded(MessageId id, const cabana::Signal *sig) { } void SignalView::handleSignalUpdated(const cabana::Signal *sig) { - if (int row = model->signalRow(sig); row != -1) { - auto item = model->getItem(model->index(row, 1)); - // invalidate the sparkline - item->sparkline.last_ts = 0; + if (int row = model->signalRow(sig); row != -1) updateState(); - } } void SignalView::updateState(const std::set *msgs) { @@ -648,11 +644,8 @@ void SignalView::updateState(const std::set *msgs) { QFutureSynchronizer synchronizer; for (int i = first_visible_row; i <= last_visible_row; ++i) { auto item = model->getItem(model->index(i, 1)); - auto &s = item->sparkline; - if (s.last_ts != last_msg.ts || s.size() != size || s.time_range != settings.sparkline_range) { - synchronizer.addFuture(QtConcurrent::run( - &s, &Sparkline::update, model->msg_id, item->sig, last_msg.ts, settings.sparkline_range, size)); - } + synchronizer.addFuture(QtConcurrent::run( + &item->sparkline, &Sparkline::update, model->msg_id, item->sig, last_msg.ts, settings.sparkline_range, size)); } }