Cabana: add button to display all cached data in chart (#26575)

* display all data btn

* remove timer

* update toolbar later

* dont update axis y in updateSeries

faster get_raw_value

* faster update

* optimize zoom y axis

* cleanup

* revert changes to get_raw_value

* updateState in eventsMerge

* cleanup:

* cleanup
old-commit-hash: 9ffb7a7518
taco
Dean Lee 2 years ago committed by GitHub
parent 426d6988c7
commit 3acdabe2c2
  1. 75
      tools/cabana/chartswidget.cc
  2. 5
      tools/cabana/chartswidget.h

@ -3,7 +3,6 @@
#include <QFutureSynchronizer> #include <QFutureSynchronizer>
#include <QGraphicsLayout> #include <QGraphicsLayout>
#include <QRubberBand> #include <QRubberBand>
#include <QTimer>
#include <QToolBar> #include <QToolBar>
#include <QToolButton> #include <QToolButton>
#include <QtConcurrent> #include <QtConcurrent>
@ -19,6 +18,7 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
title_label = new QLabel(); title_label = new QLabel();
title_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); title_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
toolbar->addWidget(title_label); toolbar->addWidget(title_label);
show_all_values_btn = toolbar->addAction("");
toolbar->addWidget(range_label = new QLabel()); toolbar->addWidget(range_label = new QLabel());
reset_zoom_btn = toolbar->addAction(""); reset_zoom_btn = toolbar->addAction("");
reset_zoom_btn->setToolTip(tr("Reset zoom (drag on chart to zoom X-Axis)")); reset_zoom_btn->setToolTip(tr("Reset zoom (drag on chart to zoom X-Axis)"));
@ -26,7 +26,6 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
remove_all_btn->setToolTip(tr("Remove all charts")); remove_all_btn->setToolTip(tr("Remove all charts"));
dock_btn = toolbar->addAction(""); dock_btn = toolbar->addAction("");
main_layout->addWidget(toolbar); main_layout->addWidget(toolbar);
updateToolBar();
// charts // charts
QWidget *charts_container = new QWidget(this); QWidget *charts_container = new QWidget(this);
@ -37,14 +36,16 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
charts_scroll->setWidgetResizable(true); charts_scroll->setWidgetResizable(true);
charts_scroll->setWidget(charts_container); charts_scroll->setWidget(charts_container);
charts_scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); charts_scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
main_layout->addWidget(charts_scroll); main_layout->addWidget(charts_scroll);
max_chart_range = settings.max_chart_x_range;
use_dark_theme = palette().color(QPalette::WindowText).value() > palette().color(QPalette::Background).value(); use_dark_theme = palette().color(QPalette::WindowText).value() > palette().color(QPalette::Background).value();
updateToolBar();
QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &ChartsWidget::removeAll); QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &ChartsWidget::removeAll);
QObject::connect(can, &CANMessages::eventsMerged, this, &ChartsWidget::eventsMerged); QObject::connect(can, &CANMessages::eventsMerged, this, &ChartsWidget::eventsMerged);
QObject::connect(can, &CANMessages::updated, this, &ChartsWidget::updateState); QObject::connect(can, &CANMessages::updated, this, &ChartsWidget::updateState);
QObject::connect(show_all_values_btn, &QAction::triggered, this, &ChartsWidget::showAllData);
QObject::connect(remove_all_btn, &QAction::triggered, this, &ChartsWidget::removeAll); QObject::connect(remove_all_btn, &QAction::triggered, this, &ChartsWidget::removeAll);
QObject::connect(reset_zoom_btn, &QAction::triggered, this, &ChartsWidget::zoomReset); QObject::connect(reset_zoom_btn, &QAction::triggered, this, &ChartsWidget::zoomReset);
QObject::connect(dock_btn, &QAction::triggered, [this]() { QObject::connect(dock_btn, &QAction::triggered, [this]() {
@ -58,7 +59,7 @@ void ChartsWidget::eventsMerged() {
if (auto events = can->events(); events && !events->empty()) { if (auto events = can->events(); events && !events->empty()) {
event_range.first = (events->front()->mono_time / (double)1e9) - can->routeStartTime(); event_range.first = (events->front()->mono_time / (double)1e9) - can->routeStartTime();
event_range.second = (events->back()->mono_time / (double)1e9) - can->routeStartTime(); event_range.second = (events->back()->mono_time / (double)1e9) - can->routeStartTime();
updateDisplayRange(); updateState();
} }
} }
@ -69,8 +70,8 @@ void ChartsWidget::updateDisplayRange() {
// reached the end, or seeked to a timestamp out of range. // reached the end, or seeked to a timestamp out of range.
display_range.first = current_sec - 5; display_range.first = current_sec - 5;
} }
display_range.first = std::max(display_range.first, event_range.first); display_range.first = std::floor(std::max(display_range.first, event_range.first) * 10.0) / 10.0;
display_range.second = std::min(display_range.first + settings.max_chart_x_range, event_range.second); display_range.second = std::floor(std::min(display_range.first + max_chart_range, event_range.second) * 10.0) / 10.0;
if (prev_range != display_range) { if (prev_range != display_range) {
QFutureSynchronizer<void> future_synchronizer; QFutureSynchronizer<void> future_synchronizer;
for (auto c : charts) for (auto c : charts)
@ -100,13 +101,29 @@ void ChartsWidget::updateState() {
} }
const auto &range = is_zoomed ? zoomed_range : display_range; const auto &range = is_zoomed ? zoomed_range : display_range;
setUpdatesEnabled(false);
for (auto c : charts) { for (auto c : charts) {
c->setDisplayRange(range.first, range.second); c->setDisplayRange(range.first, range.second);
c->scene()->invalidate({}, QGraphicsScene::ForegroundLayer); c->scene()->invalidate({}, QGraphicsScene::ForegroundLayer);
} }
setUpdatesEnabled(true);
}
void ChartsWidget::showAllData() {
bool switch_to_show_all = max_chart_range == settings.max_chart_x_range;
max_chart_range = switch_to_show_all ? settings.cached_segment_limit * 60
: settings.max_chart_x_range;
max_chart_range = std::min(max_chart_range, (uint32_t)can->totalSeconds());
updateToolBar();
updateState();
} }
void ChartsWidget::updateToolBar() { void ChartsWidget::updateToolBar() {
int min_range = std::min(settings.max_chart_x_range, (int)can->totalSeconds());
bool displaying_all = max_chart_range != min_range;
show_all_values_btn->setText(tr("%1 minutes").arg(max_chart_range / 60));
show_all_values_btn->setToolTip(tr("Click to display %1 data").arg(displaying_all ? tr("%1 minutes").arg(min_range / 60) : tr("ALL cached")));
show_all_values_btn->setVisible(!is_zoomed);
remove_all_btn->setEnabled(!charts.isEmpty()); remove_all_btn->setEnabled(!charts.isEmpty());
reset_zoom_btn->setEnabled(is_zoomed); reset_zoom_btn->setEnabled(is_zoomed);
range_label->setText(is_zoomed ? tr("%1 - %2").arg(zoomed_range.first, 0, 'f', 2).arg(zoomed_range.second, 0, 'f', 2) : ""); range_label->setText(is_zoomed ? tr("%1 - %2").arg(zoomed_range.first, 0, 'f', 2).arg(zoomed_range.second, 0, 'f', 2) : "");
@ -232,6 +249,7 @@ void ChartView::addSeries(const QString &msg_id, const Signal *sig) {
sigs.push_back({.msg_id = msg_id, .address = address, .source = source, .sig = sig, .series = series}); sigs.push_back({.msg_id = msg_id, .address = address, .source = source, .sig = sig, .series = series});
updateTitle(); updateTitle();
updateSeries(sig); updateSeries(sig);
updateAxisY();
} }
void ChartView::removeSeries(const QString &msg_id, const Signal *sig) { void ChartView::removeSeries(const QString &msg_id, const Signal *sig) {
@ -242,8 +260,7 @@ void ChartView::removeSeries(const QString &msg_id, const Signal *sig) {
} }
bool ChartView::hasSeries(const QString &msg_id, const Signal *sig) const { bool ChartView::hasSeries(const QString &msg_id, const Signal *sig) const {
auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; }); return std::any_of(sigs.begin(), sigs.end(), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; });
return it != sigs.end();
} }
QList<ChartView::SigItem>::iterator ChartView::removeSeries(const QList<ChartView::SigItem>::iterator &it) { QList<ChartView::SigItem>::iterator ChartView::removeSeries(const QList<ChartView::SigItem>::iterator &it) {
@ -261,11 +278,11 @@ QList<ChartView::SigItem>::iterator ChartView::removeSeries(const QList<ChartVie
} }
void ChartView::signalUpdated(const Signal *sig) { void ChartView::signalUpdated(const Signal *sig) {
auto it = std::find_if(sigs.begin(), sigs.end(), [=](auto &s) { return s.sig == sig; }); if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.sig == sig; })) {
if (it != sigs.end()) {
updateTitle(); updateTitle();
// TODO: don't update series if only name changed. // TODO: don't update series if only name changed.
updateSeries(sig); updateSeries(sig);
updateAxisY();
} }
} }
@ -276,8 +293,7 @@ void ChartView::signalRemoved(const Signal *sig) {
} }
void ChartView::msgUpdated(uint32_t address) { void ChartView::msgUpdated(uint32_t address) {
auto it = std::find_if(sigs.begin(), sigs.end(), [=](auto &s) { return s.address == address; }); if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.address == address; }))
if (it != sigs.end())
updateTitle(); updateTitle();
} }
@ -392,7 +408,6 @@ void ChartView::updateSeries(const Signal *sig) {
s.series->replace(s.vals); s.series->replace(s.vals);
} }
} }
updateAxisY();
} }
// auto zoom on yaxis // auto zoom on yaxis
@ -422,11 +437,39 @@ void ChartView::updateAxisY() {
axis_y->setRange(min_y - 1, max_y + 1); axis_y->setRange(min_y - 1, max_y + 1);
} else { } else {
double range = max_y - min_y; double range = max_y - min_y;
axis_y->setRange(min_y - range * 0.05, max_y + range * 0.05); applyNiceNumbers(min_y - range * 0.05, max_y + range * 0.05);
axis_y->applyNiceNumbers();
} }
QTimer::singleShot(0, this, &ChartView::adjustChartMargins); adjustChartMargins();
}
void ChartView::applyNiceNumbers(qreal min, qreal max) {
int tick_count = axis_y->tickCount();
qreal range = niceNumber((max - min), true); // range with ceiling
qreal step = niceNumber(range / (tick_count - 1), false);
min = qFloor(min / step);
max = qCeil(max / step);
tick_count = int(max - min) + 1;
axis_y->setRange(min * step, max * step);
axis_y->setTickCount(tick_count);
}
//nice numbers can be expressed as form of 1*10^n, 2* 10^n or 5*10^n
qreal ChartView::niceNumber(qreal x, bool ceiling) {
qreal z = qPow(10, qFloor(std::log10(x))); //find corresponding number of the form of 10^n than is smaller than x
qreal q = x / z; //q<10 && q>=1;
if (ceiling) {
if (q <= 1.0) q = 1;
else if (q <= 2.0) q = 2;
else if (q <= 5.0) q = 5;
else q = 10;
} else {
if (q < 1.5) q = 1;
else if (q < 3.0) q = 2;
else if (q < 7.0) q = 5;
else q = 10;
}
return q * z;
} }
void ChartView::leaveEvent(QEvent *event) { void ChartView::leaveEvent(QEvent *event) {

@ -66,6 +66,8 @@ private:
void updateTitle(); void updateTitle();
void updateFromSettings(); void updateFromSettings();
void drawForeground(QPainter *painter, const QRectF &rect) override; void drawForeground(QPainter *painter, const QRectF &rect) override;
void applyNiceNumbers(qreal min, qreal max);
qreal niceNumber(qreal x, bool ceiling);
QValueAxis *axis_x; QValueAxis *axis_x;
QValueAxis *axis_y; QValueAxis *axis_y;
@ -102,17 +104,20 @@ private:
void zoomReset(); void zoomReset();
void updateToolBar(); void updateToolBar();
void removeAll(); void removeAll();
void showAllData();
bool eventFilter(QObject *obj, QEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override;
ChartView *findChart(const QString &id, const Signal *sig); ChartView *findChart(const QString &id, const Signal *sig);
QLabel *title_label; QLabel *title_label;
QLabel *range_label; QLabel *range_label;
bool docking = true; bool docking = true;
QAction *show_all_values_btn;
QAction *dock_btn; QAction *dock_btn;
QAction *reset_zoom_btn; QAction *reset_zoom_btn;
QAction *remove_all_btn; QAction *remove_all_btn;
QVBoxLayout *charts_layout; QVBoxLayout *charts_layout;
QList<ChartView *> charts; QList<ChartView *> charts;
uint32_t max_chart_range = 0;
bool is_zoomed = false; bool is_zoomed = false;
std::pair<double, double> event_range; std::pair<double, double> event_range;
std::pair<double, double> display_range; std::pair<double, double> display_range;

Loading…
Cancel
Save