|  |  | @ -3,8 +3,9 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <algorithm> |  |  |  | #include <algorithm> | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <utility> |  |  |  | #include <utility> | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <QButtonGroup> |  |  |  | #include <QAction> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | #include <QHBoxLayout> |  |  |  | #include <QActionGroup> | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #include <QMenu> | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <QMouseEvent> |  |  |  | #include <QMouseEvent> | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <QPainter> |  |  |  | #include <QPainter> | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <QStackedLayout> |  |  |  | #include <QStackedLayout> | 
			
		
	
	
		
		
			
				
					|  |  | @ -27,50 +28,18 @@ static const QColor timeline_colors[] = { | 
			
		
	
		
		
			
				
					
					|  |  |  | VideoWidget::VideoWidget(QWidget *parent) : QFrame(parent) { |  |  |  | VideoWidget::VideoWidget(QWidget *parent) : QFrame(parent) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   setFrameStyle(QFrame::StyledPanel | QFrame::Plain); |  |  |  |   setFrameStyle(QFrame::StyledPanel | QFrame::Plain); | 
			
		
	
		
		
			
				
					
					|  |  |  |   auto main_layout = new QVBoxLayout(this); |  |  |  |   auto main_layout = new QVBoxLayout(this); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (!can->liveStreaming()) { |  |  |  |   if (!can->liveStreaming()) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     main_layout->addWidget(createCameraWidget()); |  |  |  |     main_layout->addWidget(createCameraWidget()); | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   main_layout->addLayout(createPlaybackController()); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   // btn controls
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   QButtonGroup *group = new QButtonGroup(this); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   group->setExclusive(true); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   QHBoxLayout *control_layout = new QHBoxLayout(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   play_btn = new QToolButton(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   play_btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   control_layout->addWidget(play_btn); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (can->liveStreaming()) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     control_layout->addWidget(skip_to_end_btn = new QToolButton(this)); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     skip_to_end_btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     skip_to_end_btn->setIcon(utils::icon("skip-end-fill")); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     skip_to_end_btn->setToolTip(tr("Skip to the end")); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     QObject::connect(skip_to_end_btn, &QToolButton::clicked, [group]() { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       // set speed to 1.0
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       group->buttons()[2]->click(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       can->pause(false); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       can->seekTo(can->totalSeconds() + 1); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     }); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (float speed : {0.1, 0.5, 1., 2.}) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     QToolButton *btn = new QToolButton(this); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     btn->setText(QString("%1x").arg(speed)); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     btn->setCheckable(true); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     QObject::connect(btn, &QToolButton::clicked, [speed]() { can->setSpeed(speed); }); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     control_layout->addWidget(btn); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     group->addButton(btn); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (speed == 1.0) btn->setChecked(true); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   main_layout->addLayout(control_layout); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); |  |  |  |   setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   QObject::connect(play_btn, &QToolButton::clicked, []() { can->pause(!can->isPaused()); }); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   QObject::connect(can, &AbstractStream::paused, this, &VideoWidget::updatePlayBtnState); |  |  |  |   QObject::connect(can, &AbstractStream::paused, this, &VideoWidget::updatePlayBtnState); | 
			
		
	
		
		
			
				
					
					|  |  |  |   QObject::connect(can, &AbstractStream::resume, 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); |  |  |  |   QObject::connect(&settings, &Settings::changed, this, &VideoWidget::updatePlayBtnState); | 
			
		
	
		
		
			
				
					
					|  |  |  |   updatePlayBtnState(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   updatePlayBtnState(); | 
			
		
	
		
		
			
				
					
					|  |  |  |   setWhatsThis(tr(R"( |  |  |  |   setWhatsThis(tr(R"( | 
			
		
	
		
		
			
				
					
					|  |  |  |     <b>Video</b><br /> |  |  |  |     <b>Video</b><br /> | 
			
		
	
		
		
			
				
					
					|  |  |  |     <!-- TODO: add descprition here --> |  |  |  |     <!-- TODO: add descprition here --> | 
			
		
	
	
		
		
			
				
					|  |  | @ -93,6 +62,71 @@ VideoWidget::VideoWidget(QWidget *parent) : QFrame(parent) { | 
			
		
	
		
		
			
				
					
					|  |  |  |           timeline_colors[(int)TimelineType::AlertCritical].name())); |  |  |  |           timeline_colors[(int)TimelineType::AlertCritical].name())); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | QHBoxLayout *VideoWidget::createPlaybackController() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   QHBoxLayout *layout = new QHBoxLayout(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   layout->addWidget(seek_backward_btn = new ToolButton("rewind", tr("Seek backward"))); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   layout->addWidget(play_btn = new ToolButton("play", tr("Play"))); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   layout->addWidget(seek_forward_btn = new ToolButton("fast-forward", tr("Seek forward"))); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (can->liveStreaming()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     layout->addWidget(skip_to_end_btn = new ToolButton("skip-end", tr("Skip to the end"), this)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     QObject::connect(skip_to_end_btn, &QToolButton::clicked, [this]() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       // set speed to 1.0
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       speed_btn->menu()->actions()[7]->setChecked(true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       can->pause(false); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       can->seekTo(can->totalSeconds() + 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     }); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   layout->addWidget(time_btn = new QToolButton); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   time_btn->setToolTip(settings.absolute_time ? tr("Elapsed time") : tr("Absolute time")); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   time_btn->setAutoRaise(true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   layout->addStretch(0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (!can->liveStreaming()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     layout->addWidget(loop_btn = new ToolButton("repeat", tr("Loop playback"))); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     QObject::connect(loop_btn, &QToolButton::clicked, this, &VideoWidget::loopPlaybackClicked); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // speed selector
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   layout->addWidget(speed_btn = new QToolButton(this)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   speed_btn->setAutoRaise(true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   speed_btn->setMenu(new QMenu(speed_btn)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   speed_btn->setPopupMode(QToolButton::InstantPopup); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   QActionGroup *speed_group = new QActionGroup(this); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   speed_group->setExclusive(true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int max_width = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   QFont font = speed_btn->font(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   font.setBold(true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   speed_btn->setFont(font); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   QFontMetrics fm(font); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   for (float speed : {0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 0.8, 1., 2., 3., 5.}) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     QString name = QString("%1x").arg(speed); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     max_width = std::max(max_width, fm.width(name) + fm.horizontalAdvance(QLatin1Char(' ')) * 2); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     QAction *act = new QAction(name, speed_group); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     act->setCheckable(true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     QObject::connect(act, &QAction::toggled, [this, speed]() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       can->setSpeed(speed); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       speed_btn->setText(QString("%1x  ").arg(speed)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     }); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     speed_btn->menu()->addAction(act); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (speed == 1.0)act->setChecked(true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   speed_btn->setMinimumWidth(max_width + style()->pixelMetric(QStyle::PM_MenuButtonIndicator)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   QObject::connect(play_btn, &QToolButton::clicked, []() { can->pause(!can->isPaused()); }); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   QObject::connect(seek_backward_btn, &QToolButton::clicked, []() { can->seekTo(can->currentSec() - 1); }); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   QObject::connect(seek_forward_btn, &QToolButton::clicked, []() { can->seekTo(can->currentSec() + 1); }); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   QObject::connect(time_btn, &QToolButton::clicked, [this]() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     settings.absolute_time = !settings.absolute_time; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     time_btn->setToolTip(settings.absolute_time ? tr("Elapsed time") : tr("Absolute time")); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     updateState(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   }); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return layout; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | QWidget *VideoWidget::createCameraWidget() { |  |  |  | QWidget *VideoWidget::createCameraWidget() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   QWidget *w = new QWidget(this); |  |  |  |   QWidget *w = new QWidget(this); | 
			
		
	
		
		
			
				
					
					|  |  |  |   QVBoxLayout *l = new QVBoxLayout(w); |  |  |  |   QVBoxLayout *l = new QVBoxLayout(w); | 
			
		
	
	
		
		
			
				
					|  |  | @ -106,30 +140,30 @@ QWidget *VideoWidget::createCameraWidget() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   stacked->addWidget(alert_label = new InfoLabel(this)); |  |  |  |   stacked->addWidget(alert_label = new InfoLabel(this)); | 
			
		
	
		
		
			
				
					
					|  |  |  |   l->addLayout(stacked); |  |  |  |   l->addLayout(stacked); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // slider controls
 |  |  |  |   l->addWidget(slider = new Slider(this)); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   auto slider_layout = new QHBoxLayout(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   slider_layout->addWidget(time_label = new QLabel("00:00")); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   slider = new Slider(this); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   slider->setSingleStep(0); |  |  |  |   slider->setSingleStep(0); | 
			
		
	
		
		
			
				
					
					|  |  |  |   slider_layout->addWidget(slider); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   slider_layout->addWidget(end_time_label = new QLabel(this)); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   l->addLayout(slider_layout); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   setMaximumTime(can->totalSeconds()); |  |  |  |   setMaximumTime(can->totalSeconds()); | 
			
		
	
		
		
			
				
					
					|  |  |  |   QObject::connect(slider, &QSlider::sliderReleased, [this]() { can->seekTo(slider->currentSecond()); }); |  |  |  |   QObject::connect(slider, &QSlider::sliderReleased, [this]() { can->seekTo(slider->currentSecond()); }); | 
			
		
	
		
		
			
				
					
					|  |  |  |   QObject::connect(slider, &QSlider::valueChanged, [=](int value) { time_label->setText(utils::formatSeconds(slider->currentSecond())); }); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   QObject::connect(slider, &Slider::updateMaximumTime, this, &VideoWidget::setMaximumTime, Qt::QueuedConnection); |  |  |  |   QObject::connect(slider, &Slider::updateMaximumTime, this, &VideoWidget::setMaximumTime, Qt::QueuedConnection); | 
			
		
	
		
		
			
				
					
					|  |  |  |   QObject::connect(cam_widget, &CameraWidget::clicked, []() { can->pause(!can->isPaused()); }); |  |  |  |   QObject::connect(cam_widget, &CameraWidget::clicked, []() { can->pause(!can->isPaused()); }); | 
			
		
	
		
		
			
				
					
					|  |  |  |   QObject::connect(static_cast<ReplayStream*>(can), &ReplayStream::qLogLoaded, slider, &Slider::parseQLog); |  |  |  |   QObject::connect(static_cast<ReplayStream*>(can), &ReplayStream::qLogLoaded, slider, &Slider::parseQLog); | 
			
		
	
		
		
			
				
					
					|  |  |  |   QObject::connect(can, &AbstractStream::updated, this, &VideoWidget::updateState); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   return w; |  |  |  |   return w; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | void VideoWidget::loopPlaybackClicked() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   auto replay = qobject_cast<ReplayStream *>(can)->getReplay(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (replay->hasFlag(REPLAY_FLAG_NO_LOOP)) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     replay->removeFlag(REPLAY_FLAG_NO_LOOP); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     loop_btn->setIcon("repeat"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     replay->addFlag(REPLAY_FLAG_NO_LOOP); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     loop_btn->setIcon("repeat-1"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void VideoWidget::setMaximumTime(double sec) { |  |  |  | void VideoWidget::setMaximumTime(double sec) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   maximum_time = sec; |  |  |  |   maximum_time = sec; | 
			
		
	
		
		
			
				
					
					|  |  |  |   end_time_label->setText(utils::formatSeconds(sec)); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   slider->setTimeRange(0, sec); |  |  |  |   slider->setTimeRange(0, sec); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -143,19 +177,29 @@ void VideoWidget::updateTimeRange(double min, double max, bool is_zoomed) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     min = 0; |  |  |  |     min = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |     max = maximum_time; |  |  |  |     max = maximum_time; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   end_time_label->setText(utils::formatSeconds(max)); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   slider->setTimeRange(min, max); |  |  |  |   slider->setTimeRange(min, max); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | QString VideoWidget::formatTime(double sec, bool include_milliseconds) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (settings.absolute_time) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     sec = can->beginDateTime().addMSecs(sec * 1000).toMSecsSinceEpoch() / 1000.0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return utils::formatSeconds(sec, include_milliseconds, settings.absolute_time); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void VideoWidget::updateState() { |  |  |  | void VideoWidget::updateState() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (!slider->isSliderDown()) { |  |  |  |   if (slider) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     slider->setCurrentSecond(can->currentSec()); |  |  |  |     if (!slider->isSliderDown()) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       slider->setCurrentSecond(can->currentSec()); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     alert_label->showAlert(slider->alertInfo(can->currentSec())); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     time_btn->setText(QString("%1 / %2").arg(formatTime(can->currentSec(), true), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                                              formatTime(slider->maximum() / slider->factor))); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     time_btn->setText(formatTime(can->currentSec(), true)); | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   alert_label->showAlert(slider->alertInfo(can->currentSec())); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void VideoWidget::updatePlayBtnState() { |  |  |  | void VideoWidget::updatePlayBtnState() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   play_btn->setIcon(utils::icon(can->isPaused() ? "play" : "pause")); |  |  |  |   play_btn->setIcon(can->isPaused() ? "play" : "pause"); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   play_btn->setToolTip(can->isPaused() ? tr("Play") : tr("Pause")); |  |  |  |   play_btn->setToolTip(can->isPaused() ? tr("Play") : tr("Pause")); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -284,8 +328,7 @@ void InfoLabel::showPixmap(const QPoint &pt, const QString &sec, const QPixmap & | 
			
		
	
		
		
			
				
					
					|  |  |  |   second = sec; |  |  |  |   second = sec; | 
			
		
	
		
		
			
				
					
					|  |  |  |   pixmap = pm; |  |  |  |   pixmap = pm; | 
			
		
	
		
		
			
				
					
					|  |  |  |   alert_info = alert; |  |  |  |   alert_info = alert; | 
			
		
	
		
		
			
				
					
					|  |  |  |   resize(pm.size()); |  |  |  |   setGeometry(QRect(pt, pm.size())); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   move(pt); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   setVisible(true); |  |  |  |   setVisible(true); | 
			
		
	
		
		
			
				
					
					|  |  |  |   update(); |  |  |  |   update(); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					|  |  | 
 |