37 #include <QMouseEvent>
57 BaseWidget(parent,
"PlaybackWidget",
"Playback")
60 this->setToolTip(this->defaultWhatsThis());
63 mTimer->initialize(QDateTime::currentDateTime(), 100000);
64 connect(mTimer.get(), SIGNAL(changed()), SLOT(timeChangedSlot()));
66 QVBoxLayout* topLayout =
new QVBoxLayout(
this);
68 mStartTimeLabel =
new QLabel;
69 topLayout->addWidget(mStartTimeLabel);
70 mTotalLengthLabel =
new QLabel;
71 topLayout->addWidget(mTotalLengthLabel);
73 topLayout->addWidget(mLabel);
76 connect(mToolTimelineWidget, SIGNAL(positionChanged()),
this, SLOT(timeLineWidgetValueChangedSlot()));
77 topLayout->addWidget(mToolTimelineWidget);
80 QHBoxLayout* playButtonsLayout =
new QHBoxLayout;
81 topLayout->addLayout(playButtonsLayout);
84 QIcon(
":/icons/open_icon_library/button-red.png"),
86 SLOT(toggleOpenSlot()),
89 QIcon(
":/icons/open_icon_library/media-seek-backward-3.png"),
94 QIcon(
":/icons/open_icon_library/media-playback-start-3.png"),
99 QIcon(
":/icons/open_icon_library/media-seek-forward-3.png"),
104 QIcon(
":/icons/open_icon_library/media-playback-stop-3.png"),
109 QIcon(
":/icons/open_icon_library/system-run-5.png"),
110 "Details",
"Details",
111 SLOT(toggleDetailsSlot()),
117 "Set speed of playback, 0 is normal speed.", 0,
DoubleRange(-5,5,1),0);
118 connect(mSpeedAdapter.get(), SIGNAL(changed()),
this, SLOT(speedChangedSlot()));
121 playButtonsLayout->addStretch();
123 topLayout->addStretch();
131 QString PlaybackWidget::defaultWhatsThis()
const
136 "Play back the whole operation."
137 "Play back contain all tool positions and recorded video "
138 "(video is only recorded during 3D acquisition)."
140 "Green indicates visible tools.<br>"
141 "Orange indicates recorded video."
143 "<b>Tip: </b> Press the red putton to start playback"
148 void PlaybackWidget::toggleDetailsSlot()
154 void PlaybackWidget::showDetails()
156 bool on =
settings()->
value(
"playback/ShowDetails").toBool();
158 mStartTimeLabel->setVisible(on);
159 mTotalLengthLabel->setVisible(on);
162 void PlaybackWidget::timeLineWidgetValueChangedSlot()
164 mTimer->setTime(QDateTime::fromMSecsSinceEpoch(mToolTimelineWidget->
getPos()));
167 void PlaybackWidget::toggleOpenSlot()
180 reportError(
"trackingService is not in playback mode");
184 report(QString(
"Started Playback with start time [%1] and end time [%2]")
188 this->toolManagerInitializedSlot();
192 QColor PlaybackWidget::generateRandomToolColor()
const
194 std::vector<QColor> colors;
197 colors.push_back(QColor::fromHsv(110, s, v));
198 colors.push_back(QColor::fromHsv(80, s, v));
199 colors.push_back(QColor::fromHsv(140, s, v));
200 colors.push_back(QColor::fromHsv(95, s, v));
201 colors.push_back(QColor::fromHsv(125, s, v));
203 static int gCounter = 0;
204 return colors[(gCounter++)%colors.size()];
207 std::vector<TimelineEvent> PlaybackWidget::convertHistoryToEvents(
ToolPtr tool)
209 std::vector<TimelineEvent> retval;
211 if (!history || history->empty())
213 double timeout = 200;
214 TimelineEvent currentEvent(tool->getName() +
" visible", history->begin()->first);
215 currentEvent.mGroup =
"tool";
216 currentEvent.mColor = this->generateRandomToolColor();
219 for(TimedTransformMap::iterator iter=history->begin(); iter!=history->end(); ++iter)
221 double current = iter->first;
223 if (current - currentEvent.mEndTime > timeout)
225 retval.push_back(currentEvent);
226 currentEvent.mStartTime = currentEvent.mEndTime = current;
230 currentEvent.mEndTime = current;
233 if (!
similar(currentEvent.mEndTime - currentEvent.mStartTime, 0))
234 retval.push_back(currentEvent);
241 std::vector<TimelineEvent> events;
243 std::vector<RegistrationTransform> tr = reg->getData();
244 for (
unsigned i=0; i<tr.size(); ++i)
246 if (!tr[i].mTimestamp.isValid())
249 QString text = QString(
"Registraton %1, fixed=%2").arg(tr[i].mType).arg(tr[i].mFixed);
250 if (!tr[i].mMoving.isEmpty())
251 text = QString(
"%1, moving=%2").arg(text).arg(tr[i].mMoving);
253 events.push_back(TimelineEvent(text,
254 tr[i].mTimestamp.toMSecsSinceEpoch()));
257 std::vector<ParentSpace> ps = reg->getParentSpaces();
262 std::vector<TimelineEvent> PlaybackWidget::createEvents()
264 typedef std::vector<TimelineEvent> TimelineEventVector;
267 TimelineEventVector events;
269 for (TrackingService::ToolMap::iterator iter=tools.begin(); iter!=tools.end(); ++iter)
273 TimelineEventVector current = convertHistoryToEvents(iter->second);
274 copy(current.begin(), current.end(), std::back_inserter(events));
279 for (std::map<QString, DataPtr>::iterator iter=data.begin(); iter!=data.end(); ++iter)
281 QString desc(
"loaded " + iter->second->getName());
282 if (iter->second->getAcquisitionTime().isValid())
284 double acqTime = iter->second->getAcquisitionTime().toMSecsSinceEpoch();
285 events.push_back(TimelineEvent(desc, acqTime));
289 TimelineEventVector current = this->convertRegistrationHistoryToEvents(reg);
290 copy(current.begin(), current.end(), std::back_inserter(events));
294 TimelineEventVector current = this->convertRegistrationHistoryToEvents(reg);
295 copy(current.begin(), current.end(), std::back_inserter(events));
298 copy(current.begin(), current.end(), std::back_inserter(events));
307 std::pair<double,double> PlaybackWidget::findTimeRange(std::vector<TimelineEvent> events)
311 double now = QDateTime::currentDateTime().toMSecsSinceEpoch();
312 return std::make_pair(now, now+1000);
318 for (
unsigned i=0; i<events.size(); ++i)
320 timeRange.first = std::min(timeRange.first, events[i].mStartTime);
321 timeRange.second = std::max(timeRange.second, events[i].mEndTime);
336 void PlaybackWidget::toolManagerInitializedSlot()
340 mOpenAction->setText(
"Close Playback");
341 mOpenAction->setIcon(QIcon(
":/icons/open_icon_library/button-green.png"));
345 mOpenAction->setText(
"Open Playback");
346 mOpenAction->setIcon(QIcon(
":/icons/open_icon_library/button-red.png"));
347 mToolTimelineWidget->
setEvents(std::vector<TimelineEvent>());
354 std::vector<TimelineEvent> events = this->createEvents();
355 std::pair<double,double> range = this->findTimeRange(events);
358 mTimer->initialize(QDateTime::fromMSecsSinceEpoch(range.first), range.second - range.first);
361 mToolTimelineWidget->
setRange(range.first, range.second);
364 QString startDate = mTimer->getStartTime().toString(
"yyyy-MM-dd");
365 QString startTime = mTimer->getStartTime().toString(
"hh:mm");
366 QString endTime = mTimer->getStartTime().addMSecs(mTimer->getLength()).toString(
"hh:mm");
368 QString
length = this->convertMillisecsToNiceString(mTimer->getLength());
369 mStartTimeLabel->setText(
370 QString(
"Date:").leftJustified(15) +
"" + startDate+
"\n" +
371 QString(
"Time:").leftJustified(15) +
"" + startTime +
" - " + endTime +
"\n" +
372 QString(
"Duration:").leftJustified(15)+
"" + length);
374 this->timeChangedSlot();
380 QString PlaybackWidget::stripLeadingZeros(QString time)
382 QStringList split = time.split(
":");
384 while (!split.empty() && (split.front().toInt(&ok)==0) && ok)
388 return split.join(
":");
394 QString PlaybackWidget::convertMillisecsToNiceString(qint64 length)
const
398 qint64 ms = length % 1000;
399 qint64 s = (length / 1000) % 60;
400 qint64 m = (length / (1000*60)) % 60;
401 qint64 h = (length / (1000*60*60));
404 retval = QString(
"%1:%2.%3").arg(m,2,10,c).arg(s,2,10,c).arg(ms,3,10,c);
406 retval = QString(
"%1:%2").arg(h).arg(retval);
411 void PlaybackWidget::speedChangedSlot()
413 double speed = mSpeedAdapter->getValue();
414 speed = pow(2,speed);
415 mTimer->setSpeed(speed);
419 void PlaybackWidget::timeChangedSlot()
421 QString color(
"green");
423 qint64 offset = mTimer->getOffset();
424 QString format = QString(
"<font size=%1 color=%2><b>%3</b></font>").arg(fontSize).arg(color);
426 QString currentTime = mTimer->getTime().toString(
"hh:mm:ss");
428 QString currentOffset = this->convertMillisecsToNiceString(offset);
430 mLabel->setText(format.arg(
"Elapsed: "+currentOffset+
" \tTime: " + currentTime));
432 if (mTimer->isPlaying())
434 mPlayAction->setIcon(QIcon(
":/icons/open_icon_library/media-playback-pause-3.png"));
435 mPlayAction->setText(
"Pause");
439 mPlayAction->setIcon(QIcon(
":/icons/open_icon_library/media-playback-start-3.png"));
440 mPlayAction->setText(
"Play");
452 mToolTimelineWidget->blockSignals(
true);
453 mToolTimelineWidget->
setPos(mTimer->getTime().toMSecsSinceEpoch());
454 mToolTimelineWidget->blockSignals(
false);
457 void PlaybackWidget::playSlot()
459 if (mTimer->isPlaying())
468 void PlaybackWidget::pauseSlot()
472 void PlaybackWidget::stopSlot()
476 void PlaybackWidget::forwardSlot()
478 mTimer->forward(1000*mTimer->getSpeed());
480 void PlaybackWidget::rewindSlot()
482 mTimer->rewind(1000*mTimer->getSpeed());
void reportError(QString msg)
boost::shared_ptr< class RegistrationHistory > RegistrationHistoryPtr
Utility class for describing a bounded numeric range.
double getMilliSecondsSinceEpoch()
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
void setValue(const QString &key, const QVariant &value)
boost::shared_ptr< TimedTransformMap > TimedTransformMapPtr
Settings * settings()
Shortcut for accessing the settings instance.
std::map< QString, ToolPtr > ToolMap
cxLogicManager_EXPORT VideoServicePtr videoService()
cxLogicManager_EXPORT PatientModelServicePtr patientService()
static DoublePropertyPtr initialize(const QString &uid, QString name, QString help, double value, DoubleRange range, int decimals, QDomNode root=QDomNode())
RealScalar length() const
cxLogicManager_EXPORT TrackingServicePtr trackingService()
Controller for historic time, playback etc.
QString timestampMilliSecondsFormatNice()
boost::shared_ptr< class PlaybackTime > PlaybackTimePtr
boost::shared_ptr< class Tool > ToolPtr