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