16 #include <QMouseEvent> 36 BaseWidget(parent,
"playback_widget",
"Playback"),
37 mTrackingService(trackingService),
38 mVideoService(videoService),
39 mPatientModelService(patientModelService)
42 this->setToolTip(
"Replay current session");
45 mTimer->initialize(QDateTime::currentDateTime(), 100000);
46 connect(mTimer.get(), SIGNAL(changed()), SLOT(timeChangedSlot()));
48 QVBoxLayout* topLayout =
new QVBoxLayout(
this);
50 mStartTimeLabel =
new QLabel;
51 topLayout->addWidget(mStartTimeLabel);
52 mTotalLengthLabel =
new QLabel;
53 topLayout->addWidget(mTotalLengthLabel);
55 topLayout->addWidget(mLabel);
58 connect(mToolTimelineWidget, SIGNAL(positionChanged()),
this, SLOT(timeLineWidgetValueChangedSlot()));
59 topLayout->addWidget(mToolTimelineWidget);
62 QHBoxLayout* playButtonsLayout =
new QHBoxLayout;
63 topLayout->addLayout(playButtonsLayout);
66 QIcon(
":/icons/open_icon_library/button-red.png"),
68 SLOT(toggleOpenSlot()),
71 QIcon(
":/icons/open_icon_library/media-seek-backward-3.png"),
76 QIcon(
":/icons/open_icon_library/media-playback-start-3.png"),
81 QIcon(
":/icons/open_icon_library/media-seek-forward-3.png"),
86 QIcon(
":/icons/open_icon_library/media-playback-stop-3.png"),
91 QIcon(
":/icons/open_icon_library/system-run-5.png"),
93 SLOT(toggleDetailsSlot()),
99 "Set speed of playback, 0 is normal speed.", 0,
DoubleRange(-5,5,1),0);
100 connect(mSpeedAdapter.get(), SIGNAL(changed()),
this, SLOT(speedChangedSlot()));
103 playButtonsLayout->addStretch();
105 topLayout->addStretch();
113 void PlaybackWidget::toggleDetailsSlot()
119 void PlaybackWidget::showDetails()
121 bool on =
settings()->
value(
"playback/ShowDetails").toBool();
123 mStartTimeLabel->setVisible(on);
124 mTotalLengthLabel->setVisible(on);
127 void PlaybackWidget::timeLineWidgetValueChangedSlot()
129 mTimer->setTime(QDateTime::fromMSecsSinceEpoch(mToolTimelineWidget->
getPos()));
132 void PlaybackWidget::toggleOpenSlot()
134 if (mTrackingService->isPlaybackMode())
142 mTrackingService->setPlaybackMode(mTimer);
143 if (!mTrackingService->isPlaybackMode())
145 reportError(
"trackingService is not in playback mode");
148 mVideoService->setPlaybackMode(mTimer);
149 report(QString(
"Started Playback with start time [%1] and end time [%2]")
153 this->toolManagerInitializedSlot();
157 QColor PlaybackWidget::generateRandomToolColor()
const 159 std::vector<QColor> colors;
162 colors.push_back(QColor::fromHsv(110, s, v));
163 colors.push_back(QColor::fromHsv(80, s, v));
164 colors.push_back(QColor::fromHsv(140, s, v));
165 colors.push_back(QColor::fromHsv(95, s, v));
166 colors.push_back(QColor::fromHsv(125, s, v));
168 static int gCounter = 0;
169 return colors[(gCounter++)%colors.size()];
172 std::vector<TimelineEvent> PlaybackWidget::convertHistoryToEvents(
ToolPtr tool)
174 std::vector<TimelineEvent> retval;
176 if (!history || history->empty())
178 double timeout = 200;
179 TimelineEvent currentEvent(tool->getName() +
" visible", history->begin()->first);
180 currentEvent.
mGroup =
"tool";
181 currentEvent.mColor = this->generateRandomToolColor();
184 for(TimedTransformMap::iterator iter=history->begin(); iter!=history->end(); ++iter)
186 double current = iter->first;
188 if (current - currentEvent.mEndTime > timeout)
190 retval.push_back(currentEvent);
191 currentEvent.mStartTime = currentEvent.mEndTime = current;
195 currentEvent.mEndTime = current;
198 if (!
similar(currentEvent.mEndTime - currentEvent.mStartTime, 0))
199 retval.push_back(currentEvent);
206 std::vector<TimelineEvent> events;
208 std::vector<RegistrationTransform> tr = reg->getData();
209 for (
unsigned i=0; i<tr.size(); ++i)
211 if (!tr[i].mTimestamp.isValid())
214 QString text = QString(
"Registraton %1, fixed=%2").arg(tr[i].mType).arg(tr[i].mFixed);
215 if (!tr[i].mMoving.isEmpty())
216 text = QString(
"%1, moving=%2").arg(text).arg(tr[i].mMoving);
219 tr[i].mTimestamp.toMSecsSinceEpoch()));
228 bool PlaybackWidget::isInterestingTool(
ToolPtr tool)
const 233 std::vector<TimelineEvent> PlaybackWidget::createEvents()
235 typedef std::vector<TimelineEvent> TimelineEventVector;
238 TimelineEventVector events;
240 for (TrackingService::ToolMap::iterator iter=tools.begin(); iter!=tools.end(); ++iter)
242 if(this->isInterestingTool(iter->second))
244 TimelineEventVector current = convertHistoryToEvents(iter->second);
245 copy(current.begin(), current.end(), std::back_inserter(events));
249 std::map<QString, DataPtr> data = mPatientModelService->getDatas();
250 for (std::map<QString, DataPtr>::iterator iter=data.begin(); iter!=data.end(); ++iter)
252 QString desc(
"loaded " + iter->second->getName());
253 if (iter->second->getAcquisitionTime().isValid())
255 double acqTime = iter->second->getAcquisitionTime().toMSecsSinceEpoch();
260 TimelineEventVector current = this->convertRegistrationHistoryToEvents(reg);
261 copy(current.begin(), current.end(), std::back_inserter(events));
265 TimelineEventVector current = this->convertRegistrationHistoryToEvents(reg);
266 copy(current.begin(), current.end(), std::back_inserter(events));
268 current = mVideoService->getPlaybackEvents();
269 copy(current.begin(), current.end(), std::back_inserter(events));
278 std::pair<double,double> PlaybackWidget::findTimeRange(std::vector<TimelineEvent> events)
282 double now = QDateTime::currentDateTime().toMSecsSinceEpoch();
283 return std::make_pair(now, now+1000);
289 for (
unsigned i=0; i<events.size(); ++i)
291 timeRange.first = std::min(timeRange.first, events[i].mStartTime);
292 timeRange.second = std::max(timeRange.second, events[i].mEndTime);
307 void PlaybackWidget::toolManagerInitializedSlot()
309 if (mTrackingService->isPlaybackMode())
311 mOpenAction->setText(
"Close Playback");
312 mOpenAction->setIcon(QIcon(
":/icons/open_icon_library/button-green.png"));
316 mOpenAction->setText(
"Open Playback");
317 mOpenAction->setIcon(QIcon(
":/icons/open_icon_library/button-red.png"));
318 mToolTimelineWidget->
setEvents(std::vector<TimelineEvent>());
325 std::vector<TimelineEvent> events = this->createEvents();
326 std::pair<double,double> range = this->findTimeRange(events);
329 mTimer->initialize(QDateTime::fromMSecsSinceEpoch(range.first), range.second - range.first);
332 mToolTimelineWidget->
setRange(range.first, range.second);
335 QString startDate = mTimer->getStartTime().toString(
"yyyy-MM-dd");
336 QString startTime = mTimer->getStartTime().toString(
"hh:mm");
337 QString endTime = mTimer->getStartTime().addMSecs(mTimer->getLength()).toString(
"hh:mm");
339 QString
length = this->convertMillisecsToNiceString(mTimer->getLength());
340 mStartTimeLabel->setText(
341 QString(
"Date:").leftJustified(15) +
"" + startDate+
"\n" +
342 QString(
"Time:").leftJustified(15) +
"" + startTime +
" - " + endTime +
"\n" +
343 QString(
"Duration:").leftJustified(15)+
"" + length);
345 this->timeChangedSlot();
365 QString PlaybackWidget::convertMillisecsToNiceString(qint64
length)
const 369 qint64 ms = length % 1000;
370 qint64 s = (length / 1000) % 60;
371 qint64 m = (length / (1000*60)) % 60;
372 qint64 h = (length / (1000*60*60));
375 retval = QString(
"%1:%2.%3").arg(m,2,10,c).arg(s,2,10,c).arg(ms,3,10,c);
377 retval = QString(
"%1:%2").arg(h).arg(retval);
382 void PlaybackWidget::speedChangedSlot()
384 double speed = mSpeedAdapter->getValue();
385 speed = pow(2,speed);
386 mTimer->setSpeed(speed);
390 void PlaybackWidget::timeChangedSlot()
392 QString color(
"green");
394 qint64 offset = mTimer->getOffset();
395 QString format = QString(
"<font size=%1 color=%2><b>%3</b></font>").arg(fontSize).arg(color);
397 QString currentTime = mTimer->getTime().toString(
"hh:mm:ss");
399 QString currentOffset = this->convertMillisecsToNiceString(offset);
401 mLabel->setText(format.arg(
"Elapsed: "+currentOffset+
" \tTime: " + currentTime));
403 if (mTimer->isPlaying())
405 mPlayAction->setIcon(QIcon(
":/icons/open_icon_library/media-playback-pause-3.png"));
406 mPlayAction->setText(
"Pause");
410 mPlayAction->setIcon(QIcon(
":/icons/open_icon_library/media-playback-start-3.png"));
411 mPlayAction->setText(
"Play");
423 mToolTimelineWidget->blockSignals(
true);
424 mToolTimelineWidget->
setPos(mTimer->getTime().toMSecsSinceEpoch());
425 mToolTimelineWidget->blockSignals(
false);
428 void PlaybackWidget::playSlot()
430 if (mTimer->isPlaying())
443 void PlaybackWidget::stopSlot()
447 void PlaybackWidget::forwardSlot()
449 mTimer->forward(1000*mTimer->getSpeed());
451 void PlaybackWidget::rewindSlot()
453 mTimer->rewind(1000*mTimer->getSpeed());
boost::shared_ptr< class VideoService > VideoServicePtr
void reportError(QString msg)
boost::shared_ptr< class RegistrationHistory > RegistrationHistoryPtr
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