# include  "tools/cabana/historylog.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <functional> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <QFileDialog> 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <QPainter> 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <QVBoxLayout> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "tools/cabana/commands.h" 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "tools/cabana/utils/export.h" 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								QVariant  HistoryLogModel : : data ( const  QModelIndex  & index ,  int  role )  const  { 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  const  auto  & m  =  messages [ index . row ( ) ] ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  const  int  col  =  index . column ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( role  = =  Qt : : DisplayRole )  { 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( col  = =  0 )  return  QString : : number ( can - > toSeconds ( m . mono_time ) ,  ' f ' ,  3 ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( ! isHexMode ( ) )  return  sigs [ col  -  1 ] - > formatValue ( m . sig_values [ col  -  1 ] ,  false ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  }  else  if  ( role  = =  Qt : : TextAlignmentRole )  { 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  ( uint32_t ) ( Qt : : AlignRight  |  Qt : : AlignVCenter ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( isHexMode ( )  & &  col  = =  1 )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( role  = =  ColorsRole )  return  QVariant : : fromValue ( ( void  * ) ( & m . colors ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( role  = =  BytesRole )  return  QVariant : : fromValue ( ( void  * ) ( & m . data ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  { } ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  HistoryLogModel : : setMessage ( const  MessageId  & message_id )  { 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  msg_id  =  message_id ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  reset ( ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  HistoryLogModel : : reset ( )  { 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  beginResetModel ( ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  sigs . clear ( ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  if  ( auto  dbc_msg  =  dbc ( ) - > msg ( msg_id ) )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    sigs  =  dbc_msg - > getSignals ( ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  messages . clear ( ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  hex_colors  =  { } ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  endResetModel ( ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  setFilter ( 0 ,  " " ,  nullptr ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								QVariant  HistoryLogModel : : headerData ( int  section ,  Qt : : Orientation  orientation ,  int  role )  const  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( orientation  = =  Qt : : Horizontal )  { 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( role  = =  Qt : : DisplayRole  | |  role  = =  Qt : : ToolTipRole )  { 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      if  ( section  = =  0 )  return  " Time " ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( isHexMode ( ) )  return  " Data " ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      QString  name  =  sigs [ section  -  1 ] - > name ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      QString  unit  =  sigs [ section  -  1 ] - > unit ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  unit . isEmpty ( )  ?  name  :  QString ( " %1 (%2) " ) . arg ( name ,  unit ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  if  ( role  = =  Qt : : BackgroundRole  & &  section  >  0  & &  ! isHexMode ( ) )  { 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      // Alpha-blend the signal color with the background to ensure contrast
   
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      QColor  sigColor  =  sigs [ section  -  1 ] - > color ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      sigColor . setAlpha ( 128 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  QBrush ( sigColor ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  { } ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  HistoryLogModel : : setHexMode ( bool  hex )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  hex_mode  =  hex ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  reset ( ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  HistoryLogModel : : setFilter ( int  sig_idx ,  const  QString  & value ,  std : : function < bool ( double ,  double ) >  cmp )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  filter_sig_idx  =  sig_idx ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  filter_value  =  value . toDouble ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  filter_cmp  =  value . isEmpty ( )  ?  nullptr  :  cmp ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  updateState ( true ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  HistoryLogModel : : updateState ( bool  clear )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( clear  & &  ! messages . empty ( ) )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    beginRemoveRows ( { } ,  0 ,  messages . size ( )  -  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    messages . clear ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    endRemoveRows ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  uint64_t  current_time  =  can - > toMonoTime ( can - > lastMessage ( msg_id ) . ts )  +  1 ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  fetchData ( messages . begin ( ) ,  current_time ,  messages . empty ( )  ?  0  :  messages . front ( ) . mono_time ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								bool  HistoryLogModel : : canFetchMore ( const  QModelIndex  & parent )  const  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  auto  & events  =  can - > events ( msg_id ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  ! events . empty ( )  & &  ! messages . empty ( )  & &  messages . back ( ) . mono_time  >  events . front ( ) - > mono_time ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  HistoryLogModel : : fetchMore ( const  QModelIndex  & parent )  { 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  if  ( ! messages . empty ( ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fetchData ( messages . end ( ) ,  messages . back ( ) . mono_time ,  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  HistoryLogModel : : fetchData ( std : : deque < Message > : : iterator  insert_pos ,  uint64_t  from_time ,  uint64_t  min_time )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  auto  & events  =  can - > events ( msg_id ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  first  =  std : : upper_bound ( events . rbegin ( ) ,  events . rend ( ) ,  from_time ,  [ ] ( uint64_t  ts ,  auto  e )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  ts  >  e - > mono_time ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : vector < HistoryLogModel : : Message >  msgs ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  std : : vector < double >  values ( sigs . size ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  msgs . reserve ( batch_size ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  ( ;  first  ! =  events . rend ( )  & &  ( * first ) - > mono_time  >  min_time ;  + + first )  { 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    const  CanEvent  * e  =  * first ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  ( int  i  =  0 ;  i  <  sigs . size ( ) ;  + + i )  { 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      sigs [ i ] - > getValue ( e - > dat ,  e - > size ,  & values [ i ] ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! filter_cmp  | |  filter_cmp ( values [ filter_sig_idx ] ,  filter_value ) )  { 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								       msgs . emplace_back ( Message { e - > mono_time ,  values ,  { e - > dat ,  e - > dat  +  e - > size } } ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      if  ( msgs . size ( )  > =  batch_size  & &  min_time  = =  0 )  { 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        break ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  if  ( ! msgs . empty ( ) )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( isHexMode ( )  & &  ( min_time  >  0  | |  messages . empty ( ) ) )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      const  auto  freq  =  can - > lastMessage ( msg_id ) . freq ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      const  std : : vector < uint8_t >  no_mask ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  ( auto  & m  :  msgs )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        hex_colors . compute ( msg_id ,  m . data . data ( ) ,  m . data . size ( ) ,  m . mono_time  /  ( double ) 1e9 ,  can - > getSpeed ( ) ,  no_mask ,  freq ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        m . colors  =  hex_colors . colors ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    int  pos  =  std : : distance ( messages . begin ( ) ,  insert_pos ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    beginInsertRows ( { } ,  pos  ,  pos  +  msgs . size ( )  -  1 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    messages . insert ( insert_pos ,  std : : move_iterator ( msgs . begin ( ) ) ,  std : : move_iterator ( msgs . end ( ) ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    endInsertRows ( ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								// HeaderView
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								QSize  HeaderView : : sectionSizeFromContents ( int  logicalIndex )  const  { 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  static  const  QSize  time_col_size  =  fontMetrics ( ) . size ( Qt : : TextSingleLine ,  " 000000.000 " )  +  QSize ( 10 ,  6 ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  if  ( logicalIndex  = =  0 )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  time_col_size ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  }  else  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  default_size  =  qMax ( 100 ,  ( rect ( ) . width ( )  -  time_col_size . width ( ) )  /  ( model ( ) - > columnCount ( )  -  1 ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    QString  text  =  model ( ) - > headerData ( logicalIndex ,  this - > orientation ( ) ,  Qt : : DisplayRole ) . toString ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    const  QRect  rect  =  fontMetrics ( ) . boundingRect ( { 0 ,  0 ,  default_size ,  2000 } ,  defaultAlignment ( ) ,  text . replace ( QChar ( ' _ ' ) ,  '   ' ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    QSize  size  =  rect . size ( )  +  QSize { 10 ,  6 } ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  QSize { qMax ( size . width ( ) ,  default_size ) ,  size . height ( ) } ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  HeaderView : : paintSection ( QPainter  * painter ,  const  QRect  & rect ,  int  logicalIndex )  const  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  bg_role  =  model ( ) - > headerData ( logicalIndex ,  Qt : : Horizontal ,  Qt : : BackgroundRole ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( bg_role . isValid ( ) )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    painter - > fillRect ( rect ,  bg_role . value < QBrush > ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QString  text  =  model ( ) - > headerData ( logicalIndex ,  Qt : : Horizontal ,  Qt : : DisplayRole ) . toString ( ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  painter - > setPen ( palette ( ) . color ( settings . theme  = =  DARK_THEME  ?  QPalette : : BrightText  :  QPalette : : Text ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  painter - > drawText ( rect . adjusted ( 5 ,  3 ,  - 5 ,  - 3 ) ,  defaultAlignment ( ) ,  text . replace ( QChar ( ' _ ' ) ,  '   ' ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								// LogsWidget
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								LogsWidget : : LogsWidget ( QWidget  * parent )  :  QFrame ( parent )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  setFrameStyle ( QFrame : : StyledPanel  |  QFrame : : Plain ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  QVBoxLayout  * main_layout  =  new  QVBoxLayout ( this ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  main_layout - > setContentsMargins ( 0 ,  0 ,  0 ,  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  main_layout - > setSpacing ( 0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QWidget  * toolbar  =  new  QWidget ( this ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  toolbar - > setAutoFillBackground ( true ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QHBoxLayout  * h  =  new  QHBoxLayout ( toolbar ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  filters_widget  =  new  QWidget ( this ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QHBoxLayout  * filter_layout  =  new  QHBoxLayout ( filters_widget ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  filter_layout - > setContentsMargins ( 0 ,  0 ,  0 ,  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  filter_layout - > addWidget ( display_type_cb  =  new  QComboBox ( this ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  filter_layout - > addWidget ( signals_cb  =  new  QComboBox ( this ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  filter_layout - > addWidget ( comp_box  =  new  QComboBox ( this ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  filter_layout - > addWidget ( value_edit  =  new  QLineEdit ( this ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  h - > addWidget ( filters_widget ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  h - > addStretch ( 0 ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  export_btn  =  new  ToolButton ( " filetype-csv " ,  tr ( " Export to CSV file... " ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  h - > addWidget ( export_btn ,  0 ,  Qt : : AlignRight ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  display_type_cb - > addItems ( { " Signal " ,  " Hex " } ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  display_type_cb - > setToolTip ( tr ( " Display signal value or raw hex value " ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  comp_box - > addItems ( { " > " ,  " = " ,  " != " ,  " < " } ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  value_edit - > setClearButtonEnabled ( true ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  value_edit - > setValidator ( new  DoubleValidator ( this ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  main_layout - > addWidget ( toolbar ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QFrame  * line  =  new  QFrame ( this ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  line - > setFrameStyle ( QFrame : : HLine  |  QFrame : : Sunken ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  main_layout - > addWidget ( line ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  main_layout - > addWidget ( logs  =  new  QTableView ( this ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  logs - > setModel ( model  =  new  HistoryLogModel ( this ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  logs - > setItemDelegate ( delegate  =  new  MessageBytesDelegate ( this ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  logs - > setHorizontalHeader ( new  HeaderView ( Qt : : Horizontal ,  this ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  logs - > horizontalHeader ( ) - > setDefaultAlignment ( Qt : : AlignRight  |  ( Qt : : Alignment ) Qt : : TextWordWrap ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  logs - > horizontalHeader ( ) - > setSectionResizeMode ( QHeaderView : : ResizeToContents ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  logs - > verticalHeader ( ) - > setSectionResizeMode ( QHeaderView : : Fixed ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  logs - > verticalHeader ( ) - > setDefaultSectionSize ( delegate - > sizeForBytes ( 8 ) . height ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  logs - > setFrameShape ( QFrame : : NoFrame ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  QObject : : connect ( display_type_cb ,  qOverload < int > ( & QComboBox : : activated ) ,  model ,  & HistoryLogModel : : setHexMode ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QObject : : connect ( signals_cb ,  SIGNAL ( activated ( int ) ) ,  this ,  SLOT ( filterChanged ( ) ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QObject : : connect ( comp_box ,  SIGNAL ( activated ( int ) ) ,  this ,  SLOT ( filterChanged ( ) ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QObject : : connect ( value_edit ,  & QLineEdit : : textEdited ,  this ,  & LogsWidget : : filterChanged ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  QObject : : connect ( export_btn ,  & QToolButton : : clicked ,  this ,  & LogsWidget : : exportToCSV ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  QObject : : connect ( can ,  & AbstractStream : : seekedTo ,  model ,  & HistoryLogModel : : reset ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QObject : : connect ( dbc ( ) ,  & DBCManager : : DBCFileChanged ,  model ,  & HistoryLogModel : : reset ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QObject : : connect ( UndoStack : : instance ( ) ,  & QUndoStack : : indexChanged ,  model ,  & HistoryLogModel : : reset ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QObject : : connect ( model ,  & HistoryLogModel : : modelReset ,  this ,  & LogsWidget : : modelReset ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QObject : : connect ( model ,  & HistoryLogModel : : rowsInserted ,  [ this ] ( )  {  export_btn - > setEnabled ( true ) ;  } ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  LogsWidget : : modelReset ( )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  signals_cb - > clear ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  ( auto  s  :  model - > sigs )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    signals_cb - > addItem ( s - > name ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  export_btn - > setEnabled ( false ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  value_edit - > clear ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  comp_box - > setCurrentIndex ( 0 ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  filters_widget - > setVisible ( ! model - > sigs . empty ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  LogsWidget : : filterChanged ( )  { 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  if  ( value_edit - > text ( ) . isEmpty ( )  & &  ! value_edit - > isModified ( ) )  return ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  std : : function < bool ( double ,  double ) >  cmp  =  nullptr ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  switch  ( comp_box - > currentIndex ( ) )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  0 :  cmp  =  std : : greater < double > { } ;  break ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  1 :  cmp  =  std : : equal_to < double > { } ;  break ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    case  2 :  cmp  =  [ ] ( double  l ,  double  r )  {  return  l  ! =  r ;  } ;  break ;  // not equal
   
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    case  3 :  cmp  =  std : : less < double > { } ;  break ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  model - > setFilter ( signals_cb - > currentIndex ( ) ,  value_edit - > text ( ) ,  cmp ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  LogsWidget : : exportToCSV ( )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QString  dir  =  QString ( " %1/%2_%3.csv " ) . arg ( settings . last_dir ) . arg ( can - > routeName ( ) ) . arg ( msgName ( model - > msg_id ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  QString  fn  =  QFileDialog : : getSaveFileName ( this ,  QString ( " Export %1 to CSV file " ) . arg ( msgName ( model - > msg_id ) ) , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                            dir ,  tr ( " csv (*.csv) " ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! fn . isEmpty ( ) )  { 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    model - > isHexMode ( )  ?  utils : : exportToCSV ( fn ,  model - > msg_id ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       :  utils : : exportSignalsToCSV ( fn ,  model - > msg_id ) ; 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}