cabana/sparkline: Fix "Painter not active" warning (#30370)

fix painter not active
old-commit-hash: a46544f708
testing-closet
Dean Lee 1 year ago committed by GitHub
parent 080ae26ee3
commit 76bddbd23d
  1. 55
      tools/cabana/chart/sparkline.cc
  2. 17
      tools/cabana/chart/sparkline.h
  3. 17
      tools/cabana/signalview.cc

@ -1,5 +1,6 @@
#include "tools/cabana/chart/sparkline.h"
#include <algorithm>
#include <limits>
#include <QPainter>
@ -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<double>::max();
max_val = std::numeric_limits<double>::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();

@ -1,29 +1,24 @@
#pragma once
#include <algorithm>
#include <QPixmap>
#include <QPointF>
#include <vector>
#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<QPointF> values;
void render(const QColor &color, int range, QSize size);
std::vector<QPointF> points;
double freq_ = 0;
};

@ -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<MessageId> *msgs) {
@ -648,11 +644,8 @@ void SignalView::updateState(const std::set<MessageId> *msgs) {
QFutureSynchronizer<void> 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));
}
}

Loading…
Cancel
Save