@ -1,4 +1,4 @@
# include "tools/cabana/signaledit .h"
# include "tools/cabana/signalview .h"
# include <QApplication>
# include <QCompleter>
@ -366,17 +366,15 @@ void SignalItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
void SignalItemDelegate : : drawSparkline ( QPainter * painter , const QStyleOptionViewItem & option , const QModelIndex & index ) const {
static std : : vector < QPointF > points ;
// TODO: get seconds from settings.
const uint64_t chart_seconds = 15 ; // seconds
const auto & msg_id = ( ( SignalView * ) parent ( ) ) - > msg_id ;
const auto & msgs = can - > events ( ) . at ( msg_id ) ;
uint64_t ts = ( can - > lastMessage ( msg_id ) . ts + can - > routeStartTime ( ) ) * 1e9 ;
auto first = std : : lower_bound ( msgs . cbegin ( ) , msgs . cend ( ) , CanEvent { . mono_time = ( uint64_t ) std : : max < int64_t > ( ts - chart_seconds * 1e9 , 0 ) } ) ;
if ( first ! = msgs . cend ( ) ) {
auto first = std : : lower_bound ( msgs . cbegin ( ) , msgs . cend ( ) , CanEvent { . mono_time = ( uint64_t ) std : : max < int64_t > ( ts - settings . sparkline_range * 1e9 , 0 ) } ) ;
auto last = std : : upper_bound ( first , msgs . cend ( ) , CanEvent { . mono_time = ts } ) ;
if ( first ! = last ) {
double min = std : : numeric_limits < double > : : max ( ) ;
double max = std : : numeric_limits < double > : : lowest ( ) ;
const auto sig = ( ( SignalModel : : Item * ) index . internalPointer ( ) ) - > sig ;
auto last = std : : lower_bound ( first , msgs . cend ( ) , CanEvent { . mono_time = ts } ) ;
points . clear ( ) ;
for ( auto it = first ; it ! = last ; + + it ) {
double value = get_raw_value ( it - > dat , it - > size , * sig ) ;
@ -391,7 +389,7 @@ void SignalItemDelegate::drawSparkline(QPainter *painter, const QStyleOptionView
int h_margin = option . widget - > style ( ) - > pixelMetric ( QStyle : : PM_FocusFrameHMargin ) ;
int v_margin = std : : max ( option . widget - > style ( ) - > pixelMetric ( QStyle : : PM_FocusFrameVMargin ) + 2 , 4 ) ;
const double xscale = ( option . rect . width ( ) - 175.0 * option . widget - > devicePixelRatioF ( ) - h_margin * 2 ) / chart_seconds ;
const double xscale = ( option . rect . width ( ) - 175.0 * option . widget - > devicePixelRatioF ( ) - h_margin * 2 ) / settings . sparkline_range ;
const double yscale = ( option . rect . height ( ) - v_margin * 2 ) / ( max - min ) ;
const int left = option . rect . left ( ) ;
const int top = option . rect . top ( ) + v_margin ;
@ -401,6 +399,13 @@ void SignalItemDelegate::drawSparkline(QPainter *painter, const QStyleOptionView
}
painter - > setPen ( getColor ( sig ) ) ;
painter - > drawPolyline ( points . data ( ) , points . size ( ) ) ;
if ( ( points . back ( ) . x ( ) - points . front ( ) . x ( ) ) / points . size ( ) > 10 ) {
painter - > setPen ( Qt : : NoPen ) ;
painter - > setBrush ( getColor ( sig ) ) ;
for ( const auto & pt : points ) {
painter - > drawEllipse ( pt , 2 , 2 ) ;
}
}
}
}
@ -451,6 +456,17 @@ SignalView::SignalView(ChartsWidget *charts, QWidget *parent) : charts(charts),
filter_edit - > setPlaceholderText ( tr ( " filter signals " ) ) ;
hl - > addWidget ( filter_edit ) ;
hl - > addStretch ( 1 ) ;
// WARNING: increasing the maximum range can result in severe performance degradation.
// 30s is a reasonable value at present.
const int max_range = 30 ; // 30s
settings . sparkline_range = std : : clamp ( settings . sparkline_range , 1 , max_range ) ;
hl - > addWidget ( sparkline_label = new QLabel ( ) ) ;
hl - > addWidget ( sparkline_range_slider = new QSlider ( Qt : : Horizontal , this ) ) ;
sparkline_range_slider - > setRange ( 1 , max_range ) ;
sparkline_range_slider - > setValue ( settings . sparkline_range ) ;
sparkline_range_slider - > setToolTip ( tr ( " Sparkline time range " ) ) ;
auto collapse_btn = toolButton ( " dash-square " , tr ( " Collapse All " ) ) ;
collapse_btn - > setIconSize ( { 12 , 12 } ) ;
hl - > addWidget ( collapse_btn ) ;
@ -473,8 +489,10 @@ SignalView::SignalView(ChartsWidget *charts, QWidget *parent) : charts(charts),
main_layout - > setSpacing ( 0 ) ;
main_layout - > addWidget ( title_bar ) ;
main_layout - > addWidget ( tree ) ;
updateToolBar ( ) ;
QObject : : connect ( filter_edit , & QLineEdit : : textEdited , model , & SignalModel : : setFilter ) ;
QObject : : connect ( sparkline_range_slider , & QSlider : : valueChanged , this , & SignalView : : setSparklineRange ) ;
QObject : : connect ( collapse_btn , & QPushButton : : clicked , tree , & QTreeView : : collapseAll ) ;
QObject : : connect ( tree , & QAbstractItemView : : clicked , this , & SignalView : : rowClicked ) ;
QObject : : connect ( tree , & QTreeView : : viewportEntered , [ this ] ( ) { emit highlight ( nullptr ) ; } ) ;
@ -521,7 +539,7 @@ void SignalView::rowsChanged() {
} ) ;
}
}
signal_count_lb - > setText ( tr ( " Signals: %1 " ) . arg ( model - > rowCount ( ) ) ) ;
updateToolBar ( ) ;
updateChartState ( ) ;
}
@ -569,6 +587,17 @@ void SignalView::signalHovered(const cabana::Signal *sig) {
}
}
void SignalView : : updateToolBar ( ) {
signal_count_lb - > setText ( tr ( " Signals: %1 " ) . arg ( model - > rowCount ( ) ) ) ;
sparkline_label - > setText ( QString ( " Range: %1 " ) . arg ( utils : : formatSeconds ( settings . sparkline_range ) ) ) ;
}
void SignalView : : setSparklineRange ( int value ) {
settings . sparkline_range = value ;
updateToolBar ( ) ;
model - > updateState ( nullptr ) ;
}
void SignalView : : leaveEvent ( QEvent * event ) {
emit highlight ( nullptr ) ;
QWidget : : leaveEvent ( event ) ;