Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
QmitkIGTLStreamingManagementWidget.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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 
15 //mitk headers
16 #include <mitkSurface.h>
17 #include <mitkIGTLDeviceSource.h>
18 #include <mitkDataStorage.h>
19 #include <mitkIGTLMessageFactory.h>
20 
21 //qt headers
22 #include <qfiledialog.h>
23 #include <qinputdialog.h>
24 #include <qmessagebox.h>
25 #include <qscrollbar.h>
26 
27 //igtl
28 #include <igtlStringMessage.h>
29 #include <igtlBindMessage.h>
30 #include <igtlQuaternionTrackingDataMessage.h>
31 #include <igtlTrackingDataMessage.h>
32 
33 //poco headers
34 #include <Poco/Path.h>
35 
37 "org.mitk.views.igtldevicesourcemanagementwidget";
38 
40  QWidget* parent, Qt::WindowFlags f)
41  : QWidget(parent, f), m_IsClient(false)
42 {
43  m_Controls = nullptr;
44  this->m_IGTLDevice = nullptr;
45  CreateQtPartControl(this);
46 }
47 
49 {
50  this->RemoveObserver();
51 }
52 
54 {
55  if (this->m_IGTLDevice.IsNotNull())
56  {
57  this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag);
58  this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag);
59  this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag);
60  }
61  if (this->m_IGTLMsgProvider.IsNotNull())
62  {
65  }
66 }
67 
69 {
70  if (!m_Controls)
71  {
72  // create GUI widgets
73  m_Controls = new Ui::QmitkIGTLStreamingManagementWidgetControls;
74  // setup GUI widgets
75  m_Controls->setupUi(parent);
76  }
77 
78  //connect slots with signals
80 }
81 
83 {
84  if (m_Controls)
85  {
86  connect((QObject*)(m_Controls->messageSourceSelectionWidget),
87  SIGNAL(IGTLMessageSourceSelected(mitk::IGTLMessageSource::Pointer)),
88  this,
89  SLOT(SourceSelected(mitk::IGTLMessageSource::Pointer)));
90  connect(m_Controls->startStreamPushButton, SIGNAL(clicked()),
91  this, SLOT(OnStartStreaming()));
92  connect(m_Controls->stopStreamPushButton, SIGNAL(clicked()),
93  this, SLOT(OnStopStreaming()));
94  }
95  //this is used for thread seperation, otherwise the worker thread would change the ui elements
96  //which would cause an exception
97  connect(this, SIGNAL(AdaptGUIToStateSignal()), this, SLOT(AdaptGUIToState()));
98  connect(this, SIGNAL(SelectSourceAndAdaptGUISignal()), this, SLOT(SelectSourceAndAdaptGUI()));
99 }
100 
102 {
103  if (this->m_IGTLMsgProvider.IsNotNull())
104  {
105  //get the state of the device
107  this->m_IGTLDevice->GetState();
108 
109  switch (state)
110  {
113  m_Controls->messageSourceSelectionWidget->setEnabled(false);
114  m_Controls->selectedSourceLabel->setText("<none>");
115  m_Controls->startStreamPushButton->setEnabled(false);
116  m_Controls->selectedSourceLabel->setEnabled(false);
117  m_Controls->label->setEnabled(false);
118  m_Controls->stopStreamPushButton->setEnabled(false);
119  m_Controls->fpsLabel->setEnabled(false);
120  m_Controls->fpsSpinBox->setEnabled(false);
121  break;
123  //check the number of connections of the device, a server can be in
124  //the running state even if there is no connected device, this part of
125  //the GUI shall just be available when there is a connection
126  if (this->m_IGTLDevice->GetNumberOfConnections() == 0)
127  {
128  m_Controls->messageSourceSelectionWidget->setEnabled(false);
129  m_Controls->selectedSourceLabel->setText("<none>");
130  m_Controls->startStreamPushButton->setEnabled(false);
131  m_Controls->selectedSourceLabel->setEnabled(false);
132  m_Controls->label->setEnabled(false);
133  m_Controls->stopStreamPushButton->setEnabled(false);
134  m_Controls->fpsLabel->setEnabled(false);
135  m_Controls->fpsSpinBox->setEnabled(false);
136  }
137  else //there is a connection
138  {
139  //check if the user already selected a source to stream
140  if (this->m_IGTLMsgSource.IsNull()) // he did not so far
141  {
142  m_Controls->messageSourceSelectionWidget->setEnabled(true);
143  m_Controls->selectedSourceLabel->setText("<none>");
144  m_Controls->startStreamPushButton->setEnabled(false);
145  m_Controls->selectedSourceLabel->setEnabled(false);
146  m_Controls->label->setEnabled(false);
147  m_Controls->stopStreamPushButton->setEnabled(false);
148  m_Controls->fpsLabel->setEnabled(false);
149  m_Controls->fpsSpinBox->setEnabled(false);
150  }
151  else //user already selected a source
152  {
153  QString nameOfSource =
154  QString::fromStdString(m_IGTLMsgSource->GetName());
155  m_Controls->messageSourceSelectionWidget->setEnabled(true);
156  m_Controls->selectedSourceLabel->setText(nameOfSource);
157  m_Controls->selectedSourceLabel->setEnabled(true);
158  m_Controls->label->setEnabled(true);
159 
160  //check if the streaming is already running
161  if (this->m_IGTLMsgProvider->IsStreaming())
162  {
163  m_Controls->startStreamPushButton->setEnabled(false);
164  m_Controls->stopStreamPushButton->setEnabled(true);
165  m_Controls->fpsLabel->setEnabled(false);
166  m_Controls->fpsSpinBox->setEnabled(false);
167  }
168  else
169  {
170  m_Controls->startStreamPushButton->setEnabled(true);
171  m_Controls->stopStreamPushButton->setEnabled(false);
172  m_Controls->fpsLabel->setEnabled(true);
173  m_Controls->fpsSpinBox->setEnabled(true);
174  }
175  }
176  }
177  break;
178  default:
179  mitkThrow() << "Invalid Device State";
180  break;
181  }
182  }
183  else
184  {
185  this->DisableSourceControls();
186  }
187 }
188 
190  mitk::IGTLMessageProvider::Pointer provider)
191 {
192  //reset the GUI
194 
195  if (provider.IsNull())
196  return;
197 
198  //reset the observers
199  this->RemoveObserver();
200 
201  //disconnect the timer
202  disconnect(&this->m_StreamingTimer);
203 
204  this->m_IGTLMsgProvider = provider;
205 
206  //get the device
207  this->m_IGTLDevice = this->m_IGTLMsgProvider->GetIGTLDevice();
208 
209  //check if the device is a server or a client
210  if (dynamic_cast<mitk::IGTLClient*>(
211  this->m_IGTLDevice.GetPointer()) == nullptr)
212  {
213  m_IsClient = false;
214  }
215  else
216  {
217  m_IsClient = true;
218  }
219 
220  typedef itk::SimpleMemberCommand< QmitkIGTLStreamingManagementWidget > CurCommandType;
221  // CurCommandType::Pointer messageReceivedCommand = CurCommandType::New();
222  // messageReceivedCommand->SetCallbackFunction(
223  // this, &QmitkIGTLStreamingManagementWidget::OnMessageReceived );
224  // this->m_MessageReceivedObserverTag =
225  // this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand);
226 
227  // CurCommandType::Pointer commandReceivedCommand = CurCommandType::New();
228  // commandReceivedCommand->SetCallbackFunction(
229  // this, &QmitkIGTLStreamingManagementWidget::OnCommandReceived );
230  // this->m_CommandReceivedObserverTag =
231  // this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), commandReceivedCommand);
232 
233  CurCommandType::Pointer connectionLostCommand = CurCommandType::New();
234  connectionLostCommand->SetCallbackFunction(
236  this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver(
237  mitk::LostConnectionEvent(), connectionLostCommand);
238 
239  CurCommandType::Pointer newConnectionCommand = CurCommandType::New();
240  newConnectionCommand->SetCallbackFunction(
242  this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver(
243  mitk::NewClientConnectionEvent(), newConnectionCommand);
244 
245  CurCommandType::Pointer stateModifiedCommand = CurCommandType::New();
246  stateModifiedCommand->SetCallbackFunction(
248  this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver(
249  itk::ModifiedEvent(), stateModifiedCommand);
250 
251  CurCommandType::Pointer startStreamingTimerCommand = CurCommandType::New();
252  startStreamingTimerCommand->SetCallbackFunction(
254  this->m_StartStreamingTimerObserverTag = this->m_IGTLMsgProvider->AddObserver(
255  mitk::StreamingStartRequiredEvent(), startStreamingTimerCommand);
256 
257  CurCommandType::Pointer stopStreamingTimerCommand = CurCommandType::New();
258  stopStreamingTimerCommand->SetCallbackFunction(
260  this->m_StopStreamingTimerObserverTag = this->m_IGTLMsgProvider->AddObserver(
261  mitk::StreamingStopRequiredEvent(), stopStreamingTimerCommand);
262 
263  this->AdaptGUIToState();
264 }
265 
267 {
268  m_Controls->selectedSourceLabel->setText("<none>");
269  m_Controls->startStreamPushButton->setEnabled(false);
270  m_Controls->stopStreamPushButton->setEnabled(false);
271  m_Controls->fpsLabel->setEnabled(false);
272  m_Controls->fpsSpinBox->setEnabled(false);
273  m_Controls->selectedSourceLabel->setEnabled(false);
274  m_Controls->label->setEnabled(false);
275  m_Controls->messageSourceSelectionWidget->setEnabled(false);
276 }
277 
279  mitk::IGTLMessageSource::Pointer source)
280 {
281  //reset everything
282  this->DisableSourceControls();
283 
284  if (source.IsNotNull()) //no source selected
285  {
286  this->m_IGTLMsgSource = source;
287  m_Controls->selectedSourceLabel->setText(source->GetName().c_str());
288  m_Controls->selectedSourceLabel->setEnabled(true);
289  }
290 
291  this->AdaptGUIToState();
292 }
293 
295 {
296  unsigned int fps = this->m_Controls->fpsSpinBox->value();
297  this->m_IGTLMsgProvider->StartStreamingOfSource(this->m_IGTLMsgSource, fps);
298  this->AdaptGUIToState();
299 }
300 
302 {
303  this->m_IGTLMsgProvider->StopStreamingOfSource(this->m_IGTLMsgSource);
304  this->AdaptGUIToState();
305 }
306 
308 {
309 }
310 
312 {
313 }
314 
316 {
317  emit AdaptGUIToStateSignal();
318 }
319 
321 {
322  emit AdaptGUIToStateSignal();
323 }
324 
326 {
328 }
329 
331 {
332  if (this->m_IGTLMsgProvider.IsNotNull())
333  {
334  //get the frame rate
335  unsigned int interval = this->m_IGTLMsgProvider->GetStreamingTime();
336  //connect the update method
337  connect(&m_StreamingTimer, SIGNAL(timeout()), this, SLOT(OnStreamingTimerTimeout()));
338  //start the timer
339  this->m_StreamingTimer.start(interval);
340  }
341  emit AdaptGUIToStateSignal();
342 }
343 
345 {
346  //stop the timer
347  this->m_StreamingTimer.stop();
348  //if the provider is still valid disconnect from it
349  if (this->m_IGTLMsgProvider.IsNotNull())
350  {
351  //disconnect the update method
352  disconnect(&m_StreamingTimer, SIGNAL(timeout()), this, SLOT(OnStreamingTimerTimeout()));
353  }
354  emit AdaptGUIToStateSignal();
355 }
356 
358 {
359  if (this->m_IGTLMsgSource.IsNotNull())
360  {
361  this->m_IGTLMsgProvider->Update();
362  }
363 }
364 
366 {
367  //get the current selection (the auto-selected message source) and call
368  //SourceSelected which will call AdaptGUI
369  mitk::IGTLMessageSource::Pointer curSelSrc =
370  m_Controls->messageSourceSelectionWidget->AutoSelectFirstIGTLMessageSource();
371  SourceSelected(curSelSrc);
372 
373  if( curSelSrc.IsNotNull() )
374  {
375  //automatically start streaming for better support and handling when using
376  //e.g. the US-module.
377  this->OnStartStreaming();
378  }
379 }
void OnNewConnection()
Is called when the current device connected to another device.
void SourceSelected(mitk::IGTLMessageSource::Pointer source)
Is called when a new source is selected.
void OnMessageReceived()
Is called when the current device received a message.
virtual void CreateConnections()
Creation of the connections.
mitk::IGTLDevice::Pointer m_IGTLDevice
holds the OpenIGTLink device
void AdaptGUIToState()
Adapts the GUI to the state of the device.
void OnCommandReceived()
Is called when the current device received a command.
void OnLostConnection()
Is called when the current device lost a connection to one of its sockets.
#define mitkThrow()
void SelectSourceAndAdaptGUISignal()
used for thread seperation, the worker thread must not call SelectSourceAndAdaptGUI directly...
IGTLDeviceState
Type for state variable. The IGTLDevice is always in one of these states.
void AdaptGUIToStateSignal()
used for thread seperation, the worker thread must not call AdaptGUIToState directly. QT signals are thread safe and seperate the threads
void SelectSourceAndAdaptGUI()
selects the current source and adapts the GUI according to the selection
QTimer m_StreamingTimer
the streaming timer that periodically calls the update method of the provider
void LoadSource(mitk::IGTLMessageProvider::Pointer provider)
QmitkIGTLStreamingManagementWidget(QWidget *parent=nullptr, Qt::WindowFlags f=nullptr)
void OnStartStreamingTimer()
Is called when provider requests the start of the streaming timer.
mitk::IGTLMessageSource::Pointer m_IGTLMsgSource
holds the IGTLDeviceSource we are working with.
mitk::IGTLMessageProvider::Pointer m_IGTLMsgProvider
holds the IGTL Message Provider that will send the stream
Ui::QmitkIGTLStreamingManagementWidgetControls * m_Controls
bool m_IsClient
flag to indicate if the IGTL device is a client or a server
void OnStopStreamingTimer()
Is called when provider requests the stop of the streaming timer.