|  |  |  | @ -33,11 +33,9 @@ VideoWidget::VideoWidget(QWidget *parent) : QFrame(parent) { | 
			
		
	
		
			
				
					|  |  |  |  |   main_layout->addLayout(createPlaybackController()); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   QObject::connect(can, &AbstractStream::paused, this, &VideoWidget::updatePlayBtnState); | 
			
		
	
		
			
				
					|  |  |  |  |   QObject::connect(can, &AbstractStream::resume, this, &VideoWidget::updatePlayBtnState); | 
			
		
	
		
			
				
					|  |  |  |  |   QObject::connect(can, &AbstractStream::updated, this, &VideoWidget::updateState); | 
			
		
	
		
			
				
					|  |  |  |  |   QObject::connect(&settings, &Settings::changed, this, &VideoWidget::updatePlayBtnState); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   updatePlayBtnState(); | 
			
		
	
		
			
				
					|  |  |  |  |   setWhatsThis(tr(R"( | 
			
		
	
	
		
			
				
					|  |  |  | @ -131,10 +129,15 @@ QWidget *VideoWidget::createCameraWidget() { | 
			
		
	
		
			
				
					|  |  |  |  |   QWidget *w = new QWidget(this); | 
			
		
	
		
			
				
					|  |  |  |  |   QVBoxLayout *l = new QVBoxLayout(w); | 
			
		
	
		
			
				
					|  |  |  |  |   l->setContentsMargins(0, 0, 0, 0); | 
			
		
	
		
			
				
					|  |  |  |  |   l->setSpacing(0); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   l->addWidget(camera_tab = new TabBar(w)); | 
			
		
	
		
			
				
					|  |  |  |  |   camera_tab->setAutoHide(true); | 
			
		
	
		
			
				
					|  |  |  |  |   camera_tab->setExpanding(false); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   QStackedLayout *stacked = new QStackedLayout(); | 
			
		
	
		
			
				
					|  |  |  |  |   stacked->setStackingMode(QStackedLayout::StackAll); | 
			
		
	
		
			
				
					|  |  |  |  |   stacked->addWidget(cam_widget = new CameraWidget("camerad", can->visionStreamType(), false)); | 
			
		
	
		
			
				
					|  |  |  |  |   stacked->addWidget(cam_widget = new CameraWidget("camerad", VISION_STREAM_ROAD, false)); | 
			
		
	
		
			
				
					|  |  |  |  |   cam_widget->setMinimumHeight(MIN_VIDEO_HEIGHT); | 
			
		
	
		
			
				
					|  |  |  |  |   cam_widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); | 
			
		
	
		
			
				
					|  |  |  |  |   stacked->addWidget(alert_label = new InfoLabel(this)); | 
			
		
	
	
		
			
				
					|  |  |  | @ -146,11 +149,34 @@ QWidget *VideoWidget::createCameraWidget() { | 
			
		
	
		
			
				
					|  |  |  |  |   setMaximumTime(can->totalSeconds()); | 
			
		
	
		
			
				
					|  |  |  |  |   QObject::connect(slider, &QSlider::sliderReleased, [this]() { can->seekTo(slider->currentSecond()); }); | 
			
		
	
		
			
				
					|  |  |  |  |   QObject::connect(slider, &Slider::updateMaximumTime, this, &VideoWidget::setMaximumTime, Qt::QueuedConnection); | 
			
		
	
		
			
				
					|  |  |  |  |   QObject::connect(cam_widget, &CameraWidget::clicked, []() { can->pause(!can->isPaused()); }); | 
			
		
	
		
			
				
					|  |  |  |  |   QObject::connect(static_cast<ReplayStream*>(can), &ReplayStream::qLogLoaded, slider, &Slider::parseQLog); | 
			
		
	
		
			
				
					|  |  |  |  |   QObject::connect(cam_widget, &CameraWidget::clicked, []() { can->pause(!can->isPaused()); }); | 
			
		
	
		
			
				
					|  |  |  |  |   QObject::connect(cam_widget, &CameraWidget::vipcAvailableStreamsUpdated, this, &VideoWidget::vipcAvailableStreamsUpdated); | 
			
		
	
		
			
				
					|  |  |  |  |   QObject::connect(camera_tab, &QTabBar::currentChanged, [this](int index) { | 
			
		
	
		
			
				
					|  |  |  |  |     if (index != -1) cam_widget->setStreamType((VisionStreamType)camera_tab->tabData(index).toInt()); | 
			
		
	
		
			
				
					|  |  |  |  |   }); | 
			
		
	
		
			
				
					|  |  |  |  |   return w; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void VideoWidget::vipcAvailableStreamsUpdated(std::set<VisionStreamType> streams) { | 
			
		
	
		
			
				
					|  |  |  |  |   static const QString stream_names[] = { | 
			
		
	
		
			
				
					|  |  |  |  |     [VISION_STREAM_ROAD] = "Road camera", | 
			
		
	
		
			
				
					|  |  |  |  |     [VISION_STREAM_WIDE_ROAD] = "Wide road camera", | 
			
		
	
		
			
				
					|  |  |  |  |     [VISION_STREAM_DRIVER] = "Driver camera"}; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   for (int i = 0; i < streams.size(); ++i) { | 
			
		
	
		
			
				
					|  |  |  |  |     if (camera_tab->count() <= i) { | 
			
		
	
		
			
				
					|  |  |  |  |       camera_tab->addTab(QString()); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     int type = *std::next(streams.begin(), i); | 
			
		
	
		
			
				
					|  |  |  |  |     camera_tab->setTabText(i, stream_names[type]); | 
			
		
	
		
			
				
					|  |  |  |  |     camera_tab->setTabData(i, type); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |   while (camera_tab->count() > streams.size()) { | 
			
		
	
		
			
				
					|  |  |  |  |     camera_tab->removeTab(camera_tab->count() - 1); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | void VideoWidget::loopPlaybackClicked() { | 
			
		
	
		
			
				
					|  |  |  |  |   auto replay = qobject_cast<ReplayStream *>(can)->getReplay(); | 
			
		
	
		
			
				
					|  |  |  |  |   if (replay->hasFlag(REPLAY_FLAG_NO_LOOP)) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -172,12 +198,8 @@ void VideoWidget::updateTimeRange(double min, double max, bool is_zoomed) { | 
			
		
	
		
			
				
					|  |  |  |  |     skip_to_end_btn->setEnabled(!is_zoomed); | 
			
		
	
		
			
				
					|  |  |  |  |     return; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   if (!is_zoomed) { | 
			
		
	
		
			
				
					|  |  |  |  |     min = 0; | 
			
		
	
		
			
				
					|  |  |  |  |     max = maximum_time; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |   slider->setTimeRange(min, max); | 
			
		
	
		
			
				
					|  |  |  |  |   is_zoomed ? slider->setTimeRange(min, max) | 
			
		
	
		
			
				
					|  |  |  |  |             : slider->setTimeRange(0, maximum_time); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | QString VideoWidget::formatTime(double sec, bool include_milliseconds) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -262,7 +284,7 @@ void Slider::paintEvent(QPaintEvent *ev) { | 
			
		
	
		
			
				
					|  |  |  |  |   double min = minimum() / factor; | 
			
		
	
		
			
				
					|  |  |  |  |   double max = maximum() / factor; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   for (auto [begin, end, type] : qobject_cast<ReplayStream *>(can)->getTimeline()) { | 
			
		
	
		
			
				
					|  |  |  |  |   for (auto [begin, end, type] : qobject_cast<ReplayStream *>(can)->getReplay()->getTimeline()) { | 
			
		
	
		
			
				
					|  |  |  |  |     if (begin > max || end < min) | 
			
		
	
		
			
				
					|  |  |  |  |       continue; | 
			
		
	
		
			
				
					|  |  |  |  |     r.setLeft(((std::max(min, begin) - min) / (max - min)) * width()); | 
			
		
	
	
		
			
				
					|  |  |  | @ -282,8 +304,7 @@ void Slider::paintEvent(QPaintEvent *ev) { | 
			
		
	
		
			
				
					|  |  |  |  | void Slider::mousePressEvent(QMouseEvent *e) { | 
			
		
	
		
			
				
					|  |  |  |  |   QSlider::mousePressEvent(e); | 
			
		
	
		
			
				
					|  |  |  |  |   if (e->button() == Qt::LeftButton && !isSliderDown()) { | 
			
		
	
		
			
				
					|  |  |  |  |     int value = minimum() + ((maximum() - minimum()) * e->x()) / width(); | 
			
		
	
		
			
				
					|  |  |  |  |     setValue(value); | 
			
		
	
		
			
				
					|  |  |  |  |     setValue(minimum() + ((maximum() - minimum()) * e->x()) / width()); | 
			
		
	
		
			
				
					|  |  |  |  |     emit sliderReleased(); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
	
		
			
				
					|  |  |  | @ -294,7 +315,7 @@ void Slider::mouseMoveEvent(QMouseEvent *e) { | 
			
		
	
		
			
				
					|  |  |  |  |   QPixmap thumb = thumbnail(seconds); | 
			
		
	
		
			
				
					|  |  |  |  |   if (!thumb.isNull()) { | 
			
		
	
		
			
				
					|  |  |  |  |     int x = std::clamp(pos - thumb.width() / 2, THUMBNAIL_MARGIN, width() - thumb.width() - THUMBNAIL_MARGIN + 1); | 
			
		
	
		
			
				
					|  |  |  |  |     int y = -thumb.height() - THUMBNAIL_MARGIN - 6; | 
			
		
	
		
			
				
					|  |  |  |  |     int y = -thumb.height() - THUMBNAIL_MARGIN; | 
			
		
	
		
			
				
					|  |  |  |  |     thumbnail_label.showPixmap(mapToParent(QPoint(x, y)), utils::formatSeconds(seconds), thumb, alertInfo(seconds)); | 
			
		
	
		
			
				
					|  |  |  |  |   } else { | 
			
		
	
		
			
				
					|  |  |  |  |     thumbnail_label.hide(); | 
			
		
	
	
		
			
				
					|  |  |  | 
 |