@ -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 ( ) ;
updateDisplayRang e ( ) ;
updateStat e ( ) ;
}
}
@ -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 ) {