37 #include <QMouseEvent> 57 BaseWidget(parent,
"playback_widget",
"Playback"),
58 mTrackingService(trackingService),
59 mVideoService(videoService),
60 mPatientModelService(patientModelService)
63 this->setToolTip(
"Replay current session");
66 mTimer->initialize(QDateTime::currentDateTime(), 100000);
67 connect(mTimer.get(), SIGNAL(changed()), SLOT(timeChangedSlot()));
69 QVBoxLayout* topLayout =
new QVBoxLayout(
this);
71 mStartTimeLabel =
new QLabel;
72 topLayout->addWidget(mStartTimeLabel);
73 mTotalLengthLabel =
new QLabel;
74 topLayout->addWidget(mTotalLengthLabel);
76 topLayout->addWidget(mLabel);
79 connect(mToolTimelineWidget, SIGNAL(positionChanged()),
this, SLOT(timeLineWidgetValueChangedSlot()));
80 topLayout->addWidget(mToolTimelineWidget);
83 QHBoxLayout* playButtonsLayout =
new QHBoxLayout;
84 topLayout->addLayout(playButtonsLayout);
87 QIcon(
":/icons/open_icon_library/button-red.png"),
89 SLOT(toggleOpenSlot()),
92 QIcon(
":/icons/open_icon_library/media-seek-backward-3.png"),
97 QIcon(
":/icons/open_icon_library/media-playback-start-3.png"),
102 QIcon(
":/icons/open_icon_library/media-seek-forward-3.png"),
107 QIcon(
":/icons/open_icon_library/media-playback-stop-3.png"),
112 QIcon(
":/icons/open_icon_library/system-run-5.png"),
113 "Details",
"Details",
114 SLOT(toggleDetailsSlot()),
120 "Set speed of playback, 0 is normal speed.", 0,
DoubleRange(-5,5,1),0);
121 connect(mSpeedAdapter.get(), SIGNAL(changed()),
this, SLOT(speedChangedSlot()));
124 playButtonsLayout->addStretch();
126 topLayout->addStretch();
134 void PlaybackWidget::toggleDetailsSlot()
140 void PlaybackWidget::showDetails()
142 bool on =
settings()->
value(
"playback/ShowDetails").toBool();
144 mStartTimeLabel->setVisible(on);
145 mTotalLengthLabel->setVisible(on);
148 void PlaybackWidget::timeLineWidgetValueChangedSlot()
150 mTimer->setTime(QDateTime::fromMSecsSinceEpoch(mToolTimelineWidget->
getPos()));
153 void PlaybackWidget::toggleOpenSlot()
155 if (mTrackingService->isPlaybackMode())
163 mTrackingService->setPlaybackMode(mTimer);
164 if (!mTrackingService->isPlaybackMode())
166 reportError(
"trackingService is not in playback mode");
169 mVideoService->setPlaybackMode(mTimer);
170 report(QString(
"Started Playback with start time [%1] and end time [%2]")
174 this->toolManagerInitializedSlot();
178 QColor PlaybackWidget::generateRandomToolColor()
const 180 std::vector<QColor> colors;
183 colors.push_back(QColor::fromHsv(110, s, v));
184 colors.push_back(QColor::fromHsv(80, s, v));
185 colors.push_back(QColor::fromHsv(140, s, v));
186 colors.push_back(QColor::fromHsv(95, s, v));
187 colors.push_back(QColor::fromHsv(125, s, v));
189 static int gCounter = 0;
190 return colors[(gCounter++)%colors.size()];
193 std::vector<TimelineEvent> PlaybackWidget::convertHistoryToEvents(
ToolPtr tool)
195 std::vector<TimelineEvent> retval;
197 if (!history || history->empty())
199 double timeout = 200;
200 TimelineEvent currentEvent(tool->getName() +
" visible", history->begin()->first);
201 currentEvent.
mGroup =
"tool";
202 currentEvent.mColor = this->generateRandomToolColor();
205 for(TimedTransformMap::iterator iter=history->begin(); iter!=history->end(); ++iter)
207 double current = iter->first;
209 if (current - currentEvent.mEndTime > timeout)
211 retval.push_back(currentEvent);
212 currentEvent.mStartTime = currentEvent.mEndTime = current;
216 currentEvent.mEndTime = current;
219 if (!
similar(currentEvent.mEndTime - currentEvent.mStartTime, 0))
220 retval.push_back(currentEvent);
227 std::vector<TimelineEvent> events;
229 std::vector<RegistrationTransform> tr = reg->getData();
230 for (
unsigned i=0; i<tr.size(); ++i)
232 if (!tr[i].mTimestamp.isValid())
235 QString text = QString(
"Registraton %1, fixed=%2").arg(tr[i].mType).arg(tr[i].mFixed);
236 if (!tr[i].mMoving.isEmpty())
237 text = QString(
"%1, moving=%2").arg(text).arg(tr[i].mMoving);
240 tr[i].mTimestamp.toMSecsSinceEpoch()));
249 bool PlaybackWidget::isInterestingTool(
ToolPtr tool)
const 254 std::vector<TimelineEvent> PlaybackWidget::createEvents()
256 typedef std::vector<TimelineEvent> TimelineEventVector;
259 TimelineEventVector events;
261 for (TrackingService::ToolMap::iterator iter=tools.begin(); iter!=tools.end(); ++iter)
263 if(this->isInterestingTool(iter->second))
265 TimelineEventVector current = convertHistoryToEvents(iter->second);
266 copy(current.begin(), current.end(), std::back_inserter(events));
270 std::map<QString, DataPtr> data = mPatientModelService->getDatas();
271 for (std::map<QString, DataPtr>::iterator iter=data.begin(); iter!=data.end(); ++iter)
273 QString desc(
"loaded " + iter->second->getName());
274 if (iter->second->getAcquisitionTime().isValid())
276 double acqTime = iter->second->getAcquisitionTime().toMSecsSinceEpoch();
281 TimelineEventVector current = this->convertRegistrationHistoryToEvents(reg);
282 copy(current.begin(), current.end(), std::back_inserter(events));
286 TimelineEventVector current = this->convertRegistrationHistoryToEvents(reg);
287 copy(current.begin(), current.end(), std::back_inserter(events));
289 current = mVideoService->getPlaybackEvents();
290 copy(current.begin(), current.end(), std::back_inserter(events));
299 std::pair<double,double> PlaybackWidget::findTimeRange(std::vector<TimelineEvent> events)
303 double now = QDateTime::currentDateTime().toMSecsSinceEpoch();
304 return std::make_pair(now, now+1000);
310 for (
unsigned i=0; i<events.size(); ++i)
312 timeRange.first = std::min(timeRange.first, events[i].mStartTime);
313 timeRange.second = std::max(timeRange.second, events[i].mEndTime);
328 void PlaybackWidget::toolManagerInitializedSlot()
330 if (mTrackingService->isPlaybackMode())
332 mOpenAction->setText(
"Close Playback");
333 mOpenAction->setIcon(QIcon(
":/icons/open_icon_library/button-green.png"));
337 mOpenAction->setText(
"Open Playback");
338 mOpenAction->setIcon(QIcon(
":/icons/open_icon_library/button-red.png"));
339 mToolTimelineWidget->
setEvents(std::vector<TimelineEvent>());
346 std::vector<TimelineEvent> events = this->createEvents();
347 std::pair<double,double> range = this->findTimeRange(events);
350 mTimer->initialize(QDateTime::fromMSecsSinceEpoch(range.first), range.second - range.first);
353 mToolTimelineWidget->
setRange(range.first, range.second);
356 QString startDate = mTimer->getStartTime().toString(
"yyyy-MM-dd");
357 QString startTime = mTimer->getStartTime().toString(
"hh:mm");
358 QString endTime = mTimer->getStartTime().addMSecs(mTimer->getLength()).
toString(
"hh:mm");
360 QString
length = this->convertMillisecsToNiceString(mTimer->getLength());
361 mStartTimeLabel->setText(
362 QString(
"Date:").leftJustified(15) +
"" + startDate+
"\n" +
363 QString(
"Time:").leftJustified(15) +
"" + startTime +
" - " + endTime +
"\n" +
364 QString(
"Duration:").leftJustified(15)+
"" + length);
366 this->timeChangedSlot();
386 QString PlaybackWidget::convertMillisecsToNiceString(qint64
length)
const 390 qint64 ms = length % 1000;
391 qint64 s = (length / 1000) % 60;
392 qint64 m = (length / (1000*60)) % 60;
393 qint64 h = (length / (1000*60*60));
396 retval = QString(
"%1:%2.%3").arg(m,2,10,c).arg(s,2,10,c).arg(ms,3,10,c);
398 retval = QString(
"%1:%2").arg(h).arg(retval);
403 void PlaybackWidget::speedChangedSlot()
405 double speed = mSpeedAdapter->getValue();
406 speed = pow(2,speed);
407 mTimer->setSpeed(speed);
411 void PlaybackWidget::timeChangedSlot()
413 QString color(
"green");
415 qint64 offset = mTimer->getOffset();
416 QString format = QString(
"<font size=%1 color=%2><b>%3</b></font>").arg(fontSize).arg(color);
418 QString currentTime = mTimer->getTime().toString(
"hh:mm:ss");
420 QString currentOffset = this->convertMillisecsToNiceString(offset);
422 mLabel->setText(format.arg(
"Elapsed: "+currentOffset+
" \tTime: " + currentTime));
424 if (mTimer->isPlaying())
426 mPlayAction->setIcon(QIcon(
":/icons/open_icon_library/media-playback-pause-3.png"));
427 mPlayAction->setText(
"Pause");
431 mPlayAction->setIcon(QIcon(
":/icons/open_icon_library/media-playback-start-3.png"));
432 mPlayAction->setText(
"Play");
444 mToolTimelineWidget->blockSignals(
true);
445 mToolTimelineWidget->
setPos(mTimer->getTime().toMSecsSinceEpoch());
446 mToolTimelineWidget->blockSignals(
false);
449 void PlaybackWidget::playSlot()
451 if (mTimer->isPlaying())
464 void PlaybackWidget::stopSlot()
468 void PlaybackWidget::forwardSlot()
470 mTimer->forward(1000*mTimer->getSpeed());
472 void PlaybackWidget::rewindSlot()
474 mTimer->rewind(1000*mTimer->getSpeed());
boost::shared_ptr< class VideoService > VideoServicePtr
void reportError(QString msg)
boost::shared_ptr< class RegistrationHistory > RegistrationHistoryPtr
std::string toString(T const &value)
converts any type to a string
boost::shared_ptr< class TrackingService > TrackingServicePtr
Description of one event in time.
Utility class for describing a bounded numeric range.
double getMilliSecondsSinceEpoch()
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
boost::shared_ptr< class PlaybackTime > PlaybackTimePtr
void setValue(const QString &key, const QVariant &value)
boost::shared_ptr< TimedTransformMap > TimedTransformMapPtr
boost::shared_ptr< class PatientModelService > PatientModelServicePtr
Settings * settings()
Shortcut for accessing the settings instance.
std::map< QString, ToolPtr > ToolMap
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
static DoublePropertyPtr initialize(const QString &uid, QString name, QString help, double value, DoubleRange range, int decimals, QDomNode root=QDomNode())
RealScalar length() const
Controller for historic time, playback etc.
QString timestampMilliSecondsFormatNice()
Namespace for all CustusX production code.
boost::shared_ptr< class Tool > ToolPtr