37 #include <QMouseEvent>
57 BaseWidget(parent,
"PlaybackWidget",
"Playback")
60 this->setToolTip(
"Replay current session");
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 void PlaybackWidget::toggleDetailsSlot()
137 void PlaybackWidget::showDetails()
139 bool on =
settings()->
value(
"playback/ShowDetails").toBool();
141 mStartTimeLabel->setVisible(on);
142 mTotalLengthLabel->setVisible(on);
145 void PlaybackWidget::timeLineWidgetValueChangedSlot()
147 mTimer->setTime(QDateTime::fromMSecsSinceEpoch(mToolTimelineWidget->
getPos()));
150 void PlaybackWidget::toggleOpenSlot()
163 reportError(
"trackingService is not in playback mode");
167 report(QString(
"Started Playback with start time [%1] and end time [%2]")
171 this->toolManagerInitializedSlot();
175 QColor PlaybackWidget::generateRandomToolColor()
const
177 std::vector<QColor> colors;
180 colors.push_back(QColor::fromHsv(110, s, v));
181 colors.push_back(QColor::fromHsv(80, s, v));
182 colors.push_back(QColor::fromHsv(140, s, v));
183 colors.push_back(QColor::fromHsv(95, s, v));
184 colors.push_back(QColor::fromHsv(125, s, v));
186 static int gCounter = 0;
187 return colors[(gCounter++)%colors.size()];
190 std::vector<TimelineEvent> PlaybackWidget::convertHistoryToEvents(
ToolPtr tool)
192 std::vector<TimelineEvent> retval;
194 if (!history || history->empty())
196 double timeout = 200;
197 TimelineEvent currentEvent(tool->getName() +
" visible", history->begin()->first);
198 currentEvent.mGroup =
"tool";
199 currentEvent.mColor = this->generateRandomToolColor();
202 for(TimedTransformMap::iterator iter=history->begin(); iter!=history->end(); ++iter)
204 double current = iter->first;
206 if (current - currentEvent.mEndTime > timeout)
208 retval.push_back(currentEvent);
209 currentEvent.mStartTime = currentEvent.mEndTime = current;
213 currentEvent.mEndTime = current;
216 if (!
similar(currentEvent.mEndTime - currentEvent.mStartTime, 0))
217 retval.push_back(currentEvent);
224 std::vector<TimelineEvent> events;
226 std::vector<RegistrationTransform> tr = reg->getData();
227 for (
unsigned i=0; i<tr.size(); ++i)
229 if (!tr[i].mTimestamp.isValid())
232 QString text = QString(
"Registraton %1, fixed=%2").arg(tr[i].mType).arg(tr[i].mFixed);
233 if (!tr[i].mMoving.isEmpty())
234 text = QString(
"%1, moving=%2").arg(text).arg(tr[i].mMoving);
236 events.push_back(TimelineEvent(text,
237 tr[i].mTimestamp.toMSecsSinceEpoch()));
246 bool PlaybackWidget::isInterestingTool(
ToolPtr tool)
const
251 std::vector<TimelineEvent> PlaybackWidget::createEvents()
253 typedef std::vector<TimelineEvent> TimelineEventVector;
256 TimelineEventVector events;
258 for (TrackingService::ToolMap::iterator iter=tools.begin(); iter!=tools.end(); ++iter)
260 if(this->isInterestingTool(iter->second))
262 TimelineEventVector current = convertHistoryToEvents(iter->second);
263 copy(current.begin(), current.end(), std::back_inserter(events));
268 for (std::map<QString, DataPtr>::iterator iter=data.begin(); iter!=data.end(); ++iter)
270 QString desc(
"loaded " + iter->second->getName());
271 if (iter->second->getAcquisitionTime().isValid())
273 double acqTime = iter->second->getAcquisitionTime().toMSecsSinceEpoch();
274 events.push_back(TimelineEvent(desc, acqTime));
278 TimelineEventVector current = this->convertRegistrationHistoryToEvents(reg);
279 copy(current.begin(), current.end(), std::back_inserter(events));
283 TimelineEventVector current = this->convertRegistrationHistoryToEvents(reg);
284 copy(current.begin(), current.end(), std::back_inserter(events));
287 copy(current.begin(), current.end(), std::back_inserter(events));
296 std::pair<double,double> PlaybackWidget::findTimeRange(std::vector<TimelineEvent> events)
300 double now = QDateTime::currentDateTime().toMSecsSinceEpoch();
301 return std::make_pair(now, now+1000);
307 for (
unsigned i=0; i<events.size(); ++i)
309 timeRange.first = std::min(timeRange.first, events[i].mStartTime);
310 timeRange.second = std::max(timeRange.second, events[i].mEndTime);
325 void PlaybackWidget::toolManagerInitializedSlot()
329 mOpenAction->setText(
"Close Playback");
330 mOpenAction->setIcon(QIcon(
":/icons/open_icon_library/button-green.png"));
334 mOpenAction->setText(
"Open Playback");
335 mOpenAction->setIcon(QIcon(
":/icons/open_icon_library/button-red.png"));
336 mToolTimelineWidget->
setEvents(std::vector<TimelineEvent>());
343 std::vector<TimelineEvent> events = this->createEvents();
344 std::pair<double,double> range = this->findTimeRange(events);
347 mTimer->initialize(QDateTime::fromMSecsSinceEpoch(range.first), range.second - range.first);
350 mToolTimelineWidget->
setRange(range.first, range.second);
353 QString startDate = mTimer->getStartTime().toString(
"yyyy-MM-dd");
354 QString startTime = mTimer->getStartTime().toString(
"hh:mm");
355 QString endTime = mTimer->getStartTime().addMSecs(mTimer->getLength()).toString(
"hh:mm");
357 QString
length = this->convertMillisecsToNiceString(mTimer->getLength());
358 mStartTimeLabel->setText(
359 QString(
"Date:").leftJustified(15) +
"" + startDate+
"\n" +
360 QString(
"Time:").leftJustified(15) +
"" + startTime +
" - " + endTime +
"\n" +
361 QString(
"Duration:").leftJustified(15)+
"" + length);
363 this->timeChangedSlot();
383 QString PlaybackWidget::convertMillisecsToNiceString(qint64 length)
const
387 qint64 ms = length % 1000;
388 qint64 s = (length / 1000) % 60;
389 qint64 m = (length / (1000*60)) % 60;
390 qint64 h = (length / (1000*60*60));
393 retval = QString(
"%1:%2.%3").arg(m,2,10,c).arg(s,2,10,c).arg(ms,3,10,c);
395 retval = QString(
"%1:%2").arg(h).arg(retval);
400 void PlaybackWidget::speedChangedSlot()
402 double speed = mSpeedAdapter->getValue();
403 speed = pow(2,speed);
404 mTimer->setSpeed(speed);
408 void PlaybackWidget::timeChangedSlot()
410 QString color(
"green");
412 qint64 offset = mTimer->getOffset();
413 QString format = QString(
"<font size=%1 color=%2><b>%3</b></font>").arg(fontSize).arg(color);
415 QString currentTime = mTimer->getTime().toString(
"hh:mm:ss");
417 QString currentOffset = this->convertMillisecsToNiceString(offset);
419 mLabel->setText(format.arg(
"Elapsed: "+currentOffset+
" \tTime: " + currentTime));
421 if (mTimer->isPlaying())
423 mPlayAction->setIcon(QIcon(
":/icons/open_icon_library/media-playback-pause-3.png"));
424 mPlayAction->setText(
"Pause");
428 mPlayAction->setIcon(QIcon(
":/icons/open_icon_library/media-playback-start-3.png"));
429 mPlayAction->setText(
"Play");
441 mToolTimelineWidget->blockSignals(
true);
442 mToolTimelineWidget->
setPos(mTimer->getTime().toMSecsSinceEpoch());
443 mToolTimelineWidget->blockSignals(
false);
446 void PlaybackWidget::playSlot()
448 if (mTimer->isPlaying())
461 void PlaybackWidget::stopSlot()
465 void PlaybackWidget::forwardSlot()
467 mTimer->forward(1000*mTimer->getSpeed());
469 void PlaybackWidget::rewindSlot()
471 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)
boost::shared_ptr< class PlaybackTime > PlaybackTimePtr
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 Tool > ToolPtr