3
3
#include < QFutureSynchronizer>
4
4
#include < QGraphicsLayout>
5
5
#include < QRubberBand>
6
- #include < QTimer>
7
6
#include < QToolBar>
8
7
#include < QToolButton>
9
8
#include < QtConcurrent>
@@ -19,14 +18,14 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
19
18
title_label = new QLabel ();
20
19
title_label->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Preferred);
21
20
toolbar->addWidget (title_label);
21
+ show_all_values_btn = toolbar->addAction (" " );
22
22
toolbar->addWidget (range_label = new QLabel ());
23
23
reset_zoom_btn = toolbar->addAction (" ⟲" );
24
24
reset_zoom_btn->setToolTip (tr (" Reset zoom (drag on chart to zoom X-Axis)" ));
25
25
remove_all_btn = toolbar->addAction (" ✖" );
26
26
remove_all_btn->setToolTip (tr (" Remove all charts" ));
27
27
dock_btn = toolbar->addAction (" " );
28
28
main_layout->addWidget (toolbar);
29
- updateToolBar ();
30
29
31
30
// charts
32
31
QWidget *charts_container = new QWidget (this );
@@ -37,14 +36,16 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
37
36
charts_scroll->setWidgetResizable (true );
38
37
charts_scroll->setWidget (charts_container);
39
38
charts_scroll->setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
40
-
41
39
main_layout->addWidget (charts_scroll);
42
40
41
+ max_chart_range = settings.max_chart_x_range ;
43
42
use_dark_theme = palette ().color (QPalette::WindowText).value () > palette ().color (QPalette::Background).value ();
43
+ updateToolBar ();
44
44
45
45
QObject::connect (dbc (), &DBCManager::DBCFileChanged, this , &ChartsWidget::removeAll);
46
46
QObject::connect (can, &CANMessages::eventsMerged, this , &ChartsWidget::eventsMerged);
47
47
QObject::connect (can, &CANMessages::updated, this , &ChartsWidget::updateState);
48
+ QObject::connect (show_all_values_btn, &QAction::triggered, this , &ChartsWidget::showAllData);
48
49
QObject::connect (remove_all_btn, &QAction::triggered, this , &ChartsWidget::removeAll);
49
50
QObject::connect (reset_zoom_btn, &QAction::triggered, this , &ChartsWidget::zoomReset);
50
51
QObject::connect (dock_btn, &QAction::triggered, [this ]() {
@@ -58,7 +59,7 @@ void ChartsWidget::eventsMerged() {
58
59
if (auto events = can->events (); events && !events->empty ()) {
59
60
event_range.first = (events->front ()->mono_time / (double )1e9 ) - can->routeStartTime ();
60
61
event_range.second = (events->back ()->mono_time / (double )1e9 ) - can->routeStartTime ();
61
- updateDisplayRange ();
62
+ updateState ();
62
63
}
63
64
}
64
65
@@ -69,8 +70,8 @@ void ChartsWidget::updateDisplayRange() {
69
70
// reached the end, or seeked to a timestamp out of range.
70
71
display_range.first = current_sec - 5 ;
71
72
}
72
- display_range.first = std::max (display_range.first , event_range.first );
73
- display_range.second = std::min (display_range.first + settings. max_chart_x_range , event_range.second );
73
+ display_range.first = std::floor ( std:: max (display_range.first , event_range.first ) * 10.0 ) / 10.0 ;
74
+ display_range.second = std::floor ( std:: min (display_range.first + max_chart_range , event_range.second ) * 10.0 ) / 10.0 ;
74
75
if (prev_range != display_range) {
75
76
QFutureSynchronizer<void > future_synchronizer;
76
77
for (auto c : charts)
@@ -100,13 +101,29 @@ void ChartsWidget::updateState() {
100
101
}
101
102
102
103
const auto &range = is_zoomed ? zoomed_range : display_range;
104
+ setUpdatesEnabled (false );
103
105
for (auto c : charts) {
104
106
c->setDisplayRange (range.first , range.second );
105
107
c->scene ()->invalidate ({}, QGraphicsScene::ForegroundLayer);
106
108
}
109
+ setUpdatesEnabled (true );
110
+ }
111
+
112
+ void ChartsWidget::showAllData () {
113
+ bool switch_to_show_all = max_chart_range == settings.max_chart_x_range ;
114
+ max_chart_range = switch_to_show_all ? settings.cached_segment_limit * 60
115
+ : settings.max_chart_x_range ;
116
+ max_chart_range = std::min (max_chart_range, (uint32_t )can->totalSeconds ());
117
+ updateToolBar ();
118
+ updateState ();
107
119
}
108
120
109
121
void ChartsWidget::updateToolBar () {
122
+ int min_range = std::min (settings.max_chart_x_range , (int )can->totalSeconds ());
123
+ bool displaying_all = max_chart_range != min_range;
124
+ show_all_values_btn->setText (tr (" %1 minutes" ).arg (max_chart_range / 60 ));
125
+ show_all_values_btn->setToolTip (tr (" Click to display %1 data" ).arg (displaying_all ? tr (" %1 minutes" ).arg (min_range / 60 ) : tr (" ALL cached" )));
126
+ show_all_values_btn->setVisible (!is_zoomed);
110
127
remove_all_btn->setEnabled (!charts.isEmpty ());
111
128
reset_zoom_btn->setEnabled (is_zoomed);
112
129
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) {
232
249
sigs.push_back ({.msg_id = msg_id, .address = address, .source = source, .sig = sig, .series = series});
233
250
updateTitle ();
234
251
updateSeries (sig);
252
+ updateAxisY ();
235
253
}
236
254
237
255
void ChartView::removeSeries (const QString &msg_id, const Signal *sig) {
@@ -242,8 +260,7 @@ void ChartView::removeSeries(const QString &msg_id, const Signal *sig) {
242
260
}
243
261
244
262
bool ChartView::hasSeries (const QString &msg_id, const Signal *sig) const {
245
- auto it = std::find_if (sigs.begin (), sigs.end (), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; });
246
- return it != sigs.end ();
263
+ return std::any_of (sigs.begin (), sigs.end (), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; });
247
264
}
248
265
249
266
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
261
278
}
262
279
263
280
void ChartView::signalUpdated (const Signal *sig) {
264
- auto it = std::find_if (sigs.begin (), sigs.end (), [=](auto &s) { return s.sig == sig; });
265
- if (it != sigs.end ()) {
281
+ if (std::any_of (sigs.begin (), sigs.end (), [=](auto &s) { return s.sig == sig; })) {
266
282
updateTitle ();
267
283
// TODO: don't update series if only name changed.
268
284
updateSeries (sig);
285
+ updateAxisY ();
269
286
}
270
287
}
271
288
@@ -276,8 +293,7 @@ void ChartView::signalRemoved(const Signal *sig) {
276
293
}
277
294
278
295
void ChartView::msgUpdated (uint32_t address) {
279
- auto it = std::find_if (sigs.begin (), sigs.end (), [=](auto &s) { return s.address == address; });
280
- if (it != sigs.end ())
296
+ if (std::any_of (sigs.begin (), sigs.end (), [=](auto &s) { return s.address == address; }))
281
297
updateTitle ();
282
298
}
283
299
@@ -392,7 +408,6 @@ void ChartView::updateSeries(const Signal *sig) {
392
408
s.series ->replace (s.vals );
393
409
}
394
410
}
395
- updateAxisY ();
396
411
}
397
412
398
413
// auto zoom on yaxis
@@ -422,11 +437,39 @@ void ChartView::updateAxisY() {
422
437
axis_y->setRange (min_y - 1 , max_y + 1 );
423
438
} else {
424
439
double range = max_y - min_y;
425
- axis_y->setRange (min_y - range * 0.05 , max_y + range * 0.05 );
426
- axis_y->applyNiceNumbers ();
440
+ applyNiceNumbers (min_y - range * 0.05 , max_y + range * 0.05 );
427
441
}
428
442
429
- QTimer::singleShot (0 , this , &ChartView::adjustChartMargins);
443
+ adjustChartMargins ();
444
+ }
445
+
446
+ void ChartView::applyNiceNumbers (qreal min, qreal max) {
447
+ int tick_count = axis_y->tickCount ();
448
+ qreal range = niceNumber ((max - min), true ); // range with ceiling
449
+ qreal step = niceNumber (range / (tick_count - 1 ), false );
450
+ min = qFloor (min / step);
451
+ max = qCeil (max / step);
452
+ tick_count = int (max - min) + 1 ;
453
+ axis_y->setRange (min * step, max * step);
454
+ axis_y->setTickCount (tick_count);
455
+ }
456
+
457
+ // nice numbers can be expressed as form of 1*10^n, 2* 10^n or 5*10^n
458
+ qreal ChartView::niceNumber (qreal x, bool ceiling) {
459
+ qreal z = qPow (10 , qFloor (std::log10 (x))); // find corresponding number of the form of 10^n than is smaller than x
460
+ qreal q = x / z; // q<10 && q>=1;
461
+ if (ceiling) {
462
+ if (q <= 1.0 ) q = 1 ;
463
+ else if (q <= 2.0 ) q = 2 ;
464
+ else if (q <= 5.0 ) q = 5 ;
465
+ else q = 10 ;
466
+ } else {
467
+ if (q < 1.5 ) q = 1 ;
468
+ else if (q < 3.0 ) q = 2 ;
469
+ else if (q < 7.0 ) q = 5 ;
470
+ else q = 10 ;
471
+ }
472
+ return q * z;
430
473
}
431
474
432
475
void ChartView::leaveEvent (QEvent *event) {
0 commit comments