| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -3,6 +3,7 @@ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include <QButtonGroup> | 
					 | 
					 | 
					 | 
					#include <QButtonGroup> | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include <QMouseEvent> | 
					 | 
					 | 
					 | 
					#include <QMouseEvent> | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include <QPainter> | 
					 | 
					 | 
					 | 
					#include <QPainter> | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#include <QStackedLayout> | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include <QStyleOptionSlider> | 
					 | 
					 | 
					 | 
					#include <QStyleOptionSlider> | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include <QVBoxLayout> | 
					 | 
					 | 
					 | 
					#include <QVBoxLayout> | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include <QtConcurrent> | 
					 | 
					 | 
					 | 
					#include <QtConcurrent> | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -19,7 +20,6 @@ static const QColor timeline_colors[] = { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  [(int)TimelineType::AlertCritical] = QColor(199, 0, 57), | 
					 | 
					 | 
					 | 
					  [(int)TimelineType::AlertCritical] = QColor(199, 0, 57), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}; | 
					 | 
					 | 
					 | 
					}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool sortTimelineBasedOnEventPriority(const std::tuple<int, int, TimelineType> &left, const std::tuple<int, int, TimelineType> &right){ | 
					 | 
					 | 
					 | 
					bool sortTimelineBasedOnEventPriority(const std::tuple<int, int, TimelineType> &left, const std::tuple<int, int, TimelineType> &right){ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  const static std::map<TimelineType, int> timelinePriority = { | 
					 | 
					 | 
					 | 
					  const static std::map<TimelineType, int> timelinePriority = { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    {  TimelineType::None, 0 }, | 
					 | 
					 | 
					 | 
					    {  TimelineType::None, 0 }, | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -29,7 +29,6 @@ bool sortTimelineBasedOnEventPriority(const std::tuple<int, int, TimelineType> & | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    {  TimelineType::AlertCritical, 40 }, | 
					 | 
					 | 
					 | 
					    {  TimelineType::AlertCritical, 40 }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    {  TimelineType::UserFlag, 35 } | 
					 | 
					 | 
					 | 
					    {  TimelineType::UserFlag, 35 } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }; | 
					 | 
					 | 
					 | 
					  }; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return timelinePriority.at(std::get<2>(left)) < timelinePriority.at(std::get<2>(right)); | 
					 | 
					 | 
					 | 
					  return timelinePriority.at(std::get<2>(left)) < timelinePriority.at(std::get<2>(right)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -92,10 +91,14 @@ QWidget *VideoWidget::createCameraWidget() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QWidget *w = new QWidget(this); | 
					 | 
					 | 
					 | 
					  QWidget *w = new QWidget(this); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QVBoxLayout *l = new QVBoxLayout(w); | 
					 | 
					 | 
					 | 
					  QVBoxLayout *l = new QVBoxLayout(w); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  l->setContentsMargins(0, 0, 0, 0); | 
					 | 
					 | 
					 | 
					  l->setContentsMargins(0, 0, 0, 0); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  cam_widget = new CameraWidget("camerad", can->visionStreamType(), false); | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  QStackedLayout *stacked = new QStackedLayout(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  stacked->setStackingMode(QStackedLayout::StackAll); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  stacked->addWidget(cam_widget = new CameraWidget("camerad", can->visionStreamType(), false)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  cam_widget->setMinimumHeight(MIN_VIDEO_HEIGHT); | 
					 | 
					 | 
					 | 
					  cam_widget->setMinimumHeight(MIN_VIDEO_HEIGHT); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  cam_widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); | 
					 | 
					 | 
					 | 
					  cam_widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  l->addWidget(cam_widget); | 
					 | 
					 | 
					 | 
					  stacked->addWidget(alert_label = new InfoLabel(this)); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  l->addLayout(stacked); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // slider controls
 | 
					 | 
					 | 
					 | 
					  // slider controls
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  slider_layout = new QHBoxLayout(); | 
					 | 
					 | 
					 | 
					  slider_layout = new QHBoxLayout(); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -130,9 +133,18 @@ void VideoWidget::rangeChanged(double min, double max, bool is_zoomed) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void VideoWidget::updateState() { | 
					 | 
					 | 
					 | 
					void VideoWidget::updateState() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!slider->isSliderDown()) | 
					 | 
					 | 
					 | 
					  if (!slider->isSliderDown()) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    slider->setValue(can->currentSec() * 1000); | 
					 | 
					 | 
					 | 
					    slider->setValue(can->currentSec() * 1000); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  std::lock_guard lk(slider->thumbnail_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  uint64_t mono_time = (can->currentSec() + can->routeStartTime()) * 1e9; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  auto it = slider->alerts.lower_bound(mono_time); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (it != slider->alerts.end() && (it->first - mono_time) < 1e9) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    alert_label->showAlert(it->second); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    alert_label->showAlert({}); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void VideoWidget::updatePlayBtnState() { | 
					 | 
					 | 
					 | 
					void VideoWidget::updatePlayBtnState() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  play_btn->setIcon(utils::icon(can->isPaused() ? "play" : "pause")); | 
					 | 
					 | 
					 | 
					  play_btn->setIcon(utils::icon(can->isPaused() ? "play" : "pause")); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -144,7 +156,6 @@ Slider::Slider(QWidget *parent) : timer(this), thumbnail_label(this), QSlider(Qt | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  timer.callOnTimeout([this]() { | 
					 | 
					 | 
					 | 
					  timer.callOnTimeout([this]() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    timeline = can->getTimeline(); | 
					 | 
					 | 
					 | 
					    timeline = can->getTimeline(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    std::sort(timeline.begin(), timeline.end(), sortTimelineBasedOnEventPriority); | 
					 | 
					 | 
					 | 
					    std::sort(timeline.begin(), timeline.end(), sortTimelineBasedOnEventPriority); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    update(); | 
					 | 
					 | 
					 | 
					    update(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }); | 
					 | 
					 | 
					 | 
					  }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  setMouseTracking(true); | 
					 | 
					 | 
					 | 
					  setMouseTracking(true); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -169,11 +180,11 @@ void Slider::streamStarted() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void Slider::loadThumbnails() { | 
					 | 
					 | 
					 | 
					void Slider::loadThumbnails() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  const auto &segments = can->route()->segments(); | 
					 | 
					 | 
					 | 
					  const auto &segments = can->route()->segments(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (auto it = segments.rbegin(); it != segments.rend() && !abort_load_thumbnail; ++it) { | 
					 | 
					 | 
					 | 
					  for (auto it = segments.rbegin(); it != segments.rend() && !abort_load_thumbnail; ++it) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    std::string qlog = it->second.qlog.toStdString(); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (!qlog.empty()) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LogReader log; | 
					 | 
					 | 
					 | 
					    LogReader log; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (log.load(qlog, &abort_load_thumbnail, {cereal::Event::Which::THUMBNAIL}, true, 0, 3)) { | 
					 | 
					 | 
					 | 
					    std::string qlog = it->second.qlog.toStdString(); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (!qlog.empty() && log.load(qlog, &abort_load_thumbnail, {cereal::Event::Which::THUMBNAIL, cereal::Event::Which::CONTROLS_STATE}, true, 0, 3)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      for (auto ev = log.events.cbegin(); ev != log.events.cend() && !abort_load_thumbnail; ++ev) { | 
					 | 
					 | 
					 | 
					      for (auto ev = log.events.cbegin(); ev != log.events.cend() && !abort_load_thumbnail; ++ev) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        if ((*ev)->which == cereal::Event::Which::THUMBNAIL) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          auto thumb = (*ev)->event.getThumbnail(); | 
					 | 
					 | 
					 | 
					          auto thumb = (*ev)->event.getThumbnail(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          auto data = thumb.getThumbnail(); | 
					 | 
					 | 
					 | 
					          auto data = thumb.getThumbnail(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          if (QPixmap pm; pm.loadFromData(data.begin(), data.size(), "jpeg")) { | 
					 | 
					 | 
					 | 
					          if (QPixmap pm; pm.loadFromData(data.begin(), data.size(), "jpeg")) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -181,6 +192,12 @@ void Slider::loadThumbnails() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            std::lock_guard lk(thumbnail_lock); | 
					 | 
					 | 
					 | 
					            std::lock_guard lk(thumbnail_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            thumbnails[thumb.getTimestampEof()] = pm; | 
					 | 
					 | 
					 | 
					            thumbnails[thumb.getTimestampEof()] = pm; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          } | 
					 | 
					 | 
					 | 
					          } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        } else if ((*ev)->which == cereal::Event::Which::CONTROLS_STATE) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          auto cs = (*ev)->event.getControlsState(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          if (cs.getAlertType().size() > 0 && cs.getAlertText1().size() > 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            std::lock_guard lk(thumbnail_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            alerts.emplace((*ev)->mono_time, AlertInfo{cs.getAlertStatus(), cs.getAlertText1().cStr(), cs.getAlertText2().cStr()}); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        } | 
					 | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      } | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -234,15 +251,21 @@ void Slider::mousePressEvent(QMouseEvent *e) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void Slider::mouseMoveEvent(QMouseEvent *e) { | 
					 | 
					 | 
					 | 
					void Slider::mouseMoveEvent(QMouseEvent *e) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QPixmap thumb; | 
					 | 
					 | 
					 | 
					  QPixmap thumb; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  AlertInfo alert; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  double seconds = (minimum() + e->pos().x() * ((maximum() - minimum()) / (double)width())) / 1000.0; | 
					 | 
					 | 
					 | 
					  double seconds = (minimum() + e->pos().x() * ((maximum() - minimum()) / (double)width())) / 1000.0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  { | 
					 | 
					 | 
					 | 
					  { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    std::lock_guard lk(thumbnail_lock); | 
					 | 
					 | 
					 | 
					    std::lock_guard lk(thumbnail_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    auto it = thumbnails.lowerBound((seconds + can->routeStartTime()) * 1e9); | 
					 | 
					 | 
					 | 
					    uint64_t mono_time = (seconds + can->routeStartTime()) * 1e9; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    auto it = thumbnails.lowerBound(mono_time); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (it != thumbnails.end()) thumb = it.value(); | 
					 | 
					 | 
					 | 
					    if (it != thumbnails.end()) thumb = it.value(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    auto alert_it = alerts.lower_bound(mono_time); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (alert_it != alerts.end() && (alert_it->first - mono_time) < 1e9) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      alert = alert_it->second; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int x = std::clamp(e->pos().x() - thumb.width() / 2, THUMBNAIL_MARGIN, rect().right() - thumb.width() - THUMBNAIL_MARGIN); | 
					 | 
					 | 
					 | 
					  int x = std::clamp(e->pos().x() - thumb.width() / 2, THUMBNAIL_MARGIN, rect().right() - thumb.width() - THUMBNAIL_MARGIN); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int y = -thumb.height() - THUMBNAIL_MARGIN - style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing); | 
					 | 
					 | 
					 | 
					  int y = -thumb.height() - THUMBNAIL_MARGIN - style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  thumbnail_label.showPixmap(mapToGlobal({x, y}), utils::formatSeconds(seconds), thumb); | 
					 | 
					 | 
					 | 
					  thumbnail_label.showPixmap(mapToGlobal({x, y}), utils::formatSeconds(seconds), thumb, alert); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QSlider::mouseMoveEvent(e); | 
					 | 
					 | 
					 | 
					  QSlider::mouseMoveEvent(e); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -251,16 +274,17 @@ void Slider::leaveEvent(QEvent *event) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QSlider::leaveEvent(event); | 
					 | 
					 | 
					 | 
					  QSlider::leaveEvent(event); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// ThumbnailLabel
 | 
					 | 
					 | 
					 | 
					// InfoLabel
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					ThumbnailLabel::ThumbnailLabel(QWidget *parent) : QWidget(parent, Qt::Tool | Qt::FramelessWindowHint) { | 
					 | 
					 | 
					 | 
					InfoLabel::InfoLabel(QWidget *parent) : QWidget(parent, Qt::Tool | Qt::FramelessWindowHint) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  setAttribute(Qt::WA_ShowWithoutActivating); | 
					 | 
					 | 
					 | 
					  setAttribute(Qt::WA_ShowWithoutActivating); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  setVisible(false); | 
					 | 
					 | 
					 | 
					  setVisible(false); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void ThumbnailLabel::showPixmap(const QPoint &pt, const QString &sec, const QPixmap &pm) { | 
					 | 
					 | 
					 | 
					void InfoLabel::showPixmap(const QPoint &pt, const QString &sec, const QPixmap &pm, const AlertInfo &alert) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  pixmap = pm; | 
					 | 
					 | 
					 | 
					  pixmap = pm; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  second = sec; | 
					 | 
					 | 
					 | 
					  second = sec; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  alert_info = alert; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  setVisible(!pm.isNull()); | 
					 | 
					 | 
					 | 
					  setVisible(!pm.isNull()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (isVisible()) { | 
					 | 
					 | 
					 | 
					  if (isVisible()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    setGeometry({pt, pm.size()}); | 
					 | 
					 | 
					 | 
					    setGeometry({pt, pm.size()}); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -268,10 +292,42 @@ void ThumbnailLabel::showPixmap(const QPoint &pt, const QString &sec, const QPix | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void ThumbnailLabel::paintEvent(QPaintEvent *event) { | 
					 | 
					 | 
					 | 
					void InfoLabel::showAlert(const AlertInfo &alert) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  alert_info = alert; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  pixmap = {}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  setVisible(!alert_info.text1.isEmpty()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (isVisible()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    update(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					void InfoLabel::paintEvent(QPaintEvent *event) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  QPainter p(this); | 
					 | 
					 | 
					 | 
					  QPainter p(this); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  p.drawPixmap(0, 0, pixmap); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  p.setPen(QPen(Qt::white, 2)); | 
					 | 
					 | 
					 | 
					  p.setPen(QPen(Qt::white, 2)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (!pixmap.isNull()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    p.drawPixmap(0, 0, pixmap); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    p.drawRect(rect()); | 
					 | 
					 | 
					 | 
					    p.drawRect(rect()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    p.drawText(rect().adjusted(0, 0, 0, -THUMBNAIL_MARGIN), second, Qt::AlignHCenter | Qt::AlignBottom); | 
					 | 
					 | 
					 | 
					    p.drawText(rect().adjusted(0, 0, 0, -THUMBNAIL_MARGIN), second, Qt::AlignHCenter | Qt::AlignBottom); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (alert_info.text1.size() > 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    QColor color = timeline_colors[(int)TimelineType::AlertInfo]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (alert_info.status == cereal::ControlsState::AlertStatus::USER_PROMPT) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      color = timeline_colors[(int)TimelineType::AlertWarning]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } else if (alert_info.status == cereal::ControlsState::AlertStatus::CRITICAL) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      color = timeline_colors[(int)TimelineType::AlertCritical]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    color.setAlphaF(0.5); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    QString text = alert_info.text1; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (!alert_info.text2.isEmpty()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      text += "\n" + alert_info.text2; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    QFont font; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    font.setPixelSize(!pixmap.isNull() ? 11 : QFont().pixelSize()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    p.setFont(font); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    QRect text_rect = rect().adjusted(2, 2, -2, -2); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    QRect r = p.fontMetrics().boundingRect(text_rect, Qt::AlignTop | Qt::AlignHCenter | Qt::TextWordWrap, text); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    p.fillRect(text_rect.left(), r.top(), text_rect.width(), r.height(), color); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    p.drawText(text_rect, Qt::AlignTop | Qt::AlignHCenter | Qt::TextWordWrap, text); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
					 | 
					 | 
					
  |