mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-01 11:32:21 +08:00
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: 9ffb7a751874ce829b01c23809615a955819b9a6
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
#include <QFutureSynchronizer>
|
||||
#include <QGraphicsLayout>
|
||||
#include <QRubberBand>
|
||||
#include <QTimer>
|
||||
#include <QToolBar>
|
||||
#include <QToolButton>
|
||||
#include <QtConcurrent>
|
||||
@@ -19,6 +18,7 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
|
||||
title_label = new QLabel();
|
||||
title_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
toolbar->addWidget(title_label);
|
||||
show_all_values_btn = toolbar->addAction("");
|
||||
toolbar->addWidget(range_label = new QLabel());
|
||||
reset_zoom_btn = toolbar->addAction("⟲");
|
||||
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"));
|
||||
dock_btn = toolbar->addAction("");
|
||||
main_layout->addWidget(toolbar);
|
||||
updateToolBar();
|
||||
|
||||
// charts
|
||||
QWidget *charts_container = new QWidget(this);
|
||||
@@ -37,14 +36,16 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
|
||||
charts_scroll->setWidgetResizable(true);
|
||||
charts_scroll->setWidget(charts_container);
|
||||
charts_scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
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();
|
||||
updateToolBar();
|
||||
|
||||
QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &ChartsWidget::removeAll);
|
||||
QObject::connect(can, &CANMessages::eventsMerged, this, &ChartsWidget::eventsMerged);
|
||||
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(reset_zoom_btn, &QAction::triggered, this, &ChartsWidget::zoomReset);
|
||||
QObject::connect(dock_btn, &QAction::triggered, [this]() {
|
||||
@@ -58,7 +59,7 @@ void ChartsWidget::eventsMerged() {
|
||||
if (auto events = can->events(); events && !events->empty()) {
|
||||
event_range.first = (events->front()->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.
|
||||
display_range.first = current_sec - 5;
|
||||
}
|
||||
display_range.first = std::max(display_range.first, event_range.first);
|
||||
display_range.second = std::min(display_range.first + settings.max_chart_x_range, event_range.second);
|
||||
display_range.first = std::floor(std::max(display_range.first, event_range.first) * 10.0) / 10.0;
|
||||
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) {
|
||||
QFutureSynchronizer<void> future_synchronizer;
|
||||
for (auto c : charts)
|
||||
@@ -100,13 +101,29 @@ void ChartsWidget::updateState() {
|
||||
}
|
||||
|
||||
const auto &range = is_zoomed ? zoomed_range : display_range;
|
||||
setUpdatesEnabled(false);
|
||||
for (auto c : charts) {
|
||||
c->setDisplayRange(range.first, range.second);
|
||||
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() {
|
||||
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());
|
||||
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) : "");
|
||||
@@ -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});
|
||||
updateTitle();
|
||||
updateSeries(sig);
|
||||
updateAxisY();
|
||||
}
|
||||
|
||||
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 {
|
||||
auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; });
|
||||
return it != sigs.end();
|
||||
return std::any_of(sigs.begin(), sigs.end(), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; });
|
||||
}
|
||||
|
||||
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) {
|
||||
auto it = std::find_if(sigs.begin(), sigs.end(), [=](auto &s) { return s.sig == sig; });
|
||||
if (it != sigs.end()) {
|
||||
if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.sig == sig; })) {
|
||||
updateTitle();
|
||||
// TODO: don't update series if only name changed.
|
||||
updateSeries(sig);
|
||||
updateAxisY();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,8 +293,7 @@ void ChartView::signalRemoved(const Signal *sig) {
|
||||
}
|
||||
|
||||
void ChartView::msgUpdated(uint32_t address) {
|
||||
auto it = std::find_if(sigs.begin(), sigs.end(), [=](auto &s) { return s.address == address; });
|
||||
if (it != sigs.end())
|
||||
if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.address == address; }))
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
@@ -392,7 +408,6 @@ void ChartView::updateSeries(const Signal *sig) {
|
||||
s.series->replace(s.vals);
|
||||
}
|
||||
}
|
||||
updateAxisY();
|
||||
}
|
||||
|
||||
// auto zoom on yaxis
|
||||
@@ -422,11 +437,39 @@ void ChartView::updateAxisY() {
|
||||
axis_y->setRange(min_y - 1, max_y + 1);
|
||||
} else {
|
||||
double range = max_y - min_y;
|
||||
axis_y->setRange(min_y - range * 0.05, max_y + range * 0.05);
|
||||
axis_y->applyNiceNumbers();
|
||||
applyNiceNumbers(min_y - range * 0.05, max_y + range * 0.05);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -66,6 +66,8 @@ private:
|
||||
void updateTitle();
|
||||
void updateFromSettings();
|
||||
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_y;
|
||||
@@ -102,17 +104,20 @@ private:
|
||||
void zoomReset();
|
||||
void updateToolBar();
|
||||
void removeAll();
|
||||
void showAllData();
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
ChartView *findChart(const QString &id, const Signal *sig);
|
||||
|
||||
QLabel *title_label;
|
||||
QLabel *range_label;
|
||||
bool docking = true;
|
||||
QAction *show_all_values_btn;
|
||||
QAction *dock_btn;
|
||||
QAction *reset_zoom_btn;
|
||||
QAction *remove_all_btn;
|
||||
QVBoxLayout *charts_layout;
|
||||
QList<ChartView *> charts;
|
||||
uint32_t max_chart_range = 0;
|
||||
bool is_zoomed = false;
|
||||
std::pair<double, double> event_range;
|
||||
std::pair<double, double> display_range;
|
||||
|
||||
Reference in New Issue
Block a user