MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
QmitkIGTPlayerWidget.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found in the LICENSE file.
10
11============================================================================*/
12
14
15//mitk headers
16#include "mitkTrackingTypes.h"
17#include <mitkSurface.h>
23#include <mitkIGTException.h>
24#include <mitkIOUtil.h>
26
27//qt headers
28#include <qfiledialog.h>
29#include <qmessagebox.h>
30#include <qtimer.h>
31
32QmitkIGTPlayerWidget::QmitkIGTPlayerWidget(QWidget* parent, Qt::WindowFlags f)
33 : QWidget(parent, f),
34 m_RealTimePlayer(mitk::NavigationDataPlayer::New()),
35 m_SequentialPlayer(mitk::NavigationDataSequentialPlayer::New()),
36 m_StartTime(-1.0),
37 m_CurrentSequentialPointNumber(0),
38 m_Controls(new Ui::QmitkIGTPlayerWidgetControls)
39{
40 m_Controls->setupUi(this);
41 m_PlayingTimer = new QTimer(this); // initialize update timer
42
44
45 m_Controls->samplePositionHorizontalSlider->setVisible(false);
46
47 this->ResetLCDNumbers(); // reset lcd numbers at start
48}
49
56
58{
59 connect( (QObject*)(m_Controls->playPushButton), SIGNAL(clicked(bool)), this, SLOT(OnPlayButtonClicked(bool)) ); // play button
60 connect( (QObject*)(m_PlayingTimer), SIGNAL(timeout()), this, SLOT(OnPlaying()) ); // update timer
61 connect( (QObject*) (m_Controls->beginPushButton), SIGNAL(clicked()), this, SLOT(OnGoToBegin()) ); // reset player and go to begin
62 connect( (QObject*) (m_Controls->stopPushButton), SIGNAL(clicked()), this, SLOT(OnGoToEnd()) ); // reset player
63 // pass this widgets protected combobox signal to public signal
64 connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) );
65 // pass this widgets protected checkbox signal to public signal
66 connect( m_Controls->splineModeCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(SignalSplineModeToggled(bool)) );
67 //connect( m_Controls->sequencialModeCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnSequencialModeToggled(bool)) );
68
69 connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderPressed()), this, SLOT(OnSliderPressed()) );
70 connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderReleased()), this, SLOT(OnSliderReleased()) );
71
72 connect( m_Controls->m_OpenFileButton, SIGNAL(clicked()), this, SLOT(OnOpenFileButtonPressed()) );
73}
74
76{
77 return m_Controls->splineModeCheckBox->isChecked();
78}
79
81{
82 QFile file(m_CmpFilename);
83
84 // check if file exists
85 if(!file.exists())
86 {
87 QMessageBox::warning(nullptr, "IGTPlayer: Error", "No valid input file was loaded. Please load input file first!");
88 return false;
89 }
90
91 return true;
92}
93
95{
96 unsigned int result = 0;
97
99 {
100 if(m_RealTimePlayer.IsNotNull())
101 result = m_RealTimePlayer->GetNumberOfOutputs();
102 }
103
104 else if(this->GetCurrentPlaybackMode() == SequentialMode)
105 {
106 if(m_SequentialPlayer.IsNotNull())
107 result = m_SequentialPlayer->GetNumberOfOutputs();
108 }
109
110 // at the moment this works only if player is initialized
111 return result;
112}
113
115{
116 m_PlayingTimer->setInterval((int) msecs); // set update timer update rate
117}
118
120{
121 if ( ! checked )
122 {
123 if ( this->GetCurrentPlaybackMode() == RealTimeMode )
124 {
125 m_RealTimePlayer->StopPlaying();
126 }
127 else if ( this->GetCurrentPlaybackMode() == SequentialMode )
128 {
129 // m_SequentialPlayer->
130 }
131 }
132
133 if(CheckInputFileValid()) // no playing possible without valid input file
134 {
135 switch ( this->GetCurrentPlaybackMode() )
136 {
137 case RealTimeMode:
138 {
139 break;
140 }
141 case SequentialMode:
142 {
143 break;
144 }
145 }
146
147 PlaybackMode currentMode = this->GetCurrentPlaybackMode();
148 bool isRealTimeMode = currentMode == RealTimeMode;
149 bool isSequentialMode = currentMode == SequentialMode;
150
151 if(checked) // play
152 {
153 if( (isRealTimeMode && m_RealTimePlayer.IsNull()) || (isSequentialMode && m_SequentialPlayer.IsNull())) // start play
154 {
155 mitk::NavigationDataSet::Pointer navigationDataSet;
156 try
157 {
158 navigationDataSet = dynamic_cast<mitk::NavigationDataSet*> (mitk::IOUtil::Load(m_CmpFilename.toStdString())[0].GetPointer());
159 }
160 catch(const mitk::IGTException&)
161 {
162 std::string errormessage = "Error during start playing. Invalid or wrong file?";
163 QMessageBox::warning(nullptr, "IGTPlayer: Error", errormessage.c_str());
164 m_Controls->playPushButton->setChecked(false);
165 m_RealTimePlayer = nullptr;
166 return;
167 }
168
169 if(isRealTimeMode)
170 {
171 m_RealTimePlayer = mitk::NavigationDataPlayer::New();
172 m_RealTimePlayer->SetNavigationDataSet(navigationDataSet);
173 try
174 {
175 m_RealTimePlayer->StartPlaying();
176 }
177 catch(const mitk::IGTException&)
178 {
179 std::string errormessage = "Error during start playing. Invalid or wrong file?";
180 QMessageBox::warning(nullptr, "IGTPlayer: Error", errormessage.c_str());
181 m_Controls->playPushButton->setChecked(false);
182 m_RealTimePlayer = nullptr;
183 return;
184 }
185 }
186 else if(isSequentialMode)
187 {
188 m_SequentialPlayer = mitk::NavigationDataSequentialPlayer::New();
189 try
190 {
191 m_SequentialPlayer->SetNavigationDataSet(navigationDataSet);
192 }
193 catch(const mitk::IGTException&)
194 {
195 std::string errormessage = "Error during start playing. Invalid or wrong file type?";
196 QMessageBox::warning(nullptr, "IGTPlayer: Error", errormessage.c_str());
197 m_Controls->playPushButton->setChecked(false);
198 m_RealTimePlayer = nullptr;
199 return;
200 }
201
202 m_Controls->samplePositionHorizontalSlider->setMinimum(0);
203
204 m_Controls->samplePositionHorizontalSlider->setMaximum(m_SequentialPlayer->GetNumberOfSnapshots());
205
206 m_Controls->samplePositionHorizontalSlider->setEnabled(true);
207 }
208
209 m_PlayingTimer->start(100);
210
212 }
213 else // resume play
214 {
215 if(isRealTimeMode)
216 m_RealTimePlayer->Resume();
217
218 m_PlayingTimer->start(100);
220 }
221 }
222
223 else // pause
224 {
225 if(isRealTimeMode)
226 m_RealTimePlayer->Pause();
227
228 m_PlayingTimer->stop();
229 emit SignalPlayingPaused();
230 }
231 }
232
233 else
234 {
235 m_Controls->playPushButton->setChecked(false); // uncheck play button if file unvalid
236 }
237}
238
240{
241 /*if(m_Controls->sequencialModeCheckBox->isChecked())
242 return SequentialMode;
243 else*/
244 return RealTimeMode;
245}
246
251
256
258{
259 m_PlayingTimer->stop();
261
262 if(m_RealTimePlayer.IsNotNull())
263 m_RealTimePlayer->StopPlaying();
264
265 m_StartTime = -1; // set starttime back
267 m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber);
268 m_Controls->sampleLCDNumber->display(static_cast<int>(m_CurrentSequentialPointNumber));
269
270 this->ResetLCDNumbers();
271 m_Controls->playPushButton->setChecked(false); // set play button unchecked
272}
273
275{
276 switch ( this->GetCurrentPlaybackMode() )
277 {
278 case RealTimeMode:
279 {
280 if ( m_RealTimePlayer.IsNull() ) { return; }
281
282 if ( m_StartTime < 0 )
283 {
284 // get playback start time
285 m_StartTime = m_RealTimePlayer->GetOutput()->GetTimeStamp();
286 }
287
288 if( ! m_RealTimePlayer->IsAtEnd() )
289 {
290 m_RealTimePlayer->Update(); // update player
291
292 int msc = (int) (m_RealTimePlayer->GetOutput()->GetTimeStamp() - m_StartTime);
293
294 // calculation for playing time display
295 int ms = msc % 1000;
296 msc = (msc - ms) / 1000;
297 int s = msc % 60;
298 int min = (msc-s) / 60;
299
300 // set lcd numbers
301 m_Controls->msecLCDNumber->display(ms);
302 m_Controls->secLCDNumber->display(s);
303 m_Controls->minLCDNumber->display(min);
304
305 emit SignalPlayerUpdated(); // player successfully updated
306 }
307 else
308 {
309 this->StopPlaying(); // if player is at EOF
310 }
311
312 break;
313 }
314 case SequentialMode:
315 {
316 if ( m_SequentialPlayer.IsNull() ) { return; }
317
319 {
320 m_SequentialPlayer->Update(); // update sequential player
321
322 m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber++); // refresh slider position
323 m_Controls->sampleLCDNumber->display(static_cast<int>(m_CurrentSequentialPointNumber));
324
325 //for debugging purposes
326 //std::cout << "Sample: " << m_CurrentSequentialPointNumber << " X: " << m_SequentialPlayer->GetOutput()->GetPosition()[0] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[1] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[2] << std::endl;
327
328 emit SignalPlayerUpdated(); // player successfully updated
329 }
330 else
331 {
332 this->StopPlaying(); // if player is at EOF
333 }
334
335 break;
336 }
337 }
338}
339
340const std::vector<mitk::NavigationData::Pointer> QmitkIGTPlayerWidget::GetNavigationDatas()
341{
342 std::vector<mitk::NavigationData::Pointer> navDatas;
343
344 if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull())
345 {
346 for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i)
347 {
348 navDatas.push_back(m_RealTimePlayer->GetOutput(i)); // push back current navigation data for each tool
349 }
350 }
351
352 else if(this->GetCurrentPlaybackMode() == SequentialMode && m_SequentialPlayer.IsNotNull())
353 {
354 for(unsigned int i=0; i < m_SequentialPlayer->GetNumberOfOutputs(); ++i)
355 {
356 navDatas.push_back(m_SequentialPlayer->GetOutput(i)); // push back current navigation data for each tool
357 }
358 }
359
360 return navDatas;
361}
362
364{
365 mitk::PointSet::Pointer result = mitk::PointSet::New();
366
367 mitk::PointSet::PointType pointType;
368
369 PlaybackMode currentMode = this->GetCurrentPlaybackMode();
370 bool isRealTimeMode = currentMode == RealTimeMode;
371 bool isSequentialMode = currentMode == SequentialMode;
372
373 if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull()))
374 {
375 for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i)
376 {
378
379 if(isRealTimeMode)
380 position = m_RealTimePlayer->GetOutput(i)->GetPosition();
381 else
382 position = m_SequentialPlayer->GetOutput(i)->GetPosition();
383
384 pointType[0] = position[0];
385 pointType[1] = position[1];
386 pointType[2] = position[2];
387
388 result->InsertPoint(i,pointType); // insert current ND as Pointtype in PointSet for return
389 }
390 }
391
392 return result;
393}
394
395const mitk::PointSet::PointType QmitkIGTPlayerWidget::GetNavigationDataPoint(unsigned int index)
396{
397 if( index > this->GetNumberOfTools() )
398 throw std::out_of_range("Tool Index out of range!");
399
400 PlaybackMode currentMode = this->GetCurrentPlaybackMode();
401 bool isRealTimeMode = currentMode == RealTimeMode;
402 bool isSequentialMode = currentMode == SequentialMode;
403
404 // create return PointType from current ND for tool index
405 mitk::PointSet::PointType result;
406
407 if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull()))
408 {
410
411 if(isRealTimeMode)
412 position = m_RealTimePlayer->GetOutput(index)->GetPosition();
413 else if(isSequentialMode)
414 position = m_SequentialPlayer->GetOutput(index)->GetPosition();
415
416 result[0] = position[0];
417 result[1] = position[1];
418 result[2] = position[2];
419 }
420
421 return result;
422}
423
424/*void QmitkIGTPlayerWidget::SetRealTimePlayer( mitk::NavigationDataPlayer::Pointer player )
425{
426if(player.IsNotNull())
427m_RealTimePlayer = player;
428}
429
430void QmitkIGTPlayerWidget::SetSequentialPlayer( mitk::NavigationDataSequentialPlayer::Pointer player )
431{
432if(player.IsNotNull())
433m_SequentialPlayer = player;
434}*/
435
437{
438 QString filename = QFileDialog::getOpenFileName(this, "Load tracking data", QmitkIGTCommonHelper::GetLastFileLoadPath(),"XML files (*.xml)");
439 QFile file(filename);
440
442 // if something went wrong or user pressed cancel in the save dialog
443 if ( filename.isEmpty() || ! file.exists() )
444 {
445 QMessageBox::warning(nullptr, "Warning", QString("Please enter valid path. Using previous path again."));
446 return;
447 }
448
449 m_CmpFilename = filename;
450
451 this->OnGoToEnd();
452
453 m_Controls->m_ActiveFileLabel->setText(m_CmpFilename);
454
456
457 mitk::NavigationDataSet::Pointer navigationDataSet = dynamic_cast<mitk::NavigationDataSet*> (mitk::IOUtil::Load(m_CmpFilename.toStdString())[0].GetPointer());
458 m_RealTimePlayer->SetNavigationDataSet(navigationDataSet);
459 m_SequentialPlayer->SetNavigationDataSet(navigationDataSet);
460
461 m_Controls->m_PlayerControlsGroupBox->setEnabled(true);
462}
463
465{
466 this->StopPlaying();
467
468 // reset lcd numbers
469 this->ResetLCDNumbers();
470}
471
473{
474 // stop player manual so no PlayingStopped()
475 m_PlayingTimer->stop();
476
477 if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull())
478 {
479 m_RealTimePlayer->StopPlaying();
480 m_RealTimePlayer = nullptr; // set player to nullptr so it can be initialized again if playback is called afterwards
481 }
482
483 m_StartTime = -1; // set starttime back
484
485 //reset view elements
486 m_Controls->playPushButton->setChecked(false);
487 this->ResetLCDNumbers();
488}
489
491{
492 m_Controls->minLCDNumber->display(QString("00"));
493 m_Controls->secLCDNumber->display(QString("00"));
494 m_Controls->msecLCDNumber->display(QString("000"));
495}
496
497void QmitkIGTPlayerWidget::SetTrajectoryNames(const QStringList toolNames)
498{
499 QComboBox* cBox = m_Controls->trajectorySelectComboBox;
500
501 if(cBox->count() > 0)
503
504 // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS
505 disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) );
506
507 if(!toolNames.isEmpty())
508 m_Controls->trajectorySelectComboBox->insertItems(0, toolNames); // adding current tool names to combobox
509
510 // reconnect after performed changes
511 connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) );
512}
513
515{
516 return m_Controls->resolutionSpinBox->value(); // return currently selected trajectory resolution
517}
518
520{
521 // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS
522 disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) );
523
524 m_Controls->trajectorySelectComboBox->clear();
525
526 // reconnect after performed changes
527 connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) );
528}
529
531{
532 this->StopPlaying(); // stop playing when mode is changed
533
534 if(toggled)
535 {
536 m_Controls->samplePositionHorizontalSlider->setEnabled(true); // enable slider if sequential mode
537 }
538 else if(!toggled)
539 {
540 m_Controls->samplePositionHorizontalSlider->setSliderPosition(0); // set back and disable slider
541 m_Controls->samplePositionHorizontalSlider->setDisabled(true);
542 }
543}
544
546{
547 int currentSliderValue = m_Controls->samplePositionHorizontalSlider->value(); // current slider value selected through user movement
548
549 if(currentSliderValue > static_cast<int>(m_CurrentSequentialPointNumber)) // at the moment only forward scrolling is possible
550 {
551 auto snapshotNumber = static_cast<unsigned int>(currentSliderValue);
552 m_SequentialPlayer->GoToSnapshot(snapshotNumber); // move player to selected snapshot
553 m_CurrentSequentialPointNumber = currentSliderValue;
554 m_Controls->sampleLCDNumber->display(currentSliderValue); // update lcdnumber in widget
555 }
556 else
557 m_Controls->samplePositionHorizontalSlider->setValue(m_CurrentSequentialPointNumber);
558}
559
561{
562 if(m_Controls->playPushButton->isChecked()) // check if widget is playing
563 m_Controls->playPushButton->click(); // perform click to pause the play
564}
static void SetLastFileLoadPathByFileName(const QString &str)
static const QString GetLastFileLoadPath()
void ResetLCDNumbers()
Sets all LCD numbers to 0.
void SignalPlayingStarted()
This signal is emitted when the player starts the playback.
virtual void CreateConnections()
Creation of the connections.
void ClearTrajectorySelectCombobox()
Clears all items in the trajectory selection combobox.
void SignalPlayingResumed()
This signal is emitted when the player resumes after a pause.
int GetResolution()
Returns the current resolution value from the resolution spinbox.
QmitkIGTPlayerWidget(QWidget *parent=nullptr, Qt::WindowFlags f={})
default constructor
QTimer * m_PlayingTimer
update timer
PlaybackMode GetCurrentPlaybackMode()
void SignalSplineModeToggled(bool toggled)
This signal is emitted if the spline mode checkbox is toggled or untoggled.
void SetUpdateRate(unsigned int msecs)
Sets the update rate of this widget's playing timer.
void OnStopPlaying()
Stops the playback.
QString m_CmpFilename
filename of the input file
void SignalPlayingPaused()
This signal is emitted when the player is paused.
void OnPlaying()
Updates the playback data.
void OnGoToBegin()
Stops the playback and resets the player to the beginning.
unsigned int m_CurrentSequentialPointNumber
current point number
void SetTrajectoryNames(const QStringList toolNames)
Sets the given tool names list to the trajectory select combobox.
mitk::NavigationDataSequentialPlayer::Pointer m_SequentialPlayer
void SignalInputFileChanged()
This signal is emitted if the input file for the replay was changed.
@ RealTimeMode
playback mode enum
unsigned int GetNumberOfTools()
Returns the number of different tools from the current playing stream.
void StopPlaying()
Stops the playback.
void OnOpenFileButtonPressed()
Opens file open dialog for searching the input file.
~QmitkIGTPlayerWidget() override
default deconstructor
void SignalCurrentTrajectoryChanged(int index)
This signal is emitted if the index of the current selected trajectory select combobox item changes.
QTimer * GetPlayingTimer()
Sets the real time player for this player widget.
Ui::QmitkIGTPlayerWidgetControls * m_Controls
const std::vector< mitk::NavigationData::Pointer > GetNavigationDatas()
Returns the current playback NavigationDatas from the xml-file.
void OnSliderReleased()
Moves player position to the position selected with the slider.
void SignalPlayerUpdated()
This signal is emitted every time the player updated the NavigationDatas.
void OnPlayButtonClicked(bool toggled)
Starts or pauses the playback.
void OnSliderPressed()
Pauses playback when slider is pressed by user.
const mitk::PointSet::PointType GetNavigationDataPoint(unsigned int index)
Returns a PointType of the current NavigationData for a specific tool with the given index.
void OnGoToEnd()
Stops the playback.
void SignalPlayingStopped()
This signal is emitted when the player stops.
void OnSequencialModeToggled(bool toggled)
Switches widget between realtime and sequential mode.
bool IsTrajectoryInSplineMode()
Returns whether spline mode checkbox is selected.
const mitk::PointSet::Pointer GetNavigationDatasPointSet()
Returns a PointSet of the current NavigationDatas for all recorded tools.
bool CheckInputFileValid()
Checks if an imput file with the set filename exists.
mitk::NavigationData::TimeStampType m_StartTime
start time of playback needed for time display
mitk::NavigationDataPlayer::Pointer m_RealTimePlayer
plays NDs from a XML file
An object of this class represents an exception of the MITK-IGT module.
Data structure which stores streams of mitk::NavigationData for multiple tools.
mitk::Point3D PositionType
Type that holds the position part of the tracking data.
IGT Exceptions.